GPU で実行されているシェーダーから CPU で実行されているプログラムに結果を戻す方法はありますか?
GPU で計算コストの高いアルゴリズムに基づいて単純なボクセル データからポリゴン メッシュを生成したいのですが、物理計算のために CPU で結果が必要です。
GPU で実行されているシェーダーから CPU で実行されているプログラムに結果を戻す方法はありますか?
GPU で計算コストの高いアルゴリズムに基づいて単純なボクセル データからポリゴン メッシュを生成したいのですが、物理計算のために CPU で結果が必要です。
「結果」を定義しますか?
一般に、OpenGLでGPGPUスタイルの計算を行う場合は、レンダリングシステムのニーズに合わせてシェーダーを構造化する必要があります。レンダリングシステムは一方向になるように設計されています。データがレンダリングシステムに入力され、画像が生成されます。逆に、レンダリングシステムにデータを生成させることは、一般的にレンダリングシステムの構造ではありません。
もちろん、それができないという意味ではありません。ただし、OpenGLの制限を中心にすべてを設計する必要があります。
OpenGLには、特定のシェーダーステージからデータを書き込むことができるフックがいくつか用意されています。これらのほとんどは、専用のハードウェアを必要とします
フラグメントシェーダーに対応しているハードウェアであれば、レンダリングしている現在のフレームバッファーに書き込むことができます。浮動小数点または整数の画像形式のフレームバッファオブジェクトとテクスチャを使用することで、さまざまな画像に必要なほとんどすべてのデータを書き込むことができます。テクスチャに入ると、単に呼び出すだけで、レンダリングされたピクセルデータを取得できます。または、FBOがまだバインドされている場合は、それを取得するために行うことができます。どちらの方法でも機能します。glGetTexImage
glReadPixels
この方法の主な制限は次のとおりです。
フレームバッファに添付できる画像の数。これにより、書き込むことができるデータの量が制限されます。GL 3.xより前のハードウェアでは、FBOは通常4つの画像と深度/ステンシルバッファに制限されていました。3.x以降のハードウェアでは、最低8つのイメージを期待できます。
レンダリングしているという事実。これは、データを変更する場所に三角形を正確に配置するように頂点データを設定する必要があることを意味します。これは些細なことではありません。また、通常、各テクセルを互いにかなり独立させたいため、有用な入力データを取得することも困難です。これらの制限を回避するフラグメントシェーダーを構築することは困難です。不可能ではありませんが、多くの場合、重要です。
このOpenGL3.0機能を使用すると、 OpenGLの頂点処理ステージ(頂点シェーダーおよびオプションのジオメトリシェーダー)からの出力を1つ以上のバッファーオブジェクトにキャプチャできます。
これは、再生したり、再度レンダリングしたりする頂点データをキャプチャする場合にはるかに自然です。あなたの場合、おそらくglGetBufferSubData
呼び出しで、または読み取りに使用して、レンダリング後に読み戻す必要がありますglMapBufferRange
。
ここでの制限は、通常、4つの出力値しかキャプチャできないことです。各値はvec4です。いくつかの厳しいレイアウト制限もあります。一部のOpenGL3.xおよび4.xハードウェアは、複数のフィードバックストリームにデータを書き込む機能を提供します。これらのストリームはすべて、異なるバッファーに書き込むことができます。
このGL4.2の機能は、書き込みの頂点を表しています。画像をバインドして(バッファに書き込みたい場合は、バッファテクスチャ)、それに書き込むだけです。作業する必要のあるメモリ順序の制約があります。
非常に柔軟性がありますが、非常に複雑です。それを適切に使用することの難しさに加えて、いくつかの制限があります。書き込むことができる画像の数はかなり制限されており、おそらく8程度です。また、実装には合計書き込み制限がある場合があるため、書き込み先の8つのイメージをフラグメントシェーダーの出力で共有する必要がある場合があります。
さらに、画像出力はフラグメントシェーダー(および4.3の計算シェーダー)に対してのみ保証されます。つまり、ハードウェアは、非FS/CSシェーダーステージでのイメージのロード/ストアの使用を禁止することができます。