2017-07-25 38 views
0

dx12バインディングビデオを見て、いくつかのドキュメントを読んだ後、ヒープを正しく管理する方法を正しく理解しているかどうかは100%わかりません。DX12ディスクリプタヒープ管理

私のアプリケーションでは達成できないことを説明しましょう: 初期化中、2つのヒープ、1つはサンプラー、もう1つはSRV、CBV、およびUAVを保持します。 これらのヒープには、アプリケーションの有効期間中に使用されるすべてのリソースが含まれます。

ここで興味深い部分が始まります。ルート・シグネチャを構築するには、大部分のルート・ディスクリプタ・テーブルを使用します。

私たちが知っているように、テーブルは範囲を保持します。範囲は基本シェーダスロット、ディスクリプタ数、その他の設定です。 (たとえば、B0、B1、B2用およびB3)非シーケンシャルですが、コマンドリストの記録時に、私たちができるだけの範囲があることができ、例に示すように

Root Parameters 
0 - root_table 
1 - root_table 

0 root_table 
CBV b1 
CBV b6 
SRV t0 
SRV t2 

1 root_table 
Sampler s1 
Sampler s4 

: 私はあなたとの例をお見せしましょう実行します。我々は適切mCbvSrvUavHeapmSamplerHeapで注文した記述子を持っている必要がありますことを意味し

ID3D12DescriptorHeaps* heaps[2] = {mCbvSrvUavHeap,mSamplerHeap}; 
mCmdList->SetDescriptorHeaps(2,heaps); 

mCmdList->SetGraphicsRootDescriptorTable(0, mCbvSrvUavHeapGpuHanleStart); 
mCmdList->SetGraphicsRootDescriptorTable(1, mSamplerHandleHanleStart); 

。例えば

:問題は私のためにあるのはここ

mCbvSrvUavHeap 
CBV 
CBV 
SRV 
SRV 

です。私が最初に言ったように、私はアプリケーションのすべてのリソースを持つ2つの大きなヒープを作成しますが、使用されない他の記述子を持つので、これらのヒープをコマンドリストに設定することはできません!

どうすれば対応できますか?私は使用する記述子だけを含む新しいヒープを作成する必要がありますか?

私はそれをうまく説明しました!

+0

追加のルートスロットを使用する場合は、連続している必要はありません。 [ここにある](https://github.com/Microsoft/DirectXTK12/blob/master/Src/Shaders/RootSig.fxh)私が[DirectX 12用のDirectX Tool Kit](https://github.com/)で使ったルーツMicrosoft/DirectXTK12)。私は彼らが最適だと言っているわけではないが、彼らは仕事を終わらせる。 –

答えて

1

間違っていると思います。ディスクリプタヒープは、不変なものではなく常に変化するオブジェクトです。ディスクリプタテーブルをバインドすると、実際にはオフセットからバインドされています。記述子ヒープを交換することは、コストをかけずに避けたいと考える高価な操作です。

考えられるのは、非GPU可視ヒープでディスクリプタを準備することです(CPU割り当てオブジェクトだけです)。CopyDescriptorまたはCopyDescriptorSimpleを使用してリングバッファ方式でGPUに可視のものをコピーします。

シェーダが2つのCBVと2つのSRVを持つテーブルを使用する場合は、ヒープ内で連続している必要があるため、ヒープから4の配列を割り当て、ヒープオフセットを取得し、それをSetGraphicsRootDescriptorTableと結びつけてください。

ヒープ内のディスクリプタの寿命は、GPUがそれらを使用してコマンドを処理するまで上書きできないため、注意する必要があります。最後に、多くのシェーダが同じようなルートシグネチャからいくつかの共通テーブルを共有している場合は、更新を因数分解して処理を保存することができます。

+0

これは確かに1つの戦略ですが、記述子ヒープの変更は、他に何が起きているかによっては必ずしも世界の終わりではありません。はい、一部のハードウェアでパイプラインがフラッシュされますが、他のベンダーのベストプラクティスとのトレードオフが必要なので、それほど悪くない場合もあります。 –

+0

例えば、NVIDIAの場合(70%のPC市場)、並列非同期計算とグラフィックスワークロードの実行を目指す場合は、すべてのフレームのリングバッファとしてCBV/SRV/UAV /ディスクリプタヒープを1つだけ使用してください。私が理解しているのは、記述子ヒープの間に障壁があることです。各Draw呼び出しの間にWaitForIdleを挿入し、並列性のすべての可能性を緩和するようなものになります。 – galop1n

+0

私は、フレームの後ろにリングバッファを持つという考えを思いついたので、各フレームをフェンスしなくてもダブル/トリプルバッファリングを行うことができます:)説明してくれてありがとう、本当に役に立ちます。私は次のことを行うと思います:SRV_UAV_CBVで大きなヒープ(非シェイダーの可視)を作成し、サンプラーで別のヒープを作成して、次の描画/ディスパッチの記述子で現在の記述子ヒープを作成します。その新しいヒープを終えたら、ID3D12Descriptorheap :: Release()を呼び出す必要がありますか? – Nacho

関連する問題