間接繪圖
間接繪製可讓某些場景周游和撲殺從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 檢視。
作為使用命令簽章的範例:假設應用程式開發人員想要在間接自變數緩衝區中指定唯一的根常數。 應用程式會建立命令簽章,讓間接自變數緩衝區為每個繪製呼叫指定下列參數:
- 一個根常數的值。
- 繪製自變數(頂點計數、實例計數等)。
應用程式所產生的間接自變數緩衝區會包含固定大小記錄的陣列。 每個結構都會對應至一個繪製呼叫。 每個結構都包含繪圖自變數,以及根常數的值。 繪製呼叫數目是在個別的 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 的 typedef'd 同義字)。
- 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 參數中指定的自變數順序。 間接自變數緩衝區內一個繪製(圖形)/分派(計算)呼叫的所有自變數都會緊密包裝。 不過,應用程式可以指定間接自變數緩衝區中繪製/分派命令之間的任意位元組步幅。
只有在命令簽章變更其中一個根自變數時,才必須指定根簽章。
對於根 SRV/UAV/CBV,應用程式指定的大小是以位元組為單位。 偵錯層會驗證位址的下列限制:
- CBV – 地址必須是 256 個字節的倍數。
- 原始 SRV/UAV – 位址必須是 4 個字節的倍數。
- 結構化 SRV/UAV – 位址必須是結構位元組步幅的倍數(在著色器中宣告)。
指定的命令簽章是繪製或計算命令簽章。 如果命令簽章包含繪圖作業,則它是圖形命令簽章。 否則,命令簽章必須包含分派作業,而且它是計算命令簽章。
下列各節顯示一些範例命令簽章。
無自變數變更
在此範例中,應用程式所產生的間接自變數緩衝區會保存 36 位元組結構的數位。 每個結構只包含傳遞至 DrawIndexedInstanced 的五個參數(加上填補)。
建立命令簽章描述的程式代碼如下:
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;
間接自變數緩衝區內單一結構的版面配置為:
Bytes | 描述 |
---|---|
0:3 | IndexCountPerInstance |
4:7 | InstanceCount |
8:11 | StartIndexLocation |
12:15 | BaseVertexLocation |
16:19 | StartInstanceLocation |
20:35 | 填補 |
根常數和頂點緩衝區
在此範例中,間接自變數緩衝區中的每個結構都會變更兩個根常數、變更一個頂點緩衝區系結,並執行一個繪製非索引作業。 結構之間沒有邊框間距。
建立命令簽章描述的程式代碼如下:
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;
間接自變數緩衝區內單一結構的版面配置如下:
Bytes | 描述 |
---|---|
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 |
相關主題