ジョンはすでに素晴らしい答えを書いているので、この答えを彼の延長と考えてください。
現在、さまざまなアルゴリズムの計算シェーダーで多くの作業を行っています。一般的に、コンピューティングシェーダーは、同等のピクセルシェーダーよりもはるかに高速であるか、フィードバックベースの代替を変換できることがわかりました。
計算シェーダーがどのように機能するかについて頭を包むと、多くの場合、それらはより意味があります。ピクセルシェーダーを使用して画像をフィルター処理するには、フレームバッファーの設定、頂点の送信、複数のシェーダーステージの使用などが必要です。画像のフィルター処理にこれが必要なのはなぜですか?私の意見では、画像処理のためにフルスクリーンクワッドをレンダリングすることに慣れていることが、それらを引き続き使用する唯一の「有効な」理由です。コンピューティンググラフィックスの分野の新参者は、テクスチャへのレンダリングよりもコンピューティングシェーダーが画像処理にはるかに自然に適合すると確信しています。
あなたの質問は特に画像フィルタリングに関するものなので、他のトピックについてはあまり詳しく説明しません。一部のテストでは、変換フィードバックを設定するか、フレームバッファオブジェクトを切り替えてテクスチャにレンダリングするだけで、パフォーマンスコストが約0.2ms発生する可能性があります。これはレンダリングを除外することに注意してください!あるケースでは、計算シェーダーに移植されたまったく同じアルゴリズムを維持し、顕著なパフォーマンスの向上が見られました。
計算シェーダーを使用する場合、GPUのより多くのシリコンを使用して実際の作業を行うことができます。ピクセルシェーダールートを使用する場合は、これらすべての追加手順が必要です。
- 頂点アセンブリ(頂点属性、頂点除数、型変換の読み取り、vec4への展開など)
- 頂点シェーダーは、最小限であってもスケジュールする必要があります
- ラスタライザは、頂点出力をシェーディングおよび補間するピクセルのリストを計算する必要があります(おそらく、画像処理のテクスチャ座標のみ)
- すべての異なる状態(深度テスト、アルファテスト、はさみ、ブレンド)を設定および管理する必要があります
前述のパフォーマンス上の利点はすべて、スマートドライバーによって無効にされる可能性があると言えます。あなたは正しいでしょう。このようなドライバーは、深度テストなどを行わずにフルスクリーンクワッドをレンダリングしていることを識別し、ピクセルシェーダーをサポートするために行われた無駄な作業をすべてスキップする「高速パス」を構成できます。一部のドライバーが特定のGPU向けのAAAゲームのポストプロセッシングパスを高速化するためにこれを実行しても驚かないでしょう。もちろん、AAAゲームに取り組んでいない場合は、そのような処理を忘れることができます。
ただし、ドライバーができないことは、計算シェーダーパイプラインによって提供されるより良い並列処理の機会を見つけることです。ガウスフィルターの典型的な例を見てみましょう。計算シェーダーを使用すると、次のようなことができます(フィルターを分離するかどうか)。
- ワークグループごとに、ソースイメージのサンプリングをワークグループサイズ全体に分割し、結果をグループ共有メモリに保存します。
- 共有メモリに保存されたサンプル結果を使用して、フィルター出力を計算します。
- 出力テクスチャに書き込む
ここで重要なのはステップ1です。ピクセルシェーダーバージョンでは、ソースイメージはピクセルごとに複数回サンプリングされます。計算シェーダーバージョンでは、各ソーステクセルはワークグループ内で1回だけ読み取られます。テクスチャ読み取りは通常、タイルベースのキャッシュを使用しますが、このキャッシュは共有メモリよりもはるかに低速です。
ガウスフィルターは、より単純な例の1つです。他のフィルタリングアルゴリズムは、共有メモリを使用してワークグループ内で中間結果を共有する他の機会を提供します。
ただし、キャッチがあります。計算シェーダーでは、出力を同期するために明示的なメモリバリアが必要です。また、誤ったメモリアクセスから保護するための保護手段も少なくなります。並列プログラミングの知識が豊富なプログラマーの場合、計算シェーダーははるかに高い柔軟性を提供します。ただし、この柔軟性は、通常のC ++コードのように計算シェーダーを扱い、遅いコードまたは誤ったコードを記述する方が簡単であることを意味します。
参照資料