2016-07-10 17 views
1

Ich möchte eine Anwendung erstellen, die OpenCL verwendet, um den Farbwert jedes Pixels in einer Textur und OpenGL zum Anzeigen dieser Textur zu berechnen. Das Problem ist, dass wenn ich versuche, einen Kontext mit GL Sharing-Eigenschaften zu erstellen, das Programm einfriert. Mit der Funktion erhalte ich eine Liste [(8200, 65538), (8203, 18446744072971422270)]. Die letzte Zahl in der Liste ist zu groß, um zu einem 64-Bit-int zu konvertieren, und ich bekomme einen Überlauffehler. Der Code Ich verwende den CL Kontext zu schaffen:PyOpenCL: gl Freigabe Kontext Erstellung fehlgeschlagen (Überlauffehler)

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) 

Der Code nie erreicht print("Context creation done"). Ich verwende QtPy4 und das QGLWidget, um den OpenGL-Kontext zu erstellen und die Textur anzuzeigen.

+0

Konnten Sie das jemals zum Laufen bringen? Ich stoße gerade auf dasselbe Problem. Besonders frustrierend ist, dass 'get_gl_sharing_context_properties()' manchmal einen gültigen 64-Bit-Wert zurückgibt, aber manchmal wird es zufällig fehlschlagen ... – CodeSurgeon

Antwort

0

Ok lief selbst in ein ähnliches Problem und hier ist meine Lösung dafür. Wenn Sie an, was get_gl_sharing_context_properties() sehen genau tut nach PyOpenCL's source code on github unter dem tools Modul, werden Sie den folgenden plattformspezifischen Code finden:

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 

Jetzt, da ich unter Windows bin ich an dem WGL-Code einen Blick nahm (was von PyOpenGL kommt) und festgestellt, dass WGL.wglGetCurrentDC() (wie natürlich) falsche Handle-Werte manchmal zurückgegeben, die den Integer-Überlauf verursacht. Es stellt sich heraus, dass der DC (Gerätekontext) ist wirklich angenommen zu einem 32 Bit vorzeichenbehafteten ganzzahligen. In der Wrapperfunktion PyOpenGL wird es jedoch falsch in eine 64-Bit-Ganzzahl ohne Vorzeichen konvertiert. Wenn ein negativer DC-Handle-Wert in PyOpenGL übergeben wird, wird es stattdessen zu 2^64 + annoying_negative_dc_number stattdessen konvertiert!

Die Lösung: konvertieren Sie es zurück! Hier ist, was ich jetzt tun, um zuverlässig eine Arbeits gl Interop Kontext zu erhalten:

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) 
0

Es ist ein Fehler in PyOpenCL, dass der Kontext Schöpfung verursacht falsch behandelt werden. Im Wesentlichen nimmt pyopencl eine Liste von Tupeln für die opencl-Eigenschaften und analysiert sie intern und übergibt sie an den CL-Kontexterstellungs-Handler. Die Tupel werden entweder als Zeiger oder Ganzzahlen übergeben. Wenn Zeiger für bestimmte Eigenschaften übergeben werden, wird angenommen, dass der Zeiger in einen ganzzahligen Wert umgewandelt wird, der an den CL-Kontext-Erstellungshandler übergeben wird, aber dies geschieht nicht korrekt. Stattdessen nimmt es die Adresse des Zeigers selbst.

Es gibt zwei mögliche Fehlerbehebungen.

Von der Benutzer-Codepage aus könnten Sie so etwas wie den folgenden eingeben, um den Ganzzahlwert für fehlerhafte Eigenschaften wie GLX_DISPLAY_KHR manuell zu übergeben. Oder Sie könnten das Problem nähern, indem die Tupel aus get_gl_sharing_context_properties zurück zerpflücken() und korrigieren sie:

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])] 
    ) 

oder innerhalb cffi_cl.py src Code von PyOpenCL beheben den Fehler selbst und neu kompilieren:

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) 
    ... 

Ich habe diesen Fehler vor ein paar Jahren dem Entwickler mitgeteilt, also wird er hoffentlich bald behoben sein. Siehe: https://lists.tiker.net/pipermail/pyopencl/2017-April/002285.html