間接的な描画
間接的な描画により、一部のシーン トラバーサルとカリングを CPU から GPU に移動できます。これにより、パフォーマンスを向上させることができます。 CPU または GPU によってコマンド バッファーを生成できます。
コマンド署名
コマンド署名オブジェクト (ID3D12CommandSignature) により、アプリで間接的な描画を指定できます。特に次の設定を指定できます。
- 間接引数バッファーの形式。
- (ID3D12GraphicsCommandList のメソッド DrawInstanced、DrawIndexedInstanced、または Dispatch から) 使用するコマンドの種類。
- コマンドごとの呼び出しを変更するリソース バインディングのセットと継承されるセット。
起動時に、アプリはコマンド署名の小規模なセットを作成します。 実行時に、アプリケーションは、(アプリ開発者が選択した何らかの方法を使用して) バッファーにコマンドを格納します。 コマンドには、頂点バッファー ビュー、インデックス バッファー ビュー、ルート定数、およびルート記述子に対して設定する状態がオプションで含まれます (未加工または構造化された SRV/UAV/CBV)。 これらの引数のレイアウトはハードウェア固有ではないため、アプリはバッファーを直接生成できます。 コマンド署名は、コマンド リストから残りの状態を継承します。 その後、アプリは ExecuteIndirect を呼び出して、特定のコマンド署名によって定義されている形式に従い、間接引数バッファーの内容を解釈するように GPU に指示します。
コマンド署名によってルート引数が変更された場合、その変更は、ルート署名のサブセットとしてコマンド署名内に保存されます。
実行の完了後、コマンド署名の状態はコマンド リストに戻されません。 ただし、ExecuteIndirect の後、すべてのバインディングが既知の値にリセットされます。 特に次の点に違いがあります。
- コマンド署名によって頂点バッファーが特定のスロットにバインドされた場合、 ExecuteIndirect が呼び出されると、NULL 頂点バッファーがそのスロットにバインドされます。
- コマンド署名がインデックス バッファーをバインドする場合、ExecuteIndirect の後に NULL インデックス バッファーがバインドされます。
- コマンド署名でルート定数が設定されている場合、ExecuteIndirect が呼び出された後、ルート定数の値は 0 に設定されます。
- コマンド署名によってルート ビュー (CBV/SRV/UAV) が設定された場合、ExecuteIndirect が呼び出されると、ルート ビューは NULL ビューに設定されます。
コマンド署名の使用例: アプリ開発者が、間接引数バッファーでの描画呼び出しごとに、固有のルート定数を指定する必要があるとします。 アプリは、間接引数バッファーで描画呼び出しごとに次のパラメーターを指定できるようにするコマンド署名を作成します。
- 1 つのルート定数の値。
- 描画引数 (頂点の数、インスタンス数など)。
アプリケーションによって生成される間接引数バッファーには、固定サイズのレコードの配列が含まれます。 各構造体は、1 つの描画呼び出しに対応します。 各構造体には、描画引数とルート定数の値が含まれます。 描画呼び出しの数は、GPU が認識できる個別のバッファーで指定されます。
アプリによって生成されるコマンド バッファーの例を次に示します。
間接引数バッファーの構造体
次の構造体により、間接引数バッファーで特定の引数がどのように表されるかが定義されます。 これらの構造体は、D3D12 API では使用されません。 アプリケーションは、(CPU または GPU を使用して) 間接引数バッファーに書き込みを行うときに、これらの定義を使用します。
- D3D12_DRAW_ARGUMENTS
- D3D12_DRAW_INDEXED_ARGUMENTS
- D3D12_DISPATCH_ARGUMENTS
- D3D12_VERTEX_BUFFER_VIEW
- D3D12_INDEX_BUFFER_VIEW
- D3D12_GPU_VIRTUAL_ADDRESS (UINT64 の型が定義された同意語)。
- D3D12_CONSTANT_BUFFER_VIEW
コマンド署名の作成
コマンド署名を作成するには、次の API アイテムを使用します。
- ID3D12Device::CreateCommandSignature (ID3D12CommandSignature を出力)
- D3D12_INDIRECT_ARGUMENT_TYPE
- D3D12_INDIRECT_ARGUMENT_DESC
- D3D12_COMMAND_SIGNATURE_DESC
間接引数バッファー内の引数の順序は、D3D12_COMMAND_SIGNATURE_DESC の pArguments パラメーターで指定される引数の順序に正確に一致するように定義されます。 間接引数バッファー内の 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 |
関連トピック