window 显示驱动开发-视频内存供应和回收(二)
提供和回收 DDI
从Windows 8开始,用户模式驱动程序提供或回收内存的新函数可用。
驱动程序调用系统提供的这些函数来提供或回收内存分配:
- pfnOfferAllocationsCb
- pfnReclaimAllocationsCb
如果驱动程序支持 Microsoft Direct3D 10 硬件,则会实现以下函数:
- pfnOfferResources
- pfnReclaimResources
如果驱动程序支持 Microsoft Direct3D 9 硬件,则会实现以下功能。 此外,如果应用在使用 Direct3D 9 硬件上运行的 Direct3D 11 API 时提供或回收其分配,则 Direct3D 运行时将调用以下函数:
- OfferResources
- ReclaimResources
使用以下关联的结构和枚举:
- D3DDDI_OFFER_PRIORITY
- D3DDDIARG_OFFERRESOURCES
- D3DDDIARG_RECLAIMRESOURCES
- D3DDDICB_OFFERALLOCATIONS
- D3DDDICB_RECLAIMALLOCATIONS
- DXGI_DDI_ARG_OFFERRESOURCES
- DXGI_DDI_ARG_RECLAIMRESOURCES
- DXGI1_2_DDI_BASE_FUNCTIONS
若要支持产品/服务/回收功能,请从Windows 8此结构具有两个新成员:
- D3DDDI_ALLOCATIONLIST
应仔细测试驱动程序是否正确处理此功能,因为在放弃分配后,其中的所有数据都将丢失。
1. 核心概念
功能目标:动态管理 GPU 内存(尤其是共享系统内存的集成显卡),通过临时释放闲置资源减少内存压力。
适用场景:
- Direct3D 9/10/11 硬件驱动(WDDM 1.2+)。
- 移动设备、多应用并行等高内存压力环境。
2. 驱动程序回调函数
根据硬件支持的 Direct3D 版本,需实现不同的回调:
Direct3D 版本 | 回调函数 | 调用方 | 关联数据结构 |
---|---|---|---|
Direct3D 9 | OfferResources ReclaimResources | Direct3D 运行时(D3D9/D3D11 兼容模式) | D3DDDIARG_OFFERRESOURCES D3DDDIARG_RECLAIMRESOURCES |
Direct3D 10+ | pfnOfferResources pfnReclaimResources | 用户模式驱动(UMD) | DXGI_DDI_ARG_OFFERRESOURCES DXGI_DDI_ARG_RECLAIMRESOURCES |
内核模式通用 | pfnOfferAllocationsCb pfnReclaimAllocationsCb | 显示微型端口驱动(KMD) |
3. 关键数据结构与枚举
(1) 优先级控制(D3DDDI_OFFER_PRIORITY)
typedef enum _D3DDDI_OFFER_PRIORITY {D3DDDI_OFFER_PRIORITY_LOW = 1, // 低优先级(如缓存数据)D3DDDI_OFFER_PRIORITY_NORMAL = 2, // 常规资源D3DDDI_OFFER_PRIORITY_HIGH = 3 // 高优先级(避免回收)
} D3DDDI_OFFER_PRIORITY;
(2) Direct3D 9 结构(示例)
// 提供资源参数
typedef struct _D3DDDIARG_OFFERRESOURCES {D3DKMT_HANDLE hDevice;UINT NumResources;D3DKMT_HANDLE* phResources;D3DDDI_OFFER_PRIORITY Priority;
} D3DDDIARG_OFFERRESOURCES;// 回收资源结果
typedef struct _D3DDDIARG_RECLAIMRESOURCES {UINT NumResources;D3DKMT_HANDLE* phResources;BOOL* pDiscarded; // 输出:是否被丢弃
} D3DDDIARG_RECLAIMRESOURCES;
(3) 内核模式回调结构(D3DDDICB_OFFERALLOCATIONS)
typedef struct _D3DDDICB_OFFERALLOCATIONS {UINT NumAllocations;D3DKMT_HANDLE* phAllocations;D3DDDI_OFFER_PRIORITY Priority;
} D3DDDICB_OFFERALLOCATIONS;
4. 实现步骤
(1) 用户模式驱动(UMD)
Direct3D 10/11 驱动:
// 在 DXGI1_2_DDI_BASE_FUNCTIONS 中注册回调
DXGI1_2_DDI_BASE_FUNCTIONS BaseFunctions;
BaseFunctions.pfnOfferResources = YourOfferResourcesHandler;
BaseFunctions.pfnReclaimResources = YourReclaimResourcesHandler;
Direct3D 9 驱动:
实现 OfferResources 和 ReclaimResources 导出函数。
(2) 内核模式驱动(KMD)
响应 Offer/Reclaim 请求:
NTSTATUS DxgkDdiOfferAllocations(DXGKARG_OFFER_ALLOCATIONS* pOffer) {for (UINT i = 0; i < pOffer->NumAllocations; i++) {MarkAsOfferable(pOffer->pAllocations[i], pOffer->Priority);}return STATUS_SUCCESS;
}NTSTATUS DxgkDdiReclaimAllocations(DXGKARG_RECLAIM_ALLOCATIONS* pReclaim) {for (UINT i = 0; i < pReclaim->NumAllocations; i++) {pReclaim->pResults[i] = CheckAllocationValid(pReclaim->pAllocations[i]) ?DXGK_RECLAIM_RESULT_OK : DXGK_RECLAIM_RESULT_DISCARDED;}return STATUS_SUCCESS;
}
5. 关键注意事项
- 数据丢失风险:回收时若返回 DISCARDED,驱动必须重建资源内容(如重新上传纹理)。
- 线程安全:Offer/Reclaim 可能与其他渲染操作并发,需加锁保护资源状态。
- 性能优化:高优先级资源(如帧缓冲区)应避免频繁 Offer。
6. 测试验证(WHCK 要求)
测试项:Device.Graphics.WDDM12.Render.OfferReclaim
验证点:
- Offer 后内存释放是否正确。
- Reclaim 时能否正确处理 DISCARDED 状态。
- 多线程并发调用稳定性。
7. 调试技巧
- ETW 日志:监控 Microsoft-Windows-DxgKrnl 事件中的 Offer/Reclaim 调用。
- 错误注入:强制模拟 DISCARDED 状态测试驱动恢复逻辑。
8. 总结
必须实现:WDDM 1.2+ 驱动需完整支持 Offer/Reclaim DDI。
跨版本兼容:Direct3D 9/10/11 驱动需分别适配。
健壮性关键:正确处理资源丢弃和重建是核心挑战。
适用于 移动设备、集成显卡及多应用高负载场景 的驱动程序开发。