显示微型端口驱动程序应提交命令缓冲区以响应对 DxgkDdiRenderKm 函数的调用,如 提交命令缓冲区中所述。
驱动程序可以使用 DXGKARG_RENDER 结构的 MultipassOffset 成员来跟踪输入命令缓冲区处理的进度。 例如,显示微型端口驱动程序可以使用高 16 位作为上次处理命令的偏移量,并使用低 16 位来跟踪命令的处理。
1. 核心流程
当 DirectX 图形内核(Dxgkrnl.sys) 调用驱动程序的 DxgkDdiRenderKm 函数时,驱动程序必须:
- 解析输入命令缓冲区(来自内核模式 CDD)。
- 生成 GPU 可执行的 DMA 缓冲区(或直接提交硬件命令)。
- 使用 MultipassOffset 跟踪处理进度(多阶段处理时)。
2. 关键数据结构:DXGKARG_RENDR
成员 | 类型 | 说明 |
---|---|---|
pCommand |
const VOID* |
输入命令缓冲区的指针(由 CDD 提供)。 |
CommandLength |
UINT |
输入命令缓冲区的总长度(字节)。 |
MultipassOffset |
UINT |
进度跟踪字段(高16位:已处理偏移量;低16位:子进度)。 |
DmaBuffer |
DXGKARG_BUFFER |
输出的 DMA 缓冲区描述(供 GPU 执行)。 |
DmaSize |
UINT |
已写入 DMA 缓冲区的字节数(驱动程序设置)。 |
3. 多阶段处理(MultipassOffset 使用)
场景:当命令缓冲区过大或需要分段处理时,驱动程序需分多次调用完成提交。
字段拆分
高 16 位 (MultipassOffset >> 16):
记录已处理的命令缓冲区偏移量(字节)。
低 16 位 (MultipassOffset & 0xFFFF):
用于内部状态跟踪(如当前命令的子操作索引)。
伪代码示例
NTSTATUS DxgkDdiRenderKm(D3DKMDT_HDEVICE hDevice, CONST DXGKARG_RENDER* pArgs) {
UINT processedOffset = pArgs->MultipassOffset >> 16; // 已处理偏移
UINT subProgress = pArgs->MultipassOffset & 0xFFFF; // 子进度
while (processedOffset < pArgs->CommandLength) {
// 解析命令并生成 DMA 缓冲区
BOOL isComplete = ProcessCommand(
pArgs->pCommand + processedOffset,
pArgs->CommandLength - processedOffset,
&subProgress,
pArgs->DmaBuffer
);
if (!isComplete) {
// 更新进度并返回 STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER
pArgs->MultipassOffset = (processedOffset << 16) | subProgress;
return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
}
processedOffset += GetCommandSize(pArgs->pCommand + processedOffset);
subProgress = 0; // 重置子进度
}
pArgs->DmaSize = ...; // 设置实际写入的 DMA 大小
return STATUS_SUCCESS;
}
4. 错误处理与状态码
状态码 | 场景 |
---|---|
STATUS_SUCCESS |
所有命令已成功处理并提交。 |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER |
DMA 缓冲区不足,需继续调用(更新 MultipassOffset )。 |
STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE |
命令解析或执行失败(如非法指令)。 |
5. 硬件加速优化建议
批处理命令:合并多个 GDI 命令到单个 DMA 缓冲区以减少提交开销。
异步提交:若硬件支持,使用并行队列处理命令缓冲区。
状态缓存:避免在多次调用中重复解析不变的状态(如颜色格式)。
6. 与 GDI 上下文的交互
当 DXGKARG_CREATECONTEXT 的 GdiContext=TRUE 时:
命令缓冲区可能包含 GDI 特定的指令(如 BitBlt、AlphaBlend)。
需确保生成的 DMA 缓冲区符合 GDI 的 立即模式渲染 要求。
7. 调试技巧
日志记录:在 DxgkDdiRenderKm 中记录 MultipassOffset 和命令类型,便于跟踪分段处理问题。
验证工具:使用 WDK 的 DXGK Debug Extensions 检查 DMA 缓冲区内容。
8. 总结
- MultipassOffset 是核心:确保正确处理大型命令缓冲区的分段提交。
- 性能关键路径:DxgkDdiRenderKm 的优化直接影响 GDI 硬件加速的吞吐量。
- 兼容性:
- 必须支持 Windows 7+ 的多阶段处理协议。
- 适用于 WDDM v1.2+ 显示驱动程序开发,尤其是需要高效处理 GDI/Direct3D 混合工作负载的 GPU 驱动。