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
+15 -4
View File
@@ -9,10 +9,12 @@
// 和事件钩子(OnEvent + 类型化事件)定义程序行为;
// runtime、editor 等不同程序形态只是不同的派生类。
//
// 主循环固定为:PollEvents → OnUpdate(dt) → [主渲染 → OnRenderOverlay] → 判退出。
// 主渲染(Renderer.Render(scene))是框架行为,派生类不可覆盖也不会丢失;
// 派生类的渲染扩展(ImGui/调试视图/编辑器叠加层)走 OnRenderOverlay,
// 在主渲染之后、Present 之前执行,不覆写则什么都不发生。
// 主循环固定为:PollEvents → OnUpdate(dt) → [NewFrame → OnRenderOverlay →
// BuildDrawData] → 主渲染(Renderer.Render)→ 判退出。
// UI 构建与 GPU 提交分离:OnRenderOverlay 只"声明"控件,真正的 draw data
// 提交发生在主渲染管线中的 ImGui pass(Forward 之后、Present 之前,
// loadOp=Load 叠加)。主渲染是框架行为,派生类不可覆盖也不会丢失;
// 框架自身永远不绘制任何 ImGui 控件——UI 内容全部由派生类定义。
// dt 由框架统一计时(含首帧与卡顿钳制),派生层无需自己管理。
//
@@ -28,6 +30,7 @@ namespace Engine {
class Window;
class Renderer;
class ImGuiLayer;
namespace ECS { class Scene; }
namespace Assets { class AssetManager; }
@@ -46,6 +49,11 @@ namespace Engine {
// 请求退出(当帧结束后生效)
void Close() { m_Running = false; }
// 启用 ImGui 叠加层(OnInit 内调用)。启用后每帧:
// NewFrame → OnRenderOverlay(派生类画控件)→ BuildDrawData →
// 主渲染(ImGui pass 把 draw data 叠加到场景上)。
void EnableImGui();
// ---- 供派生类访问的模块 ----
Window& GetWindow() const { return *m_Window; }
Renderer& GetRenderer() const { return *m_Renderer; }
@@ -92,6 +100,9 @@ namespace Engine {
Scope<ECS::Scene> m_Scene;
Scope<Renderer> m_Renderer;
Scope<Assets::AssetManager> m_Assets;
// 注意成员序:ImGuiLayer 必须后声明(先于 Renderer/Window 析构,
// 其后端销毁需要 Device 与 GLFWwindow 存活)
Scope<ImGuiLayer> m_ImGuiLayer;
bool m_Running = false;
f32 m_DeltaTime = 0.0f;