Browse Source

runtime improvements

David Rose 20 years ago
parent
commit
0bd34f9f4b

+ 1 - 1
dtool/Config.pp

@@ -289,7 +289,7 @@
 // to help track memory leaks, and also report total memory usage on
 // PStats.  There is some small overhead for having this ability
 // available, even if it is unused.
-#defer DO_MEMORY_USAGE $[<= $[OPTIMIZE], 3]
+#defer DO_MEMORY_USAGE $[<= $[OPTIMIZE], 2]
 
 // Do you want to compile in support for pipelining?  This enables
 // setting and accessing multiple different copies of frame-specific

+ 41 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -371,12 +371,52 @@ release_index_buffer(IndexBufferContext *) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_geom_munger
+//       Access: Public
+//  Description: Looks up or creates a GeomMunger object to munge
+//               vertices appropriate to this GSG for the indicated
+//               state.
+////////////////////////////////////////////////////////////////////
+PT(qpGeomMunger) GraphicsStateGuardian::
+get_geom_munger(const RenderState *state) {
+  // Before we even look up the map, see if the _last_mi value points
+  // to this GSG.  This is likely because we tend to visit the same
+  // state multiple times during a frame.  Also, this might well be
+  // the only GSG in the world anyway.
+  if (!state->_mungers.empty()) {
+    RenderState::Mungers::const_iterator mi = state->_last_mi;
+    if ((*mi).first == this && !(*mi).first.was_deleted()) {
+      return (*mi).second;
+    }
+  }
+
+  // Nope, we have to loop up in the map.
+  RenderState::Mungers::const_iterator mi = state->_mungers.find(this);
+  if (mi != state->_mungers.end() && !(*mi).first.was_deleted()) {
+    ((RenderState *)state)->_last_mi = mi;
+    return (*mi).second;
+  }
+
+  // Nothing in the map; create a new entry.
+  PT(qpGeomMunger) munger = make_geom_munger(state);
+
+  // Cast the RenderState to a non-const object.  We can do this
+  // because we are only updating a cache within the RenderState, not
+  // really changing any of its properties.
+  RenderState *nc_state = (RenderState *)state;
+  mi = nc_state->_mungers.insert(RenderState::Mungers::value_type(this, munger)).first;
+  nc_state->_last_mi = mi;
+
+  return munger;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::make_geom_munger
 //       Access: Public, Virtual
 //  Description: Creates a new GeomMunger object to munge vertices
 //               appropriate to this GSG for the indicated state.
 ////////////////////////////////////////////////////////////////////
 PT(qpGeomMunger) GraphicsStateGuardian::
-get_geom_munger(const RenderState *state) {
+make_geom_munger(const RenderState *state) {
   // The default implementation returns no munger at all, but
   // presumably, every kind of GSG needs some special munging action,
   // so real GSG's will override this to return something more

+ 2 - 1
panda/src/display/graphicsStateGuardian.h

@@ -122,7 +122,8 @@ public:
   virtual IndexBufferContext *prepare_index_buffer(qpGeomPrimitive *data);
   virtual void release_index_buffer(IndexBufferContext *ibc);
 
-  virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
+  PT(qpGeomMunger) get_geom_munger(const RenderState *state);
+  virtual PT(qpGeomMunger) make_geom_munger(const RenderState *state);
 
   virtual void set_state_and_transform(const RenderState *state,
                                        const TransformState *transform);

+ 2 - 2
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -3550,13 +3550,13 @@ release_index_buffer(IndexBufferContext *ibc) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DXGraphicsStateGuardian8::get_geom_munger
+//     Function: DXGraphicsStateGuardian8::make_geom_munger
 //       Access: Public, Virtual
 //  Description: Creates a new GeomMunger object to munge vertices
 //               appropriate to this GSG for the indicated state.
 ////////////////////////////////////////////////////////////////////
 PT(qpGeomMunger) DXGraphicsStateGuardian8::
-get_geom_munger(const RenderState *state) {
+make_geom_munger(const RenderState *state) {
   PT(DXGeomMunger8) munger = new DXGeomMunger8(this, state);
   return qpGeomMunger::register_munger(munger);
 }

+ 1 - 1
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -115,7 +115,7 @@ public:
   void apply_index_buffer(IndexBufferContext *ibc);
   virtual void release_index_buffer(IndexBufferContext *ibc);
 
-  virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
+  virtual PT(qpGeomMunger) make_geom_munger(const RenderState *state);
 
   virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
                                            const RenderBuffer &rb);

+ 20 - 0
panda/src/express/pointerTo.I

@@ -39,6 +39,16 @@ PointerTo(const PointerTo<T> &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PointerTo::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE PointerTo<T>::
+~PointerTo() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerTo::Dereference operator
 //       Access: Public
@@ -138,6 +148,16 @@ ConstPointerTo(const PointerTo<T> &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ConstPointerTo::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE ConstPointerTo<T>::
+~ConstPointerTo() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ConstPointerTo::Copy Constructor
 //       Access: Public

+ 2 - 0
panda/src/express/pointerTo.h

@@ -85,6 +85,7 @@ public:
 PUBLISHED:
   INLINE PointerTo(To *ptr = (To *)NULL);
   INLINE PointerTo(const PointerTo<T> &copy);
+  INLINE ~PointerTo();
 
 public:
   INLINE To &operator *() const;
@@ -142,6 +143,7 @@ PUBLISHED:
   INLINE ConstPointerTo(const To *ptr = (const To *)NULL);
   INLINE ConstPointerTo(const PointerTo<T> &copy);
   INLINE ConstPointerTo(const ConstPointerTo<T> &copy);
+  INLINE ~ConstPointerTo();
 
 public:
   INLINE const To &operator *() const;

+ 24 - 11
panda/src/express/pointerToBase.I

@@ -58,7 +58,7 @@ INLINE PointerToBase<T>::
 //               reference count and increment the new one.
 ////////////////////////////////////////////////////////////////////
 template<class T>
-void PointerToBase<T>::
+INLINE void PointerToBase<T>::
 reassign(To *ptr) {
   if (ptr != (To *)_void_ptr) {
     // First save the old pointer; we won't delete it until we have
@@ -73,16 +73,7 @@ reassign(To *ptr) {
       ptr->ref();
 #ifdef DO_MEMORY_USAGE
       if (MemoryUsage::get_track_memory_usage()) {
-        // Make sure the MemoryUsage record knows what the TypeHandle
-        // is, if we know it ourselves.
-        TypeHandle type = get_type_handle(To);
-        if (type == TypeHandle::none()) {
-          do_init_type(To);
-          type = get_type_handle(To);
-        }
-        if (type != TypeHandle::none()) {
-          MemoryUsage::update_type(ptr, type);
-        }
+        update_type(ptr);
       }
 #endif
     }
@@ -105,6 +96,28 @@ reassign(const PointerToBase<To> &copy) {
   reassign((To *)copy._void_ptr);
 }
 
+#ifdef DO_MEMORY_USAGE
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::update_type
+//       Access: Protected
+//  Description: Ensures that the MemoryUsage record for the pointer
+//               has the right type of object, if we know the type
+//               ourselves.
+////////////////////////////////////////////////////////////////////
+template<class T>
+void PointerToBase<T>::
+update_type(To *ptr) {
+  TypeHandle type = get_type_handle(To);
+  if (type == TypeHandle::none()) {
+    do_init_type(To);
+    type = get_type_handle(To);
+  }
+  if (type != TypeHandle::none()) {
+    MemoryUsage::update_type(ptr, type);
+  }
+}
+#endif  // DO_MEMORY_USAGE
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerToBase::clear

+ 5 - 1
panda/src/express/pointerToBase.h

@@ -42,9 +42,13 @@ protected:
   INLINE PointerToBase(const PointerToBase<T> &copy);
   INLINE ~PointerToBase();
 
-  void reassign(To *ptr);
+  INLINE void reassign(To *ptr);
   INLINE void reassign(const PointerToBase<To> &copy);
 
+#ifdef DO_MEMORY_USAGE
+  void update_type(To *ptr);
+#endif  // DO_MEMORY_USAGE
+
   // No assignment or retrieval functions are declared in
   // PointerToBase, because we will have to specialize on const
   // vs. non-const later.

+ 0 - 151
panda/src/express/pointerToVoid.I

@@ -59,157 +59,6 @@ get_hash() const {
   return (size_t)_void_ptr;
 }
 
-#if 0
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator == (const void *other) const {
-  return _void_ptr == other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator != (const void *other) const {
-  return _void_ptr != other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator > (const void *other) const {
-  return _void_ptr > other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator <= (const void *other) const {
-  return _void_ptr <= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator >= (const void *other) const {
-  return _void_ptr >= other;
-}
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator == (void *other) const {
-  return _void_ptr == other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator != (void *other) const {
-  return _void_ptr != other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator > (void *other) const {
-  return _void_ptr > other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator <= (void *other) const {
-  return _void_ptr <= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator >= (void *other) const {
-  return _void_ptr >= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator == (const PointerToVoid &other) const {
-  return _void_ptr == other._void_ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator != (const PointerToVoid &other) const {
-  return _void_ptr != other._void_ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator > (const PointerToVoid &other) const {
-  return _void_ptr > other._void_ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator <= (const PointerToVoid &other) const {
-  return _void_ptr <= other._void_ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToVoid::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE bool PointerToVoid::
-operator >= (const PointerToVoid &other) const {
-  return _void_ptr >= other._void_ptr;
-}
-#endif  // WIN32_VC
-
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerToVoid::Less-than operator
 //       Access: Public

+ 0 - 18
panda/src/express/pointerToVoid.h

@@ -45,24 +45,6 @@ PUBLISHED:
 public:
   // These comparison functions are common to all things PointerTo, so
   // they're defined up here.
-#if 0
-  INLINE bool operator == (const void *other) const;
-  INLINE bool operator != (const void *other) const;
-  INLINE bool operator > (const void *other) const;
-  INLINE bool operator <= (const void *other) const;
-  INLINE bool operator >= (const void *other) const;
-  INLINE bool operator == (void *other) const;
-  INLINE bool operator != (void *other) const;
-  INLINE bool operator > (void *other) const;
-  INLINE bool operator <= (void *other) const;
-  INLINE bool operator >= (void *other) const;
-
-  INLINE bool operator == (const PointerToVoid &other) const;
-  INLINE bool operator != (const PointerToVoid &other) const;
-  INLINE bool operator > (const PointerToVoid &other) const;
-  INLINE bool operator <= (const PointerToVoid &other) const;
-  INLINE bool operator >= (const PointerToVoid &other) const;
-#endif  // WIN32_VC
   INLINE bool operator < (const void *other) const;
   INLINE bool operator < (const PointerToVoid &other) const;
 

+ 9 - 48
panda/src/express/referenceCount.I

@@ -188,21 +188,7 @@ get_ref_count() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int ReferenceCount::
 ref() const {
-  nassertr(this != NULL, 0);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_ref_count != deleted_ref_count, 0);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_ref_count >= 0, 0);
+  nassertr(test_ref_count_integrity(), 0);
 
   return AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
 }
@@ -234,26 +220,12 @@ ref() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int ReferenceCount::
 unref() const {
-  nassertr(this != NULL, false);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_ref_count != deleted_ref_count, false);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_ref_count >= 0, false);
+  nassertr(test_ref_count_integrity(), 0);
 
   // If this assertion fails, you tried to unref an object with a
   // zero reference count.  Are you using ref() and unref()
   // directly?  Are you sure you can't use PointerTo's?
-  nassertr(_ref_count > 0, false);
+  nassertr(_ref_count > 0, 0);
   return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
 }
 
@@ -262,26 +234,15 @@ unref() const {
 //     Function: ReferenceCount::test_ref_count_integrity
 //       Access: Published
 //  Description: Does some easy checks to make sure that the reference
-//               count isn't completely bogus.
+//               count isn't completely bogus.  Returns true if ok,
+//               false otherwise.
 ////////////////////////////////////////////////////////////////////
-INLINE void ReferenceCount::
+INLINE bool ReferenceCount::
 test_ref_count_integrity() const {
 #ifndef NDEBUG
-  nassertv(this != NULL);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertv(_ref_count != deleted_ref_count);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertv(_ref_count >= 0);
+  return do_test_ref_count_integrity();
+#else
+  return true;
 #endif
 }
 

+ 28 - 0
panda/src/express/referenceCount.cxx

@@ -20,3 +20,31 @@
 #include "referenceCount.h"
 
 TypeHandle ReferenceCount::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::do_test_ref_count_integrity
+//       Access: Protected
+//  Description: Does some easy checks to make sure that the reference
+//               count isn't completely bogus.  Returns true if ok,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool ReferenceCount::
+do_test_ref_count_integrity() const {
+  nassertr(this != NULL, false);
+
+  // If this assertion fails, we're trying to delete an object that
+  // was just deleted.  Possibly you used a real pointer instead of a
+  // PointerTo at some point, and the object was deleted when the
+  // PointerTo went out of scope.  Maybe you tried to create an
+  // automatic (local variable) instance of a class that derives from
+  // ReferenceCount.  Or maybe your headers are out of sync, and you
+  // need to make clean in direct or some higher tree.
+  nassertr(_ref_count != deleted_ref_count, false);
+
+  // If this assertion fails, the reference counts are all screwed
+  // up altogether.  Maybe some errant code stomped all over memory
+  // somewhere.
+  nassertr(_ref_count >= 0, false);
+
+  return true;
+}

+ 4 - 1
panda/src/express/referenceCount.h

@@ -51,7 +51,7 @@ PUBLISHED:
   INLINE int ref() const;
   INLINE int unref() const;
 
-  INLINE void test_ref_count_integrity() const;
+  INLINE bool test_ref_count_integrity() const;
 
 public:
   INLINE void local_object();
@@ -61,6 +61,9 @@ public:
   INLINE void weak_ref(WeakPointerToVoid *ptv);
   INLINE void weak_unref(WeakPointerToVoid *ptv);
 
+protected:
+  bool do_test_ref_count_integrity() const;
+
 private:
   enum { 
     // We use this value as a flag to indicate an object has been

+ 2 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -3210,13 +3210,13 @@ setup_primitive(const qpGeomPrimitive *data) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::get_geom_munger
+//     Function: GLGraphicsStateGuardian::make_geom_munger
 //       Access: Public, Virtual
 //  Description: Creates a new GeomMunger object to munge vertices
 //               appropriate to this GSG for the indicated state.
 ////////////////////////////////////////////////////////////////////
 PT(qpGeomMunger) CLP(GraphicsStateGuardian)::
-get_geom_munger(const RenderState *state) {
+make_geom_munger(const RenderState *state) {
   PT(CLP(GeomMunger)) munger = new CLP(GeomMunger)(this, state);
   return qpGeomMunger::register_munger(munger);
 }

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -123,7 +123,7 @@ public:
   virtual void release_index_buffer(IndexBufferContext *ibc);
   const unsigned char *setup_primitive(const qpGeomPrimitive *data);
 
-  virtual PT(qpGeomMunger) get_geom_munger(const RenderState *state);
+  virtual PT(qpGeomMunger) make_geom_munger(const RenderState *state);
 
   virtual void framebuffer_copy_to_texture
     (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb);

+ 0 - 19
panda/src/pgraph/cullResult.I

@@ -54,22 +54,3 @@ get_bin(int bin_index) {
   }
   return make_new_bin(bin_index);
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: CullResult::get_geom_munger
-//       Access: Private
-//  Description: Returns a suitable GeomMunger for the indicated
-//               state.  This will ask the GSG to create a new munger
-//               if we haven't already created one for this state;
-//               otherwise, it will return the existing one.
-////////////////////////////////////////////////////////////////////
-INLINE PT(qpGeomMunger) CullResult::
-get_geom_munger(const RenderState *state) {
-  Mungers::iterator mi = _mungers.find(state);
-  if (mi != _mungers.end()) {
-    return (*mi).second;
-  }
-  PT(qpGeomMunger) munger = _gsg->get_geom_munger(state);
-  _mungers.insert(Mungers::value_type(state, munger));
-  return munger;
-}

+ 2 - 2
panda/src/pgraph/cullResult.cxx

@@ -129,7 +129,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
               get_dual_transparent_state();
             transparent_part->_state = state->compose(transparent_state);
             transparent_part->munge_geom
-              (_gsg, get_geom_munger(transparent_part->_state),
+              (_gsg, _gsg->get_geom_munger(transparent_part->_state),
                traverser);
             CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
             nassertv(bin != (CullBin *)NULL);
@@ -157,7 +157,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
 
   // Munge vertices as needed for the GSG's requirements, and the
   // object's current state.
-  object->munge_geom(_gsg, get_geom_munger(object->_state), traverser);
+  object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state), traverser);
   
   CullBin *bin = get_bin(object->_state->get_bin_index());
   nassertv(bin != (CullBin *)NULL);

+ 0 - 4
panda/src/pgraph/cullResult.h

@@ -66,7 +66,6 @@ public:
 
 private:
   CullBin *make_new_bin(int bin_index);
-  INLINE PT(qpGeomMunger) get_geom_munger(const RenderState *state);
 
   static CPT(RenderState) get_binary_state();
   static CPT(RenderState) get_dual_transparent_state();
@@ -75,9 +74,6 @@ private:
 
   GraphicsStateGuardianBase *_gsg;
 
-  typedef pmap<CPT(RenderState), PT(qpGeomMunger) > Mungers;
-  Mungers _mungers;
-
   typedef pvector< PT(CullBin) > Bins;
   Bins _bins;
 };

+ 1 - 0
panda/src/pgraph/renderState.cxx

@@ -65,6 +65,7 @@ RenderState() {
   }
   _saved_entry = _states->end();
   _flags = 0;
+  _last_mi = _mungers.end();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 14 - 0
panda/src/pgraph/renderState.h

@@ -30,6 +30,8 @@
 #include "renderModeAttrib.h"
 #include "texGenAttrib.h"
 #include "texMatrixAttrib.h"
+#include "qpgeomMunger.h"
+#include "weakPointerTo.h"
 
 class GraphicsStateGuardianBase;
 class FogAttrib;
@@ -215,6 +217,16 @@ private:
   CompositionCache _composition_cache;
   CompositionCache _invert_composition_cache;
 
+  // This is here to provide a quick cache of GSG + RenderState ->
+  // GeomMunger for the cull phase.  It is here because it is faster
+  // to look up the GSG 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 pmap<WCPT(GraphicsStateGuardianBase), PT(qpGeomMunger) > Mungers;
+  Mungers _mungers;
+  Mungers::const_iterator _last_mi;
+
   // This is used to mark nodes as we visit them to detect cycles.
   UpdateSeq _cycle_detect;
   static UpdateSeq _last_cycle_detect;
@@ -305,6 +317,8 @@ public:
 
 private:
   static TypeHandle _type_handle;
+
+  friend class GraphicsStateGuardian;
 };
 
 INLINE ostream &operator << (ostream &out, const RenderState &state) {

+ 7 - 50
panda/src/putil/cachedTypedWritableReferenceCount.I

@@ -157,21 +157,7 @@ get_cache_ref_count() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int CachedTypedWritableReferenceCount::
 cache_ref() const {
-  nassertr(this != NULL, 0);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_cache_ref_count != -100, 0);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_cache_ref_count >= 0, 0);
+  nassertr(test_ref_count_integrity(), 0);
 
   ref();
   return AtomicAdjust::inc(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
@@ -204,58 +190,29 @@ cache_ref() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int CachedTypedWritableReferenceCount::
 cache_unref() const {
-  nassertr(this != NULL, false);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_cache_ref_count != -100, false);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_cache_ref_count >= 0, false);
+  nassertr(test_ref_count_integrity(), 0);
 
   // If this assertion fails, you tried to unref an object with a
   // zero reference count.  Are you using ref() and unref()
   // directly?  Are you sure you can't use PointerTo's?
-  nassertr(_cache_ref_count > 0, false);
+  nassertr(_cache_ref_count > 0, 0);
 
   unref();
   return AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count);
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CachedTypedWritableReferenceCount::test_ref_count_integrity
 //       Access: Published
 //  Description: Does some easy checks to make sure that the reference
 //               count isn't completely bogus.
 ////////////////////////////////////////////////////////////////////
-INLINE void CachedTypedWritableReferenceCount::
+INLINE bool CachedTypedWritableReferenceCount::
 test_ref_count_integrity() const {
 #ifndef NDEBUG
-  nassertv(this != NULL);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertv(_cache_ref_count != -100);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertv(_cache_ref_count >= 0);
-
-  TypedWritableReferenceCount::test_ref_count_integrity();
+  return do_test_ref_count_integrity();
+#else
+  return true;
 #endif
 }
 

+ 27 - 0
panda/src/putil/cachedTypedWritableReferenceCount.cxx

@@ -19,3 +19,30 @@
 #include "cachedTypedWritableReferenceCount.h"
 
 TypeHandle CachedTypedWritableReferenceCount::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: CachedTypedWritableReferenceCount::do_test_ref_count_integrity
+//       Access: Protected
+//  Description: Does some easy checks to make sure that the reference
+//               count isn't completely bogus.
+////////////////////////////////////////////////////////////////////
+bool CachedTypedWritableReferenceCount::
+do_test_ref_count_integrity() const {
+  nassertr(this != NULL, false);
+
+  // If this assertion fails, we're trying to delete an object that
+  // was just deleted.  Possibly you used a real pointer instead of a
+  // PointerTo at some point, and the object was deleted when the
+  // PointerTo went out of scope.  Maybe you tried to create an
+  // automatic (local variable) instance of a class that derives from
+  // ReferenceCount.  Or maybe your headers are out of sync, and you
+  // need to make clean in direct or some higher tree.
+  nassertr(_cache_ref_count != -100, false);
+
+  // If this assertion fails, the reference counts are all screwed
+  // up altogether.  Maybe some errant code stomped all over memory
+  // somewhere.
+  nassertr(_cache_ref_count >= 0, false);
+
+  return TypedWritableReferenceCount::do_test_ref_count_integrity();
+}

+ 4 - 1
panda/src/putil/cachedTypedWritableReferenceCount.h

@@ -52,7 +52,10 @@ PUBLISHED:
   INLINE int get_cache_ref_count() const;
   INLINE int cache_ref() const;
   INLINE int cache_unref() const;
-  INLINE void test_ref_count_integrity() const;
+  INLINE bool test_ref_count_integrity() const;
+
+protected:
+  bool do_test_ref_count_integrity() const;
 
 private:
   int _cache_ref_count;

+ 7 - 50
panda/src/putil/nodeCachedReferenceCount.I

@@ -157,21 +157,7 @@ get_node_ref_count() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int NodeCachedReferenceCount::
 node_ref() const {
-  nassertr(this != NULL, 0);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_node_ref_count != -100, 0);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_node_ref_count >= 0, 0);
+  nassertr(test_ref_count_integrity(), 0);
 
   ref();
   return AtomicAdjust::inc(((NodeCachedReferenceCount *)this)->_node_ref_count);
@@ -204,58 +190,29 @@ node_ref() const {
 ////////////////////////////////////////////////////////////////////
 INLINE int NodeCachedReferenceCount::
 node_unref() const {
-  nassertr(this != NULL, false);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertr(_node_ref_count != -100, false);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertr(_node_ref_count >= 0, false);
+  nassertr(test_ref_count_integrity(), 0);
 
   // If this assertion fails, you tried to unref an object with a
   // zero reference count.  Are you using ref() and unref()
   // directly?  Are you sure you can't use PointerTo's?
-  nassertr(_node_ref_count > 0, false);
+  nassertr(_node_ref_count > 0, 0);
 
   unref();
   return AtomicAdjust::dec(((NodeCachedReferenceCount *)this)->_node_ref_count);
 }
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeCachedReferenceCount::test_ref_count_integrity
 //       Access: Published
 //  Description: Does some easy checks to make sure that the reference
 //               count isn't completely bogus.
 ////////////////////////////////////////////////////////////////////
-INLINE void NodeCachedReferenceCount::
+INLINE bool NodeCachedReferenceCount::
 test_ref_count_integrity() const {
 #ifndef NDEBUG
-  nassertv(this != NULL);
-
-  // If this assertion fails, we're trying to delete an object that
-  // was just deleted.  Possibly you used a real pointer instead of a
-  // PointerTo at some point, and the object was deleted when the
-  // PointerTo went out of scope.  Maybe you tried to create an
-  // automatic (local variable) instance of a class that derives from
-  // ReferenceCount.  Or maybe your headers are out of sync, and you
-  // need to make clean in direct or some higher tree.
-  nassertv(_node_ref_count != -100);
-
-  // If this assertion fails, the reference counts are all screwed
-  // up altogether.  Maybe some errant code stomped all over memory
-  // somewhere.
-  nassertv(_node_ref_count >= 0);
-
-  CachedTypedWritableReferenceCount::test_ref_count_integrity();
+  return do_test_ref_count_integrity();
+#else
+  return true;
 #endif
 }
 

+ 26 - 0
panda/src/putil/nodeCachedReferenceCount.cxx

@@ -20,3 +20,29 @@
 
 TypeHandle NodeCachedReferenceCount::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeCachedReferenceCount::do_test_ref_count_integrity
+//       Access: Protected
+//  Description: Does some easy checks to make sure that the reference
+//               count isn't completely bogus.
+////////////////////////////////////////////////////////////////////
+bool NodeCachedReferenceCount::
+do_test_ref_count_integrity() const {
+  nassertr(this != NULL, false);
+
+  // If this assertion fails, we're trying to delete an object that
+  // was just deleted.  Possibly you used a real pointer instead of a
+  // PointerTo at some point, and the object was deleted when the
+  // PointerTo went out of scope.  Maybe you tried to create an
+  // automatic (local variable) instance of a class that derives from
+  // ReferenceCount.  Or maybe your headers are out of sync, and you
+  // need to make clean in direct or some higher tree.
+  nassertr(_node_ref_count != -100, false);
+
+  // If this assertion fails, the reference counts are all screwed
+  // up altogether.  Maybe some errant code stomped all over memory
+  // somewhere.
+  nassertr(_node_ref_count >= 0, false);
+
+  return CachedTypedWritableReferenceCount::do_test_ref_count_integrity();
+}

+ 4 - 1
panda/src/putil/nodeCachedReferenceCount.h

@@ -59,7 +59,7 @@ PUBLISHED:
   INLINE int get_node_ref_count() const;
   INLINE int node_ref() const;
   INLINE int node_unref() const;
-  INLINE void test_ref_count_integrity() const;
+  INLINE bool test_ref_count_integrity() const;
 
   enum Referenced {
     R_node  = 0x001,
@@ -67,6 +67,9 @@ PUBLISHED:
   };
 
   INLINE int get_referenced_bits() const;
+
+protected:
+  bool do_test_ref_count_integrity() const;
   
 private:
   int _node_ref_count;

+ 20 - 0
panda/src/putil/nodePointerTo.I

@@ -39,6 +39,16 @@ NodePointerTo(const NodePointerTo<T> &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePointerTo::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE NodePointerTo<T>::
+~NodePointerTo() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePointerTo::Dereference operator
 //       Access: Public
@@ -150,6 +160,16 @@ NodeConstPointerTo(const NodeConstPointerTo<T> &copy) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeConstPointerTo::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE NodeConstPointerTo<T>::
+~NodeConstPointerTo() {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeConstPointerTo::Dereference operator
 //       Access: Public

+ 3 - 3
panda/src/putil/nodePointerTo.h

@@ -24,9 +24,7 @@
 
 ////////////////////////////////////////////////////////////////////
 //       Class : NodePointerTo
-// Description : 
-
-//               This implements the special NodePointerTo template
+// Description : This implements the special NodePointerTo template
 //               class, which works just like PointerTo except it
 //               manages the objects node_ref_count instead of the
 //               normal ref_count.
@@ -37,6 +35,7 @@ public:
   typedef TYPENAME NodePointerToBase<T>::To To;
   INLINE NodePointerTo(To *ptr = (To *)NULL);
   INLINE NodePointerTo(const NodePointerTo<T> &copy);
+  INLINE ~NodePointerTo();
 
   INLINE To &operator *() const;
   INLINE To *operator -> () const;
@@ -61,6 +60,7 @@ public:
   INLINE NodeConstPointerTo(const To *ptr = (const To *)NULL);
   INLINE NodeConstPointerTo(const NodePointerTo<T> &copy);
   INLINE NodeConstPointerTo(const NodeConstPointerTo<T> &copy);
+  INLINE ~NodeConstPointerTo();
 
   INLINE const To &operator *() const;
   INLINE const To *operator -> () const;