window显示驱动开发—DirectX 9 资源创建
调用 CreateResource2 函数时:
- 设置 D3DDDIARG_CREATERESOURCE2 结构的 Flags 成员中的 Primary 和 SharedResource 位字段标志。
- 可能还会设置 Flags 中的其他位字段标志,例如:
- RenderTarget
- 纹理
- DecodeRenderTarget
- RestrictedContent
- RestrictSharedAccess
- D3DDDIARG_CREATERESOURCE2 结构的 VidPnSourceId 成员已正确初始化。
- D3DDDIARG_CREATERESOURCE2 结构的 RefreshRate 成员包含零。
1. 标志位处理规范
1.1 必须设置的标志位
在创建MPO资源时,D3DDDIARG_CREATERESOURCE2结构的Flags成员必须包含:
Flags = D3DDDI_RESOURCE_FLAG_PRIMARY | D3DDDI_RESOURCE_FLAG_SHARED_RESOURCE;
1.2 可选标志位组合
标志位 | 用途 | 兼容性要求 |
---|---|---|
D3DDDI_RESOURCE_FLAG_RENDER_TARGET | 允许作为渲染目标 | 需硬件支持扫描输出+渲染混合 |
D3DDDI_RESOURCE_FLAG_TEXTURE | 允许作为纹理资源 | 需验证格式支持 |
D3DDDI_RESOURCE_FLAG_DECODE_RENDER_TARGET | 视频解码器专用目标 | 需配合RESTRICTED_CONTENT 使用 |
D3DDDI_RESOURCE_FLAG_RESTRICTED_CONTENT | 保护内容资源 | 必须启用硬件加密 |
D3DDDI_RESOURCE_FLAG_RESTRICT_SHARED_ACCESS | 限制共享访问 | 需实现访问控制列表(ACL) |
标志验证逻辑:
BOOL ValidateMpoFlags(UINT Flags) {// 必须包含PRIMARY和SHARED_RESOURCEif (!(Flags & D3DDDI_RESOURCE_FLAG_PRIMARY) || !(Flags & D3DDDI_RESOURCE_FLAG_SHARED_RESOURCE)) {return FALSE;}// 解码目标必须配合内容保护if ((Flags & D3DDDI_RESOURCE_FLAG_DECODE_RENDER_TARGET) &&!(Flags & D3DDDI_RESOURCE_FLAG_RESTRICTED_CONTENT)) {return FALSE;}return TRUE;
}
2. 关键字段处理
2.1 VidPnSourceId 验证
HRESULT CheckVidPnSource(UINT VidPnSourceId) {// 获取当前拓扑结构DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopology;DXGKARG_GETVIDPNTOPOLOGY vidPnTopologyArg = {0};NTSTATUS status = pDxgkInterface->DxgkCbGetVidPnTopology(hAdapter, &vidPnTopologyArg, &pVidPnTopology);// 验证SourceId有效性if (!NT_SUCCESS(status) || VidPnSourceId >= pVidPnTopology->GetNumVidPnSources()) {return E_INVALIDARG;}return S_OK;
}
2.2 RefreshRate 特殊处理
- 必须设置为0:表示使用当前显示器的原生刷新率
- 非零值处理:应返回STATUS_GRAPHICS_INVALID_DISPLAY_FREQUENCY
3. 多平面覆盖资源创建流程
3.1 完整创建序列
sequenceDiagramUMD->>KMD: CreateResource2(Flags=PRIMARY|SHARED)KMD->>DisplayEngine: 分配MPO平面资源DisplayEngine-->>KMD: 返回物理地址KMD->>MemoryManager: 注册保护内存区域MemoryManager-->>KMD: 分配句柄KMD-->>UMD: 返回资源句柄
3.2 错误码规范
错误场景 | 返回码 |
---|---|
无效的VidPnSourceId | STATUS_GRAPHICS_INVALID_VIDPN_SOURCEID |
非零RefreshRate | STATUS_GRAPHICS_INVALID_DISPLAY_FREQUENCY |
不支持的标志组合 | STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE |
硬件平面资源不足 | STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER |
4. 安全资源实现
4.1 保护内存分配
NTSTATUS AllocateProtectedMemory(D3DKMT_HANDLE hDevice,SIZE_T Size,D3DDDI_RESOURCE_FLAGS Flags,PHANDLE phProtectedAlloc)
{DXGK_ALLOCATIONINFOFLAGS allocFlags = {0};allocFlags.Protected = (Flags & D3DDDI_RESOURCE_FLAG_RESTRICTED_CONTENT) ? 1 : 0;allocFlags.RestrictSharedAccess = (Flags & D3DDDI_RESOURCE_FLAG_RESTRICT_SHARED_ACCESS) ? 1 : 0;return DxgkDdiCreateAllocation(hDevice, &allocFlags, Size, phProtectedAlloc);
}
4.2 访问控制列表
typedef struct _MPO_ACCESS_CONTROL {D3DKMT_HANDLE hDevice; // 拥有者设备HANDLE hProcess; // 创建进程ACCESS_MASK dwAccessRights; // 访问权限位掩码
} MPO_ACCESS_CONTROL;
5. WHQL 认证要求
5.1 必须通过的测试项
Device.Graphics.WDDM.MPO.CreateResource2
- 验证标志位组合
- 测试VidPnSourceId绑定
Device.Graphics.WDDM.ProtectedContent
- 保护资源创建/访问测试
5.2 认证检查清单
- 正确处理所有标准标志组合
- 强制RefreshRate=0的实现
- VidPnSourceId有效性验证
- 保护内存分配路径测试
6. 调试与优化
6.1 诊断命令
# 检查当前MPO资源状态
Get-WinEvent -LogName "Microsoft-Windows-DxgKrnl/Operational" |
Where-Object {$_.Id -eq 200} # MPO资源创建事件ID
6.2 性能计数器
// 在驱动中记录关键指标
void TrackMpoAllocPerformance() {PERF_COUNTER_INC(MPO_ALLOC_COUNT);PERF_COUNTER_ADD(MPO_ALLOC_SIZE, AllocSize);
}
7. 厂商特定实现
7.1 Intel 平台建议
- 使用 GTT (Graphics Translation Table) 优化保护内存访问
- 为 DECODE_RENDER_TARGET 启用 PAVP 1.1 加密
7.2 NVIDIA 平台建议
- 利用 NV12 平面压缩减少内存占用
- 对 RESTRICT_SHARED_ACCESS 资源启用 Turing 加密引擎
7.3 AMD 平台建议
- 结合 Secure Memory Zone 实现保护内存
- 为 PRIMARY 资源启用 ASIC 级加速