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

标签 opengl opencl

网络上有关 PBO 的大多数示例都是关于使 CPU-GPU 传输异步。

我正在尝试将 PBO 用于其他用途 - 用于 OpenGL-OpenCL 互操作,如 this tutorial 中所述。 。引用自那里:

[...] 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.

本教程解释了我需要创建 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, 0, 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 缓冲区对象,您首先需要将该图像复制到 GL 缓冲区对象中:

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

这会将 GL 纹理的第一层 PBO 复制到 GL 缓冲区对象中。

接下来,在 OpenCL 中共享 GL 缓冲区:

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

然后,通过clEnqueueAcquireGLObjects()获取共享GL/CL缓冲区对象的所有权,执行更新CL缓冲区内容的内核,并通过clEnqueueReleaseGLObjects()释放所有权.

最后,使用从 GL 缓冲区对象传输的 PBO 更新 OpenGL 纹理(当前绑定(bind)到 GL_TEXTURE_2D):

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);

关于opengl - 在OpenGL-OpenCL纹理互操作中,PBO如何从纹理接收数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65423216/

相关文章:

java - OpenGL使用错误?

queue - OpenCL 事件和命令队列

c++ - 在 OpenCL 库中找不到 cl::Error 类

opencl - 适用于 Xeon Phi 的最新 OpenCL 驱动程序

opencl - OpenCL1.1 上的惰性策略

java - 图像轮廓点生成器?

c++ - OpenGL、GLM 四元数旋转

c++ - OpenGL with Qt 5 : #error gl. h 包含在 glew.h 之前

c++ - 计算给定轨道偏心率和距中心点的顶点的椭圆

c - OpenCL 内核中的中断和继续