OSX上的OpenCL / OpenGL Interop - 有没有人共享过Renderbuffer或Texture?

时间:2012-10-01 18:47:49

标签: opencl

问题:当调用clSetKernelArg()时,尝试共享绑定到Framebuffer的Renderbuffer(或Texture)会失败。在通话之前,彻底的错误检查报告没有问题。

我的程序为视频投影仪生成帧,帧速率为60fps(16.7ms帧)。

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

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

有两种不同的方法可以做到这一点,它们都涉及Framebuffer对象。

您可以将Renderbuffer附加到Framebuffer,也可以将纹理附加到Framebuffer。

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

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

*注意:我宁愿使用Renderbuffer而不是Texture,因为我所做的只是制作一个我想要显示的2-D 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,就像interop未打开时使用的缓冲区对象一样。区别在于它是使用clCreateFromGLRenderbuffer而不是clCreateBuffer创建的,它位于与gl sharegroup关联创建的上下文中。


(我已经尝试添加第二个Renderbuffer并将其附加到深度附着点,以防需要。没有帮助。)

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

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

1 个答案:

答案 0 :(得分:2)

确定;得到了它!

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

Bonus事实:你不能用write_imageui写入UNORM_INT8图像;你必须使用write_imagef。