2012-01-11 31 views
3

私はレイキャスティング、レイマーチングなどのOpenCLでグラフィックス計算を行うつもりです。そして、私はこの計算(ピクセル画像)の結果を表示するためにOpenGLを使用したいと思います。フレームバッファにテクスチャバッファを付けて使用します。 OpenCLは結果をテクスチャに書き込み、glBlitFrameBuffer関数を使ってテクスチャデータをアプリケーションウィンドウのフレームバッファにコピーします。 私は、CL/GL間の問題を実装中に満たしました。私はそれを示す簡単な例を書いた。この例は、フレームバッファオブジェクトとテクスチャオブジェクトの初期化、それらの結合、GLテクスチャバッファからのOpenCLバッファの作成を示しています。最後に、メインレンダーループが表示されます。各フレームに新しいデータを含むテクスチャ書き込み、フレームバッファの添付とこのフレームバッファのコピーから構成されます。GL/CL相互運用性:共有テクスチャ

テクスチャ初期化:

for (int i = 0; i < data.Length; i +=4) { 
    data [i] = 255; 
} 
GL.BindTexture (TextureTarget.Texture2D, tboID [0]); 
GL.TexImage2D<byte>(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0, 
        PixelFormat.Rgba, PixelType.UnsignedByte, data); 
GL.BindTexture (TextureTarget.Texture2D, 0) 

TBO + FBO初期化:

GL.BindFramebuffer (FramebufferTarget.FramebufferExt, fboID [0]); 
GL.FramebufferTexture2D (FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0, 
          TextureTarget.Texture2D, tboID [0], 0); 
GL.BindFramebuffer (FramebufferTarget.FramebufferExt, 0); 

CL/GL初期化:

bufferID = CL.CreateFromGLTexture2D (context, memInfo, textureTarget, mipLevel, glBufferObject, out errorCode); 

レンダリングループ:

for (int i = 0; i < data.Length; i += 4) { 
    data [i] = tt; 
} 
tt++; 
GL.BindTexture (TextureTarget.Texture2D, tboID [0]); 
GL.TexImage2D<byte> (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0, 
         PixelFormat.Rgba, PixelType.UnsignedByte, data); 

GL.BindTexture (TextureTarget.Texture2D, 0); 
GL.BindFramebuffer (FramebufferTarget.FramebufferExt, fboID [0]); 
GL.FramebufferTexture2D (FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0, 
          TextureTarget.Texture2D, tboID [0], 0); 
GL.BindFramebuffer (FramebufferTarget.FramebufferExt, 0);GL.BindFramebuffer (FramebufferTarget.ReadFramebuffer, fboID [0]); 

GL.ReadBuffer (ReadBufferMode.ColorAttachment0); 
GL.DrawBuffer (DrawBufferMode.Back); 

GL.BlitFramebuffer (0, 0, w, h, 0, 0, w, h, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest); 

GL.BindFramebuffer (FramebufferTarget.ReadFramebuffer, 0); 

一見すると、このコードは奇妙に見えますが、それは私の問題を完全に示しています。 CLはここではまったく動作しません。このアプリケーションでは、OpenCLコンテキストが作成され、OpenCLバッファの初期化が行われます。 これの作業は簡単でなければなりません。画面の色が黒から赤に変わります。そして、このようには機能しません。色は最初の赤色(テクスチャの初期化)から変化しません。 しかし、私はCL/GL初期化(GLテクスチャからCLバッファを作成する)をコメントすると正常に動作します。 なぜそうですか?なぜGLバッファの動作がCLの添付ファイルによって変わるのですか?それを修正して動作させるには?

+0

私は最終的にこの現象を確認できます。Image2DGLオブジェクトがテクスチャにバインドされると、テクスチャはブロックされ、別のコンテキストとの間でやりとりできません。これはNVIDIAデバイス上にもあります。とにかくブロックされた場合、明示的な 'acquire'と' release'がなぜあるのでしょうか? – rdoubleui

答えて

1

最後に私のシステム(Windows 7/AMD Radeon HD 5870)でItunのコードを実行することができました。このテクスチャでGL/CL Interopをアクティブにした後、ItunのコードがGLによって徐々に色でテクスチャから黒色から赤色に変わることを思い出してください。

結果は少なくとも奇妙です。私のシステムでは、意図したとおりに動作します。しかし、Itunシステム(Windows 7/NVidia GeForce)では、同じコードがまったく機能せず、例外やエラーコードも提供されません。さらに、CLが両方のシステムでこのテクスチャを適切に使用することについて言及したいと思います。したがって、この場合GLに何か問題があります。

私たちは何が起こっているのか分かりません。これは、Itunの古いGPUハードウェアまたはバグの多いNVidiaドライバのいずれかです。

+0

ちょうど記録のために:どのnVidiaチップがありますか? – rdoubleui

+0

また、あなたのamdカードを使ってその間違った画像記述子を取り除くためにあなたが変えなければならなかったものを知ってうれしいです... – rdoubleui

3

EDIT 2:

次に、あなたがInvalidImageFormatDescriptorを得ている理由を確認する必要があります。パラメータの順序が正しく、tboの画像記述子が誤解を招くかどうか(内部画像構造体 - OpenCL仕様参照)を確認してください。仕様から:

OpenGLテクスチャ内部フォーマットがサポートされているOpenCLイメージフォーマットにマップされていない場合、CL_INVALID_IMAGE_FORMAT_DESCRIPTOR。


EDIT:

だから私は、OpenTKでOpenCLの機能はClooという名前の別のプロジェクトによって提供されて理解しています。 ComputeImage2Dそのドキュメントの状態の場合:あなたのと比較すると

CreateFromGLTexture2D (ComputeContext context, ComputeMemoryFlags flags, int textureTarget, int mipLevel, int textureId) 

CreateFromGLTexture2D (context, MemFlags.MemReadWrite, TextureTarget.Texture2D, ((uint[])tboID.Clone()) [0], 0); 

は、あなたが間違った順序でミップレベルとtboを持っていることを見てみます。誤った初期化は、未知の動作につながる可能性があります。


あなたが提供しているコードから何が問題になるかは分かりません。今Interopを見ていて、ただそれに入っています。最初に試してみるのは、try/catchブロックを置いて、可能であれば error codeについての手がかりを得ることです。

明らかに確認済みです:cl_khr_gl_sharing拡張機能はお使いの端末で利用できますか?

サンプルコード内の実際のOpenCl/OpenGL Interopのテクスチャ/イメージ初期化のみを提供しているので、もう一度推測します。メモリオブジェクトを取得しましたか?

cl_int clEnqueueAcquireGLObjects (cl_command_queue command_queue, 
    cl_uint num_objects. 
    const cl_mem *mem_objects, 
    cl_uint num_events_in_wait_list, 
    const cl_event *event_wait_list, 
    cl_event *event) 

OpenCL 1.1 specifiction状態:

機能cl_int clEnqueueAcquireGLObjectsは、OpenGLオブジェクトから作成されたOpenCLのメモリ・オブジェクトを取得するために使用されます。これらの オブジェクトは、 コマンドキューにキューイングされたOpenCLコマンドで使用するには、事前に取得する必要があります。 OpenGLオブジェクトは、 command_queueに関連付けられたOpenCLコンテキストによって取得されるため、OpenCL コンテキストに関連付けられたすべてのコマンドキューで使用できます。

したがって、メモリオブジェクトが特定のコマンドキューにバインドされていない可能性があります。

また、glFinish()を発行して、メモリオブジェクトを取得する前にOpenGL側のすべての初期化を確実に行う必要があります。

+0

Itunの例はかなりシンプルです - あなたが見ることができるように、CLはそこでさえ使用されていません - GLだけです。したがって、 'clEnqueueAcquireGLObjects'も' glFinish'も必要ではありません。問題の本質は 'CL.CreateFromGLTexture2D'コールです。その後、" Render Loop "スニペットが動作を停止します(また、" Render Loop "サンプルはGLのみを使用します)。例えば、私のシステム(Radeon HD 5870)では、 'System.Exception:CL Error has occured:InvalidImageFormatDescriptor'を取得します。驚くべきことに、Itunシステムでは(NVidia GeForce​​)、例外なくGLが正常に動作しなくなります。 –

+0

'CL.CreateFromGLTexture2D'が干渉を引き起こすかのように見えます。とにかく、(glFinishを使うなどの)多くの組み合わせはすでにテストされています。解決策はまだ出ていない。誰かが自分のプラットフォームで同様のコードをテストしてフィードバックを与えることができれば幸いです。 –

+0

私が言及したように、私は、OpenCLの部分に関するすべてのコードが表示されているわけではないことを前提としています(したがってコードをテストしようとしませんでした)。 OPは、OpenCLでレイキャストのような計算をしたかったと述べているので、CL/GL interopチェーンの初期化で可能な欠点を調べました。 – rdoubleui