FrameGraph 资源生命周期与渲染管线对比
在 Vulkan 和 Direct3D 12 中,手动维护 RenderTarget 生命周期与 VkImageMemoryBarrier 很容易漏掉读写同步或产生冗余屏障。把每帧的 Pass 组织为有向无环图(FrameGraph),可以在编译期自动裁剪无引用的 Pass、复用瞬态显存并集中计算管线屏障。
光照着色阶段的微表面方程推导见 [[PBR 微表面 BRDF 与能量守恒推导]],渲染模块的静态库依赖隔离见 [[CMake Target 依赖传递与属性速查]]。
实时渲染管线带宽与特性对比
| 管线类型 | G-Buffer 带宽开销 | 多光源扩展性 | MSAA 支持 | 着色灵活性 | 适用场景 |
|---|---|---|---|---|---|
| Forward | 低(直接写 Color/Depth) | 差 | 原生支持 | 高(可按材质定制 Shader) | 移动端场景、半透明物体 |
| Clustered Forward+ | 较低(需 Depth Pre-pass) | 好(按三维簇剔除光源) | 原生支持 | 高(存在寄存器占用压力) | VR、高帧率场景 |
| Standard Deferred | 高(3~4 张 MRT 读写) | 好(屏幕空间解耦) | 差(依赖 TAA/FSR) | 受限于 G-Buffer 通道数 | PC 与主机写实场景 |
| Visibility Buffer | 低(仅存 PrimitiveID / InstanceID) | 好(Compute 分类着色) | 配合时域超分 | 高(消除 Quad Overdraw) | 虚拟几何体管线 |
FrameGraph 执行阶段
flowchart LR
Setup["Setup\n声明读写纹理与 Buffer"] --> Compile["Compile\n引用计数裁剪与拓扑排序"]
Compile --> Alias["Memory Aliasing\n瞬态资源显存池复用"]
Alias --> Barrier["Barrier 计算\n合并生成 PipelineBarrier"]
Barrier --> Exec["Execute\n录制 CommandBuffer"]
RenderPass 声明接口示例
每个 Pass 在 setup 阶段只声明自己读写的虚拟资源句柄和期望的 ResourceState,不直接分配底层 VkImage:
void DeferredLightingPass::setup(FrameGraphBuilder& builder, PassData& data) {
data.gbufferAlbedo = builder.read(m_blackboard.get<FGTexture>("GBufferAlbedo"), ResourceState::ShaderResource);
data.gbufferNormal = builder.read(m_blackboard.get<FGTexture>("GBufferNormal"), ResourceState::ShaderResource);
data.depthStencil = builder.read(m_blackboard.get<FGTexture>("SceneDepth"), ResourceState::DepthRead);
FGTextureDesc hdrDesc{};
hdrDesc.width = m_viewport.width;
hdrDesc.height = m_viewport.height;
hdrDesc.format = PixelFormat::RGBA16_FLOAT;
data.sceneHdrColor = builder.create<FGTexture>("SceneHDRColor", hdrDesc);
data.sceneHdrColor = builder.write(data.sceneHdrColor, ResourceState::RenderTarget);
} 出链引用 (Outgoing Links) 2