リアルタイムレイトレーサーを書こうとしています。そのために、OpenGL と OpenCL の Java と Jogamp バインディングを使用します (Jogl と Jocl を呼び出します)。既に .cl カーネルにレイトレーシング コードがあり、うまく機能しています。出力を FloatBuffer として取得し、それを glTexImage2D 経由で OpenGL テクスチャに渡します。これを実現するために、プログラムで 2 回発生する FloatBuffer コピーを削除します (最初に OpenCL カーネル結果から RAM へ、次に RAM から OpenGL テクスチャへ)。明らかに、OpenGL テクスチャ ダイレクトから OpenCL バッファを指す方法があり、すべての計算が GPU で機能します。cl_khr_gl_sharingがあることを知っています私が望むことを行うOpenCLの拡張。しかし、これを Java Jogamp バインディング (jocl/jogl) で使用する方法がわかりません。誰かが私を助けたり、サンプルのJAVAコードを提供したりできますか(詳細が実際に異なるC++ではありません)?
1 に答える
0
それで、数日間の調査の後、私はそれを行う方法を見つけました。興味のある人のために回答を投稿します。
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 メソッドを使用して、float データ (0.0f - 1.0f) をこのテクスチャに書き込みます。
興味があれば、このアプローチについてお気軽にお尋ねください。
于 2016-05-17T12:34:36.133 に答える