Share via


Windows 8 以降での TDR

Windows 8 以降では、GPU タイムアウトの検出と回復 (TDR) の動作により、アダプター全体のリセットを必要とするのではなく、個々の物理アダプターの一部をリセットできます。

TDR の詳細については、「 タイムアウトの検出と回復 (TDR)」 を参照してください。

要件

  • WDDM の最小バージョン: 1.2
  • Windows の最小バージョン: 8
  • ドライバーの実装 — 完全なグラフィックスおよびレンダーのみ: 必須
  • WHLK の要件とテスト: Device.Graphics...TDRResiliency

TDR デバイス ドライバー インターフェイス (DDI)

この動作の変更に対応するために、ディスプレイ ミニポート ドライバーは、以下の関数を実装します。

ディスプレイ ミニポート ドライバーは、DXGK_DRIVERCAPS.SupportPerEngineTDR メンバーを設定することで、これらの関数をサポートすることを示し、この場合はこれらの関数のすべてを実装する必要があります。

Note

これらの関数をサポートするドライバーは、DxgkDdiCollectDbgInfo 関数のレベル 0 の同期もサポートする必要があります。 これは、リセット操作の影響を受けず、レベル 0 のミニポート呼び出しを続行できるようにするためです。 「DxgkDdiCollectDbgInfo」の備考を参照してください。

上記の関数には、次の構造体が関連付けられています。

Nodes

上記の TDR 機能で使用されているように、 ノード は、個別にスケジュールできる 1 つの物理アダプターの複数部分のうちの 1 つです。 たとえば、3D ノード、ビデオ デコード ノード、コピー ノードはすべて同じ物理アダプター内に存在でき、DXGKARG_QUERYDEPENDENTENGINEGROUP. NodeOrdinal メンバーに (DxgkDdiQueryDependentEngineGroup の呼び出し) でそれぞれに個別のノード序数値を割り当てることができます。

物理アダプター内のノードの数は、NbAsymetricProcessingNodes メンバー (DXGK_DRIVERCAPS.GpuEngineTopology のメンバー)で ミニポート ドライバーによって報告されます。

ノード序数値は、コンテキストの作成時に NodeOrdinal メンバー (DXGKARG_CREATECONTEXT 構造体のメンバー) で渡されます。

エンジン

上記の TDR 機能で使用されているように、 エンジン は 1 つの論理アダプターとして機能する複数の物理アダプター (または GPU) の 1 つです。 DirectX グラフィックス カーネル サブシステムは、このような構成をサポートしますが、各エンジンが同じ数のノードを持っている必要があります。

たとえば、GPU スケジューラでは、エンジン 0 が物理アダプター 0 に対応すると見なされます。 エンジン 0 には、アダプター 1 に対応するエンジン 1 と同じ数のノードが必要です。

コンテキスト作成時のエンジンまたは序数値

コンテキストが作成されると、エンジンの序数値に対応する 1 ビットが、EngineAffinity メンバー (DXGKARG_CREATECONTEXT 構造体のメンバー) に設定されます。 これと他のスケジューラ関連構造体の EngineOrdinal メンバーは、0 から始まるインデックスです。 EngineAffinity の値は 1 <<EngineOrdinal であり、EngineOrdinalEngineAffinity の最上位ビット位置です。

エンジンのリセットの影響を受けないパケット

ドライバーは、エンジンのリセットが完了する前に完全に処理するには、エンジン ハードウェア キューに送信されたパケットを再送信するように GPU スケジューラから求められる場合があります。 ドライバーは、このようなパケットを再送信するには、次のガイドラインに従う必要があります。

  • ページング パケット: ドライバーは、元のフェンス ID を使用して、最初に送信されたのと同じ順序でページング パケットを再送信するように GPU スケジューラから要求されます。 このようなパケットは、新しいパケットがハードウェア キューに追加される前に再送信されます。
  • レンダリング パケット: GPU スケジューラは、レンダリング パケットに新しいフェンス ID を割り当ててから再送信します。

エンジンをリセットするための呼び出しシーケンス

DxgkDdiResetEngine が成功すると、GPU スケジューラは、エンジン リセット呼び出しから返される LastAbortedFenceId 値が、ハードウェア キュー内の既存のフェンス ID または GPU の最後に完了したフェンス ID のいずれかに対応することを保証します。 後者の状況は、GPU タイムアウトが検出された後、エンジン リセット コールバックが呼び出される前にハードウェア キューが空になったときに発生する可能性があります。

GPU 上で最後に完了したフェンス ID 値は、DmaPreempted.LastCompletedFenceId メンバー (DXGKARGCB_NOTIFY_INTERRUPT_DATA プリエンプション割り込み通知構造のメンバー) を設定する必要があるので、常にドライバーによって維持されている必要があります。 最後に完了したフェンス ID は、次の状況でのみ進める必要があります。

  • パケットが (割り込まれていない) 完了したら、最後に完了したフェンス ID を完了したパケットのフェンス ID に設定する必要があります。
  • DxgkDdiResetEngine が成功したら、最後に完了したフェンス ID を、エンジン リセット呼び出しによって返される LastCompletedFenceId メンバーの値に設定する必要があります。
  • アダプター全体のリセットでは、すべてのノードで最後に完了したフェンス ID を、リセット時に最後に送信されたフェンス ID に進める必要があります。

GPU スケジューラで見られるように、エンジンのリセットが成功した時系列シーケンスを次に示します。

  1. プリエンプション試行が発行されます。

  2. GPU タイムアウトが検出されました。

  3. 最後に送信され、完了したフェンス ID のスナップショットは GPU スケジューラによって取得され、タイムアウト したエンジンからの割り込みは無視されます。 これは、デバイス割り込みレベルでの 1 つのアトミック操作です。

  4. この時点でハードウェア キューにパケットがない場合は、終了します。 これは、手順 2 から 3 の時間枠でパケットが完了した場合に発生する可能性があります。

  5. キューに登録されているすべての DPC がフラッシュされます。

  6. エンジンのリセットを準備します。

  7. DxgkDdiResetEngine を呼び出します。

  8. LastAbortedFenceId メンバーが最後に完了したフェンス ID より小さいか、最後に送信されたフェンス ID より大きい場合、DirectX グラフィックス カーネル サブシステムによってシステム バグチェックが発生します。 クラッシュ ダンプ ファイルでは、エラーは、次の 4 つのパラメーターを持つ BugCheck 0x119 メッセージによって示されます。

    • ドライバーが無効な中止されたフェンス ID を報告したことを意味する 0xA
    • ドライバーによって返される LastAbortedFenceId
    • 最後に完了したフェンス ID
    • 内部オペレーティング システム パラメーター
  9. LastAbortedFenceId の値が有効な場合は、次のようにエンジンのリセット回復に進みます。 ページング パケットがエンジンのリセットの影響を受けた場合、GPU スケジューラは、アダプター全体のリセットでエンジンのリセットに従います。 そのページング パケットによって参照される割り当てを所有するすべてのデバイスも、エラー状態になります。 ただし、システム デバイス自体はエラー状態にならず、リセットが完了した後に実行を再開します。

特殊なケース

上記のステップ 3~7 の間に GPU でパケットが完了すると、特別な状況が発生する可能性があります。 この場合、ドライバーの観点からハードウェア キューにパケットがない場合は、 最後に完了したパケットのフェンス ID にドライバーがLastAbortedFenceId を設定する必要があります。 スケジューラの観点からは、このようなパケットが中止されたように見え、パケットが最終的に完了した場合でも、対応するデバイスはエラー状態になります。

ハードウェアが無効な状態であるか、ハードウェアがノードをリセットできないためにドライバーがリセット操作を実行できない場合、ドライバーはエラー状態コードを返す必要があります。 GPU スケジューラは、障害状態コードを受け取った場合、Windows 8 よりも前の TDR 動作に従ってアダプター全体のリセットおよび再起動操作を実行します。

ドライバーが Windows 8 以降の TDR 動作を選択した場合でも、GPU スケジューラが論理アダプター全体のリセットと再起動を要求する場合があります。 そのため、ドライバーは引き続き DxgkDdiResetFromTimeout 関数と DxgkDdiRestartFromTimeout 関数を実装する必要があり、そのセマンティクスは Windows 8 よりも前と同じです。 DxgkDdiResetEngine を使用して物理アダプターをリセットしようとすると、論理アダプターがリセットされると、Windows デバッガーの !analyze コマンドは、TDR 回復コンテキストの TdrReason 値が TdrEngineTimeoutPromotedToAdapterReset = 9 の新しい値に設定されていることを示します。