我正在尝试编写实时raytracer。
我使用OpenGL和OpenCL的Java和Jogamp绑定(bind)(称为Jogl和Jocl)。
我的.cl内核中已经有光线追踪代码,并且效果很好。我将输出作为FloatBuffer并将其通过glTexImage2D传递给OpenGL纹理。现在,我想实时进行操作,要实现此目的,我想删除FloatBuffer副本,该副本在程序中发生两次(第一个-从OpenCL内核结果到RAM,第二个从RAM到OpenGL纹理)。显然,有一种方法可以直接从OpenGL纹理指向OpenCL缓冲区,因为所有计算都可以在GPU上进行。
我知道OpenCL有 cl_khr_gl_sharing 扩展名,可以满足我的要求。但是我不明白如何在Java Jogamp绑定(bind)(jocl / jogl)中使用它。有人可以帮我还是提供一些示例JAVA代码(不是C++,实际上细节有所不同)?

最佳答案

因此,经过几天的研究,我找到了解决方法。为感兴趣的人发布答案。

在Jogl的GLEventListener的“init”方法中,您将创建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);您应该为先前创建的OpenGL纹理创建一个OpenCL纹理对象。创建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)写入此纹理。

如果您有兴趣,随时问我这种方法。

关于java - 如何在Jocl​​中使用cl_khr_gl_sharing?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37161647/

10-16 21:49