Caminho de apresentação do DXGI

O DXGI fornece aos aplicativos uma metodologia de apresentação que "funciona apenas". Por exemplo, os aplicativos não são necessários para executar operações especiais para fazer a transição entre o modo de janela e o modo de tela inteira. Essa metodologia de apresentação é possível porque o DXGI e o driver de exibição em modo de usuário trabalham juntos para preservar a apresentação em combinações de Anti-Aliasing de Múltiplas Amostras (MSAA), rotação do monitor, tamanho e formato dos buffers traseiro e frontal e modos de tela cheia versus janela. Outra vantagem do DXGI é que ele permite que um adaptador de exibição tenha capacidade limitada de verificar MSAA e superfícies giradas porque o DXGI fornece uma DDI "sem estado". Em uma DDI sem estado, o driver do adaptador não é obrigado a registrar dados em chamadas DDI.

A tarefa básica da apresentação é mover dados de um back buffer renderizado para a superfície primária para visualização. Essa tarefa é executada nas diferentes situações descritas nas seções a seguir.

Modo de janela com DWM ativado

No modo com janelas no caso de DWM (Gerenciador de Janelas da Área de Trabalho), o DXGI se comunica com o DWM e abre uma exibição de um recurso compartilhado que é um destino de renderização para o produtor do DXGI e uma textura para o DWM. Esse recurso compartilhado existe além dos buffers de fundo que o aplicativo cria. O DXGI chama a função BltDXGI do driver para mover dados de qualquer um dos buffers de fundo para a superfície compartilhada. Essa operação pode exigir alongamento, conversão de cores e resolução de MSAA. No entanto, essa operação nunca requer sub-retângulos de origem e destino. Na verdade, esses sub-retângulos não podem ser expressos na chamada para BltDXGI. Essa transferência de bloco de bits (bitblt) sempre tem o sinalizador Present definido no membro Flags da estrutura DXGI_DDI_ARG_BLT à qual o parâmetro pBltData aponta. Configurar o flag Presente indica que o driver deve executar a operação de forma atômica. O driver executa a operação bitblt atomicamente para minimizar a possibilidade de rasgar enquanto o DWM lê o recurso compartilhado para composição.

Modo janela com DWM desativado

No modo de janela com o caso de DWM desligado, DXGI chama a função PresentDXGI do driver com o sinalizador Blt definido no membro Flags da estrutura DXGI_DDI_ARG_PRESENT para a qual o parâmetro pPresentData aponta. Nesta chamada PresentDXGI, o DXGI pode especificar qualquer um dos buffers de retorno criados pelo aplicativo nos membros hSurfaceToPresent e SrcSubResourceIndex de DXGI_DDI_ARG_PRESENT. Não há nenhuma superfície compartilhada adicional.

Modo de tela inteira

O caso de tela cheia é mais complicado do que o modo em janela com o DWM ativado ou desativado.

Quando o DXGI faz a transição para o modo de tela inteira, ele tenta explorar uma operação de flip para reduzir a largura de banda e obter a sincronização vertical. As seguintes condições podem impedir o uso de uma operação de inversão:

  • O aplicativo não realocou seus buffers de segundo plano de forma que corresponda à superfície primária.

  • O driver especificou que ele não processará o buffer de fundo (por exemplo, porque o buffer de fundo é girado ou é MSAA).

  • O aplicativo especificou que não pode aceitar o descarte, em tempo de execução, do conteúdo do back buffer pelo Direct3D e solicitou apenas um buffer (total) na cadeia de buffers. (Nesse caso, o DXGI aloca uma superfície traseira e uma superfície primária; no entanto, o DXGI usa a função PresentDXGI do driver com o sinalizador Blt definido.)

Quando uma das condições anteriores ocorreu, impedindo assim uma operação de inversão e uma chamada para a função PresentDXGI do driver com o sinalizador Blt configurado também não é apropriada (porque o buffer traseiro não corresponde exatamente ao buffer frontal), o DXGI aloca a superfície proxy. Essa superfície de proxy corresponde ao buffer frontal. Portanto, uma troca entre a superfície proxy e o buffer frontal passa a ser possível. Se a superfície do proxy existir, o DXGI usará a função BltDXGI do driver com o sinalizador Present zerado (0) para copiar os buffers de retaguarda do aplicativo para a superfície do proxy. Nesta chamada BltDXGI, o DXGI pode solicitar conversão, alongamento ou resolução. Em seguida, o DXGI chama a função PresentDXGI do driver com o sinalizador Flip definido no membro Flags da estrutura DXGI_DDI_ARG_PRESENT para mover os bits da superfície proxy para o scan-out.

Para notificar o driver de exibição do modo de usuário de que o driver pode recusar a verificação, o driver receberá chamadas de criação de recursos para classes opcionais e não opcionais de superfícies de verificação. As superfícies de saída opcionais são designadas pelo indicador DXGI_DDI_PRIMARY_OPTIONAL. As superfícies de verificação não opcionais não têm o sinalizador de DXGI_DDI_PRIMARY_OPTIONAL definido. Para obter mais informações sobre esses tipos de chamadas de criação de recursos, consulte Passando informações de DXGI no momento da criação do recurso.

O DXGI define o sinalizador DXGI_DDI_PRIMARY_OPTIONAL para criar todas as superfícies de buffer de fundo (ou seja, superfícies opcionais) e não define o sinalizador para nenhum buffer frontal ou superfície proxy (ou seja, superfície não opcional).

Se o DXGI_DDI_PRIMARY_OPTIONAL estiver definido para um buffer de fundo, o driver poderá definir o sinalizador DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT. Para obter mais informações sobre como definir esse sinalizador, consulte Passando informações de DXGI no momento da criação do recurso. Se o driver definir DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT para um buffer opcional, ele não terá nenhum efeito a não ser fazer com que o DXGI chame a função PresentDXGI do driver com o sinalizador Blt definido em vez de com o sinalizador Flip definido.

Se DXGI_DDI_PRIMARY_OPTIONAL não estiver definido para um buffer frontal ou a superfície de proxy, o driver ainda poderá recusar o scan-out falhando na tentativa de criar o recurso com o código de erro DXGI_DDI_ERR_UNSUPPORTED e definindo DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT.

Nota Falha na chamada de criação sem definir DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT é reservada para casos reais de falha, como falta de memória.

O DXGI explora essa metodologia de exclusão quando tenta criar uma cadeia de apresentação em tela inteira para um back buffer MSAA ou girado. Se o driver não verificar nenhum ou ambos os tipos, o driver recusará. O DXGI tentará criar uma superfície não girada, uma superfície não MSAA ou ambas até que o driver aceite a criação do recurso. Portanto, o DXGI recuará progressivamente até que a superfície não opcional corresponda exatamente ao formato de buffer frontal, à contagem de exemplos, à rotação e ao tamanho.

Se o driver optar por não usar qualquer superfície obrigatória, o DXGI ainda deve ter uma maneira de mover bits do back buffer para a superfície primária. Consequentemente, se o driver optar por não participar da saída escaneada para MSAA e rotação, o driver opta por resolver, girar ou ambos quando o DXGI chamar a função BltDXGI do driver. Quando o driver desativa, o DXGI criará uma superfície de proxy e chamará BltDXGI para mover dados dos buffers traseiros para essa superfície de proxy. O driver não deve ter motivos para recusar essa superfície de proxy porque o proxy corresponde exatamente ao buffer frontal.

As seguintes situações incomuns ocorrem quando o aplicativo não recria suas superfícies após uma transição para ou a partir do modo de tela cheia:

  • Se o aplicativo não recriar suas superfícies quando entrar no modo de tela inteira, o DXGI determinará que os buffers traseiros não correspondem ao buffer frontal, mesmo que eles realmente correspondam ao formato, ao tamanho, à rotação e à contagem de exemplos. O motivo dessa determinação é que o sistema operacional requer que os buffers de volta sejam marcados para verificação em um monitor específico quando esses buffers são criados. Os buffers de saída em janela ainda não podem ser atribuídos definitivamente a um monitor específico porque o monitor é escolhido dinamicamente quando o modo de tela cheia é ativado. Portanto, o DXGI não deve enviar esses buffers de volta para o driver para exibição (por meio de uma operação de troca). Os aplicativos desse tipo normalmente forçam o DXGI a criar a superfície de proxy.

  • Se o aplicativo não recriar seus buffers de fundo quando retornar ao modo de janela, o DXGI poderá chamar o BltDXGI ou o PresentDXGI do driver (com blt definido) para executar um bitblt em uma superfície que foi criada anteriormente para uma operação de inversão. Essa situação não deve ser um problema, mas é mencionada aqui para fins de integridade. Observe que o DXGI sempre destrói a superfície do proxy quando o aplicativo faz a transição para o modo de janela.

Além disso, observe que os aplicativos podem redimensionar seus buffers de fundo dinamicamente enquanto os aplicativos estão no modo de tela inteira. Essa ação faz com que a lógica descrita nas situações anteriores ocorra novamente. Portanto, a superfície de proxy pode ser criada e destruída, e recusar pode ou não ser necessário ao longo do tempo, mesmo que o aplicativo permaneça no modo de tela inteira. O aplicativo também pode transferir sua saída para outro monitor dinamicamente sem sair do modo de tela inteira. Portanto, o aplicativo incorre em um retorno para o modo BitBlt porque os back buffers do aplicativo foram marcados para um monitor diferente.

Por fim, você deve estar ciente da situação que ocorre em relação aos buffers de fundo do MSAA se o driver não recusar a visualização do MSAA. Nessa situação, o driver opta pela visualização do MSAA. Portanto, o DXGI intercala o buffer de fundo MSAA e o buffer frontal MSAA por meio de operações de inversão e executa uma operação de resolução pelo que é equivalente ao DAC (conversor digital para analógico). Nessa situação, o aplicativo pode redimensionar seus buffers de fundo dinamicamente enquanto estiver no modo de tela inteira, o que força o DXGI a alternar para chamar a função BltDXGI do driver. Como as características MSAA do buffer traseiro e do buffer frontal ainda correspondem, o DXGI especificará que o driver execute um bitblt elástico não resolvido, possivelmente convertido por cores. Em seguida, o driver deve replicar, sem resolver, multiamostras para o buffer frontal, o que é necessário se um driver optar por exibir o MSAA.