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

# Barreiras Aprimoradas do D3D12

> Barreiras Aprimoradas do D3D12

Este documento tem como objetivo explicar a implementação das Barreiras Aprimoradas (Enhanced Barriers) para o XBOX Series X|S e fornecer exemplos detalhados de como aproveitá-las da melhor forma. Este recurso não é compatível com o Durango.

## Lista de conteúdo

1. [Introdução](#introduction)
2. [Sincronização da GPU no XBOX Series X|S](#gpu-synchronization-on-scarlett)
3. [Barreiras em detalhes](#barriers-in-depth)
4. [Configuração](#setting-things-up)
5. [Diferenças em relação à especificação do PC](#differences-with-the-pc-spec)
6. [Exemplos de Barreiras Aprimoradas](#enhanced-barrier-examples)
7. [Compatibilidade com as Barreiras de Recursos herdadas](#compatibility-with-legacy-resource-barriers)
8. [Suporte e validação do PIX](#pix-support-and-validation)

<a id="introduction" />

## Introdução

***

As *Barreiras Aprimoradas* (Enhanced Barriers, EB) são um novo conjunto de APIs do D3D12 projetado para resolver alguns dos problemas introduzidos pela API herdada de Barreiras de Recursos (Resource Barriers), como conceitos confusos de promoção e decaimento de estado de recursos, problemas de design com as Barreiras de Aliasing, operações de flush excessivas etc., além de oferecer aos desenvolvedores controle independente sobre a sincronização do trabalho da GPU. Elas oferecem um tipo de barreira mais expressivo do que era possível com as Barreiras de Recursos herdadas.

Os recursos das Barreiras Aprimoradas incluem:

* Redução da latência de sincronização e de flushes de cache excessivos.
* Nenhuma regra misteriosa de promoção e decaimento.
* Aliasing de recursos rápido e flexível.
* Descarte durante a transição da barreira.
* Leitura/gravação simultânea e autocópia.

Um link para a especificação do DirectX das Barreiras Aprimoradas pode ser encontrado [aqui](https://microsoft.github.io/DirectX-Specs/d3d/D3D12EnhancedBarriers.html).

<a id="gpu-synchronization-on-scarlett" />

## Sincronização da GPU no XBOX Series X|S

***

Antes de prosseguir com as Barreiras Aprimoradas, é necessária uma introdução à sincronização no XBOX Series X|S. É importante entender os conceitos e mecanismos explicados nessa seção, pois eles são os blocos de construção das Barreiras.

[Sincronização da GPU no XBOX Series X/S](/pt-BR/build/core-features/graphics/overviews/gpu-synchronization-scarlett)

Agora podemos nos aprofundar nas Barreiras Aprimoradas e explicar como elas funcionam em mais detalhes.

<a id="barriers-in-depth" />

## Barreiras em detalhes

***

As Barreiras Aprimoradas introduzem três conceitos úteis para decidir como fazer a transição de qualquer recurso (ou memória). São eles: **Sync**, **Access** e **Layout**. De certa forma, eles substituem o conceito anterior de **Resource State** usado nas Barreiras de Recursos. No entanto, eles não são equivalentes, pois sempre é possível expressar um estado de recurso como uma combinação de Sync, Access e Layout, mas nem sempre é possível expressar uma combinação de Sync, Access e Layout como um estado de recurso. A nova API é mais expressiva.

**Sync (Before-After)** é usado para informar ao driver qual estágio do pipeline precisamos aguardar até a conclusão e qual mecanismo deve ser impedido de executar até terminarmos as operações da barreira.

* A tabela a seguir mostra como alguns sinalizadores de sync se traduzem em requisitos para que estágios sejam drenados ou bloqueados (consulte a seção de pipelining). Vale observar que alguns sinalizadores de sync de Barreira se referem a um estágio amplo (como cópia), mas, internamente e com base nos dados fornecidos por access e layout, são mapeados para estágios específicos (origem da cópia/destino da cópia), gerando requisitos de drenagem/bloqueio mais adequados. Além disso, a tabela abaixo considera o caso de texturas (para Buffer, alguns estágios seriam diferentes).

| **Sinalizador de sync da barreira** | **Estágio(s) a ser(em) drenado(s)** | **Estágio(s) a ser(em) bloqueado(s)** |
| - | - | - |
| D3D12\_BARRIER\_SYNC\_RENDER\_TARGET | Drain CB | BlockME |
| D3D12\_BARRIER\_SYNC\_COMPUTE\_SHADING | Drain CS | BlockME |
| D3D12\_BARRIER\_SYNC\_RAYTRACING | Drain CS | BlockME |
| D3D12\_BARRIER\_SYNC\_COPY (origem) | DrainCPDMA, DrainCS, DrainPS | BlockME |
| D3D12\_BARRIER\_SYNC\_COPY (destino) | DrainCPDMA, DrainCS, DrainCB, DrainDB | BlockME |
| D3D12\_BARRIER\_SYNC\_DEPTH\_STENCIL | Drain DB | BlockME |
| D3D12XBOX\_BARRIER\_SYNC\_EXECUTE\_INDIRECT | DrainME | BlockPFP, BlockCE |

* Esses requisitos são posteriormente analisados e passados, junto com outras primitivas, para as funções SyncBottomOfPipe/SyncTopOfPipe para determinar as ações finais de sincronização (por exemplo, D3D12XBOX\_SYNC\_FLAG\_PS\_PARTIAL\_FLUSH ou D3D12XBOX\_SYNC\_FLAG\_IDLE). Esses sinalizadores não devem ser confundidos com os sinalizadores D3D12\_BARRIER\_SYNC, que são usados nas chamadas de Barreiras Aprimoradas.
* Esses requisitos não conhecem os mecanismos usados em última instância para atendê-los, então eles indicam explicitamente qual componente de hardware precisa ser drenado/bloqueado. Componentes posteriores podem perceber, por exemplo, que várias drenagens podem ser realizadas por um único evento EoP.

**Access (Before-After)** nos informa com quais caches esse recurso pode interagir antes e depois da barreira, o que, por sua vez, se traduz em requisitos de WB e de invalidação.

* No contexto das Barreiras, é útil saber quais recursos são mapeados para quais caches. Por exemplo, se tivermos um AccessBefore de D3D12\_ACCESS\_RENDER\_TARGET e um access after de D3D12\_ACCESS\_SHADER\_RESOURCE, queremos saber quais caches invalidar e/ou liberar (se necessário). A tabela a seguir mostra alguns tipos de recursos usados com frequência e qual memória eles utilizam.
* Os tipos de recurso não serão o único fator determinante para quais caches o recurso usa. O tipo de operação (escalar vs. vetorial) também importa, e isso é algo que o compilador decide. Uma busca em um buffer de constantes, por exemplo, pode passar pelo caminho \$K-L2 se for uma operação escalar (SMEM), ou pelo caminho L0-L1-L2 se for uma operação vetorial (VMEM).

| **Nome do access** | **Caches que utiliza** | **Observações** |
| - | - | - |
| Rendertarget | Caches do CB - L1, L2 | |
| Depth/Stencil | Caches do DB - L1, L2 | |
| ShaderResource | L0-L1, \$K, L2, LM | |
| UnorderedAccess | L0-L1, \$K, L2, LM | |
| ConstantBuffer | L0-L1, \$K, L2 | Os buffers de constantes normalmente são lidos por meio de instruções SMEM, mas, se acessados por índices não uniformes, o compilador gerará instruções VMEM. |
| VertexBuffer | L0-L1, L2 | Os buffers de vértices são lidos por meio de instruções VMEM (através de L0-L1-L2). |
| IndexBuffer | L2 | Os buffers de índices são buscados da DRAM para o L2 por meio do CPDMA acionado pelo PFP. |
| CopyDest | L0-L1, \$K, L2, LM, caches do CB, caches do DB | |
| CopySource | L0-L1, \$K, L2, LM | |
| Estrutura de aceleração de ray tracing (leitura/gravação) | L0-L1, \$K, L2 | |

**Layout (before-after)** descreve o layout de memória do recurso. Ele determinará se os recursos precisarão ser descompactados/compactados na operação da barreira, bem como se a inicialização de metadados é necessária (para rendertargets e depthstencils). Por exemplo, um rendertarget com DCC habilitado pode precisar executar um DCC-Eliminate ao fazer a transição para SRV, passando assim por uma descompactação.

* Determinados sinalizadores de recurso e de barreira alteram os requisitos resultantes de compactação/descompactação:
  * O driver mantém duas tabelas que mapeiam o tipo de recurso para operações de compactação/descompactação. Uma dessas tabelas é para recursos criados com D3D12XBOX\_RESOURCE\_FLAG\_FORCE\_TEXTURE\_COMPATIBILITY, enquanto a outra é para recursos não TC.
  * As EB introduzem o D3D12\_TEXTURE\_BARRIER\_FLAG\_DISCARD que, quando passado como argumento para o método Barrier, força a inicialização de metadados. Antes das EB, isso podia ser feito com uma operação de limpeza executada antes do primeiro uso do recurso.
  * Rendertargets e depthstencils precisam ser criados com D3D12\_RESOURCE\_FLAGS\_ALLOW\_RENDER\_TARGET e D3D12\_RESOURCE\_FLAGS\_ALLOW\_DEPTH\_STENCIL, respectivamente, para a alocação correta das superfícies de metadados.
  * Se você quiser usar DCC, o recurso precisa ser criado com o sinalizador D3D12XBOX\_RESOURCE\_FLAG\_ALLOW\_DCC. O DCC implicará operações de descompactação ao fazer a transição de um estado de gravação para um estado de leitura, mas não quando o recurso também for criado com D3D12XBOX\_RESOURCE\_FLAG\_FORCE\_TEXTURE\_COMPATIBILITY.
* A tabela a seguir, que mapeia sinalizadores de layout para sinalizadores de estado de compactação, ajuda a entender melhor como as transições de entrada e saída podem causar compactações/descompactações: por exemplo, passar de rendertarget (rt) para shader resource (sr) em recursos não TC requer uma descompactação, pois rt tem vários sinalizadores de compactação, enquanto sr está marcado como *uncompressedAll*. Mas a mesma transição para um recurso TC não acionaria uma descompactação, já que sr tem um superconjunto dos sinalizadores de estado de compactação de rt.

| **Sinalizador de layout** | **Não TC** | **TC** |
| - | - | - |
| D3D12\_BARRIER\_LAYOUT\_COMMON | uncompressedAll | uncompressedAll |
| D3D12\_BARRIER\_LAYOUT\_GENERIC\_READ | uncompressedAll | uncompressedAll |
| D3D12\_BARRIER\_LAYOUT\_RENDER\_TARGET | CompressedColor CompressedDcc ScatteredFmask IndirectColorClear | CompressedColor CompressedDcc ScatteredFmask IndirectColorClear |
| D3D12\_BARRIER\_LAYOUT\_UNORDERED\_ACCESS | uncompressedAll | CompressedColor CompressedDepth CompressedStencil CompressedDcc ScatteredFmask |
| D3D12\_BARRIER\_LAYOUT\_SHADER\_RESOURCE | uncompressedAll | CompressedColor CompressedDcc ScatteredFmask CompressedDepth CompressedStencil |
| D3D12\_BARRIER\_LAYOUT\_COPY\_SOURCE | CompressedColor CompressedDcc | CompressedColor CompressedDcc ScatteredFmask IndirectColorClear CompressedDepth CompressedStencil |
| D3D12\_BARRIER\_LAYOUT\_COPY\_DEST | CompressedColor CompressedDcc | CompressedColor CompressedDepth CompressedStencil CompressedDcc ScatteredFmask IndirectColorClear |

Definir before e after para **layout**, **access** e **sync** nos dá grande flexibilidade para fazer coisas que não conseguíamos ao usar ResourceBarriers (exceto com barreiras divididas, falaremos mais sobre isso adiante), além de melhorar os casos em que as Barreiras de Recursos podiam resultar em Partial Flushes desnecessários (barreiras UAV) e, no pior caso, levar a corrupção de memória (barreiras de aliasing, ao tentar uma descompactação sem ter certeza do layout atual da memória). Isso também corresponde melhor à forma como a sincronização funciona na GPU, oferecendo um controle mais refinado ao desenvolvedor.

### A especificação também define três tipos de barreiras:

* Barreiras globais:
  * Aplicam-se a toda a memória. A definição não recebe um ponteiro de recurso.
  * Nenhuma informação de layout é passada como argumento.
* Barreiras de buffer
  * Como o nome indica, as Barreiras de buffer são usadas para fazer a transição de recursos de buffer.
  * Nenhum layout ou sub-recurso é especificado como parâmetro (já que os buffers não usam nenhum dos dois).
* Barreiras de textura
  * Transição para recursos de textura (rendertargets, depthstencils, texturas SRV, texturas UAV etc.).
  * O layout é obrigatório, portanto essa barreira pode acionar descompactações e compactações.
  * É possível especificar um sub-recurso específico ou um intervalo.
    * Para sub-recursos, há limitações em termos de descompactação, pois não é possível descompactar apenas parte de um recurso.

Veja abaixo a definição da API do D3D12 para os três tipos de barreira:

```cpp theme={null}
struct D3D12_BUFFER_BARRIER 
{ 
    D3D12_BARRIER_SYNC SyncBefore; 
    D3D12_BARRIER_SYNC SyncAfter; 
    D3D12_BARRIER_ACCESS AccessBefore; 
    D3D12_BARRIER_ACCESS AccessAfter; 
    ID3D12Resource *pResource;     
    UINT64 Offset;  // Must be 0 
    UINT64 Size;    // UINT64_MAX or size in bytes 
};  
```

```cpp theme={null}
struct D3D12 _GLOBAL_BARRIER 
{ 
    D3D12_BARRIER_SYNC SyncBefore; 
    D3D12_BARRIER_SYNC SyncAfter; 
    D3D12_BARRIER_ACCESS AccessBefore; 
    D3D12_BARRIER_ACCESS AccessAfter; 
}  
```

```cpp theme={null}
struct D3D12_TEXTURE_BARRIER 
{ 
    D3D12_BARRIER_SYNC SyncBefore; 
    D3D12_BARRIER_SYNC SyncAfter; 
    D3D12_BARRIER_ACCESS AccessBefore; 
    D3D12_BARRIER_ACCESS AccessAfter; 
    D3D12_BARRIER_LAYOUT LayoutBefore; 
    D3D12_BARRIER_LAYOUT LayoutAfter; 
    ID3D12Resource *pResource; 
    D3D12_BARRIER_SUBRESOURCE_RANGE Subresources; 
    D3D12_TEXTURE_BARRIER_FLAGS Flags; 
};
```

* **LayoutBefore, LayourAfter**: layout de memória antes e depois da barreira. Determinará o que será compactado/descompactado. Usado somente por D3D12\_TEXTURE\_BARRIER.
* **SyncBefore, SyncAfter**: estágio a aguardar até ser drenado e estágio a bloquear antes de prosseguir.
* **AccessBefore, AccessAfter**: informa de quais caches deixaremos de fazer uso e quais passaremos a usar na transição.
* **Subresource range** -- Permite definir um intervalo de sub-recursos dos quais a barreira fará a transição. Usado somente por D3D12\_TEXTURE\_BARRIER.
* **Resource** -- O proprietário da memória da qual estamos fazendo a transição. Usado por D3D12\_TEXTURE\_BARRIER e D3D12\_BUFFER\_BARRIER.
* **Texture Barrier flags** -- Os valores podem ser D3D12\_TEXTURE\_BARRIER\_FLAG\_NONE e D3D12\_TEXTURE\_BARRIER\_FLAG\_DISCARD. Usado somente por D3D12\_TEXTURE\_BARRIER.
  * Usamos o sinalizador de descarte ao ativar um recurso, para que seus metadados sejam inicializados corretamente.
  * O uso desse sinalizador também permite agrupar a inicialização de recursos. As limpezas podem se sobrepor, e as operações de sync da barreira são agrupadas.

<a id="setting-things-up" />

## Configuração

***

Para usar as barreiras aprimoradas, você precisa do seguinte:

* GDK de março de 2023 ou mais recente.
* ID3D12GraphicsCommandList7: necessário para chamar o método [Barrier](https://learn.microsoft.com/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist7-barrier). Recebe uma struct D3D12\_BARRIER\_GROUP e o número do grupo.

(**Opcional**) ID3D12Device10 dá acesso às novas definições de criação de recursos: **CreatePlacedResource2**, **CreateCommitedResource3** e **CreateReservedResource2**. Elas recebem um D3D12\_BARRIER\_LAYOUT como parâmetro em vez do D3D12\_RESOURCE\_STATE.

* De acordo com a especificação, a interoperabilidade entre as APIs de Barreiras aprimoradas e os D3D12\_RESOURCE\_STATES herdados é compatível. No entanto, sub-recursos em qualquer estado herdado diferente de D3D12\_RESOURCE\_STATE\_COMMON precisam passar por uma transição para D3D12\_RESOURCE\_STATE\_COMMON antes de serem referenciados com uma Barreira aprimorada.

(**Opcional**) ID3D12Device11 dá acesso a novas APIs de extensão para criação de recursos: **CreatePlacedResourceX1** e **CreateComponentPlacedResourceX2**. Elas recebem um D3D12\_BARRIER\_LAYOUT como parâmetro em vez do D3D12\_RESOURCE\_STATE.

**Testes com as Barreiras de Recursos herdadas**

Temos um mecanismo que pode ser usado para desativar as EB e voltar à implementação anterior das Barreiras de Recursos. Se, a qualquer momento, os desenvolvedores encontrarem um travamento ou perceberem Barreiras agindo de forma inesperada (como levar mais tempo do que o normal para uma determinada transição ou gerar os sinalizadores de sincronização/descompactação errados), pode valer a pena voltar e verificar se o problema persiste. As etapas necessárias são:

* Crie um arquivo vazio na pasta Loose (diretório de implantação) e nomeie-o como **D3D\_\_DisableLegacyResourceBarrierTranslation**.
* Implante o jogo e verifique se o arquivo foi implantado no console.
  * **Observação**: ao executar nesse modo, o driver não oferece suporte à combinação de barreiras herdadas com barreiras aprimoradas.

Os desenvolvedores são **fortemente** incentivados a entrar em contato conosco pelos [Fóruns de Desenvolvedores do XBOX](https://forums.xboxlive.com/) caso encontrem algum problema desse tipo com as Barreiras Aprimoradas.

<a id="differences-with-the-pc-spec" />

## Diferenças em relação à especificação do PC

***

1. **No XBOX, o flush no limite de ExecuteCommandList** não é emitido, portanto não há suporte para acesso sem barreiras.
   * Isso se deve ao desempenho, pois um flush completo da GPU é caro.
   * [Acesso sem barreiras na especificação](https://microsoft.github.io/DirectX-Specs/d3d/D3D12EnhancedBarriers.html#barrier-free-access)
2. **Sub-recursos**. O PC rastreia metadados por sub-recurso, enquanto nós não. Isso significa que o estado de compactação por sub-recurso não pode ser rastreado. Por isso, alterações de layout que envolvem compactação ou descompactação terão resultados diferentes dependendo de o intervalo de recursos abranger (ou não) o recurso inteiro.
   * Se um recurso em um layout compactado tiver um ou mais (mas não todos) sub-recursos em transição para um layout não compactado, o recurso inteiro será descompactado.
   * Se um recurso em um layout não compactado tiver um ou mais (mas não todos) sub-recursos em transição para um layout compactado, o recurso inteiro permanecerá não compactado.
   * Oferecemos suporte a estados de compactação independentes para depth/stencil, o que significa que podemos ter depth compactado e stencil não compactado ou vice-versa.
3. **Barreiras divididas** funcionam, mas não são implementadas como barreiras divididas no driver. Em vez disso, elas são convertidas em barreiras imediatas. Fazemos essa conversão porque as barreiras divididas, conforme definidas pelo D3D12, impõem um custo de memória por recurso e são desnecessariamente ineficientes no nosso hardware. No entanto, a conversão para barreiras imediatas não é tão eficiente quanto poderia ser.
   * Isso ocorre porque o driver não recebe informações completas sobre o sync before e after. A conversão para barreira imediata acontece no lado próximo da barreira (o lado distante é ignorado), e por isso o driver precisa ser pessimista e bloquear tanto o CE quanto o PFP, o que pode tornar as barreiras divididas mais lentas do que as barreiras nativamente imediatas.
   * Além disso, historicamente, pouquíssimas pessoas usam as barreiras divididas no modelo herdado.
   * Uma forma de resolver o custo de memória por recurso no futuro pode ser permitir que os próprios desenvolvedores forneçam essa memória.
   * Há planos futuros para revisar a implementação das barreiras divididas.

Embora não seja uma diferença, vale mencionar que **as cópias continuam serializadas** (a especificação menciona que, com as barreiras aprimoradas, cópias serializadas talvez não sejam mais necessárias). **Observação**: passar D3D12XBOX\_CMDLIST\_DRIVER\_HINT\_DONT\_SYNC\_ON\_COPY como dica da lista de comandos permite limpezas e cópias não serializadas.

* Uma recomendação é que os usuários implementem suas próprias cópias de textura em Compute Shaders. Eles precisarão gerenciar as dependências, é claro, mas isso permitiria um trabalho não serializado e mais eficiente.
  * Um motivo pelo qual as cópias de textura gerenciadas pelo driver podem ter desempenho inferior é que elas podem usar os caches do CB/DB. Isso gera a necessidade de fazer WB extra e invalidar os caches do CB e do DB ao entrar ou sair de cópias de texturas.

<a id="enhanced-barrier-examples" />

## Exemplos de Barreiras Aprimoradas

***

Embora melhorias automáticas de desempenho em tempo de execução possam ser obtidas pela capacidade do driver de traduzir chamadas de Barreiras de Recursos herdadas em equivalentes de Barreiras Aprimoradas, economias adicionais podem ser obtidas usando as Barreiras Aprimoradas diretamente. A expressividade da API oferece oportunidades para reduzir latências de sincronização e eliminar flushes desnecessários. Os exemplos de código a seguir mostram como expressar chamadas de Barreiras de Recursos herdadas com a API de Barreiras Aprimoradas para aproveitar esses benefícios adicionais.

* [Barreiras de Recursos de transição](#transition-resource-barriers)
* [Barreiras de Recursos de acesso não ordenado](#unordered-access-resource-barriers)
* [Autocópia](#self-copy)
* [Barreiras de Recursos de aliasing](#aliasing-resource-barriers)

<a id="transition-resource-barriers" />

### **Barreiras de Recursos de transição**

Os recursos de memória em aplicativos gráficos são frequentemente acessados em contextos diferentes, seja como destinos de renderização, exibições de recursos de sombreador, exibições de buffer de vértices ou em outros tipos de estados. Isso gera a necessidade frequente de barreiras de recursos de transição para garantir a sincronização correta e a coerência do cache. No entanto, em alguns casos, as barreiras de recursos de transição podem introduzir lentidões de desempenho desnecessárias, como flush excessivo do pipeline.

Considere o seguinte trecho de código de barreira de recursos herdada, que mostra o estado de um recurso fazendo a transição de uma exibição de recurso de sombreador (SRV) para uma exibição de destino de renderização (RTV):

```cpp theme={null}
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(renderTarget,
    D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
    D3D12_RESOURCE_STATE_RENDER_TARGET);
commandList->ResourceBarrier(1, &barrier);
```

Este exemplo primeiro desenha em uma RTV, faz a transição do recurso para uma SRV para uso pelo compute shader e, em seguida, faz a transição de volta para uma RTV para que o próximo quadro execute o mesmo padrão de uso. Como não havia uma forma explícita de descrever como o recurso foi acessado pela última vez e que tipo de trabalho da GPU precisa ser sincronizado, o driver precisa fazer o flush de todos os estágios do pipeline em que o recurso poderia ter tido o estado D3D12\_RESOURCE\_STATE\_NON\_PIXEL\_SHADER\_RESOURCE.

Como visto na captura do PIX abaixo, essa transição faz com que o driver, como esperado, invoque um partial flush do compute shader para contabilizar o último dispatch, mas aciona desnecessariamente um partial flush do vertex shader. Esse recurso foi usado em uma chamada de desenho anterior e em um dispatch, e o driver não sabe em qual estado o recurso foi usado em cada caso. Ele também não sabe se os desenhos e dispatches foram concluídos no momento da emissão da barreira. Assim, ao priorizar a sincronização correta, ele precisa presumir que todos os estágios ativos do pipeline que não são de pixel shader (vertex e compute) e que usam o recurso podem ser afetados pela mudança no tipo de acesso ao recurso.

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_01.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=feb23c0da6682c3b650d4c6ef9302033" alt="Interface gráfica do usuário, aplicativo. Descrição gerada automaticamente" width="1100" height="690" data-path="images/gdk/features/graphics/EnhancedBarriers_01.png" />

O partial flush do vertex shader custa 0 us, já que nenhum outro desenho está em execução no momento, como visto na captura do PIX acima. No entanto, a barreira de recursos poderia levar mais tempo para ser concluída se houvesse algum trabalho anterior do vertex shader de eventos D3D anteriores não relacionados.

Isso pode ser evitado especificando também os estados de sincronização e de layout do recurso com a API de Barreiras Aprimoradas, conforme indicado abaixo pelos argumentos destacados. O usuário pode garantir que nenhum trabalho do vertex shader estará ativo durante a chamada da barreira e limitar explicitamente os partial flushes ao estágio de compute shading, bloqueando apenas o trabalho que solicita operar em uma RTV.

```cpp theme={null}
auto barrierSubresourceRange = CD3DX12_BARRIER_SUBRESOURCE_RANGE();

auto textureBarrier = CD3DX12_TEXTURE_BARRIER (
    D3D12_BARRIER_SYNC_COMPUTE_SHADING,
    D3D12_BARRIER_SYNC_RENDER_TARGET,
    D3D12_BARRIER_ACCESS_SHADER_RESOURCE,
    D3D12_BARRIER_ACCESS_RENDER_TARGET,
    D3D12_BARRIER_LAYOUT_SHADER_RESOURCE,
    D3D12_BARRIER_LAYOUT_RENDER_TARGET,
    renderTarget,
    barrierSubresourceRange
);

auto barrierGroup = CD3DX12_BARRIER_GROUP(1, &textureBarrier);
```

Como mostrado abaixo, a Barreira Aprimorada agora deixa de usar um partial flush do vertex shader. A exibição Command Disassembly e a exibição Event Details do PIX também podem ser usadas para ver, respectivamente, os pacotes de comando e as informações de configuração da Barreira com mais detalhes:

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_02.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=3ca408d5ea63002ae2ccff6ecb8bbfa7" alt="Interface gráfica do usuário, texto, aplicativo, email. Descrição gerada automaticamente" width="750" height="391" data-path="images/gdk/features/graphics/EnhancedBarriers_02.png" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_03.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=3bf3a236e5f689fcaa10dc0626b80524" alt="Interface gráfica do usuário, aplicativo, tabela. Descrição gerada automaticamente" width="750" height="556" data-path="images/gdk/features/graphics/EnhancedBarriers_03.png" />

Se o recurso fosse um buffer em vez de uma textura 2D, como no caso anterior, e o buffer fosse usado como saída de streaming em vez de uma RTV, uma barreira de buffer poderia ser usada de forma semelhante:

```cpp theme={null}
auto bufferBarrier = CD3DX12_BUFFER_BARRIER (
    D3D12_BARRIER_SYNC_COMPUTE_SHADING,
    D3D12_BARRIER_SYNC_STREAM_OUTPUT,
    D3D12_BARRIER_ACCESS_SHADER_RESOURCE,
    D3D12_BARRIER_ACCESS_STREAM_OUTPUT,
    m_renderTarget.Get(),
    barrierSubresourceRange
);
```

<a id="unordered-access-resource-barriers" />

### **Barreiras de Recursos de acesso não ordenado**

As Barreiras de Recursos herdadas criadas para sincronizar leituras e gravações em uma exibição de acesso não ordenado (UAV) também são vítimas de flushes supérfluos do pipeline da GPU, por motivos relacionados ao driver semelhantes aos que existem nas barreiras de recursos de transição herdadas. Considere um cenário em que texturas com mipmaps são geradas a partir de um compute shader, todas gravadas e lidas a partir de uma UAV de textura, e o seguinte código de barreira de recursos de acesso não ordenado é usado para evitar riscos:

```cpp theme={null}
auto barrier = CD3DX12_RESOURCE_BARRIER::UAV(texture0);
commandList->ResourceBarrier(1, &barrier);
```

Observando os eventos de hardware resultantes gerados no PIX, partial flushes são executados para os estágios de pixel shader, vertex shader e compute shader. Há apenas itens de trabalho de computação despachados até a barreira ser executada, portanto os partial flushes do compute shader são suficientes.

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_04.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=38b89f5d74fede1bba85870254f2ad07" alt="Interface gráfica do usuário, aplicativo, tabela. Descrição gerada automaticamente" width="1100" height="969" data-path="images/gdk/features/graphics/EnhancedBarriers_04.png" />

A solução aqui, assim como no exemplo da Barreira de Recursos de transição, é usar uma barreira de textura em que os estados de sincronização façam flush e bloqueiem exclusivamente o trabalho do compute shader. A modificação de código a seguir faz com que os partial flushes do vertex shader e do pixel shader desapareçam da captura do PIX.

```cpp theme={null}
auto barrierSubresourceRange = CD3DX12_BARRIER_SUBRESOURCE_RANGE();

auto barrier = CD3DX12_TEXTURE_BARRIER (
    D3D12_BARRIER_SYNC_CLEAR_UNORDERED_ACCESS_VIEW,
    D3D12_BARRIER_SYNC_COMPUTE_SHADING,
    D3D12_BARRIER_ACCESS_UNORDERED_ACCESS
    D3D12_BARRIER_ACCESS_SHADER_RESOURCE,
    D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS,
    D3D12_BARRIER_LAYOUT_SHADER_RESOURCE,
    texture0,
    barrierSubresourceRange
);

auto barrierGroup = CD3DX12_BARRIER_GROUP(1, &barrier);
```

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_05.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=ceb9f67d854cd57cc87cebceb8913d3e" alt="Interface gráfica do usuário, aplicativo, tabela. Descrição gerada automaticamente" width="750" height="445" data-path="images/gdk/features/graphics/EnhancedBarriers_05.png" />

<a id="self-copy" />

### **Autocópia**

Anteriormente, não era possível gravar e ler simultaneamente um sub-recurso, pois o design das Barreiras de Recursos herdadas não permite combinar bits somente leitura e de gravação. Isso significava que mover dados em um recurso entre duas regiões não sobrepostas exigiria a criação de uma textura temporária, mais barreiras de transição para alternar entre D3D12\_RESOURCE\_STATE\_COPY\_SOURCE e D3D12\_RESOURCE\_STATE\_COPY\_DEST e mais operações de cópia de sub-recursos. Isso é ilustrado no exemplo de código abaixo, que mostra o trabalho necessário para copiar o quarto superior esquerdo de uma textura para o seu quarto inferior direito.

```cpp theme={null}
// Legacy resource barriers
{
    auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
        D3D12_RESOURCE_STATE_COPY_SOURCE
    );
    commandList->ResourceBarrier(1, &barrier);

    barrier = CD3DX12_RESOURCE_BARRIER::Transition(textureTmp,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
        D3D12_RESOURCE_STATE_COPY_DEST
    );
    commandList->ResourceBarrier(1, &barrier);
}

// Copy top left quarter to temp texture
{
    auto locationSrc = CD3DX12_TEXTURE_COPY_LOCATION(texture, 0);
    auto locationDst = CD3DX12_TEXTURE_COPY_LOCATION(textureTmp, 0);
    commandList->CopyTextureRegion(&locationDst, boxTopLeft.left,
        boxTopLeft.top, boxTopLeft.front, &locationSrc, &boxTopLeft);

    auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture,
        D3D12_RESOURCE_STATE_COPY_SOURCE,
        D3D12_RESOURCE_STATE_COPY_DEST
    );
    commandList->ResourceBarrier(1, &barrier);

    barrier = CD3DX12_RESOURCE_BARRIER::Transition(textureTmp,
        D3D12_RESOURCE_STATE_COPY_DEST,
        D3D12_RESOURCE_STATE_COPY_SOURCE
    );
    commandList->ResourceBarrier(1, &barrier);
}

// Copy temp texture to bottom right quarter
{
    auto locationSrc = CD3DX12_TEXTURE_COPY_LOCATION(textureTmp, 0);
    auto locationDst = CD3DX12_TEXTURE_COPY_LOCATION(texture, 0);
    commandList->CopyTextureRegion(&locationDst, boxBottomRight.left,
        boxBottomRight.top, boxBottomRight.front, &locationSrc, &boxTopLeft);

    auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture,
        D3D12_RESOURCE_STATE_COPY_DEST,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS
    );
    commandList->ResourceBarrier(1, &barrier);

    barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_textureTmp.Get(),
        D3D12_RESOURCE_STATE_COPY_SOURCE,
        D3D12_RESOURCE_STATE_UNORDERED_ACCESS
    );
    commandList->ResourceBarrier(1, &barrier);
}
```

A API de barreiras aprimoradas agora permite a autocópia, tornando o código necessário muito mais fácil de ler e escrever, além de eliminar a necessidade de uma textura intermediária:

```cpp theme={null}
// Self copy top left quarter to bottom right quarter
auto locationSrc = CD3DX12_TEXTURE_COPY_LOCATION(texture, 0);
auto locationDst = CD3DX12_TEXTURE_COPY_LOCATION(texture, 0);

commandList->CopyTextureRegion(&locationDst, boxBottomRight.left,
    boxBottomRight.top, boxBottomRight.front, &locationSrc, &boxTopLeft);
```

A exibição Events do PIX pode ser usada para visualizar a diferença nos eventos de hardware entre a implementação de autocópia de textura com Barreiras de Recursos herdadas e com Barreiras Aprimoradas. Considere o seguinte par de capturas de tela de capturas do PIX, em que a primeira contém apenas Barreiras de Recursos herdadas e a segunda tem Barreiras Aprimoradas:

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_06.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=40e35c9cfcfc4fa549e5b79574a96fad" alt="Tabela. Descrição gerada automaticamente" width="926" height="1100" data-path="images/gdk/features/graphics/EnhancedBarriers_06.png" />

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_07.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=8145f6ff6b0ffaabb5a5032722f1693d" alt="Interface gráfica do usuário, texto, aplicativo, email. Descrição gerada automaticamente" width="750" height="248" data-path="images/gdk/features/graphics/EnhancedBarriers_07.png" />

<a id="aliasing-resource-barriers" />

### **Barreiras de Recursos de aliasing**

Como visto no código abaixo, extraído da [documentação pública do D3D12 no MSDN](https://learn.microsoft.com/windows/win32/api/d3d12/ns-d3d12-d3d12_resource_aliasing_barrier), o aliasing de recursos posicionados na API de Barreiras de Recursos herdadas historicamente envolvia apenas especificar os dois recursos que compartilhavam a memória do heap. A API de Barreiras Aprimoradas pode ajudar a evitar a necessidade de bloquear todo o trabalho da GPU e fazer flush de todas as gravações, além de fornecer estados de layout explícitos para garantir que o driver não descompacte memória não compactada (consulte [este link](https://microsoft.github.io/DirectX-Specs/d3d/D3D12EnhancedBarriers.html#aliasing-barriers-are-very-expensive) para obter mais informações sobre esse último problema em "Aliasing Barriers Are Very Expensive").

```cpp theme={null}
typedef struct D3D12_RESOURCE_ALIASING_BARRIER 
{
    ID3D12Resource *pResourceBefore;
    ID3D12Resource *pResourceAfter;
} D3D12_RESOURCE_ALIASING_BARRIER;
```

Este trecho de código demonstra como as barreiras de textura podem ser usadas para facilitar o aliasing entre dois recursos posicionados: pTex0 hospeda dados copiados anteriormente de um heap de upload, e pTex1 reutiliza esses dados para serem copiados de volta para outro buffer.

```cpp theme={null}
// Transition pTex0 to COPY_SOURCE
auto tex0Barrier = CD3DX12_TEXTURE_BARRIER (
    D3D12_BARRIER_SYNC_RENDER_TARGET,
    D3D12_BARRIER_SYNC_COPY,
    D3D12_BARRIER_ACCESS_RENDER_TARGET,
    D3D12_BARRIER_ACCESS_COPY_SOURCE,
    D3D12_BARRIER_LAYOUT_RENDER_TARGET,
    D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE,
    pTex0,
    CD3DX12_BARRIER_SUBRESOURCE_RANGE(0, 1, 0, 1)
);

// Barrier to affect an aliasing transition from pTex0 to
// pTex1 with a layout of COPY_SOURCE
auto tex1Barrier = CD3DX12_TEXTURE_BARRIER (
    D3D12_BARRIER_SYNC_RENDER_TARGET,
    D3D12_BARRIER_SYNC_COPY,
    D3D12_BARRIER_ACCESS_NO_ACCESS,
    D3D12_BARRIER_ACCESS_COPY_SOURCE,
    D3D12_BARRIER_LAYOUT_UNDEFINED,
    D3D12_BARRIER_LAYOUT_COPY_SOURCE,
    pTex1,
    CD3DX12_BARRIER_SUBRESOURCE_RANGE(0, 1, 0, 1)
);
```

<a id="compatibility-with-legacy-resource-barriers" />

## Compatibilidade com as Barreiras de Recursos herdadas

***

A API de barreiras anterior (Barreiras de Recursos) ainda é compatível, mas o driver as **traduz** internamente em Barreiras Aprimoradas. Vários testes foram executados em capturas do PIX para ver o impacto da tradução (em comparação com o uso da implementação anterior). Os resultados mostraram que a tradução para EB oferece ganhos significativos.

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_08.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=7117c2331d6b4da6e8de894026bbc3f2" alt="Gráfico, gráfico de linhas. Descrição gerada automaticamente" width="1223" height="689" data-path="images/gdk/features/graphics/EnhancedBarriers_08.png" />

O gráfico acima mostra os ganhos em capturas de quadro único (em termos de % de melhoria no tempo de quadro) para um total de 115 capturas. Vale observar que a seleção aqui inclui títulos de jogos e exemplos, sendo que os exemplos apresentam os maiores ganhos. Abaixo está uma lista de títulos AAA e a melhoria no tempo de quadro (%) que obtivemos a partir de suas capturas do PIX.

| Título | Melhoria no tempo de quadro (%) |
| - | - |
| Título A | 5,7% |
| Título B | 3,7% |
| Título C | 3,2% |
| Título D | 2,5% |
| Título E | 2,4% |
| Título F | 2,3% |
| Título G | 1,6% |

Vale observar que os ganhos dependerão muito da forma como o mecanismo gráfico é construído em termos de sincronização e posicionamento das barreiras.

Exemplos em que a tradução apresentou melhorias em relação às Barreiras de Recursos herdadas:

### **Exemplo 1 - Geração de partial flush na barreira UAV**

Barreira de Recursos herdada

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_09.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=f6c371681e9f7d80af7d70d03a23773a" alt="Interface gráfica do usuário" width="455" height="150" data-path="images/gdk/features/graphics/EnhancedBarriers_09.png" />

Barreira de Recursos traduzida

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_10.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=acf5eca179145aca94b75c08225e6423" alt="Interface gráfica do usuário" width="426" height="179" data-path="images/gdk/features/graphics/EnhancedBarriers_10.png" />

A barreira traduzida mostra as etapas de sync corretas. Ela executa partial flushes de PS, VS e CS antes de invalidar, pois precisa se preparar para o pior caso (considerar todos os estágios que poderiam estar gravando na UAV). Por outro lado, a barreira herdada aciona um partial flush de PS e de CS antes de invalidar. Isso não está correto, pois presume que os estágios de VS serão necessariamente seguidos por PS, o que nem sempre é o caso. **Neste exemplo, as barreiras traduzidas corrigem um problema presente nas Barreiras de Recursos UAV**.

### **Exemplo 2 - Aliasing**

Barreira de Recursos herdada

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_11.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=fa96c405ce385338f87f5851ae3e1be6" alt="Interface gráfica do usuário" width="1342" height="371" data-path="images/gdk/features/graphics/EnhancedBarriers_11.png" />

Barreira de Recursos traduzida

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_12.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=e50298acca609ad108f9a55d080ead6c" alt="Interface gráfica do usuário" width="1029" height="122" data-path="images/gdk/features/graphics/EnhancedBarriers_12.png" />

Neste exemplo, o ResourceBarrier::Aliasing estava gerando alguns flushes de streamout que não eram necessários. A barreira traduzida fará uma espera de fence por alguns flushes e invalidações de BoP, seguida de alguma sincronização de ToP (isso é idêntico ao que a herdada fazia, sem os pacotes relacionados ao streamout). **Neste exemplo, as barreiras traduzidas obtêm um ganho de desempenho com a tradução**.

> Tudo isso mostra os ganhos que os desenvolvedores podem obter simplesmente por terem as Barreiras Aprimoradas, sem alterações no código. Para ver os ganhos potenciais ao atualizar para a nova API de Barreiras, consulte a seção [**Exemplos de Barreiras Aprimoradas**](#enhanced-barrier-examples).

<a id="pix-support-and-validation" />

## Suporte e validação do PIX

***

O **PIX** oferece suporte tanto às barreiras aprimoradas quanto às Barreiras de Recursos herdadas traduzidas.

**Para as Barreiras Aprimoradas**, será criado um evento do PIX chamado **Barrier**, que contém os pacotes de CP gerados.

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_13.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=4bff7bc7ae85abc391ca2d7d705ab5a0" alt="Imagem de uma barreira de buffer de SRV para UAV no PIX" width="594" height="114" data-path="images/gdk/features/graphics/EnhancedBarriers_13.png" />

Na exibição Event Details, você pode obter todos os detalhes da chamada da API Barrier, como os tipos, a contagem de Barrier Groups, os valores before/after de sync, access e layout (se for uma barreira de textura) e também pResource (se não for uma Barreira global).

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_14.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=324c1b88b935cdee6166bb371d6c950e" alt="Interface gráfica do usuário, texto. Descrição gerada automaticamente" width="1023" height="754" data-path="images/gdk/features/graphics/EnhancedBarriers_14.png" />

**Para as Barreiras de Recursos (herdadas)**, será exibido o nome da API ResourceBarrier e, como nó filho, a Barreira traduzida (\[Barrier]).

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_15.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=3816626e092ebf565bc71b746be4e77c" alt="Interface gráfica do usuário, texto, aplicativo, site. Descrição gerada automaticamente" width="778" height="142" data-path="images/gdk/features/graphics/EnhancedBarriers_15.png" />

Você pode ver os Event Details da barreira herdada ao selecionar o evento ResourceBarrier (é igual à exibição Event Details da Barreira de Recursos antes das Barreiras Aprimoradas, exceto pelos bits de Actions, que aparecem como D3D12XBOX\_RESOURCE\_BARRIER\_ACTION\_NONE).

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_16.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=60ae625af8392910661bb0e243d863fc" alt="Captura de tela de um computador. Descrição gerada automaticamente com confiança média" width="877" height="577" data-path="images/gdk/features/graphics/EnhancedBarriers_16.png" />

Ao selecionar o nó filho \[barrier], você pode ver os Event Details da barreira traduzida (como faria para uma Barreira Aprimorada).

<img src="https://mintcdn.com/microsoft-4404708b/EHFikhsC0GyEu9Ca/images/gdk/features/graphics/EnhancedBarriers_17.png?fit=max&auto=format&n=EHFikhsC0GyEu9Ca&q=85&s=e9c824b9f2c87a30e721fea5af7affc3" alt="Interface gráfica do usuário, texto, aplicativo. Descrição gerada automaticamente" width="868" height="157" data-path="images/gdk/features/graphics/EnhancedBarriers_17.png" />

### **Validação**

A validação estará disponível tanto para as **barreiras aprimoradas** quanto para as **barreiras de recursos herdadas que passam pela camada de tradução**. A validação que você obtém dependerá de qual API você está usando:

* Para as Barreiras Aprimoradas, a paridade de validação se refere aos cenários cobertos. As Barreiras Aprimoradas são diferentes das Barreiras de Recursos, portanto a validação não replicará exatamente o que fazia para as herdadas, mas garantirá que todas as propriedades before e after estejam corretas para a transição. Por exemplo:
  * Garantir que os recursos estejam no layout correto ao iniciar uma transição.
  * Validar a correção da API (mais detalhes abaixo).
* Para as Barreiras de Recursos herdadas (traduzidas), a validação oferece paridade com a validação atual das Barreiras de Recursos.

A validação também verifica se os recursos em transição de barreiras herdadas para aprimoradas estão no estado correto (D3D12\_RESOURCE\_STATE\_COMMON).

**Para a validação da API**, a especificação lista o que é esperado. A camada de depuração valida o seguinte durante as chamadas de Barrier:

* O dispositivo subjacente oferece suporte a barreiras aprimoradas
* Não é uma lista de comandos de pacote (bundle)
* Avisa se alguma contagem (de grupos ou de barreiras por grupo) for zero
* Verifica se os sub-recursos da barreira de textura correspondem aos limites de sub-recursos da textura
* O tipo de barreira corresponde ao tipo de recurso
* LayoutBefore e AccessBefore correspondem ao layout e ao acesso conhecidos ou presumidos do recurso.
* SyncBefore, AccessBefore e LayoutBefore são compatíveis.
* SyncAfter, AccessAfter e LayoutAfter são compatíveis.
* As barreiras de fim de divisão correspondem às barreiras de início de divisão anteriores.
* As barreiras divididas de Buffer e de D3D12\_BARRIER\_LAYOUT\_COMMON não ultrapassam os limites de ExecuteCommandLists.
  * Provavelmente um aviso em vez de um erro, devido às permissões herdadas

Quanto à saída da validação, ela seguirá o esquema mostrado abaixo:

```cpp theme={null}
TextD3D12 ERROR: [0xA7900038] ID3D12CommandQueue(Graphics)::ExecuteCommandLists: Resource is being transitioned from legacy to enhanced barriers but is not in the state D3D12_RESOURCE_STATE_COMMON as is required.
Current State is: D3D12_RESOURCE_STATE_RENDER_TARGET
|  -Group Index:   0
|  -Barrier Index: 0
|  -Barrier
|   |  -SyncBefore:   D3D12_BARRIER_SYNC_RENDER_TARGET
|   |  -SyncAfter:    D3D12_BARRIER_SYNC_COMPUTE_SHADING
|   |  -AccessBefore: D3D12_BARRIER_ACCESS_RENDER_TARGET
|   |  -AccessAfter:  D3D12_BARRIER_ACCESS_UNORDERED_ACCESS
|   |  -LayoutBefore: D3D12_BARRIER_LAYOUT_RENDER_TARGET
|   |  -LayoutAfter:  D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS
|   |  -pResource:    (0x0000000200200C00) "<untitled>"
|   |  -Subresources
|   |    |  -IndexOrFirstMipLevel: 4294967295
|   |    |  -NumMipLevels:         0
|   |    |  -FirstArraySlice:      0
|   |    |  -NumArraySlices:       0
|   |    |  -FirstPlane:           0
|   |    |  -NumPlanes:            0
|   |  -Flags: D3D12_TEXTURE_BARRIER_FLAG_NONE (0x00000000)
```


## Related topics

- [Diretório de tópicos NDA: links ativos do Microsoft Learn](/pt-BR/nda/nda-topic-directory.md)
- [D3D12_CULL_MODE](/reference/graphics/d3d12/enums/d3d12_cull_mode_public.md)
- [D3D12_TILE_MAPPING_FLAGS](/reference/graphics/d3d12/enums/d3d12_tile_mapping_flags_public.md)
- [D3D12_RTV_DIMENSION](/reference/graphics/d3d12/enums/d3d12_rtv_dimension_public.md)
- [D3D12_RESOURCE_HEAP_TIER](/reference/graphics/d3d12/enums/d3d12_resource_heap_tier_public.md)
