Desenho indireto
O desenho indireto permite que algumas travessias de cena e abate sejam movidos da CPU para a GPU, o que pode melhorar o desempenho. O buffer de comando pode ser gerado pela CPU ou GPU.
- Assinaturas de comando
- Estruturas de buffer de argumento indireto
- Criação de assinatura de comando
- Tópicos relacionados
Assinaturas de comando
O objeto de assinatura de comando (ID3D12CommandSignature) permite que os aplicativos especifiquem o desenho indireto, em particular definindo o seguinte:
- O formato de buffer de argumento indireto.
- O tipo de comando que será usado (dos métodos ID3D12GraphicsCommandList DrawInstanced, DrawIndexedInstance ou Dispatch).
- O conjunto de associações de recursos que mudará por chamada de comando versus o conjunto que será herdado.
Na inicialização, um aplicativo cria um pequeno conjunto de assinaturas de comando. Em tempo de execução, o aplicativo preenche um buffer com comandos (por meio de qualquer meio que o desenvolvedor do aplicativo escolher). Os comandos opcionalmente contêm estado a ser definido para exibições de buffer de vértice, exibições de buffer de índice, constantes de raiz e descritores de raiz (SRV/UAV/CBVs brutos ou estruturados). Esses layouts de argumento não são específicos de hardware para que os aplicativos possam gerar os buffers diretamente. A assinatura do comando herda o estado restante da lista de comandos. Em seguida, o aplicativo chama ExecuteIndirect para instruir a GPU a interpretar o conteúdo do buffer de argumento indireto de acordo com o formato definido por uma assinatura de comando específica.
Se a assinatura de comando alterar quaisquer argumentos de raiz, isso será armazenado na assinatura de comando como um subconjunto de uma assinatura raiz.
Nenhum estado de assinatura de comando vaza de volta para a lista de comandos após a conclusão da execução. Mas, após ExecuteIndirect, todas as ligações são redefinidas para valores conhecidos. Especialmente:
- Se a assinatura do comando vincular um buffer de vértice a um slot específico, depois que ExecuteIndirect for chamado, um buffer de vértice NULL será vinculado a esse slot.
- Se a assinatura do comando vincular um buffer de índice, depois de ExecuteIndirect, um buffer de índice NULL será vinculado.
- Se a assinatura do comando definir uma constante raiz, depois que ExecuteIndirect for chamado, o valor da constante raiz será definido como 0.
- Se a assinatura de comando definir uma exibição raiz (CBV/SRV/UAV), depois que ExecuteIndirect for chamada, a exibição raiz será definida como uma exibição NULL.
Como exemplo de uso de assinaturas de comando: suponha que um desenvolvedor de aplicativo queira que uma constante raiz exclusiva seja especificada por chamada por desenho no buffer de argumento indireto. O aplicativo criaria uma assinatura de comando que permite que o buffer de argumento indireto especifique os seguintes parâmetros por chamada de desenho:
- O valor de uma constante de raiz.
- Os argumentos de desenho (contagem de vértices, contagem de instâncias, etc.).
O buffer de argumento indireto gerado pelo aplicativo conteria uma matriz de registros de tamanho fixo. Cada estrutura corresponde a uma chamada de sorteio. Cada estrutura contém os argumentos de desenho e o valor da constante raiz. O número de chamadas de desenho é especificado em um buffer visível de GPU separado.
Segue-se um exemplo de buffer de comando gerado pelo aplicativo:
Estruturas de buffer de argumento indireto
As estruturas a seguir definem como argumentos específicos aparecem em um buffer de argumento indireto. Essas estruturas não aparecem em nenhuma API D3D12. Os aplicativos usam essas definições ao gravar em um buffer de argumento indireto (com a CPU ou GPU):
- D3D12_DRAW_ARGUMENTS
- D3D12_DRAW_INDEXED_ARGUMENTS
- D3D12_DISPATCH_ARGUMENTS
- D3D12_VERTEX_BUFFER_VIEW
- D3D12_INDEX_BUFFER_VIEW
- D3D12_GPU_VIRTUAL_ADDRESS (um sinônimo typedef'd de UINT64).
- D3D12_CONSTANT_BUFFER_VIEW
Criação de assinatura de comando
Para criar uma assinatura de comando, use os seguintes itens de API:
- ID3D12Device::CreateCommandSignature (gera uma saída ID3D12CommandSignature)
- D3D12_INDIRECT_ARGUMENT_TYPE
- D3D12_INDIRECT_ARGUMENT_DESC
- D3D12_COMMAND_SIGNATURE_DESC
A ordem dos argumentos dentro de um buffer de argumento indireto é definida para corresponder exatamente à ordem dos argumentos especificada no parâmetro pArguments de D3D12_COMMAND_SIGNATURE_DESC. Todos os argumentos para uma chamada de desenho (gráficos)/despacho (computação) dentro de um buffer de argumento indireto são compactados corretamente. No entanto, os aplicativos têm permissão para especificar uma etapa de bytes arbitrária entre comandos draw/dispatch em um buffer de argumento indireto.
A assinatura raiz deve ser especificada se e somente se a assinatura do comando alterar um dos argumentos raiz.
Para raiz SRV/UAV/CBV, o tamanho especificado do aplicativo é em bytes. A camada de depuração validará as seguintes restrições no endereço:
- CBV – o endereço deve ser um múltiplo de 256 bytes.
- SRV/UAV bruto – o endereço deve ser um múltiplo de 4 bytes.
- SRV/UAV estruturado – o endereço deve ser um múltiplo da etapa de byte da estrutura (declarada no sombreador).
Uma determinada assinatura de comando é uma assinatura de desenho ou de comando de computação. Se uma assinatura de comando contiver uma operação de desenho, ela será uma assinatura de comando gráfico. Caso contrário, a assinatura de comando deve conter uma operação de despacho e é uma assinatura de comando de computação.
As seções a seguir mostram alguns exemplos de assinaturas de comando.
Sem alterações de argumento
Neste exemplo, o buffer de argumento indireto gerado pelo aplicativo contém uma matriz de estruturas de 36 bytes. Cada estrutura contém apenas os cinco parâmetros passados para DrawIndexedInstanced (mais preenchimento).
O código para criar a descrição da assinatura de comando segue:
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;
O layout de uma única estrutura dentro de um buffer de argumento indireto é:
Bytes | Descrição |
---|---|
0:3 | IndexCountPerInstance |
4:7 | InstanceCount |
8:11 | StartIndexLocation |
12:15 | BaseVertexLocalização |
16:19 | StartInstanceLocation |
20:35 | Preenchimento |
Constantes de raiz e buffers de vértice
Neste exemplo, cada estrutura em um buffer de argumento indireto altera duas constantes de raiz, altera uma associação de buffer de vértice e executa uma operação de desenho não indexada. Não há acolchoamento entre as estruturas.
O código para criar a descrição da assinatura do comando é:
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;
O layout de uma única estrutura dentro do buffer de argumento indireto é o seguinte:
Bytes | Descrição |
---|---|
0:3 | Dados para o índice de parâmetro raiz 2 |
4:7 | Dados para o índice de parâmetro raiz 6 |
8:15 | Endereço virtual do VB no slot 3 (64 bits) |
16:19 | Tamanho VB |
20:23 | Passo VB |
24:27 | VertexCountPerInstance |
28:31 | InstanceCount |
32:35 | StartVertexLocalização |
36:39 | StartInstanceLocation |
Tópicos relacionados