4.3 KiB
4.3 KiB
RHIPipelineState
命名空间: XCEngine::RHI
类型: class (abstract)
头文件: XCEngine/RHI/RHIPipelineState.h
描述: 图形/计算管线状态的跨后端抽象,负责收敛固定功能状态、着色器与目标格式,并向具体后端暴露统一的配置接口。
角色概述
RHIPipelineState 对应的是“上层渲染系统描述管线状态”的统一入口。它不是简单照抄某个 native API 的 PSO 结构,而是把输入布局、光栅化、混合、深度模板、拓扑、目标格式、多重采样信息以及计算着色器统一收敛到一套接口上。
这是一种典型的商业引擎设计思路:
- 渲染器先在统一描述层组织状态。
- 具体后端再决定这些状态是立即创建 native PSO、延迟编译,还是只作为运行时状态缓存。
当前状态模型
图形路径
- SetInputLayout
- SetRasterizerState
- SetBlendState
- SetDepthStencilState
- SetTopology
- SetRenderTargetFormats
- SetSampleCount
- SetSampleQuality
计算路径
其中 SetSampleCount 和 SetSampleQuality 共同表达多重采样配置,目的是让 GraphicsPipelineDesc 的采样参数可以完整下传到后端,而不是让上层在描述层就为不同图形 API 分叉。
为什么要有 SetSampleQuality
sampleQuality 在显式图形 API 中并不是完全对等的概念:
- D3D12 会直接把它映射到
DXGI_SAMPLE_DESC::Quality - Vulkan 当前实现只消费 sample count,不消费 quality
- OpenGL 当前实现也没有把 quality 落到真实状态
但抽象层仍然保留这个接口,原因很明确:
- 上层
GraphicsPipelineDesc可以保持完整 - 后端可以渐进式演进,不必修改渲染器对外契约
- 文档能够明确告诉使用者“这个字段在不同后端的成熟度不同”
这比“为了照顾当前最弱后端,直接把接口删掉”更符合商业级引擎的长期演进方式。
后端语义差异
D3D12PipelineState会真正存储 sample quality,并让它进入 PSO 创建与 hash。VulkanPipelineState暂时把 quality 视为兼容字段,当前实现忽略其值。OpenGLPipelineState当前同样把它作为占位契约处理。
因此 RHIPipelineState 的接口是稳定的,但“字段被消费的深度”仍然是后端相关事实,文档必须把这一点写清楚。
生命周期与有效性
RHIPipelineState 的“有效”并不保证在所有后端都等价于“native pipeline 已经创建完成”:
- 有的后端在初始化时就固化 native 对象。
- 有的后端在
EnsureValid()时才推进到真正可绑定状态。 - 还有的后端只是把状态缓存起来,绑定时再逐步写回。
这也是为什么文档不能把所有实现都粗暴描述成“标准 PSO”。
公开方法
- SetInputLayout
- SetRasterizerState
- SetBlendState
- SetDepthStencilState
- SetTopology
- SetRenderTargetFormats
- SetSampleCount
- SetSampleQuality
- SetComputeShader
- GetRasterizerState
- GetBlendState
- GetDepthStencilState
- GetInputLayout
- GetHash
- GetComputeShader
- HasComputeShader
- IsValid
- EnsureValid
- Shutdown
- Bind
- Unbind
- GetNativeHandle
- GetType