功能概述
上下文監視機制是GPU與CPU協同計算的核心同步技術,通過受監視圍欄(Monitored Fence)實現跨硬件單元的高效協調。其核心目標是解決以下場景的同步需求:
- GPU引擎間同步:例如在多渲染管線中,后處理階段需等待前級計算完成。
- CPU-GPU異構同步:如CPU需確保GPU完成紋理上傳后再進行后續邏輯處理。
- 跨設備資源訪問:在異構計算集群中,避免多個GPU或CPU核心對共享資源的讀寫沖突。
傳統信號量機制存在內核態切換開銷大、靈活性不足等問題,而受監視圍欄通過以下創新實現優化:
- 硬件級原子操作:直接通過GPU/CPU虛擬地址讀寫圍欄值,減少軟件層干預。
- 分離式地址映射:為CPU和GPU提供獨立的內存視圖,兼顧安全性與性能。
- 自適應環繞處理:針對32位原子操作硬件自動管理圍欄值溢出,降低開發者負擔。?
受監視圍欄的創建
創建流程與技術細節
1. 觸發條件
- Direct3D運行時檢測到應用程序調用CreateFence API時,生成D3DDDI_MONITORED_FENCE類型的請求。
- 用戶模式驅動程序(UMD)通過CreateSynchronizationObjectCb回調接收創建指令。
2. 參數定義
- 初始值(InitialValue):通常設為0,表示圍欄初始未觸發狀態。在環形緩沖區場景中可預設為歷史最大值以規避環繞問題。
- 標志位(Flags):
- D3DDDI_FENCE_FLAG_SHARED:允許跨進程共享圍欄對象。
- D3DDDI_FENCE_FLAG_CPU_WRITABLE:啟用CPU直接寫權限(需硬件支持MMIO)。
- D3DDDI_FENCE_FLAG_GLOBAL_TIMEOUT:設置全局等待超時閾值(默認禁用)。
3.內核資源分配
圖形內核完成以下操作:
- 在非分頁內存池分配同步對象控制塊(Sync Control Block, SCB),存儲圍欄狀態機信息。
- 建立雙重地址映射:
- CPU端映射:將物理地址轉換為FenceValueCPUVirtualAddress,屬性為MEMORY_CACHED_TYPE_WRITEBACK,確保CPU讀取時可通過緩存加速
- GPU端映射:若硬件支持Reserved Virtual Address (RVA),則分配固定GPU虛擬地址FenceValueGPUVirtualAddress,否則使用PCI BAR空間映射。
- 初始化圍欄監控線程,該線程以10μs周期輪詢高優先級圍欄對象(可通過注冊表調整間隔)。
4.返回值結構
字段 | 技術規格 |
hSyncObject | 64位內核對象句柄,包含版本號(高16位)和對象ID(低48位),有效周期與設備綁定。 |
FenceValueCPUVirtualAddress | 對齊至64字節緩存行,避免False Sharing。支持通過CLFLUSH指令手動刷新緩存。 |
FenceValueGPUVirtualAddress | 對于NVIDIA Ampere架構,強制使用Non-Coherent內存屬性以兼容L2 TCC緩存策略。 |
原子操作兼容性處理
當GPU聲明DXGK_VIDSCHCAPS::No64BitAtomics=1時,系統啟用兼容模式:
- 將64位圍欄拆分為兩個32位寄存器(高32位為周期計數器,低32位為遞增值)。
- 每次信號操作自動執行:
if (Low32 == UINT32_MAX) { High32++; Low32 = 0;
} else { Low32++;
}
- 等待邏輯改為:TargetValue ≤ (High32 << 32) | Low32
- 約束條件:TargetValue - LastSignaledValue < UINT32_MAX/2,防止高32位計數器溢出誤判。
GPU信號機制
硬件信號路徑
支持原子寫入的GPU可直接生成以下機器指令:
; AMD GCN 示例
global_atomic_add_x2 v[FenceValueGPUVirtualAddress], v[signal_value]
s_waitcnt lgkmcnt(0)
此操作在GPU L1緩存中完成,約消耗40個時鐘周期。
軟件信號路徑
當GPU無法直接訪問圍欄地址(如舊式移動GPU),UMD需構造信號包:
-
在命令緩沖區插入NOP占位符,預留12字節空間。
- 調用SignalSynchronizationObjectFromGpuCb,內核將填充以下微代碼:
0xCAFEBABE // 魔數標識信號包
FenceObjectID
SignalValue
- GPU調度器執行到該包時,通過PM4引擎間接更新圍欄值,增加約200ns延遲。
內核監控流程
- 每個GPU上下文維護一個PendingFenceList,記錄未完成的圍欄信號。
- 調度器在提交命令緩沖區前,執行以下操作:
- 將當前時間戳寫入圍欄值的Bit 63-62(保留位),用于死鎖檢測。
- 使用紅黑樹按信號值排序,優化遍歷效率。
- 完成事件觸發后,內核工作者線程:
- 鎖定圍欄對象的自旋鎖(SpinLock)。
- 對比當前值與等待隊列中的目標閾值。
- 對滿足條件的等待項,調用KeSetEvent喚醒相關線程。
GPU等待操作
精細化依賴管理
1.多級等待鏈
例如:
UMD可提交嵌套等待指令
// 等待FenceA≥100 且 FenceB≥200
pfnWaitForSynchronizationObjectFromGpuCb(hFenceA, 100, D3DDDI_WAIT_FLAG_AND);
pfnWaitForSynchronizationObjectFromGpuCb(hFenceB, 200, D3DDDI_WAIT_FLAG_AND);
內核將其轉換為依賴圖節點,確保所有條件滿足后才調度后續任務。
2.超時處理
若等待超過500ms(可配置),內核觸發Timeout Workflow:
- 生成WER錯誤報告,包含當前所有圍欄狀態快照。
- 強制推進圍欄值至目標值,標記設備為"丟失"狀態。
- 向UMD返回STATUS_GRAPHICS_DRIVER_THREAD_REQUEST_TIMEOUT錯誤碼。?