2017-08-10 4 views
1

OpenGLレッドブックバージョン8(GL 4.3)の例11.19 whileループにimageLoad()を配置し、前のプリミティブの少なくとも1つのフラグメントがこの値を更新するまでポーリングを維持します。この本はGLSL memoryBarrier()

と言っています。例11.19は、メモリバリアの非常に単純な使用例を示しています。それは、フラグメント間のある程度の順序付けが保証されることを可能にする。 functionUsingBarriers()の上部では、単純なループを使用して、メモリロケーションの内容 が現在のプリミティブIDに達するまで待機します。 同じプリミティブの2つのフラグメントが同じ ピクセルに存在しないことがわかっているので、 関数の本体でコードを実行するとき、前のプリミティブの少なくとも1つのフラグメントは 処理された。次に非整数演算を使用して、 フラグメントの位置でメモリの内容を変更します。我々は、他のシェーダ の呼び出しに、もともとは関数の先頭でポーリングされた共有メモリ位置 に書き込むことによって行われます。

当社修正された画像の内容が他のシェーダの呼び出し前にメモリ に書き戻されることを保証するためには、関数の本体の中に開始、我々は カラー画像の更新と順序を強制する プリミティブカウンターの間にメモリバリアへの呼び出しを使用します。

しかし、GL仕様4.3は、別の呼び出しによって書かれた1回の呼び出しのポール・メモリは、どのようにすることができ、他の呼び出しが開始されていることを前提とし、その書き込み

を完了することができた

を語ります以前のプリミティブのフラグメント呼び出しが開始され、その書き込みが完了したことを確認しますか?

郵便SRCコード

#version 420 core 

layout (rgba32f} uniform coherent image2D my_image; 

// Declaration of function 
void functionUsingBarriers(coherent uimageBuffer i) 

{ 

    uint val; 

    // This loop essentially waits until at least one fragment from 
    // an earlier primitive (that is, one with gl_PrimitiveID - 1) 
    // has reached the end of this function point. Note that this is 
    // not a robust loop as not every primitive will generate 
    // fragments. 
    do 
    { 
     val = imageLoad(i, 0).x; 
    } while (val != gl_PrimitiveID); 

    // At this point, we can load data from another global image 
    vec4 frag = imageLoad(my_image, gl_FragCoord.xy); 

    // Operate on it... 
    frag *= 0.1234; 
    frag = pow(frag, 2.2); 

    // Write it back to memory 
    imageStore(my_image, gl_FragCoord.xy, frag); 

    // Now, we’re about to signal that we’re done with processing 
    // the pixel. We need to ensure that all stores thus far have 
    // been posted to memory. So, we insert a memory barrier. 
    memoryBarrier(); 

    // Now we write back into the original "primitive count" memory 
    // to signal that we have reached this point. The stores 
    // resulting from processing "my_image" will have reached memory 
    // before this store is committed due to the barrier. 
    imageStore(i, 0, gl_PrimitiveID + 1); 

    // Now issue another barrier to ensure that the results of the 
    // image store are committed to memory before this shader 
    // invocation ends. 
    memoryBarrier(); 
} 
+0

私たちは皆この本を持っていません。この例で何が起こっているのか具体的な詳細を実際に教えてもらえますか?特に、「以前のプリミティブ」は何を意味していますか? –

+0

こんにちはNicol、私は質問を更新しました。それを再度読んでください。 –

答えて

0

このコード(とそれに付随するテキスト)が誤っナンセンスです。この文を考えてみましょう:

我々は同じプリミティブからの二つの断片から、我々は関数の本体にコードを実行しているときことを知って、同じピクセル上に少なくとも1つの断片が上陸できないことを知っているので前のプリミティブが処理されました。我々は、メッシュ内のプリミティブは、プリミティブ間で仕事のGPUの分布に関する正確を意味しないこと、(一般的に難合理的な仮定)を重複していないことを前提とした場合でも

OpenGLの仕様では、これは明らかに:

同じシェーダタイプの呼び出しの相対的順序は未定義です。プリミティブBで作業中にシェーダによって発行された ストアは、プリミティブAがプリミティブ Bの前に指定されていても、プリミティブAのストアに先に を完了することがあります。これはフラグメントシェーダにも適用されます。フラグメントシェーダ出力 は常にプリミティブな順序でフレームバッファに書き込まれますが、 によって実行されるストアはフラグメントシェーダの呼び出しではありません。

...

シェーダ呼び出し順に上記の制限もunimplementableプリミティブの単一のセット内のシェーダ呼び出しの間 同期のいくつかの形態を作ります。たとえば、別の呼び出しによって書き込まれたポーリング・メモリーを1つ呼び出すと、他の呼び出しが開始されたとみなされ、 の書き込みを完了することができます。このような保証が行われる唯一のケースは、前のステージ のシェーダ呼び出しの出力から の1つのシェーダ呼び出しの入力が生成された場合です。

はい、OpenGLの仕様は、特にあなたがを行うことができない何かとしてこれを呼ばれます。公式のOpenGLの本にはどうなっているのか分かりませんが、あなたの本能は正しいです。それはまったく間違っています。これは実際にARB_fragment_shader_interlockが存在する理由です。そうでなければ、そのようなことはできません。

+0

ありがとうございました。あなたの明確化は私の疑惑を支えます。このコード例は、権威あるOpenGLの赤い本から来ているので、私は本能を疑った! –