Microsoft Direct3D 运行时调用用户模式显示驱动程序的 CreateResource 函数,以创建用于视频处理的呈现目标图面。 用户模式显示驱动程序确定它应根据 CreateResource 的 pResource 参数指向的 D3DDDIARG_CREATERESOURCE 结构的 Flags 成员中的 VideoProcessRenderTarget 位字段标志创建用于视频处理的呈现目标图面。 用户模式显示驱动程序可以将此呈现目标用于视频处理,但不一定用于三维。 用户模式显示驱动程序可以在常规 RGB 三维渲染目标图面上执行视频处理。 但是,用户模式显示驱动程序通常可以输出为 3D 硬件不支持的 YUV 格式作为呈现目标。
以下是驱动程序应支持作为视频处理的有效呈现目标的唯一图面类型:
- 使用 VideoProcessRenderTarget 位字段标志创建的 RGB 或 YUV 图面。
- 使用 RenderTarget 位字段标志创建的 RGB 图面。
- 使用 RenderTarget 和 Texture 位字段标志创建的 RGB 纹理 。
渲染目标创建机制
核心标识标志
typedef struct _D3DDDIARG_CREATERESOURCE {
D3DDDIFORMAT Format; // 表面格式
UINT Flags; // 包含VideoProcessRenderTarget标志
// ...其他字段
} D3DDDIARG_CREATERESOURCE;
当创建用于视频处理的渲染目标时,Direct3D运行时会在D3DDDIARG_CREATERESOURCE结构中设置以下标志位:
关键标志位定义:
#define D3DDDI_VIDEOPROCESSRENDERTARGET 0x00080000
#define D3DDDI_RENDERTARGET 0x00000001
#define D3DDDI_TEXTURE 0x00000002
支持的渲染目标类型
- 专用视频处理渲染目标
标志组合:VideoProcessRenderTarget
格式支持:
- RGB格式:D3DDDIFMT_A8R8G8B8, D3DDDIFMT_X8R8G8B8
- YUV格式:D3DDDIFMT_NV12, D3DDDIFMT_YUY2, D3DDDIFMT_P010
驱动程序实现:
if (pCreateData->Flags & D3DDDI_VIDEOPROCESSRENDERTARGET) {
// 验证格式支持
if (!IsVideoProcessFormatSupported(pCreateData->Format)) {
return DXVA2_E_UNSUPPORTED_FORMAT;
}
// 分配视频专用表面
AllocateVideoProcessSurface(pCreateData);
}
-
常规RGB渲染目标
-
标志组合:RenderTarget
-
格式限制:
- 仅RGB格式
- 不支持YUV格式
实现示例:
if ((pCreateData->Flags & D3DDDI_RENDERTARGET) &&
!(pCreateData->Flags & D3DDDI_TEXTURE)) {
if (IsYUVFormat(pCreateData->Format)) {
return E_INVALIDARG; // YUV格式不支持纯RenderTarget
}
// 创建常规RGB渲染目标
}
-
纹理渲染目标
-
标志组合:RenderTarget | Texture
-
特殊考虑:
- 必须支持纹理采样
- 通常用于视频与3D内容混合
驱动程序处理:
if ((pCreateData->Flags & (D3DDDI_RENDERTARGET | D3DDDI_TEXTURE)) ==
(D3DDDI_RENDERTARGET | D3DDDI_TEXTURE)) {
if (!IsTextureRenderTargetFormat(pCreateData->Format)) {
return E_INVALIDARG;
}
// 创建纹理渲染目标
}
格式支持矩阵
格式类型 | VideoProcessRenderTarget | RenderTarget | RenderTarget+Texture |
---|---|---|---|
D3DDDIFMT_A8R8G8B8 | 支持 | 支持 | 支持 |
D3DDDIFMT_X8R8G8B8 | 支持 | 支持 | 支持 |
D3DDDIFMT_NV12 | 支持 | 不支持 | 不支持 |
D3DDDIFMT_YUY2 | 支持 | 不支持 | 不支持 |
D3DDDIFMT_P010 | 支持 | 不支持 | 不支持 |
高级实现策略
内存优化分配
void AllocateVideoProcessSurface(D3DDDIARG_CREATERESOURCE* pCreateData) {
if (IsYUVFormat(pCreateData->Format)) {
// YUV表面使用平铺内存布局
ConfigureTileMemoryLayout(pCreateData);
} else {
// RGB表面使用线性布局
ConfigureLinearMemoryLayout(pCreateData);
}
// 根据使用场景选择内存池
if (IsZeroCopySupported()) {
pCreateData->Pool = D3DDDIPOOL_VIDEOMEMORY;
} else {
pCreateData->Pool = D3DDDIPOOL_SYSTEMMEM;
}
}
多平面YUV处理
// 处理多平面YUV格式(如NV12)
if (pCreateData->Format == D3DDDIFMT_NV12) {
// 分配Y平面
AllocatePlane(pCreateData, 0, width, height);
// 分配UV平面
AllocatePlane(pCreateData, 1, width/2, height/2);
}
错误处理规范
格式不支持
if (IsYUVFormat(pCreateData->Format) &&
!(pCreateData->Flags & D3DDDI_VIDEOPROCESSRENDERTARGET)) {
return DXVA2_E_UNSUPPORTED_FORMAT;
}
标志冲突检测
if ((pCreateData->Flags & D3DDDI_VIDEOPROCESSRENDERTARGET) &&
(pCreateData->Flags & D3DDDI_DEPTHSTENCIL)) {
return E_INVALIDARG; // 深度模板与视频处理目标冲突
}
实际应用示例
运行时创建流程
// 创建专用视频处理目标(NV12格式)
D3DDDIARG_CREATERESOURCE createNV12 = {
D3DDDIFMT_NV12,
D3DDDI_VIDEOPROCESSRENDERTARGET,
D3DDDIPOOL_VIDEOMEMORY,
// ...其他参数
};
pDevice->CreateResource(&createNV12);
// 创建兼容的RGB渲染目标
D3DDDIARG_CREATERESOURCE createRGB = {
D3DDDIFMT_A8R8G8B8,
D3DDDI_RENDERTARGET | D3DDDI_TEXTURE,
D3DDDIPOOL_DEFAULT,
// ...其他参数
};
pDevice->CreateResource(&createRGB);
性能优化建议
表面重用策略
// 维护表面循环池
static std::vector<HANDLE> g_surfacePool;
HANDLE GetVideoProcessSurface() {
if (!g_surfacePool.empty()) {
HANDLE hSurface = g_surfacePool.back();
g_surfacePool.pop_back();
return hSurface;
}
// ...创建新表面
}
硬件加速检测
bool IsHardwareAccelerated(D3DDDIFORMAT format) {
DXVA2_VideoProcessorCaps caps;
pVP->GetVideoProcessorCaps(&caps);
if (caps.DeviceCaps & DXVA2_VPDev_HardwareDevice) {
return CheckFormatSupport(format);
}
return false;
}
此规范确保:
- 视频处理与3D渲染的兼容性
- 最优化的内存使用
- 硬件加速能力最大化利用
- 灵活的多格式支持