2016-05-11 12 views
3

Ich versuche Raytracer in Echtzeit zu schreiben. Ich verwende Java und Jogamp Bindings von OpenGL und OpenCL dafür (ruft Jogl und Jocl). Ich habe bereits Raytracing-Code in meinem .cl Kernel und es funktioniert gut. Ich werde als FloatBuffer ausgegeben und über glTexImage2D an die OpenGL-Textur übergeben. Jetzt möchte ich in Echtzeit gehen, und um dies zu erreichen, möchte ich die FloatBuffer-Kopie entfernen, die zweimal in meinem Programm passiert (zuerst - vom OpenCL-Kernel-Ergebnis zum RAM, und zweitens vom RAM zur OpenGL-Textur). Offensichtlich gibt es eine Möglichkeit, den OpenCL-Puffer direkt von der OpenGL-Textur zu unterscheiden, da alle Berechnungen auf der GPU laufen. Ich weiß, dass es cl_khr_gl_sharing Erweiterung für OpenCL gibt, die tun, was ich will. Aber ich kann nicht verstehen, wie man das in Java Jogamp Bindings (jocl/jogl) benutzt. Kann jemand mir helfen oder einen Beispiel-JAVA-Code geben (nicht C++, das sich wirklich in Details unterscheidet)?Wie benutzt man cl_khr_gl_sharing in Jocl?

+0

Hinweis: Haben Sie OpenGL-Compute-Shader untersucht? Denn es wäre perfekt für deinen Fall – elect

+0

Hast du Jogl-Demos auf Github angeschaut? – gouessej

Antwort

0

Also, nach ein paar Tagen der Forschung finde ich, wie es geht. Veröffentlichen Sie eine Antwort für jeden, der interessiert ist.

In "init" -Methode von Jogl GLEventListener Sie GL-Kontext erstellen. Sie müssen CL-Kontext auch in dieser Methode erstellen. Mein Beispielcode für diesen:

public void init(GLAutoDrawable drawable) { 
    GL4 gl4 = drawable.getGL().getGL4(); 

    gl4.glDisable(GL4.GL_DEPTH_TEST); 
    gl4.glEnable(GL4.GL_CULL_FACE); 
    gl4.glCullFace(GL4.GL_BACK); 
    buildScreenVAO(gl4); 

    FloatBuffer pixelBuffer = GLBuffers.newDirectFloatBuffer(width * height * 4); 
    this.textureIndex = GLUtils.initTexture(gl4, width, height, pixelBuffer); 
    this.samplerIndex = GLUtils.initSimpleSampler(gl4); 

    if (clContext == null) { 
     try { 
      gl4.glFinish(); 
      this.clContext = CLGLContext.create(gl4.getContext()); 
      this.clDevice = clContext.getMaxFlopsDevice(); 
      //if (device.getExtensions().contains("cl_khr_gl_sharing")) 
      this.clCommandQueue = clDevice.createCommandQueue(); 

      this.clProgram = clContext.createProgram(new FileInputStream(new File(ResourceLocator.getInstance().kernelsPath + "raytracer.cl"))).build(); // load sources, create and build program 
      this.clKernel = clProgram.createCLKernel("main"); 

      this.clTexture = (CLGLTexture2d<FloatBuffer>) clContext.createFromGLTexture2d(GL4.GL_TEXTURE_2D, textureIndex, 0, Mem.WRITE_ONLY); 
      this.viewTransform = clContext.createFloatBuffer(16 * 4, Mem.READ_ONLY); 
      this.w = clContext.createFloatBuffer(1, Mem.READ_ONLY); 

      clKernel.putArg(clTexture).putArg(width).putArg(height).putArg(viewTransform).putArg(w); 
      fillViewTransform(viewTransform); 
      fillW(w); 

      clCommandQueue.putWriteBuffer(viewTransform, false); 
      clCommandQueue.putWriteBuffer(w, false); 
      clCommandQueue.putAcquireGLObject(clTexture); 
      clCommandQueue.put1DRangeKernel(clKernel, 0, width * height, 0); 
      clCommandQueue.putReleaseGLObject(clTexture); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    buildShaderProgram(gl4); 
    bindObjects(gl4); 
} 

Der Kern Linie ist: clContext.createFromGLTexture2d(GL4.GL_TEXTURE_2D, textureIndex, 0, Mem.WRITE_ONLY); Sie sollten ein OpenCL-Textur-Objekt für Ihre vorherige erstellt OpenGL Textur erstellen. Code of Erstellen OpenGL Textur:

 gl4.glGenTextures(1, indexBuffer); 
     int textureIndex = indexBuffer.get(); 
     indexBuffer.clear(); 

     gl4.glBindTexture(GL4.GL_TEXTURE_2D, textureIndex); 
     gl4.glTexParameterf(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR); 
     gl4.glTexParameterf(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR); 
     gl4.glTexImage2D(GL4.GL_TEXTURE_2D, 0, GL4.GL_RGBA32F, width, height, 0, GL4.GL_RGBA, GL4.GL_FLOAT, pixelBuffer); //TODO 

     gl4.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_BASE_LEVEL, 0); 
     gl4.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAX_LEVEL, 0); 

     int[] swizzle = new int[] { GL4.GL_RED, GL4.GL_GREEN, GL4.GL_BLUE, GL4.GL_ONE }; 
     gl4.glTexParameterIiv(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_SWIZZLE_RGBA, swizzle, 0); 
     gl4.glBindTexture(GL4.GL_TEXTURE_2D, 0); 
     return textureIndex; 

Und die letzte - Sie müssen richtigen Datentyp Textur Argument in Ihrem OpenCL-Kernel verwenden. In meinem Fall Kernel-Methode hat die folgende Signatur:

kernel void main(write_only image2d_t dst, const uint width, const uint height, global float* viewTransform, global float* w){                    

und ich verwende write_imagef build-in OpenCL Methode float Daten (0.0f - 1.0f) schreiben in diese Textur.

Fühlen Sie sich frei, mich über diesen Ansatz zu fragen, wenn Sie interessiert sind.