Fila de inversão de hardware
Este artigo descreve o recurso de fila de inversão de hardware com suporte a partir do Windows 11 (WDDM 3.0). Uma fila de inversão de hardware permite que vários quadros futuros sejam enviados para a fila do controlador de exibição. A CPU e partes da GPU podem fazer a transição para estados de menor consumo de energia enquanto o controlador de vídeo está processando vários quadros em fila, melhorando a eficiência energética de cenários de reprodução de vídeo em hardware capaz.
Modelo de fila de inversão pré-WDDM 3.0
Muitos controladores de vídeo modernos oferecem suporte à capacidade de enfileirar vários quadros que devem ser exibidos em uma sequência. A partir do WDDM 2.1, o sistema operacional suporta várias solicitações de substituição de inversão pendentes que devem ser apresentadas no próximo VSync. O driver de miniporta de exibição (KMD) indica esse suporte por meio do valor MaxQueuedMultiPlaneOverlayFlipVSync no DXGK_DRIVERCAPS. Esse recurso é útil para reduzir a latência em cenários de jogos com alta taxa de quadros em que vários quadros são renderizados sequencialmente com intervalo 0, com a intenção de exibir apenas o quadro mais recente.
Em cenários de reprodução de vídeo, o conteúdo de vários quadros futuros a serem exibidos sequencialmente é conhecido com antecedência e pode ser enfileirado para a GPU. Essa fila avançada permite que a CPU entre em um estado de baixo consumo de energia enquanto os quadros enfileirados são processados, resultando em uma economia substancial de energia. No entanto, antes do WDDM 3.0, não havia nenhum mecanismo para o sistema operacional enviar mais de um quadro que precisa permanecer na tela por pelo menos um intervalo VSync sem intervenção adicional da CPU. A seção Fila de inversão de hardware básica apresenta uma solução onde permite que a CPU entre em um estado de baixo consumo de energia e descarregue o processamento de quadros em fila para a GPU.
Em cenários de jogos anteriores ao WDDM 3.0, depois que a GPU terminar de renderizar a cena para o buffer de fundo da cadeia de troca, há uma viagem de ida e volta à CPU para enviar a solicitação e apresentar o conteúdo do quadro à tela. Para cargas de trabalho pesadas de GPU que terminam perto do VSync, essa viagem de ida e volta pode fazer com que os quadros sejam atrasados e percam o tempo de destino pretendido, resultando em falhas de quadro observáveis. A seção Advanced hardware flip queue introduz um mecanismo para evitar essa viagem de ida e volta da CPU e apresentar quadros concluídos na tela com baixa latência. A fila de inversão de hardware avançada requer que a funcionalidade básica de inversão de hardware e a funcionalidade de estágio 2 de agendamento de hardware da GPU estejam presentes.
Fila de inversão de hardware básica
O diagrama a seguir ilustra o caso de apresentar três quadros, cada um permanecendo na tela por um intervalo VSync.
O padrão de preenchimento no diagrama mostra as vezes em que o processamento de fila de inversão de software Dxgkrnl e threads de aplicativos precisam ser ativados para fazer o trabalho da CPU. Em cada VSync, o controlador de vídeo tem que emitir uma notificação de CPU para o sistema operacional sobre a inversão concluída, e o sistema operacional precisa enviar a próxima solicitação de inversão. O aplicativo também tem que acordar em cada VSync e consultar as estatísticas de apresentação para eventualmente saber quando o último quadro do lote de três é exibido.
DDIs de fila de inversão de hardware que podem enviar vários quadros futuros para a fila do controlador de vídeo estão disponíveis a partir do WDDM 3.0. Como dito anteriormente, esse mecanismo permite que a CPU e partes da GPU façam a transição para estados de menor consumo de energia enquanto o controlador de vídeo está processando vários quadros enfileirados. Essa transição melhora a eficiência energética de cenários de reprodução de vídeo em hardware capaz.
O diagrama a seguir ilustra a arquitetura proposta.
Com a abordagem de fila de inversão de hardware, os componentes da CPU do aplicativo e do Dxgkrnl ficam totalmente ociosos por dois intervalos VSync entre os tempos v2 e v4, permitindo que a CPU entre em um estado de baixo consumo de energia. A CPU é notificada somente quando o quadro N+2 que o aplicativo solicitou uma espera é concluído.
Fila de inversão de hardware avançada
Em cenários de jogos anteriores ao WDDM 3.0, depois que a GPU terminar de renderizar a cena para o buffer de fundo da cadeia de troca, há uma viagem de ida e volta à CPU para enviar a solicitação e apresentar o conteúdo do quadro à tela. O diagrama a seguir mostra esse cenário.
O custo dessa viagem de ida e volta pode fazer com que os quadros percam seu destino se a renderização for concluída muito perto do VSync, conforme mostrado no diagrama a seguir.
Alguns controladores de vídeo suportam nativamente condições de espera que permitem que a tela envie a solicitação de inversão assim que a GPU terminar de renderizar o quadro sem a viagem de ida e volta da CPU. Como a fila de inversão de hardware pode enviar o quadro N concluído para a exibição sem uma viagem de ida e volta da CPU, ela pode evitar quadros perdidos, conforme mostrado no diagrama a seguir.
O restante deste artigo discute o recurso básico de fila de inversão de hardware.
Suporte a DDI
As seguintes DDIs foram adicionadas para oferecer suporte ao recurso da fila de inversão de hardware.
Verificar a disponibilidade de recursos
A fila de inversão de hardware requer a negociação de habilitar/desabilitar o sistema operacional. Um KMD que ofereça suporte à fila de inversão de hardware deve primeiro chamar o DXGKCB_QUERYFEATURESUPPORT durante o início do dispositivo com um FeatureId de DXGK_FEATURE_HWFLIPQUEUE para determinar se o sistema operacional permite que a fila de inversão de hardware seja habilitada.
A fila de inversão de hardware pode ser usada apenas se o retorno de chamada for bem-sucedido e se Habilitar estiver definido como TRUE.
Um KMD pode usar o seguinte código de amostra durante os estágios experimentais e de fila de inversão de hardware.
DXGKARGCB_QUERYFEATURESUPPORT HwFlipQueueEnabledArgs = {};
HwFlipQueueEnabledArgs.DeviceHandle = DeviceHandle;
HwFlipQueueEnabledArgs.FeatureId = DXGK_FEATURE_HWFLIPQUEUE;
HwFlipQueueEnabledArgs.DriverSupportState = DXGK_FEATURE_SUPPORT_EXPERIMENTAL;
if (!NT_SUCCESS(pDxgkInterface->DxgkCbQueryFeatureSupport(&HwFlipQueueEnabledArgs)) ||
!HwFlipQueueEnabledArgs.Enabled)
{
// Disable hardware flip queue because the OS didn't allow it.
}
else
{
// Enable hardware flip queue because the OS allowed it.
}
Durante a ativação do driver, mesmo que seja possível habilitar a fila de inversão de hardware sem habilitar o agendamento de hardware da GPU, essa combinação não é oficialmente suportada. Atualmente, o Windows exige que o agendamento de hardware da GPU esteja habilitado para que a fila de inversão de hardware básica seja habilitada em drivers lançados oficialmente.
Indicando recursos de enfileiramento de hardware
O MaxHwQueuedFlips foi adicionado ao DXGK_DRIVERCAPS para indicar o suporte à fila de inversão de hardware. Se o SO permitir suporte a fila de inversão de hardware conforme descrito anteriormente, um KMD que ofereça suporte a uma fila de inversão de hardware deverá definir MaxHwQueuedFlips para um valor maior que 1. Quando o MaxHwQueuedFlips é maior que 1, o KMD indica que o hardware de exibição suporta até MaxHwQueuedFlips quadros futuros que podem ser enfileirados e exibidos para um determinado VidPnSource na GPU. O sistema operacional respeita as restrições fornecidas pelo driver sobre o tipo de flips que podem ser enfileirados com antecedência.
O HwQueuedFlipCaps também foi adicionado ao DXGK_DRIVERCAPS. Este membro está atualmente reservado para uso do sistema; os motoristas não devem usá-lo.
Tempo de inversão e formato de carimbo de data/hora de destino
Quando o sistema operacional envia uma solicitação de inversão para a fila de inversão de hardware, ele também envia o tempo de inversão de destino. A inversão pode ser tornada visível para o usuário depois que o tempo de inversão alvo é atingido.
O sistema operacional usa as unidades do contador de relógio da CPU, obtidas do KeQueryPerformanceCounter, para passar o tempo do quadro de destino e interpretar o tempo real do quadro.
Enviando inversões em fila
A estrutura DXGKARG_SETVIDPNSOURCEADDRESSWITHMULTIPLANEOVERLAY3 , que é passada para a função de retorno de chamada DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 do KMD, foi modificada da seguinte forma para permitir o envio de inversões em fila:
Os três membros a seguir foram adicionados à estrutura DXGK_SETVIDPNSOURCEADDRESS_OUTPUT_FLAGS do OutputFlags. Consulte casos de repetição e falha de DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 para obter detalhes sobre esses membros.
- HwFlipQueueDrainNeeded
- HwFlipQueueDrainAllPlanes
- HwFlipQueueDrainAllSources
Um membro TargetFlipTime foi adicionado. O TargetFlipTime descreve o tempo de inversão de destino em unidades QPC. Quando o relógio atinge esse valor, o quadro pode ser enviado para a tela enquanto honra o VSync e remove sinalizadores. Na presença de inversões pendentes anteriormente enfileiradas, o sistema operacional garante que, para cada plano MPO referenciado pela solicitação de inversão, o TargetFlipTime seja maior ou igual a qualquer um dos tempos de inversão de destino pendentes para este plano. Em outras palavras, pode haver uma sequência de inversão com os mesmos ou crescentes carimbos de data/hora, mas não pode haver uma sequência que volte no tempo.
casos de repetição e falha de DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3
Falha ao enfileirar a solicitação para o hardware devido a inversões pendentes
Há vários casos especiais que podem impedir o KMD de enfileirar uma solicitação de inversão enquanto outras solicitações de inversão estão pendentes. Nesses casos, o KMD deve retornar STATUS_RETRY de DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 e definir o HwFlipQueueDrainNeeded igual a 1. O sistema operacional tentará enviar a solicitação de flip novamente depois que todas as inversões pendentes nos aviões afetados pela inversão forem concluídas e quando o tempo alvo for atingido.
Em alguns casos, o hardware de exibição pode exigir a conclusão de inversões pendentes em todos os planos, não apenas naqueles referenciados pela solicitação de inversão recebida. Nesse caso, os sinalizadores HwFlipQueueDrainNeeded e HwFlipQueueDrainAllPlanes devem ser definidos como 1 e o KMD deve retornar STATUS_RETRY.
Da mesma forma, o hardware de exibição pode exigir a conclusão de inversões pendentes em todas as fontes VidPn para realocar recursos internos, caso em que os sinalizadores HwFlipQueueDrainAllSources e HwFlipQueueDrainNeeded devem ser definidos e KMD deve retornar STATUS_RETRY.
Além disso, o KMD pode indicar ao sistema operacional se o reenvio deve ser feito no dispositivo IRQL (PrePresentNeeded definido como 0) ou se o sistema operacional deve executar essa chamada em PASSIVE_LEVEL (PrePresentNeeded definido como 1). Se o KMD ainda retornar STATUS_RETRY mesmo que não haja mais inversões pendentes nesse VidPnSourceId, essa condição será tratada como uma falha de parâmetro inválido.
É importante que o valor de MaxHwQueuedFlips ainda reflita o número máximo de inversões de alteração simples somente de endereço que podem ser enfileiradas para um plano MPO. O mecanismo STATUS_RETRY deve ser usado para solicitações de inversão mais complexas que não podem ser profundamente enfileiradas, como as alterações de configuração de plano.
Falha de parâmetro inválido
No modelo de fila de inversão de hardware, o processamento do sistema operacional de solicitações de inversão com falha foi retrabalhado para permitir uma melhor depuração. Quando o KMD não consegue processar uma solicitação de inversão, ele deve retornar STATUS_INVALID_PARAMETER de DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3. Dependendo das configurações do sistema operacional, o sistema operacional executa uma das seguintes ações:
- Quebra do Depurador de Kernel e verificação de bugs: Esse comportamento geralmente é ativado em compilações de desenvolvimento/pré-lançamento para melhor capacidade de depuração à medida que a condição de falha ocorre.
- Despejo de kernel em tempo real seguido por um TDR: o comportamento do usuário final de varejo.
Especificando o comportamento de interrupção do VSync
Para obter economia de energia em cenários de inversão em fila, o sistema operacional geralmente suspende interrupções regulares do VSync para manter a CPU em um estado de baixo consumo de energia. No entanto, algumas inversões são marcadas como exigindo que uma interrupção seja acionada para que o aplicativo observe o lote de presentes concluídos e coloque mais trabalho na fila. Há também casos em que os aplicativos solicitam o despertar em cada interrupção do VSync, independentemente de haver solicitações de flip pendentes. E, inversamente, em um sistema completamente ocioso, as interrupções do VSync são suspensas até que uma nova atividade de apresentação ou ouvintes do VSync apareçam.
Para lidar com todos esses casos, a seguinte estrutura de retorno de chamada e retorno de chamada de driver foi introduzida:
O KMD fornece um ponteiro para a sua função DxgkDdiSetInterruptTargetPresentId no DRIVER_INITIALIZATION_DATA
O sistema operacional chama o DxgkDdiSetInterruptTargetPresentId para especificar o PresentId de destino que deve resultar em uma interrupção do VSync gerada quando a inversão correspondente for concluída. Essa função é chamada no nível de interrupção do dispositivo (DIRQL) para sincronizar com DxgkDdiSetVidPnSourceAddress e a interrupção do VSync.
Interação com o DxgkDdiControlInterrupt
Quando as interrupções do VSync são totalmente desativadas por meio do DxgkDdiControlInterrupt/DxgkDdiControlInterrupt2/DxgkDdiControlInterrupt3, elas permanecem desabilitadas independentemente do valor PresentId da interrupção de destino. O KMD é necessário para armazenar o ID presente de interrupção de destino mais recente para que possa ser honrado assim que o VSync for habilitado novamente.
Quando as interrupções do VSync são ativadas pelo DxgkDdiControlInterruptXxx, o ID presente de interrupção de destino (pSetInterruptTargetPresentId) fornece um controle granulado mais fino da seguinte maneira:
Quando o ID presente de destino é definido como UINT64_MAX, nenhuma interrupção do VSync é necessária até que o ID presente de destino seja alterado novamente. As interrupções do VSync estão desabilitadas, mas o KMD é necessário para implementar o comportamento DXGK_VSYNC_DISABLE_KEEP_PHASE e reativar interrupções.
Quando o ID presente de destino é definido como 0, interrupções são necessárias para cada VSync.
Para qualquer outro valor de ID presente, as interrupções serão geradas se o PresentId atualmente verificado >= InterruptTargetPresentId.
Quando vários planos MPO estão disponíveis, a interrupção do VSync deve ser acionada se qualquer um dos planos exigir.
Desativação do VSync em 2 estágios com o DxgkDdiSetInterruptTargetPresentId
Se a chamada do sistema operacional para DxgkDdiSetInterruptTargetPresentId definir um InterruptTargetPresentId em um plano que levaria à desativação total do VSync neste VidPnSource (ou seja, esse plano foi o último plano que manteve o VSync habilitado, e agora esse plano também está desabilitando o VSync), o KMD deverá desabilitar as interrupções do VSync, mas manter a fase VSync no hardware habilitado (DXGK_VSYNC_DISABLE_KEEP_PHASE). Após um determinado período de tempo (normalmente equivalente a dois períodos VSync), o sistema operacional seguirá com uma chamada para DxgkDdiControlInterruptXxx com DXGK_VSYNC_DISABLE_NO_PHASE. Essa chamada garante que o KMD tenha a chance de desabilitar a fase VSync e os relógios VSync para economizar energia máxima e manter a paridade de desempenho com sistemas de fila de inversão que não sejam de hardware.
Cancelamento de inversão enfileirada
Em casos como transições de estado de tela inteira ou saídas de aplicativos, futuras inversões enfileiradas podem precisar ser canceladas. Para lidar com esses casos, foi introduzido o seguinte retorno de chamada de driver e estruturas relacionadas:
O KMD fornece um ponteiro para a sua função DxgkDdiCancelFlips no DRIVER_INITIALIZATION_DATA.
O sistema operacional especifica o intervalo de inversões enfileiradas a serem canceladas quando chama a DxgkDdiCancelFlips e o KMD relata ao sistema operacional o intervalo de inversões que foi capaz de cancelar de forma síncrona.
O exemplo a seguir ilustra a mecânica e o caso síncrono de cancelamento de inversão em um único plano. (O sistema operacional não oferece suporte ao cancelamento assíncrono no Windows 11, versão 22H2.) Imagine que as seguintes inversões estão sendo enfileiradas para a fila de inversão de hardware:
- PresentId N
- tempo t0 PresentId N+1
- tempo t1 PresentId N+2
- tempo t2 PresentId N+3
- tempo t3 PresentId N+4
- tempo t4
Depois, o sistema operacional decide cancelar as inversões N+2, N+3 e N+4, então ele chama DxgkDdiCancelFlips com o PresentIdCancelRequested definido como N+2.
Quando o KMD inspeciona o estado da fila de inversão de hardware, ele determina que:
- O Flip N+2 já foi enviado para o hardware de exibição e não pode ser cancelado no momento da chamada.
- Os flips N+3 e N+4 podem ser removidos de forma síncrona da fila de inversão de hardware sem efeitos colaterais.
Como resultado, o KMD define PresentIdCancelled como N+3 e conclui N+2 como de costume.
O sistema operacional marca N+3 e N+4 como cancelados, e trata N, N+1, N+2 como estando em voo. Quando as próximas interrupções do VSync forem geradas, o log da fila de inversão indicará os carimbos de data/hora para N, N+1 e N+2 como de costume.
O intervalo de inversões canceladas de forma síncrona deve ser contínuo e, quando não é zero, presume-se que inclui o último ID presente submetido ao KMD. Em outras palavras, não pode haver lacunas dentro de ambos os intervalos de inversão síncronos cancelados.
Cancelando inversões intertravadas em vários planos
Uma inversão intertravada é enviada chamando DxgkDdiSetVidPnSourceAddress com vários planos e PresentIds. O contrato entre o sistema operacional e o KMD é o seguinte:
- O conjunto de planos deve ser tornado visível no mesmo VSync.
- O hardware de vídeo não tem permissão para exibir apenas um subconjunto desses planos em um VSync e o restante no próximo.
No modelo de fila de inversão de hardware, essas inversões intertravadas são canceladas passando vários planos e PresentIds na chamada para DxgkDdiCancelFlips. O conjunto de planos passados nesses casos deve corresponder a uma solicitação de inversão intertravada pendente e a decisão do KMD para todos os PresentIds intertravados deve ser a mesma:
- Não cancelar ou
- Cancelar de forma síncrona
O DxgkDdiCancelFlips é chamado no nível de interrupção do dispositivo (DIRQL) para sincronizar com o DxgkDdiSetVidPnSourceAddress e a interrupção do VSync.
Obtendo estatísticas atuais para inversões enfileiradas
Como a abordagem da fila de inversão de hardware é para evitar a ativação da CPU em cada VSync, precisa haver um mecanismo para reter os tempos de exibição de quadros para as últimas inversões enfileiradas.
Os drivers gráficos que oferecem suporte à fila de inversão de hardware devem gravar informações no buffer de log da fila de inversão fornecido pelo sistema operacional para cada inversão concluída ou cancelada para um determinado plano MPO para cada VidPnSource ativo.
O sistema operacional garante fornecer o ponteiro de log da fila de inversão (em uma chamada para DxgkDdiSetFlipQueueLogBuffer) antes da primeira chamada DxgkDdiSetVidPnSourceAddress para um determinado plano MPO para cada VidPnSource ativo. O sistema operacional tem permissão para destruir o buffer de log da fila de inversão quando ela não tiver solicitações pendentes. Nesse caso, ele fornecerá um novo ponteiro de log antes da próxima chamada DxgkDdiSetVidPnSourceAddress . O log da fila de inversão é circular. Depois que a entrada [NumberOfEntries-1] for gravada, a próxima entrada de log será [0].
Depois que um lote de inversões enfileiradas é concluído, o KMD deve garantir que o log da fila de inversão para as inversões concluídas seja atualizado no início desses dois pontos a tempo:
- Um manipulador de interrupção do VSync para uma inversão que exigia que uma interrupção fosse acionada.
- Em resposta a uma solicitação explícita DxgkDdiUpdateFlipQueueLog do sistema operacional.
DDIs de log de fila de inversão
O seguinte retorno de chamada relacionado ao log de fila de inversão e estruturas associadas foram adicionados:
O KMD fornece um ponteiro para suas funções no DRIVER_INITIALIZATION_DATA.
Atualizações da estrutura de interrupção do VSync
As seguintes alterações foram feitas na estrutura DXGKARGCB_NOTIFY_INTERRUPT_DATA para implementar interrupções do VSync no modelo de fila de inversão de hardware:
- O valor de enumeração DXGK_INTERRUPT_CRTC_VSYNC_WITH_MULTIPLANE_OVERLAY3 foi adicionado como InterruptType.
- A estrutura CrtcVSyncWithMultiPlaneOverlay3 foi adicionada à união. A semântica de CrtcVSyncWithMultiPlaneOverlay3 é semelhante à estrutura CrtcVSyncWithMultiPlaneOverlay2 existente, exceto que, em vez de um único PresentId concluído para cada plano, CrtcVSyncWithMultiPlaneOverlay3.pMultiPlaneOverlayVSyncInfo indica o intervalo de PresentIds não relatados anteriormente do log da fila de inversão.
- A estrutura DXGK_MULTIPLANE_OVERLAY_VSYNC_INFO3 foi adicionada para o membro pMultiPlaneOverlay3 do CrtcVSyncWithMultiPlaneOverlay3.
Usando o diagrama de exemplo de Fila de inversão de hardware básico novamente:
Suponha que FirstFreeFlipQueueLogEntryIndex foi definido como 40 no momento em que a inversão N foi enviada e, em seguida, N, N+1e N+2 presentes foram concluídos.
Depois que uma configuração de plano único conclui três PresentIds N, N+1 e N+2 nos respectivos tempos v2, v3, v4, o KMD gravou três novas entradas em seu buffer de log de fila de inversão com índices 40, 41 e 42. O KMD relata um valor FirstFreeFlipQueueLogEntryIndex de 43 na estrutura CrtcVSyncWithMultiPlaneOverlay3. O sistema operacional observa que FirstFreeFlipQueueLogEntryIndex mudou de 40 para 43 e lê as entradas de log 40, 41 e 42. O KMD precisa definir os próximos valores de buffer de log de fila de inversão da seguinte maneira:
VidPnTargetId: mesmo significado que em CrtcVSyncWithMultiPlaneOverlay2
PhysicalAdapterMask: mesmo significado que em CrtcVSyncWithMultiPlaneOverlay2
MultiPlaneOverlayVSyncInfoCount = 1
pMultiPlaneOverlayVSyncInfo[0].LayerIndex = 0
pMultiPlaneOverlayVSyncInfo[0].PrimeiroFreeFlipQueueLogEntryIndex = 43
LogBufferAddressForPlane0[40].PresentId = N
LogBufferAddressForPlane0[40].PresentTimestamp = v2
LogBufferAddressForPlane0[41].PresentId = N+1
LogBufferAddressForPlane0[41].PresentTimestamp = v3
LogBufferAddressForPlane0[42].PresentId = N+2
LogBufferAddressForPlane0[42].PresentTimestamp = v4
Solicitação explícita de atualização de log de fila de inversão
Há casos em que o sistema operacional precisa obter informações sobre o último lote completo de inversões sem ter que esperar pela interrupção do VSync. Nesses casos, o sistema operacional faz uma chamada explícita para DxgkDdiUpdateFlipQueueLog, solicitando que o KMD leia a sua estrutura de dados de hardware de exibição proprietária e grave informações de inversão passadas no log de fila de inversão. A semântica do log é a mesma descrita anteriormente, a única alteração é que o FirstFreeFlipQueueLogEntryIndex é retornado ao sistema operacional fora da interrupção do VSync.
O DxgkDdiUpdateFlipQueueLog é chamado no nível de interrupção do dispositivo (DIRQL) e está na mesma classe de sincronização que a DDI DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3.
Alterações no modo de exibição e transições de energia na presença de uma inversão enfileirada na fila de inversão de hardware
O Dxgkrnl garante que as inversões já enfileiradas na fila de inversão de hardware sejam concluídas ou canceladas antes de iniciar uma mudança de modo ou desligar o monitor.
Mapeando solicitações de apresentação para carimbos de data/hora da fila de inversão de hardware
Quando a fila de inversão de hardware está habilitada em um adaptador específico, um carimbo de data/hora acompanha todas as chamadas de inversão. Em outras palavras, o KMD não precisa lidar com uma mistura de semântica antiga e nova de DxgkDdiSetVidPnSourceAddress.
O sistema operacional converte automaticamente solicitações existentes de API Presente baseadas em intervalo em chamadas de inversão baseadas em carimbo de data/hora para KMD. As seções a seguir discutem vários casos e como eles são mapeados para uma combinação de sinalizadores, Duração e carimbos de data/hora recebidos pelo KMD.
Rasgar e não rasgar inverte a semântica
A semântica de remover inversões é conceitualmente a mesma quando a fila de inversão de hardware está ativada. Depois que o TargetFlipTime for atingido, o KMD deve enviar a inversão para exibição enquanto ainda respeita sinalizadores como FlipImmediate, FlipImmediateNoTearing, and FlipOnNextVSync. Em outras palavras, o KMD deve se comportar como se o sistema operacional enviasse a inversão para ele exatamente no TargetFlipTime com os mesmos sinalizadores e parâmetros de inversão.
Por exemplo, se FlipOnNextVSync estiver definido como 1 e o TargetFlipTime estiver no meio do quadro, a inversão só deverá ser exibida no próximo VSync.
Suporte ao FlipOverwrite e fila de inversão de hardware
A fila de inversão de hardware é um superconjunto estrito do recurso de substituição de inversão controlado pelo valor de MaxQueuedMultiPlaneOverlayFlipVSync em DXGK_DRIVERCAPS.
Portanto, o sistema operacional ignora o valor de MaxQueuedMultiPlaneOverlayFlipVSync se o driver optar pela fila de inversão de hardware definindo MaxHwQueuedFlips para um valor maior que 1.
Várias inversões com um TargetFlipTime expirado
Quando há várias inversões em fila com um TargetFlipTime expirado para um determinado plano MPO, a fila de exibição de hardware deve escolher a inversão expirada na fila mais recente e enviá-la para exibição. As inversões expiradas restantes deves ser tratadas como canceladas e as entradas de log de fila de inversão correspondentes para elas devem conter DXGK_HWFLIPQUEUE_TIMESTAMP_CANCELLED como os valores de PresentTimestamp.
Interação entre a duração e o TargetFlipTime
O parâmetro Duração na estrutura DXGKARG_SETVIDPNSOURCEADDRESSWITHMULTIPLANEOVERLAY3 deve entrar em vigor quando a inversão especificada nessa estrutura for exibida na tela. Ele especifica o novo comportamento de taxa de atualização de exibição desejado para a saída especificada por VidPnSourceId em todos os planos. Nas versões WDDM 3.1 e Windows Server 2022, para simplificar a implementação de driver para hardware que não oferece suporte a alterações de Duração personalizadas em fila, o sistema operacional só envia solicitações de inversão com um novo parâmetro Duração depois que as solicitações de inversão anteriores são concluídas.
Mapeando intervalos presentes para o TargetFlipTime
Mapeando intervalos quando a taxa de atualização é fixa
Para preservar a semântica de intervalo presente existente, o sistema operacional precisa calcular o tempo de inversão de destino usando o intervalo atual e a taxa de atualização. No entanto, definir o tempo de inversão de destino exatamente para o tempo de inversão pretendido do VSync no qual o flip deve atingir a tela resulta em falhas frequentes. Estas falhas devem-se ao VSync perdido quando o tempo real do VSync se desvia um pouco. Para se proteger contra falhas, o sistema operacional subtrai metade do intervalo VSync do tempo de inversão de destino calculado.
A seguir temos uma fórmula simplificada para mapear o intervalo atual do tempo de inversão de destino:
TargetFlipTime = PreviousFlipStartVSyncTime + (PreviousFlipPresentInterval * FixedRefreshRate) - (FixedRefreshRate / 2)
Mapeando intervalos quando o recurso de taxa de atualização virtual WDDM 2.9 está presente
O recurso de taxa de atualização virtual pode aumentar temporariamente a taxa de atualização da tela para um múltiplo inteiro da taxa de atualização atual (ou seja, 24 Hz podem ser aumentados para 144 Hz ou 192 Hz). Para dispositivos capazes de suportar esse aumento, a fórmula na seção anterior é modificada para usar o múltiplo mais rápido da taxa de atualização atual:
TargetFlipTime = PreviousFlipStartVSyncTime + (PreviousFlipPresentInterval * FixedRefreshRate) - (FastestRefreshRate / 2)
Mapeando intervalos quando a taxa de atualização é alterada para um não múltiplo
Quando a taxa de atualização é alterada para um não múltiplo de uma taxa de atualização atual (por exemplo, de 24 Hz para 60 Hz), o sistema operacional precisa inspecionar as inversões de fila para ver se o tempo de destino calculado ainda é válido para a nova taxa de atualização. Se o tempo de inversão de destino precisar ser alterado, o sistema operacional cancelará as inversões em fila e as enfileirará novamente com os tempos de inversão de destino recém-calculados.