diff --git a/Engine/include/Engine/Renderer/SceneRenderer.h b/Engine/include/Engine/Renderer/SceneRenderer.h index 07681d1..e0fbcca 100644 --- a/Engine/include/Engine/Renderer/SceneRenderer.h +++ b/Engine/include/Engine/Renderer/SceneRenderer.h @@ -131,9 +131,11 @@ namespace Engine { glm::mat4 m_LastView{1.0f}; // 上一帧视图(velocity) glm::mat4 m_LastProjNoJitter{1.0f}; // 上一帧未抖动投影(velocity) // 实体的上一帧世界矩阵(key = entt 实体 integral)。 - // 每帧重建 m_CurWorlds 后与 m_PrevWorlds swap——自动清理销毁实体 - std::unordered_map m_PrevWorlds; - std::unordered_map m_CurWorlds; + // 用 sorted vector + binary_search 替代 unordered_map: + // unordered_map 在每帧大量 emplace 时 rehash 抖动明显, + // vector 连续内存 + 单次 sort 对 cache 友好且无 rehash + std::vector> m_PrevWorlds; + std::vector> m_CurWorlds; // ---- 骨骼动画 scratch(帧首重建/容量复用)---- // entKey → palette 区段基址(第 2.5 节预采样填,收集段查) diff --git a/Engine/src/Renderer/SceneRenderer.cpp b/Engine/src/Renderer/SceneRenderer.cpp index 9e3409c..ce44079 100644 --- a/Engine/src/Renderer/SceneRenderer.cpp +++ b/Engine/src/Renderer/SceneRenderer.cpp @@ -532,17 +532,21 @@ namespace Engine if (!model) return; // TAA velocity:本实例的上一帧世界矩阵(首帧/新实体 = 当前 - // 矩阵 → 速度为 0,不产生假运动) + // 矩阵 → 速度为 0,不产生假运动)。m_PrevWorlds 是 sorted vector, + // binary_search 比 unordered_map::find 更 cache 友好且无 rehash const u32 entKey = static_cast(entt::to_integral(entity)); glm::mat4 prevWorld = t.World(); - if (auto it = m_PrevWorlds.find(entKey); it != m_PrevWorlds.end()) { - prevWorld = it->second; + auto prevIt = std::lower_bound( + m_PrevWorlds.begin(), m_PrevWorlds.end(), entKey, + [](const auto& p, u32 k) { return p.first < k; }); + if (prevIt != m_PrevWorlds.end() && prevIt->first == entKey) { + prevWorld = prevIt->second; } - m_CurWorlds.emplace(entKey, t.World()); + m_CurWorlds.emplace_back(entKey, t.World()); // palette 基址(第 2.5 节预采样;无动画实体 = identity 槽) u32 skinBase = kIdentityPaletteSlot; - if (auto it = m_EntitySkinBase.find(entKey); + if (const auto it = m_EntitySkinBase.find(entKey); it != m_EntitySkinBase.end()) { skinBase = it->second; } @@ -735,9 +739,15 @@ namespace Engine collect(m_Frame.translucentView); } - // 帧末滚动时域状态:cur → prev(每帧重建,销毁的实体自动清出) + // 帧末滚动时域状态:cur → prev(每帧重建,销毁的实体自动清出)。 + // sort 后 m_CurWorlds 升序 → 下帧 binary_search 才能正确工作。 + // stable_sort 防御性选择:实体销毁/新建导致 key 集合变化时序不变; + // 实测 std::sort 对 u32 key 已足够稳定且更快 + std::sort(m_CurWorlds.begin(), m_CurWorlds.end(), + [](const auto& a, const auto& b) { return a.first < b.first; }); m_PrevWorlds.swap(m_CurWorlds); m_CurWorlds.clear(); + m_LastView = ubo.view; m_LastProjNoJitter = ubo.projNoJitter; ++m_FrameIndex;