Partilhar via


Fila de troca de hardware

Este artigo descreve o recurso de fila de inversão de hardware que é suportado 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 enfileirados, melhorando a eficiência energética de cenários de reprodução de vídeo em hardware compatível.

Modelo de fila de inversão pré-WDDM 3.0

Muitos controladores de vídeo modernos suportam a capacidade de enfileirar vários quadros que devem ser exibidos em uma sequência. A partir do WDDM 2.1, o SO suporta múltiplas solicitações pendentes para sobrescrever o flip, 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 de alta taxa de quadros em que vários quadros são renderizados sequencialmente com o 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. Esse enfileiramento avançado permite que a CPU entre em um estado de baixo consumo de energia enquanto os quadros enfileirados são processados, resultando em economias substanciais 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 secção Fila de espera de hardware básica apresenta uma solução que permite à CPU entrar num estado de baixo consumo de energia e transferir o processamento de quadros em fila para a GPU.

Em cenários de jogos anteriores ao WDDM 3.0, depois de a GPU terminar de renderizar a cena no buffer de fundo da cadeia de troca, há uma comunicação de ida e volta com a CPU para enviar a solicitação para apresentar o conteúdo da imagem no ecrã. 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 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 a presença tanto da fila de inversão de hardware básica quanto da funcionalidade de agendamento de hardware da GPU do estágio 2.

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.

Diagrama ilustrando três quadros que permanecem na tela por um intervalo VSync cada.

O padrão de preenchimento no diagrama mostra os momentos em que o processamento de fila de flip do software Dxgkrnl e os threads de aplicativos precisam acordar e realizar processamento na CPU. Em cada VSync, o controlador de exibição tem que emitir uma notificação para a CPU ao sistema operativo para a troca concluída, e o sistema operativo tem que submeter a próxima solicitação de troca. O aplicativo também tem que acordar em cada VSync e consultar estatísticas presentes para eventualmente aprender quando o último quadro no 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 exibição 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 compatível.

O diagrama a seguir ilustra a arquitetura proposta.

Diagrama demonstrando o mecanismo básico de fila de inversão de hardware.

Com a abordagem de fila de inversão de hardware, os componentes do aplicativo e da CPU 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 só é notificada quando o quadro N+2 para o qual 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 de a GPU terminar de renderizar a cena no buffer de fundo da cadeia de troca, há uma comunicação de ida e volta com a CPU para enviar a solicitação para apresentar o conteúdo da imagem no ecrã. O diagrama a seguir mostra esse cenário.

Diagrama que mostra a conclusão do quadro que requer uma interação de ida e volta com o CPU.

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.

Diagrama ilustrando um frame perdido devido ao ciclo necessário da CPU.

Alguns controladores de vídeo suportam nativamente condições de espera que permitem que o monitor envie a solicitação de inversão assim que a GPU terminar de renderizar o quadro sem a ida e volta da CPU. Como a fila de inversão de hardware pode enviar o quadro N concluído para a tela sem uma ida e volta da CPU, ela pode evitar quadros perdidos, conforme mostrado no diagrama a seguir.

Diagrama mostrando a conclusão do frame sem a necessidade de um ciclo da CPU.

O restante deste artigo discute a funcionalidade básica da fila de inversão de hardware.

Suporte DDI

Os DDIs a seguir foram adicionados para suportar o recurso de fila de inversão de hardware.

Verificando a disponibilidade de recursos

A fila de inversão de hardware requer negociação de ativação/desativação com o sistema operativo. Um KMD que suporte a fila de inversão de hardware deve primeiro chamar DXGKCB_QUERYFEATURESUPPORT durante o tempo de inicialização do dispositivo com um FeatureId de DXGK_FEATURE_HWFLIPQUEUE para determinar se o sistema operacional permite habilitar a fila de inversão de hardware.

A fila de inversão de hardware só pode ser usada se o retorno de chamada for bem-sucedido e Ativar estiver definido como TRUE.

Um KMD pode usar o código de exemplo a seguir durante os estágios experimentais e de criação da 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 implementação do driver, embora seja possível ativar a fila de troca de hardware sem habilitar o agendamento de hardware da GPU, essa combinação não é oficialmente suportada. Atualmente, o Windows requer que o agendamento de hardware da GPU seja habilitado para que a fila de inversão de hardware básica seja habilitada nos drivers lançados oficialmente.

Indicando os recursos de enfileiramento de hardware

MaxHwQueuedFlips foi adicionado ao DXGK_DRIVERCAPS para indicar o suporte à fila de inversão de hardware. Se o SO permitiu o suporte à fila de inversão de hardware conforme descrito anteriormente, um KMD que suporte uma fila de inversão de hardware deve definir MaxHwQueuedFlips para um valor maior que 1. Quando MaxHwQueuedFlips é maior que 1, KMD indica que o hardware de exibição suporta até MaxHwQueuedFlips quadros futuros que podem ser enfileirados para serem exibidos para um determinado VidPnSource na GPU. O sistema operativo respeita as restrições fornecidas pelo controlador sobre o tipo de transições que podem ser enfileiradas antecipadamente.

HwQueuedFlipCaps também foi adicionado ao DXGK_DRIVERCAPS. Este membro está atualmente reservado para uso do sistema; os motoristas não devem usá-lo.

Inverter o horário e o formato do 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. O flip pode ser tornado visível para o utilizador depois de alcançado o tempo alvo do flip.

O sistema operacional usa as unidades de contador de relógio da CPU, obtidas de KeQueryPerformanceCounter, para passar o tempo de quadro de destino e interpretar o tempo de quadro real.

Enviando flips 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 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 para obter detalhes sobre os casos de repetição e falha desses membros.

    • HwFlipQueueDrainNeeded
    • HwFlipQueueDrainAllPlanes
    • HwFlipQueueDrainAllSources
  • Um membro TargetFlipTime foi adicionado. TargetFlipTime descreve o tempo de troca alvo em unidades QPC. Quando o relógio atinge esse valor, o quadro pode ser enviado para o ecrã respeitando o VSync e os parâmetros de tearing. Na presença de flips pendentes previamente enfileirados, o sistema operacional garante que para cada plano MPO referenciado pela solicitação de flip, TargetFlipTime é maior ou igual a qualquer um dos tempos de destino de flip pendentes para este plano. Em outras palavras, pode haver uma sequência de mudanças com os mesmos carimbos de data/hora ou crescentes, mas não pode haver uma sequência que volte no tempo.

DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 casos de tentativa e falha

Falha ao enfileirar a solicitação para o hardware devido a alternações pendentes

Existem vários casos especiais que podem impedir o KMD de enfileirar uma solicitação de inversão com outras solicitações de inversão pendentes. Nesses casos, o KMD deve retornar STATUS_RETRY de DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 e definir HwFlipQueueDrainNeeded igual a 1. O sistema operacional tentará enviar a solicitação de flip novamente depois que todos os flips pendentes em planos afetados pelo flip forem concluídos e assim que o tempo alvo for atingido.

Em alguns casos, o hardware de visualização pode exigir a conclusão dos flips pendentes em todos os planos, não apenas nos referenciados pelo pedido de flip recebido. Nesse caso, os sinalizadores HwFlipQueueDrainNeeded e HwFlipQueueDrainAllPlanes devem ser definidos como 1 e KMD deve retornar STATUS_RETRY.

Da mesma forma, o hardware de exibição pode exigir a conclusão de flips 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 SO se o reenvio deve ser feito no dispositivo IRQL (PrePresentNeeded definido como 0), ou se o SO deve executar esta chamada em PASSIVE_LEVEL (PrePresentNeeded definido como 1). Se o KMD ainda retornar STATUS_RETRY mesmo que não haja mais flips pendentes nesse VidPnSourceId, essa condição será tratada como uma falha de parâmetro inválida.

É importante que o valor de MaxHwQueuedFlips ainda reflita o número máximo de simples alterações apenas de endereço que podem ser enfileiradas num plano MPO. O mecanismo STATUS_RETRY deve ser usado para pedidos de inversão mais complexos que não podem ser colocados em filas profundas, como alterações na configuração de aviões.

Falha de parâmetro inválido

No modelo de fila de flip de hardware, a gestão de solicitações de flip com falha pelo SO foi reformulada para permitir uma melhor facilidade de 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 do kernel e verificação de bugs: Este comportamento é frequentemente ativado em compilações de desenvolvimento/pré-lançamento para melhorar a capacidade de depuração exatamente no momento em que ocorre a condição de falha.
  • Live Kernel Dump seguido por um TDR: O comportamento do usuário final de varejo.

Especificando o comportamento de interrupção do VSync

Para obter poupança de energia em cenários de inversão em fila, o sistema operativo geralmente suspende as interrupções de VSync regulares para manter a CPU em um estado de baixo consumo de energia. No entanto, alguns flips são marcados como exigindo uma interrupção a ser levantada para que o aplicativo observe o lote de presentes concluídos e enfileire o trabalho adicional. Também há casos em que as aplicações solicitam ser ativadas em cada interrupção do VSync, independentemente de haver solicitações de troca pendentes. E, inversamente, em um sistema completamente ocioso, as interrupções do VSync são suspensas até que novas atividades de apresentação ou ouvintes do VSync apareçam.

Para lidar com todos esses casos, foram introduzidos o seguinte controlador de retorno de chamada e a estrutura de retorno de chamada:

KMD fornece um ponteiro para sua função DxgkDdiSetInterruptTargetPresentId em DRIVER_INITIALIZATION_DATA

O sistema operacional chama DxgkDdiSetInterruptTargetPresentId para especificar o PresentId de destino que deve resultar em uma interrupção VSync acionada quando o flip correspondente for concluído. Esta função é chamada no nível de interrupção do dispositivo (DIRQL) para sincronizar com DxgkDdiSetVidPnSourceAddress e a interrupção VSync.

Interação com DxgkDdiControlInterrupt

Quando as interrupções VSync são totalmente desativadas via DxgkDdiControlInterrupt/DxgkDdiControlInterrupt2/DxgkDdiControlInterrupt3, elas permanecem desabilitadas independentemente do valor PresentId de destino de interrupção. É necessário que o KMD armazene a ID mais recente de destino de interrupção presente, para que esta possa ser respeitada assim que o VSync for novamente ativado.

Quando as interrupções VSync são habilitadas via DxgkDdiControlInterruptXxx, a ID presente do destino de interrupção (pSetInterruptTargetPresentId) fornece um controle granular mais fino da seguinte maneira:

  • Quando a ID presente de destino é definida como UINT64_MAX, nenhuma interrupção VSync é necessária daqui para frente até que a ID presente de destino seja alterada novamente. As interrupções do VSync estão desativadas, mas o KMD requer implementar o comportamento DXGK_VSYNC_DISABLE_KEEP_PHASE para reativar as interrupções.

  • Quando o ID presente de destino é definido como 0, as 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 verificado no momento for maior ou igual ao >.

Quando vários planos MPO estão disponíveis, a interrupção VSync deve ser acionada se qualquer dos planos o requerer.

Desativação de VSync em 2 estágios usando DxgkDdiSetInterruptTargetPresentId

Se a chamada do SO para DxgkDdiSetInterruptTargetPresentId definir um InterruptTargetPresentId num plano que levaria a desativar totalmente o VSync neste VidPnSource (ou seja, este plano foi o último que manteve o VSync ativado, e agora este plano também está a desativar o VSync), o KMD deve desativar as interrupções do VSync, mas manter a fase VSync ativada no hardware (DXGK_VSYNC_DISABLE_KEEP_PHASE). Após um determinado período de tempo (normalmente equivalente a dois períodos de VSync), o sistema operativo fará 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 transição na fila

Em casos como transições de estado em tela cheia ou saídas de aplicativos, futuras inversões em fila podem precisar ser canceladas. Para lidar com esses casos, foram introduzidas a seguinte rotina de retorno do driver e as estruturas relacionadas:

KMD fornece um ponteiro para a função denominada DxgkDdiCancelFlips em DRIVER_INITIALIZATION_DATA.

O SO especifica o intervalo de flips em fila a cancelar quando chama DxgkDdiCancelFlips, e o KMD reporta ao SO o intervalo de flips que conseguiu cancelar de forma síncrona.

O exemplo a seguir ilustra a mecânica e o caso síncrono de cancelamento de flip em um único plano. (O SO não suporta cancelamento assíncrono no Windows 11, versão 22H2.) Imagine que as seguintes inversões estão sendo enfileiradas para a fila de inversões de hardware:

  • PresenteId N
  • tempo t0 PresentId N+1
  • tempo t1 PresentId N+2
  • tempo t2 PresentId N+3
  • tempo t3 PresentId N+4
  • tempo t4

O sistema operacional então decide cancelar os flips N+2, N+3 e N+4, por isso chama DxgkDdiCancelFlips com 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 flips de hardware sem efeitos colaterais.

Como resultado, o KMD define PresentIdCancelled como N+3 e conclui N+2 como de costume.

O SO 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 de fila de troca indicará os timestamps para N, N+1, N+2 como de costume.

O intervalo de flips cancelados de forma síncrona deve ser contínuo e, quando não for zero, presume-se que inclua o último ID presente enviado ao KMD. Em outras palavras, não pode haver quaisquer lacunas dentro dos dois intervalos de inversão cancelados de forma síncrona.

Cancelamento de rotações intertravadas em vários planos

Um flip interbloqueado é enviado chamando DxgkDdiSetVidPnSourceAddress com vários planos e PresentIds. O contrato entre o SO e a KMD é o seguinte:

  • O conjunto de planos deve ser tornado visível no mesmo VSync.
  • O hardware de display não está autorizado a exibir apenas uma parte desses planos num VSync e o restante no VSync seguinte.

No modelo de fila 'flip' de hardware, tais flips interbloqueados são cancelados ao passar múltiplos planos e PresentIds na invocação de DxgkDdiCancelFlips. O conjunto de planos passados nesses casos deve corresponder a uma solicitação de flip intertravada pendente, e a decisão do KMD em relação a todos os PresentIds intertravados deve ser a mesma:

  • Não cancele, ou
  • Cancelar de forma síncrona

DxgkDdiCancelFlips é chamado no nível de interrupção do dispositivo (DIRQL) para sincronizar com DxgkDdiSetVidPnSourceAddress e interrupção VSync.

Obtenção de estatísticas atuais para flips em espera

Como a abordagem de fila de troca de hardware é evitar acordar a CPU em cada VSync, precisa haver um mecanismo para reter os tempos de exibição de frames para as últimas inversões enfileiradas.

Os drivers gráficos que suportam a fila de inversão de hardware devem gravar informações no buffer de log da fila de inversão fornecido pelo sistema operativo para cada inversão concluída ou cancelada para um determinado plano MPO para cada VidPnSource ativo.

O sistema operativo garante fornecer o ponteiro de log da fila de inversão (numa chamada para DxgkDdiSetFlipQueueLogBuffer) antes da primeira chamada DxgkDdiSetVidPnSourceAddress para um determinado plano MPO para cada VidPnSource ativo. O sistema operativo está autorizado a destruir o buffer de registo da fila de flip quando a fila de flip não tiver qualquer solicitação pendente. Nesse caso, ele fornecerá um novo ponteiro de log antes da próxima chamada DxgkDdiSetVidPnSourceAddress . O log de fila de inversão é circular. Depois que a entrada [NumberOfEntries-1] é gravada, a próxima entrada de log é [0].

Depois de um lote de flips em fila ser concluído, o KMD deve garantir que o log da fila de flips para os flips concluídos seja atualizado no mais cedo de um destes dois momentos:

  • Um manipulador de interrupção VSync para uma inversão que exigiu que uma interrupção fosse gerada.
  • Em resposta a uma solicitação explícita DxgkDdiUpdateFlipQueueLog do sistema operacional.

Inverter DDIs de fila de log

O seguinte callback relacionado ao log da fila de flip e as estruturas associadas foram adicionadas:

KMD fornece um ponteiro para as suas funções em 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 VSync para o modelo de fila de inversão por hardware:

  • O valor enum DXGK_INTERRUPT_CRTC_VSYNC_WITH_MULTIPLANE_OVERLAY3 foi adicionado como InterruptType.
  • A estrutura CrtcVSyncWithMultiPlaneOverlay3 foi adicionada à união. A semântica de CrtcVSyncWithMultiPlaneOverlay3 é semelhante à da estrutura CrtcVSyncWithMultiPlaneOverlay2 existente, exceto que, em vez de um único PresentId concluído para cada plano, CrtcVSyncWithMultiPlaneOverlay3.pMultiPlaneOverlayVSyncInfo aponta para o intervalo de PresentIds anteriormente não relatados do registo de fila de troca.
  • A estrutura DXGK_MULTIPLANE_OVERLAY_VSYNC_INFO3 foi adicionada para o membro pMultiPlaneOverlayVSyncInfo do CrtcVSyncWithMultiPlaneOverlay3.

Usando novamente o diagrama de exemplo da fila de inversão de hardware básico:

Diagrama demonstrando o mecanismo básico de fila de inversão de hardware.

Suponha que FirstFreeFlipQueueLogEntryIndex foi definido como 40 no momento em que o flip N foi enviado e, em seguida, N, N+1, 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 respetivos momentos v2, v3, v4, o KMD gravou três novas entradas em seu buffer de log de fila flip com índices 40, 41 e 42. KMD reporta 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 seguintes 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]. FirstFreeFlipQueueLogEntryIndex = 43

  • LogBufferAddressForPlane0[40].PresentId = O

  • LogBufferAddressForPlane0[40].TimestampPresente = v2

  • LogBufferAddressForPlane0[41]. PresenteId = N+1

  • LogBufferAddressForPlane0[41]. Carimbo de Tempo/Presente = v3

  • LogBufferAddressForPlane0[42]. PresentId = N+2

  • LogBufferAddressForPlane0[42].PresentTimestamp = v4

Solicitação explícita de atualização do log de fila de inversão

Há casos em que o sistema operacional precisa obter informações sobre o último lote concluído de flips sem ter que esperar pela interrupção do VSync. Nesses casos, o sistema operativo faz uma chamada explícita para DxgkDdiUpdateFlipQueueLog para solicitar que o KMD leia a partir da sua estrutura de dados de hardware de exibição proprietária, e escreva informações antigas de flip no log de fila de flip. A semântica do log é a mesma descrita anteriormente; a única alteração é que FirstFreeFlipQueueLogEntryIndex é retornado ao sistema operacional fora da interrupção VSync.

DxgkDdiUpdateFlipQueueLog é chamado no nível de interrupção do dispositivo (DIRQL) e está na mesma classe de sincronização que DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 DDI.

Alterações no modo de exibição e transições de energia na presença de uma inversão em fila na fila de inversão de hardware

O Dxgkrnl garante que os flips já enfileirados na fila de flips de hardware sejam concluídos ou cancelados antes de iniciar uma mudança de modo ou o desligamento do monitor.

Mapeamento: Apresentar solicitações para carimbos de data/hora da fila de inversão de hardware

Quando a fila de inversão de hardware está habilitada num adaptador específico, uma marca temporal é acompanhada por todas as chamadas de inversão. Em outras palavras, o KMD não precisa lidar com uma mistura de semântica DxgkDdiSetVidPnSourceAddress antiga e nova.

O Sistema Operativo converte automaticamente as solicitações existentes da API Present baseadas em intervalos em chamadas flip baseadas em timestamp 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.

Semântica de flips rasgando e não rasgando

A semântica dos flips rasgados é conceitualmente a mesma quando a fila de flips de hardware está ativada. Uma vez atingido o TargetFlipTime, o KMD deve enviar o flip para exibição enquanto ainda respeita flags como FlipImmediate, FlipImmediateNoTearing e FlipOnNextVSync. Em outras palavras, o KMD deve se comportar como se o sistema operacional enviasse o flip para ele exatamente no TargetFlipTime com os mesmos sinalizadores e parâmetros de flip.

Por exemplo, se FlipOnNextVSync estiver definido como 1 e o TargetFlipTime estiver no meio do quadro, o flip só deverá ser exibido no próximo VSync.

Suporte para FlipOverwrite e filas de processamento de hardware

A fila de inversão de hardware é um superconjunto estrito do recurso de sobreposição de inversão controlado pelo valor MaxQueuedMultiPlaneOverlayFlipVSync em DXGK_DRIVERCAPS.

Portanto, o sistema operativo ignora o valor MaxQueuedMultiPlaneOverlayFlipVSync se o controlador optar pela fila de inversão de hardware ao definir MaxHwQueuedFlips para um valor superior a 1.

Várias inversões com um TargetFlipTime expirado

Quando há várias mudanças em fila com um TargetFlipTime expirado para um determinado plano MPO, o processo de exibição de hardware deve selecionar a mudança expirada mais recentemente enfileirada e submetê-la à exibição. O resto das inversões expiradas deve ser tratado como cancelado, e as entradas de log da fila de inversões correspondentes devem conter DXGK_HWFLIPQUEUE_TIMESTAMP_CANCELLED como os valores de PresentTimestamp.

Interação entre Duração e TargetFlipTime

O parâmetro Duration na estrutura DXGKARG_SETVIDPNSOURCEADDRESSWITHMULTIPLANEOVERLAY3 deve entrar em vigor quando o flip especificado nessa estrutura é exibido na tela. Ele especifica o novo comportamento desejado da taxa de atualização de exibição 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 Duration depois que as solicitações de inversão anteriores são concluídas.

Mapeando intervalos atuais para TargetFlipTime

Mapeando intervalos quando a taxa de atualização é fixa

Para preservar a semântica do intervalo atual existente, o SO tem que calcular o tempo de transição alvo usando o intervalo atual e a frequência de atualização. No entanto, definir o tempo de flip alvo exatamente para o tempo VSync pretendido em que o flip deve atingir a tela resulta em falhas frequentes. Essas falhas são devidas à perda do VSync 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.

Aqui está uma fórmula simplificada para associar o intervalo atual ao tempo alvo de inversão:

TargetFlipTime = PreviousFlipStartVSyncTime + (PreviousFlipPresentInterval * FixedRefreshRate) - (FixedRefreshRate / 2)

Mapeando intervalos quando a funcionalidade virtual de taxa de atualização 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)

Mapeamento de intervalos quando a frequência de atualização é alterada para um valor não múltiplo

Quando a taxa de atualização é alterada para um valor que não seja múltiplo da taxa de atualização atual (por exemplo, de 24 Hz para 60 Hz), o sistema operativo precisa inspecionar as alterações na fila para ver se o tempo de destino calculado ainda é válido para a nova taxa de atualização. Se o tempo de mudança de destino precisar ser alterado, o sistema operativo cancelará as mudanças enfileiradas e as reenfileirará com os tempos de mudança de destino recém-calculados.