Cadeias de permuta

As cadeias de permuta 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 permuta no Direct3D 12 não é idêntico ao das versões anteriores do D3D. A conveniência de programação, por exemplo, de suportar a rotação automática de recursos que estava presente em D3D10 e D3D11 não é mais suportada. A rotação automática de recursos permitiu que os aplicativos renderizassem o mesmo objeto de API enquanto a superfície real que está sendo renderizada muda a cada quadro. O comportamento das cadeias de permuta é 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 a amostragem múltipla não são suportadas, embora ainda sejam notavelmente alongamento e rotação.

Vida útil do buffer

Os aplicativos têm permissão para armazenar descritores pré-criados que fazem referência a buffers de retorno. Isso é habilitado garantindo que o conjunto de buffers de propriedade de uma cadeia de permuta nunca seja alterado durante o tempo de vida da cadeia de permuta. O conjunto de buffers retornado por IDXGISwapChain::GetBuffer não muda até que determinadas APIs sejam chamadas:

A ordem dos buffers devolvidos por GetBuffer nunca muda.

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

Efeitos de permuta

Os únicos efeitos de permuta suportados são DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL e DXGI_SWAP_EFFECT_FLIP_DISCARD, o que requer que a contagem de buffer seja maior que um.

Tip

Para jogos que visem a latência mínima de entrada, crie a cadeia de troca com DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING e depois chame Present(0, DXGI_PRESENT_ALLOW_TEARING). Isto ignora o vsync do compositor e oferece a menor latência entre a apresentação e a exibição no ecrã. Em tempo de execução, verifique o suporte a tearing chamando IDXGIFactory5::CheckFeatureSupport com DXGI_FEATURE_PRESENT_ALLOW_TEARING antes de usar este caminho.

Warning

Um erro comum de cadenciamento de fotogramas é chamar Present(1, 0) (vsync ativado) sem sincronizar corretamente o trabalho da CPU com a fence da GPU. Isto faz com que o CPU avance, construindo uma fila de frames que aumenta a latência de entrada. Utilize sempre uma barreira de contagem de frames para limitar os frames da CPU em processamento (normalmente, para o número de buffers menos um).

Transição entre os modos de janela e de ecrã inteiro

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

O Direct3D 12 mantém a restrição de que os aplicativos devem chamar ResizeBuffers após a transição entre os modos de janela e tela cheia (as cadeias de permuta de modelo flip-model D3D11 têm as mesmas restrições).

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

Quando ou IDXGISwapChain::P resent ou IDXGISwapChain1::P resent é chamado, o buffer traseiro a ser apresentado deve estar no estado D3D12_RESOURCE_STATE_PRESENT. Present falhará com o erro DXGI_ERROR_INVALID_CALL se não for esse o caso.

As cadeias de troca em ecrã inteiro continuam a ter a restrição de que SetFullscreenState(FALSE, NULL) tem de ser chamado antes da libertação final da cadeia de troca. SetFullscreenState(FALSE) é bem-sucedido em cadeias de permuta executadas em dispositivos Direct3D 12.

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

Quando a parte final do trabalho gráfico (por exemplo, pós-processamento de quadros) é feita em uma fila de computação ou não envolve a fila de gráficos do dispositivo, criar uma segunda fila 3D para apresentar 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:

Warning

O exemplo abaixo é simplificado para maior clareza. Um ciclo de jogo de produção deve desacoplar as atualizações de simulação da frequência de renderização — por exemplo, usando um passo de tempo fixo para simulação enquanto renderiza o mais rápido possível — e usar uma cerca para limitar os frames em voo. Sem limitação de frame-flight, o Present pode ter sucesso imediato em cadeias de troca de modelos invertidos, permitindo que a CPU coloque frames em fila ilimitada e aumente a latência de entrada.

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

Criação de cadeias de permuta

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

Apresentação 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, pelo que tem de usar o ID3D12CommandQueueDownLevel fornecido pelo D3D12On7 (obtido a partir da fila de comandos diretos) para efetuar a apresentação.

Fornece uma lista de comandos em aberto ao método Present do Windows 7, a qual será depois utilizada, fechada e submetida automaticamente ao dispositivo. Você deve fornecer um buffer de retorno que deve ser criado pelo aplicativo, deve ser um recurso comprometido, 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