1

フラグメント シェーダーは、2 つのアトミック カウンターを使用します。最初の値をインクリメントする場合としない場合と、2 番目の値をインクリメントする場合としない場合があります (ただし、両方をインクリメントすることはありません)。ただし、カウンターを変更する前に、現在の値が常に読み取られ、カウンターが後で変更された場合、以前に読み取られた値がカスタム ロジックに使用されます。これはすべて (ほとんどの場合展開可能な) ループで発生します。

大まかに次のようなフローを想像してください。

  • FOR 0-20(コンパイル時に解決可能なconst)など、いくつかの小さな展開可能なループで...
  • AC1 と AC2 のカウンター値を取得する
  • いくつかの値を確認してください:
  • x の場合: uimage1D_A のテクセルをインデックス AC1 に設定し、AC1 をインクリメントします。
  • それ以外: uimage1D_B のインデックス (imgwidth-AC2-1) にテクセルを設定し、AC2 をインクリメントします。

質問: シェーダーは現在のカウンター値を照会します。常に「最新」の値を取得しますか? ここで、フラグメント シェーダーの大規模な並列性が失われますか (現在の世代および将来の GPU とドライバーに関してのみ)?

分岐 (if x) については、別の ( readonly restrict uniform)のテクセルをuimage1D( uniform)と比較しuintます。したがって、一方のオペランドは間違いなく均一なスカラーですが、もう一方はimageLoad().x画像は均一ですが、この種の分岐はまだ「完全に並列化」されていますか? 両方の分岐がそれぞれ正確に 2 つのほぼ同一の命令であることがわかります。「完全に最適化された」GLSL コンパイラを想定すると、この種の分岐はストールを引き起こす可能性がありますか?

4

2 に答える 2

6

アトミック カウンターはアトミックです。ただし、各アトミック操作は、その操作に対してのみアトミックです。

そのため、すべてのシェーダーがカウンターから一意の値を取得するようにするには、すべてのシェーダーがそのカウンターにアクセスする必要があります(またはatomicCounterIncrementDecrementただし、すべて同じものを使用する必要があります)。

あなたが提案していることを行う正しい方法は次のとおりです。

  1. いくつかの値を確認してください:
  2. x の場合:
    1. atomicCounterIncrement(AC1)、返された値を格納します。
    2. 格納された値を、uimage1D_A に何かを設定するテクセルとして使用します。
  3. そうしないと:
    1. atomicCounterIncrement(AC2)、返された値を格納します。
    2. 格納された値を使用して、uimage1D_B に何かを設定するテクセル (imgwidth - val - 1) を計算します。

あなたの「フェッチして後でインクリメントする」戦略は、発生するのを待っている競合状態です。壊れているので「完全に並列化」されていても構いません。高速になるかどうか疑問に思う前に、それが機能する必要があります。

GPU に取り組む前に、 CPUのアトミックとスレッド化に慣れることを強くお勧めします。これは、初心者がアトミックを扱う際に犯すよくある間違いです。GLSL アトミックとイメージのロード/ストアを正常に使用するには、スレッドのエキスパート (または少なくとも中級レベル) である必要があります。

于 2012-03-17T08:44:29.607 に答える
2

Nicol Bolasが示唆したように、アトミックカウンターから読み取った値が別のカーネルによって読み取られないようにしたい場合は、アトミックインクリメントを実行し、返された値を使用する必要があります。実行しない限り、他のカーネルにはありません。atomicCounter(AC1)インクリメントせずに値をチェックします。アトミックに値をインクリメントして古い値に戻した瞬間に、同じことを行う他のすべての人がインクリメントされた値のみを取得するようにします。

あなたは A-Buffer を行っているようですが、なぜ 2 番目のカウンターが必要なのか知りたいです。uimage1D_A は、uimage1D_B に格納されているフラグメント リストへのポインタの画面サイズのマップだと思いますが、そうですか? AC2 を使用して uimage1D_B の新しい未使用メモリ部分へのポインタを生成しますが、AC1 は uimage1D_A に徐々にアクセスしていることを示唆しているため、完全に間違っている可能性があります:)

于 2014-07-28T23:20:42.057 に答える