Partilhar via


Desenho Indireto

A renderização indireta permite que alguns percursos de cena e a eliminação sejam transferidos da CPU para a GPU, o que pode melhorar o desempenho. O buffer de comandos pode ser gerado pela CPU ou GPU.

Assinaturas de comando

O objeto de assinatura de comando (ID3D12CommandSignature) permite que os aplicativos especifiquem o desenho indireto, em particular definindo o seguinte:

Na inicialização, uma aplicação cria um pequeno conjunto de assinaturas de comando. No tempo de execução, o aplicativo preenche um buffer com comandos (por meio de qualquer meio que o desenvolvedor do aplicativo escolher). Os comandos contêm opcionalmente o 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 raiz, isso será armazenado na assinatura de comando como um subconjunto de uma assinatura raiz.

Não ocorre nenhuma fuga de estado de assinatura de comando para a lista de comandos após a execução ter sido concluída. Mas, depois de ExecuteIndirect, todas as ligações são redefinidas para valores conhecidos. Em especial:

  • Se a assinatura de 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 de comando vincular um buffer de índice, então, depois de ExecuteIndirect, um buffer de índice NULL será vinculado.
  • Se a assinatura de 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), então, após a execução de ExecuteIndirect, a exibição raiz será definida como uma vista NULL.

Como exemplo de uso de assinaturas de comando: suponha que um programador de aplicações queira que uma constante base exclusiva seja especificada por chamada de renderização no buffer de argumento indireto. A aplicação criaria uma assinatura de comando que permite que o buffer de argumento indireto especifique os seguintes parâmetros para cada chamada de desenho gráfico:

  • O valor de uma constante radical.
  • 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 num buffer separado visível pela GPU.

Segue-se um exemplo de buffer de comandos gerado pela aplicação:

formato de buffer de comando

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):

Criação de assinatura de comando

Para criar uma assinatura de comando, use os seguintes itens de API:

A ordenação dos argumentos dentro de um buffer de argumentos indiretos é 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 estão bem compactados. No entanto, as aplicações têm permissão para especificar um espaçamento arbitrário de bytes entre comandos de desenho/despacho num buffer de argumento indireto.

A assinatura raiz deve ser especificada se e somente se a assinatura de comando alterar um dos argumentos raiz.

Para a raiz SRV/UAV/CBV, o tamanho especificado da aplicação é 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 do espaçamento em bytes da estrutura (declarado no sombreador).

Uma assinatura de comando determinada é ou de renderização ou de computação. Se uma assinatura de comando contiver uma operação de desenho, então é 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 (incluindo espaço reservado).

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 ContagemDeÍndicePorInstância
4:7 ContagemDeInstâncias
8:11 StartIndexLocation
12:15 BaseVertexLocalização
16:19 StartInstanceLocation
20:35 Margem

 

Constantes de raiz e buffers de vértice

Neste exemplo, cada estrutura em um buffer de argumento indireto altera duas constantes raiz, altera uma ligação de buffer de vértice e executa uma operação de desenho não indexada. Não há preenchimento entre estruturas.

O código para criar a descrição da assinatura de 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âmetros raiz 2
4:7 Dados para o índice de parâmetros raiz 6
8:15 Endereço virtual do VB no slot 3 (64 bits)
16:19 Tamanho VB
20:23 VB Stride
24:27 VertexCountPerInstance
28:31 ContagemDeInstâncias
32:35 StartVertexLocalização
36:39 LocalizaçãoDeInícioDaInstância

 

pt-PT: Tutoriais em vídeo para aprendizagem avançada do DirectX: Execução Indireta e eliminação assíncrona de GPU

Desenho indireto e remoção de GPU: código passo a passo

Renderização