0

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 ?

user1391967
  • 497
  • 1
  • 6
  • 13
  • 2
    "*if I try to replace the dummy texture by the newly created "m_texture", it's not working :*" Why would you expect that to work? Your "newly created 'm_texture'" is an *object*, not a pointer. – Nicol Bolas Jan 26 '18 at 20:07
  • Yes, i understand that its wrong. I just dont' see which (or how to build) the object to pass to glTexImage2D. – user1391967 Jan 26 '18 at 21:23

2 Answers2

2

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.

Community
  • 1
  • 1
StarShine
  • 1,940
  • 1
  • 27
  • 45
1

Thanks StarShine.

With pyopencl, clCreateFromGLTexture is called GLTexture. And you need to call glTexImage2D with an initial texture array before GLTexture or it will not work.

The working code is :

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])
user1391967
  • 497
  • 1
  • 6
  • 13