次の方法で共有


間接的な描画

間接的な描画により、一部のシーン トラバーサルとカリングを CPU から GPU に移動できます。これにより、パフォーマンスを向上させることができます。 CPU または GPU によってコマンド バッファーを生成できます。

コマンド署名

コマンド署名オブジェクト (ID3D12CommandSignature) により、アプリで間接的な描画を指定できます。特に次の設定を指定できます。

起動時に、アプリはコマンド署名の小規模なセットを作成します。 実行時に、アプリケーションは、(アプリ開発者が選択した何らかの方法を使用して) バッファーにコマンドを格納します。 コマンドには、頂点バッファー ビュー、インデックス バッファー ビュー、ルート定数、およびルート記述子に対して設定する状態がオプションで含まれます (未加工または構造化された SRV/UAV/CBV)。 これらの引数のレイアウトはハードウェア固有ではないため、アプリはバッファーを直接生成できます。 コマンド署名は、コマンド リストから残りの状態を継承します。 その後、アプリは ExecuteIndirect を呼び出して、特定のコマンド署名によって定義されている形式に従い、間接引数バッファーの内容を解釈するように GPU に指示します。

コマンド署名によってルート引数が変更された場合、その変更は、ルート署名のサブセットとしてコマンド署名内に保存されます。

実行の完了後、コマンド署名の状態はコマンド リストに戻されません。 ただし、ExecuteIndirect の後、すべてのバインディングが既知の値にリセットされます。 特に次の点に違いがあります。

  • コマンド署名によって頂点バッファーが特定のスロットにバインドされた場合、 ExecuteIndirect が呼び出されると、NULL 頂点バッファーがそのスロットにバインドされます。
  • コマンド署名がインデックス バッファーをバインドする場合、ExecuteIndirect の後に NULL インデックス バッファーがバインドされます。
  • コマンド署名でルート定数が設定されている場合、ExecuteIndirect が呼び出された後、ルート定数の値は 0 に設定されます。
  • コマンド署名によってルート ビュー (CBV/SRV/UAV) が設定された場合、ExecuteIndirect が呼び出されると、ルート ビューは NULL ビューに設定されます。

コマンド署名の使用例: アプリ開発者が、間接引数バッファーでの描画呼び出しごとに、固有のルート定数を指定する必要があるとします。 アプリは、間接引数バッファーで描画呼び出しごとに次のパラメーターを指定できるようにするコマンド署名を作成します。

  • 1 つのルート定数の値。
  • 描画引数 (頂点の数、インスタンス数など)。

アプリケーションによって生成される間接引数バッファーには、固定サイズのレコードの配列が含まれます。 各構造体は、1 つの描画呼び出しに対応します。 各構造体には、描画引数とルート定数の値が含まれます。 描画呼び出しの数は、GPU が認識できる個別のバッファーで指定されます。

アプリによって生成されるコマンド バッファーの例を次に示します。

コマンド バッファーの形式

間接引数バッファーの構造体

次の構造体により、間接引数バッファーで特定の引数がどのように表されるかが定義されます。 これらの構造体は、D3D12 API では使用されません。 アプリケーションは、(CPU または GPU を使用して) 間接引数バッファーに書き込みを行うときに、これらの定義を使用します。

コマンド署名の作成

コマンド署名を作成するには、次の API アイテムを使用します。

間接引数バッファー内の引数の順序は、D3D12_COMMAND_SIGNATURE_DESCpArguments パラメーターで指定される引数の順序に正確に一致するように定義されます。 間接引数バッファー内の 1 つの描画 (グラフィックス)/ディスパッチ (計算) 呼び出しのすべての引数は、区切らずに連結して指定します。 ただし、アプリケーションは、間接引数バッファー内の描画/ディスパッチ コマンドの間で任意のバイト ストライドを指定できます。

コマンド署名によってルート引数の 1 つが変更される場合に限り、ルート署名を指定する必要があります。

ルート SRV/UAV/CBV の場合、アプリケーション指定のサイズはバイト単位です。 デバッグ レイヤーによって、アドレスに関する次の制限が検証されます。

  • CBV - アドレスは 256 バイトの倍数である必要があります。
  • 未加工 SRV/UAV - アドレスは 4 バイトの倍数である必要があります。
  • 構造化 SRV/UAV - アドレスは、(シェーダーで宣言された) 構造体のバイト ストライドの倍数である必要があります。

指定されるコマンド署名は、描画コマンド署名または計算コマンド署名のいずれかです。 コマンド署名に描画操作が含まれる場合、その署名はグラフィックス コマンド署名です。 それ以外の場合、コマンド署名には、ディスパッチ操作が必ず含まれます。これは、計算コマンド署名です。

次のセクションで、コマンド署名の例をいくつか示します。

引数の変更なし

この例では、アプリケーションによって生成された間接引数バッファーに、36 バイトの構造体の配列が格納されます。 各構造体には、DrawIndexedInstanced に渡される 5 つのパラメーター (とパディング) のみ含まれます。

コマンド署名の記述を作成するためのコードを以下に示します。

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

間接引数バッファー内の 1 つの構造体のレイアウトは次のとおりです。

バイト 説明
0:3 IndexCountPerInstance
4:7 InstanceCount
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 パディング

 

ルート定数と頂点バッファー

この例では、間接引数バッファー内の各構造体により、2 つのルート定数が変更され、1 つの頂点バッファー バインディングが変更され、1 つのインデックスなしの描画操作が実行されます。 構造体の間にパディングはありません。

コマンド署名の記述を作成するためのコードを以下に示します。

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

間接引数バッファー内の 1 つの構造体のレイアウトは次のとおりです。

バイト 説明
0:3 ルート パラメーター インデックス 2 のデータ
4:7 ルート パラメーター インデックス 6 のデータ
8:15 スロット 3 での VB の仮想アドレス (64 ビット)
16:19 VB のサイズ
20:23 VB のストライド
24:27 VertexCountPerInstance
28:31 InstanceCount
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

DirectX の高度な学習ビデオ チュートリアル: 間接的な非同期 GPU カリングの実行

間接的な描画と GPU カリング: コードの解説

レンダリング