2016-04-24 11 views
2

Ich versuche, OpenCL mit OpenGL-Interop zu verwenden. um den Pfadverfolgungsalgorithmus auf der GPU zu berechnen und dann die GL-Textur auf Quad zu zeichnen. Funktioniert wie beabsichtigt auf Intel-CPU, aber wenn ich versuche, auf GTX 970 einzulaufen, gibt es segfault beim Entsperren dieser GL-Textur. Weiß nicht, ob das der Grund oder der laufende Kernel ist. Ich werde den Code für sich sprechen lassen. Ich benutze OpenCL C++ Wrapper BTW.OpenCL/OpenGL Interoperabilität Textur segfault

GL Textur Schöpfung

glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer); 
glBindTexture(GL_TEXTURE_2D, 0); //Unbind texture 

CL Textur Zuordnung

m_textureCL = cl::ImageGL(m_context, 
     CL_MEM_READ_WRITE, 
     GL_TEXTURE_2D, 
     0, 
     texture, 
     &errCode); 

RunKernel Funktion

//----------------------------------------------------------------------------- 
// Lock texture 
//----------------------------------------------------------------------------- 
std::vector<cl::Memory> glObjects; //Create vector of GL objects to lock 
glObjects.push_back(m_textureCL); //Add created CL texture buffer 
glFlush(); //Flush GL queue 

errCode = m_cmdQueue.enqueueAcquireGLObjects(&glObjects, NULL, NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error locking texture" << errCode << std::endl; 
    return errCode; 
} 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
// Run queue 
//----------------------------------------------------------------------------- 
errCode = m_cmdQueue.enqueueNDRangeKernel(
     m_kernel, 
     cl::NullRange, 
     cl::NDRange(height*width), 
     cl::NullRange, 
     NULL, 
     NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error running queue: " << errCode << std::endl; 
    return errCode; 
} 
//--------------------------------------- 


//----------------------------------------------------------------------------- 
// Unlock 
//----------------------------------------------------------------------------- 
errCode = m_cmdQueue.enqueueReleaseGLObjects(&glObjects, NULL, NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error unlocking texture: " << errCode << std::endl; 
    return errCode; 
} <<------ Here's where segfault occurs, can't get past this point 

Kernel-Funktion def.

__kernel void RadianceGPU (
    __write_only image2d_t texture, 
    other_stuff...) 

zu Textur im Kernel-Schreiben

write_imagef(
     texture, 
     (int2)(x, height-y-1), 
     (float4)(
      clamp(framebuffer[id].x, 0.0f, 1.0f), 
      clamp(framebuffer[id].y, 0.0f, 1.0f), 
      clamp(framebuffer[id].z, 0.0f, 1.0f), 
      1.0f) * 1.0f); 

Interessant ist, dass write_imagef() funktioniert trotz der Textur UNSIGNED_BYTE zu sein.

EDIT: So habe ich endlich herausgefunden, was das Problem verursacht. Beim Erstellen von CL-Eigenschaften wurde eine falsche Anzeige eingestellt. Ich habe gerade ein Fenster von GLFW eingefügt, was Probleme bei Nvidia-Treibern verursacht. Sie müssen glxGetCurrentDisplay oder glfwGetX11Display verwenden. Dies behebt den segfault.

+0

Welche Version von OpenCL verwenden Sie? – Andreas

+0

Nvidia CUDA 1.2 – Nixx

Antwort

2

Ich bin mir nicht sicher, ob das dein Problem ist, aber ich werde es trotzdem versuchen.

Sie haben den Zugriff auf glObjects nicht portabel synchronisiert. Von OpenCL 1.1:

Vor clEnqueueAcquireGLObjects Aufruf muss die Anwendung sicherzustellen, dass alle ausstehenden GL Operationen, die die Objekte in mem_objects angegebenen Zugriff abgeschlossen haben. Dies kann portabel durch Ausgeben und Warten auf die Vervollständigung eines glFinish-Befehls in allen GL-Kontexten mit ausstehenden Verweisen auf diese Objekte erreicht werden. Implementierungen bieten möglicherweise effizientere Synchronisationsmethoden; für Beispiel auf einigen Plattformen Aufruf glFlush möglicherweise ausreichend, oder Synchronisation kann implizit innerhalb eines Threads sein, oder es Hersteller - spezifische Erweiterungen, die Platzierung eines Zauns in den GL-Befehlsstrom und warten auf die Fertigstellung dieser Zaun in der CL-Befehl Warteschlange. Beachten Sie, dass derzeit keine anderen Synchronisationsmethoden als glFinish zwischen OpenGL-Implementierungen übertragen werden können.

Grundsätzlich ist glFinish für tragbares Verhalten erforderlich.

Im Abschnitt unter der bereits zitierten dort weitere Informationen, die von Interesse sein könnte:

In ähnlicher Weise nach dem Aufruf clEnqueueReleaseGLObjects, die Anwendung ist dafür verantwortlich, sicherzustellen, dass alle OpenCL anstehende Operationen , die auf die Objekte zugreifen Spezifiziert in mem_objects wurde abgeschlossen, bevor nachfolgende GL-Befehle ausgeführt werden, die auf diese Objekte verweisen. Dies kann portabel erreicht werden, indem clWaitForEvents mit dem Ereignisobjekt aufgerufen wird, das von clEnqueueRelease GL Objects zurückgegeben wird, oder indem clFinish aufgerufen wird. Wie oben, können einige Implementierungen effizientere Methoden anbieten.

Hier ist ein Link auf das Dokument aus zitiert: https://www.khronos.org/registry/cl/specs/opencl-1.1.pdf#nameddest=section-9.8.6

+0

Danke für deine Antwort, ich gebe es eine Chance, sobald ich die Chance habe. Eine andere Sache, die mich stört ist, wenn ich CL-Textur zuweisen, kann ich nicht auf die GL-Textur zugreifen. Dies passiert, wenn ich Nvidia Opencl 1.2 und OpenGL 4.5 benutze, aber es gibt keine Probleme, wenn ich opencl 1.2 von AMD auf Intel CPU/GPU und OpenGL 3.3 – Nixx

+0

@ Nixx Post als einen anderen Fragecode und alles verwende. – Andreas