使用OpenCL获取OpenGL缓冲区

use*_*425 3 c++ opengl opencl

是否可以使用OpenCL获取OpenGL缓冲区的值?例如,编写一个用缓冲区创建OpenGL上下文的程序,另一个用于执行OpenCL代码?我不希望第一个程序代码改变.

jpr*_*ice 8

有一个可选的OpenCL扩展,cl_khr_gl_sharing允许实现与OpenCL对象(缓冲区和图像)共享某些OpenGL对象(缓冲区和纹理).OpenCL的大多数可用GPU实现都支持此扩展.扩展定义的其他API函数在头文件中可用CL/cl_gl.h.

你可以通过调用检查是否您的设备和平台支持该扩展clGetDeviceInfoCL_DEVICE_EXTENSIONS论证,并检查所产生的字符串是否cl_khr_gl_sharing存在.

在OpenCL初始化期间,您需要以特定方式创建OpenCL上下文,以便与OpenGL共享对象.这是特定于操作系统的,但在所有情况下都涉及创建一组传递给的上下文属性clCreateContext.以下是一些例子:


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
};
Run Code Online (Sandbox Code Playgroud)

Linux(使用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
};
Run Code Online (Sandbox Code Playgroud)

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
};
Run Code Online (Sandbox Code Playgroud)

Android(使用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
};
Run Code Online (Sandbox Code Playgroud)

设置属性后,创建如下的上下文:

context = clCreateContext(properties, 1, &device, NULL, NULL, &err);
Run Code Online (Sandbox Code Playgroud)

接下来要做的是从现有的OpenGL对象创建OpenCL对象.OpenGL方面的任何内容都不需要改变.给定一个调用的现有OpenGL缓冲区bufferGL,您可以从中创建一个OpenCL缓冲区对象,如下所示:

bufferCL = clCreateFromGLBuffer(context, CL_MEM_READ_WRITE, bufferGL, &err);
Run Code Online (Sandbox Code Playgroud)

或者,您可以从OpenGL纹理创建OpenCL图像:

imageCL = clCreateFromGLTexture2D(context, CL_MEM_WRITE_ONLY,
                                  GL_TEXTURE_2D, 0, textureGL, &err);
Run Code Online (Sandbox Code Playgroud)

剩下的就是将在这些共享CL/GL对象上运行的OpenCL内核排入队列.您需要在内核的任何一侧排队一些额外的命令,以告诉实现您要将对象的所有权转移到OpenCL或从OpenCL转移对象的所有权.您需要执行的一般操作顺序如下:

// 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);
Run Code Online (Sandbox Code Playgroud)

有一些示例代码可以演示OpenCL/OpenGL的互操作性,值得一看,在完整的应用程序中展示了所有这些: