From 6ecfcb1fd355707c0031cff5a13e0493346e02e2 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 17 Oct 2017 23:21:38 +0200 Subject: [PATCH] Store munged states more efficiently, without weak key maps --- panda/src/display/graphicsStateGuardian.cxx | 24 ++++++++++++++++--- panda/src/gsgbase/graphicsStateGuardianBase.h | 2 ++ panda/src/pgraph/renderState.cxx | 1 + panda/src/pgraph/renderState.h | 10 +++++--- panda/src/pgraph/stateMunger.cxx | 13 ++++++---- panda/src/pgraph/stateMunger.h | 2 -- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index f0d807ffce..9d368467f8 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -281,6 +281,11 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _gamma = 1.0f; _texture_quality_override = Texture::QL_default; + + // Give it a unique identifier. Unlike a pointer, we can guarantee that + // this value will never be reused. + static size_t next_index = 0; + _id = next_index++; } /** @@ -290,6 +295,19 @@ GraphicsStateGuardian:: ~GraphicsStateGuardian() { remove_gsg(this); GeomMunger::unregister_mungers_for_gsg(this); + + // Remove the munged states for this GSG. This requires going through all + // states, although destructing a GSG should be rare enough for this not to + // matter too much. + // Note that if uniquify-states is false, we can't iterate over all the + // states, and some GSGs will linger. Let's hope this isn't a problem. + LightReMutexHolder holder(*RenderState::_states_lock); + size_t size = RenderState::_states->get_num_entries(); + for (size_t si = 0; si < size; ++si) { + const RenderState *state = RenderState::_states->get_key(si); + state->_mungers.remove(_id); + state->_munged_states.remove(_id); + } } /** @@ -743,7 +761,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) { // multiple times during a frame. Also, this might well be the only GSG // in the world anyway. int mi = state->_last_mi; - if (mi >= 0 && mungers.has_element(mi) && mungers.get_key(mi) == this) { + if (mi >= 0 && mi < mungers.get_num_entries() && mungers.get_key(mi) == _id) { PT(GeomMunger) munger = mungers.get_data(mi); if (munger->is_registered()) { return munger; @@ -751,7 +769,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) { } // Nope, we have to look it up in the map. - mi = mungers.find(this); + mi = mungers.find(_id); if (mi >= 0) { PT(GeomMunger) munger = mungers.get_data(mi); if (munger->is_registered()) { @@ -769,7 +787,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) { nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger); nassertr(munger->is_of_type(StateMunger::get_class_type()), munger); - state->_last_mi = mungers.store(this, munger); + state->_last_mi = mungers.store(_id, munger); return munger; } diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 361407ec6c..f86d39a8a3 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -235,6 +235,8 @@ public: static void add_gsg(GraphicsStateGuardianBase *gsg); static void remove_gsg(GraphicsStateGuardianBase *gsg); + size_t _id; + private: struct GSGList { LightMutex _lock; diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 1aad1ed25c..6f035a6557 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -987,6 +987,7 @@ clear_munger_cache() { for (size_t si = 0; si < size; ++si) { RenderState *state = (RenderState *)(_states->get_key(si)); state->_mungers.clear(); + state->_munged_states.clear(); state->_last_mi = -1; } } diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index a7dc550625..4e2b2e3384 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -30,10 +30,8 @@ #include "lightMutex.h" #include "deletedChain.h" #include "simpleHashMap.h" -#include "weakKeyHashMap.h" #include "cacheStats.h" #include "renderAttribRegistry.h" -#include "graphicsStateGuardianBase.h" class FactoryParams; class ShaderAttrib; @@ -264,10 +262,15 @@ private: // in the RenderState pointer than vice-versa, since there are likely to be // far fewer GSG's than RenderStates. The code to manage this map lives in // GraphicsStateGuardian::get_geom_munger(). - typedef WeakKeyHashMap Mungers; + typedef SimpleHashMap Mungers; mutable Mungers _mungers; mutable int _last_mi; + // Similarly, this is a cache of munged states. This map is managed by + // StateMunger::munge_state(). + typedef SimpleHashMap MungedStates; + mutable MungedStates _munged_states; + // This is used to mark nodes as we visit them to detect cycles. UpdateSeq _cycle_detect; static UpdateSeq _last_cycle_detect; @@ -360,6 +363,7 @@ private: friend class GraphicsStateGuardian; friend class RenderAttribRegistry; friend class Extension; + friend class StateMunger; }; // We can safely redefine this as a no-op. diff --git a/panda/src/pgraph/stateMunger.cxx b/panda/src/pgraph/stateMunger.cxx index c57366133d..db94c81ba8 100644 --- a/panda/src/pgraph/stateMunger.cxx +++ b/panda/src/pgraph/stateMunger.cxx @@ -27,15 +27,20 @@ StateMunger:: */ CPT(RenderState) StateMunger:: munge_state(const RenderState *state) { - int mi = _state_map.find(state); + RenderState::MungedStates &munged_states = state->_munged_states; + + int id = get_gsg()->_id; + int mi = munged_states.find(id); if (mi != -1) { - if (!_state_map.get_data(mi).was_deleted()) { - return _state_map.get_data(mi).p(); + if (!munged_states.get_data(mi).was_deleted()) { + return munged_states.get_data(mi).p(); + } else { + munged_states.remove_element(mi); } } CPT(RenderState) result = munge_state_impl(state); - _state_map.store(state, result.p()); + munged_states.store(id, result.p()); return result; } diff --git a/panda/src/pgraph/stateMunger.h b/panda/src/pgraph/stateMunger.h index b246d67413..467eaaf604 100644 --- a/panda/src/pgraph/stateMunger.h +++ b/panda/src/pgraph/stateMunger.h @@ -33,8 +33,6 @@ public: protected: virtual CPT(RenderState) munge_state_impl(const RenderState *state); - typedef WeakKeyHashMap StateMap; - StateMap _state_map; public: static TypeHandle get_class_type() {