Is it possible to get the values of OpenGL buffers using OpenCL? For example, writing a program that creates OpenGL context with buffers, and another one to execute OpenCL code? I don't want the first programs code to change.
There is an optional OpenCL extension, cl_khr_gl_sharing, that allows an implementation to share certain OpenGL objects (buffers and textures) with OpenCL objects (buffers and images). This extension is supported on most of the available GPU implementations of OpenCL. The additional API functions defined by the extension are available in the header file CL/cl_gl.h.
You can check whether your device and platform support this extension by calling clGetDeviceInfo with the CL_DEVICE_EXTENSIONS argument, and checking the resulting string to see if cl_khr_gl_sharing is present.
During OpenCL initialisation, you need to create the OpenCL context in a particular way in order to enable sharing objects with OpenGL. This is OS specific, but in all cases involves creating a set of context properties which you pass to clCreateContext. Here's a few examples:
OS X
CGLContextObj CGLGetCurrentContext(void);
CGLShareGroupObj CGLGetShareGroup(CGLContextObj);
CGLContextObj kCGLContext = CGLGetCurrentContext();
CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
cl_context_properties properties[] =
{
CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
(cl_context_properties) kCGLShareGroup,
0
};
Linux (with GLX)
cl_context_properties properties[] =
{
CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
CL_CONTEXT_PLATFORM, (cl_context_properties)platform, // OpenCL platform object
0
};
Windows (WGL)
cl_context_properties properties[] =
{
CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
CL_CONTEXT_PLATFORM, (cl_context_properties)platform, // OpenCL platform object
0
};
Android (with EGL)
cl_context_properties properties[] =
{
CL_GL_CONTEXT_KHR, (cl_context_properties)eglGetCurrentContext(),
CL_EGL_DISPLAY_KHR, (cl_context_properties)eglGetCurrentDisplay(),
CL_CONTEXT_PLATFORM, (cl_context_properties)platform, // OpenCL platform object
0
};
Once the properties have been set up, create the context like this:
context = clCreateContext(properties, 1, &device, NULL, NULL, &err);
The next thing to do is to create your OpenCL objects from the existing OpenGL objects. Nothing on the OpenGL side needs to change. Given an existing OpenGL buffer called bufferGL, you can create an OpenCL buffer object from it like this:
bufferCL = clCreateFromGLBuffer(context, CL_MEM_READ_WRITE, bufferGL, &err);
Or you can create an OpenCL image from an OpenGL texture:
imageCL = clCreateFromGLTexture2D(context, CL_MEM_WRITE_ONLY,
GL_TEXTURE_2D, 0, textureGL, &err);
All that remains is to enqueue your OpenCL kernels that operate on these shared CL/GL objects. You need to enqueue some extra commands either side of your kernel in order to tell the implementation that you want to transfer ownership of the objects to/from OpenCL. The general sequence of operations that you need to perform is as follows:
// Flush GL queue
glFlush();
// Acquire shared objects
err = clEnqueueAcquireGLObjects(queue, 1, &bufferCL, 0, NULL, NULL);
// Enqueue OpenCL commands to operate on objects (kernels, read/write commands, etc)
// Release shared objects
err = clEnqueueReleaseGLObjects(queue, 1, &bufferCL, 0, NULL, NULL);
checkError(err, "releasing GL objects");
// Flush CL queue
err = clFinish(queue);
There's a few example codes out there that demonstrate OpenCL/OpenGL interoperability, which would be worth a look to see all of this demonstrated inside a full application:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With