Cadeias de Troca

As cadeias de troca controlam a rotação do buffer traseiro, formando a base da animação gráfica.

Visão geral

O modelo de programação para cadeias de troca no Direct3D 12 não é idêntico ao das versões anteriores do D3D. A conveniência de programação, por exemplo, de oferecer suporte à rotação automática de recursos, presente no D3D10 e no D3D11, não é mais oferecida. A rotação automática de recursos permitia aos aplicativos renderizar o mesmo objeto da API, enquanto a superfície real renderizada mudava a cada quadro. O comportamento das cadeias de troca é alterado com o Direct3D 12 para permitir que outros recursos do Direct3D 12 tenham baixa sobrecarga de CPU. Não há suporte para chave de cor automática e multisampling, embora, notavelmente, alongamento e rotação ainda sejam.

Tempo de vida do buffer

Os aplicativos podem armazenar descritores pré-criados que fazem referência a back buffers. Isso é habilitado garantindo que o conjunto de buffers pertencentes a uma cadeia de troca nunca mude durante o tempo de vida da cadeia de troca. O conjunto de buffers retornados por IDXGISwapChain::GetBuffer não é alterado até que determinadas APIs sejam chamadas:

A ordem dos buffers retornados por GetBuffer nunca é alterada.

IDXGISwapChain3::GetCurrentBackBufferIndex retorna o índice do buffer de fundo atual para o aplicativo.

Efeitos de troca

Os únicos efeitos de troca com suporte são DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL e DXGI_SWAP_EFFECT_FLIP_DISCARD, o que exige que a contagem de buffers seja maior que uma.

Dica

Para jogos que visam à menor latência de entrada possível, crie a cadeia de troca com DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING e, em seguida, chame Present(0, DXGI_PRESENT_ALLOW_TEARING). Isso contorna o vsync do compositor e proporciona a menor latência entre a apresentação e a exibição. Em runtime, verifique o suporte de rasgo chamando IDXGIFactory5::CheckFeatureSupport com DXGI_FEATURE_PRESENT_ALLOW_TEARING antes de usar esse caminho.

Aviso

Um bug comum de cadenciamento de quadros consiste em chamar Present(1, 0) (vsync-on) sem sincronizar corretamente o trabalho da CPU com a fence da GPU. Isso faz com que a CPU seja executada com antecedência, criando uma fila de quadros que aumenta a latência de entrada. Sempre use um semáforo de contagem de quadros para limitar os quadros da CPU em processamento (normalmente ao número de buffers menos um).

Transição entre os modos de janela e tela inteira

O Direct3D 12 não dá suporte ao FSE (modo exclusivo de tela inteira). Em vez disso, quando um jogo é o único aplicativo visível na tela, o sistema operacional usa uma estratégia chamada FSO (otimizações de tela inteira) para obter um efeito semelhante ao FSE sem as desvantagens de desempenho. Para obter mais informações sobre o FSO, consulte Desmistificando as otimizações de tela inteira.

O Direct3D 12 mantém a restrição de que os aplicativos devem chamar ResizeBuffers após alternar entre os modos de janela e tela inteira (as swap chains do modelo flip do D3D11 têm as mesmas restrições).

As transiçõesIDXGISwapChain::SetFullscreenStatenão alteram o conjunto de buffers visíveis do aplicativo na cadeia de troca. Somente as chamadas ResizeBuffers e ResizeTarget criam ou destroem buffers visíveis para o aplicativo. No entanto, no Direct3D 12 IDXGISwapChain::SetFullscreenState não entra no modo exclusivo de tela inteira e simplesmente altera as resoluções e as taxas de atualização para permitir otimizações de tela inteira. Essas alterações podem ser feitas por um aplicativo sem o uso desse método

Quando ou IDXGISwapChain::P ent ou IDXGISwapChain1::P resent é chamado, o buffer de fundo a ser apresentado deve estar no estado D3D12_RESOURCE_STATE_PRESENT. O presente falhará com DXGI_ERROR_INVALID_CALL se esse não for o caso.

As cadeias de permuta em tela inteira continuam sujeitas à restrição de que SetFullscreenState(FALSE, NULL) deve ser chamado antes da liberação final da cadeia de permuta. SetFullscreenState(FALSE) é bem-sucedido em cadeias de troca em execução em dispositivos Direct3D 12.

As operações presentes ocorrem na fila 3D fornecida na criação de swapchain e os aplicativos são livres para apresentar simultaneamente várias cadeias de troca e registrar e executar listas de comandos.

Quando a parte final do trabalho gráfico (por exemplo, o pós-processamento de quadros) é executada em uma fila de computação, ou não envolve a fila de gráficos do dispositivo, criar uma segunda fila 3D para apresentação pode ser benéfico e evitar que a latência da apresentação atrase o início do próximo quadro.

Exemplo

O código de exemplo a seguir estaria presente no loop de renderização principal:

Aviso

O exemplo a seguir é simplificado para maior clareza. O loop principal de um jogo em produção deve desacoplar as atualizações da simulação da frequência de renderização — por exemplo, usando um fixed timestep para a simulação enquanto renderiza o mais rápido possível — e usar uma fence para limitar os quadros em processamento. Sem a limitação do número de quadros em voo, o Present pode ser concluído imediatamente em cadeias de troca do modelo flip, permitindo que a CPU enfileire quadros sem limite e aumente a latência de entrada.

void Present()
{
    m_swapChain->Present(0, m_presentFlags);
    m_backBufferIndex = (m_backBufferIndex + 1) % m_backBufferCount;
}

Criando cadeias de troca

Ao usar as chamadas CreateSwapChainForHwnd, CreateSwapChainForCoreWindow ou CreateSwapChainForComposition, observe que o parâmetro pDevice na verdade requer um ponteiro para uma fila de comandos diretos no Direct3D 12, e não um dispositivo.

Apresentando no Windows 7

Ao usar o Direct3D 12 no Windows 7, os tipos DXGI necessários para o Direct3D 12 não estão disponíveis, portanto, você deve usar a interface ID3D12CommandQueueDownLevel, fornecida pelo D3D12On7 (obtida da fila de comandos direta), para fazer a apresentação.

Você fornece uma lista de comandos em aberto ao método de apresentação do Windows 7, que então será usada, fechada e enviada automaticamente ao dispositivo em seu nome. Você deve fornecer um buffer de fundo que deve ser criado pelo aplicativo, deve ser um recurso confirmado, deve ser de amostra única e deve ser um dos seguintes formatos.

  • DXGI_FORMAT_R16G16B16A16_FLOAT
  • DXGI_FORMAT_R10G10B10A2_UNORM
  • DXGI_FORMAT_R8G8B8A8_UNORM
  • DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
  • DXGI_FORMAT_B8G8R8X8_UNORM
  • DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
  • DXGI_FORMAT_B8G8R8A8_UNORM
  • DXGI_FORMAT_B8G8R8A8_UNORM_SRGB