從內核模式驅動程式發出 CPU 事件的訊號
在某些情況下,核心模式驅動程式 (KMD) 需要發出 CPU 事件的訊號,以通知使用者模式驅動程式 (UMD) 相關專案;例如:
- 當 KMD 偵測到其中一個對象處於不良狀態,且需要通知 UMD 時。
- 在 GPU 偵錯期間,KMD 需要與 UMD 通訊,因為發生某些事件。 對於具有 GPU 控制面板的 IHV,KMD 發出 CPU 事件的訊號可讓 KMD 通知控制面板應用程式有關內部事件。
一般而言,UMD 可以建立 CPU 事件,並將其 NT 句柄傳遞至逸出私人數據中的 KMD。 此方法無法在 GPU 參數化 (GPU-PV) 案例中運作,因為 NT 句柄無法跨虛擬機界限使用。
從 Windows 11 21H2 版 (WDDM 3.0) 開始,WDDM API 已擴充為允許 UMD 建立可由 KMD 發出訊號的 CPU 事件物件。 當UMD在主機上或使用 GPU-PV 的虛擬機上執行時,此功能都適用。
功能流程
UMD 會建立 CPU 事件。
UMD 會建立具有 D3DDDI_CPU_NOTIFICATION 類型的 GPU 同步處理物件。 建立的物件會在呼叫 D3DKMTCreateSynchronizationObject 時設定 SignalByKmd 旗標,讓 KMD 可見。
Dxgkrnl 會 呼叫 DXGKDDI_CREATECPUEVENT ,以允許 KMD 建立自己的物件。
UMD 會呼叫具有 D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE已知逸出類型的 D3DKMTEscape,以通知 KMD 有關同步處理物件的預期使用方式。
Dxgkrnl 會 呼叫 DXGKDDI_ESCAPE ,以將私人數據傳遞至 KMD。
在某些時候,KMD 會使用 CpuEventObject 旗標呼叫DXGKCB_SIGNALEVENT,以發出 CPU 事件對象的訊號。
UMD 會呼叫 D3DKMTDestroySynchronizationObject 來終結 CPU 事件物件。
Dxgkrnl 會 呼叫DXGKDDI_DESTROYCPUEVENT 來終結 CPU 事件物件。 此時 不應該呼叫DXGKCB_SIGNALEVENT。
同步處理物件無法插入內容佇列。 它只能透過 KMD 使用 DXGKCB_SIGNALEVENT來發出訊號。
處理 CPU 事件同步物件的使用者模式 API
建立 KMD CPU 事件物件
KMD CPU 事件物件會藉由呼叫 D3D12DDICB_CREATESYNCHRONIZATIONOBJECT2下列專案來 建立為 GPU 同步處理物件:
類型 設定為 D3DDDI_CPU_NOTIFICATION。
設定為 SignalByKmd 的旗標,以指定 KMD 會發出物件訊號。 只有當D3DDDI_SYNCHRONIZATIONOBJECTINFO2的 Type 成員D3DDDI_CPU_NOTIFICATION時,才能設定此旗標。
設定 SignalByKmd 旗標時,將會呼叫 DXGKDDI_CREATECPUEVENT 來建立 KMD CPU 事件物件。 請注意,建立同步處理物件時,必須指定裝置句柄。
同步處理物件不能用於訊號和等候 API (D3DKMTSignalSynchronizationObject、 D3DKMTWaitForSynchronizatioObject) 。 它只能由 KMD 發出訊號,UMD 可以等候對應的 CPU 事件。
UMD 逸出以定義 KMD CPU 事件同步物件的使用方式
已知逸出已新增至 D3DDDI_DRIVERESCAPETYPE。 D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE 用來通知 KMD 有關 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 設定為用來建立同步處理物件的迷你埠裝置句柄
- pPrivateDriverData 指向 D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE 結構
- PrivateDriverDataSize 設為
sizeof(D3DDDI_DRIVERESCAPE_CPUEVENTUSAGE)
建立和終結 KMD CPU 事件物件
下列 DIS 可用來建立和終結 KMD CPU 事件同步物件:
從 KMD 發出 CPU 事件對象的訊號
若要發出 CPU 事件對象的訊號,KMD 會在 IRQL <= DISPATCH_LEVEL 呼叫 DXGKCB_SIGNALEVENT,並將 DXGKARGCB_SIGNALEVENT 結構值設定如下:
hDxgkProcess 等於 0。
hEvent 等於傳入至 DXGKDDI_CREATECPUEVENT 的 Dxgkrnl CPU 事件物件句柄。
CpuEventObject 必須是 1。
保留 必須是 0。