如何解决在OpenGL-OpenCL纹理互操作中,PBO如何从纹理接收数据?
网络上关于 PBO 的大多数示例都是关于使 CPU-GPU 传输异步。
我正在尝试将 PBO 用于其他用途 - 用于 OpenGL-OpenCL 互操作,如 this tutorial 中所述。从那里引用:
[...] 通过 clCreateFromGLBuffer 为 OpenGL 纹理创建中间(暂存)像素缓冲区对象,使用 OpenCL 更新缓冲区,并将结果复制回纹理。
教程解释了我需要按如下方式创建 PBO:
GLuint pbo;
glGenBuffers(1,&pbo);
glBindBuffer(GL_ARRAY_BUFFER,pbo);
//specifying the buffer size
glBufferData(GL_ARRAY_BUFFER,width * height * sizeof(cl_uchar4),…);
我已将省略号替换为 NULL,GL_DYNAMIC_COPY
,因为我不想从主机发送任何数据。
这是我最终得到的 createPbo 函数:
void createPbo(ivec2 sz,int elementSize) {
glGenBuffers(1,&pbo);
glBindBuffer(GL_ARRAY_BUFFER,pbo);
glBufferData(GL_ARRAY_BUFFER,sz.x * sz.y * elementSize,NULL,GL_DYNAMIC_COPY);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER,pbo);
glGetTexImage(GL_TEXTURE_2D,GL_RED,GL_FLOAT,NULL);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0);
}
在我的其余代码中,我执行了教程所做的操作,并且代码运行良好。 问题在于 glGetTexImage
调用:教程没有提到它,这意味着我可以跳过这个慢拷贝吗?我可以吗?
请注意我的用例:我正在尝试将现有 OpenGL 纹理数据发送到 OpenCL,在那里对其进行操作,然后将其发送回 OpenGL。
解决方法
您可以在 OpenCL 中直接访问 OpenGL 纹理的图像级别,而无需通过 clCreateFromGLTexture 复制(至少不是作为显式 API 操作)作为 OpenCL 图像对象。
你提到的教程也提到了这一点。您不需要缓冲区对象或像素缓冲区传输操作。
而且,为了完整性,因为问题明确是关于如何在 OpenCL 中使用 GL 缓冲区共享,然后使用 GL 缓冲区来更新纹理图像:
您参考的教程(在方法 2 中)也准确地介绍了如何执行此操作。在这种情况下,我们不共享 GL 纹理的级别,但我们共享一个 GL 缓冲区对象作为 CL 缓冲区对象:
(以下内容或多或少是对该教程来源的直接复制/粘贴)
首先,创建我们想要与 OpenCL 共享的 OpenGL 缓冲区对象,稍后我们将使用该对象通过 PBO 传输更新纹理图像:
GLuint pbo;
glGenBuffers(1,&pbo);
glBindBuffer(GL_ARRAY_BUFFER,pbo);
//specifying the buffer size
glBufferData(GL_ARRAY_BUFFER,width * height * sizeof(cl_uchar4),…);
接下来,如果您想用原始 GL 纹理的级别初始化 GL 缓冲区对象,您首先需要将该图像PBO复制到 GL 缓冲区对象中:
glBindBuffer(GL_PIXEL_PACK_BUFFER,pbo);
glBindTexture(GL_TEXTURE_2D,tex);
glGetTexImage(GL_TEXTURE_2D,texFormat,texType,0);
这会将 GL 纹理的第一级 PBO 复制到 GL 缓冲区对象中。
接下来,在 OpenCL 中共享 GL 缓冲区:
mem = clCreateFromGLBuffer(g_context,CL_MEM_WRITE_ONLY,pbo,NULL);
然后通过clEnqueueAcquireGLObjects()
获取共享GL/CL缓冲区对象的所有权,执行更新CL缓冲区内容的内核,通过clEnqueueReleaseGLObjects()
释放所有权。
最后,更新一个 OpenGL 纹理(当前绑定到 GL_TEXTURE_2D
),使用 PBO 传输出 GL 缓冲区对象:
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,texture);
glTexSubImage2D(GL_TEXTURE_2D,width,height,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
,
不,您不能,因为数据是通过缓冲区 Mapping (glMapBuffer
) 访问的。您不能直接映射纹理图像,但可以映射缓冲区对象的数据存储。因此,您需要将纹理图像中的数据复制到缓冲区的数据存储中。glGetTexImage
执行“复制”过程(以及必要的格式和类型转换)。它从绑定到目标 GL_TEXTURE_2D
的纹理中获取数据,并将数据存储在绑定到目标 GL_PIXEL_PACK_BUFFER
的缓冲区中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。