问题:当调用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的纹理做同样的事情,我在同一个地方也得到了同样的错误。)
......有人有任何想法吗?
答案 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。