OpenCL / GL:从缓冲区

时间:2018-01-26 19:39:23

标签: opengl interop textures pyopengl

我想从共享缓冲区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缓冲区加载纹理。 我使用与提供的链接相同的代码来创建一个带有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);

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

您正在寻找的是将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策略来获取正常像素。还要注意在计算步骤之前和之后锁定/解锁纹理资源/ clBuffer。

答案 1 :(得分:1)

感谢StarShine。

使用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])