window 显示驱动开发-视频内存的直接交替(二)
DirectFlip 设备驱动程序接口 (DDI)
这些函数和结构是针对Windows 8而新增的或更新的:
- CheckDirectFlipSupport
- CheckDirectFlipSupport (D3D11_1)
- DxgkDdiSetVidPnSourceAddress
- D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS
- D3DDDI_CHECK_DIRECT_FLIP_FLAGS
- D3DDDIARG_CHECKDIRECTFLIPSUPPORT
- D3DKMT_DIRECTFLIP_SUPPORT
- D3DKMT_QUERYADAPTERINFO
- D3DKMT_WAITFORVERTICALBLANKEVENT2
- D3DKMTWaitForVerticalBlankEvent2
- DXGK_DRIVERCAPS
- DXGK_SEGMENTFLAGS
- DXGK_SETVIDPNSOURCEADDRESS_FLAGS
1. 核心函数与结构概览
以下是为支持 Direct Flip 功能 在 Windows 8 (WDDM 1.2) 中新增或更新的关键接口:
类型 | 名称 | 作用 |
---|---|---|
函数 | CheckDirectFlipSupport | 检查硬件是否支持 Direct Flip(用户模式 D3D11.1 驱动)。 |
函数 | DxgkDdiSetVidPnSourceAddress | 内核模式驱动设置扫描源地址,实现直接翻转(关键路径)。 |
结构体 | D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS | 定义 Direct Flip 支持的检查标志(如窗口化兼容性)。 |
枚举 | D3DKMT_DIRECTFLIP_SUPPORT | 描述 Direct Flip 支持级别(完全/部分/不支持)。 |
回调 | D3DKMTWaitForVerticalBlankEvent2 | 扩展的垂直同步等待接口,支持 Direct Flip 时序控制。 |
2. 关键函数详解
(1) CheckDirectFlipSupport (UMD)
调用方:Direct3D 11.1+ 用户模式驱动。
作用:验证当前交换链配置是否支持 Direct Flip。
参数:
typedef struct _D3DDDIARG_CHECKDIRECTFLIPSUPPORT {D3DKMT_HANDLE hDevice; // 设备句柄D3DKMT_HANDLE hPrimarySurface; // 主表面句柄D3DKMT_HANDLE hSecondarySurface;// 后台缓冲区句柄BOOL Supported; // 输出:是否支持
} D3DDDIARG_CHECKDIRECTFLIPSUPPORT;
实现示例:
BOOL CheckDirectFlipSupport(D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS Flags) {return (Flags & D3D11_1_DDI_CHECK_DIRECT_FLIP_SURFACE_REQUIREMENTS) != 0;
}
(2) DxgkDdiSetVidPnSourceAddress (KMD)
调用时机:翻转操作时由 Dxgkrnl 调用。
关键参数:
typedef struct _DXGKARG_SETVIDPNSOURCEADDRESS {DXGK_VIDPNSOURCEADDRESS_FLAGS Flags; // 包含 DirectFlip 标志HANDLE hPrimaryAllocation; // 前台缓冲区分配句柄PHYSICAL_ADDRESS PrimaryAddress; // 扫描物理地址
} DXGKARG_SETVIDPNSOURCEADDRESS;
驱动行为:
若 Flags.DirectFlip=1,直接配置显示控制器扫描地址,跳过 DWM 合成。
必须验证缓冲区格式/布局是否符合扫描要求(如线性内存、无压缩)。
3. 关键结构体与枚举
(1) D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS
typedef enum _D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS {D3D11_1_DDI_CHECK_DIRECT_FLIP_SURFACE_REQUIREMENTS = 0x1, // 表面需满足扫描条件D3D11_1_DDI_CHECK_DIRECT_FLIP_WINDOWED = 0x2 // 支持窗口化 Direct Flip
} D3D11_1_DDI_CHECK_DIRECT_FLIP_FLAGS;
(2) D3DKMT_DIRECTFLIP_SUPPORT
typedef enum _D3DKMT_DIRECTFLIP_SUPPORT {D3DKMT_DIRECTFLIP_NONE = 0, // 不支持D3DKMT_DIRECTFLIP_PARTIAL = 1, // 部分支持(如仅全屏)D3DKMT_DIRECTFLIP_FULL = 2 // 完全支持(全屏+窗口化)
} D3DKMT_DIRECTFLIP_SUPPORT;
(3) DXGK_SETVIDPNSOURCEADDRESS_FLAGS
typedef struct _DXGK_SETVIDPNSOURCEADDRESS_FLAGS {UINT DirectFlip : 1; // 当前为 Direct Flip 操作UINT SrcColorSpaceChanged : 1; // 颜色空间变更需处理// ... 其他标志位
} DXGK_SETVIDPNSOURCEADDRESS_FLAGS;
4. 驱动实现流程
(1) 用户模式驱动(UMD)
初始化时检查支持:
D3DKMT_QUERYADAPTERINFO QueryInfo = {0};
QueryInfo.Type = KMTQAITYPE_DIRECTFLIP_SUPPORT;
D3DKMTQueryAdapterInfo(&QueryInfo); // 获取 D3DKMT_DIRECTFLIP_SUPPORT
Present 时请求 Direct Flip:
pSwapChain->Present(0, DXGI_PRESENT_DIRECT_FLIP);
(2) 内核模式驱动(KMD)
声明能力:
DXGK_DRIVERCAPS Caps = {0};
Caps.FlipCaps.DirectFlip = 1; // 在 DxgkDdiQueryAdapterInfo 中返回
处理翻转:
NTSTATUS DxgkDdiSetVidPnSourceAddress(DXGKARG_SETVIDPNSOURCEADDRESS* pArgs) {if (pArgs->Flags.DirectFlip) {if (!ValidateScanoutSurface(pArgs->hPrimaryAllocation)) {return STATUS_GRAPHICS_INVALID_SCANOUT_SURFACE;}ProgramHardwareScanout(pArgs->PrimaryAddress);}return STATUS_SUCCESS;
}
5. 认证与调试
WHCK 测试项:
- Device.Graphics.WDDM12.DirectFlip.Functional
- Device.Graphics.WDDM12.DirectFlip.Power
调试工具:
- GPUView:观察翻转队列是否绕过 DWM。
- ETW 日志:过滤 Microsoft-Windows-DxgKrnl 的 DirectFlip_* 事件。
6. 常见问题与解决
问题 | 排查步骤 |
---|---|
Direct Flip 未触发 | 检查 DXGK_DRIVERCAPS 声明、表面格式(需 DXGI_FORMAT_R8G8B8A8_UNORM )。 |
切换时撕裂 | 确保 FlipOnVSyncMmIo=1 且 VSync 信号严格同步。 |
窗口化模式失败 | 验证 D3D11_1_DDI_CHECK_DIRECT_FLIP_WINDOWED 是否支持。 |
7. 总结
必要性:Direct Flip 是 WDDM 1.2+ 驱动必须实现的功能,尤其针对移动设备优化。
关键点:
正确实现 DxgkDdiSetVidPnSourceAddress 的 Direct Flip 路径。
严格验证扫描表面的硬件兼容性。
性能收益:全屏应用内存带宽降低 30-50%,显著提升电池续航。