與 Microsoft Windows 2000 顯示驅動程序模型不同,Windows Vista 顯示驅動程序模型允許創建比可用物理視頻內存總量更多的視頻內存資源,然后根據需要分頁進出視頻內存。 換句話說,并非所有視頻內存資源都同時位于視頻內存中。
GPU 的管道中可以有多個 DMA 緩沖區。 這些活動 DMA 緩沖區引用的視頻內存資源必須位于視頻內存中。 其他空閑視頻內存資源可以分頁到系統內存。
在 GPU 計劃程序調用顯示微型端口驅動程序的 DxgkDdiSubmitCommand 函數以將 DMA 緩沖區提交到 GPU 之前,計劃程序必須確保 DMA 緩沖區使用的所有視頻內存資源實際上都在視頻內存中。 如果某些資源不在視頻內存中,則必須從系統內存中分頁。 GPU 計劃程序必須調用視頻內存管理器來查找視頻內存中的空間,以便將必要的視頻內存資源數據從系統內存傳輸到視頻內存。 當視頻內存需求較高時,GPU 計劃程序必須調用視頻內存管理器,以將空閑視頻內存資源數據傳輸到系統內存,以便為所需的視頻內存資源數據騰出空間。 包含用于在視頻和系統內存之間傳輸數據的命令的特殊用途 DMA 緩沖區稱為分頁緩沖區。 視頻內存管理器調用顯示微型端口驅動程序的 DxgkDdiBuildPagingBuffer 函數來創建分頁緩沖區,驅動程序將硬件特定的數據傳輸命令寫入該緩沖區。
1. 內存虛擬化架構對比
Windows 2000 (XPDM) 模型
- 靜態分配:資源一旦創建即永久占用顯存
- 硬性限制:總資源大小 ≤ 物理顯存容量
- 問題:多應用競爭顯存時需頻繁切換上下文
Windows Vista+ (WDDM) 模型
- 虛擬化池:所有應用共享的虛擬顯存空間(物理顯存 + 系統內存)
- 按需分頁:僅活躍資源占用物理顯存
- 優勢:支持的總資源量 >> 物理顯存容量
2. 關鍵組件協作流程
(1) 分頁觸發條件
當 GPU 調度器準備提交 DMA 緩沖區時:
BOOL CheckResourceResidency(DMA_BUFFER* dmaBuffer) {foreach (Resource* res in dmaBuffer->ReferencedResources) {if (!res->IsResidentInVRAM()) { // 檢查物理顯存駐留TriggerPaging(res); // 觸發分頁操作return FALSE;}}return TRUE;
}
(2) 分頁緩沖區構建
(3) 分頁緩沖區示例內容
// AMD GPU 的分頁命令示例
struct PAGE_COMMAND {uint64_t srcSysMemAddr; // 系統內存源地址uint64_t dstVramAddr; // 顯存目標地址uint32_t size; // 傳輸數據大小uint32_t tilingFlags; // 塊狀排列參數
};void BuildPagingBuffer(PAGE_COMMAND* buffer, Resource* res) {buffer->srcSysMemAddr = res->sysMemBacking;buffer->dstVramAddr = VidMmAllocVram(res->size);buffer->size = res->size;buffer->tilingFlags = res->tilingMode;
}
3. 內存管理策略
(1) 駐留集管理
- 活動集(Working Set):當前 DMA 緩沖區引用的資源必須駐留
- LRU 策略:非活躍資源按最近使用時間排序逐出
void VidMmEvictResources(uint64_t requiredSize) {while (freeVram < requiredSize) {Resource* victim = FindLRUResource();CopyToSystemMemory(victim); // 回寫系統內存FreeVram(victim->vramAddr);}
}
(2) 并發控制
柵欄(Fence)同步:確保分頁操作完成前 GPU 不訪問資源
void SubmitPagingBuffer(DMA_BUFFER* pagingBuf) {uint64_t fenceVal = InsertFence();QueueToGpu(pagingBuf, fenceVal);WaitForFence(fenceVal); // 等待傳輸完成
}
4. 開發者注意事項
用戶模式驅動(UMD)
// 創建資源時應考慮分頁開銷
HRESULT CreateTexture(UINT size, bool isFrequentlyUsed) {D3DDDI_ALLOCATIONINFO info = {0};if (isFrequentlyUsed) {info.Flags.PreferContiguous = 1; // 提示VidMm優先駐留}return pfnAllocateCb(&info);
}
內核模式驅動(KMD)
// 必須正確處理分頁失敗
NTSTATUS DxgkDdiBuildPagingBuffer(IN_PDXGKARG_BUILDPAGINGBUFFER pArgs)
{if (!CheckHwCapability(pArgs->SizeRequired)) {return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;}// ...生成硬件命令
}
5. 性能優化技巧
技術 | 適用場景 | 實現方式 |
---|---|---|
預加載(Preload) | 關鍵幀資源加載 | 在Present前異步提交分頁請求 |
批量傳輸 | 大量小資源遷移 | 合并多個資源到單個分頁緩沖區 |
壓縮分頁 | 帶寬受限系統 | 實現驅動級內存壓縮/解壓 |
智能駐留 | 開放世界游戲地形 | 使用D3DDDI_ALLOCATIONFLG_PERSISTENT 標記 |
6. 調試與問題排查
常見問題癥狀
- GPU 掛起:分頁操作未完成導致依賴等待
- 幀率驟降:頻繁分頁引發帶寬瓶頸
- 紋理閃爍:分頁同步錯誤導致部分更新
診斷工具
# Windows Performance Analyzer (WPA)
wpaexporter.exe -d Graphics.gpuperf -o trace.csv# WinDbg 命令
!dxgkd_ext.vidmm -stats # 顯示內存分布統計
!dxgkd_ext.resource 0xADDR # 檢查資源狀態
演進與現狀
Windows 10+ 改進:
- 內存優先級:支持資源優先級分層管理
- 直接存儲:繞過CPU直接分頁(GPU←→NVMe)
- UMA優化:統一內存架構下的零拷貝分頁
開發者適配建議:
// 使用DX12內存池提示
D3D12_HEAP_PROPERTIES heapProps = {.Type = D3D12_HEAP_TYPE_DEFAULT,.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE,.MemoryPoolPreference = D3D12_MEMORY_POOL_L1 // 顯存優先
};
WDDM 的內存虛擬化機制通過精細的分頁策略和硬件加速,實現了 GPU 內存資源的彈性管理,為現代圖形應用提供了更大的資源池和更高的內存利用率,同時也對驅動開發者的內存管理能力提出了更高要求。