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?
Antwort
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.
Hinweis: Haben Sie OpenGL-Compute-Shader untersucht? Denn es wäre perfekt für deinen Fall – elect
Hast du Jogl-Demos auf Github angeschaut? – gouessej