0%

从零实现 Render Graph

Render Graph,也可以叫 Frame Graph,由这个GDC演讲首次提出,是一个比较现代的渲染架构。

为什么选择使用 Render Graph 呢?一开始,我只是在参考别人的开源项目时第一次接触到这个概念,简单了解它的作用后就跟着实现了。不过后来在开发测试中,我真正体会到了它的好。

如果不使用 Render Graph,是可以预见的 debug 地狱。目前我的 Pass 和 Shader 数量都分别超过了 10 个,手动配置这些依赖想想就头痛。而且现在底层实现了有向无环图(DAG),可以很方便地实现图的可视化,同时配合 ImGui 选择中间的 View 输出,能够非常快速地查看和验证渲染结果。

什么是 Render Graph

其实已经有许多很好的材料讲过这个概念了,比如这篇大佬的文章 。我就在这里聊聊一开始让我比较困惑的点。

如何理解 Render Graph?我们可以用现代工厂的流水线来打个简单的比方。

  • Render Graph = 整个工厂的自动化调度系统。
  • Pass = 工作站 / 派工单。它本身不干体力活,主要负责向系统声明需求(明确指出要去哪拿材料,以及最后要产出什么)。
  • Shader = 一线工人 / 操作手册。它们被固定在工作站里,一旦材料到位,就负责底层的具体工作(比如像素的切割、光照的计算)。
  • Resource = 原材料、半成品以及最终的产品。在 Render Graph 中,它既是 Pass 提交的虚拟“提货单”(逻辑资源),也是最终分配在 GPU 上的真实物理显存。
  • RenderPath = 架构设计师。他决定了今天到底要造什么级别的产品(比如是走前向渲染还是复杂的混合渲染),并把需要经过的工序图纸交接给工厂。

通过这种方式,原本手动管理极其痛苦的资源分配和读写依赖,就被这套“工厂系统”自动化接管了。

实现

本引擎的 Render Graph 实现遵循“逻辑抽象 -> 自动推导 -> 物理执行”的原则,核心由以下四个模块构成:

1. 资源的扁平化抽象与显存复用

本引擎采用面向数据设计(DOD)的思路来处理渲染资源,将其严格划分为逻辑与物理两层:

  • 前端(逻辑句柄): 开发者在编写 Pass 时,资源仅体现为一个轻量级的整数句柄,通过名称(如 "Albedo")来引用,不直接操作物理显存。
  • 后端(扁平数组): 真实的物理资源统一存放在一个连续的数组(std::vector<PhysicalResource>)中,这种紧凑的内存布局有效提高了 CPU 缓存命中率。
  • 显存复用(Memory Aliasing): 系统在编译期执行生命周期分析,计算每个资源的创建与销毁节点。生命周期不重叠的资源会被自动分配到同一块物理显存上。这种复用机制在混合渲染等复杂管线下,为引擎节省了大量的显存空间。

2. 基于链式调用的声明式接口

为了提升代码的可读性,接口设计引入了 Fluent API(链式调用)模式。

1
2
3
4

data.normal = builder.Write("Normal")
                     .Format(VK_FORMAT_R16G16B16A16_SFLOAT)
                     .SaveAsHistory("NormalHistory"); // 标记需要保留到下一帧

这种设计将资源的“配置参数”与“使用意图”结合在一起,保证资源属性在声明时即被明确定义,避免了“先使用后初始化”等潜在错误。

3. 自动化的拓扑排序与同步

在所有 Pass 声明完毕后,系统会自动分析它们之间的读写依赖,完成两项核心工作:

  • 拓扑排序: 根据资源的输入输出关系,自动对打乱的 Pass 进行重排,推导出正确的执行顺序。
  • 屏障推导: 对比资源在前后 Pass 中的状态变化。如果一个资源从“写入”状态流向“读取”状态,系统会自动在 GPU 指令流中插入对应的内存屏障(Memory Barrier) 和布局转换(Layout Transition)。这直接避免了手动管理 Vulkan 同步状态带来的 Debug 难题。

4. 结合 Vulkan 动态渲染

引擎底层接入了 Vulkan 1.3 的动态渲染(Dynamic Rendering) 特性。

传统的 Vulkan 渲染需要预先创建 VkRenderPassVkFramebuffer 对象。而在本系统中,Render Graph 搭配动态渲染实现了“即用即建”:在执行阶段,直接根据当前的资源绑定关系实时组装渲染指令。这种模式大幅精简了底层的样板代码,也让引擎在处理窗口尺寸变化或管线切换时更加简单直接。


这篇文章主要是博主用来记录学习过程的,欢迎大佬来指正交流。