关于C#:使用OpenCL获取OpenGL缓冲区

Getting OpenGL buffers using OpenCL

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


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

中可用。

您可以通过使用CL_DEVICE_EXTENSIONS参数调用clGetDeviceInfo并检查结果字符串以查看是否存在cl_khr_gl_sharing来检查设备和平台是否支持此扩展。

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

OS X

1
2
3
4
5
6
7
8
9
10
11
12
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(带有GLX)

1
2
3
4
5
6
7
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)

1
2
3
4
5
6
7
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(带有EGL)

1
2
3
4
5
6
7
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
};

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

1
context = clCreateContext(properties, 1, &device, NULL, NULL, &err);

下一步是从现有OpenGL对象创建OpenCL对象。 OpenGL方面无需进行任何更改。给定一个名为bufferGL的现有OpenGL缓冲区,您可以像这样从中创建一个OpenCL缓冲区对象:

1
bufferCL = clCreateFromGLBuffer(context, CL_MEM_READ_WRITE, bufferGL, &err);

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

1
2
imageCL = clCreateFromGLTexture2D(context, CL_MEM_WRITE_ONLY,
                                  GL_TEXTURE_2D, 0, textureGL, &err);

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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);

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

  • 英特尔的OpenCL / OpenGL教程
  • Apple的OpenCL程序几何位移示例
  • NVIDIA的简单OpenCL / OpenGL示例