Browse Source

robustify collect_vertex_data some more

David Rose 20 years ago
parent
commit
500f17c091

+ 14 - 5
panda/src/display/graphicsStateGuardian.cxx

@@ -47,11 +47,16 @@
 
 PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage");
 PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
+PStatCollector GraphicsStateGuardian::_texture_count_pcollector("Prepared Textures");
+PStatCollector GraphicsStateGuardian::_active_texture_count_pcollector("Prepared Textures:Active");
+PStatCollector GraphicsStateGuardian::_total_buffer_count_pcollector("Vertex buffer count");
+PStatCollector GraphicsStateGuardian::_active_vertex_buffer_count_pcollector("Vertex buffer count:Active vertex");
+PStatCollector GraphicsStateGuardian::_active_index_buffer_count_pcollector("Vertex buffer count:Active index");
 PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
 PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
-PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffers");
-PStatCollector GraphicsStateGuardian::_active_vertex_buffers_pcollector("Vertex buffers:Active vertex");
-PStatCollector GraphicsStateGuardian::_active_index_buffers_pcollector("Vertex buffers:Active index");
+PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffer size");
+PStatCollector GraphicsStateGuardian::_active_vertex_buffers_pcollector("Vertex buffer size:Active vertex");
+PStatCollector GraphicsStateGuardian::_active_index_buffers_pcollector("Vertex buffer size:Active index");
 PStatCollector GraphicsStateGuardian::_total_geom_node_pcollector("Prepared GeomNodes");
 PStatCollector GraphicsStateGuardian::_active_geom_node_pcollector("Prepared GeomNodes:Active");
 PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory");
@@ -1552,6 +1557,8 @@ init_frame_pstats() {
     _active_geom_node_pcollector.clear_level();
     _active_vertex_buffers_pcollector.clear_level();
     _active_index_buffers_pcollector.clear_level();
+    _active_vertex_buffer_count_pcollector.clear_level();
+    _active_index_buffer_count_pcollector.clear_level();
     
     // Also clear out our other counters while we're here.
     _vertices_tristrip_pcollector.clear_level();
@@ -1606,8 +1613,8 @@ add_to_geom_record(GeomContext *gc) {
 //       Access: Protected
 //  Description: Records that the indicated data array has been drawn
 //               this frame.  This function is only used to update the
-//               PStats active_vertex_buffers collector; it gets compiled out
-//               if we aren't using PStats.
+//               PStats active_vertex_buffers collector; it gets
+//               compiled out if we aren't using PStats.
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 add_to_vertex_buffer_record(VertexBufferContext *vbc) {
@@ -1617,6 +1624,7 @@ add_to_vertex_buffer_record(VertexBufferContext *vbc) {
     if (PStatClient::is_connected()) {
       if (_current_vertex_buffers.insert(vbc).second) {
         _active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes());
+        _active_vertex_buffer_count_pcollector.add_level(1);
       }
     }
   }
@@ -1638,6 +1646,7 @@ add_to_index_buffer_record(IndexBufferContext *ibc) {
     if (PStatClient::is_connected()) {
       if (_current_index_buffers.insert(ibc).second) {
         _active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes());
+        _active_index_buffer_count_pcollector.add_level(1);
       }
     }
   }

+ 5 - 0
panda/src/display/graphicsStateGuardian.h

@@ -332,6 +332,11 @@ public:
   // Statistics
   static PStatCollector _total_texusage_pcollector;
   static PStatCollector _active_texusage_pcollector;
+  static PStatCollector _texture_count_pcollector;
+  static PStatCollector _active_texture_count_pcollector;
+  static PStatCollector _total_buffer_count_pcollector;
+  static PStatCollector _active_vertex_buffer_count_pcollector;
+  static PStatCollector _active_index_buffer_count_pcollector;
   static PStatCollector _total_geom_pcollector;
   static PStatCollector _active_geom_pcollector;
   static PStatCollector _total_buffers_pcollector;

+ 1 - 0
panda/src/egg2pg/load_egg_file.cxx

@@ -46,6 +46,7 @@ load_from_loader(EggLoader &loader) {
 
     SceneGraphReducer gr;
     int num_reduced = gr.flatten(loader._root, combine_siblings_bits);
+    //    gr.collect_vertex_data(loader._root);
     egg2pg_cat.info() << "Flattened " << num_reduced << " nodes.\n";
   }
 

+ 8 - 1
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -27,7 +27,8 @@
 #include "mutexHolder.h"
 
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
-PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffers");
+PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer size");
+PStatCollector PreparedGraphicsObjects::_total_buffer_count_pcollector("Vertex buffer count");
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PreparedGraphicsObjects::Constructor
@@ -449,6 +450,7 @@ release_vertex_buffer(VertexBufferContext *vbc) {
 
   vbc->_data->clear_prepared(this);
   _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
+  _total_buffer_count_pcollector.sub_level(1);
 
   // We have to set the Data pointer to NULL at this point, since
   // the Data itself might destruct at any time after it has been
@@ -482,6 +484,7 @@ release_all_vertex_buffers() {
     VertexBufferContext *vbc = (*vbci);
     vbc->_data->clear_prepared(this);
     _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
+    _total_buffer_count_pcollector.sub_level(1);
     vbc->_data = (qpGeomVertexArrayData *)NULL;
 
     _released_vertex_buffers.insert(vbc);
@@ -532,6 +535,7 @@ prepare_vertex_buffer_now(qpGeomVertexArrayData *data, GraphicsStateGuardianBase
     // GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to
     // count it again here.
     //_total_buffers_pcollector.add_level(vbc->get_data_size_bytes());
+    _total_buffer_count_pcollector.add_level(1);
   }
 
   return vbc;
@@ -596,6 +600,7 @@ release_index_buffer(IndexBufferContext *ibc) {
 
   ibc->_data->clear_prepared(this);
   _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
+  _total_buffer_count_pcollector.sub_level(1);
 
   // We have to set the Data pointer to NULL at this point, since
   // the Data itself might destruct at any time after it has been
@@ -629,6 +634,7 @@ release_all_index_buffers() {
     IndexBufferContext *ibc = (*ibci);
     ibc->_data->clear_prepared(this);
     _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
+    _total_buffer_count_pcollector.sub_level(1);
     ibc->_data = (qpGeomPrimitive *)NULL;
 
     _released_index_buffers.insert(ibc);
@@ -679,6 +685,7 @@ prepare_index_buffer_now(qpGeomPrimitive *data, GraphicsStateGuardianBase *gsg)
     // GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to
     // count it again here.
     //_total_buffers_pcollector.add_level(ibc->get_data_size_bytes());
+    _total_buffer_count_pcollector.add_level(1);
   }
 
   return ibc;

+ 1 - 0
panda/src/gobj/preparedGraphicsObjects.h

@@ -116,6 +116,7 @@ private:
 
   static PStatCollector _total_texusage_pcollector;
   static PStatCollector _total_buffers_pcollector;
+  static PStatCollector _total_buffer_count_pcollector;
 
   friend class GraphicsStateGuardian;
 };

+ 41 - 25
panda/src/pgraph/geomTransformer.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "geomTransformer.h"
+#include "sceneGraphReducer.h"
 #include "geomNode.h"
 #include "qpgeom.h"
 #include "qpgeomVertexRewriter.h"
@@ -528,29 +529,23 @@ apply_state(GeomNode *node, const RenderState *state) {
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomTransformer::collect_vertex_data
 //       Access: Public
-//  Description: Transforms the vertices and the normals in the
-//               indicated Geom by the indicated matrix.  Returns true
-//               if the Geom was changed, false otherwise.
+//  Description: Collects together GeomVertexDatas from different
+//               geoms into one big (or several big) GeomVertexDatas.
+//               Returns the number of unique GeomVertexDatas created.
 ////////////////////////////////////////////////////////////////////
-bool GeomTransformer::
-collect_vertex_data(Geom *geom, bool keep_names) {
-  if (!geom->is_of_type(qpGeom::get_class_type())) {
-    return false;
-  }
-
-  qpGeom *qpgeom = DCAST(qpGeom, geom);
-
-  const qpGeomVertexData *vdata = qpgeom->get_vertex_data();
+int GeomTransformer::
+collect_vertex_data(qpGeom *geom, int collect_bits) {
+  const qpGeomVertexData *vdata = geom->get_vertex_data();
 
   if (vdata->get_num_vertices() > _max_collect_vertices) {
     // Don't even bother.
-    return false;
+    return 0;
   }
 
   const qpGeomVertexFormat *format = vdata->get_format();
 
   NewCollectedKey key;
-  if (keep_names) {
+  if ((collect_bits & SceneGraphReducer::CVD_name) != 0) {
     key._name = vdata->get_name();
   }
   key._format = format;
@@ -561,12 +556,13 @@ collect_vertex_data(Geom *geom, bool keep_names) {
   if (ai != _already_collected.end()) {
     // We've previously collected this vertex data; reuse it.
     const AlreadyCollectedData &acd = (*ai).second;
-    qpgeom->offset_vertices(acd._data, acd._offset);
-    return true;
+    geom->offset_vertices(acd._data, acd._offset);
+    return 0;
   }
 
   // We haven't collected this vertex data yet; append the vertices
   // onto the new data.
+  int num_created = 0;
 
   NewCollectedData::iterator ni = _new_collected_data.find(key);
   PT(qpGeomVertexData) new_data;
@@ -576,6 +572,7 @@ collect_vertex_data(Geom *geom, bool keep_names) {
     new_data = new qpGeomVertexData(vdata->get_name(), format, 
                                     vdata->get_usage_hint());
     _new_collected_data[key] = new_data;
+    ++num_created;
   }
 
   int offset = new_data->get_num_vertices();
@@ -588,6 +585,7 @@ collect_vertex_data(Geom *geom, bool keep_names) {
     _new_collected_data[key] = new_data;
     offset = 0;
     new_num_vertices = vdata->get_num_vertices();
+    ++num_created;
   }
 
   new_data->set_num_vertices(new_num_vertices);
@@ -604,12 +602,12 @@ collect_vertex_data(Geom *geom, bool keep_names) {
            old_array->get_data(), copy_bytes);
   }
 
-  qpgeom->offset_vertices(new_data, offset);
   AlreadyCollectedData &acd = _already_collected[vdata];
   acd._data = new_data;
   acd._offset = offset;
+  geom->offset_vertices(new_data, offset);
 
-  return true;
+  return num_created;
 }
 
 
@@ -621,20 +619,38 @@ collect_vertex_data(Geom *geom, bool keep_names) {
 //               GeomVertexData structure.  This is designed to
 //               minimize context switches on the graphics card.
 ////////////////////////////////////////////////////////////////////
-bool GeomTransformer::
-collect_vertex_data(GeomNode *node, bool keep_names) {
-  bool any_changed = false;
+int GeomTransformer::
+collect_vertex_data(GeomNode *node, int collect_bits) {
+  int num_created = 0;
+
+  GeomTransformer *dynamic = NULL;
 
   GeomNode::CDWriter cdata(node->_cycler);
   GeomNode::Geoms::iterator gi;
   for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
     GeomNode::GeomEntry &entry = (*gi);
-    PT(Geom) new_geom = entry._geom->make_copy();
-    if (collect_vertex_data(new_geom, keep_names)) {
+    if (entry._geom->is_of_type(qpGeom::get_class_type())) {
+      PT(qpGeom) new_geom = DCAST(qpGeom, entry._geom->make_copy());
       entry._geom = new_geom;
-      any_changed = true;
+
+      if ((collect_bits & SceneGraphReducer::CVD_avoid_dynamic) != 0 &&
+          new_geom->get_vertex_data()->get_usage_hint() < qpGeomUsageHint::UH_static) {
+        // This one has some dynamic properties.  Collect it
+        // independently of the outside world.
+        if (dynamic == (GeomTransformer *)NULL) {
+          dynamic = new GeomTransformer(*this);
+        }
+        num_created += dynamic->collect_vertex_data(new_geom, collect_bits);
+        
+      } else {
+        num_created += collect_vertex_data(new_geom, collect_bits);
+      }
     }
   }
 
-  return any_changed;
+  if (dynamic != (GeomTransformer *)NULL) {
+    delete dynamic;
+  }
+
+  return num_created;
 }

+ 3 - 2
panda/src/pgraph/geomTransformer.h

@@ -28,6 +28,7 @@
 class GeomNode;
 class RenderState;
 class InternalName;
+class qpGeom;
 
 ///////////////////////////////////////////////////////////////////
 //       Class : GeomTransformer
@@ -72,8 +73,8 @@ public:
 
   bool apply_state(GeomNode *node, const RenderState *state);
 
-  bool collect_vertex_data(Geom *geom, bool keep_names);
-  bool collect_vertex_data(GeomNode *node, bool keep_names);
+  int collect_vertex_data(qpGeom *geom, int collect_bits);
+  int collect_vertex_data(GeomNode *node, int collect_bits);
 
 private:
   int _max_collect_vertices;

+ 35 - 22
panda/src/pgraph/sceneGraphReducer.cxx

@@ -574,37 +574,50 @@ choose_name(PandaNode *preserve, PandaNode *source1, PandaNode *source2) {
 int SceneGraphReducer::
 r_collect_vertex_data(PandaNode *node, int collect_bits,
                       GeomTransformer &transformer) {
-  int num_collected = 0;
+  int num_created = 0;
 
-  if ((collect_bits & CVD_model) != 0 &&
-      node->is_of_type(ModelNode::get_class_type())) {
-    // When we come to a model node, start a new collection.
+  int this_node_bits = 0;
+  if (node->is_of_type(ModelNode::get_class_type())) {
+    this_node_bits |= CVD_model;
+  }
+  if (!node->get_transform()->is_identity()) {
+    this_node_bits |= CVD_transform;
+  }
+
+  if ((collect_bits & this_node_bits) != 0) {
+    // We need to start a unique collection here.
     GeomTransformer new_transformer(transformer);
 
+    if (node->is_geom_node()) {
+      // When we come to geom node, collect.
+      if (new_transformer.collect_vertex_data(DCAST(GeomNode, node), collect_bits)) {
+        ++num_created;
+      }
+    }
+
     PandaNode::Children children = node->get_children();
     int num_children = children.get_num_children();
     for (int i = 0; i < num_children; ++i) {
-      num_collected += 
+      num_created += 
         r_collect_vertex_data(children.get_child(i), collect_bits, new_transformer);
     }
-    return num_collected;
-  }
 
-  if (node->is_geom_node()) {
-    // When we come to geom node, collect.
-    bool keep_names = ((collect_bits & SceneGraphReducer::CVD_name) != 0);
-    if (transformer.collect_vertex_data(DCAST(GeomNode, node), keep_names)) {
-      ++num_collected;
-    }
-  }
+  } else {
+    // Keep the same collection.
 
-  // Then recurse.
-  PandaNode::Children children = node->get_children();
-  int num_children = children.get_num_children();
-  for (int i = 0; i < num_children; ++i) {
-    num_collected +=
-      r_collect_vertex_data(children.get_child(i), collect_bits, transformer);
+    if (node->is_geom_node()) {
+      if (transformer.collect_vertex_data(DCAST(GeomNode, node), collect_bits)) {
+        ++num_created;
+      }
+    }
+    
+    PandaNode::Children children = node->get_children();
+    int num_children = children.get_num_children();
+    for (int i = 0; i < num_children; ++i) {
+      num_created +=
+        r_collect_vertex_data(children.get_child(i), collect_bits, transformer);
+    }
   }
-
-  return num_collected;
+    
+  return num_created;
 }

+ 17 - 0
panda/src/pgraph/sceneGraphReducer.h

@@ -62,8 +62,25 @@ PUBLISHED:
   };
 
   enum CollectVertexData {
+    // If set, two GeomVertexDatas with different names will not be
+    // collected together.
     CVD_name           = 0x001,
+
+    // If set, a ModelNode begins a subgraph of nodes whose
+    // GeomVertexDatas will not be collected with nodes outside the
+    // subgraph.
     CVD_model          = 0x002,
+
+    // If set, a non-identity transform begins a subgraph of nodes
+    // whose GeomVertexDatas will not be collected with nodes outside
+    // the subgraph.
+    CVD_transform      = 0x004,
+
+    // If set, GeomVertexDatas with any usage_hint other than
+    // UH_static will not be collected with any other Geoms in a
+    // different GeomNode.  However, two different Geoms within the
+    // same node might still be collected together.
+    CVD_avoid_dynamic  = 0x008,
   };
 
   INLINE void apply_attribs(PandaNode *node, int attrib_types = ~0);

+ 8 - 3
panda/src/pstatclient/pStatProperties.cxx

@@ -151,13 +151,18 @@ static LevelCollectorProperties level_properties[] = {
   { 1, "Texture memory:In use",            { 0.0, 1.0, 1.0 } },
   { 1, "Texture manager",                  { 1.0, 0.0, 0.0 },  "MB", 12, 1048576 },
   { 1, "Texture manager:Resident",         { 1.0, 1.0, 0.0 } },
+  { 1, "Prepared Textures",                { 0.6, 0.8, 0.0 },  "", 500 },
+  { 1, "Prepared Textures:Active",         { 0.0, 0.6, 0.8 } },
   { 1, "Prepared Geoms",                   { 1.0, 0.0, 0.5 },  "", 500 },
   { 1, "Prepared Geoms:Active",            { 0.5, 1.0, 0.8 } },
   { 1, "Prepared GeomNodes",               { 1.0, 0.0, 0.5 },  "", 500 },
   { 1, "Prepared GeomNodes:Active",        { 0.5, 1.0, 0.8 } },
-  { 1, "Vertex buffers:Active vertex",     { 1.0, 0.0, 0.5 } },
-  { 1, "Vertex buffers:Active index" ,     { 0.5, 0.6, 1.0 } },
-  { 1, "Vertex buffers",                   { 0.0, 0.0, 1.0 },  "MB", 12, 1048576 },
+  { 1, "Vertex buffer size",               { 0.0, 0.0, 1.0 },  "MB", 12, 1048576 },
+  { 1, "Vertex buffer size:Active vertex", { 1.0, 0.0, 0.5 } },
+  { 1, "Vertex buffer size:Active index" , { 0.5, 0.6, 1.0 } },
+  { 1, "Vertex buffer count",              { 0.0, 0.6, 0.8 },  "", 500 },
+  { 1, "Vertex buffer count:Active vertex", { 0.8, 0.0, 0.6 } },
+  { 1, "Vertex buffer count:Active index", { 0.8, 0.6, 0.3 } },
   { 1, "Vertices",                         { 0.5, 0.2, 0.0 },  "K", 10, 1000 },
   { 1, "Vertices:Other",                   { 0.2, 0.2, 0.2 } },
   { 1, "Vertices:Triangles",               { 0.8, 0.8, 0.8 } },