I want to read a texture from a shared buffer OpenCL/OpenGL (as i have a CFD solver on openCL). My environment is Python 3.6 x64, with pyopencl and pyopengl.
Displaying a dummy texture is working :
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();
Using openCL/OpenGL interop for moving vertices is also working, as I can run this example on my computer. https://github.com/inducer/pyopencl/blob/master/examples/gl_interop_demo.py
So far so good. But I have no idea how to load a texture from an openCL buffer. I've followed the same code as the link provided to create a shared buffer (m_texture) with opencl :
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()
But, if I try to replace the dummy texture by the newly created "m_texture", it's not working :
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA ,nx,ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture);
Any idea ?
What you are looking for is the interop functions that map gl textures into cl buffers. For OpenCL 1.2+ this is:
clCreateFromGLTexture(clContext, memflags, target, miplevel, glTexHandle, errno)
and for OpenCL 1.1-:
clCreateFromGLTexture2D(clContext, memflags, target, miplevel, glTexHandle, errno)
clCreateFromGLTexture3D(clContext, memflags, target, miplevel, glTexHandle, errno)
Please be careful, the texture MUST have the following applied after binding, and before setting up the cl mapping!:
// 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
Since the texture IS the buffer that openCL uses to compute, you can directly render it without offloading it to CPU first, or you can use a PBO or map/unmap strategy to fetch the pixels like normal. Also be careful to lock/unlock both your texture resource / clBuffer before and after the compute step.