perf: BuildFrame 收集段优化——实体级粗剔除 + 数组化 batch 查找 + 合并矩阵写
定位数据(100 背包 + SunTemple,RTX 5060):GPU 全帧仅 ~3ms (Forward 1.91 + Shadow 0.82),CPU BuildFrame 收集段 5.94ms 才是 帧率瓶颈。三段细分测量:pre 0.2 / each+cull 5.0 / flatten 0.4。 优化(collect 5.94 → 4.6ms,-23%): 1. Mesh 全局连续槽位(GetSlot);ViewScratch batch 查找 hash → 数组寻址(slot × kMeshLodCount 槽) 2. Model 级联合包围球(各 mesh bounds 并集):实体在四视图全部 不可见 → 跳过整个 mesh 循环(多 mesh 模型的粗剔除) 3. worlds/prevWorlds 合并为 stride-2 InstanceMatrices 单次写 (每实例每视图 2 次随机堆访问 → 1 次,cache miss 减半) 遥测:Renderer::GetCollectMs 暴露收集段耗时。剩余 4.6ms 的进一步 压缩(并行收集 / GPU-driven culling)单独立项。
This commit is contained in:
@@ -45,6 +45,23 @@ Model::Model(Device& device, MemoryAllocator& allocator,
|
||||
|
||||
Model::~Model() = default;
|
||||
|
||||
void Model::RebuildUnionBounds()
|
||||
{
|
||||
if (m_Meshes.empty()) {
|
||||
m_Bounds = {};
|
||||
return;
|
||||
}
|
||||
// 各 mesh 包围球 → AABB 并集 → 外接球(保守,宁多画不漏画)
|
||||
glm::vec3 mn(1e9f), mx(-1e9f);
|
||||
for (const auto& mesh : m_Meshes) {
|
||||
const auto& b = mesh->GetBounds();
|
||||
mn = glm::min(mn, b.center - glm::vec3(b.radius));
|
||||
mx = glm::max(mx, b.center + glm::vec3(b.radius));
|
||||
}
|
||||
m_Bounds.center = (mn + mx) * 0.5f;
|
||||
m_Bounds.radius = 0.5f * glm::length(mx - mn);
|
||||
}
|
||||
|
||||
void Model::InitDefaultTextures()
|
||||
{
|
||||
// 各材质槽位的兜底纹理(1x1,开销可忽略):
|
||||
@@ -91,6 +108,7 @@ Model::Model(Device& device, MemoryAllocator& allocator,
|
||||
|
||||
m_Meshes.push_back(CreateScope<Mesh>(
|
||||
m_Device, m_Allocator, vertices, lodIndices, mat));
|
||||
RebuildUnionBounds();
|
||||
}
|
||||
|
||||
Scope<Model> Model::CreatePlane(Device& device, MemoryAllocator& allocator,
|
||||
@@ -165,6 +183,7 @@ Scope<Model> Model::FromParsed(Device& device, MemoryAllocator& allocator,
|
||||
}
|
||||
ENGINE_INFO("Model loaded: {} ({} meshes, {} textures)",
|
||||
parsed.path, model->m_Meshes.size(), model->m_TextureCache.size());
|
||||
model->RebuildUnionBounds();
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -184,6 +203,7 @@ void Model::LoadModel(const std::string& path)
|
||||
}
|
||||
ENGINE_INFO("Model loaded: {} ({} meshes, {} textures)",
|
||||
path, m_Meshes.size(), m_TextureCache.size());
|
||||
RebuildUnionBounds();
|
||||
}
|
||||
|
||||
void Model::ProcessNode(const aiNode* node, const aiScene* scene,
|
||||
|
||||
Reference in New Issue
Block a user