0% found this document useful (0 votes)
117 views18 pages

Opencl: Graphics Interop: The Best of Both Worlds - Graphics and Compute

The document discusses using OpenCL and OpenGL together by sharing resources between the APIs. It provides code examples for checking OpenGL support on a device, creating a shared OpenCL-OpenGL context, and sharing resources like textures and buffers between the APIs while managing ownership. Functions covered include clCreateContext, clGetGLContextInfoKHR, clEnqueueAcquireGLObjects, clEnqueueReleaseGLObjects, clCreateFromGLTexture2D and clCreateFromGLBuffer. The document aims to explain how to best utilize graphics and compute capabilities together through OpenCL and OpenGL interoperability.

Uploaded by

blablablabla2222
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
117 views18 pages

Opencl: Graphics Interop: The Best of Both Worlds - Graphics and Compute

The document discusses using OpenCL and OpenGL together by sharing resources between the APIs. It provides code examples for checking OpenGL support on a device, creating a shared OpenCL-OpenGL context, and sharing resources like textures and buffers between the APIs while managing ownership. Functions covered include clCreateContext, clGetGLContextInfoKHR, clEnqueueAcquireGLObjects, clEnqueueReleaseGLObjects, clCreateFromGLTexture2D and clCreateFromGLBuffer. The document aims to explain how to best utilize graphics and compute capabilities together through OpenCL and OpenGL interoperability.

Uploaded by

blablablabla2222
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

OpenCL: Graphics Interop

The best of both worlds -- graphics and compute

Graphics & Compute


Best of both worlds

Choose the most appropriate API for your app


Add a kernel anywhere in your graphics pipeline
Zero-copy data sharing between APIs
Minor overhead associated with context switching

Detecting OpenGL Support


Verify GL sharing is supported

Get extension string for CL_DEVICE_EXTENSIONS


Check for the appropriate platform extension string:
cl_khr_gl_sharing !

// Linux + Windows

cl_APPLE_gl_sharing

// Apple OSX / iOS

#if defined (__APPLE__) || defined(MACOSX)


! static const char* CL_GL_SHARING_EXT = "cl_APPLE_gl_sharing";
#else
! static const char* CL_GL_SHARING_EXT = "cl_khr_gl_sharing";
#endif
!
! // Get string containing supported device extensions
! int ext_size = 1024;
! char* ext_string = (char*)malloc(ext_size);
! err = clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, ext_size, ext_string, &ext_size);
!
! // Search for GL support in extension string (space delimited)
! int supported = IsExtensionSupported(CL_GL_SHARING_EXT, ext_string, ext_size);
! if( supported )
!{
! ! // Device supports context sharing with OpenGL
! ! printf("Found GL Sharing Support!\n");
!}

Code Example:

check for GL sharing support

!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!

int IsExtensionSupported(
! const char* support_str, const char* ext_string, size_t ext_buffer_size)
{
! size_t offset = 0;
! const char* space_substr = strnstr(ext_string + offset, " ", ext_buffer_size - offset);
! size_t space_pos = space_substr ? space_substr - ext_string : 0;
! while (space_pos < ext_buffer_size)
! {
! ! if( strncmp(support_str, ext_string + offset, space_pos) == 0 )
! ! {
! ! ! // Device supports requested extension!
! ! ! printf("Info: Found extension support %s!\n", support_str);
! ! ! return 1;
! ! }
! ! // Keep searching -- skip to next token string
! ! offset = space_pos + 1;
! ! space_substr = strnstr(ext_string + offset, " ", ext_buffer_size - offset);
! ! space_pos = space_substr ? space_substr - ext_string : 0;
! }
! printf("Warning: Extension not supported %s!\n", support_str);
! return 0;
}

Code Example:

verify extension is supported

Setting Up a Shared Context


Use GL devices in OpenCL context

Get the handle for your windowing framework


Use platform context properties to indicate GL interop
Create an OpenCL context using active GL devices

WGL Shared Context Creation


!
!
!
!

// Create CL context properties, add WGL context & handle to DC


cl_context_properties properties[] = {
! CL_GL_CONTEXT_KHR,
(cl_context_properties)wglGetCurrentContext(), // WGL Context
! CL_WGL_HDC_KHR,
(cl_context_properties)wglGetCurrentDC(),
// WGL HDC
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
// OpenCL platform
0
! };
!
!
!
!

// Find CL capable devices in the current GL context


cl_device_id devices[32]; size_t size;
clGetGLContextInfoKHR(properties, CL_DEVICES_FOR_GL_CONTEXT_KHR,
! ! ! ! !
32 * sizeof(cl_device_id), devices, &size);

! // Create a context using the supported devices


! int count = size / sizeof(cl_device_id);
! cl_context context = clCreateContext(properties, devices, count, NULL, 0, 0);

Code Example:

WGL context properties

GLX Shared Context Creation


!
!
!
!

// Create CL context properties, add GLX context & handle to DC


cl_context_properties properties[] = {
! CL_GL_CONTEXT_KHR,
(cl_context_properties)glXGetCurrentContext(), // GLX Context
! CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(), // GLX Display
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
// OpenCL platform
0
! };
!
!
!
!

// Find CL capable devices in the current GL context


cl_device_id devices[32]; size_t size;
clGetGLContextInfoKHR(properties, CL_DEVICES_FOR_GL_CONTEXT_KHR,
! ! ! ! !
32 * sizeof(cl_device_id), devices, &size);

! // Create a context using the supported devices


! int count = size / sizeof(cl_device_id);
! cl_context context = clCreateContext(properties, devices, count, NULL, 0, 0);

Code Example:

GLX context properties

Apple Shared Context Creation

! // Get current CGL Context and CGL Share group


! CGLContextObj kCGLContext = CGLGetCurrentContext();
! CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
!
!
!
!
!

// Create CL context properties, add handle & share-group enum


cl_context_properties properties[] = {
! CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
! (cl_context_properties)kCGLShareGroup, 0
};

! // Create a context with device in the CGL share group


! cl_context context = clCreateContext(properties, 0, 0, NULL, 0, 0);

Code Example:

Apple GL context properties

Apple Shared Context Creation


w/CPU + GPU
! // Get current CGL Context and CGL Share group
! CGLContextObj kCGLContext = CGLGetCurrentContext();
! CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
!
!
!
!
!

// Create CL context properties, add handle & share-group enum


cl_context_properties properties[] = {
! CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
! (cl_context_properties)kCGLShareGroup, 0
};

! // Optional: Get the CPU device (we can request this in addition to GPUs in Share Group)
! cl_device_id cpu_device; int count;
! clGetDeviceIds(platform, CL_DEVICE_TYPE_CPU, 1 * sizeof(cl_device_id), &cpu_device, & count);
! // Create a context from a CGL share group (note: only use CPU if software renderer is enabled!)
! cl_context context = clCreateContext(properties, count, cpu_device, NULL, 0, 0);

Code Example:

Apple GL context properties

Sharing Resources
Using GL objects in OpenCL

Create objects in GL like normal


Create reference object in OpenCL
Switch ownership from GL to OpenCL to use
Release reference in OpenCL first then destroy in GL

OpenGL Texture: OpenCL Image


!

// Create a texture in OpenGL and allocate space


glGenTextures(1, &gl_texture_id);
glBindTexture(gl_texture_target, gl_texture_id);
glTexImage2D(gl_texture_target, 0, gl_texture_internal, width, height, 0,
gl_texture_format, gl_texture_type, NULL);
glBindTexture(TextureTarget, 0);

!
!

// Create a reference mem object in OpenCL from GL texture


cl_mem cl_image = clCreateFromGLTexture2D(cl_context, CL_MEM_READ_WRITE,
gl_texture_target, 0, gl_texture_id, &err);
if (!cl_image || err != CL_SUCCESS)
{
printf("Failed to create OpenGL texture reference! %d\n", err);
return -1;
}

Code Example:

GL texture sharing

OpenGL Buffer: OpenCL Buffer


!

// Create a buffer object in OpenGL and allocate space


glGenBuffers(1, &gl_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER_ARB, gl_buffer_id);
// Note: specify GL_STATIC_DRAW_ARB to modify outside of GL
glBufferData(GL_ARRAY_BUFFER_ARB, bytes, NULL,
GL_STATIC_DRAW_ARB); !
// Note: could use colors, normals, etc
glVertexPointer(4, GL_FLOAT, 0, 0);
glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
// Create a reference cl_mem object from GL buffer object
cl_mem cl_buffer = clCreateFromGLBuffer(cl_context, CL_MEM_READ_WRITE,
gl_buffer_id, &err);

Code Example:

GL buffer sharing

OpenCL + GL Execution
Intermixing command streams

Synchronising commands between OpenCL & GL


OpenCL v1.0: glFlush to exec pending commands
OpenCL v1.1: Create cl_event from GL_ARB_sync

Switching Ownership from GL to OpenCL


!

// Force pending GL commands to get executed so memory is up-to-date


glFlush();
// Acquire ownership of GL texture for OpenCL Image
err = clEnqueueAcquireGLObjects(cl_cmd_queue, 1, &cl_image, 0, 0, 0);
// ... execute kernel or other OpenCL operations ...
// Release ownership of GL texture for OpenCL Image
err = clEnqueueReleaseGLObjects(cl_cmd_queue, 1, &cl_image, 0, 0, 0);
// Force pending CL commands to get executed
err = clFlush(cl_cmd_queue);
// Bind GL texture and use for rendering
glBindTexture(gl_texture_target, gl_texture_id);

Code Example:

CL buffer to GL texture

Using an OpenCL Buffer to update an OpenGL texture


// Acquire ownership of GL texture for OpenCL Image
err = clEnqueueAcquireGLObjects(cl_cmd_queue, 1, &cl_image, 0, 0, 0);
size_t origin[] = { 0, 0, 0 };
size_t region[] = { Width, Height, 1 };
// Copy contiguous buffer to formatted image bound to GL texture
err = clEnqueueCopyBufferToImage(cl_cmd_queue, gl_texture, cl_image,
0, origin, region, 0, NULL, 0);
// Release ownership of GL texture for OpenCL Image
err = clEnqueueReleaseGLObjects(cl_cmd_queue, 1, &cl_image, 0, 0, 0);
if (err != CL_SUCCESS)
{
printf("Failed to release GL object! %d\n", err);
return EXIT_FAILURE;
}

Code Example:

CL buffer to GL texture




K>W/YZW
K>W/YZW

hD>KD'KD'

^&
d
^<





><EKZD>/KKZ^dZh&>^


><Z^^ZWd>DWEKE
><Z^^>DWdK'D/ZZKZZWd

><&/>dZEZ^d><&/>dZ>/EZ

Z'>K

&'>Z
K>K'>


&'>&'>d
K> 
K>
'>
&'>d&'>Z
d
dK>hD

&'>

K>K'>^W/

>/K'>Z

K'>
> hD>d

K>

>K'>K

&'>
Z

'>

>DDZtZ/dKE>z>DDZtZ/d


>/K'>d




&'>d
'>

'>'>

^&'>



'>dydhZZdE'>


'>dydhZhDWWK^/d/syz


'>dydhZhDWE'd/syz

'

>

>K'>^K

,
  
E
Y/
Zt Zt E
E

&'><,Z
''>K/
< E
^
^ '>
^
'>
Zt Z Zt Zt
>'>K:dh&&Z

dK>W
>'>K:ddydhZdydhZ
>'>^
hd
>'>K:dZEZh&&Z
''>/<,Z

''>d/



>'>dydhZdZ'd
>'>D/WDW>s>






>s/^&KZ'>KEdyd<,Z
>hZZEds/&KZ'>KEdyd<,Z

^K

'>K
&'>d
hD>KD'KD'

'>

'>'>
Z'>K
>/K'>Z

K>K'>^W/


^&'>
&'>Z
K>K'>



&'>&'>d
'>dydhZ


&'>d&'>Z
K'>
K>

K>^W/

>K'>K
&'>

'>

&'>




>K'>^K

Y/

&<,Z
K<,Z
&'><,Z
''>K/
'>


'>

'>
K>K'>

>'>K:dh&&Z
/

>DDZtZ/dKE>z>DDZtZ/d
>'>K:ddydhZdydhZ
>'>^

&'>&'>d

>'>K:dZEZh&&Z
''>/<,Z
>DDZtZ/dKE>z>DDZtZ/d
>/K'>d

&'>d&'>Z

''>d/
&'>d


K'>

'>

&d<,Z

'>'>
K>



Questions?
Derek Gerstmann
University of Western Australia
http://local.wasp.uwa.edu.au/~derek

You might also like