11

私は以前、次のようなことをして画像ユニットの色の値をブレンドしたいという問題をすでに抱えていました。

vec4 texelCol = imageLoad(myImage, myTexel);
imageStore(myImage, myTexel, texelCol+newCol);

複数のフラグメントが「myTexel」に同じ値を持つ可能性があるシナリオでは、imageLoadコマンドとimageStoreコマンドの間にアトミック性を作成できず、他のシェード呼び出しによってその間のテクセルカラーが変更される可能性があるため、これは明らかに不可能です。

今、誰かが私に、シェーダーがテクセルにアクセスする前にしばらくループで待機し、フリーになるとすぐに整数をアトミックに書き込むように、uintテクスチャでアトミックコマンドを使用してセマフォを作成することで、この問題を回避していると言いましたテクスチャを使用して他のフラグメントシェーダーの呼び出しをブロックし、カラーテクセルを処理し、終了したら整数テクセルを再びアトミックに解放します。

しかし、これが実際にどのように機能するのか、そしてそのようなコードがどのように見えるのかについて頭を悩ませることはできませんか?

これを行うことは本当に可能ですか?GLSLフラグメントシェーダーをwhileループで待機するように設定できますか?可能であれば、誰かが例を挙げてもらえますか?

4

1 に答える 1

10

基本的には、スピンロックを実装しているだけです。1つのロック変数の代わりに、テクスチャ全体に相当するロックがあります。

論理的には、あなたがしていることは理にかなっています。しかし、OpenGLに関する限り、これは実際には機能しません

OpenGLシェーダー実行モデルでは、呼び出しは相互にほとんど定義されていない順序で実行されると述べられています。を参照してください。ただし、スピンロックは、さまざまなスレッド間で前進が保証されている場合にのみ機能します。基本的に、スピンロックでは、回転しているスレッドが、待機しているスレッドの実行から実行システムを飢えさせないようにする必要があります。

OpenGLはそのような保証を提供しません。つまり、あるスレッドがピクセルをロックしてから(何らかの理由で)実行を停止し、別のスレッドがそのピクセルをブロックする可能性があります。ブロックされたスレッドは実行を停止せず、ロックを所有するスレッドは実行を再開しません。

これは実際のシステムでどのように発生する可能性がありますか?さて、三角形からのいくつかのフラグメントで実行されているフラグメントシェーダー呼び出しグループがあるとしましょう。それらはすべてピクセルをロックします。ただし、ロック領域内の条件分岐により、実行時に分岐します。実行の相違は、それらの呼び出しの一部が別の実行ユニットに転送されることを意味する場合があります。現在利用可能なものがない場合は、利用可能になるまで事実上一時停止します。

ここで、他のフラグメントシェーダー呼び出しグループがやって来て、発散グループのに実行ユニットが割り当てられたとしましょう。そのグループが発散グループからのピクセルをスピンロックしようとすると、それは本質的に実行時間の発散グループを飢えさせ、決して起こらないことさえ待っています。

明らかに、実際のGPUには複数の実行ユニットがありますが、呼び出しグループがたくさんあると、そのようなシナリオで作業がときどき詰まる可能性があります。

于 2012-05-18T13:58:08.570 に答える