4

问题:当调用 clSetKernelArg() 时,尝试共享绑定到帧缓冲区的渲染缓冲区(或纹理)失败。在调用之前,彻底的错误检查不会报告任何问题。

我的程序为以 60fps(16.7ms 帧)运行的视频投影仪生成帧。

我的内核(通常)运行 24 毫秒,但每帧之间需要 50 毫秒。我假设一些额外的成本是因为我使用 GPU 来计算像素,然后将读取缓冲区排入队列以从 GPU 中提取数据然后使用 glDrawPixels 将其放回GPU 上进行显示。尝试 OpenGL/OpenCL 互操作的完美情况,对吧?,以避免两个额外的复制操作。

有很多例子,我已经成功地与 OpenCL 共享了一个 VBO,并且可以写入它,但这对我没有帮助。我不想写顶点数据,只是一个计算出来的二维图像。

有两种不同方法的示例,它们都涉及 Framebuffer 对象。

您可以将渲染缓冲区附加到帧缓冲区,也可以将纹理附加到帧缓冲区。

然后你应该能够在 opencl 中写入该缓冲区并用 opengl 显示它,没有额外的副本。

我在代码中找到了一些这样的例子,我认为我正在按照例子所说的方式做所有事情,但也许它在 OSX 中被破坏了?..因为它不起作用。FBO 是“完整的”,一路上没有错误,直到我尝试执行 clSetKernelArg。该调用返回错误 -38,CL_INVALID_MEM_OBJECT。

*注意:我宁愿使用渲染缓冲区而不是纹理,因为我所做的只是制作我想要显示的二维 RGB 图像。但我绝望地尝试了纹理。仍然没有帮助。

我按照这个顺序执行这些步骤,中间还有一些其他的东西:

kCGLContext = CGLGetCurrentContext(); 
kCGLShareGroup = CGLGetShareGroup( kCGLContext );

glGenFramebuffers( 1, &fboid );
glBindFramebuffer( GL_FRAMEBUFFER, fboid );

glGenRenderbuffers( 1, &rboid );
glBindRenderbuffer( GL_RENDERBUFFER, rboid );
glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA, rb_wid, rb_hgt );

glboid = rboid;

glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboid );

然后:

cl_context_properties ourprops[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup, 0 };

contextZ = clCreateContext( ourprops, 1, &dev_idZ[0], clLogMessagesToStdoutAPPLE, NULL, &err );

clbo = clCreateFromGLRenderbuffer( contextZ, CL_MEM_WRITE_ONLY, glboid, &err );

然后 clCreateCommandQueue、clCreateProgramWithBinary、clBuildProgram、clCreateKernel,都没有错误

然后稍后:

glFinish();
clEnqueueAcquireGLObjects( queueZ, 1, &clbo, 0,0,0 );

err = clSetKernelArg( kernelZ, 1, sizeof(cl_mem), &clbo );

...失败并出现错误 -38,CL_INVALID_MEM_OBJECT。

clbo 是一个静态 cl_mem,就像互操作未打开时使用的缓冲区对象一样。不同之处在于它是使用 clCreateFromGLRenderbuffer 而不是 clCreateBuffer 创建的,并且它是在与 gl 共享组关联的上下文中创建的。


(我尝试添加第二个渲染缓冲区并将其附加到深度连接点,以防万一。没有帮助。)

(我用绑定到 FBO 的纹理尝试了同样的事情,但我在同一个地方得到了同样的错误。)

...有没有人有任何想法?

4

1 回答 1

3

好的; 知道了!

问题是内核指定了一个 uint * 作为其输出参数,而不是 image2d_t。我认为这至少对 setkarg 调用无关紧要。它们都是主机端的 cl_mem(image2d_t 是 #defined 为 cl_mem)。但是,一旦您调用 clCreateFromGLTexture2D 或 clCreateFromGLRenderbuffer,该对象就会获取 ocl 知道的属性。当内核更改为指定 image2d_t 时,出现了更多有用的错误消息,现在它可以工作了。

额外的事实:您不能使用 write_imageui 写入 UNORM_INT8 图像;你必须使用 write_imagef。

于 2012-10-15T17:07:04.523 回答