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