feat: 模型异步加载——assimp 解析移后台线程(SunTemple 3s 卡顿消除)
Model 拆两段式:ParseFromDisk(static 纯 CPU,assimp 解析 → 几何 + 材质引用,worker 可调)/ FromParsed(GPU 构建:纹理上传 / mesh 缓冲 / 材质描述符,主线程),同步路径等价两段串行。第二个异步任务类型落地, 线程收割骨架抽成 Core/AsyncTask<T>(thread + atomic + Take,覆盖式 Run;pending 接力语义留调用方)。 实测(SunTemple 1056 mesh):解析 2.5s 全程在 worker,主线程持续 渲染;GPU 构建 0.56s。assets 层经 IAssetUploader/AssetManager 重载 传预解析产物(路径缓存去重,路径已缓存则产物丢弃)。 已知边界:纹理解码(backpack 4k PNG ~1s)仍在 GPU 段主线程—— Texture 需支持预解码像素注入,后续演进。
This commit is contained in:
+28
-1
@@ -11,6 +11,7 @@
|
||||
#include <Engine/Core/Application.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/Core/Stats.h>
|
||||
#include <Engine/Core/AsyncTask.h>
|
||||
#include <Engine/ECS/Scene.h>
|
||||
#include <Engine/ECS/EntityHandle.h>
|
||||
#include <Engine/ECS/Components.h>
|
||||
@@ -47,6 +48,7 @@ namespace
|
||||
};
|
||||
constexpr int kEnvCount = 4;
|
||||
constexpr int kDefaultEnv = 0;
|
||||
constexpr const char* kTemplePath = "assets/models/SunTemple/SunTemple.fbx";
|
||||
|
||||
class SandboxApp final : public Application
|
||||
{
|
||||
@@ -88,7 +90,13 @@ namespace
|
||||
const auto model = GetAssets().LoadModel("assets/models/backpack/backpack.obj");
|
||||
// const auto model = GetAssets().LoadModel("assets/models/pocket_watch_4k.gltf/pocket_watch_4k.gltf");
|
||||
|
||||
int countSize = 10;
|
||||
// 大模型异步加载:assimp 解析在 worker 线程(SunTemple 约 3s),
|
||||
// 完成后 OnUpdate 收割 → GPU 构建 → 建实体(cm 尺度 → 0.001)
|
||||
m_TempleTask.Run([] { return Model::ParseFromDisk(kTemplePath); });
|
||||
m_TempleScale = 0.001f;
|
||||
|
||||
|
||||
int countSize = 0;
|
||||
for (int i = 0; i < countSize; i ++)
|
||||
{
|
||||
for (int j = 0; j < countSize; j ++)
|
||||
@@ -155,6 +163,21 @@ namespace
|
||||
|
||||
void OnUpdate(f32 deltaTime) override
|
||||
{
|
||||
// 异步模型收割:解析完成 → GPU 构建 → 建实体
|
||||
if (m_TempleTask.Done()) {
|
||||
ParsedModel parsed = m_TempleTask.Take();
|
||||
const auto ref = GetAssets().LoadModel(kTemplePath,
|
||||
std::move(parsed));
|
||||
if (ref.Valid()) {
|
||||
auto temple = GetScene().CreateEntity("SunTemple");
|
||||
temple.AddComponent<MeshRendererComponent>(
|
||||
MeshRendererComponent{ref});
|
||||
temple.GetComponent<TransformComponent>()
|
||||
.SetScale(glm::vec3{m_TempleScale});
|
||||
ENGINE_INFO("[ASYNC] SunTemple ready, entity created");
|
||||
}
|
||||
}
|
||||
|
||||
// 异步环境加载:每帧收割完成的解码结果
|
||||
PollEnvironment();
|
||||
|
||||
@@ -473,6 +496,10 @@ namespace
|
||||
std::atomic<bool> m_EnvLoadDone{false};
|
||||
bool m_EnvLoadBusy = false;
|
||||
int m_EnvPending = -1;
|
||||
|
||||
// ---- 异步模型加载(SunTemple)----
|
||||
AsyncTask<ParsedModel> m_TempleTask;
|
||||
f32 m_TempleScale = 1.0f; // cm 尺度资产 → 米(解析后应用)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user