feat: RenderGraph 帧历史资源(ReadHistory)+ TemporalDiff 验证 pass

- PassBuilder::ReadHistory:读上一帧槽位 ((slot-1+F) mod F) 的物理镜像,
  TAA/运动模糊等时域效果的前置能力,RG 最后一个已知边界补齐
- 历史读不建拓扑边(跨帧依赖由同队列提交序保证)、不入本帧状态链、
  不改生命周期;剔除照常参与(生产者存活判定)
- 历史 barrier:首帧走 first(old=Undefined),之后走 steady 且
  src=ALL_COMMANDS|MEMORY_WRITE 显式闭合跨帧可用性+可见性;
  有历史读的资源,常规 entry steady 的 src 同样升级(历史读打破了
  同槽位 fence 全等保前提)
- TemporalDiff 调试 pass:|上一帧−当前帧|×增益,静止=黑/运动边缘发光
  即链路正确;Tonemap binding2 经 push 开关切调试视图
- 编译零错误、validation 零警告、8 秒冒烟通过(9 pass 全活跃)
This commit is contained in:
2026-09-23 13:05:10 +08:00
parent 0de8498350
commit c75832e73e
15 changed files with 294 additions and 17 deletions
@@ -37,6 +37,7 @@ namespace Engine {
bool useACES = true;
f32 bloomThreshold = 1.0f; // HDR 域亮度阈值
f32 bloomStrength = 0.8f; // 叠加强度
bool showTemporalDiff = false; // 调试视图:显示帧历史差异
};
class FullscreenGpu {
@@ -48,10 +49,11 @@ namespace Engine {
FullscreenGpu(const FullscreenGpu&) = delete;
FullscreenGpu& operator=(const FullscreenGpu&) = delete;
vk::DescriptorSetLayout setLayout; // Set0 = {输入0, 输入1}
vk::DescriptorSetLayout setLayout; // Set0 = {输入0, 输入1, 调试输入}
vk::PipelineLayout layout; // push 16B(FullscreenPush)
vk::Sampler sampler;
vk::ShaderEXT vert{}, extractFrag{}, blurFrag{}, tonemapFrag{};
vk::ShaderEXT diffFrag{}; // temporal_diff(帧历史调试)
// 各 pass 自己持有 per-slot set;分配统一走这里
vk::DescriptorSet AllocateSet();
@@ -0,0 +1,40 @@
//
// Created by atdunbg on 2026/9/23.
//
// TemporalDiffPass:帧历史链路调试视图。
// 读 HDRColor 的帧历史镜像(ReadHistory)与当前帧,输出 |prev − cur| × 增益。
// 静止画面纯黑、运动边缘发光 = 帧历史机制正确;噪声/残影错位 = 有 bug。
// 也是 RenderGraph::ReadHistory 的参考实现(TAA 照此模式接入)。
//
#ifndef HELLOVULKAN_TEMPORALDIFFPASS_H
#define HELLOVULKAN_TEMPORALDIFFPASS_H
#include <Engine/Renderer/Passes/RenderPass.h>
#include <Engine/Renderer/Passes/FullscreenGpu.h>
#include <vulkan/vulkan.hpp>
#include <vector>
namespace Engine::Passes {
class TemporalDiffPass final : public RenderPass {
public:
TemporalDiffPass(FullscreenGpu& gpu, f32 gain,
RG::TextureHandle hdrColor, RG::TextureHandle output);
~TemporalDiffPass() override = default;
void Register(RG::RenderGraph& rg) override;
void OnTargetsRebuilt(RG::RenderGraph& rg) override;
private:
FullscreenGpu& m_Gpu;
f32 m_Gain;
RG::TextureHandle m_HDR;
RG::TextureHandle m_Output;
std::vector<vk::DescriptorSet> m_Sets; // per-slot
};
} // namespace Engine::Passes
#endif //HELLOVULKAN_TEMPORALDIFFPASS_H
@@ -20,7 +20,7 @@ namespace Engine::Passes {
public:
TonemapPass(FullscreenGpu& gpu, PostProcessParams& params,
RG::TextureHandle hdrColor, RG::TextureHandle bloomA,
RG::TextureHandle backbuffer);
RG::TextureHandle temporalDiff, RG::TextureHandle backbuffer);
~TonemapPass() override = default;
void Register(RG::RenderGraph& rg) override;
@@ -31,6 +31,7 @@ namespace Engine::Passes {
PostProcessParams& m_Params;
RG::TextureHandle m_HDR;
RG::TextureHandle m_A;
RG::TextureHandle m_TemporalDiff; // 调试视图输入(当前帧槽位)
RG::TextureHandle m_Backbuffer;
std::vector<vk::DescriptorSet> m_Sets; // per-slot