TDR in Windows 8 und höher
Ab Windows 8 ermöglicht das Verhalten von GPU-TDR (Timeout Detection and Recovery, Timeouterkennung und Wiederherstellung), dass Teile einzelner physischer Adapter zurückgesetzt werden können, anstatt ein adapterweites Zurücksetzen zu erfordern.
Weitere Informationen finden Sie unter Timeouterkennung und Wiederherstellung (Timeout Detection and Recovery, TDR).
Anforderungen
- WDDM-Mindestversion: 1.2
- Mindestversion von Windows: 8
- Treiberimplementierung – Nur vollständige Grafik- und Renderingprozesse: Obligatorisch
- WHLK-Anforderungen und -Tests: Device.Graphics…TDRResiliency
TDR-DDI (Device Driver Interface; Gerätetreiberschnittstelle)
Um diese Verhaltensänderung zu berücksichtigen, können Kernelmodus-Miniporttreiber (KMD) diese Funktionen implementieren:
Ein KMD gibt die Unterstützung für diese Funktionen durch Festlegen des Members DXGK_DRIVERCAPS.SupportPerEngineTDR an. In diesem Fall müssen alle aufgeführten Funktionen implementiert werden.
Ein Treiber, der diese Funktionen unterstützt, muss auch die Synchronisierung der Ebene Null für die Funktion DxgkDdiCollectDbgInfo unterstützen. Diese Anforderung stellt sicher, dass KMD-Aufrufe der Ebene Null fortgesetzt werden können, wenn der Zurücksetzungsvorgang sie nicht beeinflusst. Siehe Hinweise zu DxgkDdiCollectDbgInfo.
Die folgenden Strukturen sind den oben genannten Funktionen zugeordnet:
- DXGK_DRIVERCAPS
- DXGK_ENGINESTATUS
- DXGKARG_QUERYDEPENDENTENGINEGROUP
- DXGKARG_QUERYENGINESTATUS
- DXGKARG_RESETENGINE
Nodes
Wie in den aufgeführten TDR-Funktionen verwendet, ist ein Knoten einer von mehreren Teilen eines einzelnen physischen Adapters, der unabhängig geplant werden kann. Beispielsweise können ein 3D-Knoten, ein Videodecodierungsknoten und ein Kopierknoten alle in demselben physischen Adapter vorhanden sein, und jedem kann ein separater Knotenordinalwert zugewiesen werden. Diese Zuweisung wird im Member DXGKARG_QUERYDEPENDENTENGINEGROUP.NodeOrdinal in einem Aufruf von DxgkDdiQueryDependentEngineGroup gespeichert.
Die Anzahl der Knoten im physischen Adapter wird vom Display-Miniporttreiber im Member NbAsymetricProcessingNodes von DXGK_DRIVERCAPS.GpuEngineTopology gemeldet.
Der Knotenordinalwert wird beim Erstellen eines Kontexts im Member NodeOrdinal der DXGKARG_CREATECONTEXT-Struktur übergeben.
Engines
Wie in den TDR-DDI-Funktionen verwendet, ist ein Modul einer von mehreren physischen Adaptern (oder GPUs), die zusammen als ein logischer Adapter fungieren. Dxgkrnl unterstützt solche Konfigurationen, erfordert jedoch, dass jedes Modul dieselbe Anzahl von Knoten aufweisen muss.
Der GPU-Scheduler geht beispielsweise davon aus, dass Modul 0 dem physischen Adapter 0 entspricht. Modul 0 muss dieselbe Anzahl von Knoten wie Modul 1 aufweisen, was Adapter 1 entspricht.
Modulordinalwert bei der Kontexterstellung
Wenn ein Kontext erstellt wird, wird ein einzelnes Bit, das dem Modulordinalwert entspricht, im EngineAffinity-Member der Struktur DXGKARG_CREATECONTEXT festgelegt. Der EngineOrdinal-Member dieser und anderer schedulerbezogener Strukturen ist ein nullbasierter Index. Der Wert von EngineAffinity ist 1 <<EngineOrdinal, und EngineOrdinal ist die höchste Bitposition in EngineAffinity.
Pakete, die von der Modulzurücksetzung nicht betroffen sind
Der GPU-Scheduler fordert den Treiber möglicherweise auf, Pakete erneut zu übermitteln, die zu spät an die Hardwarewarteschlange des Moduls übermittelt wurden, um vollständig verarbeitet zu werden, bevor die Modulzurücksetzung abgeschlossen wurde. Der Treiber muss die folgenden Richtlinien befolgen, um solche Pakete erneut zu übermitteln:
- Pagingpakete: Der GPU-Scheduler fordert den Treiber auf, Pagingpakete mit ihren ursprünglichen Fence-IDs erneut zu übermitteln, und zwar in der gleichen Reihenfolge wie bei der ursprünglichen Übermittlung. Alle solchen Pakete werden erneut übermittelt, bevor neue Pakete der Hardwarewarteschlange hinzugefügt werden.
- Renderingpakete: Der GPU-Scheduler weist Renderingpaketen neue Fence-IDs zu und übermittelt sie dann erneut.
Aufrufen der Sequenz zum Zurücksetzen eines Moduls
Wenn DxgkDdiResetEngine erfolgreich ist, stellt der GPU-Scheduler sicher, dass der vom Modulzurücksetzungsaufruf zurückgegebene LastAbortedFenceId-Wert einem der folgenden Werte entspricht:
- Eine vorhandene Fence-ID in der Hardwarewarteschlange.
- Die letzte abgeschlossene Fence-ID für die GPU. Diese Situation kann auftreten, wenn die Hardwarewarteschlange geleert wird, nachdem das GPU-Timeout erkannt wurde, aber bevor der Rückruf für die Modulzurücksetzung aufgerufen wird.
Der Treiber muss immer den Wert der letzten abgeschlossenen Fence-ID für die GPU beibehalten, da diese Fence-ID erforderlich ist, um das DmaPreempted.LastCompletedFenceId-Member der DXGKARGCB_NOTIFY_INTERRUPT_DATA-Struktur einer Nachricht zur präemptiven Unterbrechung festzulegen. Die letzte abgeschlossene Fence-ID sollte nur in diesen Situationen erhöht werden:
- Wenn ein Paket abgeschlossen ist (nicht vorzeitig), sollte die letzte abgeschlossene Fence-ID auf die Fence-ID des abgeschlossenen Pakets festgelegt werden.
- Wenn DxgkDdiResetEngine erfolgreich ist, sollte die letzte abgeschlossene Fence-ID auf den Wert des LastCompletedFenceId-Members festgelegt werden, das vom Modulzurücksetzungsaufruf zurückgegeben wird.
- Beim adapterweiten Zurücksetzen sollte die letzte abgeschlossene Fence-ID auf allen Knoten auf die letzte übermittelte Fence-ID zum Zeitpunkt der Zurücksetzung erhöht werden.
Hier sehen Sie eine chronologische Sequenz einer erfolgreichen Modulzurücksetzung aus Sicht des GPU-Schedulers:
Ein vorzeitiger Versuch wird ausgegeben.
Ein GPU-Timeout wird erkannt.
Der GPU-Scheduler erstellt eine Momentaufnahme der letzten übermittelten und abgeschlossenen Fence-IDs, und Unterbrechungen vom Modul, für das ein Timeout aufgetreten ist, werden ignoriert. Diese Kombination ist ein unteilbarer Vorgang auf der Unterbrechungsebene des Geräts.
Wenn an diesem Punkt keine Pakete in der Hardwarewarteschlange vorhanden sind, beenden Sie den Vorgang. Diese Situation kann auftreten, wenn ein Paket im Zeitfenster zwischen Schritt 2 und 3 abgeschlossen wurde.
Alle in die Warteschlange eingereihten DPCs werden geleert.
Bereiten Sie die Modulzurücksetzung vor.
Rufen Sie DxgkDdiResetEngine auf.
Wenn der LastAbortedFenceId-Member kleiner als die letzte abgeschlossene Fence-ID oder größer als die zuletzt übermittelte Fence-ID ist, veranlasst Dxgkrnl eine Systemfehlerüberprüfung. In einer Absturzabbilddatei wird der Fehler durch die Meldung BugCheck 0x119 angegeben, die folgende vier Parameter enthält:
- 0xA, was bedeutet, dass der Treiber eine ungültige abgebrochene Fence-ID gemeldet hat
- Vom Treiber zurückgegebener LastAbortedFenceId-Wert
- Letzte abgeschlossene Fence-ID
- Ein interner Betriebssystemparameter
Wenn der LastAbortedFenceId-Wert gültig ist, fahren Sie wie folgt mit der Wiederherstellung durch Modulzurücksetzung fort. Wenn sich die Modulzurücksetzung auf ein Pagingpaket ausgewirkt hat, führt der GPU-Scheduler nach der Modulzurücksetzung eine adapterweite Zurücksetzung aus. Alle Geräte mit Zuweisungen, auf die von diesem Pagingpaket verwiesen wird, werden ebenfalls in den Fehlerzustand versetzt. Das Systemgerät selbst wird nicht in den Fehlerzustand versetzt und setzt die Ausführung nach Abschluss der Zurücksetzung fort.
Sonderfälle
Eine besondere Situation kann auftreten, wenn ein Paket auf der GPU zwischen Schritt 3 und 7 abgeschlossen wird. In diesem Fall muss der Treiber LastAbortedFenceId auf die Fence-ID des letzten abgeschlossenen Pakets festlegen, wenn keine Pakete in der Hardwarewarteschlange aus Sicht des Treibers vorhanden sind. Aus Sicht des Schedulers sieht es so aus, als ob ein solches Paket abgebrochen wurde. Daher versetzt der Scheduler das entsprechende Gerät in einen Fehlerzustand, obwohl das Paket schließlich abgeschlossen wurde.
Wenn der Treiber aus einem der folgenden Gründe keinen Zurücksetzungsvorgang ausführen kann, sollte ein Fehlerstatuscode zurückgegeben werden:
- Die Hardware befindet sich in einem ungültigen Zustand.
- Die Hardware kann die Knoten nicht zurücksetzen.
Wenn der GPU-Scheduler einen Fehlerstatuscode empfängt, führt er einen adapterweiten Zurücksetzungs- und Neustartvorgang gemäß dem TDR-Verhalten vor Windows 8 aus.
Auch wenn ein Treiber das TDR-Verhalten von Windows 8 und höher nutzt, gibt es Fälle, in denen der GPU-Scheduler eine Zurücksetzung und einen Neustart des gesamten logischen Adapters anfordert. Daher muss der Treiber weiterhin die Funktionen DxgkDdiResetFromTimeout und DxgkDdiRestartFromTimeout implementieren, und ihre Semantik bleibt die gleiche wie vor Windows 8. Wenn ein Versuch, einen physischen Adapter mit DxgkDdiResetEngine zurückzusetzen, zu einer Zurücksetzung des logischen Adapters führt, zeigt der Befehl !analyze des Windows-Debuggers an, dass der TdrReason-Wert des TDR-Wiederherstellungskontexts auf einen neuen Wert von TdrEngineTimeoutPromotedToAdapterReset (9) festgelegt ist.