feat: 引入 RenderGraph、Application 框架、ECS 与资产句柄系统
架构分层(自上而下):
App(SandboxApp) → Application(生命周期+事件) → Scene(ECS) / AssetManager(句柄) → Renderer → RenderGraph → Vulkan 模块
- RenderGraph:声明式帧图。虚拟资源+生成号句柄、死 pass 剔除、
拓扑排序、资源生命周期、barrier 编译期预算(Synchronization2)、
物理镜像池按帧槽位隔离(帧间竞争从根上消除)
- 帧同步修复:per-frame-slot 命令缓冲与 UBO ring(原先单份存在
数据竞争);统一 kMaxFramesInFlight / FrameContext
- Application:生命周期钩子(OnInit/OnUpdate/OnRender/OnShutdown)
+ 事件系统(GLFW 回调 → POD 事件 → 类型化钩子);main 只 new 派生类
- ECS:自研稀疏集 Registry(Entity=(index,generation) 防悬空,
O(1) 增删查,Each 取最小池遍历);Scene 延迟销毁队列;
IdComponent{UUID} 稳定外部身份
- Assets:AssetManager + AssetHandle。组件存句柄不存裸指针/Ref
(单一所有者 + 多使用者),Renderer 删除 LoadModel 改为纯消费
- 修复退出析构:成员析构前 GPU waitIdle(资产层先于 Renderer
析构导致 VUID-00922 资源销毁时仍在使用)
- 引入 entt 子模块备用
validation 全程零错误零警告(RTX 5060 实测)
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/22.
|
||||
//
|
||||
|
||||
#include <Engine/Core/Application.h>
|
||||
#include <Engine/Core/Window.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/ECS/Scene.h>
|
||||
#include <Engine/Renderer/Renderer.h>
|
||||
#include <Engine/Assets/AssetManager.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
Application::Application(std::string title, u32 width, u32 height)
|
||||
{
|
||||
m_Window = CreateScope<Window>(std::move(title), width, height);
|
||||
|
||||
// 事件通道:GLFW 回调 → 本类 DispatchEvent → 派生类钩子
|
||||
m_Window->SetEventCallback(
|
||||
[this](const Event& e) { DispatchEvent(e); });
|
||||
|
||||
// 场景(ECS 世界)+ 渲染器
|
||||
m_Scene = CreateScope<ECS::Scene>();
|
||||
m_Renderer = CreateScope<Renderer>(*m_Window);
|
||||
|
||||
// 资产层:复用渲染器的 GPU 上下文;
|
||||
// 声明在 Renderer 之后 → 析构先于 Renderer(它引用其子模块)
|
||||
m_Assets = CreateScope<Assets::AssetManager>(
|
||||
m_Renderer->GetDevice(),
|
||||
m_Renderer->GetAllocator(),
|
||||
m_Renderer->GetDescriptorManager(),
|
||||
m_Renderer->GetTextureSetLayout());
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
// 关键:必须在成员析构之前等 GPU 空闲。
|
||||
//
|
||||
// 成员析构序(后声明先析构)是 m_Assets → m_Renderer → m_Scene → m_Window:
|
||||
// 资产层持有全部 GPU buffer/texture/sampler,会先于 Renderer 析构,
|
||||
// 而 Renderer 的 waitIdle 在它自己的析构里——那时资产已经销毁了。
|
||||
// 若最后一帧命令缓冲仍在 GPU 上执行,就会出现
|
||||
// VUID-vkDestroyBuffer-buffer-00922(资源销毁时仍在使用)。
|
||||
// 这里显式等待,保证成员按任意顺序析构都是安全的。
|
||||
if (m_Renderer) {
|
||||
m_Renderer->GetDevice().GetDevice().waitIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Run()
|
||||
{
|
||||
ENGINE_INFO("Application starting");
|
||||
|
||||
m_Running = true;
|
||||
m_LastFrameTime = std::chrono::steady_clock::now();
|
||||
|
||||
OnInit();
|
||||
|
||||
while (m_Running && !m_Window->ShouldClose()) {
|
||||
m_Window->PollEvents();
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
f32 dt = std::chrono::duration<f32>(now - m_LastFrameTime).count();
|
||||
// 钳制卡顿(断点/窗口拖动导致的超大 dt),避免物理/动画穿模
|
||||
m_DeltaTime = std::clamp(dt, 0.0f, 0.25f);
|
||||
m_LastFrameTime = now;
|
||||
|
||||
OnUpdate(m_DeltaTime);
|
||||
|
||||
// 延迟销毁在渲染前统一 flush,保证渲染遍历时池结构不变
|
||||
m_Scene->FlushDestroyQueue();
|
||||
|
||||
OnRender();
|
||||
|
||||
++m_FrameCount;
|
||||
}
|
||||
|
||||
OnShutdown();
|
||||
ENGINE_INFO("Application stopped ({} frames)", m_FrameCount);
|
||||
}
|
||||
|
||||
void Application::OnRender()
|
||||
{
|
||||
m_Renderer->Render(*m_Scene, *m_Assets);
|
||||
}
|
||||
|
||||
void Application::DispatchEvent(const Event& event)
|
||||
{
|
||||
OnEvent(event);
|
||||
|
||||
switch (event.type) {
|
||||
case EventType::WindowClose: OnWindowClose(event); break;
|
||||
case EventType::WindowResize: OnWindowResize(event); break;
|
||||
case EventType::WindowFocus: OnWindowFocus(event); break;
|
||||
case EventType::WindowLostFocus: OnWindowLostFocus(event); break;
|
||||
case EventType::KeyPress: OnKeyPress(event); break;
|
||||
case EventType::KeyRelease: OnKeyRelease(event); break;
|
||||
case EventType::MouseButtonPress: OnMouseButtonPress(event); break;
|
||||
case EventType::MouseButtonRelease: OnMouseButtonRelease(event); break;
|
||||
case EventType::MouseMove: OnMouseMove(event); break;
|
||||
case EventType::MouseScroll: OnMouseScroll(event); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::OnWindowClose(const Event& event)
|
||||
{
|
||||
// 默认行为:直接退出。需要"退出确认"的程序覆写本钩子。
|
||||
Close();
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
Reference in New Issue
Block a user