GLSL の memoryBarrier が単一のシェーダー呼び出し内でメモリ トランザクションを注文し、OpenGL API の glMemoryBarrier が複数のシェーダー呼び出し (必ずしも同じプログラムであるとは限らない) にわたってメモリ トランザクションを注文するということですか。
1 に答える
GLSL の memoryBarrier が単一のシェーダー呼び出し内でメモリ トランザクションを注文し、OpenGL API の glMemoryBarrier が複数のシェーダー呼び出し (必ずしも同じプログラムであるとは限らない) にわたってメモリ トランザクションを注文するということですか。
ではない正確に。シェーダー呼び出しとは何かを明確にすることから始める必要があります。これは、単一の入力エンティティが処理されるためのシェーダー コードの実行です。そのため、描画呼び出しの頂点ごとに頂点シェーダーが呼び出され、ラスタライズによって生成されたフラグメントごとに少なくとも 1 回フラグメント シェーダーが呼び出されます (特定のタイプのマルチサンプリングでは複数になります)。異なる描画呼び出し (異なる可能性があります) のシェーダー呼び出しは、もちろん異なる呼び出しでもあります。しかし、通常、「複数の呼び出し」について話すとき、1 つは同じ描画呼び出し中の同じシェーダーのことを意味します (これらはすべて並列で実行される可能性があります)。
GLSL 仕様 (バージョン 4.40) (セクション 8.17) には、メモリバリアについて次のように書かれています。
すべてのタイプのシェーダーは、イメージ変数を使用して、テクスチャおよびバッファー オブジェクトの内容を読み書きできます。1 回のシェーダー呼び出し内での読み取りと書き込みの順序は明確に定義されていますが、複数の個別のシェーダー呼び出しから 1 つの共有メモリ アドレスへの読み取りと書き込みの相対的な順序はほとんど定義されていません。1 つのシェーダー呼び出しによって実行されるメモリ アクセスの順序は、他のシェーダー呼び出しによって観察されるように、ほとんど定義されていませんが、メモリ制御関数によって制御できます。
したがって、これは、「単一の呼び出し」の意味に応じて、上記のステートメントで意図したものである場合とそうでない場合があります。ただし、それを「単一の描画呼び出しのすべての呼び出し」と解釈した場合に限ります。
これは、OpenGL 4.4 コア プロファイル仕様のセクション 7.12.2からのものです。
シェーダーによって実行されるバッファーおよびテクスチャ データ ストアの効果が、同じオブジェクトを使用する後続の操作に表示され、以前に要求された操作によってまだ読み取られるデータが上書きされないようにするために、明示的な同期が必要です。手動で同期しないと、「古い」プリミティブの処理が完了する前に、「新しい」プリミティブのシェーダー ストアが完了する場合があります。さらに、「古い」プリミティブのストアは、「新しい」プリミティブの処理が開始される前に完了しない場合があります。
したがって、これは、次の描画呼び出しのシェーダー呼び出しに関するすべてでもありません。新しいシェーダーの呼び出しもまったく必要ありません。次の GL コマンドが、シェーダーが書き込んだデータを使用または上書きする場合、これを手動で同期する必要があります。これは、シェーダがバッファまたはテクスチャに書き込む場合にのみ関連することに注意してください。パイプラインを介した「通常の」フレームバッファ書き込みには関連しません。
同じシェーダー タイプの呼び出しの相対的な順序は定義されていません。プリミティブ B の処理中にシェーダーによって発行されたストアは、プリミティブ A がプリミティブ B の前に指定されている場合でも、プリミティブ A のストアの前に完了する可能性があります。これは、フラグメント シェーダーにも当てはまります。フラグメント シェーダーの出力はプリミティブな順序でフレーム バッファーに書き込まれますが、フラグメント シェーダーの呼び出しによって実行されるストアはそうではありません。
ここに貼り付けるには長すぎるセクション 7.12 をすべて読むことをお勧めしますが、GL のメモリ バリア機能を理解するには重要です。