Browse Source

Store munged states more efficiently, without weak key maps

rdb 8 years ago
parent
commit
6ecfcb1fd3

+ 21 - 3
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;
 }
 

+ 2 - 0
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;

+ 1 - 0
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;
   }
 }

+ 7 - 3
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<GraphicsStateGuardianBase, PT(GeomMunger) > Mungers;
+  typedef SimpleHashMap<size_t, PT(GeomMunger), size_t_hash> 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<size_t, WCPT(RenderState), size_t_hash> 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<RenderState>;
+  friend class StateMunger;
 };
 
 // We can safely redefine this as a no-op.

+ 9 - 4
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;
 }

+ 0 - 2
panda/src/pgraph/stateMunger.h

@@ -33,8 +33,6 @@ public:
 protected:
   virtual CPT(RenderState) munge_state_impl(const RenderState *state);
 
-  typedef WeakKeyHashMap<RenderState, WCPT(RenderState) > StateMap;
-  StateMap _state_map;
 
 public:
   static TypeHandle get_class_type() {