refactor: 解耦重构——还清四处架构债(对齐 UE/Unity 分层)
- SceneRenderer:场景→渲染数据翻译层(UE FSceneRenderer / Unity CullingResults
模式),收口相机/灯光/光空间矩阵/双视图剔除,Renderer 只编排
- pass 对象化(Unity ScriptableRenderPass 模式):8 个 pass lambda 拆为
Passes::{Shadow,Forward,Bloom,Tonemap,ImGui,Present},BuildGraph 超级函数消失;
SceneGpu/FullscreenGpu 承接共享装配
- 中性 AssetRef(Core 层):ECS 组件不再依赖 Assets 模块(Unity InstanceID 思路)
- IAssetUploader 接口:AssetManager 不感知 Vulkan 具体类,上传服务由渲染层
VulkanAssetUploader 提供
- Renderer 公共 API 不变(App 层零改动),编译零错误 validation 零警告
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/22.
|
||||
//
|
||||
// AssetHandle:资产句柄 = (池内索引, 生成号),与 Entity/RG 句柄同一哲学。
|
||||
//
|
||||
// 组件、场景数据只存句柄;所有权归 AssetManager。
|
||||
// 悬空句柄(generation 不匹配)会被 Get 显式拒绝,杜绝 use-after-free。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_ASSETHANDLE_H
|
||||
#define HELLOVULKAN_ASSETHANDLE_H
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
|
||||
// Model 前向声明(句柄不依赖完整类型)
|
||||
namespace Engine { class Model; }
|
||||
|
||||
namespace Engine::Assets {
|
||||
|
||||
inline constexpr u32 kInvalidAssetIndex = 0xFFFFFFFF;
|
||||
|
||||
template<typename T>
|
||||
struct AssetHandle {
|
||||
u32 index = kInvalidAssetIndex;
|
||||
u32 generation = 0;
|
||||
|
||||
bool Valid() const { return index != kInvalidAssetIndex; }
|
||||
explicit operator bool() const { return Valid(); }
|
||||
bool operator==(const AssetHandle& o) const = default;
|
||||
};
|
||||
|
||||
// 常用别名
|
||||
using ModelHandle = AssetHandle<Engine::Model>;
|
||||
|
||||
} // namespace Engine::Assets
|
||||
|
||||
#endif //HELLOVULKAN_ASSETHANDLE_H
|
||||
@@ -3,14 +3,9 @@
|
||||
//
|
||||
// AssetManager:引擎资产层。
|
||||
//
|
||||
// 职责划分(对照 Renderer):
|
||||
// - 资产层:路径 → 解析/加载 → 缓存去重 → 句柄分发 + 生命周期管理
|
||||
// - 渲染层:拿已解析资产创建/绑定 GPU 资源
|
||||
//
|
||||
// Model 的构造仍需要 GPU 上下文(buffer/image upload),这是现阶段的
|
||||
// 折中:资产层"使用"GPU 层的接口,但 Renderer 不再知道磁盘和缓存。
|
||||
// 后续演进:把 Model 拆成 CPU 解析数据 + GPU 上传两段,实现真正的
|
||||
// 异步加载(IO 线程解析 → 主线程/上传队列提交),本文件结构已为此留好位置。
|
||||
// 职责:路径 → 解析/加载 → 缓存去重 → 句柄分发 + 生命周期管理。
|
||||
// GPU 创建不在这里:经 IAssetUploader 接口(渲染层提供实现)完成,
|
||||
// 本类不感知 Vulkan——依赖方向 Assets → 接口,实现由组合根注入。
|
||||
//
|
||||
// 组件存句柄不存指针的理由:
|
||||
// shared_ptr 会引入共享所有权 → 原子引用计数(swap-remove 拷贝时)
|
||||
@@ -23,7 +18,8 @@
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/Assets/AssetHandle.h>
|
||||
#include <Engine/Core/AssetRef.h>
|
||||
#include <Engine/Assets/IAssetUploader.h>
|
||||
#include <Engine/Renderer/Model.h>
|
||||
|
||||
#include <functional>
|
||||
@@ -32,11 +28,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
class MemoryAllocator;
|
||||
class DescriptorManager;
|
||||
|
||||
namespace Assets {
|
||||
|
||||
// ---------- 通用资产缓存(不感知 Vulkan / 磁盘细节由 loader 决定) ----------
|
||||
@@ -48,7 +39,7 @@ namespace Engine {
|
||||
using LoaderFn = std::function<Scope<T>(const std::string&)>;
|
||||
|
||||
// 加载(带路径去重)。失败返回无效句柄。
|
||||
AssetHandle<T> Load(const std::string& path, const LoaderFn& loader)
|
||||
AssetRef<T> Load(const std::string& path, const LoaderFn& loader)
|
||||
{
|
||||
if (auto it = m_ByPath.find(path); it != m_ByPath.end()) {
|
||||
return it->second;
|
||||
@@ -60,7 +51,7 @@ namespace Engine {
|
||||
return {};
|
||||
}
|
||||
|
||||
AssetHandle<T> h;
|
||||
AssetRef<T> h;
|
||||
if (!m_Free.empty()) {
|
||||
h.index = m_Free.back();
|
||||
m_Free.pop_back();
|
||||
@@ -77,7 +68,7 @@ namespace Engine {
|
||||
}
|
||||
|
||||
// 句柄 → 资产指针。悬空句柄 FATAL(bug 信号);已卸载返回 nullptr。
|
||||
T* Get(AssetHandle<T> h) const
|
||||
T* Get(AssetRef<T> h) const
|
||||
{
|
||||
if (!h.Valid() || h.index >= m_Entries.size()) {
|
||||
ENGINE_FATAL("AssetCache::Get: invalid handle (index={}, gen={})",
|
||||
@@ -94,7 +85,7 @@ namespace Engine {
|
||||
// 卸载:句柄即刻失效(generation 递增),路径缓存清除。
|
||||
// 注意:GPU 侧何时安全释放由上层(Renderer fence)保证——
|
||||
// 本类只管所有权,不管 GPU 生命周期。
|
||||
void Unload(AssetHandle<T> h)
|
||||
void Unload(AssetRef<T> h)
|
||||
{
|
||||
if (!h.Valid() || h.index >= m_Entries.size()) return;
|
||||
|
||||
@@ -109,7 +100,7 @@ namespace Engine {
|
||||
m_Free.push_back(h.index);
|
||||
}
|
||||
|
||||
const std::string& Path(AssetHandle<T> h) const
|
||||
const std::string& Path(AssetRef<T> h) const
|
||||
{
|
||||
static const std::string kEmpty;
|
||||
if (!h.Valid() || h.index >= m_Entries.size()) return kEmpty;
|
||||
@@ -132,29 +123,27 @@ namespace Engine {
|
||||
|
||||
std::vector<Entry> m_Entries;
|
||||
std::vector<u32> m_Free;
|
||||
std::unordered_map<std::string, AssetHandle<T>> m_ByPath;
|
||||
std::unordered_map<std::string, AssetRef<T>> m_ByPath;
|
||||
};
|
||||
|
||||
// ---------- AssetManager:全引擎资产入口 ----------
|
||||
// (ModelHandle 别名来自 AssetHandle.h)
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
// GPU 上下文由组合根(Application)在 Renderer 装配完成后注入
|
||||
AssetManager(Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptors,
|
||||
vk::DescriptorSetLayout textureLayout);
|
||||
// 上传服务由组合根(Application)注入:渲染层实现接口,
|
||||
// 资产层不感知 Vulkan 具体类
|
||||
explicit AssetManager(IAssetUploader& uploader);
|
||||
~AssetManager() = default;
|
||||
|
||||
AssetManager(const AssetManager&) = delete;
|
||||
AssetManager& operator=(const AssetManager&) = delete;
|
||||
|
||||
ModelHandle LoadModel(const std::string& path);
|
||||
Model* GetModel(ModelHandle h) const { return m_Models.Get(h); }
|
||||
void UnloadModel(ModelHandle h) { m_Models.Unload(h); }
|
||||
ModelRef LoadModel(const std::string& path);
|
||||
Model* GetModel(ModelRef h) const { return m_Models.Get(h); }
|
||||
void UnloadModel(ModelRef h) { m_Models.Unload(h); }
|
||||
|
||||
// 程序化平面(纯色贴图):size 为半边长。带缓存,同参数共享一份。
|
||||
ModelHandle CreatePlane(f32 halfSize, u8 r, u8 g, u8 b);
|
||||
ModelRef CreatePlane(f32 halfSize, u8 r, u8 g, u8 b);
|
||||
|
||||
AssetCache<Model>& Models() { return m_Models; }
|
||||
|
||||
@@ -162,10 +151,7 @@ namespace Engine {
|
||||
// 各自一个 AssetCache<T> + 便捷方法,模式与 Model 完全一致。
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
DescriptorManager& m_Descriptors;
|
||||
vk::DescriptorSetLayout m_TextureLayout;
|
||||
IAssetUploader& m_Uploader;
|
||||
|
||||
AssetCache<Model> m_Models;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// IAssetUploader:资产层 → GPU 的上传接口。
|
||||
//
|
||||
// 资产层(AssetManager/AssetCache)只认这个接口,不感知 Vulkan 具体类
|
||||
// (Device/Allocator/DescriptorManager)。实现由渲染层提供
|
||||
// (VulkanAssetUploader),组合根(Renderer)装配后注入。
|
||||
//
|
||||
// 对齐 UE:资产系统(AssetManager/StreamableManager)与渲染资源创建
|
||||
// (rendering thread / RHI)分离,资产层只拿到"可用的渲染资源"。
|
||||
//
|
||||
// 后续演进点:接口加返回 future / 回调即为异步加载
|
||||
// (IO 线程解析 → 上传队列提交),本接口已是正确的接缝。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_IASSETUPLOADER_H
|
||||
#define HELLOVULKAN_IASSETUPLOADER_H
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Renderer/Model.h>
|
||||
|
||||
namespace Engine::Assets {
|
||||
|
||||
class IAssetUploader {
|
||||
public:
|
||||
virtual ~IAssetUploader() = default;
|
||||
|
||||
// 磁盘模型 → 解析 + GPU 上传(失败返回 nullptr)
|
||||
virtual Scope<Model> LoadModel(const std::string& path) = 0;
|
||||
|
||||
// 程序化纯色平面(size 为半边长)
|
||||
virtual Scope<Model> CreatePlane(f32 halfSize, u8 r, u8 g, u8 b) = 0;
|
||||
};
|
||||
|
||||
} // namespace Engine::Assets
|
||||
|
||||
#endif //HELLOVULKAN_IASSETUPLOADER_H
|
||||
Reference in New Issue
Block a user