カーネル モード ドライバーからの CPU イベントの通知

カーネル モード ドライバー (KMD) が何かについてユーザー モード ドライバー (UMD) に通知する CPU イベントを通知する必要がある場合があります。例えば:

  • KMD がオブジェクトの 1 つが不適切な状態にあり、UMD に通知する必要があることを検出した場合。
  • KMD が UMD に何らかのイベントが発生したことを通信する必要がある GPU デバッグ中。 GPU のコントロール パネルがある IHV の場合、KMD による CPU イベントのシグナル通知により、KMD は内部イベントについてコントロール パネルアプリに通知できます。

通常、UMD は CPU イベントを作成し、その NT ハンドルをエスケープ プライベート データ内の KMD に渡すことができます。 NT ハンドルは仮想マシンの境界を越えて使用できないため、この方法は GPU 準仮想化 (GPU-PV) シナリオでは機能しません。

Windows 11 バージョン 21H2 (WDDM 3.0) 以降では、WDDM API が拡張され、UMD が KMD によって通知できる CPU イベント オブジェクトを作成できるようになりました。 この機能は、UMD がホスト上で実行されている場合と、GPU-PV を使用する仮想マシンで実行されている場合の両方で機能します。

機能のフロー

  • UMD によって CPU イベントが作成されます。

  • UMD は、D3DDDI_CPU_NOTIFICATION の種類を持つ GPU 同期オブジェクトを作成します。 作成されたオブジェクトは、D3DKMTCreateSynchronizationObject を呼び出すときに SignalByKmd フラグを設定することで KMD に表示されます。

  • DxgkrnlDXGKDDI_CREATECPUEVENTを呼び出して、KMD が独自のオブジェクトを作成できるようにします。

  • UMD は、D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE で既知のエスケープ型を使用して D3DKMTEscape を呼び出して、同期オブジェクトの意図した使用方法について KMD に通知します。

  • DxgkrnlDXGKDDI_ESCAPE を呼び出して、プライベート データを KMD に渡します。

  • ある時点で、KMD は CpuEventObject フラグを使用してDXGKCB_SIGNALEVENTを呼び出して CPU イベント オブジェクトを通知します。

  • UMD は D3DKMTDestroySynchronizationObject を呼び出して CPU イベント オブジェクトを破棄します。

  • DxgkrnlDXGKDDI_DESTROYCPUEVENTを呼び出して CPU イベント オブジェクトを破棄します。 この時点より後に DXGKCB_SIGNALEVENT を呼び出さないでください。

同期オブジェクトをコンテキスト キューに挿入することはできません。 DXGKCB_SIGNALEVENTを使用して KMD によってのみ通知できます。

CPU イベント同期オブジェクトを処理するユーザー モード API

KMD CPU イベント オブジェクトの作成

KMD CPU イベント オブジェクトは、次を使用してD3D12DDICB_CREATESYNCHRONIZATIONOBJECT2を呼び出すことによって GPU 同期オブジェクトとして作成されます。

  • D3DDDI_CPU_NOTIFICATION に設定された

  • オブジェクトが KMD によって通知されるように指定する SignalByKmd に設定されたフラグ。 このフラグは、D3DDDI_SYNCHRONIZATIONOBJECTINFO2Type メンバーがD3DDDI_CPU_NOTIFICATIONの場合にのみ設定できます。

SignalByKmd フラグを設定すると、KMD CPU イベント オブジェクトを作成するためにDXGKDDI_CREATECPUEVENTが呼び出されます。 同期オブジェクトを作成するときは、デバイス ハンドルを指定する必要があることに注意してください。

同期オブジェクトは、シグナル API と待機 API (D3DKMTSignalSynchronizationObjectD3DKMTWaitForSynchronizatioObject) では使用できません。 これは KMD によってのみ通知でき、UMD は対応する CPU イベントを待機できます。

KMD CPU イベント同期オブジェクトの使用状況を定義する UMD エスケープ

既知のエスケープが D3DDDI_DRIVERESCAPETYPE に追加されました。 D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGEは、KMD CPU イベント オブジェクトの使用目的について KMD に通知するために使用されます。 既知のエスケープは、DXGKARG_ESCAPE::Flags.DriverKnownEscape = 1 を設定することで定義されます。 既知のエスケープは、セキュリティで保護された仮想マシンからでもホストに送信されます。

次のコード スニペットに用途例を示します。

D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE Command = {};
Command.EscapeType = D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE;
Command.hSyncObject = SyncObjectHandle;
Command.Usage[0] = 1;

D3DKMT_ESCAPE Args = {};
Args.hAdapter = AdapterHandle;
Args.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
Args.Flags.DriverKnownEscape = 1;
Args.Flags.NoAdapterSynchronization = 1; // Prevent waking up the device from D3
Args.pPrivateDriverData = &Command;
Args.PrivateDriverDataSize = sizeof(Command);

NTSTATUS Status = D3DKMTEscape(&Args);

Dxgkrnl は、次のようにDXGKDDI_ESCAPEを呼び出します。

  • 同期オブジェクトの作成に使用されたミニポート デバイス ハンドルに設定された hDevice
  • D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE構造体を指す pPrivateDriverData
  • PrivateDriverDataSizesizeof(D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE)に設定されている

KMD CPU イベント オブジェクトの作成と破棄

次の DDI を使用して、KMD CPU イベント同期オブジェクトを作成および破棄します。

KMDからのCPUイベントオブジェクトの通知

CPU イベント オブジェクトを通知するために、KMD は IRQL <= DISPATCH_LEVEL で DXGKCB_SIGNALEVENT を呼び出し、DXGKARGCB_SIGNALEVENT 構造体の値を次のように設定します。

  • hDxgkProcess は 0 です。

  • hEvent は、DXGKDDI_CREATECPUEVENT に 渡される Dxgkrnl CPU イベント オブジェクト ハンドルと 同じです。

  • CpuEventObject は 1 である必要があります。

  • 予約済みは 0 である必要があります。