2016-05-11 3 views
3

Я пытаюсь писать в реальном времени raytracer. Я использую привязки Java и Jogamp OpenGL и OpenCL для него (вызывает Jogl и Jocl). У меня уже есть raytracing-код в моем ядре .cl и его работа хорошо. Я получаю вывод как FloatBuffer и передаю его текстуре OpenGL через glTexImage2D. Теперь я хочу идти в реальном времени, и для этого я хочу удалить копию FloatBuffer, которая дважды повторяется в моей программе (сначала - из результата ядра OpenCL в ОЗУ, а также от ОЗУ до текстуры OpenGL). Очевидно, что есть способ указывать буфер OpenCL из прямой текстуры OpenGL, потому что все вычисления работают на графическом процессоре. Я знаю, что есть cl_khr_gl_sharing Расширение для OpenCL, которые делают то, что я хочу. Но я не могу понять, как использовать это в Java Jogamp bindings (jocl/jogl). Может ли кто-нибудь помочь мне или дать образец JAVA-кода (а не C++, который действительно отличается деталями)?Как использовать cl_khr_gl_sharing в Jocl?

+0

Подсказка: вы исследовали информацию об аутриггерах? Потому что это было бы идеально для вашего дела. – elect

+0

Вы посмотрели jogl-demos на Github? – gouessej

ответ

0

Итак, после нескольких дней исследований я нахожу, как это сделать. Отправка ответа для любого, кто интересуется.

В методе «init» GLEventListener Jogl вы создаете контекст GL. Вы также должны создать CL-контекст в этом методе. Мой пример кода для этого:

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); 
} 

Ядром линия: clContext.createFromGLTexture2d(GL4.GL_TEXTURE_2D, textureIndex, 0, Mem.WRITE_ONLY); Вы должны создать текстуру объекта OpenCL для предыдущей созданной текстуры OpenGL. Код создания OpenGL текстуры:

 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; 

И последнее - вы должны использовать правильный тип данных текстуры аргумента в вашем OpenCL ядра. В моем методе случае ядро ​​имеет следующую подпись:

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

и я использую write_imagef построить в методе OpenCL для записи данных с плавающей точкой (0.0f - 1.0f) в эту текстуру.

Не стесняйтесь спрашивать меня об этом подходе, если вы заинтересованы.

 Смежные вопросы

  • Нет связанных вопросов^_^