Browse Source

more robust pstats for qpgeom stuff

David Rose 20 years ago
parent
commit
c83feafc70

+ 4 - 0
panda/src/display/graphicsEngine.cxx

@@ -32,6 +32,7 @@
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 #include "cullFaceAttrib.h"
 #include "cullFaceAttrib.h"
 #include "string_utils.h"
 #include "string_utils.h"
+#include "qpgeomCacheManager.h"
 
 
 #if defined(WIN32)
 #if defined(WIN32)
   #define WINDOWS_LEAN_AND_MEAN
   #define WINDOWS_LEAN_AND_MEAN
@@ -500,6 +501,9 @@ render_frame() {
   CullTraverser::_nodes_pcollector.clear_level();
   CullTraverser::_nodes_pcollector.clear_level();
   CullTraverser::_geom_nodes_pcollector.clear_level();
   CullTraverser::_geom_nodes_pcollector.clear_level();
   CullTraverser::_geoms_pcollector.clear_level();
   CullTraverser::_geoms_pcollector.clear_level();
+  qpGeomCacheManager::_geom_cache_record_pcollector.clear_level();
+  qpGeomCacheManager::_geom_cache_erase_pcollector.clear_level();
+  qpGeomCacheManager::_geom_cache_evict_pcollector.clear_level();
   
   
   _transform_states_pcollector.set_level(TransformState::get_num_states());
   _transform_states_pcollector.set_level(TransformState::get_num_states());
   _render_states_pcollector.set_level(RenderState::get_num_states());
   _render_states_pcollector.set_level(RenderState::get_num_states());

+ 54 - 12
panda/src/display/graphicsStateGuardian.cxx

@@ -49,9 +49,12 @@ PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage"
 PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
 PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
 PStatCollector GraphicsStateGuardian::_texture_count_pcollector("Prepared Textures");
 PStatCollector GraphicsStateGuardian::_texture_count_pcollector("Prepared Textures");
 PStatCollector GraphicsStateGuardian::_active_texture_count_pcollector("Prepared Textures:Active");
 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::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
+PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
+PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
+PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
+PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
+PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
 PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
 PStatCollector GraphicsStateGuardian::_total_geom_pcollector("Prepared Geoms");
 PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
 PStatCollector GraphicsStateGuardian::_active_geom_pcollector("Prepared Geoms:Active");
 PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffer size");
 PStatCollector GraphicsStateGuardian::_total_buffers_pcollector("Vertex buffer size");
@@ -63,6 +66,11 @@ PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory")
 PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use");
 PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use");
 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector("Texture manager:Resident");
+PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector("Primitive batches");
+PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector("Primitive batches:Triangle strips");
+PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector("Primitive batches:Triangle fans");
+PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector("Primitive batches:Triangles");
+PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector("Primitive batches:Other");
 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips");
 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector("Vertices:Triangle strips");
 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans");
 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector("Vertices:Triangle fans");
 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles");
 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector("Vertices:Triangles");
@@ -1541,14 +1549,19 @@ init_frame_pstats() {
     _current_vertex_buffers.clear();
     _current_vertex_buffers.clear();
     _current_index_buffers.clear();
     _current_index_buffers.clear();
     _active_texusage_pcollector.clear_level();
     _active_texusage_pcollector.clear_level();
+    _data_transferred_pcollector.clear_level();
     _active_geom_pcollector.clear_level();
     _active_geom_pcollector.clear_level();
     _active_geom_node_pcollector.clear_level();
     _active_geom_node_pcollector.clear_level();
     _active_vertex_buffers_pcollector.clear_level();
     _active_vertex_buffers_pcollector.clear_level();
     _active_index_buffers_pcollector.clear_level();
     _active_index_buffers_pcollector.clear_level();
-    _active_vertex_buffer_count_pcollector.clear_level();
-    _active_index_buffer_count_pcollector.clear_level();
+    _vertex_buffer_switch_pcollector.clear_level();
+    _index_buffer_switch_pcollector.clear_level();
     
     
-    // Also clear out our other counters while we're here.
+    _primitive_batches_pcollector.clear_level();
+    _primitive_batches_tristrip_pcollector.clear_level();
+    _primitive_batches_trifan_pcollector.clear_level();
+    _primitive_batches_tri_pcollector.clear_level();
+    _primitive_batches_other_pcollector.clear_level();
     _vertices_tristrip_pcollector.clear_level();
     _vertices_tristrip_pcollector.clear_level();
     _vertices_trifan_pcollector.clear_level();
     _vertices_trifan_pcollector.clear_level();
     _vertices_tri_pcollector.clear_level();
     _vertices_tri_pcollector.clear_level();
@@ -1607,12 +1620,10 @@ add_to_geom_record(GeomContext *gc) {
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 add_to_vertex_buffer_record(VertexBufferContext *vbc) {
 add_to_vertex_buffer_record(VertexBufferContext *vbc) {
   if (vbc != (VertexBufferContext *)NULL) {
   if (vbc != (VertexBufferContext *)NULL) {
-    int delta = vbc->get_data()->get_data_size_bytes() - vbc->get_data_size_bytes();
-    _total_buffers_pcollector.add_level(delta);
     if (PStatClient::is_connected()) {
     if (PStatClient::is_connected()) {
+      _vertex_buffer_switch_pcollector.add_level(1);
       if (_current_vertex_buffers.insert(vbc).second) {
       if (_current_vertex_buffers.insert(vbc).second) {
         _active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes());
         _active_vertex_buffers_pcollector.add_level(vbc->get_data()->get_data_size_bytes());
-        _active_vertex_buffer_count_pcollector.add_level(1);
       }
       }
     }
     }
   }
   }
@@ -1629,16 +1640,47 @@ add_to_vertex_buffer_record(VertexBufferContext *vbc) {
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 add_to_index_buffer_record(IndexBufferContext *ibc) {
 add_to_index_buffer_record(IndexBufferContext *ibc) {
   if (ibc != (IndexBufferContext *)NULL) {
   if (ibc != (IndexBufferContext *)NULL) {
-    int delta = ibc->get_data()->get_data_size_bytes() - ibc->get_data_size_bytes();
-    _total_buffers_pcollector.add_level(delta);
     if (PStatClient::is_connected()) {
     if (PStatClient::is_connected()) {
+      _index_buffer_switch_pcollector.add_level(1);
       if (_current_index_buffers.insert(ibc).second) {
       if (_current_index_buffers.insert(ibc).second) {
         _active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes());
         _active_index_buffers_pcollector.add_level(ibc->get_data()->get_data_size_bytes());
-        _active_index_buffer_count_pcollector.add_level(1);
       }
       }
     }
     }
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::add_to_total_buffer_record
+//       Access: Protected
+//  Description: Records that the indicated data array has been loaded
+//               this frame.  This function is only used to update the
+//               PStats total_buffers collector; it gets
+//               compiled out if we aren't using PStats.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+add_to_total_buffer_record(VertexBufferContext *vbc) {
+  if (vbc != (VertexBufferContext *)NULL) {
+    int delta = vbc->get_data()->get_data_size_bytes() - vbc->get_data_size_bytes();
+    _total_buffers_pcollector.add_level(delta);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::add_to_total_buffer_record
+//       Access: Protected
+//  Description: Records that the indicated data array has been loaded
+//               this frame.  This function is only used to update the
+//               PStats total_buffers collector; it gets
+//               compiled out if we aren't using PStats.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+add_to_total_buffer_record(IndexBufferContext *ibc) {
+  if (ibc != (IndexBufferContext *)NULL) {
+    int delta = ibc->get_data()->get_data_size_bytes() - ibc->get_data_size_bytes();
+    _total_buffers_pcollector.add_level(delta);
+  }
+}
+
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 16 - 4
panda/src/display/graphicsStateGuardian.h

@@ -240,6 +240,8 @@ protected:
   void add_to_geom_record(GeomContext *gc);
   void add_to_geom_record(GeomContext *gc);
   void add_to_vertex_buffer_record(VertexBufferContext *vbc);
   void add_to_vertex_buffer_record(VertexBufferContext *vbc);
   void add_to_index_buffer_record(IndexBufferContext *ibc);
   void add_to_index_buffer_record(IndexBufferContext *ibc);
+  void add_to_total_buffer_record(VertexBufferContext *vbc);
+  void add_to_total_buffer_record(IndexBufferContext *ibc);
 
 
   pset<TextureContext *> _current_textures;
   pset<TextureContext *> _current_textures;
   pset<GeomContext *> _current_geoms;
   pset<GeomContext *> _current_geoms;
@@ -251,7 +253,9 @@ protected:
   INLINE void add_to_geom_record(GeomContext *) { }
   INLINE void add_to_geom_record(GeomContext *) { }
   INLINE void record_state_change(TypeHandle) { }
   INLINE void record_state_change(TypeHandle) { }
   INLINE void add_to_vertex_buffer_record(VertexBufferContext *) { }
   INLINE void add_to_vertex_buffer_record(VertexBufferContext *) { }
-  INLINE void add_to_index_buffer_record(IndexBufferContext *i) { }
+  INLINE void add_to_index_buffer_record(IndexBufferContext *) { }
+  INLINE void add_to_total_buffer_record(VertexBufferContext *) { };
+  INLINE void add_to_total_buffer_record(IndexBufferContext *) { };
 #endif
 #endif
 
 
   static CPT(RenderState) get_unlit_state();
   static CPT(RenderState) get_unlit_state();
@@ -334,9 +338,12 @@ public:
   static PStatCollector _active_texusage_pcollector;
   static PStatCollector _active_texusage_pcollector;
   static PStatCollector _texture_count_pcollector;
   static PStatCollector _texture_count_pcollector;
   static PStatCollector _active_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 _vertex_buffer_switch_pcollector;
+  static PStatCollector _index_buffer_switch_pcollector;
+  static PStatCollector _load_vertex_buffer_pcollector;
+  static PStatCollector _load_index_buffer_pcollector;
+  static PStatCollector _load_texture_pcollector;
+  static PStatCollector _data_transferred_pcollector;
   static PStatCollector _total_geom_pcollector;
   static PStatCollector _total_geom_pcollector;
   static PStatCollector _active_geom_pcollector;
   static PStatCollector _active_geom_pcollector;
   static PStatCollector _total_buffers_pcollector;
   static PStatCollector _total_buffers_pcollector;
@@ -348,6 +355,11 @@ public:
   static PStatCollector _used_texmem_pcollector;
   static PStatCollector _used_texmem_pcollector;
   static PStatCollector _texmgrmem_total_pcollector;
   static PStatCollector _texmgrmem_total_pcollector;
   static PStatCollector _texmgrmem_resident_pcollector;
   static PStatCollector _texmgrmem_resident_pcollector;
+  static PStatCollector _primitive_batches_pcollector;
+  static PStatCollector _primitive_batches_tristrip_pcollector;
+  static PStatCollector _primitive_batches_trifan_pcollector;
+  static PStatCollector _primitive_batches_tri_pcollector;
+  static PStatCollector _primitive_batches_other_pcollector;
   static PStatCollector _vertices_tristrip_pcollector;
   static PStatCollector _vertices_tristrip_pcollector;
   static PStatCollector _vertices_trifan_pcollector;
   static PStatCollector _vertices_trifan_pcollector;
   static PStatCollector _vertices_tri_pcollector;
   static PStatCollector _vertices_tri_pcollector;

+ 8 - 3
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -2738,6 +2738,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
 void DXGraphicsStateGuardian8::
 void DXGraphicsStateGuardian8::
 draw_triangles(const qpGeomTriangles *primitive) {
 draw_triangles(const qpGeomTriangles *primitive) {
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
+  _primitive_batches_tri_pcollector.add_level(1);
   if (_vbuffer_active) {
   if (_vbuffer_active) {
     IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
     IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
     nassertv(ibc != (IndexBufferContext *)NULL);
     nassertv(ibc != (IndexBufferContext *)NULL);
@@ -2779,6 +2780,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     // One long triangle strip, connected by the degenerate vertices
     // One long triangle strip, connected by the degenerate vertices
     // that have already been set up within the primitive.
     // that have already been set up within the primitive.
     _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
     _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
+    _primitive_batches_tristrip_pcollector.add_level(1);
     if (_vbuffer_active) {
     if (_vbuffer_active) {
       IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
       IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
       nassertv(ibc != (IndexBufferContext *)NULL);
       nassertv(ibc != (IndexBufferContext *)NULL);
@@ -2804,6 +2806,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     // degenerate vertices.
     // degenerate vertices.
     CPTA_int ends = primitive->get_ends();
     CPTA_int ends = primitive->get_ends();
     int index_stride = primitive->get_index_stride();
     int index_stride = primitive->get_index_stride();
+    _primitive_batches_tristrip_pcollector.add_level(ends.size());
 
 
     qpGeomVertexReader mins(primitive->get_mins(), 0);
     qpGeomVertexReader mins(primitive->get_mins(), 0);
     qpGeomVertexReader maxs(primitive->get_maxs(), 0);
     qpGeomVertexReader maxs(primitive->get_maxs(), 0);
@@ -2866,6 +2869,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
   // with degenerate vertices, so no worries about that.
   // with degenerate vertices, so no worries about that.
   CPTA_int ends = primitive->get_ends();
   CPTA_int ends = primitive->get_ends();
   int index_stride = primitive->get_index_stride();
   int index_stride = primitive->get_index_stride();
+  _primitive_batches_trifan_pcollector.add_level(ends.size());
 
 
   qpGeomVertexReader mins(primitive->get_mins(), 0);
   qpGeomVertexReader mins(primitive->get_mins(), 0);
   qpGeomVertexReader maxs(primitive->get_maxs(), 0);
   qpGeomVertexReader maxs(primitive->get_maxs(), 0);
@@ -2920,6 +2924,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
 void DXGraphicsStateGuardian8::
 void DXGraphicsStateGuardian8::
 draw_lines(const qpGeomLines *primitive) {
 draw_lines(const qpGeomLines *primitive) {
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
+  _primitive_batches_other_pcollector.add_level(1);
   if (_vbuffer_active) {
   if (_vbuffer_active) {
     IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
     IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
     nassertv(ibc != (IndexBufferContext *)NULL);
     nassertv(ibc != (IndexBufferContext *)NULL);
@@ -3193,9 +3198,8 @@ VertexBufferContext *DXGraphicsStateGuardian8::
 prepare_vertex_buffer(qpGeomVertexArrayData *data) {
 prepare_vertex_buffer(qpGeomVertexArrayData *data) {
   DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
   DXVertexBufferContext8 *dvbc = new DXVertexBufferContext8(data);
 
 
-  if (vertex_buffers) {
+  if (vertex_buffers && data->get_usage_hint() != qpGeom::UH_client) {
     dvbc->create_vbuffer(*_pScrn);
     dvbc->create_vbuffer(*_pScrn);
-    dvbc->mark_loaded();
 
 
     if (dxgsg8_cat.is_debug()) {
     if (dxgsg8_cat.is_debug()) {
       dxgsg8_cat.debug()
       dxgsg8_cat.debug()
@@ -3232,6 +3236,7 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
         dvbc->upload_data();
         dvbc->upload_data();
       }
       }
       
       
+      add_to_total_buffer_record(dvbc);
       dvbc->mark_loaded();
       dvbc->mark_loaded();
     }
     }
 
 
@@ -3278,7 +3283,6 @@ prepare_index_buffer(qpGeomPrimitive *data) {
   DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data);
   DXIndexBufferContext8 *dibc = new DXIndexBufferContext8(data);
 
 
   dibc->create_ibuffer(*_pScrn);
   dibc->create_ibuffer(*_pScrn);
-  dibc->mark_loaded();
 
 
   if (dxgsg8_cat.is_debug()) {
   if (dxgsg8_cat.is_debug()) {
     dxgsg8_cat.debug()
     dxgsg8_cat.debug()
@@ -3315,6 +3319,7 @@ apply_index_buffer(IndexBufferContext *ibc) {
         dibc->upload_data();
         dibc->upload_data();
       }
       }
       
       
+      add_to_total_buffer_record(dibc);
       dibc->mark_loaded();
       dibc->mark_loaded();
     }
     }
 
 

+ 4 - 0
panda/src/dxgsg8/dxIndexBufferContext8.cxx

@@ -19,6 +19,8 @@
 #include "dxIndexBufferContext8.h"
 #include "dxIndexBufferContext8.h"
 #include "qpgeomPrimitive.h"
 #include "qpgeomPrimitive.h"
 #include "config_dxgsg8.h"
 #include "config_dxgsg8.h"
+#include "graphicsStateGuardian.h"
+#include "pStatTimer.h"
 #include <d3dx8.h>
 #include <d3dx8.h>
 
 
 TypeHandle DXIndexBufferContext8::_type_handle;
 TypeHandle DXIndexBufferContext8::_type_handle;
@@ -90,6 +92,7 @@ create_ibuffer(DXScreenData &scrn) {
 void DXIndexBufferContext8::
 void DXIndexBufferContext8::
 upload_data() {
 upload_data() {
   nassertv(_ibuffer != NULL);
   nassertv(_ibuffer != NULL);
+  PStatTimer timer(GraphicsStateGuardian::_load_index_buffer_pcollector);
 
 
   int data_size = get_data()->get_data_size_bytes();
   int data_size = get_data()->get_data_size_bytes();
   
   
@@ -107,6 +110,7 @@ upload_data() {
     return;
     return;
   }
   }
 
 
+  GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
   memcpy(local_pointer, get_data()->get_data(), data_size);
   memcpy(local_pointer, get_data()->get_data(), data_size);
 
 
   _ibuffer->Unlock();
   _ibuffer->Unlock();

+ 121 - 132
panda/src/dxgsg8/dxTextureContext8.cxx

@@ -21,7 +21,7 @@
 #include "dxTextureContext8.h"
 #include "dxTextureContext8.h"
 #include "config_dxgsg8.h"
 #include "config_dxgsg8.h"
 #include "dxGraphicsStateGuardian8.h"
 #include "dxGraphicsStateGuardian8.h"
-//#include "pnmImage.h"
+#include "pStatTimer.h"
 #include <d3dx8tex.h>
 #include <d3dx8tex.h>
 
 
 //#define FORCE_16bpp_1555
 //#define FORCE_16bpp_1555
@@ -559,22 +559,6 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
         dxgsg8_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<< TargetWidth<<"," << TargetHeight << ") to meet HW square texture reqmt\n";
         dxgsg8_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," <<dwOrigHeight << ") => ("<< TargetWidth<<"," << TargetHeight << ") to meet HW square texture reqmt\n";
 #endif
 #endif
     }
     }
-/*
-    // we now use D3DXLoadSurfFromMem to do resizing as well as fmt conversion
-    if(bShrinkOriginal) {
-        // need 2 add checks for errors
-        PNMImage pnmi_src;
-        PNMImage *pnmi = new PNMImage(TargetWidth, TargetHeight, cNumColorChannels);
-        _texture->store(pnmi_src);
-        pnmi->quick_filter_from(pnmi_src,0,0);
-
-        _texture->load(*pnmi);  // violates device independence of pixbufs
-
-        dwOrigWidth  = (DWORD)_texture->get_x_size();
-        dwOrigHeight = (DWORD)_texture->get_y_size();
-        delete pnmi;
-    }
-*/
 
 
     char *szErrorMsg;
     char *szErrorMsg;
 
 
@@ -931,128 +915,133 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) {
 
 
 HRESULT DXTextureContext8::
 HRESULT DXTextureContext8::
 FillDDSurfTexturePixels(void) {
 FillDDSurfTexturePixels(void) {
-    HRESULT hr=E_FAIL;
-    assert(IS_VALID_PTR(_texture));
-
-    CPTA_uchar image = _texture->get_ram_image();
-    if (image.is_null()) {
-      // The texture doesn't have an image to load.  That's ok; it
-      // might be a texture we've rendered to by frame buffer
-      // operations or something.
-      return S_OK;
-    }
-
-    assert(IS_VALID_PTR(_pD3DTexture8));
-
-    DWORD OrigWidth  = (DWORD) _texture->get_x_size();
-    DWORD OrigHeight = (DWORD) _texture->get_y_size();
-    DWORD cNumColorChannels = _texture->get_num_components();
-    D3DFORMAT SrcFormat=_PixBufD3DFmt;
-    BYTE *pPixels=(BYTE*)image.p();
-    int component_width = _texture->get_component_width();
-
-    assert(IS_VALID_PTR(pPixels));
-
-    IDirect3DSurface8 *pMipLevel0;
-    hr=_pD3DTexture8->GetSurfaceLevel(0,&pMipLevel0);
-    if(FAILED(hr)) {
-       dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
-       return E_FAIL;
+  HRESULT hr=E_FAIL;
+  assert(IS_VALID_PTR(_texture));
+
+  CPTA_uchar image = _texture->get_ram_image();
+  if (image.is_null()) {
+    // The texture doesn't have an image to load.  That's ok; it
+    // might be a texture we've rendered to by frame buffer
+    // operations or something.
+    return S_OK;
+  }
+
+  PStatTimer timer(GraphicsStateGuardian::_load_texture_pcollector);
+  
+  assert(IS_VALID_PTR(_pD3DTexture8));
+  
+  DWORD OrigWidth  = (DWORD) _texture->get_x_size();
+  DWORD OrigHeight = (DWORD) _texture->get_y_size();
+  DWORD cNumColorChannels = _texture->get_num_components();
+  D3DFORMAT SrcFormat=_PixBufD3DFmt;
+  BYTE *pPixels=(BYTE*)image.p();
+  int component_width = _texture->get_component_width();
+  
+  assert(IS_VALID_PTR(pPixels));
+  
+  IDirect3DSurface8 *pMipLevel0;
+  hr=_pD3DTexture8->GetSurfaceLevel(0,&pMipLevel0);
+  if(FAILED(hr)) {
+    dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", GetSurfaceLevel failed" << D3DERRORSTRING(hr);
+    return E_FAIL;
+  }
+  
+  RECT SrcSize;
+  SrcSize.left = SrcSize.top = 0;
+  SrcSize.right = OrigWidth;
+  SrcSize.bottom = OrigHeight;
+  
+  UINT SrcPixBufRowByteLength=OrigWidth*cNumColorChannels;
+  
+  DWORD Lev0Filter,MipFilterFlags;
+  bool bUsingTempPixBuf=false;
+  
+  // need filtering if size changes, (also if bitdepth reduced (need dithering)??)
+  Lev0Filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER;  //dithering looks ugly on i810 for 4444 textures
+  
+  // D3DXLoadSurfaceFromMemory will load black luminance and we want full white,
+  // so convert to explicit luminance-alpha format
+  if (_PixBufD3DFmt==D3DFMT_A8) {
+    // alloc buffer for explicit D3DFMT_A8L8
+    USHORT *pTempPixBuf=new USHORT[OrigWidth*OrigHeight];
+    if(!IS_VALID_PTR(pTempPixBuf)) {
+      dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
+      goto exit_FillDDSurf;
     }
     }
-
-    RECT SrcSize;
-    SrcSize.left = SrcSize.top = 0;
-    SrcSize.right = OrigWidth;
-    SrcSize.bottom = OrigHeight;
-
-    UINT SrcPixBufRowByteLength=OrigWidth*cNumColorChannels;
-
-    DWORD Lev0Filter,MipFilterFlags;
-    bool bUsingTempPixBuf=false;
-
-    // need filtering if size changes, (also if bitdepth reduced (need dithering)??)
-    Lev0Filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER;  //dithering looks ugly on i810 for 4444 textures
-
-    // D3DXLoadSurfaceFromMemory will load black luminance and we want full white,
-    // so convert to explicit luminance-alpha format
-    if (_PixBufD3DFmt==D3DFMT_A8) {
-      // alloc buffer for explicit D3DFMT_A8L8
-      USHORT *pTempPixBuf=new USHORT[OrigWidth*OrigHeight];
-      if(!IS_VALID_PTR(pTempPixBuf)) {
-        dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
-        goto exit_FillDDSurf;
+    bUsingTempPixBuf=true;
+    
+    USHORT *pOutPix=pTempPixBuf;
+    BYTE *pSrcPix=pPixels + component_width - 1;
+    for (UINT y = 0; y < OrigHeight; y++) {
+      for (UINT x = 0; 
+           x < OrigWidth; 
+           x++, pSrcPix += component_width, pOutPix++) {
+        // add full white, which is our interpretation of alpha-only
+        // (similar to default adding full opaque alpha 0xFF to
+        // RGB-only textures)
+        *pOutPix = ((*pSrcPix) << 8 ) | 0xFF;
       }
       }
-      bUsingTempPixBuf=true;
-      
-      USHORT *pOutPix=pTempPixBuf;
-      BYTE *pSrcPix=pPixels + component_width - 1;
-      for (UINT y = 0; y < OrigHeight; y++) {
-        for (UINT x = 0; 
-             x < OrigWidth; 
-             x++, pSrcPix += component_width, pOutPix++) {
-          // add full white, which is our interpretation of alpha-only
-          // (similar to default adding full opaque alpha 0xFF to
-          // RGB-only textures)
-          *pOutPix = ((*pSrcPix) << 8 ) | 0xFF;
-        }
-      }
-      
-      SrcFormat=D3DFMT_A8L8;
-      SrcPixBufRowByteLength=OrigWidth*sizeof(USHORT);
-      pPixels=(BYTE*)pTempPixBuf;
-      
-    } else if (component_width != 1) {
-      // Convert from 16-bit per channel (or larger) format down to
-      // 8-bit per channel.  This throws away precision in the
-      // original image, but dx8 doesn't support high-precision images
-      // anyway.
-
-      int num_components = _texture->get_num_components();
-      int num_pixels = OrigWidth * OrigHeight * num_components;
-      BYTE *pTempPixBuf = new BYTE[num_pixels];
-      if(!IS_VALID_PTR(pTempPixBuf)) {
-        dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
-        goto exit_FillDDSurf;
-      }
-      bUsingTempPixBuf=true;
-
-      BYTE *pSrcPix = pPixels + component_width - 1;
-      for (int i = 0; i < num_pixels; i++) {
-        pTempPixBuf[i] = *pSrcPix;
-        pSrcPix += component_width;
-      }
-      pPixels=(BYTE*)pTempPixBuf;
     }
     }
-
-
-    // filtering may be done here if texture if targetsize!=origsize
-    hr=D3DXLoadSurfaceFromMemory(pMipLevel0,(PALETTEENTRY*)NULL,(RECT*)NULL,(LPCVOID)pPixels,SrcFormat,
-                                 SrcPixBufRowByteLength,(PALETTEENTRY*)NULL,&SrcSize,Lev0Filter,(D3DCOLOR)0x0);
-    if(FAILED(hr)) {
-       dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
-       goto exit_FillDDSurf;
+    
+    SrcFormat=D3DFMT_A8L8;
+    SrcPixBufRowByteLength=OrigWidth*sizeof(USHORT);
+    pPixels=(BYTE*)pTempPixBuf;
+    
+  } else if (component_width != 1) {
+    // Convert from 16-bit per channel (or larger) format down to
+    // 8-bit per channel.  This throws away precision in the
+    // original image, but dx8 doesn't support high-precision images
+    // anyway.
+    
+    int num_components = _texture->get_num_components();
+    int num_pixels = OrigWidth * OrigHeight * num_components;
+    BYTE *pTempPixBuf = new BYTE[num_pixels];
+    if(!IS_VALID_PTR(pTempPixBuf)) {
+      dxgsg8_cat.error() << "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
+      goto exit_FillDDSurf;
     }
     }
-
-    if(_bHasMipMaps) {
-        if(!dx_use_triangle_mipgen_filter)
-          MipFilterFlags = D3DX_FILTER_BOX;
-         else MipFilterFlags = D3DX_FILTER_TRIANGLE;
-
+    bUsingTempPixBuf=true;
+    
+    BYTE *pSrcPix = pPixels + component_width - 1;
+    for (int i = 0; i < num_pixels; i++) {
+      pTempPixBuf[i] = *pSrcPix;
+      pSrcPix += component_width;
+    }
+    pPixels=(BYTE*)pTempPixBuf;
+  }
+  
+  
+  // filtering may be done here if texture if targetsize!=origsize
+#ifdef DO_PSTATS
+  GraphicsStateGuardian::_data_transferred_pcollector.add_level(SrcPixBufRowByteLength * OrigHeight);
+#endif
+  hr=D3DXLoadSurfaceFromMemory(pMipLevel0,(PALETTEENTRY*)NULL,(RECT*)NULL,(LPCVOID)pPixels,SrcFormat,
+                               SrcPixBufRowByteLength,(PALETTEENTRY*)NULL,&SrcSize,Lev0Filter,(D3DCOLOR)0x0);
+  if(FAILED(hr)) {
+    dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXLoadSurfFromMem failed" << D3DERRORSTRING(hr);
+    goto exit_FillDDSurf;
+  }
+  
+  if(_bHasMipMaps) {
+    if(!dx_use_triangle_mipgen_filter)
+      MipFilterFlags = D3DX_FILTER_BOX;
+    else MipFilterFlags = D3DX_FILTER_TRIANGLE;
+    
     //    MipFilterFlags|= D3DX_FILTER_DITHER;
     //    MipFilterFlags|= D3DX_FILTER_DITHER;
-
-        hr=D3DXFilterTexture(_pD3DTexture8,(PALETTEENTRY*)NULL,0,MipFilterFlags);
-        if(FAILED(hr)) {
-            dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXFilterTex failed" << D3DERRORSTRING(hr);
-            goto exit_FillDDSurf;
-        }
+    
+    hr=D3DXFilterTexture(_pD3DTexture8,(PALETTEENTRY*)NULL,0,MipFilterFlags);
+    if(FAILED(hr)) {
+      dxgsg8_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXFilterTex failed" << D3DERRORSTRING(hr);
+      goto exit_FillDDSurf;
     }
     }
-
+  }
+  
  exit_FillDDSurf:
  exit_FillDDSurf:
-    if(bUsingTempPixBuf) {
-      SAFE_DELETE_ARRAY(pPixels);
-    }
-    RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
-    return hr;
+  if(bUsingTempPixBuf) {
+    SAFE_DELETE_ARRAY(pPixels);
+  }
+  RELEASE(pMipLevel0,dxgsg8,"FillDDSurf MipLev0 texture ptr",RELEASE_ONCE);
+  return hr;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 4 - 0
panda/src/dxgsg8/dxVertexBufferContext8.cxx

@@ -19,6 +19,8 @@
 #include "dxVertexBufferContext8.h"
 #include "dxVertexBufferContext8.h"
 #include "qpgeomVertexArrayData.h"
 #include "qpgeomVertexArrayData.h"
 #include "qpgeomVertexArrayFormat.h"
 #include "qpgeomVertexArrayFormat.h"
+#include "graphicsStateGuardian.h"
+#include "pStatTimer.h"
 #include "internalName.h"
 #include "internalName.h"
 #include "config_dxgsg8.h"
 #include "config_dxgsg8.h"
 #include <d3dx8.h>
 #include <d3dx8.h>
@@ -182,6 +184,7 @@ create_vbuffer(DXScreenData &scrn) {
 void DXVertexBufferContext8::
 void DXVertexBufferContext8::
 upload_data() {
 upload_data() {
   nassertv(_vbuffer != NULL);
   nassertv(_vbuffer != NULL);
+  PStatTimer timer(GraphicsStateGuardian::_load_vertex_buffer_pcollector);
 
 
   int data_size = get_data()->get_data_size_bytes();
   int data_size = get_data()->get_data_size_bytes();
   
   
@@ -199,6 +202,7 @@ upload_data() {
     return;
     return;
   }
   }
 
 
+  GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
   memcpy(local_pointer, get_data()->get_data(), data_size);
   memcpy(local_pointer, get_data()->get_data(), data_size);
 
 
   _vbuffer->Unlock();
   _vbuffer->Unlock();

+ 117 - 14
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -75,9 +75,9 @@
 
 
 TypeHandle CLP(GraphicsStateGuardian)::_type_handle;
 TypeHandle CLP(GraphicsStateGuardian)::_type_handle;
 
 
-#ifdef DO_PSTATS
+PStatCollector CLP(GraphicsStateGuardian)::_load_display_list_pcollector("Draw:Transfer data:Display lists");
+PStatCollector CLP(GraphicsStateGuardian)::_primitive_batches_display_list_pcollector("Primitive batches:Display lists");
 PStatCollector CLP(GraphicsStateGuardian)::_vertices_display_list_pcollector("Vertices:Display lists");
 PStatCollector CLP(GraphicsStateGuardian)::_vertices_display_list_pcollector("Vertices:Display lists");
-#endif
 
 
 static void
 static void
 issue_vertex_gl(const Geom *geom, Geom::VertexIterator &viterator, 
 issue_vertex_gl(const Geom *geom, Geom::VertexIterator &viterator, 
@@ -1054,6 +1054,7 @@ begin_frame() {
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   _vertices_display_list_pcollector.clear_level();
   _vertices_display_list_pcollector.clear_level();
+  _primitive_batches_display_list_pcollector.clear_level();
 #endif
 #endif
 
 
   _actual_display_region = NULL;
   _actual_display_region = NULL;
@@ -2316,6 +2317,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
       GLP(CallList)(_geom_display_list);
       GLP(CallList)(_geom_display_list);
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
       _vertices_display_list_pcollector.add_level(ggc->_num_verts);
       _vertices_display_list_pcollector.add_level(ggc->_num_verts);
+      _primitive_batches_display_list_pcollector.add_level(1);
 #endif
 #endif
 
 
       // And now we don't need to do anything else for this geom.
       // And now we don't need to do anything else for this geom.
@@ -2323,7 +2325,11 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
       end_draw_primitives();
       end_draw_primitives();
       return false;
       return false;
     }
     }
-    
+
+    // Since we start this collector explicitly, we have to be sure to
+    // stop it again.
+    _load_display_list_pcollector.start();
+
     if (GLCAT.is_debug()) {
     if (GLCAT.is_debug()) {
       GLCAT.debug()
       GLCAT.debug()
         << "compiling display list " << _geom_display_list << "\n";
         << "compiling display list " << _geom_display_list << "\n";
@@ -2335,7 +2341,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
       GLP(NewList)(_geom_display_list, GL_COMPILE_AND_EXECUTE);
       GLP(NewList)(_geom_display_list, GL_COMPILE_AND_EXECUTE);
     } else {
     } else {
       GLP(NewList)(_geom_display_list, GL_COMPILE);
       GLP(NewList)(_geom_display_list, GL_COMPILE);
-    }      
+    }
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
     // Count up the number of vertices used by primitives in the Geom,
     // Count up the number of vertices used by primitives in the Geom,
@@ -2480,6 +2486,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 draw_triangles(const qpGeomTriangles *primitive) {
 draw_triangles(const qpGeomTriangles *primitive) {
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
+  _primitive_batches_tri_pcollector.add_level(1);
   const unsigned char *client_pointer = setup_primitive(primitive);
   const unsigned char *client_pointer = setup_primitive(primitive);
 
 
   _glDrawRangeElements(GL_TRIANGLES, 
   _glDrawRangeElements(GL_TRIANGLES, 
@@ -2505,6 +2512,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     // One long triangle strip, connected by the degenerate vertices
     // One long triangle strip, connected by the degenerate vertices
     // that have already been set up within the primitive.
     // that have already been set up within the primitive.
     _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
     _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
+    _primitive_batches_tristrip_pcollector.add_level(1);
     _glDrawRangeElements(GL_TRIANGLE_STRIP, 
     _glDrawRangeElements(GL_TRIANGLE_STRIP, 
                          primitive->get_min_vertex(),
                          primitive->get_min_vertex(),
                          primitive->get_max_vertex(),
                          primitive->get_max_vertex(),
@@ -2523,6 +2531,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
     nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
              primitive->get_maxs()->get_num_rows() == (int)ends.size());
              primitive->get_maxs()->get_num_rows() == (int)ends.size());
     
     
+    _primitive_batches_tristrip_pcollector.add_level(ends.size());
     unsigned int start = 0;
     unsigned int start = 0;
     for (size_t i = 0; i < ends.size(); i++) {
     for (size_t i = 0; i < ends.size(); i++) {
       _vertices_tristrip_pcollector.add_level(ends[i] - start);
       _vertices_tristrip_pcollector.add_level(ends[i] - start);
@@ -2557,6 +2566,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
   nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
   nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
            primitive->get_maxs()->get_num_rows() == (int)ends.size());
            primitive->get_maxs()->get_num_rows() == (int)ends.size());
 
 
+  _primitive_batches_trifan_pcollector.add_level(ends.size());
   unsigned int start = 0;
   unsigned int start = 0;
   for (size_t i = 0; i < ends.size(); i++) {
   for (size_t i = 0; i < ends.size(); i++) {
     _vertices_trifan_pcollector.add_level(ends[i] - start);
     _vertices_trifan_pcollector.add_level(ends[i] - start);
@@ -2578,6 +2588,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 draw_lines(const qpGeomLines *primitive) {
 draw_lines(const qpGeomLines *primitive) {
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
+  _primitive_batches_other_pcollector.add_level(1);
   const unsigned char *client_pointer = setup_primitive(primitive);
   const unsigned char *client_pointer = setup_primitive(primitive);
 
 
   _glDrawRangeElements(GL_LINES, 
   _glDrawRangeElements(GL_LINES, 
@@ -2607,6 +2618,7 @@ draw_linestrips(const qpGeomLinestrips *primitive) {
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 draw_points(const qpGeomPoints *primitive) {
 draw_points(const qpGeomPoints *primitive) {
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
   _vertices_other_pcollector.add_level(primitive->get_num_vertices());
+  _primitive_batches_other_pcollector.add_level(1);
   const unsigned char *client_pointer = setup_primitive(primitive);
   const unsigned char *client_pointer = setup_primitive(primitive);
 
 
   _glDrawRangeElements(GL_POINTS, 
   _glDrawRangeElements(GL_POINTS, 
@@ -2631,9 +2643,12 @@ end_draw_primitives() {
   if (_geom_display_list != 0) {
   if (_geom_display_list != 0) {
     // If we were building a display list, close it now.
     // If we were building a display list, close it now.
     GLP(EndList)();
     GLP(EndList)();
+    _load_display_list_pcollector.stop();
+
     if (!CLP(compile_and_execute)) {
     if (!CLP(compile_and_execute)) {
       GLP(CallList)(_geom_display_list);
       GLP(CallList)(_geom_display_list);
     }      
     }      
+    _primitive_batches_display_list_pcollector.add_level(1);
   }
   }
   _geom_display_list = 0;
   _geom_display_list = 0;
 
 
@@ -2908,21 +2923,24 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
   
   
   add_to_vertex_buffer_record(gvbc);
   add_to_vertex_buffer_record(gvbc);
   if (gvbc->was_modified()) {
   if (gvbc->was_modified()) {
+    PStatTimer timer(_load_vertex_buffer_pcollector);
+    int num_bytes = gvbc->get_data()->get_data_size_bytes();
     if (GLCAT.is_spam()) {
     if (GLCAT.is_spam()) {
       GLCAT.spam()
       GLCAT.spam()
-        << "copying " << gvbc->get_data()->get_data_size_bytes()
+        << "copying " << num_bytes
         << " bytes into vertex buffer " << gvbc->_index << "\n";
         << " bytes into vertex buffer " << gvbc->_index << "\n";
     }
     }
     if (gvbc->changed_size() || gvbc->changed_usage_hint()) {
     if (gvbc->changed_size() || gvbc->changed_usage_hint()) {
-      _glBufferData(GL_ARRAY_BUFFER, gvbc->get_data()->get_data_size_bytes(),
+      _glBufferData(GL_ARRAY_BUFFER, num_bytes,
                     gvbc->get_data()->get_data(), 
                     gvbc->get_data()->get_data(), 
                     get_usage(gvbc->get_data()->get_usage_hint()));
                     get_usage(gvbc->get_data()->get_usage_hint()));
 
 
     } else {
     } else {
-      _glBufferSubData(GL_ARRAY_BUFFER, 0, gvbc->get_data_size_bytes(),
+      _glBufferSubData(GL_ARRAY_BUFFER, 0, num_bytes,
                        gvbc->get_data()->get_data());
                        gvbc->get_data()->get_data());
     }
     }
-
+    _data_transferred_pcollector.add_level(num_bytes);
+    add_to_total_buffer_record(gvbc);
     gvbc->mark_loaded();
     gvbc->mark_loaded();
   }
   }
 
 
@@ -3042,21 +3060,24 @@ apply_index_buffer(IndexBufferContext *ibc) {
   
   
   add_to_index_buffer_record(gibc);
   add_to_index_buffer_record(gibc);
   if (gibc->was_modified()) {
   if (gibc->was_modified()) {
+    PStatTimer timer(_load_index_buffer_pcollector);
+    int num_bytes = gibc->get_data()->get_data_size_bytes();
     if (GLCAT.is_spam()) {
     if (GLCAT.is_spam()) {
       GLCAT.spam()
       GLCAT.spam()
-        << "copying " << gibc->get_data()->get_data_size_bytes()
+        << "copying " << num_bytes
         << " bytes into index buffer " << gibc->_index << "\n";
         << " bytes into index buffer " << gibc->_index << "\n";
     }
     }
     if (gibc->changed_size() || gibc->changed_usage_hint()) {
     if (gibc->changed_size() || gibc->changed_usage_hint()) {
-      _glBufferData(GL_ELEMENT_ARRAY_BUFFER, gibc->get_data()->get_data_size_bytes(),
+      _glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_bytes,
                     gibc->get_data()->get_data(), 
                     gibc->get_data()->get_data(), 
                     get_usage(gibc->get_data()->get_usage_hint()));
                     get_usage(gibc->get_data()->get_usage_hint()));
 
 
     } else {
     } else {
-      _glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, gibc->get_data_size_bytes(),
+      _glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, num_bytes,
                        gibc->get_data()->get_data());
                        gibc->get_data()->get_data());
     }
     }
-
+    _data_transferred_pcollector.add_level(num_bytes);
+    add_to_total_buffer_record(gibc);
     gibc->mark_loaded();
     gibc->mark_loaded();
   }
   }
 
 
@@ -4646,6 +4667,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
     // Unsupported target (e.g. 3-d texturing on GL 1.1).
     // Unsupported target (e.g. 3-d texturing on GL 1.1).
     return false;
     return false;
   }
   }
+  PStatTimer timer(_load_texture_pcollector);
 
 
   if (uses_mipmaps) {
   if (uses_mipmaps) {
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -4660,6 +4682,9 @@ upload_texture_image(CLP(TextureContext) *gtc,
         // We only need to build the mipmaps by hand if the GL
         // We only need to build the mipmaps by hand if the GL
         // doesn't support generating them automatically.
         // doesn't support generating them automatically.
         bool success = true;
         bool success = true;
+#ifdef DO_PSTATS
+        _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type) * 4 / 3);
+#endif
         switch (target) {
         switch (target) {
         case GL_TEXTURE_1D:
         case GL_TEXTURE_1D:
           GLUP(Build1DMipmaps)(target, internal_format, width,
           GLUP(Build1DMipmaps)(target, internal_format, width,
@@ -4698,6 +4723,9 @@ upload_texture_image(CLP(TextureContext) *gtc,
       gtc->_height != height ||
       gtc->_height != height ||
       gtc->_depth != depth) {
       gtc->_depth != depth) {
     // We need to reload a new image.
     // We need to reload a new image.
+#ifdef DO_PSTATS
+    _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type));
+#endif
     switch (target) {
     switch (target) {
     case GL_TEXTURE_1D:
     case GL_TEXTURE_1D:
       GLP(TexImage1D)(target, 0, internal_format,
       GLP(TexImage1D)(target, 0, internal_format,
@@ -5033,6 +5061,75 @@ get_internal_image_format(Texture::Format format) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::get_external_texture_bytes
+//       Access: Protected, Static
+//  Description: Computes the number of bytes that should be in the
+//               "external", or local, texture buffer before
+//               transferring to OpenGL.  This is just used for
+//               sending data to PStats.
+////////////////////////////////////////////////////////////////////
+int CLP(GraphicsStateGuardian)::
+get_external_texture_bytes(int width, int height, int depth,
+                           GLint external_format, GLenum component_type) {
+  int num_components;
+  switch (external_format) {
+  case GL_COLOR_INDEX:
+  case GL_STENCIL_INDEX:
+  case GL_DEPTH_COMPONENT:
+  case GL_RED:
+  case GL_GREEN:
+  case GL_BLUE:
+  case GL_ALPHA:
+  case GL_LUMINANCE:
+    num_components = 1;
+    break;
+
+  case GL_LUMINANCE_ALPHA:
+    num_components = 2;
+    break;
+
+  case GL_BGR: 
+  case GL_RGB:
+    num_components = 3;
+    break;
+
+  case GL_BGRA: 
+  case GL_RGBA:
+    num_components = 4;
+    break;
+    
+  default:
+    GLCAT.error()
+      << "Unexpected external_format in get_external_texture_bytes(): "
+      << hex << external_format << dec << "\n";
+    num_components = 3;
+  }
+
+  int component_width;
+  switch (component_type) {
+  case GL_UNSIGNED_BYTE:
+    component_width = 1;
+    break;
+
+  case GL_UNSIGNED_SHORT:
+    component_width = 2;
+    break;
+
+  case GL_FLOAT:
+    component_width = 4;
+    break;
+
+  default:
+    GLCAT.error()
+      << "Unexpected component_type in get_external_texture_bytes(): "
+      << hex << component_type << dec << "\n";
+    component_width = 1;
+  }
+
+  return width * height * depth * num_components * component_width;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::get_texture_apply_mode_type
 //     Function: GLGraphicsStateGuardian::get_texture_apply_mode_type
 //       Access: Protected, Static
 //       Access: Protected, Static
@@ -6322,11 +6419,17 @@ build_phony_mipmap_level(int level, int x_size, int y_size) {
   } else {
   } else {
     GLenum internal_format = get_internal_image_format(tex->get_format());
     GLenum internal_format = get_internal_image_format(tex->get_format());
     GLenum external_format = get_external_image_format(tex->get_format());
     GLenum external_format = get_external_image_format(tex->get_format());
-    GLenum type = get_component_type(tex->get_component_type());
+    GLenum component_type = get_component_type(tex->get_component_type());
     
     
+#ifdef DO_PSTATS
+    int num_bytes = 
+      get_external_texture_bytes(tex->get_x_size(), tex->get_y_size(), 1,
+                                 external_format, component_type);
+    _data_transferred_pcollector.add_level(num_bytes);
+#endif
     GLP(TexImage2D)(GL_TEXTURE_2D, level, internal_format,
     GLP(TexImage2D)(GL_TEXTURE_2D, level, internal_format,
                     tex->get_x_size(), tex->get_y_size(), 0,
                     tex->get_x_size(), tex->get_y_size(), 0,
-                    external_format, type, tex->get_ram_image());
+                    external_format, component_type, tex->get_ram_image());
   }
   }
 }
 }
 
 

+ 5 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -251,6 +251,9 @@ protected:
   static GLenum get_component_type(Texture::ComponentType component_type);
   static GLenum get_component_type(Texture::ComponentType component_type);
   GLint get_external_image_format(Texture::Format format) const;
   GLint get_external_image_format(Texture::Format format) const;
   static GLint get_internal_image_format(Texture::Format format);
   static GLint get_internal_image_format(Texture::Format format);
+  static int get_external_texture_bytes(int width, int height, int depth,
+                                        GLint external_format, 
+                                        GLenum component_type);
   static GLint get_texture_apply_mode_type(TextureStage::Mode am);
   static GLint get_texture_apply_mode_type(TextureStage::Mode am);
   static GLint get_texture_combine_type(TextureStage::CombineMode cm);
   static GLint get_texture_combine_type(TextureStage::CombineMode cm);
   static GLint get_texture_src_type(TextureStage::CombineSource cs);
   static GLint get_texture_src_type(TextureStage::CombineSource cs);
@@ -392,6 +395,8 @@ public:
   typedef pvector<GLuint> DeletedDisplayLists;
   typedef pvector<GLuint> DeletedDisplayLists;
   DeletedDisplayLists _deleted_display_lists;
   DeletedDisplayLists _deleted_display_lists;
 
 
+  static PStatCollector _load_display_list_pcollector;
+  static PStatCollector _primitive_batches_display_list_pcollector;
   static PStatCollector _vertices_display_list_pcollector;
   static PStatCollector _vertices_display_list_pcollector;
 
 
 public:
 public:

+ 2 - 9
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -28,7 +28,6 @@
 
 
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
 PStatCollector PreparedGraphicsObjects::_total_texusage_pcollector("Texture usage");
 PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer size");
 PStatCollector PreparedGraphicsObjects::_total_buffers_pcollector("Vertex buffer size");
-PStatCollector PreparedGraphicsObjects::_total_buffer_count_pcollector("Vertex buffer count");
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PreparedGraphicsObjects::Constructor
 //     Function: PreparedGraphicsObjects::Constructor
@@ -83,7 +82,7 @@ PreparedGraphicsObjects::
        vbci != _prepared_vertex_buffers.end();
        vbci != _prepared_vertex_buffers.end();
        ++vbci) {
        ++vbci) {
     VertexBufferContext *vbc = (*vbci);
     VertexBufferContext *vbc = (*vbci);
-    _total_texusage_pcollector.sub_level(vbc->get_data_size_bytes());
+    _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
     vbc->_data->clear_prepared(this);
     vbc->_data->clear_prepared(this);
   }
   }
 
 
@@ -96,7 +95,7 @@ PreparedGraphicsObjects::
        ibci != _prepared_index_buffers.end();
        ibci != _prepared_index_buffers.end();
        ++ibci) {
        ++ibci) {
     IndexBufferContext *ibc = (*ibci);
     IndexBufferContext *ibc = (*ibci);
-    _total_texusage_pcollector.sub_level(ibc->get_data_size_bytes());
+    _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
     ibc->_data->clear_prepared(this);
     ibc->_data->clear_prepared(this);
   }
   }
 
 
@@ -450,7 +449,6 @@ release_vertex_buffer(VertexBufferContext *vbc) {
 
 
   vbc->_data->clear_prepared(this);
   vbc->_data->clear_prepared(this);
   _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
   _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
   // 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
   // the Data itself might destruct at any time after it has been
@@ -484,7 +482,6 @@ release_all_vertex_buffers() {
     VertexBufferContext *vbc = (*vbci);
     VertexBufferContext *vbc = (*vbci);
     vbc->_data->clear_prepared(this);
     vbc->_data->clear_prepared(this);
     _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
     _total_buffers_pcollector.sub_level(vbc->get_data_size_bytes());
-    _total_buffer_count_pcollector.sub_level(1);
     vbc->_data = (qpGeomVertexArrayData *)NULL;
     vbc->_data = (qpGeomVertexArrayData *)NULL;
 
 
     _released_vertex_buffers.insert(vbc);
     _released_vertex_buffers.insert(vbc);
@@ -535,7 +532,6 @@ prepare_vertex_buffer_now(qpGeomVertexArrayData *data, GraphicsStateGuardianBase
     // GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to
     // GraphicsStateGuardian::add_to_vertex_buffer_record(); we don't need to
     // count it again here.
     // count it again here.
     //_total_buffers_pcollector.add_level(vbc->get_data_size_bytes());
     //_total_buffers_pcollector.add_level(vbc->get_data_size_bytes());
-    _total_buffer_count_pcollector.add_level(1);
   }
   }
 
 
   return vbc;
   return vbc;
@@ -600,7 +596,6 @@ release_index_buffer(IndexBufferContext *ibc) {
 
 
   ibc->_data->clear_prepared(this);
   ibc->_data->clear_prepared(this);
   _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
   _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
   // 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
   // the Data itself might destruct at any time after it has been
@@ -634,7 +629,6 @@ release_all_index_buffers() {
     IndexBufferContext *ibc = (*ibci);
     IndexBufferContext *ibc = (*ibci);
     ibc->_data->clear_prepared(this);
     ibc->_data->clear_prepared(this);
     _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
     _total_buffers_pcollector.sub_level(ibc->get_data_size_bytes());
-    _total_buffer_count_pcollector.sub_level(1);
     ibc->_data = (qpGeomPrimitive *)NULL;
     ibc->_data = (qpGeomPrimitive *)NULL;
 
 
     _released_index_buffers.insert(ibc);
     _released_index_buffers.insert(ibc);
@@ -685,7 +679,6 @@ prepare_index_buffer_now(qpGeomPrimitive *data, GraphicsStateGuardianBase *gsg)
     // GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to
     // GraphicsStateGuardian::add_to_index_buffer_record(); we don't need to
     // count it again here.
     // count it again here.
     //_total_buffers_pcollector.add_level(ibc->get_data_size_bytes());
     //_total_buffers_pcollector.add_level(ibc->get_data_size_bytes());
-    _total_buffer_count_pcollector.add_level(1);
   }
   }
 
 
   return ibc;
   return ibc;

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

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

+ 4 - 0
panda/src/gobj/qpgeomCacheEntry.cxx

@@ -54,6 +54,8 @@ record() {
 
 
   insert_before(cache_mgr->_list);
   insert_before(cache_mgr->_list);
   cache_mgr->_total_size += _result_size;
   cache_mgr->_total_size += _result_size;
+  cache_mgr->_geom_cache_size_pcollector.set_level(cache_mgr->_total_size);
+  cache_mgr->_geom_cache_record_pcollector.add_level(1);
 
 
   // Increment our own reference count while we're in the queue, just
   // Increment our own reference count while we're in the queue, just
   // so we don't have to play games with it later--this is inner-loop
   // so we don't have to play games with it later--this is inner-loop
@@ -91,6 +93,8 @@ erase() {
 
 
   remove_from_list();
   remove_from_list();
   cache_mgr->_total_size -= _result_size;
   cache_mgr->_total_size -= _result_size;
+  cache_mgr->_geom_cache_size_pcollector.set_level(cache_mgr->_total_size);
+  cache_mgr->_geom_cache_erase_pcollector.add_level(1);
 
 
   return this;
   return this;
 }
 }

+ 7 - 0
panda/src/gobj/qpgeomCacheManager.cxx

@@ -22,6 +22,11 @@
 
 
 qpGeomCacheManager *qpGeomCacheManager::_global_ptr = NULL;
 qpGeomCacheManager *qpGeomCacheManager::_global_ptr = NULL;
 
 
+PStatCollector qpGeomCacheManager::_geom_cache_size_pcollector("Geom cache size");
+PStatCollector qpGeomCacheManager::_geom_cache_record_pcollector("Geom cache operations:record");
+PStatCollector qpGeomCacheManager::_geom_cache_erase_pcollector("Geom cache operations:erase");
+PStatCollector qpGeomCacheManager::_geom_cache_evict_pcollector("Geom cache operations:evict");
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomCacheManager::Constructor
 //     Function: qpGeomCacheManager::Constructor
 //       Access: Protected
 //       Access: Protected
@@ -88,5 +93,7 @@ evict_old_entries() {
 
 
     _total_size -= entry->_result_size;
     _total_size -= entry->_result_size;
     entry->remove_from_list();
     entry->remove_from_list();
+    _geom_cache_evict_pcollector.add_level(1);
   }
   }
+  _geom_cache_size_pcollector.set_level(_total_size);
 }
 }

+ 8 - 0
panda/src/gobj/qpgeomCacheManager.h

@@ -22,6 +22,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "config_gobj.h"
 #include "config_gobj.h"
 #include "pmutex.h"
 #include "pmutex.h"
+#include "pStatCollector.h"
 
 
 class qpGeomCacheEntry;
 class qpGeomCacheEntry;
 
 
@@ -83,6 +84,13 @@ private:
   qpGeomCacheEntry *_list;
   qpGeomCacheEntry *_list;
 
 
   static qpGeomCacheManager *_global_ptr;
   static qpGeomCacheManager *_global_ptr;
+
+public:
+  static PStatCollector _geom_cache_size_pcollector;
+  static PStatCollector _geom_cache_record_pcollector;
+  static PStatCollector _geom_cache_erase_pcollector;
+  static PStatCollector _geom_cache_evict_pcollector;
+
   friend class qpGeomCacheEntry;
   friend class qpGeomCacheEntry;
 };
 };
 
 

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

@@ -141,6 +141,11 @@ static TimeCollectorProperties time_properties[] = {
   { 1, "Draw:Flip:Begin",                  { 0.3, 0.3, 0.9 } },
   { 1, "Draw:Flip:Begin",                  { 0.3, 0.3, 0.9 } },
   { 1, "Draw:Flip:End",                    { 0.9, 0.3, 0.6 } },
   { 1, "Draw:Flip:End",                    { 0.9, 0.3, 0.6 } },
   { 1, "Draw:Bins",                        { 0.3, 0.6, 0.0 } },
   { 1, "Draw:Bins",                        { 0.3, 0.6, 0.0 } },
+  { 1, "Draw:Transfer data",               { 0.8, 0.0, 0.6 } },
+  { 1, "Draw:Transfer data:Vertex buffer", { 0.0, 0.1, 0.9 } },
+  { 1, "Draw:Transfer data:Index buffer",  { 0.1, 0.9, 0.0 } },
+  { 1, "Draw:Transfer data:Texture",       { 0.9, 0.0, 0.1 } },
+  { 1, "Draw:Transfer data:Display lists", { 0.5, 0.0, 0.9 } },
   { 0, "Draw:Primitive",                   { 0.0, 0.0, 0.5 } },
   { 0, "Draw:Primitive",                   { 0.0, 0.0, 0.5 } },
   { 0, NULL }
   { 0, NULL }
 };
 };
@@ -161,9 +166,21 @@ static LevelCollectorProperties level_properties[] = {
   { 1, "Vertex buffer size",               { 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 vertex", { 1.0, 0.0, 0.5 } },
   { 1, "Vertex buffer size:Active index" , { 0.5, 0.6, 1.0 } },
   { 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, "Vertex buffer switch",             { 0.0, 0.6, 0.8 },  "", 500 },
+  { 1, "Vertex buffer switch:Vertex",      { 0.8, 0.0, 0.6 } },
+  { 1, "Vertex buffer switch:Index",       { 0.8, 0.6, 0.3 } },
+  { 1, "Geom cache size",                  { 1.0, 0.8, 0.6 },  "MB", 12, 1048576 },
+  { 1, "Geom cache operations",            { 1.0, 0.8, 0.6 },  "", 500 },
+  { 1, "Geom cache operations:record",     { 0.2, 0.4, 0.8 } },
+  { 1, "Geom cache operations:erase",      { 0.4, 0.8, 0.2 } },
+  { 1, "Geom cache operations:evict",      { 0.8, 0.2, 0.4 } },
+  { 1, "Data transferred",                 { 0.0, 0.2, 0.4 },  "MB", 12, 1048576 },
+  { 1, "Primitive batches",                { 0.2, 0.5, 0.9 },  "", 500 },
+  { 1, "Primitive batches:Other",          { 0.2, 0.2, 0.2 } },
+  { 1, "Primitive batches:Triangles",      { 0.8, 0.8, 0.8 } },
+  { 1, "Primitive batches:Triangle fans",  { 0.8, 0.5, 0.2 } },
+  { 1, "Primitive batches:Triangle strips",{ 0.2, 0.5, 0.8 } },
+  { 1, "Primitive batches:Display lists",  { 0.8, 0.5, 1.0 } },
   { 1, "Vertices",                         { 0.5, 0.2, 0.0 },  "K", 10, 1000 },
   { 1, "Vertices",                         { 0.5, 0.2, 0.0 },  "K", 10, 1000 },
   { 1, "Vertices:Other",                   { 0.2, 0.2, 0.2 } },
   { 1, "Vertices:Other",                   { 0.2, 0.2, 0.2 } },
   { 1, "Vertices:Triangles",               { 0.8, 0.8, 0.8 } },
   { 1, "Vertices:Triangles",               { 0.8, 0.8, 0.8 } },