Modelo de inversão DXGI

Windows 8 adiciona suporte para o modelo de apresentação flip e suas estatísticas atuais associadas no DXGI 1.2. Windows 8 modelo de apresentação de inversão DXGI é semelhante à Apresentação do Modo de Inversão Direct3D 9EX do Windows 7. Aplicativos de apresentação baseados em taxa de quadros ou vídeo, como jogos, podem se beneficiar mais usando o modelo de apresentação flip. Os aplicativos que usam o modelo de apresentação de inversão DXGI reduzem a carga de recursos do sistema e aumentam o desempenho. Os aplicativos também podem usar aprimoramentos de estatísticas presentes com o modelo de apresentação de inversão para controlar melhor a taxa de apresentação fornecendo comentários em tempo real e mecanismos de correção.

Comparando o modelo de inversão DXGI e o modelo BitBlt

O runtime usa os modelos de transferência de bloco de bits (bitblt) e apresentação invertido para apresentar conteúdo gráfico em monitores de exibição. A maior diferença entre os modelos de apresentação bitblt e flip é como o conteúdo do back-buffer chega ao DWM Windows 8 para composição. No modelo bitblt, o conteúdo do buffer de fundo é copiado para a superfície de redirecionamento em cada chamada para IDXGISwapChain1::P resent1. No modelo de inversão, todos os buffers traseiros são compartilhados com o DWM (Gerenciador de Janelas da Área de Trabalho). Portanto, o DWM pode compor diretamente desses buffers de fundo sem nenhuma operação de cópia adicional. Em geral, o modelo de inversão é mais eficiente. O modelo de inversão também fornece mais recursos, como estatísticas atuais aprimoradas.

Se você tiver componentes herdados que usam a GDI (Interface de Dispositivo gráfico) do Windows para gravar diretamente em um HWND , use o modelo bitblt.

As melhorias de desempenho do modelo de inversão DXGI são significativas quando o aplicativo está no modo de janela. A sequência nesta tabela e a ilustração comparam os usos de largura de banda de memória e as leituras e gravações do sistema de aplicativos em janelas que escolhem o modelo de inversão em comparação com o modelo bitblt.

Etapa Modelo BitBlt presente no DWM Modelo de inversão DXGI presente no DWM
1. O aplicativo atualiza seu quadro (Gravação)
O aplicativo atualiza seu quadro (Gravação)
2. O runtime do Direct3D copia o conteúdo da superfície para uma superfície de redirecionamento do DWM (Leitura, Gravação)
O runtime do Direct3D passa a superfície do aplicativo para o DWM
3. Após a conclusão da cópia da superfície compartilhada, o DWM renderiza a superfície do aplicativo na tela (Leitura, Gravação)
O DWM renderiza a superfície do aplicativo na tela (Leitura, Gravação)

 

ilustração de uma comparação do modelo blt e do modelo de inversão

O modelo flip reduz o uso de memória do sistema reduzindo o número de leituras e gravações pelo runtime do Direct3D para a composição de quadro em janelas pelo DWM.

Como usar o modelo de inversão DXGI

Os aplicativos Direct3D 11.1 direcionados Windows 8 usam o modelo de inversão criando a cadeia de troca com o valor de enumeração DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL definido no membro SwapEffect da estrutura DXGI_SWAP_CHAIN_DESC1. Ao definir SwapEffectcomo DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, defina também esses membros de DXGI_SWAP_CHAIN_DESC1 com os valores indicados:

  • BufferCount para um valor entre 2 e 16 para evitar uma penalidade de desempenho como resultado da espera do DWM para liberar o buffer de apresentação anterior.
  • Formatar para DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_B8G8R8A8_UNORM ou DXGI_FORMAT_R8G8B8A8_UNORM
  • Membro count da estrutura DXGI_SAMPLE_DESC que o membro SampleDesc especifica a um e o membro Quality de DXGI_SAMPLE_DESC a zero porque não há suporte para várias suavizações de exemplo (MSAA)

Se você usar DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL no Windows 7 ou no sistema operacional anterior, a criação do dispositivo falhará. Ao usar o modelo de inversão, você pode usar estatísticas presentes em tela inteira no modo de janela. O comportamento de tela inteira não é afetado. Se você passar NULL para o parâmetro pFullscreenDesc de IDXGIFactory2::CreateSwapChainForHwnd para uma cadeia de troca em janelas e definir SwapEffectcomo DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, o runtime criará um buffer back extra e girará o identificador que pertence ao buffer que se torna o buffer frontal no momento da apresentação.

Ao usar o modelo de inversão, considere estas dicas:

  • Use uma cadeia de troca de modelo de inversão por HWND. Não direcione várias cadeias de troca de modelo de inversão para o mesmo HWND.
  • Não use a cadeia de troca de modelo de inversão com a função ScrollWindow ou ScrollWindowEx da GDI. Alguns aplicativos Direct3D usam as funções ScrollWindow e ScrollWindowEx da GDI para atualizar o conteúdo da janela após a ocorrência de um evento de rolagem do usuário. ScrollWindow e ScrollWindowEx executam bitblts do conteúdo da janela na tela enquanto o usuário rola uma janela. Essas funções também exigem atualizações de modelo bitblt para conteúdo GDI e Direct3D. Os aplicativos que usam uma das funções não necessariamente exibirão o conteúdo da janela visível rolando na tela quando o aplicativo estiver no modo de janela. Recomendamos que você não use as funções ScrollWindow e ScrollWindowEx da GDI e, em vez disso, redesenhe o conteúdo GDI e Direct3D na tela em resposta à rolagem.
  • Use o modelo de inversão em um HWND que também não é direcionado por outras APIs, incluindo o modelo de apresentação bitblt DXGI, outras versões do Direct3D ou GDI. Como o modelo bitblt mantém uma cópia adicional da superfície, você pode adicionar GDI e outros conteúdos Direct3D ao mesmo HWND por meio de atualizações por etapas do Direct3D e do GDI. Quando você usa o modelo de inversão, somente o conteúdo direct3D em cadeias de troca de modelo de inversão que o runtime passa para DWM ficam visíveis. O runtime ignora todas as outras atualizações de conteúdo direct3D ou GDI do modelo bitblt.

Sincronização de quadros de aplicativos de modelo de inversão DXGI

As estatísticas atuais são informações de tempo de quadro que os aplicativos de mídia usam para sincronizar fluxos de vídeo e áudio e se recuperar de falhas de reprodução de vídeo. Os aplicativos podem usar as informações de tempo de quadro nas estatísticas atuais para ajustar a taxa de apresentação de seus quadros de vídeo para uma apresentação mais suave. Para obter as informações de estatísticas atuais, chame o método IDXGISwapChain::GetFrameStatistics para obter a estrutura DXGI_FRAME_STATISTICS . DXGI_FRAME_STATISTICS contém estatísticas sobre chamadas IDXGISwapChain1::P resent1 . Uma cadeia de troca de modelo de inversão fornece informações de estatísticas presentes nos modos de janela e de tela inteira. Para cadeias de troca de modelo bitblt no modo de janela, todos os valores de DXGI_FRAME_STATISTICS são zeros.

Para estatísticas presentes do modelo de inversão, IDXGISwapChain::GetFrameStatistics retorna DXGI_ERROR_FRAME_STATISTICS_DISJOINT nestas situações:

  • Primeira chamada para GetFrameStatistics, que indica o início de uma sequência
  • Alteração de modo: o modo em janelas para ou de tela inteira ou de tela inteira para transições de tela inteira

Os valores nos membros PresentRefreshCount, SyncRefreshCount e SyncQPCTime de DXGI_FRAME_STATISTICS têm as seguintes características:

  • PresentRefreshCount é igual a SyncRefreshCount quando o aplicativo é apresentado em cada vsync.
  • SyncRefreshCount é obtido no intervalo vsync quando o presente foi enviado, SyncQPCTime é aproximadamente o tempo associado ao intervalo vsync.

O método IDXGISwapChain::GetLastPresentCount retorna a última contagem presente, ou seja, a ID atual da última chamada IDXGISwapChain1::P resent1 bem-sucedida feita por um dispositivo de exibição associado à cadeia de troca. Essa ID atual é o valor do membro PresentCount da estrutura DXGI_FRAME_STATISTICS . Para cadeias de troca de modelo bitblt, enquanto no modo de janela, todos os valores de DXGI_FRAME_STATISTICS são zeros.

Evitando, detectando e se recuperando de falhas

Execute estas etapas para evitar, detectar e se recuperar de falhas na apresentação do quadro:

  1. Chamadas IDXGISwapChain1::P resent1 da fila (ou seja, chame IDXGISwapChain1::P resent1 várias vezes, o que faz com que eles coletem em uma fila).

  2. Crie uma estrutura de fila atual para armazenar todas as IDXGISwapChain1::P resent1 da ID atual (retornada por IDXGISwapChain::GetLastPresentCount) e valores PresentRefreshCount associados e calculados /esperados.

  3. Para detectar uma falha:

    • Chame IDXGISwapChain::GetFrameStatistics.
    • Para esse quadro, obtenha a ID atual (PresentCount) e a contagem vsync em que o sistema operacional apresentou a última imagem ao monitor (PresentRefreshCount).
    • Recupere o PresentRefreshCount esperado associado à ID atual e que você armazenou anteriormente na estrutura da fila atual.
    • Se o PresentRefreshCount real for posterior ao Esperado PresentRefreshCount, ocorrerá uma falha.
  4. Para se recuperar da falha:

    • Calcule o número de quadros a serem pulados para se recuperar da falha. Por exemplo, se a etapa 3 revelar que a contagem vsync esperada (PresentRefreshCount) para uma ID atual (PresentCount) for 5 e a contagem vsync real para a ID atual for 8, o número de quadros a serem pulados para se recuperar da falha será de três quadros.

    • Passe 0 para o parâmetro SyncInterval nesse número de chamadas para IDXGISwapChain1::P resent1 para descartar e ignorar esse número de quadros.

      Observação

      Se a falha consistir em um grande número de quadros, chame IDXGISwapChain1::P resent1 com o parâmetro Flags definido como DXGI_PRESENT_RESTART para descartar e ignorar todos os presentes em fila pendentes.

       

Aqui está um cenário de exemplo de recuperação de falhas na apresentação de quadro:

ilustração de um cenário de exemplo de recuperação de falhas na apresentação de quadro

No cenário de exemplo, você espera que o quadro A vá para a tela em uma contagem vsync de 1. Mas você realmente detecta a contagem vsync que o quadro A aparece na tela como 4. Portanto, você determina que ocorreu uma falha. Em seguida, você pode descartar três quadros, ou seja, você pode passar 0 para o parâmetro SyncInterval em três chamadas para IDXGISwapChain1::P resent1. No cenário de exemplo anterior, para se recuperar da falha, você precisa de um total de 8 chamadas IDXGISwapChain1::P resent1 . O 9º quadro fica visível de acordo com a contagem vsync esperada.

Aqui está uma linha de tempo de eventos de apresentação. Cada linha vertical representa um vsync. A direção horizontal é o tempo, que aumenta para a direita. Você pode usar a figura para imaginar como as falhas podem ocorrer.

ilustração de uma linha de tempo de eventos de apresentação

A figura ilustra essa sequência:

  1. O aplicativo é ativado no vsync, renderiza azul, chama IDXGISwapChain1::P resent1 e volta a dormir.

  2. A GPU (unidade de processamento gráfico) é ativada do ocioso, executa a renderização para azul e, em seguida, volta a dormir.

  3. O DWM acorda no próximo vsync, compõe azul em seu buffer traseiro, chama IDXGISwapChain1::P resent1 e volta a dormir.

  4. O aplicativo é ativado, renderiza verde, chama IDXGISwapChain1::P resent1 e volta a dormir.

    Observação

    O aplicativo é executado simultaneamente enquanto a GPU executa a composição de azul.

     

  5. Em seguida, a GPU renderiza verde para o aplicativo.

  6. Por fim, o DAC (conversor digital para analógico) mostra os resultados da composição do DWM no monitor no próximo vsync.

Na linha do tempo, você pode imaginar a latência das estatísticas atuais e como as falhas podem ocorrer. Por exemplo, para mostrar uma falha de DWM para a cor verde que aparece na tela, imagine ampliar a caixa verde/vermelha para que o lado direito da caixa verde/vermelho corresponda ao lado direito da caixa roxa/vermelha. Nesse cenário, o DAC mostra dois quadros de azul e, em seguida, o quadro verde. Você pode ver que essa falha ocorreu ao ler as estatísticas atuais.

Aprimorando a apresentação com o modelo de inversão, sujo retângulos e áreas roladas