Compilação de objetos de estado de pipeline
O D3D12 fornece a interface PSO (Pipeline State Object, objeto de estado de pipeline) para configurar a GPU com shaders e estado de renderização. O fluxo de trabalho multiplataforma padrão para criar PSOs é pré-compilar shaders usando o DXC em um processo no momento do build e, em seguida, preencher um descritor de estado de pipeline gráfico ou de computação (por exemplo, D3D12_GRAPHICS_PIPELINE_STATE_DESC) com bytecode de shader e estado em tempo de execução. A validação do driver garante a congruência de entradas/saídas e do estado para cada estágio sucessivo do pipeline. No PC, a compilação de PSOs em tempo de execução é necessária, pois a GPU do usuário final geralmente é desconhecida no momento do build. Portanto, o processo offline do DXC deve compilar para um formato de bytecode intermediário, a representação intermediária baseada em LLVM, DXIL (DirectX Intermediate Language). Criar o PSO em tempo de execução com uma das APIs disponíveis (abaixo) faz com que o driver da GPU finalize o código do shader, compilando o bytecode DXIL em instruções de GPU que podem então ser executadas na GPU. Em tempo de execução:- ID3D12Device::CreatePipelineState
- ID3D12Device::CreateGraphicsPipelineState
- ID3D12Device::CreateGraphicsPipelineStateX
- ID3D12Device::CreateComputePipelineState
- ID3D12Device::CreateComputePipelineStateX
Objetos de estado de pipeline serializados
A plataforma XBOX consolida a configuração de hardware, tornando desnecessário distribuir uma representação intermediária do código de shader. Isso permite que o processo de compilação de PSOs seja movido para um evento no momento do build, eliminando a sobrecarga gasta na criação de PSOs durante a inicialização do título. Extensões da API do XBOX foram adicionadas para serializar PSOs em um formato de blob binário que pode ser salvo diretamente em disco. Em tempo de execução, esses blobs podem ser carregados do disco e desserializados de volta em um estado de pipeline funcional. Os PSOs ainda podem ser criados em tempo de execução usando a funcionalidade padrão do D3D12, mas a serialização oferece um caminho para otimizar a velocidade de inicialização. Como os PSOs serializados são distribuídos em builds de pacote, um pilar de design é minimizar o consumo de memória. Os blobs gerados por SerializeGraphicsPipelineStateX devem ser desduplicados entre todos os PSOs pré-compilados para reduzir os requisitos de memória. Outros metadados irrelevantes para a execução são descartados na serialização, o que impede a capacidade de serializar novamente PSOs desserializados anteriormente, operação que falha com uma mensagem de validação. As APIs de serialização (abaixo) não estão disponíveis em builds de varejo. Observe que o processo usado para pré-compilar PSOs deve usar um ID3D12Device criado a partir de uma biblioteca direcionada à plataforma. A função D3D12CreateDevice pode ser encontrada na pasta toolkit da instalação do GDK, em d3d12_x.h para XBOX One ou d3d12_xs.h para XBOX Series X|S; vincule-a com a d3d12_x.lib ou d3d12_xs.lib correspondente. Essas bibliotecas esperam que as DLLs do GDK estejam acessíveis a partir do diretório de trabalho ou por meio da variável de sistema PATH. As DLLs ficam na pasta bin da versão correspondente do GDK, por exemplo, C:\Program Files (x86)\Microsoft GDK\200804\GXDK\bin para o QFE 4 de agosto de 2020. No momento do build:- Informações de execução do Command Processor
- Estado da GPU para estados de blend/raster/profundidade-estêncil
- Estado da GPU para configurações de RTV/DSV
- Estado da GPU para processamento de vértices/índices, tessellation e stream out
- Estado da GPU para cada estágio de HW
- Hash CRC32 do PSO serializado
- Número de versão da estrutura serializada
- Dados de validação
- Forma compacta dos argumentos de criação do PSO
- Configurações de Input Layout e Stream Output
- Instruções de GPU pré-compiladas do shader de HW
- Número de versão da estrutura serializada
- Metadados do compilador de shader
- Informações de shader do PIX
- ID3D12Device::SerializeGraphicsPipelineStateX
- ID3D12Device::DeserializeGraphicsPipelineStateX
- ID3D12Device::SerializeComputePipelineStateX
- ID3D12Device::DeserializeComputePipelineStateX
Objetos de estado de pipeline derivados
Outro recurso exposto por meio da API D3D12.X são os objetos de estado de pipeline ‘derivados’. Esse recurso cria variantes leves de PSOs existentes, que diferem apenas pelo estado de hardware (estado de profundidade-estêncil, estado do rasterizador, estado de blend, máscara de amostra e limites de shader). Derivar um PSO exige uma quantidade trivial de sobrecarga em tempo de execução em comparação com a compilação de PSOs. Isso permite que o desenvolvedor crie um único PSO, vinculado a um conjunto comum de shaders, e depois gere um número arbitrário de variantes, pagando o custo total em tempo de execução apenas pela criação do PSO inicial.Objetos de estado de pipeline serializados e derivados
Usados em conjunto, PSOs serializados e derivados trazem benefícios adicionais para reduzir o tamanho do pacote. Os PSOs derivados permitem que os títulos minimizem o número de PSOs serializados a um subconjunto do conjunto total usado pelo título. Ao desduplicar os PSOs com base nas propriedades imutáveis às substituições de PSOs derivados, chega-se a um conjunto ‘base’, a partir do qual todos os outros PSOs do título podem ser derivados. O caso de uso canônico desses dois recursos seria:- Identificar os PSOs com combinações exclusivas de assinatura raiz, input layout, estágios de shader, saídas de stream e destinos de renderização.
- Serializar esse conjunto desduplicado de PSOs base em um processo offline e distribuí-lo como parte do pacote.
- Carregar os PSOs base do arquivo na inicialização e derivar todas as variantes de PSO necessárias para o título.
Restrições dos objetos de estado de pipeline derivados
Uma restrição notável dos PSOs derivados é que eles não podem modificar o código de shader compilado. É por isso que input layouts, formatos de destino de renderização e configurações de stream output não são opções em D3D12XBOX_DERIVED_GRAPHICS_STATE_DESC, pois exigiriam modificar as instruções de GPU do PSO compilado. O driver escolhe os tipos de dados de exportação de shader apropriados durante a compilação do PSO; os tipos de exportação de shader compatíveis são uint, sint, unorm, snorm ou float de 16 ou 32 bits. O driver seleciona o menor tipo cuja precisão seja maior ou igual à precisão do destino de renderização, desde que também se ajuste à configuração do hardware de blending. Para implementar sua escolha, o driver modifica o código de shader compilado com as instruções de exportação apropriadas, que convertem o tipo usado nas operações do shader para o tipo de exportação selecionado pelo driver. Depois dessa modificação, o driver não altera mais essas instruções de GPU finalizadas. A escolha final das instruções de exportação do shader é determinada por alguns fatores principais:- Tipos e quantidade de destinos nos quais o código HLSL grava (SV_TargetN)
- Formatos e quantidade de destinos de renderização do PSO
- Configuração de alpha-to-coverage
- Configurações de estado de blend
