Para obter melhor desempenho, use o modelo de inversão DXGI

Este tópico fornece diretrizes para desenvolvedores sobre como maximizar o desempenho e a eficiência na pilha de apresentações em versões modernas do Windows. Ele continua onde o modelo de inversão de DXGI, DirectX 12: Modos de Apresentação em Windows 10 (vídeo)e Aprimoramentos de Apresentação em Windows 10: Uma Aparência Antecipada (vídeo) parou.

Chamada para ação

Se você ainda estiver usando DXGI_SWAP_EFFECT_DISCARD ou DXGI_SWAP_EFFECT_SEQUENTIAL (também conhecido como o modelo "blt" presente), é hora de parar!

Mudar para DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ou DXGI_SWAP_EFFECT_FLIP_DISCARD (também conhecido como o modelo flip) dará melhor desempenho, menor uso de energia e fornecerá um conjunto mais rico de recursos. (Consulte DXGI_SWAP_EFFECT enumeração para obter mais informações sobre esses valores.)

Os presentes de modelo flip vão tão longe quanto tornar o modo em janelas efetivamente equivalente ou melhor quando comparado ao modo clássico "exclusivo de tela inteira". Na verdade, talvez você queira reconsiderar se seu aplicativo realmente precisa de um modo exclusivo de tela inteira, já que os benefícios de uma janela sem bordas do modelo flip incluem a troca de Alt-Tab mais rápida e uma melhor integração com os recursos de exibição modernos.

Por que agora? Antes da Atualização de abril de 2018, os presentes do modelo blt poderiam resultar em danos visíveis quando usados em configurações de GPU híbrida, geralmente encontradas em laptops high-end (consulte KB 3158621). Na Atualização de abril de 2018, essa ruptura foi corrigida, ao custo de algum trabalho adicional. Se você estiver fazendo presentes blt em altas taxas de quadros entre GPUs híbridas, especialmente em altas resoluções, como 4K, esse trabalho adicional poderá afetar o desempenho geral. Para manter o melhor desempenho nesses sistemas, alterne do blt para o modelo de lançamento atual. Além disso, considere reduzir a resolução de sua cadeia de troca, especialmente se não for o ponto principal de interação do usuário (como geralmente acontece com janelas de visualização de VR).

Uma breve história

O que é o modelo de inversão? Qual é a alternativa?

Antes do Windows 7, a única maneira de apresentar o conteúdo do D3D era "blt" ou copiá-lo para uma superfície que pertencesse à janela ou tela. Começando com o efeito de troca FLIPEX da D3D9 e chegando ao DXGI por meio do efeito de troca de FLIP_SEQUENTIAL em Windows 8, desenvolvemos uma maneira mais eficiente de colocar o conteúdo na tela compartilhando-o diretamente com o compositor da área de trabalho, com cópias mínimas. Consulte Modelo de inversão de DXGI para obter uma visão geral de alto nível da tecnologia.

Essa otimização é possível graças ao DWM (Gerenciador de Janelas da Área de Trabalho), que é o compositor que conduz a área de trabalho do Windows.

Quando devo usar o modelo blt?

Há uma parte da funcionalidade que o modelo de inversão não fornece: a capacidade de ter várias APIs diferentes produzindo conteúdo, que todas se juntam no mesmo HWND, de acordo com o presente. Um exemplo disso seria usar d3D para desenhar uma tela de fundo de janela e, em seguida, o GDI do Windows para desenhar algo na parte superior, ou usando duas APIs gráficas diferentes, ou duas swapchains da mesma API, para produzir quadros alternados. Se você não precisar de interoperabilidade no nível do HWND entre componentes gráficos, não precisará do modelo blt.

Há uma segunda parte da funcionalidade que não foi fornecida no design original do modelo de inversão, mas está disponível agora, que é a capacidade de apresentar em uma taxa de quadros não suportada. Para um aplicativo que usa o intervalo de sincronização 0, não recomendamos alternar para o modelo de inversão, a menos que a API IDXGIFactory5::CheckFeatureSupport esteja disponível e relata o suporte para DXGI_FEATURE_PRESENT_ALLOW_TEARING. Esse recurso é quase onipresente em versões recentes de Windows 10 e em hardware moderno.

DirectFlip

Se você assistiu DirectX 12: Modos de Apresentação no Windows 10, verá falar sobre "Flip Direto" e "Flip Independente". Essas são otimizações habilitadas para aplicativos que usam swapchains de modelo de inversão. Dependendo da configuração de janela e buffer, é possível ignorar totalmente a composição da área de trabalho e enviar diretamente quadros de aplicativo para a tela, da mesma forma que a tela inteira exclusiva faz.

Atualmente, essas otimizações podem se envolver em um dos três cenários, em ordem de aumento da funcionalidade:

  1. DirectFlip: os buffers de troca correspondem às dimensões da tela e a região do cliente da janela cobre a tela. Em vez de usar a cadeia de troca DWM para exibir na tela, a cadeia de troca do aplicativo é usada.
  2. DirectFlip com adaptadores de painel: a região do cliente da janela cobre a tela e os buffers de troca estão dentro de algum fator de dimensionamento dependente de hardware (por exemplo, 0,25x a 4x) da tela. O hardware de verificação de GPU é usado para dimensionar o buffer enquanto o envia para a exibição.
  3. DirectFlip com MPO (sobreposição de vários planos): seus buffers de troca estão dentro de algum fator de dimensionamento dependente de hardware das dimensões da janela. O DWM é capaz de reservar um plano de verificação de hardware dedicado para seu aplicativo, que é verificado e potencialmente estendido para uma sub-região combinada alfa da tela.

Com o modelo de inversão em janelas, o aplicativo pode consultar o suporte de hardware para diferentes cenários do DirectFlip e implementar diferentes tipos de dimensionamento dinâmico por meio do uso de IDXGIOutput6::CheckHardwareCompositionSupport. Uma ressalva a ter em mente é que, se os adaptadores de painel forem utilizados, é possível que o cursor sofra efeitos colaterais de alongamento, o que é indicado por meio de DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED.

Depois que a cadeia de troca tiver sido "DirectFlipped", o DWM poderá ir para o sono e só acordar quando algo mudar fora do aplicativo. Os quadros do aplicativo são enviados diretamente para a tela, independentemente, com a mesma eficiência que a exclusiva de tela inteira. Este é o "Flip Independente" e pode se envolver em todos os cenários acima. Se outros conteúdos da área de trabalho estiverem na parte superior, o DWM poderá fazer a transição direta de volta para o modo composto, "redigir inversamente" o conteúdo sobre o aplicativo antes de invertê-lo ou aproveitar o MPO para manter o modo de inversão independente.

Confira a ferramenta PresentMon para obter informações sobre qual das opções acima foi usada.

O que mais há de novo no modelo flip?

Além das melhorias acima, que se aplicam a swapchains padrão sem nada especial, há vários recursos disponíveis para aplicativos de modelo flip usarem:

  • Diminuindo a latência usando DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT. Quando estiver no modo Flip Independente, você poderá obter até um quadro de latência em versões recentes do Windows, com fallback normal ao mínimo possível quando composto.
    • Advertência: houve um problema que deu um mínimo de dois quadros de latência na Atualização de Aniversário do Windows 10 e anterior. Confira este tópico do fórum para obter mais informações. Isso foi corrigido na Atualização do Criador de Outono.
  • DXGI_SWAP_EFFECT_FLIP_DISCARD habilita um modo de "composição inversa" de inversão direta, o que resulta em menos trabalho geral para exibir a área de trabalho. O DWM pode rabiscar nos buffers de aplicativo e enviá-los para a tela, em vez de executar uma cópia completa em seus próprios swapchains.
  • DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING pode habilitar latência ainda menor do que o objeto de espera, mesmo em uma janela em sistemas com suporte à sobreposição de vários planos.
  • Os aplicativos têm controle sobre o dimensionamento de conteúdo que ocorre durante o redimensionamento da janela, usando a propriedade DXGI_SCALING definida durante a criação da cadeia de troca.
  • O conteúdo em formatos HDR (R10G10B10A2_UNORM ou R16G16B16A16_FLOAT) não é fixado, a menos que seja composto para uma área de trabalho SDR.
  • As estatísticas atuais estão disponíveis no modo de janela.
  • Há maior compatibilidade com o modelo de aplicativo UWP (Plataforma Universal do Windows) e o DX12, pois eles só são compatíveis com o modelo de inversão.

O que eu tenho que fazer para usar o modelo de inversão?

Os swapchains de modelo flip têm alguns requisitos adicionais sobre as cadeiras de troca blt:

  1. A contagem de buffers deve ser pelo menos 2.
  2. Depois de Apresentar chamadas, o buffer traseiro precisa ser explicitamente vinculado ao contexto imediato D3D11 antes que ele possa ser usado novamente.
  3. Depois de chamar SetFullscreenState, o aplicativo deve chamar ResizeBuffers antes de Apresentar.
  4. Não há suporte para swapchains msaa (anti-aliasing multisample) diretamente no modelo flip, portanto, o aplicativo precisará fazer um resolve MSAA antes de emitir o Presente.

Como escolher as resoluções de renderização e apresentação corretas

O padrão tradicional para aplicativos no passado foi fornecer ao usuário uma lista de resoluções para escolher quando o usuário selecionar o modo de tela inteira exclusivo. Com a capacidade de exibições modernas para começar perfeitamente a dimensionar conteúdo, considere fornecer aos usuários a capacidade de escolher uma resolução de renderização para dimensionamento de desempenho, independente de uma resolução de saída e até mesmo no modo de janela. Além disso, os aplicativos devem aproveitar IDXGIOutput6::CheckHardwareCompositionSupport para determinar se precisam dimensionar o conteúdo antes de apresentá-lo ou se devem permitir que o hardware faça o dimensionamento para eles.

Seu conteúdo pode precisar ser migrado de uma GPU para outra como parte da operação atual ou de composição. Isso geralmente é verdadeiro em laptops com várias GPUs ou sistemas com GPUs externas conectadas. À medida que essas configurações ficam mais comuns e, à medida que as exibições de alta resolução se tornam mais comuns, o custo de apresentar uma cadeia de troca de resolução completa aumenta. Se o destino da sua cadeia de troca não for o ponto principal de interação do usuário, como é frequentemente o caso com títulos VR que apresentam uma visualização 2D da cena VR em uma janela secundária, considere usar uma cadeia de troca de resolução mais baixa para minimizar a quantidade de largura de banda que precisa ser transferida entre diferentes GPUs.

Outras considerações

A primeira vez que você solicita que a GPU escreva no buffer de back swapchain é a hora em que a GPU parará aguardando o buffer ficar disponível. Quando possível, atrase esse ponto o mais longe possível no quadro.