OpenCL - 绘制到 OpenGL 纹理崩溃

Posted

技术标签:

【中文标题】OpenCL - 绘制到 OpenGL 纹理崩溃【英文标题】:OpenCL - Draw To OpenGL Texture crashes 【发布时间】:2016-03-30 19:34:31 【问题描述】:

我正在尝试创建一个 OpenCL 光线投射器。因此,我每秒多次绘制 OpenGL 纹理。然而queue.enqueueNDRangeKernel 最终返回-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 错误,我该如何解决?此外,纹理中经常有大块未绘制的“死像素”......

【问题讨论】:

【参考方案1】:

您将 GL 缓冲区的释放排入队列,但不要等待它完成。

queue.enqueueReleaseGLObjects(&this->buffersGL);

要么从中获取完成事件(注意泄漏!),要么在继续释放 GL 对象之前等待命令队列完成所有任务。当队列中的一件事依赖于另一件事时,您应该自己安排他们的排序。

您还可以排队一堆依赖于 GL 对象的任务。要么等待它们完成(完成队列),要么获取它们的事件并将它们作为附加条件提供给入队释放 GL 对象。

顺便说一句:

使用更少的内核可能是个好主意,而不是每个像素一个。

【讨论】:

【参考方案2】:

使用更少的内核可能是个好主意,而不是每个像素一个。

非常感谢 Yakk!我首先尝试使用较小的屏幕尺寸,然后它突然又可以工作了!事实证明,虽然我正在绘制的纹理是问题所在。它不是 600x600 像素大,这就是导致崩溃的原因。显然,OpenCL 可以在崩溃之前多次绘制“实际上不存在”的像素。它仍然是奇怪的行为......

【讨论】:

以上是关于OpenCL - 绘制到 OpenGL 纹理崩溃的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 渲染到纹理,然后绘制纹理

如何在 OpenCL 内核中更新 OpenCL-OpenGL 共享缓冲区数据?

如何在OpenGL中将像素作为纹理绘制到多边形?

绘制到纹理后的Opengl ES 2.0 glDeleteFramebuffers

安卓下多线程OpenGL共享Context

在 OpenGL 中绘制多个 2D 纹理