4

すべての DirectX の書籍とチュートリアルでは、ドローコール間のリソース割り当てを最小限に抑えることを強く推奨していますが、詳細を説明したガイドラインは見つかりません。Web で見つかった多くのサンプル コードを検討した結果、プログラマーはこの主題に関してまったく異なるコーディング原則を持っているという結論に達しました。一部の設定および設定解除

VS/PS 
VS/PS ResourceViews
RasterizerStage 
DepthStencilState
PrimitiveTopology
... 

すべての描画呼び出しの前後(セットアップは変更されていませんが) であり、他のものはそうではありません。

ちょっとやり過ぎかな…。

私自身の実験から、すべての描画呼び出しでバインドする必要があるリソースはShaderResourceViews(私の場合は toVSPS) だけであることがわかりました。この要件は、後で/にバインドUAVsされているバッファーにバインド/バインド解除するため、計算シェーダーの使用が原因である可能性があります。VSPS

この再バインドが必要であることに気付く前に、私は何時間もの作業を失いました。そして、多くのコーダーも確信が持てず、同様の罠に陥るよりも、「少し多すぎる」ものをアンバインドして再バインドすることを好むと思います。

質問 1:この問題に関して少なくともいくつかの経験則はありますか?

質問 2: CS ディスパッチ呼び出しの前に同じバッファーにバインドしているため (自分自身をバインド解除していない)、バインドShaderResourceViewsVS/PSがドライバー/DirectX コアによってバインド解除される可能性はありますか?UAVsSRVs

質問 3:VS/PS計算シェーダーを使用する前に、null に設定すらしていません。問題なく動作しますが、このような「怠惰な」アプローチを使用して次のトラップを掘っているのかどうか、常に確信が持てません。

4

2 に答える 2

8

オーバーヘッドをできるだけ少なくしたいだけでなく、無効なパイプライン状態を回避したい。そのため、一部の人々はすべてをアンバインドします (可能な限り防止しようとします)。それはユースケースに依存します。もちろん、これを少しバランスさせることができます。

これをバランスさせるために、リソースの種類に応じて特定のリソースをスロットに事前に割り当てることができます。スロットの数が異なるため、異なるルールが適用される可能性があります。

1/サンプラーと状態

16 個のスロットがあり、通常は 4 ~ 5 個のサンプラーが 90% の時間 (線形/ポイント/異方性/シャドウ) で使用されます。

そのため、アプリケーションの起動時にこれらの状態を作成し、必要な各シェーダー ステージにバインドします (誤って簡単にオーバーライドされるため、ゼロ スロットから開始しないようにしてください)。マッピング SamplerState -> slot を使用してシェーダー ヘッダー ファイルを作成し、それをシェーダーで使用して、スロットの更新が自動的に反映されるようにします。

これを可能な限り再利用し、カスタム サンプラーのみをバインドします。

標準状態 (Blend/Depth/Rasterizer) の場合、アプリケーションの起動時に一般的な状態の小さなコレクションを構築し、必要に応じてバインドするのが一般的な方法です。

低コストで Render State バインディングを最小限に抑える簡単な方法です。スタックを構築してデフォルトの状態を設定し、シェーダーがより具体的な状態を必要とする場合は、新しい状態をスタックにプッシュし、完了したら最後にポップすることができます。状態にして、パイプラインに再度適用します。

2/定数バッファ

14 個のスロットがありますが、これは非常に多く、(少なくとも私の使用例では) それらすべてを使用することは非常にまれです。特に、バッファー/構造化バッファーも使用できるようになりました。

単純な一般的なケースの 1 つは、カメラ用の予約済みスロットを設定することです (必要なすべてのデータ、ビュー/プロジェクション/ビュープロジェクション、およびそれらの逆も必要になる可能性があるため)。

それを (必要に応じてすべて) シェーダー ステージ スロットにバインドし、フレームごとに cbuffer を更新するだけで、どこでも使用できるようになります。

3/シェーダーステージ

Compute Shader はパイプラインから完全に分離されているため、バインドを解除する必要はほとんどありません。

一方、パイプライン ステージでは、バインドを解除する代わりに、必要なものをすべて設定し、不要なものを null に設定することをお勧めします。

この例に従わずにシャドウ マップ (深度バッファーのみ) をレンダリングすると、ピクセル シェーダーがまだバインドされている可能性があります。

以前に使用したジオメトリ シェーダーを設定解除するのを忘れた場合、レイアウトの組み合わせが無効になり、オブジェクトがレンダリングされない可能性があります (エラーはランタイム デバッグ モードでのみ表示されます)。

そのため、フル シェーダー ステージを設定してもオーバーヘッドはほとんど追加されませんが、安全性のトレードオフは無視できないほど大きくなります。

あなたのユース ケース (VS/PS と CS のみを使用してビルドする) では、それを安全に無視できます。

4/Uavs-RenderTargets-DepthStencil

書き込みリソースの場合、作業単位を使用した後は常に設定解除してください。同じルーチン内で内部を最適化できますが、レンダリング/コンピューティング シェーダー関数の最後で出力を null に戻します。これは、出力中にパイプラインが ShaderResource として再バインドされることを許可しないためです。

関数の最後に書き込みリソースの設定を解除しないと、災害のレシピになります。

5/ShaderResourceView

これは非常に状況に応じたものですが、実行時の警告を回避しながら最小化することをお勧めします (これは無害ですが、重要なメッセージを非表示にします)。

1 つの最終的なことは、フレームの開始時にすべてのシェーダー リソース入力を null にリセットすることです。たとえば、VS でまだバインドされているバッファーが CS で UAV として設定されるのを回避します。これにより、フレームごとに 6 つのパイプライン呼び出しが発生しますが、一般的には価値があります。それ。

十分な予備のレジスターといくつかの一定のリソースがある場合は、もちろんそれらをいくつかの予約済みスロットに設定し、それらを一度だけバインドすることもできます。

6/IA 関連リソース

この場合、ジオメトリを描画するために適切なデータを設定する必要があるため、バインドするたびに InputLayout/Topology を設定するのが合理的です。もちろん、ドローコールを整理してスイッチを最小限に抑えることもできます。

無効なトポロジ (たとえば、テッセレーションを含むパイプラインで Triangle List を使用する) は何も描画せず、実行時に警告が表示されるため、Topology を適切に設定することがかなり重要であることがわかりますが、AMD カードでは単にドライバーをクラッシュさせます。デバッグがかなり難しくなるため、回避することをお勧めします。

通常、頂点/インデックス バッファーのバインドを実際に解除することはありません (それらを上書きするだけで、入力レイアウトがとにかくフェッチする方法を指示するため)。上記のランタイム警告を回避するために、これらのバッファーが計算/ストリーム出力で生成される場合は、この規則の唯一の例外です。

于 2014-06-08T14:10:56.200 に答える
0

回答 1 : 少ないほどよい。

回答 2 : 逆です。リソースを別の種類のビューにバインドする前に、ビューのバインドを解除する必要があります。このようなエラーをキャッチするには、デバッグ層を有効にする必要があります。

回答 3 : 大丈夫です。

于 2013-12-03T10:05:10.570 に答える