调用 CreateResource2 函数时:
- 设置 D3DDDIARG_CREATERESOURCE2 结构的 Flags 成员中的 Primary 和 SharedResource 位字段标志。
- 可能还会设置 Flags 中的其他位字段标志,例如:
- 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_RESOURCE
if (!(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 完整创建序列
sequenceDiagram
UMD->>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 认证检查清单
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 级加速
评论前必须登录!
注册