I want to create an application that uses OpenCL to caluculate the color value of every pixel in a texture and OpenGL to display that texture. The problem is that when I try to create a context with GL sharing properties the program freezes. Using the function get_gl_sharing_context_properties()
I get a list [(8200, 65538), (8203, 18446744072971422270)]
. The last number in the list is too big to convert to a 64 bit int and I get an overflow error.
The code I use to create the CL context:
def cl_init():
platform = cl.get_platforms()[1]
device = platform.get_devices(cl.device_type.GPU)
from pyopencl.tools import get_gl_sharing_context_properties
print(cl.have_gl())
print(get_gl_sharing_context_properties())
print(sys.platform)
context = cl.Context(properties=[
(cl.context_properties.PLATFORM, platform)] +
get_gl_sharing_context_properties())
print("Context creation done")
queue = cl.CommandQueue(context)
The code never reaches print("Context creation done")
. I use QtPy4 and the QGLWidget to create the OpenGL context and display the texture.
Ok ran into a similar issue myself and here is my fix for it. If you look exactly at what get_gl_sharing_context_properties()
is doing according to PyOpenCL's source code on github under the tools
module, you will find the following platform-specific code:
def get_gl_sharing_context_properties():
ctx_props = cl.context_properties
from OpenGL import platform as gl_platform
props = []
import sys
if sys.platform in ["linux", "linux2"]:
from OpenGL import GLX
props.append(
(ctx_props.GL_CONTEXT_KHR, gl_platform.GetCurrentContext()))
props.append(
(ctx_props.GLX_DISPLAY_KHR,
GLX.glXGetCurrentDisplay()))
elif sys.platform == "win32":
from OpenGL import WGL
props.append(
(ctx_props.GL_CONTEXT_KHR, gl_platform.GetCurrentContext()))
props.append(
(ctx_props.WGL_HDC_KHR,
WGL.wglGetCurrentDC()))
elif sys.platform == "darwin":
props.append(
(ctx_props.CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
cl.get_apple_cgl_share_group()))
else:
raise NotImplementedError("platform '%s' not yet supported"
% sys.platform)
return props
Now, since I am on Windows, I took a look at the WGL code (which comes from PyOpenGL
) and found that WGL.wglGetCurrentDC()
(like get_gl_sharing_context_properties()
of course) was returning incorrect handle values sometimes that caused the integer overflow. It turns out the DC (device context) is really supposed to be a 32 bit signed integer. However, in the PyOpenGL
wrapper function, it is being converted wrongly to a 64 bit unsigned integer. As a result, whenever a negative DC handle value is passed into PyOpenGL, it is being converted to become 2^64 + annoying_negative_dc_number
instead!
The solution: convert it back! Here is what I now do to reliably get a working gl interop context:
platform = cl.get_platforms()[0]
ctx_props = cl.context_properties
gl_props = get_gl_sharing_context_properties()
device_context = gl_props[-1][-1]
if device_context >= 2 ** 32:
device_context -= (2 ** 64)
fixed_gl_props = [gl_props[0], (gl_props[-1][0], device_context)]
ctx = cl.Context(properties=[(ctx_props.PLATFORM, platform)] + fixed_gl_props)