window显示驱动开发—输出合并器阶段
逻辑管道中的最后一步是通过模具或深度确定可见性,以及写入或混合输出以呈现目标,这可以是多种资源类型之一。 这些操作以及输出资源 (呈现目标) 绑定在输出合并阶段定义。
1. 核心功能与管线定位
输出合并是渲染管线的最终固定功能阶段,负责决定像素的最终命运(写入/丢弃)并管理渲染目标输出。其核心职责包括:
- 深度/模板测试:剔除被遮挡或不符合条件的像素。
- 颜色混合:将PS输出与当前渲染目标颜色按规则混合(如Alpha混合)。
- 多目标写入:支持同时输出到多个渲染目标(MRT)。
数据流示意图:
像素着色器输出 → [深度/模板测试] → [颜色混合] → 渲染目标/深度模板缓冲区
2. 关键驱动函数与状态管理
Direct3D 运行时通过以下DDI函数控制OM阶段:
函数分类 | 函数名 | 作用 |
---|---|---|
状态对象管理 | CreateBlendState | 创建混合状态(Alpha混合、写掩码等)。 |
CreateDepthStencilState | 创建深度/模板测试状态(比较函数、读写掩码)。 | |
DestroyBlendState / DestroyDepthStencilState | 释放状态对象。 | |
资源绑定 | SetRenderTargets | 绑定渲染目标视图(RTV)和深度模板视图(DSV)。 |
CreateDepthStencilView | 创建深度/模板视图(指定资源格式和用途)。 | |
清除操作 | ClearRenderTargetView | 用指定颜色清除RTV。 |
ClearDepthStencilView | 清除深度/模板缓冲区(可单独或同时清除)。 | |
杂项控制 | SetPredication | 设置条件渲染谓词(跳过特定绘制调用)。 |
SetTextFilterSize | 设置文本过滤尺寸(专用于字体渲染优化)。 |
3. 深度/模板测试详解
(1) 深度测试流程
- 比较阶段:根据 DepthStencilState 中的 DepthFunc(如 D3D10_DDI_COMPARISON_LESS)决定是否通过。
- 写入控制:通过 DepthWriteMask 控制是否更新深度缓冲区。
(2) 模板测试流程
- 比较操作:使用 StencilFunc 比较参考值与缓冲区值。
- 操作配置:定义 StencilPassOp/StencilFailOp 等行为。
驱动实现示例(深度状态设置):
void APIENTRY SetDepthStencilState(D3D10DDI_HDEVICE hDevice,D3D10DDI_HDEPTHSTENCILSTATE hState
) {MyDeviceContext* pCtx = (MyDeviceContext*)hDevice.pDrvPrivate;MyDepthStencilState* pDS = (MyDepthStencilState*)hState.pDrvPrivate;// 配置硬件寄存器WriteGPURegister(DEPTH_FUNC_REG, pDS->DepthFunc);WriteGPURegister(DEPTH_WRITE_MASK_REG, pDS->DepthWriteMask);// ... 配置模板状态
}
4. 颜色混合机制
(1) 混合方程
根据 BlendState 计算最终颜色:
FinalColor = SrcColor * SrcBlendFactor <OP> DestColor * DestBlendFactor
其中 SrcBlendFactor 和 OP(如 D3D10_DDI_BLEND_OP_ADD)由状态对象定义。
(2) 混合状态配置
D3D10_DDI_BLEND_DESC 关键字段:
typedef struct D3D10_DDI_BLEND_DESC {BOOL BlendEnable; // 是否启用混合D3D10_DDI_BLEND SrcBlend; // 源混合因子(如D3D10_DDI_BLEND_SRC_ALPHA)D3D10_DDI_BLEND DestBlend; // 目标混合因子(如D3D10_DDI_BLEND_INV_SRC_ALPHA)D3D10_DDI_BLEND_OP BlendOp; // 混合操作UINT8 RenderTargetWriteMask; // 颜色通道掩码(如0xF表示RGBA全写)
} D3D10_DDI_BLEND_DESC;
驱动混合状态转换:
HRESULT APIENTRY CreateBlendState(const D3D10_DDI_BLEND_DESC* pDesc,D3D10DDI_HBLENDSTATE hState
) {MyBlendState* pBS = new MyBlendState;pBS->hwBlendCtrl = ConvertToHWBlendCtrl(pDesc); // 转换为硬件指令// ... 存储状态return S_OK;
}
5. 多渲染目标 (MRT) 支持
通过 SetRenderTargets
绑定多个RTV:
void APIENTRY SetRenderTargets(D3D10DDI_HDEVICE hDevice,UINT NumRTVs,const D3D10DDI_HRENDERTARGETVIEW* phRTVs,D3D10DDI_HDEPTHSTENCILVIEW hDSV
) {MyDeviceContext* pCtx = (MyDeviceContext*)hDevice.pDrvPrivate;for (UINT i = 0; i < NumRTVs; ++i) {pCtx->currentRTVs[i] = phRTVs[i]; // 更新绑定目标}pCtx->currentDSV = hDSV;// 标记渲染目标为脏(需GPU同步)pCtx->dirtyFlags |= RENDER_TARGETS_DIRTY;
}
注意事项:
- 所有RTV必须具有相同的尺寸和样本数。
- 深度缓冲区(DSV)需与RTV兼容。
6. 性能优化与调试
(1) 优化建议
- 最小化状态切换:合并相同混合/深度状态的绘制调用。
- 利用Early-Z:确保不透明物体先渲染,减少PS计算量。
- 避免全屏清除:使用 ClearRenderTargetView 仅清除必要区域。
(2) 常见问题排查
现象 | 可能原因 | 解决方案 |
---|---|---|
深度测试失效 | DepthWriteMask 误设为 0 | 检查 CreateDepthStencilState |
Alpha混合异常 | BlendEnable 未启用或因子配置错误 | 验证 BlendState 参数 |
渲染目标内容未更新 | RTV绑定错误或资源状态冲突 | 使用PIX捕获资源状态 |
7. 高级特性支持
(1) 条件渲染 (SetPredication)
通过谓词资源跳过无效绘制:
void APIENTRY SetPredication(D3D10DDI_HDEVICE hDevice,D3D10DDI_HQUERY hPredicate,BOOL PredicateValue
) {// 驱动需记录谓词状态,并在Draw调用前检查pCtx->predicate = { hPredicate, PredicateValue };
}
(2) 文本过滤优化 (SetTextFilterSize)
专为字体渲染设计的硬件优化:
void APIENTRY SetTextFilterSize(D3D10DDI_HDEVICE hDevice,UINT Width,UINT Height
) {// 配置硬件纹理过滤器(如LCD子像素抗锯齿)ConfigureTextFilter(Width, Height);
}
总结
输出合并阶段是决定最终像素可见性与颜色的最终仲裁者,其驱动实现需关注:
- 状态管理效率:快速切换深度/模板和混合状态。
- 硬件特性适配:如MRT支持、混合操作加速。
- 资源一致性:确保渲染目标与深度缓冲区的兼容性。