OpenCL - 绘制到 OpenGL 纹理崩溃
OpenCL - Draw To OpenGL Texture crashes
我正在尝试创建一个 OpenCL 光线投射器。因此,我每秒多次绘制到 OpenGL 纹理。然而 queue.enqueueNDRangeKernel
最终 returns -9999。如果我从我的内核代码中删除 write_imagef
,它就可以工作,所以我认为这是导致问题的原因。
OpenCL 内核(分解)
__kernel void main(__write_only image2d_t screen)
{
unsigned int x = get_global_id(0);
unsigned int y = get_global_id(1);
int2 coords = (int2) (x, y);
write_imagef(screen, coords, (float4)(1,0,1,1));
}
这是在c++中运行一次的代码:
cl::Program::Sources sources;
string code = ResourceLoader::loadFile(filename);
sources.push_back({ code.c_str(),code.length() });
program = cl::Program(OpenCL::context, sources);
if (program.build({ OpenCL::default_device }) != CL_SUCCESS)
{
cout << "Could not build program \"" << filename << "\"! Error:" << endl;
cout << "OpenCL: Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(OpenCL::default_device) << "\n";
system("PAUSE");
exit(1);
}
queue = CommandQueue(OpenCL::context, OpenCL::default_device);
kernel = Kernel(program, "main");
//OpenGL texture
ImageGL b(OpenCL::context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, argument, &error);
if (error != 0)
{
cout << "CL Error: " << OpenCL::get_cl_error_string(error) << endl;
system("PAUSE");
exit(error);
}
kernel.setArg(0, b);
此代码每帧运行:
glFinish();
queue.enqueueAcquireGLObjects(&this->buffersGL);
NDRange range;
if (lengthZ <= 0 && lengthY <= 0)
range = NDRange(lengthX);
else if (lengthZ <= 0)
range = NDRange(lengthX, lengthY);
else
range = NDRange(lengthX, lengthY, lengthZ);
cl::Event wait;
cl_int run_err = queue.enqueueNDRangeKernel(kernel, NDRange(), range, NullRange, NULL, &wait);
if (run_err != 0)
{
cout << OpenCL::get_cl_error_string(run_err) << " (" << run_err << ")" << endl;
system("PAUSE");
}
queue.enqueueReleaseGLObjects(&this->buffersGL);
什么可能导致 -9999 错误,我该如何解决?此外,经常有大块 "dead pixels" 未在纹理中绘制...
您排队释放 GL 缓冲区,但不要等待它完成。
queue.enqueueReleaseGLObjects(&this->buffersGL);
要么从中获取完成事件(注意泄漏!),要么等待命令队列完成所有任务,然后再继续释放 GL 对象。当队列中的一件事依赖于另一件事时,您应该自己安排它们的顺序。
您还排队了一堆依赖于 GL 对象的任务。要么等待它们完成(完成队列),要么获取它们的事件并将它们作为额外条件提供给入队释放 GL 对象。
顺便说一句:
使用较少的内核可能是个好主意,而不是每个像素一个。
Using fewer kernels might be a good idea, instead of one per pixel.
非常感谢 Yakk!我首先简单地使用较小的屏幕尺寸进行了尝试,然后它突然又起作用了!事实证明,我正在绘制的纹理是问题所在。它不是 600x600 像素大,这就是导致崩溃的原因。显然,OpenCL 可以在崩溃前多次绘制 "don't actually exist" 像素。它仍然是奇怪的行为...
我正在尝试创建一个 OpenCL 光线投射器。因此,我每秒多次绘制到 OpenGL 纹理。然而 queue.enqueueNDRangeKernel
最终 returns -9999。如果我从我的内核代码中删除 write_imagef
,它就可以工作,所以我认为这是导致问题的原因。
OpenCL 内核(分解)
__kernel void main(__write_only image2d_t screen)
{
unsigned int x = get_global_id(0);
unsigned int y = get_global_id(1);
int2 coords = (int2) (x, y);
write_imagef(screen, coords, (float4)(1,0,1,1));
}
这是在c++中运行一次的代码:
cl::Program::Sources sources;
string code = ResourceLoader::loadFile(filename);
sources.push_back({ code.c_str(),code.length() });
program = cl::Program(OpenCL::context, sources);
if (program.build({ OpenCL::default_device }) != CL_SUCCESS)
{
cout << "Could not build program \"" << filename << "\"! Error:" << endl;
cout << "OpenCL: Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(OpenCL::default_device) << "\n";
system("PAUSE");
exit(1);
}
queue = CommandQueue(OpenCL::context, OpenCL::default_device);
kernel = Kernel(program, "main");
//OpenGL texture
ImageGL b(OpenCL::context, CL_MEM_READ_WRITE, GL_TEXTURE_2D, 0, argument, &error);
if (error != 0)
{
cout << "CL Error: " << OpenCL::get_cl_error_string(error) << endl;
system("PAUSE");
exit(error);
}
kernel.setArg(0, b);
此代码每帧运行:
glFinish();
queue.enqueueAcquireGLObjects(&this->buffersGL);
NDRange range;
if (lengthZ <= 0 && lengthY <= 0)
range = NDRange(lengthX);
else if (lengthZ <= 0)
range = NDRange(lengthX, lengthY);
else
range = NDRange(lengthX, lengthY, lengthZ);
cl::Event wait;
cl_int run_err = queue.enqueueNDRangeKernel(kernel, NDRange(), range, NullRange, NULL, &wait);
if (run_err != 0)
{
cout << OpenCL::get_cl_error_string(run_err) << " (" << run_err << ")" << endl;
system("PAUSE");
}
queue.enqueueReleaseGLObjects(&this->buffersGL);
什么可能导致 -9999 错误,我该如何解决?此外,经常有大块 "dead pixels" 未在纹理中绘制...
您排队释放 GL 缓冲区,但不要等待它完成。
queue.enqueueReleaseGLObjects(&this->buffersGL);
要么从中获取完成事件(注意泄漏!),要么等待命令队列完成所有任务,然后再继续释放 GL 对象。当队列中的一件事依赖于另一件事时,您应该自己安排它们的顺序。
您还排队了一堆依赖于 GL 对象的任务。要么等待它们完成(完成队列),要么获取它们的事件并将它们作为额外条件提供给入队释放 GL 对象。
顺便说一句:
使用较少的内核可能是个好主意,而不是每个像素一个。
Using fewer kernels might be a good idea, instead of one per pixel.
非常感谢 Yakk!我首先简单地使用较小的屏幕尺寸进行了尝试,然后它突然又起作用了!事实证明,我正在绘制的纹理是问题所在。它不是 600x600 像素大,这就是导致崩溃的原因。显然,OpenCL 可以在崩溃前多次绘制 "don't actually exist" 像素。它仍然是奇怪的行为...