【问题标题】:OpenCL/OpenGL Interop on OSX -- has anyone ever shared a Renderbuffer or Texture?OSX 上的 OpenCL/OpenGL 互操作——有没有人共享过渲染缓冲区或纹理?
【发布时间】:2012-10-01 18:47:49
【问题描述】:

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

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

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

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

有两种不同方法的示例,它们都涉及帧缓冲区对象。

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

那么你应该可以在 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 的相同操作,但我在同一个地方遇到了同样的错误。)

...有人有什么想法吗?

【问题讨论】:

    标签: opencl


    【解决方案1】:

    好的;明白了!

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

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

    【讨论】:

    • 你知道为什么应该使用 write_imagef 而不是使用 UNORM_INT8 的 write_imageui 吗?您是自己找到的还是记录在某处?谢谢!
    • 哦,它在 OpenCL 规范中,我刚刚错过了。
    • 对不起;有一阵子没看这里了……不,我是通过互联网搜索发现的,偶然发现有人说“当然你不能使用 write_imageui 来编写 UNORM8”……然而,很自然,我曾以为您会必须使用以“i”结尾的东西来写入int! . . .所以,完全随机运气。我想我应该像你一样阅读规范! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多