window显示驱动开发—DirectX 9 资源创建

发布于:2025-08-17 ⋅ 阅读:(13) ⋅ 点赞:(0)

调用 CreateResource2 函数时:

  • 设置 D3DDDIARG_CREATERESOURCE2 结构的 Flags 成员中的 Primary 和 SharedResource 位字段标志。
  • 可能还会设置 Flags 中的其他位字段标志,例如:
  1. RenderTarget
  2. 纹理
  3. DecodeRenderTarget
  4. RestrictedContent
  5. 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_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 认证检查清单

  1. 正确处理所有标准标志组合
  2. 强制RefreshRate=0的实现
  3. VidPnSourceId有效性验证
  4. 保护内存分配路径测试

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 级加速 

 


网站公告

今日签到

点亮在社区的每一天
去签到