mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
fix: add 60-second grace period to M2 model cleanup
Models that lose all instances are no longer immediately evicted from GPU memory. Instead they get a 60-second grace period, preventing the thrash cycle where GO models (barrels, chests, herbs) were evicted every 5 seconds and re-loaded when the same object type respawned.
This commit is contained in:
parent
3c60ef8464
commit
f78d885e13
2 changed files with 25 additions and 2 deletions
|
|
@ -13,6 +13,7 @@
|
|||
#include <string>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
|
||||
namespace wowee {
|
||||
|
|
@ -434,6 +435,9 @@ private:
|
|||
void* glowVBMapped_ = nullptr;
|
||||
|
||||
std::unordered_map<uint32_t, M2ModelGPU> models;
|
||||
// Grace period for model cleanup: track when a model first became instanceless.
|
||||
// Models are only evicted after 60 seconds with no instances.
|
||||
std::unordered_map<uint32_t, std::chrono::steady_clock::time_point> modelUnusedSince_;
|
||||
std::vector<M2Instance> instances;
|
||||
|
||||
// O(1) dedup: key = (modelId, quantized x, quantized y, quantized z) → instanceId
|
||||
|
|
|
|||
|
|
@ -1753,6 +1753,7 @@ uint32_t M2Renderer::createInstance(uint32_t modelId, const glm::vec3& position,
|
|||
return 0;
|
||||
}
|
||||
const auto& mdlRef = modelIt->second;
|
||||
modelUnusedSince_.erase(modelId);
|
||||
|
||||
// Deduplicate: skip if same model already at nearly the same position.
|
||||
// Uses hash map for O(1) lookup instead of O(N) scan.
|
||||
|
|
@ -1864,6 +1865,7 @@ uint32_t M2Renderer::createInstanceWithMatrix(uint32_t modelId, const glm::mat4&
|
|||
LOG_WARNING("Cannot create instance: model ", modelId, " not loaded");
|
||||
return 0;
|
||||
}
|
||||
modelUnusedSince_.erase(modelId);
|
||||
|
||||
// Deduplicate: O(1) hash lookup
|
||||
{
|
||||
|
|
@ -4276,11 +4278,28 @@ void M2Renderer::cleanupUnusedModels() {
|
|||
usedModelIds.insert(instance.modelId);
|
||||
}
|
||||
|
||||
// Find and remove models with no instances
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
constexpr auto kGracePeriod = std::chrono::seconds(60);
|
||||
|
||||
// Find models with no instances that have exceeded the grace period.
|
||||
// Models that just lost their last instance get tracked but not evicted
|
||||
// immediately — this prevents thrashing when GO models are briefly
|
||||
// instance-free between despawn and respawn cycles.
|
||||
std::vector<uint32_t> toRemove;
|
||||
for (const auto& [id, model] : models) {
|
||||
if (usedModelIds.find(id) == usedModelIds.end()) {
|
||||
if (usedModelIds.find(id) != usedModelIds.end()) {
|
||||
// Model still in use — clear any pending unused timestamp
|
||||
modelUnusedSince_.erase(id);
|
||||
continue;
|
||||
}
|
||||
auto unusedIt = modelUnusedSince_.find(id);
|
||||
if (unusedIt == modelUnusedSince_.end()) {
|
||||
// First cycle with no instances — start the grace timer
|
||||
modelUnusedSince_[id] = now;
|
||||
} else if (now - unusedIt->second >= kGracePeriod) {
|
||||
// Grace period expired — mark for removal
|
||||
toRemove.push_back(id);
|
||||
modelUnusedSince_.erase(unusedIt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue