TDR no Windows 8 e superiores
A partir do Windows 8, o comportamento de TDR (detecção e recuperação de tempo limite) da GPU permite que partes de adaptadores físicos individuais sejam redefinidas, em vez de exigir uma redefinição em todo o adaptador.
Para obter mais informações, consulte TDR (detecção e recuperação de tempo limite).
Requisitos
- Versão mínima do WDDM: 1.2
- Versão mínima do Windows: 8
- Implementação do driver - somente gráficos completos e renderização: obrigatório
- Requisitos e testes do WHLK: Device.Graphics…TDRResiliency
Interface de driver de dispositivo (DDI) de TDR
Para acomodar essa alteração de comportamento, os KMD (drivers de miniporta de exibição) do modo kernel podem implementar estas funções:
Um KMD indica suporte para essas funções definindo o DXGK_DRIVERCAPS.SupportPerEngineTDR, nesse caso, ele deve implementar todas as funções listadas.
Um driver que dá suporte a essas funções também deve dar suporte à sincronização de nível zero para a função DxgkDdiCollectDbgInfo. Esse requisito garante que as chamadas KMD de nível zero possam continuar se a operação de redefinição não as afetar. Consulte Comentários de DxgkDdiCollectDbgInfo.
As seguintes estruturas estão associadas às funções acima:
- DXGK_DRIVERCAPS
- DXGK_ENGINESTATUS
- DXGKARG_QUERYDEPENDENTENGINEGROUP
- DXGKARG_QUERYENGINESTATUS
- DXGKARG_RESETENGINE
Nós
Conforme usado nas funções TDR listadas, um nó é uma das várias partes de um único adaptador físico que pode ser agendado independentemente. Por exemplo, um nó 3D, um nó de decodificação de vídeo e um nó de cópia podem existir no mesmo adaptador físico e cada um pode ser atribuído a um nó ordinal separado. Essa atribuição é armazenada no DXGKARG_QUERYDEPENDENTENGINEGROUP.NodeOrdinal em uma chamada para DxgkDdiQueryDependentEngineGroup.
O número de nós no adaptador físico é relatado pelo driver de miniporta de exibição no membro NbAsymetricProcessingNodes de DXGK_DRIVERCAPS.GpuEngineTopology.
O valor ordinal do nó é passado no membro NodeOrdinal da estrutura DXGKARG_CREATECONTEXT quando um contexto é criado.
Mecanismos
Conforme usado nas funções TDR DDI, um mecanismo é um dos vários adaptadores físicos (ou GPUs) que, juntos, atuam como um adaptador lógico. O Dxgkrnl dá suporte a essas configurações, mas requer que cada mecanismo tenha o mesmo número de nós.
Por exemplo, o agendador de GPU considera o mecanismo 0 como correspondente ao adaptador físico 0. O mecanismo 0 deve ter o mesmo número de nós que o mecanismo 1, que corresponde ao adaptador 1.
Valor ordinal do mecanismo na criação do contexto
Quando um contexto é criado, um único bit correspondente ao valor ordinal do mecanismo é definido no membro EngineAffinity da estrutura DXGKARG_CREATECONTEXT. O membro EngineOrdinal desta e de outras estruturas relacionadas ao agendador é um índice baseado em zero. O valor de EngineAffinity é 1 <<EngineOrdinal, e EngineOrdinal é a posição de bit mais alta em EngineAffinity.
Pacotes não afetados pela reinicialização do mecanismo
O agendador de GPU pode solicitar que o driver reenvie pacotes que foram enviados tarde demais para a fila de hardware do mecanismo para serem totalmente processados antes que a redefinição do mecanismo seja concluída. O driver deve seguir estas diretrizes para reenviar esses pacotes:
- Pacotes de paginação: o agendador de GPU solicita que o driver reenvie pacotes de paginação com suas IDs de limite originais e na mesma ordem em que foram enviados originalmente. Esses pacotes são reenviados antes que novos pacotes sejam adicionados à fila de hardware.
- Pacotes de renderização: o agendador de GPU atribui pacotes de renderização a novos IDs de limite e, em seguida, os reenvia.
Chamando a sequência para redefinir um mecanismo
Quando DxgkDdiResetEngine é bem-sucedido, o agendador de GPU garante que o valor LastAbortedFenceId retornado da chamada de redefinição do mecanismo corresponda a:
- Uma ID de limite existente na fila de hardware.
- A última ID de limite concluída na GPU. Essa situação pode acontecer quando a fila de hardware é esvaziada depois que o tempo limite da GPU é detectado, mas antes que o retorno de chamada de redefinição do mecanismo seja invocado.
O driver sempre deve manter o último valor de ID de limite concluído na GPU porque essa ID de limite é necessária para definir o membro DmaPreempted.LastCompletedFenceId de uma estrutura de notificação de interrupção de preempção DXGKARGCB_NOTIFY_INTERRUPT_DATA. A última ID de limite concluída deve ser avançada somente nestas situações:
- Quando um pacote é concluído (não preemptado), a última ID de limite concluída deve ser definida como a ID de limite do pacote concluído.
- Quando DxgkDdiResetEngine for bem-sucedido, a última ID de limite concluída deverá ser definida como o valor do membro LastCompletedFenceId retornado pela chamada de redefinição do mecanismo.
- Para redefinição em todo o adaptador, a última ID de limite concluída em todos os nós deve ser avançada para a última ID de limite enviada no momento da redefinição.
Aqui está uma sequência cronológica de uma redefinição bem-sucedida do mecanismo, conforme visto pelo agendador de GPU:
Uma tentativa de preempção é emitida.
Um tempo limite de GPU é detectado.
O agendador de GPU tira um instantâneo das últimas IDs de limite enviadas e concluídas e as interrupções do mecanismo de tempo limite são ignoradas. Essa combinação é uma operação atômica no nível de interrupção do dispositivo.
Se não houver pacotes na fila de hardware neste momento, saia. Essa situação pode acontecer quando um pacote foi concluído na janela de tempo entre as etapas 2 e 3.
Todos os DPCs enfileirados são liberados.
Prepare-se para a reinicialização do mecanismo.
Chame DxgkDdiResetEngine.
Se o membro LastAbortedFenceId for menor que a última ID de limite concluída ou for maior que a última ID de limite enviada, Dxgkrnl fará com que ocorra uma verificação de bug do sistema. Em um arquivo de despejo de memória, o erro é observado pela mensagem BugCheck 0x119, que tem estes quatro parâmetros:
- 0xA, o que significa que o driver relatou um ID de limite abortado inválido
- Valor LastAbortedFenceId retornado pelo driver
- Último ID de limite concluído
- Um parâmetro interno do sistema operacional
Se o valor LastAbortedFenceId for válido, prossiga com a recuperação de redefinição do mecanismo da seguinte maneira. Se a redefinição do mecanismo afetou um pacote de paginação, o agendador de GPU segue a redefinição do mecanismo com uma redefinição em todo o adaptador. Todos os dispositivos que possuem alocações referenciadas por esse pacote de paginação também são colocados no estado de erro. O dispositivo do sistema em si não é colocado no estado de erro e retoma a execução após a conclusão da redefinição.
Casos especiais
Uma situação especial pode ocorrer quando um pacote é concluído na GPU entre as etapas 3 e 7. Nesse caso, o driver deve definir LastAbortedFenceId como a ID de limite do último pacote concluído se não houver pacotes na fila de hardware do ponto de vista do driver. Do ponto de vista do agendador, parece que esse pacote foi abortado. Portanto, o agendador colocará o dispositivo correspondente em um estado de erro, mesmo que o pacote tenha sido concluído.
Se o driver não puder executar uma operação de redefinição por um dos seguintes motivos, ele deverá retornar um código de status de falha:
- O hardware está em um estado inválido.
- O hardware é incapaz de redefinir os nós.
Se o agendador de GPU receber um código de status de falha, ele executará uma operação de redefinição e reinicialização em todo o adaptador seguindo o comportamento do TDR antes do Windows 8.
Mesmo que um driver opte pelo comportamento do TDR do Windows 8 e posterior, há casos em que o agendador de GPU solicita uma redefinição e reinicialização de todo o adaptador lógico. Portanto, o driver ainda deve implementar as funções DxgkDdiResetFromTimeout e DxgkDdiRestartFromTimeout e sua semântica permanece a mesma de antes Windows 8. Quando uma tentativa de redefinir um adaptador físico com DxgkDdiResetEngine leva a uma redefinição do adaptador lógico, o comando !analyze do depurador Windows mostra que o valor TdrReason do contexto de recuperação de TDR está definido como um novo valor de TdrEngineTimeoutPromotedToAdapterReset = 9.