feat: IBL 预积分 GPU compute 化 + 环境资产入 Assets 层(动态切换)
CPU 逐像素卷积(venice 4k 阻塞 7.36s)→ 4 个 compute shader 一次性 提交:equirect→cube / irradiance / prefilter×5mip / BRDF LUT。 Cubemap 瘦身为纯资源持有类,生成职责移交 IblGenerator; 环境经 AssetManager 缓存(EnvRef),Renderer::SetEnvironment 动态换绑(RenderPass::OnEnvironmentChanged 广播)。 调试视图 +4:EnvCube / Irradiance / Prefilter / BRDF LUT。 性能前后对比(RTX 5060 Laptop,venice_dawn_1_4k.hdr): - 改造前 CPU:7.36 s(主线程阻塞) - 改造后 GPU:HDR decode 127-134ms + 资源 22-35ms + compute 17-19ms ≈ 165-190ms(约 40×);Neutral 兜底 ~6ms - 运行中动态切换环境同量级(ms 级 GPU,decode 占大头) 冒烟:两构建目录 0 警告;运行期 0 validation(含两次环境切换 + 调试视图 9-12 轮播自动化验证)。
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <Engine/Renderer/Passes/ShadowPass.h>
|
||||
#include <Engine/Renderer/Passes/ForwardPass.h>
|
||||
#include <Engine/Renderer/Cubemap.h>
|
||||
#include <Engine/Renderer/IblGenerator.h>
|
||||
#include <Engine/Renderer/Passes/TAAPass.h>
|
||||
#include <Engine/Renderer/Passes/BloomPass.h>
|
||||
#include <Engine/Renderer/Passes/TonemapPass.h>
|
||||
@@ -40,7 +41,6 @@
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <limits>
|
||||
|
||||
namespace Engine
|
||||
@@ -74,17 +74,12 @@ namespace Engine
|
||||
m_FullscreenGpu = CreateScope<Passes::FullscreenGpu>(
|
||||
*m_Device, *m_DescriptorManager, *m_ShaderManager);
|
||||
|
||||
// 3.5 环境贴图(IBL):HDR 等距柱状 → cube + 预积分。
|
||||
// 加载失败/文件缺失一律中性常数兜底(描述符恒有效)
|
||||
const std::string envPath = "assets/textures/venice_dawn_1_4k.hdr";
|
||||
if (std::filesystem::exists(envPath)) {
|
||||
m_Environment = Cubemap::CreateFromHdrEquirect(
|
||||
*m_Device, *m_Allocator, envPath, 1024);
|
||||
}
|
||||
if (!m_Environment) {
|
||||
m_Environment = Cubemap::CreateNeutral(
|
||||
*m_Device, *m_Allocator, glm::vec3(0.1f));
|
||||
}
|
||||
// 3.5 环境预积分生成端(compute 链)+ 中性兜底四件套。
|
||||
// 真实环境由 Application 经 AssetManager 加载后 SetEnvironment
|
||||
// (资产路径归资产层,Renderer 不感知具体文件)
|
||||
m_Ibl = CreateScope<IblGenerator>(
|
||||
*m_Device, *m_Allocator, *m_DescriptorManager, *m_ShaderManager);
|
||||
m_Environment = m_Ibl->Neutral(glm::vec3(0.1f));
|
||||
|
||||
// 4. Swapchain(只管呈现;渲染目标统一归 RenderGraph)
|
||||
m_Swapchain = CreateScope<Swapchain>(*m_Device, *m_Allocator, m_Window);
|
||||
@@ -101,7 +96,7 @@ namespace Engine
|
||||
// 7. 资产上传服务(渲染层对外提供的 IAssetUploader 实现)
|
||||
m_AssetUploader = CreateScope<VulkanAssetUploader>(
|
||||
*m_Device, *m_Allocator, *m_DescriptorManager,
|
||||
m_SceneGpu->textureSetLayout);
|
||||
m_SceneGpu->textureSetLayout, *m_Ibl);
|
||||
|
||||
// 8. RenderGraph:资源声明 + pass 注册 + 首次编译
|
||||
m_PostParams = CreateScope<Passes::PostProcessParams>();
|
||||
@@ -111,8 +106,12 @@ namespace Engine
|
||||
for (auto& pass : m_Passes) {
|
||||
pass->OnTargetsRebuilt(*m_RenderGraph);
|
||||
}
|
||||
// 环境辐照度绑定(view 全程稳定,绑一次)
|
||||
// 环境辐照度绑定(view 在单个环境内全程稳定,绑一次)
|
||||
m_SceneGpu->BindEnvironment(*m_Environment);
|
||||
// 环境消费端 pass(Skybox 背景 / Tonemap 调试视图)同步初始绑定
|
||||
for (auto& pass : m_Passes) {
|
||||
pass->OnEnvironmentChanged(m_Environment.get());
|
||||
}
|
||||
|
||||
// 9. GPU timestamp:每 pass 两枚(前后),按帧槽位分区
|
||||
m_QueriesPerFrame = static_cast<u32>(m_RenderGraph->GetPassCount()) * 2;
|
||||
@@ -185,13 +184,28 @@ namespace Engine
|
||||
int Renderer::GetDebugView() const { return m_SceneRenderer->Frame().debugView; }
|
||||
void Renderer::SetDebugView(int v) { m_SceneRenderer->SetDebugView(v); }
|
||||
|
||||
void Renderer::SetEnvironment(const Cubemap* env)
|
||||
{
|
||||
if (!env) env = m_Environment.get();
|
||||
|
||||
// 描述符 host 更新要求 set 不被 in-flight 帧使用(validation 严格
|
||||
// 校验):waitIdle 两槽位全停飞后统一换绑。环境切换低频,等待
|
||||
// 成本 ≈ 单帧 GPU 尾巴;生成端(compute 预积分)已在资产加载期完成
|
||||
m_Device->GetDevice().waitIdle();
|
||||
m_SceneGpu->BindEnvironment(*env);
|
||||
for (auto& pass : m_Passes) {
|
||||
pass->OnEnvironmentChanged(env);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<const char*>& Renderer::GetDebugViewNames() const
|
||||
{
|
||||
static const std::vector<const char*> kNames = {
|
||||
"Final", "TemporalDiff", "HDR", "TAAColor", "Bloom",
|
||||
"Velocity", "ShadowMap0", "ShadowMap1", "ShadowMap2",
|
||||
"EnvCube", "Irradiance", "Prefilter", "BrdfLut",
|
||||
};
|
||||
static_assert(int(Passes::kDebugViewCount) == 9,
|
||||
static_assert(int(Passes::kDebugViewCount) == 13,
|
||||
"DebugView 枚举与名表同步");
|
||||
return kNames;
|
||||
}
|
||||
@@ -285,9 +299,9 @@ namespace Engine
|
||||
*m_FullscreenGpu, *m_PostParams, frame, m_TAAColor, m_BloomA,
|
||||
m_BloomB));
|
||||
m_Passes.push_back(CreateScope<Passes::TonemapPass>(
|
||||
*m_FullscreenGpu, *m_PostParams, frame, m_TAAColor, m_BloomA,
|
||||
m_TemporalDiff, m_Backbuffer, m_HDRColor, m_Velocity,
|
||||
m_ShadowMaps[0], m_ShadowMaps[1], m_ShadowMaps[2]));
|
||||
*m_FullscreenGpu, *m_DescriptorManager, *m_PostParams, frame,
|
||||
m_TAAColor, m_BloomA, m_TemporalDiff, m_Backbuffer, m_HDRColor,
|
||||
m_Velocity, m_ShadowMaps[0], m_ShadowMaps[1], m_ShadowMaps[2]));
|
||||
m_Passes.push_back(CreateScope<Passes::ImGuiPass>(
|
||||
&m_ImGuiLayer, m_Backbuffer));
|
||||
m_Passes.push_back(CreateScope<Passes::PresentPass>(m_Backbuffer));
|
||||
|
||||
Reference in New Issue
Block a user