TDR dans Windows 8 et les versions ultérieures
À partir de Windows 8, le comportement de détection et de récupération des délais d’attente du GPU (TDR) permet de réinitialiser des parties d’adaptateurs physiques individuels, au lieu de nécessiter une réinitialisation de l’adaptateur dans son ensemble.
Pour plus d’informations, veuillez consulter la section Détection et récupération des délais d’attente (TDR).
Spécifications
- Version minimale de WDDM : 1.2
- Version minimale de Windows : 8
- Mise en œuvre du pilote : Graphiques complets et Rendu uniquement : Obligatoire
- Exigences et tests de WHLK : Device.Graphics…TDRResiliency
Interface de pilote de périphérique TDR (DDI)
Pour s’adapter à ce changement de comportement, les pilotes miniport d’affichage en mode noyau (KMD) peuvent implémenter ces fonctions :
Un KMD indique la prise en charge de ces fonctions en définissant le membre DXGK_DRIVERCAPS.SupportPerEngineTDR, auquel cas il doit implémenter toutes les fonctions répertoriées.
Un pilote qui prend en charge ces fonctions doit également prendre en charge la synchronisation de niveau zéro pour la fonction DxgkDdiCollectDbgInfo. Cette exigence garantit que les appels KMD de niveau zéro peuvent continuer si l’opération de réinitialisation ne les affecte pas. Veuillez consulter les Remarques de DxgkDdiCollectDbgInfo.
Les structures suivantes sont associées aux fonctions ci-dessus :
- DXGK_DRIVERCAPS
- DXGK_ENGINESTATUS
- DXGKARG_QUERYDEPENDENTENGINEGROUP
- DXGKARG_QUERYENGINESTATUS
- DXGKARG_RESETENGINE
Nœuds
Tel qu’il est utilisé dans les fonctions TDR répertoriées, un nœud est l’une des multiples parties d’un adaptateur physique unique qui peut être planifiée de manière indépendante. Par exemple, un nœud 3D, un nœud de décodage vidéo et un nœud de copie peuvent tous exister dans le même adaptateur physique, et chacun peut se voir attribuer un ordinal de nœud distinct. Cette attribution est stockée dans le membre DXGKARG_QUERYDEPENDENTENGINEGROUP.NodeOrdinal lors d’un appel à DxgkDdiQueryDependentEngineGroup.
Le nombre de nœuds dans l’adaptateur physique est rapporté par le pilote miniport d’affichage dans le membre NbAsymetricProcessingNodes de DXGK_DRIVERCAPS.GpuEngineTopology.
La valeur d’ordinal de nœud est transmise dans le membre NodeOrdinal de la structure DXGKARG_CREATECONTEXT lors de la création d’un contexte.
Moteurs
Tel qu’il est utilisé dans les fonctions DDI TDR, un moteur est l’un des multiples adaptateurs physiques (ou GPU) qui ensemble agissent comme un seul adaptateur logique. Dxgkrnl prend en charge de telles configurations mais nécessite que chaque moteur ait le même nombre de nœuds.
À titre d’exemple, le planificateur GPU considère que le moteur 0 correspond à l’adaptateur physique 0. Le moteur 0 doit avoir le même nombre de nœuds que le moteur 1, qui correspond à l’adaptateur 1.
Valeur d’ordinal de moteur lors de la création d’un contexte
Lorsqu’un contexte est créé, un seul bit correspondant à la valeur d’ordinal de moteur est défini dans le membre EngineAffinity de la structure DXGKARG_CREATECONTEXT. Le membre EngineOrdinal de cette structure et d’autres structures liées au planificateur est un index basé sur zéro. La valeur de EngineAffinity est 1 <<EngineOrdinal, et EngineOrdinal est la position de bit la plus élevée dans EngineAffinity.
Paquets non affectés par la réinitialisation du moteur
Le planificateur GPU peut demander au pilote de soumettre à nouveau les paquets qui ont été soumis trop tard dans la file d’attente matérielle du moteur pour être entièrement traités avant que la réinitialisation du moteur ne soit terminée. Le pilote doit suivre ces directives pour soumettre à nouveau de tels paquets :
- Paquets de pagination : Le planificateur GPU demande au pilote de soumettre à nouveau les paquets de pagination avec leurs identifiants de clôture d’origine, et dans le même ordre que celui dans lequel ils ont été initialement soumis. Ces paquets sont soumis à nouveau avant que de nouveaux paquets ne soient ajoutés à la file d’attente matérielle.
- Paquets de rendu : Le planificateur GPU attribue de nouveaux identifiants de clôture aux paquets de rendu, puis les soumet à nouveau.
Séquence d’appel pour réinitialiser un moteur
Lorsque DxgkDdiResetEngine réussit, le planificateur GPU s’assure que la valeur LastAbortedFenceId renvoyée par l’appel de réinitialisation du moteur correspond à :
- Un identifiant de clôture existant dans la file d’attente matérielle.
- L’identifiant de clôture le plus récent sur le GPU. Cette situation peut se produire lorsque la file d’attente matérielle se vide après que le délai d’attente du GPU est détecté, mais avant que le rappel de réinitialisation du moteur ne soit invoqué.
Le pilote doit toujours conserver la valeur du dernier identifiant de clôture terminé sur le GPU, car cet identifiant est nécessaire pour définir le membre DmaPreempted.LastCompletedFenceId d’une structure de notification d’interruption de préemption DXGKARGCB_NOTIFY_INTERRUPT_DATA. Le dernier identifiant de clôture terminé ne doit être avancé que dans ces situations :
- Lorsqu’un paquet est terminé (non préempté), le dernier identifiant de clôture terminé doit être défini sur l’identifiant de clôture du paquet terminé.
- Lorsque DxgkDdiResetEngine réussit, le dernier identifiant de clôture terminé doit être défini sur la valeur du membre LastCompletedFenceId renvoyé par l’appel de réinitialisation du moteur.
- Pour une réinitialisation de l’adaptateur dans son ensemble, le dernier identifiant de clôture terminé sur tous les nœuds doit être avancé à l’identifiant de clôture soumis en dernier au moment de la réinitialisation.
Voici une séquence chronologique d’une réinitialisation de moteur réussie, telle qu’elle est perçue par le planificateur GPU :
Une tentative de préemption est émise.
Un délai d’attente GPU est détecté.
Le planificateur GPU prend un instantané des derniers identifiants de clôture soumis et terminés, et les interruptions provenant du moteur en délai d’attente sont ignorées. Cette combinaison est une opération atomique au niveau de l’interruption du périphérique.
S’il n’y a pas de paquets dans la file d’attente matérielle à ce stade, sortie. Cette situation peut se produire lorsqu’un paquet a été terminé dans la fenêtre de temps entre les étapes 2 et 3.
Tous les DPC en file d’attente sont purgés.
Préparez-vous à réinitialiser le moteur.
Appelez DxgkDdiResetEngine.
Si le membre LastAbortedFenceId est inférieur à l’identifiant de clôture terminé ou est supérieur à l’identifiant de clôture soumis, Dxgkrnl provoque un arrêt système (bug check). Dans un fichier de vidage sur incident, l’erreur est signalée par le message BugCheck 0x119, qui contient les quatre paramètres suivants :
- 0xA, signifiant que le pilote a signalé un identifiant de clôture avorté invalide
- Valeur LastAbortedFenceId renvoyée par le pilote
- Dernier identifiant de clôture terminé
- Un paramètre interne du système d’exploitation
Si la valeur LastAbortedFenceId est valide, poursuivez la récupération après réinitialisation du moteur comme suit. Si la réinitialisation du moteur a affecté un paquet de pagination, le planificateur GPU suit la réinitialisation du moteur par une réinitialisation de l’adaptateur dans son ensemble. Tous les périphériques qui possèdent des allocations référencées par ce paquet de pagination sont également mis en état d’erreur. Le périphérique système lui-même n’est pas mis en état d’erreur, et il reprend son exécution une fois la réinitialisation terminée.
Cas particuliers
Une situation particulière peut se produire lorsqu’un paquet est terminé sur le GPU entre les étapes 3 et 7. Dans ce cas, le pilote doit définir LastAbortedFenceId sur l’identifiant de clôture du dernier paquet terminé s’il n’y a pas de paquets dans la file d’attente matérielle du point de vue du pilote. Du point de vue du planificateur, il semble qu’un tel paquet ait été avorté. Ainsi, le planificateur mettra le périphérique correspondant en état d’erreur, même si le paquet a finalement été terminé.
Si le pilote ne peut pas effectuer une opération de réinitialisation pour l’une des raisons suivantes, il doit renvoyer un code d’état d’échec :
- Le matériel est dans un état invalide.
- Le matériel est incapable de réinitialiser les nœuds.
Si le planificateur GPU reçoit un code d’état d’échec, il effectue une opération de réinitialisation et de redémarrage de l’adaptateur dans son ensemble, conformément au comportement TDR avant Windows 8.
Même si un pilote opte pour le comportement TDR de Windows 8 et versions ultérieures, il existe des cas où le planificateur GPU demande une réinitialisation et un redémarrage de l’adaptateur logique dans son ensemble. Par conséquent, le pilote doit toujours implémenter les fonctions DxgkDdiResetFromTimeout et DxgkDdiRestartFromTimeout, et leur sémantique reste la même qu’avant Windows 8. Lorsque la tentative de réinitialiser un adaptateur physique avec DxgkDdiResetEngine conduit à une réinitialisation de l’adaptateur logique, la commande !analyze du débogueur Windows montre que la valeur TdrReason du contexte de récupération TDR est définie sur une nouvelle valeur TdrEngineTimeoutPromotedToAdapterReset = 9.