OpenCL/GL : 从缓冲区加载纹理

OpenCL/GL : Load a texture from buffer

我想从共享缓冲区OpenCL/OpenGL读取纹理(因为我在 openCL 上有一个 CFD 求解器)。我的环境是 Python 3.6 x64,带有 pyopencl 和 pyopengl。

显示虚拟纹理有效:

glEnable(GL_TEXTURE_2D);
# Load a texture 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
m_texture = dummy_texture() # An nx*ny*4 array
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA ,nx,ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture);

# Draw plane
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2i(0, 0); glVertex2i(0, 0);
glTexCoord2i(0, 1); glVertex2i(0, ny);
glTexCoord2i(1, 1); glVertex2i(nx, ny);
glTexCoord2i(1, 0); glVertex2i(nx, 0);
glEnd();

使用 openCL/OpenGL 互操作移动顶点也有效,因为我可以在我的计算机上 运行 这个例子。 https://github.com/inducer/pyopencl/blob/master/examples/gl_interop_demo.py

到目前为止一切顺利。 但我不知道如何从 openCL 缓冲区加载纹理。 我已经按照与 link 提供的相同代码使用 opencl 创建 共享缓冲区 (m_texture) :

glClearColor(1, 1, 1, 1)
glColor(0, 0, 1)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
rawGlBufferData(GL_ARRAY_BUFFER, nx*ny * 4, None, GL_DYNAMIC_DRAW)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(2, GL_FLOAT, 0, None)
texture_buffer = cl.GLBuffer(ctx, cl.mem_flags.READ_WRITE, int(vbo))
prog = cl.Program(ctx, src).build()
queue = cl.CommandQueue(ctx)
cl.enqueue_acquire_gl_objects(queue, [buffer _dev])
prog.generate_sin(queue, (n_vertices,), None, buffer _dev)
cl.enqueue_release_gl_objects(queue, [coords_buffer ])
queue.finish()
glFlush()

但是,如果我尝试用新创建的 "m_texture" 替换虚拟纹理,它不起作用:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA ,nx,ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture);

有什么想法吗?

您正在寻找的是将 gl 纹理映射到 cl 缓冲区的互操作函数。对于 OpenCL 1.2+,这是:

clCreateFromGLTexture(clContext, memflags, target, miplevel, glTexHandle, errno)

对于 OpenCL 1.1-:

clCreateFromGLTexture2D(clContext, memflags, target, miplevel, glTexHandle, errno)

clCreateFromGLTexture3D(clContext, memflags, target, miplevel, glTexHandle, errno)

请注意,纹理必须在绑定后、设置 cl 映射之前应用以下内容!:

// bind texture first
// ...
//
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    // 1D texture
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    // 2D texture
// glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); // 3D texture

由于纹理是 openCL 用于计算的缓冲区,您可以直接渲染它而无需先将其卸载到 CPU,或者您可以使用 PBO 或 map/unmap 策略来获取像素像正常一样。还要注意 lock/unlock 计算步骤前后的纹理资源/clBuffer。

感谢星光。

使用 pyopencl,clCreateFromGLTexture 被称为 GLTexture。并且您需要在 GLTexture 之前使用初始纹理数组调用 glTexImage2D,否则它将无法工作。

工作代码是:

m_texture = dummy_texture() # An nx*ny*4 array

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    # 1D texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    # 2D texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA ,nx,ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture);

textureMem =cl.GLTexture( ctx, cl.mem_flags.READ_WRITE, GL_TEXTURE_2D, 0, textureID, 2);

// Modifying texture with opencl
cl.enqueue_acquire_gl_objects(queue, [textureMem])    
prog.changeColor(queue, (nx,ny), None, textureMem) 
cl.enqueue_release_gl_objects(queue, [textureMem])