> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Objetos de estado de pipeline serializados e derivados em detalhes

> Guia detalhado sobre objetos de estado de pipeline (PSOs) serializados e derivados do Direct3D 12, incluindo compilação em tempo de execução e bytecode DXIL no XBOX.

## 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:*

```text theme={null}
ID3D12RootSignature* rootSig = nullptr;
D3D12CreateRootSignature(0, shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&rootSig));

ComPtr<ID3DBlob> vsBlob = LoadCsoFromFile(vsFilename);
ComPtr<ID3DBlob> psBlob = LoadCsoFromFile(psFilename);

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.pRootSignature = rootSig;
psoDesc.VS             = { vsBlob->GetBufferPointer(), vsBlob->GetBufferSize() };
psoDesc.PS             = { psBlob->GetBufferPointer(), psBlob->GetBufferSize() };
psoDesc.BlendState     = { ... };
...

ID3D12PipelineState* pso = nullptr;
d3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(&pso));

// Render a rabbit, or teapot, or hopefully something cooler
```

APIs pertinentes:

* [**ID3D12Device::CreatePipelineState**](https://learn.microsoft.com/windows/win32/api/d3d12/nf-d3d12-id3d12device2-createpipelinestate)
* [**ID3D12Device::CreateGraphicsPipelineState**](https://learn.microsoft.com/windows/win32/api/d3d12/nf-d3d12-id3d12device-creategraphicspipelinestate)
* [**ID3D12Device::CreateGraphicsPipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_creategraphicspipelinestatex)
* [**ID3D12Device::CreateComputePipelineState**](https://learn.microsoft.com/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcomputepipelinestate)
* [**ID3D12Device::CreateComputePipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/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:*

```text theme={null}
ComPtr<ID3D12Device> d3dDevice;
D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_GRAPHICS_PPV_ARGS(d3dDevice.ReleaseAndGetAddressOf()));
...

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = { ... };

ID3D12PipelineState* pso = nullptr;
d3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(&pso));

D3D12XBOX_SERIALIZE_GRAPHICS_PIPELINE_STATE serializedState;
d3dDevice->SerializeGraphicsPipelineStateX(pso, D3D12XBOX_SERIALIZE_FLAGS_NONE, &serializedState);

WriteSerializedStateToFile(filename, serializedState);
```

*Em tempo de execução:*

```text theme={null}
ID3D12RootSignature* rootSig = nullptr;
D3D12CreateRootSignature(0, shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&rootSig));

D3D12XBOX_SERIALIZE_GRAPHICS_PIPELINE_STATE state = ReadSerializedStateFromFile(filename);

// Assume this data is serialized very simply.
D3D12XBOX_DESERIALIZE_GRAPHICS_PIPELINE_STATE deserialized {};
deserialized.pRootSignature = rootSig;

deserialized.PacketSize     = state.pPacket->GetBufferSize();
deserialized.pPacket        = state.pPacket->GetBufferPointer();
deserialized.MetadataSize   = state.pMetadata->GetBufferSize();
deserialized.pMetadata      = state.pMetadata->GetBufferPointer();

if (state.VS != nullptr)
{
    deserialized.VS.GpuInstructionsSize = state.VS.pGpuInstructions->GetBufferSize();
    deserialized.VS.pGpuInstructions    = state.VS.pGpuInstructions->GetBufferPointer();
    deserialized.VS.MetadataSize        = state.VS.pMetadata->GetBufferSize();
    deserialized.VS.pMetadata           = state.VS.pMetadata->GetBufferPointer();
}
...

ID3D12PipelineState* pso = nullptr;
d3dDevice->DeserializeGraphicsPipelineStateX(&deserializeState, IID_GRAPHICS_PPV_ARGS(&pso));

// Render as normal
```

Veja uma breve descrição do conteúdo de cada parte dos dados serializados:

**D3D12XBOX\_SERIALIZE\_GRAPHICS\_PIPELINE\_STATE::pPacket**

* 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

**D3D12XBOX\_SERIALIZE\_GRAPHICS\_PIPELINE\_STATE::pMetadata**

* 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

**D3D12XBOX\_SERIALIZE\_SHADER::pGpuInstructions**

* Instruções de GPU pré-compiladas do shader de HW

**D3D12XBOX\_SERIALIZE\_SHADER::pMetaData**

* Número de versão da estrutura serializada
* Metadados do compilador de shader
* Informações de shader do PIX

APIs pertinentes:

* [**ID3D12Device::SerializeGraphicsPipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_serializegraphicspipelinestatex)
* [**ID3D12Device::DeserializeGraphicsPipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_deserializegraphicspipelinestatex)
* [**ID3D12Device::SerializeComputePipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_serializecomputepipelinestatex)
* [**ID3D12Device::DeserializeComputePipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/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.

```text theme={null}
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc {};
...

ID3D12PipelineState* pso = nullptr;
d3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(&pso));

D3D12XBOX_DERIVED_GRAPHICS_STATE_DESC derivedDescs[2] {};
derivedDescs[0].Type                           = D3D12XBOX_DERIVED_GRAPHICS_STATE_TYPE_DEPTH_STENCIL;
derivedDescs[0].DepthStencilDesc               = psoDesc.DepthStencilState;
derivedDescs[0].DepthStencilDesc.StencilEnable = false;

derivedDescs[1].Type                           = D3D12XBOX_DERIVED_GRAPHICS_STATE_TYPE_RASTERIZER;
derivedDescs[1].RasterizerDesc                 = psoDesc.RasterizerState;
derivedDescs[1].RasterizerDesc.DepthBias       = -1;

ID3D12PipelineState* derivedPso = nullptr;
d3dDevice->CreateDerivedGraphicsPipelineStateX(pso, 2, &derivedDescs, IID_GRAPHICS_PPV_ARGS(&derivedPso));

// Render as normal
```

APIs pertinentes:

* [**ID3D12Device::CreateDerivedGraphicsPipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_createderivedgraphicspipelinestatex)
* [**ID3D12Device::CreateDerivedComputePipelineStateX**](/pt-BR/reference/graphics/d3d12_x/interfaces/id3d12device/methods/id3d12device_createderivedcomputepipelinestatex)

## 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

Na renderização opaca (blending desabilitado), os tipos de saída podem ser qualquer um dos tipos de exportação de shader compatíveis: uint, sint, unorm, snorm ou float de 16 ou 32 bits. O valor é exportado do shader, convertido para o tipo do destino de renderização pelo Color Block (CB) e, por fim, gravado na memória. Com o blending habilitado, o driver é obrigado a limitar os tipos de exportação de shader a float de 16 ou 32 bits, pois esses são os únicos tipos compatíveis que o CB aceita como entradas para a operação de blending. O valor resultante do blending é então convertido para o tipo do destino de renderização e gravado na memória.

Esses detalhes levam a restrições sutis sobre as substituições de estado de blend aplicáveis a PSOs derivados. O estado de blend substituído pode fazer com que os requisitos de exportação do PSO derivado sejam inconsistentes com a escolha de instrução de exportação determinada durante a compilação do PSO base, que foi incorporada às instruções de GPU. Se qualquer exportação calculada for incompatível entre os PSOs base e derivado, um erro de validação será gerado.

Alguns exemplos que geram tipos de exportação incompatíveis e falhariam na validação:

*Exemplo 1* -

```text theme={null}
    - Base PSO writes float4 to a DXGI_FORMAT_R32G32_FLOAT format with no blending
    - Driver selects RG export of 32-bit float
    - Derived PSO enables blending, using source alpha in blend equation (destination factor == 1)
    - Result: Shader doesn't export alpha - CB expects alpha export
```

*Exemplo 2* -

```text theme={null}
    - Base PSO writes float4 to DXGI_FORMAT_R16G16B16A16_UNORM with no blending
    - Driver selects RGBA export of 16-bit UNORM
    - Derived PSO enables blending
    - Result: Shader exports UNORM format - CB expects 16 or 32-bit floats
```

*Exemplo 3* -

```text theme={null}
    - Base PSO writes float2 to DXGI_FORMAT_R32G32_FLOAT format with RenderTargetWriteMask == D3D12_COLOR_WRITE_ENABLE_RED
    - Driver selects R export of 32-bit float
    - Derived PSO changes RenderTargetWriteMask == D3D12_COLOR_WRITE_ENABLE_ALL
    - Result: Shader exports only red - artifacts in green
```

## Os PSOs serializados são adequados para você?

Embora os PSOs serializados tenham sido criados para reduzir o tamanho do pacote e os custos em tempo de execução do conteúdo de shaders do jogo, certamente há um custo de desenvolvimento não trivial para criar e manter essa etapa de build. Os desenvolvedores frequentemente descobrem que distribuir shaders pré-compilados com DXIL removido oferece desempenho adequado para seus propósitos, algo que muitas vezes já é compatível com os pipelines de conteúdo existentes. O back-end do driver do XBOX foi otimizado com vários mecanismos de cache para reduzir os requisitos de memória em tempo de execução e o tempo de compilação de PSOs, facilitando esse caminho.

Dependendo do conteúdo de shaders de um título, os desenvolvedores podem considerar um método preferível em termos de tamanho do pacote, memória em tempo de execução ou tempo de compilação de PSOs. Evitar a manutenção de um pipeline de conteúdo para serialização de PSOs é outro ponto a ser considerado. Testar ambas as opções com o conteúdo do seu título fornecerá uma visão mais clara da melhor escolha para ele.


## Related topics

- [Objetos do PlayFab Party e suas relações](/pt-BR/services/playfab/multiplayer/networking/concepts-objects.md)
- [Gráficos no XBOX e no PC com o GDK](/pt-BR/build/core-features/graphics/index.md)
- [CreatePipelineLibrary](/pt-BR/reference/graphics/d3d12/interfaces/id3d12device1/methods/id3d12device1_createpipelinelibrary_public.md)
- [GetPipelineStackSize (consoles XBOX Series)](/pt-BR/reference/graphics/d3d12/interfaces/id3d12stateobjectproperties/methods/id3d12stateobjectproperties_getpipelinestacksize_public.md)
- [Diretório de tópicos NDA: links ativos do Microsoft Learn](/pt-BR/nda/nda-topic-directory.md)
