소스 검색

don't let geom-vertex-cache hang on to textures

David Rose 19 년 전
부모
커밋
c6681570d0

+ 11 - 1
panda/src/dxgsg8/dxGeomMunger8.I

@@ -28,7 +28,17 @@ DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) :
   _texture(state->get_texture()),
   _tex_gen(state->get_tex_gen())
 {
+  _filtered_texture = (TextureAttrib *)NULL;
+  _reffed_filtered_texture = false;
   if (_texture != (TextureAttrib *)NULL) {
-    _texture = _texture->filter_to_max(gsg->get_max_texture_stages());
+    _filtered_texture = _texture->filter_to_max(gsg->get_max_texture_stages());
+    if (_filtered_texture != _texture) {
+      _filtered_texture->ref();
+      _reffed_filtered_texture = true;
+    }
   }
+  // Set a callback to unregister ourselves when either the Texture or
+  // the TexGen object gets deleted.
+  _texture.set_callback(this);
+  _tex_gen.set_callback(this);
 }

+ 42 - 10
panda/src/dxgsg8/dxGeomMunger8.cxx

@@ -24,6 +24,37 @@
 GeomMunger *DXGeomMunger8::_deleted_chain = NULL;
 TypeHandle DXGeomMunger8::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger8::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DXGeomMunger8::
+~DXGeomMunger8() {
+  if (_reffed_filtered_texture) {
+    unref_delete(_filtered_texture);
+    _reffed_filtered_texture = false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger8::wp_callback
+//       Access: Public, Virtual
+//  Description: This callback is set to be made whenever the
+//               associated _texture or _tex_gen attributes are
+//               destructed, in which case the GeomMunger is invalid
+//               and should no longer be used.
+////////////////////////////////////////////////////////////////////
+void DXGeomMunger8::
+wp_callback(void *) {
+  unregister_myself();
+
+  if (_reffed_filtered_texture) {
+    unref_delete(_filtered_texture);
+    _reffed_filtered_texture = false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGeomMunger8::munge_format_impl
 //       Access: Protected, Virtual
@@ -110,13 +141,13 @@ munge_format_impl(const GeomVertexFormat *orig,
 
   // Now copy all of the texture coordinates in, in order by stage
   // index.  But we have to reuse previous columns.
-  if (_texture != (TextureAttrib *)NULL) {
+  if (_filtered_texture != (TextureAttrib *)NULL) {
     typedef pset<const InternalName *> UsedStages;
     UsedStages used_stages;
 
-    int num_stages = _texture->get_num_on_stages();
+    int num_stages = _filtered_texture->get_num_on_stages();
     for (int i = 0; i < num_stages; ++i) {
-      TextureStage *stage = _texture->get_on_stage(i);
+      TextureStage *stage = _filtered_texture->get_on_stage(i);
 
       InternalName *name = stage->get_texcoord_name();
       if (used_stages.insert(name).second) {
@@ -154,8 +185,8 @@ munge_format_impl(const GeomVertexFormat *orig,
 int DXGeomMunger8::
 compare_to_impl(const GeomMunger *other) const {
   const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other);
-  if (_texture != om->_texture) {
-    return _texture < om->_texture ? -1 : 1;
+  if (_filtered_texture != om->_filtered_texture) {
+    return _filtered_texture < om->_filtered_texture ? -1 : 1;
   }
   if (_tex_gen != om->_tex_gen) {
     return _tex_gen < om->_tex_gen ? -1 : 1;
@@ -174,12 +205,13 @@ compare_to_impl(const GeomMunger *other) const {
 ////////////////////////////////////////////////////////////////////
 int DXGeomMunger8::
 geom_compare_to_impl(const GeomMunger *other) const {
-  // Unlike GLGeomMunger, we do consider _texture and _tex_gen
-  // important for this purpose, since they control the number and
-  // order of texture coordinates we might put into the FVF.
+  // Unlike GLGeomMunger, we do consider _filtered_texture and
+  // _tex_gen important for this purpose, since they control the
+  // number and order of texture coordinates we might put into the
+  // FVF.
   const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other);
-  if (_texture != om->_texture) {
-    return _texture < om->_texture ? -1 : 1;
+  if (_filtered_texture != om->_filtered_texture) {
+    return _filtered_texture < om->_filtered_texture ? -1 : 1;
   }
   if (_tex_gen != om->_tex_gen) {
     return _tex_gen < om->_tex_gen ? -1 : 1;

+ 16 - 3
panda/src/dxgsg8/dxGeomMunger8.h

@@ -22,6 +22,8 @@
 #include "pandabase.h"
 #include "standardMunger.h"
 #include "graphicsStateGuardian.h"
+#include "weakPointerTo.h"
+#include "weakPointerCallback.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DXGeomMunger8
@@ -31,11 +33,14 @@
 //               and that all relevant components are packed into a
 //               single array, in the correct order.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger {
+class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger, public WeakPointerCallback {
 public:
   INLINE DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state);
+  virtual ~DXGeomMunger8();
   ALLOC_DELETED_CHAIN(DXGeomMunger8);
 
+  virtual void wp_callback(void *);
+
 protected:
   virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig,
                                                     const GeomVertexAnimationSpec &animation);
@@ -44,8 +49,16 @@ protected:
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
 
 private:
-  CPT(TextureAttrib) _texture;
-  CPT(TexGenAttrib) _tex_gen;
+  WCPT(TextureAttrib) _texture;
+  WCPT(TexGenAttrib) _tex_gen;
+
+  // This pointer is derived from _texture, above.  In the case that
+  // it is a different pointer, we maintain its reference count
+  // explicitly.  If it is the same pointer, we don't reference count
+  // it at all (so we won't hold on to the reference count
+  // unnecessarily).
+  const TextureAttrib *_filtered_texture;
+  bool _reffed_filtered_texture;
 
   static GeomMunger *_deleted_chain;
 

+ 11 - 1
panda/src/dxgsg9/dxGeomMunger9.I

@@ -28,8 +28,18 @@ DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) :
   _texture(state->get_texture()),
   _tex_gen(state->get_tex_gen())
 {
+  _filtered_texture = (TextureAttrib *)NULL;
+  _reffed_filtered_texture = false;
   if (_texture != (TextureAttrib *)NULL) {
-    _texture = _texture->filter_to_max(gsg->get_max_texture_stages());
+    _filtered_texture = _texture->filter_to_max(gsg->get_max_texture_stages());
+    if (_filtered_texture != _texture) {
+      _filtered_texture->ref();
+      _reffed_filtered_texture = true;
+    }
   }
+  // Set a callback to unregister ourselves when either the Texture or
+  // the TexGen object gets deleted.
+  _texture.set_callback(this);
+  _tex_gen.set_callback(this);
 }
 

+ 43 - 11
panda/src/dxgsg9/dxGeomMunger9.cxx

@@ -24,6 +24,37 @@
 GeomMunger *DXGeomMunger9::_deleted_chain = NULL;
 TypeHandle DXGeomMunger9::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger9::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DXGeomMunger9::
+~DXGeomMunger9() {
+  if (_reffed_filtered_texture) {
+    unref_delete(_filtered_texture);
+    _reffed_filtered_texture = false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger9::wp_callback
+//       Access: Public, Virtual
+//  Description: This callback is set to be made whenever the
+//               associated _texture or _tex_gen attributes are
+//               destructed, in which case the GeomMunger is invalid
+//               and should no longer be used.
+////////////////////////////////////////////////////////////////////
+void DXGeomMunger9::
+wp_callback(void *) {
+  unregister_myself();
+
+  if (_reffed_filtered_texture) {
+    unref_delete(_filtered_texture);
+    _reffed_filtered_texture = false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGeomMunger9::munge_format_impl
 //       Access: Protected, Virtual
@@ -37,7 +68,7 @@ munge_format_impl(const GeomVertexFormat *orig,
     if (animation.get_animation_type() != AT_none) {
       dxgsg9_cat.debug()
         << "preparing animation type " << animation << " for " << *orig
-  << "\n";
+        << "\n";
     }
   }
   // We have to build a completely new format that includes only the
@@ -110,13 +141,13 @@ munge_format_impl(const GeomVertexFormat *orig,
 
   // Now copy all of the texture coordinates in, in order by stage
   // index.  But we have to reuse previous columns.
-  if (_texture != (TextureAttrib *)NULL) {
+  if (_filtered_texture != (TextureAttrib *)NULL) {
     typedef pset<const InternalName *> UsedStages;
     UsedStages used_stages;
 
-    int num_stages = _texture->get_num_on_stages();
+    int num_stages = _filtered_texture->get_num_on_stages();
     for (int i = 0; i < num_stages; ++i) {
-      TextureStage *stage = _texture->get_on_stage(i);
+      TextureStage *stage = _filtered_texture->get_on_stage(i);
 
       InternalName *name = stage->get_texcoord_name();
       if (used_stages.insert(name).second) {
@@ -154,8 +185,8 @@ munge_format_impl(const GeomVertexFormat *orig,
 int DXGeomMunger9::
 compare_to_impl(const GeomMunger *other) const {
   const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
-  if (_texture != om->_texture) {
-    return _texture < om->_texture ? -1 : 1;
+  if (_filtered_texture != om->_filtered_texture) {
+    return _filtered_texture < om->_filtered_texture ? -1 : 1;
   }
   if (_tex_gen != om->_tex_gen) {
     return _tex_gen < om->_tex_gen ? -1 : 1;
@@ -174,12 +205,13 @@ compare_to_impl(const GeomMunger *other) const {
 ////////////////////////////////////////////////////////////////////
 int DXGeomMunger9::
 geom_compare_to_impl(const GeomMunger *other) const {
-  // Unlike GLGeomMunger, we do consider _texture and _tex_gen
-  // important for this purpose, since they control the number and
-  // order of texture coordinates we might put into the FVF.
+  // Unlike GLGeomMunger, we do consider _filtered_texture and
+  // _tex_gen important for this purpose, since they control the
+  // number and order of texture coordinates we might put into the
+  // FVF.
   const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
-  if (_texture != om->_texture) {
-    return _texture < om->_texture ? -1 : 1;
+  if (_filtered_texture != om->_filtered_texture) {
+    return _filtered_texture < om->_filtered_texture ? -1 : 1;
   }
   if (_tex_gen != om->_tex_gen) {
     return _tex_gen < om->_tex_gen ? -1 : 1;

+ 16 - 3
panda/src/dxgsg9/dxGeomMunger9.h

@@ -22,6 +22,8 @@
 #include "pandabase.h"
 #include "standardMunger.h"
 #include "graphicsStateGuardian.h"
+#include "weakPointerTo.h"
+#include "weakPointerCallback.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DXGeomMunger9
@@ -31,11 +33,14 @@
 //               and that all relevant components are packed into a
 //               single array, in the correct order.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDADX DXGeomMunger9 : public StandardMunger {
+class EXPCL_PANDADX DXGeomMunger9 : public StandardMunger, public WeakPointerCallback {
 public:
   INLINE DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state);
+  virtual ~DXGeomMunger9();
   ALLOC_DELETED_CHAIN(DXGeomMunger9);
 
+  virtual void wp_callback(void *);
+
 protected:
   virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig,
                                                     const GeomVertexAnimationSpec &animation);
@@ -44,8 +49,16 @@ protected:
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
 
 private:
-  CPT(TextureAttrib) _texture;
-  CPT(TexGenAttrib) _tex_gen;
+  WCPT(TextureAttrib) _texture;
+  WCPT(TexGenAttrib) _tex_gen;
+
+  // This pointer is derived from _texture, above.  In the case that
+  // it is a different pointer, we maintain its reference count
+  // explicitly.  If it is the same pointer, we don't reference count
+  // it at all (so we won't hold on to the reference count
+  // unnecessarily).
+  const TextureAttrib *_filtered_texture;
+  bool _reffed_filtered_texture;
 
   static GeomMunger *_deleted_chain;