Como gerenciar o estado do pipeline de gráficos no Direct3D 12

Este tópico descreve como o estado do pipeline de gráficos é definido no Direct3D 12.

Visão geral do estado do pipeline

Quando a geometria é enviada para a GPU (unidade de processamento gráfico) a ser desenhada, há uma ampla variedade de configurações de hardware que determinam como os dados de entrada são interpretados e renderizados. Coletivamente, essas configurações são chamadas de estado do pipeline de gráficos e incluem configurações comuns, como o estado do rasterizador, o estado de combinação e o estado do estêncil de profundidade, bem como o tipo de topologia primitiva da geometria enviada e os sombreadores que serão usados para renderização. No Microsoft Direct3D 12, a maioria dos estados do pipeline gráfico é definida usando PSO (objetos de estado de pipeline). Um aplicativo pode criar um número ilimitado desses objetos, representados pela interface ID3D12PipelineState , normalmente no momento da inicialização. Em seguida, no momento da renderização, as listas de comandos podem alternar rapidamente várias configurações do estado do pipeline chamando ID3D12GraphicsCommandList::SetPipelineState em uma lista de comandos direta ou pacote para definir o PSO ativo.

No Direct3D 11, o estado do pipeline de gráficos foi agrupado em objetos de estado grandes e refinados, como ID3D11BlendState , que poderiam ser criados e definidos no momento da renderização no contexto imediato com métodos como ID3D11DeviceContext::OMSetBlendState. A ideia por trás disso era que a GPU pudesse ganhar eficiência definindo as configurações relacionadas, como as configurações de estado de combinação, tudo de uma vez. No entanto, com o hardware gráfico de hoje, há dependências entre as diferentes unidades de hardware. Por exemplo, o estado de combinação de hardware pode ter dependências no estado de raster, bem como no estado de combinação. PSOs no Direct3D 12 foram projetados para permitir que a GPU pré-processe todas as configurações dependentes em cada estado de pipeline, normalmente durante a inicialização, para tornar a alternância entre estados no momento da renderização o mais eficiente possível.

Observe que, embora a maioria das configurações de estado do pipeline esteja definida usando PSOs, há algumas configurações de estado definidas separadamente usando APIs fornecidas por ID3D12GraphicsCommandList. Essas configurações e as APIs associadas são discutidas detalhadamente abaixo. Além disso, há diferenças na maneira como o estado do pipeline de gráficos é herdado e persistido de listas de comandos e pacotes diretos. Este tópico fornece detalhes sobre ambos abaixo.

Estados de pipeline de gráficos definidos com objetos de estado de pipeline

A maneira mais fácil de ver todos os diferentes estados de pipeline que podem ser definidos usando um objeto de estado de pipeline é examinar o tópico de referência do D3D12_GRAPHICS_PIPELINE_STATE_DESC que você passa para ID3D12Device::CreateGraphicsPipelineState ao inicializar o objeto. Um resumo rápido dos estados que podem ser definidos inclui:

  • O código de byte para todos os sombreadores, incluindo sombreadores de vértice, pixel, domínio, casco e geometria.
  • O formato de vértice de entrada.
  • O tipo de topologia primitiva. Observe que o tipo de topologia primitiva do assembler de entrada (ponto, linha, triângulo, patch) é definido dentro do PSO usando a enumeração D3D12_PRIMITIVE_TOPOLOGY_TYPE . A adjacência primitiva e ordenação (lista de linhas, faixa de linhas, faixa de linha com dados de adjacência etc.) é definida de dentro de uma lista de comandos usando o método ID3D12GraphicsCommandList::IASetPrimitiveTopology .
  • O estado de mistura, o estado do rasterizador, o estado do estêncil de profundidade.
  • O estêncil de profundidade e os formatos de destino de renderização, bem como a contagem de destino de renderização.
  • Parâmetros de amostragem múltipla.
  • Um buffer de saída de streaming.
  • A assinatura raiz. Para obter mais informações, consulte Assinaturas raiz.

Estados do pipeline de gráficos definidos fora do objeto de estado do pipeline

A maioria dos estados de pipeline gráficos são definidos usando PSOs. No entanto, há um conjunto de parâmetros de estado de pipeline que são definidos chamando métodos da interface ID3D12GraphicsCommandList de dentro de uma lista de comandos. A tabela a seguir mostra os estados definidos dessa maneira e os métodos correspondentes.

Estado Método
Associações de recursos IASetIndexBuffer
IASetVertexBuffers
SOSetTargets
OMSetRenderTargets
SetDescriptorHeaps
Todos os métodos SetGraphicsRoot...
Todos os métodos SetComputeRoot...
Viewports RSSetViewports
Rects de tesoura RSSetScissorRects
Fator blend OMSetBlendFactor
O valor de referência do estêncil de profundidade OMSetStencilRef
A ordem de topologia primitiva de input-assembler e o tipo de adjacência IASetPrimitiveTopology

Herança do estado do pipeline de gráficos

Como as listas de comandos diretos geralmente se destinam a um uso por vez e os pacotes devem ser usados várias vezes simultaneamente, há regras diferentes sobre como herdam o estado do pipeline de gráficos que foi definido por listas de comandos ou pacotes anteriores.

Para os estados de pipeline de gráficos definidos usando PSOs, nenhum desses estados é herdado por listas de comandos ou pacotes diretos. O estado inicial do pipeline de gráficos para listas de comandos diretos e pacotes é definido no momento da criação com o parâmetro ID3D12PipelineState como ID3D12Device::CreateCommandList. Se nenhum PSO for especificado na chamada, um estado inicial padrão será usado. Você pode alterar o PSO atual em uma lista de comandos chamando ID3D12GraphicsCommandList::SetPipelineState.

As listas de comandos diretos também não herdam o estado definido com métodos de lista de comandos, como RSSetViewports. Para obter detalhes sobre os valores iniciais padrão para estados não PSO, consulte ID3D12GraphicsCommandList::ClearState.

Os pacotes herdam todo o estado do pipeline gráfico que não está definido com PSOs, exceto para o tipo de topologia primitiva. A topologia primitiva é sempre definida como D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED quando um pacote começa a ser executado. Qualquer estado definido em um pacote (o próprio PSO, estado não baseado em PSO e associações de recursos) afeta o estado de sua lista de comandos diretos pai. Por exemplo, se um RSSetViewports for chamado de dentro de um pacote, os visores especificados continuarão a ser definidos na lista de comandos diretos pai para chamadas subsequentes à chamada ExecuteBundle que definem os visores.

As associações de recursos definidas em uma lista de comandos ou pacote persistem. Portanto, as associações de recursos modificadas em uma lista de comandos diretos ainda serão definidas dentro da execução subsequente do pacote filho. E as associações de recursos modificadas de dentro de um pacote ainda serão definidas para chamadas subsequentes na lista de comandos diretos pai.

Para obter mais informações sobre associações, consulte a seção Semântica de Pacote de Usando uma Assinatura Raiz.