我想创建一个应用程序,它使用OpenCL来计算纹理中每个像素的颜色值,并使用OpenGL来显示该纹理。问题是,当我尝试使用GL共享属性创建上下文时,程序会冻结。使用函数get_gl_sharing_context_properties()
,我得到一个列表[(8200, 65538), (8203, 18446744072971422270)]
。列表中的最后一个数字太大,无法转换为64位int,我收到溢出错误。
我用来创建CL上下文的代码:
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)
代码永远不会达到print("Context creation done")
。我使用QtPy4和QGLWidget来创建OpenGL上下文并显示纹理。
答案 0 :(得分:0)
我自己遇到了类似的问题,这是我对它的解决方法。如果您根据get_gl_sharing_context_properties()
模块下的PyOpenCL's source code on github准确查看tools
正在执行的操作,您将找到以下特定于平台的代码:
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
现在,由于我在Windows上,我看了一下WGL代码(来自PyOpenGL
)并发现WGL.wglGetCurrentDC()
(当然get_gl_sharing_context_properties()
)返回错误处理值有时导致整数溢出。事实证明,DC(设备上下文)实际上假设是 32位有符号整数。但是,在PyOpenGL
包装函数中,它被错误地转换为 64位无符号整数。因此,每当负的DC句柄值传递到PyOpenGL时,它就会被转换为2^64 + annoying_negative_dc_number
而不是!
解决方案:将其转换回来!以下是我现在要做的就是可靠地获得一个有效的gl互操作环境:
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)
答案 1 :(得分:0)
pyopencl中存在一个错误导致上下文创建被错误处理。本质上,pyopencl为opencl属性获取元组列表,并在内部解析它们并将它们传递给CL上下文创建处理程序。元组要么作为指针或整数传递。当为某些属性传递指针时,假设将指针转换为整数值以传递给CL上下文创建处理程序,但它会错误地执行此操作。相反,它会抓取指针本身的地址。
有两种可能的修复方法。
从用户代码方面,您可以执行以下操作,手动传递已损坏属性(如GLX_DISPLAY_KHR)的整数值。或者你可以通过挑选从get_gl_sharing_context_properties()返回的元组并纠正它们来解决问题:
glx_addr = ctypes.cast(OpenGL.GLX.glXGetCurrentDisplay(), ctypes.c_void_p).value #retrieve the glx ptr val as an int
context = cl.Context(properties=
[(cl.context_properties.GL_CONTEXT_KHR, OpenGL.platform.GetCurrentContext() )] +
[(cl.context_properties.GLX_DISPLAY_KHR, glx_addr )] +
[(cl.context_properties.PLATFORM, cl.get_platforms()[0])]
)
或者在pyffncl的cffi_cl.py src代码中修复bug本身并重新编译:
def _parse_context_properties(properties):
...
from ctypes import _Pointer, addressof
from ctypes import cast # add this
if isinstance(value, _Pointer):
#val = addressof(value) # remove this
val = cast(value, ctypes.c_void_p).value # add this
else:
val = int(value)
...
我稍微向开发人员传达了这个错误,所以希望很快就能解决。请参阅:https://lists.tiker.net/pipermail/pyopencl/2017-April/002285.html