From b2c9c49805e37ea2b3c681441a0663a70fff3495 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 16 Jul 2002 01:10:53 +0000 Subject: [PATCH] pstats TransformState, RenderState --- panda/src/display/config_display.cxx | 7 +- panda/src/display/config_display.h | 5 +- panda/src/display/graphicsStateGuardian.cxx | 67 ++++++++------- panda/src/display/graphicsStateGuardian.h | 4 + panda/src/pgraph/renderState.cxx | 90 ++++++++++++++++++++- panda/src/pgraph/renderState.h | 3 +- panda/src/pgraph/transformState.cxx | 90 ++++++++++++++++++++- panda/src/pgraph/transformState.h | 3 +- panda/src/pstatclient/pStatProperties.cxx | 4 + 9 files changed, 233 insertions(+), 40 deletions(-) diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index fb441bf308..3b4974f287 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -68,9 +68,10 @@ const bool cull_sorting = config_display.GetBool("cull-sorting", true); // (primarily useful for debugging). const bool view_frustum_cull = config_display.GetBool("view-frustum-cull", true); -const float gsg_clear_r = config_display.GetFloat("gsg-clear-r", 0.0); -const float gsg_clear_g = config_display.GetFloat("gsg-clear-g", 0.0); -const float gsg_clear_b = config_display.GetFloat("gsg-clear-b", 0.0); +// Set this true to show the number of unused states in the pstats +// graph for TransformState and RenderState counts. This adds a bit +// of per-frame overhead to count these things up. +const bool pstats_unused_states = config_display.GetBool("pstats-unused-states", false); Config::ConfigTable::Symbol::iterator pipe_modules_begin(void) { diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 377e66d87c..4b1a557067 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -38,10 +38,7 @@ extern const bool pipe_spec_is_remote; extern const bool compare_state_by_pointer; extern const bool cull_sorting; extern const bool view_frustum_cull; - -extern const float gsg_clear_r; -extern const float gsg_clear_g; -extern const float gsg_clear_b; +extern const bool pstats_unused_states; extern Config::ConfigTable::Symbol::iterator pipe_modules_begin(void); extern Config::ConfigTable::Symbol::iterator pipe_modules_end(void); diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index cf294556a1..62db722673 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -66,6 +66,10 @@ PStatCollector GraphicsStateGuardian::_frustum_cull_transforms_pcollector("Cull PStatCollector GraphicsStateGuardian::_set_state_pcollector("Draw:Set state"); PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive"); +PStatCollector GraphicsStateGuardian::_transform_states_pcollector("TransformStates"); +PStatCollector GraphicsStateGuardian::_transform_states_unused_pcollector("TransformStates:Unused"); +PStatCollector GraphicsStateGuardian::_render_states_pcollector("RenderStates"); +PStatCollector GraphicsStateGuardian::_render_states_unused_pcollector("RenderStates:Unused"); #endif @@ -134,10 +138,10 @@ reset() { _transform = TransformState::make_identity(); _buffer_mask = 0; - _color_clear_value.set(gsg_clear_r, gsg_clear_g, gsg_clear_b, 0.0); - _depth_clear_value = 1.0; - _stencil_clear_value = 0.0; - _accum_clear_value.set(0.0, 0.0, 0.0, 0.0); + _color_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); + _depth_clear_value = 1.0f; + _stencil_clear_value = 0.0f; + _accum_clear_value.set(0.0f, 0.0f, 0.0f, 0.0f); _clear_buffer_type = RenderBuffer::T_back | RenderBuffer::T_depth; _normals_enabled = false; @@ -1357,29 +1361,38 @@ close_gsg() { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: init_frame_pstats() { - _current_textures.clear(); - _current_geoms.clear(); - _current_geom_nodes.clear(); - _active_texusage_pcollector.clear_level(); - _active_geom_pcollector.clear_level(); - _active_geom_node_pcollector.clear_level(); - - // Also clear out our other counters while we're here. - _vertices_tristrip_pcollector.clear_level(); - _vertices_trifan_pcollector.clear_level(); - _vertices_tri_pcollector.clear_level(); - _vertices_other_pcollector.clear_level(); - - _state_changes_pcollector.clear_level(); - _transform_state_pcollector.clear_level(); - _texture_state_pcollector.clear_level(); - - _nodes_pcollector.clear_level(); - _geom_nodes_pcollector.clear_level(); - - // Not to mention the view-frustum-cull counters. - _frustum_cull_volumes_pcollector.clear_level(); - _frustum_cull_transforms_pcollector.clear_level(); + if (PStatClient::is_connected()) { + _current_textures.clear(); + _current_geoms.clear(); + _current_geom_nodes.clear(); + _active_texusage_pcollector.clear_level(); + _active_geom_pcollector.clear_level(); + _active_geom_node_pcollector.clear_level(); + + // Also clear out our other counters while we're here. + _vertices_tristrip_pcollector.clear_level(); + _vertices_trifan_pcollector.clear_level(); + _vertices_tri_pcollector.clear_level(); + _vertices_other_pcollector.clear_level(); + + _state_changes_pcollector.clear_level(); + _transform_state_pcollector.clear_level(); + _texture_state_pcollector.clear_level(); + + _nodes_pcollector.clear_level(); + _geom_nodes_pcollector.clear_level(); + + // Not to mention the view-frustum-cull counters. + _frustum_cull_volumes_pcollector.clear_level(); + _frustum_cull_transforms_pcollector.clear_level(); + + _transform_states_pcollector.set_level(TransformState::get_num_states()); + _render_states_pcollector.set_level(RenderState::get_num_states()); + if (pstats_unused_states) { + _transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states()); + _render_states_unused_pcollector.set_level(RenderState::get_num_unused_states()); + } + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 5698b2b077..c809524648 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -284,6 +284,10 @@ public: static PStatCollector _frustum_cull_transforms_pcollector; static PStatCollector _set_state_pcollector; static PStatCollector _draw_primitive_pcollector; + static PStatCollector _transform_states_pcollector; + static PStatCollector _transform_states_unused_pcollector; + static PStatCollector _render_states_pcollector; + static PStatCollector _render_states_unused_pcollector; private: class LightInfo { diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index f85e961f3b..2d4ac0ffb3 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -622,20 +622,106 @@ get_max_priority() { } //////////////////////////////////////////////////////////////////// -// Function: RenderState::get_cache_size +// Function: RenderState::get_num_states // Access: Published, Static // Description: Returns the total number of unique RenderState // objects allocated in the world. This will go up and // down during normal operations. //////////////////////////////////////////////////////////////////// int RenderState:: -get_cache_size() { +get_num_states() { if (_states == (States *)NULL) { return 0; } return _states->size(); } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::get_num_unused_states +// Access: Published, Static +// Description: Returns the total number of RenderState objects that +// have been allocated but have no references outside of +// the internal RenderState map. +//////////////////////////////////////////////////////////////////// +int RenderState:: +get_num_unused_states() { + if (_states == (States *)NULL) { + return 0; + } + + int num_unused = 0; + + // First, we need to count the number of times each RenderState + // object is recorded in the cache. + typedef pmap StateCount; + StateCount state_count; + + States::iterator si; + for (si = _states->begin(); si != _states->end(); ++si) { + const RenderState *state = (*si); + + CompositionCache::const_iterator ci; + for (ci = state->_composition_cache.begin(); + ci != state->_composition_cache.end(); + ++ci) { + const RenderState *result = (*ci).second._result; + if (result != (const RenderState *)NULL) { + // Here's a RenderState that's recorded in the cache. + // Count it. + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + // If the above insert operation fails, then it's already in + // the cache; increment its value. + (*(ir.first)).second++; + } + } + } + for (ci = state->_invert_composition_cache.begin(); + ci != state->_invert_composition_cache.end(); + ++ci) { + const RenderState *result = (*ci).second._result; + if (result != (const RenderState *)NULL) { + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + (*(ir.first)).second++; + } + } + } + + // Finally, check the self_compose field, which might be reference + // counted too. + if (state->_self_compose != (const RenderState *)NULL && + state->_self_compose != state) { + const RenderState *result = state->_self_compose; + if (result != (const RenderState *)NULL) { + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + (*(ir.first)).second++; + } + } + } + + } + + // Now that we have the appearance count of each RenderState + // object, we can tell which ones are unreferenced outside of the + // RenderState cache, by comparing these to the reference counts. + StateCount::iterator sci; + for (sci = state_count.begin(); sci != state_count.end(); ++sci) { + const RenderState *state = (*sci).first; + int count = (*sci).second; + nassertr(count <= state->get_ref_count(), num_unused); + if (count == state->get_ref_count()) { + num_unused++; + } + } + + return num_unused; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::clear_cache // Access: Published, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 888188f8c9..017b4272a1 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -95,7 +95,8 @@ PUBLISHED: static int get_max_priority(); - static int get_cache_size(); + static int get_num_states(); + static int get_num_unused_states(); static int clear_cache(); public: diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 44c1eb6b74..d579349e48 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -653,20 +653,106 @@ write(ostream &out, int indent_level) const { } //////////////////////////////////////////////////////////////////// -// Function: TransformState::get_cache_size +// Function: TransformState::get_num_states // Access: Published, Static // Description: Returns the total number of unique TransformState // objects allocated in the world. This will go up and // down during normal operations. //////////////////////////////////////////////////////////////////// int TransformState:: -get_cache_size() { +get_num_states() { if (_states == (States *)NULL) { return 0; } return _states->size(); } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::get_num_unused_states +// Access: Published, Static +// Description: Returns the total number of TransformState objects +// that have been allocated but have no references +// outside of the internal TransformState map. +//////////////////////////////////////////////////////////////////// +int TransformState:: +get_num_unused_states() { + if (_states == (States *)NULL) { + return 0; + } + + int num_unused = 0; + + // First, we need to count the number of times each TransformState + // object is recorded in the cache. + typedef pmap StateCount; + StateCount state_count; + + States::iterator si; + for (si = _states->begin(); si != _states->end(); ++si) { + const TransformState *state = (*si); + + CompositionCache::const_iterator ci; + for (ci = state->_composition_cache.begin(); + ci != state->_composition_cache.end(); + ++ci) { + const TransformState *result = (*ci).second._result; + if (result != (const TransformState *)NULL) { + // Here's a TransformState that's recorded in the cache. + // Count it. + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + // If the above insert operation fails, then it's already in + // the cache; increment its value. + (*(ir.first)).second++; + } + } + } + for (ci = state->_invert_composition_cache.begin(); + ci != state->_invert_composition_cache.end(); + ++ci) { + const TransformState *result = (*ci).second._result; + if (result != (const TransformState *)NULL) { + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + (*(ir.first)).second++; + } + } + } + + // Finally, check the self_compose field, which might be reference + // counted too. + if (state->_self_compose != (const TransformState *)NULL && + state->_self_compose != state) { + const TransformState *result = state->_self_compose; + if (result != (const TransformState *)NULL) { + pair ir = + state_count.insert(StateCount::value_type(result, 1)); + if (!ir.second) { + (*(ir.first)).second++; + } + } + } + + } + + // Now that we have the appearance count of each TransformState + // object, we can tell which ones are unreferenced outside of the + // TransformState cache, by comparing these to the reference counts. + StateCount::iterator sci; + for (sci = state_count.begin(); sci != state_count.end(); ++sci) { + const TransformState *state = (*sci).first; + int count = (*sci).second; + nassertr(count <= state->get_ref_count(), num_unused); + if (count == state->get_ref_count()) { + num_unused++; + } + } + + return num_unused; +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::clear_cache // Access: Published, Static diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 388a2bd444..25dff071d8 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -115,7 +115,8 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level) const; - static int get_cache_size(); + static int get_num_states(); + static int get_num_unused_states(); static int clear_cache(); private: diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 83a10c4c6e..1e96107f99 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -169,6 +169,10 @@ static LevelCollectorProperties level_properties[] = { { 1, "Memory usage", { 0.5, 1.0, 0.5 }, "MB", 64, 1048576 }, { 1, "Memory usage:C++", { 0.2, 0.2, 1.0 } }, { 1, "Memory usage:Interpreter", { 0.8, 0.2, 0.5 } }, + { 1, "TransformStates", { 1.0, 0.5, 0.5 }, "", 5000 }, + { 1, "TransformStates:Unused", { 0.2, 0.2, 0.2 } }, + { 1, "RenderStates", { 0.5, 0.5, 1.0 }, "", 1000 }, + { 1, "RenderStates:Unused", { 0.2, 0.2, 0.2 } }, { 0, NULL } };