feat: ImGui 叠加层接入 RenderGraph(docking 分支,dynamic rendering)

框架与 UI 的职责边界:
- ImGuiLayer(Engine/ImGui):只做管线桥接——上下文初始化、
  NewFrame/BuildDrawData、draw data 录入 cmd;框架自身永不绘制
  任何 ImGui 控件,UI 内容全部由派生类在 OnRenderOverlay() 定义
- 每帧顺序:NewFrame → OnRenderOverlay(声明控件)→ BuildDrawData →
  Renderer.Render(RG: Forward → ImGui(loadOp=Load 叠加) → Present)
- ImGui pass 常驻 RG,未启用叠加层时空转,无图结构开销
- 后端共存:VK_EXT_shader_object 引擎无 vk::Pipeline,ImGui 用
  UseDynamicRendering + PipelineInfoMain.PipelineRenderingCreateInfo
  (swapchain 格式),不需要 RenderPass
- 析构序:ImGuiLayer 在 Application 成员序中后声明(先于 Renderer
  析构),析构内 waitIdle 保证后端资源安全销毁

App 示例(证明职责边界):Scene Debug 面板实时拖动阴影光方向,
` 键反折叠加层
This commit is contained in:
2026-09-22 17:09:55 +08:00
parent bc63f76fc1
commit 07792c34d7
10 changed files with 338 additions and 11 deletions
+22 -2
View File
@@ -9,6 +9,7 @@
#include <Engine/Renderer/Renderer.h>
#include <Engine/Assets/AssetManager.h>
#include <Engine/Vulkan/Device.h>
#include <Engine/ImGui/ImGuiLayer.h>
#include <algorithm>
@@ -50,6 +51,14 @@ namespace Engine {
}
}
void Application::EnableImGui()
{
if (m_ImGuiLayer) return;
m_ImGuiLayer = CreateScope<ImGuiLayer>(GetWindow(), *m_Renderer);
m_Renderer->SetImGuiLayer(m_ImGuiLayer.get());
}
void Application::Run()
{
ENGINE_INFO("Application starting");
@@ -73,10 +82,21 @@ namespace Engine {
// 延迟销毁在渲染前统一 flush,保证渲染遍历时池结构不变
m_Scene->FlushDestroyQueue();
// 主渲染是框架行为(不可覆盖);叠加层钩子在提交前执行
m_Renderer->Render(*m_Scene, *m_Assets);
// ---- UI 构建段:OnRenderOverlay 只"声明"控件,不直接碰 GPU ----
if (m_ImGuiLayer) {
m_ImGuiLayer->NewFrame();
}
OnRenderOverlay();
if (m_ImGuiLayer) {
m_ImGuiLayer->BuildDrawData();
}
// ---- 主渲染(框架行为):RG 顺序 Forward → ImGui(loadOp=Load) →
// Present,draw data 在 ImGui pass 里才真正提交 GPU ----
m_Renderer->Render(*m_Scene, *m_Assets);
++m_FrameCount;
}