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])
我想从共享缓冲区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])