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. A chave de cor automática e multiamostragem não são compatíveis, embora, notadamente, 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 segmentam a latência de entrada mínima, 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 à divisão chamando IDXGIFactory5::CheckFeatureSupport com DXGI_FEATURE_PRESENT_ALLOW_TEARING antes de usar esse caminho.

Aviso

Um bug no ritmo de quadros comum consiste em chamar Present(1, 0) (vsync-on) sem sincronizar devidamente o trabalho da CPU com o limite de GPU. Isso faz com que a CPU seja executada com antecedência, acumulando uma fila de quadros que aumenta a latência de entrada. Sempre use um limite de contagem de quadros para restringir quadros de CPU em versão piloto (normalmente à contagem do buffer 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 IDXGISwapChain::P ent ou IDXGISwapChain1::P resent é chamado, o contrabuffer 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 troca em tela inteira continuam sujeitas à restrição de que SetFullscreenState(FALSE, NULL) deva ser chamado antes da liberação final da cadeia de troca. 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 estã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 separar atualizações de simulação da frequência de renderização – por exemplo, usando um timestep fixo para a simulação durante a renderização o mais rápido possível – e usar um limite para restringir os quadros em versão piloto. Sem a limitação da versão piloto do quadro, 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, logo, você deve usar ID3D12CommandQueueDownLevel fornecido pelo D3D12On7 (obtido na fila de comandos diretos), 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