YuuFrag学习记录 共享笔记库
与你的相遇就是奇迹

浅说一下在 ChikaEngine 中实现的 RDG
早期版本可以看到,就是反向做了一个可达性剔除,同时保留所有的SideEffect节点(简单理解为很重要的,不能被剔除的节点)
重构之后,先说说RDG的Compile过程 ——
RDG 的编译过程,就是把 Render Pass 和资源的读写进行一个排序,同时计算其生命周期
可以查阅RenderGraphl.cpp在仓库中具体实现,下面简单说说 ——
首先清空之前的所有状态,比如 Textures / Buffer / Pass/ 上次的编译结果 等
先跑一边所有的 pass,记录下依赖关系,以在后面可以跑拓扑排序;同时在遍历的时候进行check,判断图是否合法
std::unordered_map<RGTextureHandle, RGPassHandle> lastTextureWriter;
std::unordered_map<RGBufferHandle, RGPassHandle> lastBufferWriter;
std::unordered_map<RGTextureHandle, std::vector<RGPassHandle>> textureReaders;
std::unordered_map<RGBufferHandle, std::vector<RGPassHandle>> bufferReaders;
lastTextureWriter 记录某个 Texture 最后是由哪个 Pass 写入的
lastBufferWriter 同理,但是记录的是 Buffer
textureReaders 记录某个 Texture 在上一次写入之后,被哪些 Pass 读过
bufferReaders 同理,但是记录的是 Buffer
在遍历的过程中如果遇到非法直接提前返回
这边就是最早版本的可达性检验的保留,
for (const RGPassHandle handle : m_passInsertionOrder)
{
const RGPass* pass = m_passes.Get(handle);
if (pass && pass->hasSideEffects)
markLive(handle);
}
此处 markLive 会递归保留依赖链,然后剔除没有连接到最终输出的 Pass
(就是普通的拓扑排序)
在排序的过程中跳过无效的或者被剔除的 Pass,然后如果有环的话也报出来
直接看 Texture 生命周期更新
每当当前 Pass 使用一个 Texture,就更新:
resource->firstUsePassIdx = std::min(resource->firstUsePassIdx, passIndex);resource->lastUsePassIdx = passIndex;++resource->refCount;
含义——
| 字段 | 更新方式 | 含义 | |