简体   繁体   English

在 OpenGL-OpenCL 纹理互操作中,PBO 如何从纹理中接收数据?

[英]In OpenGL-OpenCL texture interop, how does the PBO receive the data from the texture?

Most examples on PBOs on the web are about making CPU-GPU transfers asynchronous. web 上的 PBO 的大多数示例都是关于使 CPU-GPU 传输异步的。

I'm trying to use PBOs for something else - for OpenGL-OpenCL interop, as explained in this tutorial .我正在尝试将 PBO 用于其他用途 - 用于 OpenGL-OpenCL 互操作,如本教程中所述。 Quote from there:从那里引用:

[...] Creating an intermediate (staging) Pixel-Buffer-Object for the OpenGL texture via clCreateFromGLBuffer, updating the buffer with OpenCL, and copying the results back to the texture. [...] 通过 clCreateFromGLBuffer 为 OpenGL 纹理创建中间(暂存)像素缓冲区对象,使用 OpenCL 更新缓冲区,并将结果复制回纹理。

The tutorial explains I need to create the PBO as follows:本教程解释了我需要按如下方式创建 PBO:

GLuint pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_ARRAY_BUFFER, pbo);
//specifying the buffer size
glBufferData(GL_ARRAY_BUFFER, width * height * sizeof(cl_uchar4), …);

I have replaced the ellipsis with NULL, GL_DYNAMIC_COPY , as I don't want to send any data from the host.我已经用NULL, GL_DYNAMIC_COPY替换了省略号,因为我不想从主机发送任何数据。

Here's the createPbo function I ended up with:这是我最终得到的 createPbo function:

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, 0, GL_RED, GL_FLOAT, NULL);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

In the rest of my code, I do what the tutorial does, and the code works fine.在我的代码的 rest 中,我按照教程的方式进行操作,并且代码运行良好。 The problem is the glGetTexImage call: The tutorial doesn't mention it, which means maybe I can skip doing this slow copy?问题是glGetTexImage调用:教程没有提到它,这意味着也许我可以跳过这个慢速复制? Can I?我可以吗?


Note about my usecase: I'm trying to send existing OpenGL texture data into OpenCL, manipulate it there, and then send it back to OpenGL.请注意我的用例:我正在尝试将现有的OpenGL 纹理数据发送到 OpenCL,在那里对其进行操作,然后将其发送回 OpenGL。

You can access an image level of an OpenGL texture directly in OpenCL without copying (at least not as an explicit API action) as an OpenCL image object via clCreateFromGLTexture .您可以直接在 OpenCL 中访问 OpenGL 纹理的图像级别,而无需通过cl.CreateFromGLTexture将 OpenCL 图像 object 复制(至少不是作为显式 API 操作)

The very tutorial you mentioned also mentions this.您提到的教程也提到了这一点。 You don't need a buffer object or a pixel buffer transfer operation.您不需要缓冲区 object 或像素缓冲区传输操作。

And, for completeness, since the question was explicitly about how to use GL buffer sharing in OpenCL and then using the GL buffer to update a texture image:而且,为了完整起见,因为问题是明确关于如何在 OpenCL 中使用 GL 缓冲区共享,然后使用 GL 缓冲区来更新纹理图像:

The tutorial you referenced (in Method 2) also covers exactly how to do this.您引用的教程(在方法 2 中)也准确介绍了如何执行此操作。 In this case, we do not share a level of the GL texture but we share a GL buffer object as a CL buffer object:在这种情况下,我们不共享 GL 纹理的级别,但我们共享一个 GL 缓冲区 object 作为 CL 缓冲区 object:

(the following is more or less a direct copy/paste of that tutorial's sources) (以下或多或少是该教程源代码的直接复制/粘贴)

First, create the OpenGL buffer object that we want to share with OpenCL and that we will later use to update a texture image with PBO transfer:首先,创建要与 OpenCL 共享的 OpenGL 缓冲区 object,稍后我们将使用它来通过 PBO 传输更新纹理图像:

GLuint pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_ARRAY_BUFFER, pbo);
//specifying the buffer size
glBufferData(GL_ARRAY_BUFFER, width * height * sizeof(cl_uchar4), …);

Next, if you want to initialize the GL buffer object with a level of your original GL texture, you first need to PBO copy that image into the GL buffer object:接下来,如果您想使用原始 GL 纹理的级别初始化 GL 缓冲区 object,您首先需要将该图像 PBO 复制到 GL 缓冲区 object 中:

glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBindTexture(GL_TEXTURE_2D, tex);
glGetTexImage(GL_TEXTURE_2D, 0, texFormat, texType, 0);

This will PBO-copy the GL texture's first level into the GL buffer object.这会将 GL 纹理的第一层 PBO 复制到 GL 缓冲区 object 中。

Next, share the GL buffer in OpenCL:接下来,在 OpenCL 中共享 GL 缓冲区:

mem = clCreateFromGLBuffer(g_context, CL_MEM_WRITE_ONLY, pbo,  NULL);

Then, acquire the ownership of the shared GL/CL buffer object via clEnqueueAcquireGLObjects() , execute the kernel that updates the CL buffer content, and release the ownership via clEnqueueReleaseGLObjects() .然后,通过clEnqueueAcquireGLObjects()获取共享 GL/CL 缓冲区 object 的所有权,执行更新 CL 缓冲区内容的 kernel ,并通过clEnqueueReleaseGLObjects()释放所有权。

And last, update an OpenGL texture (currently bound to GL_TEXTURE_2D ) with PBO transfer out of the GL buffer object:最后,更新 OpenGL 纹理(当前绑定到GL_TEXTURE_2D ),将 PBO 传输出 GL 缓冲区 object:

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

No, you cannot because the data is accessed with buffer Mapping ( glMapBuffer ).不,您不能,因为数据是通过缓冲区映射( glMapBuffer ) 访问的。 You cannot directly map a texture image, but you can map the data store of a buffer object.您不能直接 map 纹理图像,但您可以 map 缓冲区 object 的数据存储。 Therefore you need to copy the data from the texture image into the data store of a buffer.因此,您需要将纹理图像中的数据复制到缓冲区的数据存储中。
glGetTexImage carries out the "copying" process (and necessary format and type conversions). glGetTexImage执行“复制”过程(以及必要的格式和类型转换)。 It get the data from the texture bound to target GL_TEXTURE_2D and stores the data in the buffer bound to target GL_PIXEL_PACK_BUFFER .它从绑定到目标GL_TEXTURE_2D的纹理中获取数据,并将数据存储在绑定到目标GL_PIXEL_PACK_BUFFER的缓冲区中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM