From 5173168621e6e8d973ccf8d29b752f40d062f287 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 29 Mar 2006 23:37:46 +0000 Subject: [PATCH] more pstats options with z-buffer --- panda/src/cull/config_cull.cxx | 6 +++ panda/src/cull/config_cull.h | 2 + panda/src/cull/cullBinHierarchicalZBuffer.I | 15 ++++++- panda/src/cull/cullBinHierarchicalZBuffer.cxx | 39 ++++++++++--------- panda/src/cull/cullBinHierarchicalZBuffer.h | 7 +++- panda/src/display/graphicsEngine.cxx | 3 +- panda/src/pgraph/cullTraverser.cxx | 1 + panda/src/pgraph/cullTraverser.h | 1 + panda/src/pstatclient/pStatProperties.cxx | 5 ++- 9 files changed, 56 insertions(+), 23 deletions(-) diff --git a/panda/src/cull/config_cull.cxx b/panda/src/cull/config_cull.cxx index c853818c1d..a9f1700951 100644 --- a/panda/src/cull/config_cull.cxx +++ b/panda/src/cull/config_cull.cxx @@ -47,6 +47,12 @@ ConfigVariableDouble octree_multiassign_ratio "order to be assigned to the node itself. If the object is smaller " "than this, it will be multiply assigned to the node's children.")); +ConfigVariableBool show_octree +("show-octree", false, + PRC_DESC("When true, visualizes the octree created for the hierarchical " + "Z-buffer algorithm, by drawing wireframe cubes around each " + "nonempty octree cell.")); + //////////////////////////////////////////////////////////////////// // Function: init_libcull // Description: Initializes the library. This must be called at diff --git a/panda/src/cull/config_cull.h b/panda/src/cull/config_cull.h index 12922cfd0c..cade417ba0 100644 --- a/panda/src/cull/config_cull.h +++ b/panda/src/cull/config_cull.h @@ -24,6 +24,7 @@ #include "dconfig.h" #include "configVariableInt.h" #include "configVariableDouble.h" +#include "configVariableBool.h" class DSearchPath; @@ -32,6 +33,7 @@ NotifyCategoryDecl(cull, EXPCL_PANDA, EXPTP_PANDA); extern ConfigVariableInt max_objects_per_octree_node; extern ConfigVariableDouble octree_multiassign_ratio; +extern ConfigVariableBool show_octree; extern EXPCL_PANDA void init_libcull(); diff --git a/panda/src/cull/cullBinHierarchicalZBuffer.I b/panda/src/cull/cullBinHierarchicalZBuffer.I index 32f6d3fc5c..6317c58425 100644 --- a/panda/src/cull/cullBinHierarchicalZBuffer.I +++ b/panda/src/cull/cullBinHierarchicalZBuffer.I @@ -59,7 +59,8 @@ operator = (const CullBinHierarchicalZBuffer::ObjectData ©) { //////////////////////////////////////////////////////////////////// INLINE CullBinHierarchicalZBuffer:: CullBinHierarchicalZBuffer(const string &name, GraphicsStateGuardianBase *gsg) : - CullBin(name, gsg) + CullBin(name, gsg), + _draw_occlusion_pcollector(_draw_this_pcollector, "Occlusion") { nassertv(_gsg->get_supports_occlusion_query()); } @@ -75,6 +76,17 @@ initial_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) { _objects.push_back(object_data); } +//////////////////////////////////////////////////////////////////// +// Function: CullBinHierarchicalZBuffer::OctreeNode::get_total_num_objects +// Access: Public +// Description: Returns the total number of objects in this node and +// all nested nodes. +//////////////////////////////////////////////////////////////////// +INLINE int CullBinHierarchicalZBuffer::OctreeNode:: +get_total_num_objects() const { + return _total_num_objects; +} + //////////////////////////////////////////////////////////////////// // Function: CullBinHierarchicalZBuffer::OctreeNode::reassign // Access: Public @@ -84,6 +96,7 @@ initial_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) { //////////////////////////////////////////////////////////////////// INLINE void CullBinHierarchicalZBuffer::OctreeNode:: reassign(const CullBinHierarchicalZBuffer::ObjectData &object_data) { + ++_total_num_objects; if (object_data._bounds->get_radius() / _half_side >= octree_multiassign_ratio) { // The object is large enough to keep in this node. //cerr << " reassigning.\n"; diff --git a/panda/src/cull/cullBinHierarchicalZBuffer.cxx b/panda/src/cull/cullBinHierarchicalZBuffer.cxx index 48a93cbeed..93698e25fe 100644 --- a/panda/src/cull/cullBinHierarchicalZBuffer.cxx +++ b/panda/src/cull/cullBinHierarchicalZBuffer.cxx @@ -32,6 +32,7 @@ #include "thread.h" PStatCollector CullBinHierarchicalZBuffer::_wait_occlusion_pcollector("Wait:Occlusion test"); +PStatCollector CullBinHierarchicalZBuffer::_geoms_occluded_pcollector("Geoms:Occluded"); PT(Geom) CullBinHierarchicalZBuffer::_octree_solid_test; PT(Geom) CullBinHierarchicalZBuffer::_octree_wireframe_viz; @@ -160,8 +161,13 @@ draw() { // The octree cell is at least partially visible. Draw it, and // continue recursion. pending._octree_node->draw(*this); + if (show_octree) { + pending._octree_node->draw_wireframe(*this); + } } else { - pending._octree_node->draw_wireframe(*this); + // The octree cell is completely occluded. Don't draw any of + // it, and don't recurse into it. + _geoms_occluded_pcollector.add_level(pending._octree_node->get_total_num_objects()); } _pending_nodes.pop_front(); } @@ -175,6 +181,7 @@ draw() { //////////////////////////////////////////////////////////////////// CullBinHierarchicalZBuffer::OctreeNode:: OctreeNode() { + _total_num_objects = 0; for (int i = 0; i < 8; ++i) { _corners[i] = (OctreeNode *)NULL; } @@ -190,6 +197,7 @@ OctreeNode(float mid_x, float mid_y, float mid_z, float half_side) : _mid(mid_x, mid_y, mid_z), _half_side(half_side) { + _total_num_objects = 0; for (int i = 0; i < 8; ++i) { _corners[i] = (OctreeNode *)NULL; } @@ -254,10 +262,9 @@ make_initial_bounds() { //////////////////////////////////////////////////////////////////// void CullBinHierarchicalZBuffer::OctreeNode:: group_objects() { - //cerr << "group_objects, " << _objects.size() << " objects.\n"; if ((int)_objects.size() <= max_objects_per_octree_node) { // No need to do any more subdividing. - //cerr << " small enough.\n"; + _total_num_objects += (int)_objects.size(); return; } @@ -268,7 +275,6 @@ group_objects() { Objects::const_iterator oi; for (oi = old_objects.begin(); oi != old_objects.end(); ++oi) { - //cerr << " object " << (oi - old_objects.begin()) << "\n"; const ObjectData &object_data = (*oi); const LPoint3f &c = object_data._bounds->get_center(); float r = object_data._bounds->get_radius(); @@ -354,7 +360,7 @@ group_objects() { // occlusion query object representing this test. //////////////////////////////////////////////////////////////////// PT(OcclusionQueryContext) CullBinHierarchicalZBuffer::OctreeNode:: -occlusion_test(GraphicsStateGuardianBase *gsg) { +occlusion_test(CullBinHierarchicalZBuffer &bin) { // Draw the bounding volume for visualization. This is // complicated because we're doing this at such a low level, here // in the middle of the draw task--we've already completed the @@ -364,21 +370,22 @@ occlusion_test(GraphicsStateGuardianBase *gsg) { CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale (_mid, LVecBase3f(0.0f, 0.0f, 0.0f), LVecBase3f(_half_side, _half_side, _half_side)); - CPT(TransformState) world_transform = gsg->get_scene()->get_world_transform(); + CPT(TransformState) world_transform = bin._gsg->get_scene()->get_world_transform(); CPT(TransformState) modelview_transform = world_transform->compose(net_transform); CPT(RenderState) state = get_octree_solid_test_state(); - PT(GeomMunger) munger = gsg->get_geom_munger(state); + PT(GeomMunger) munger = bin._gsg->get_geom_munger(state); CPT(Geom) viz = get_octree_solid_test(); CPT(GeomVertexData) munged_data = viz->get_vertex_data(); munger->munge_geom(viz, munged_data); - gsg->set_state_and_transform(state, modelview_transform); + bin._gsg->set_state_and_transform(state, modelview_transform); - gsg->begin_occlusion_query(); - viz->draw(gsg, munger, munged_data); - return gsg->end_occlusion_query(); + PStatTimer timer(bin._draw_occlusion_pcollector); + bin._gsg->begin_occlusion_query(); + viz->draw(bin._gsg, munger, munged_data); + return bin._gsg->end_occlusion_query(); } //////////////////////////////////////////////////////////////////// @@ -395,10 +402,7 @@ draw(CullBinHierarchicalZBuffer &bin) { Objects::const_iterator oi; for (oi = _objects.begin(); oi != _objects.end(); ++oi) { CullableObject *object = (*oi)._object; - if (object->_already_drawn) { - //cerr << "skipping object.\n"; - } else { - //cerr << "drawing object.\n"; + if (!object->_already_drawn) { CullHandler::draw(object, bin._gsg); object->_already_drawn = true; } @@ -409,7 +413,7 @@ draw(CullBinHierarchicalZBuffer &bin) { if (_corners[i] != (OctreeNode *)NULL) { PendingNode pending; pending._octree_node = _corners[i]; - pending._query = _corners[i]->occlusion_test(bin._gsg); + pending._query = _corners[i]->occlusion_test(bin); bin._pending_nodes.push_back(pending); } } @@ -560,8 +564,6 @@ multi_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) { const LPoint3f &c = object_data._bounds->get_center(); float r = object_data._bounds->get_radius(); - //cerr << "multi_assigning " << c << " vs. " << _mid << "\n"; - if (c[0] + r <= _mid[0]) { // -X if (c[1] + r <= _mid[1]) { @@ -726,7 +728,6 @@ multi_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) { //////////////////////////////////////////////////////////////////// INLINE void CullBinHierarchicalZBuffer::OctreeNode:: make_corner(int index) { - //cerr << "making corner " << hex << index << dec << "\n"; nassertv(_corners[index] == NULL); OctreeNode *node = NULL; diff --git a/panda/src/cull/cullBinHierarchicalZBuffer.h b/panda/src/cull/cullBinHierarchicalZBuffer.h index 76c37dd03d..e4e8fc3a5e 100644 --- a/panda/src/cull/cullBinHierarchicalZBuffer.h +++ b/panda/src/cull/cullBinHierarchicalZBuffer.h @@ -98,18 +98,21 @@ private: void make_initial_bounds(); void group_objects(); - PT(OcclusionQueryContext) occlusion_test(GraphicsStateGuardianBase *gsg); + PT(OcclusionQueryContext) occlusion_test(CullBinHierarchicalZBuffer &bin); void draw(CullBinHierarchicalZBuffer &bin); void draw_wireframe(CullBinHierarchicalZBuffer &bin); INLINE void initial_assign(const ObjectData &object_data); + INLINE int get_total_num_objects() const; + private: INLINE void reassign(const ObjectData &object_data); INLINE void assign_to_corner(int index, const ObjectData &object_data); void multi_assign(const ObjectData &object_data); void make_corner(int index); + int _total_num_objects; Objects _objects; OctreeNode *_corners[8]; LPoint3f _mid; @@ -129,7 +132,9 @@ private: typedef pdeque PendingNodes; PendingNodes _pending_nodes; + PStatCollector _draw_occlusion_pcollector; static PStatCollector _wait_occlusion_pcollector; + static PStatCollector _geoms_occluded_pcollector; static PT(Geom) _octree_solid_test; static PT(Geom) _octree_wireframe_viz; diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index c1b9d8694e..c159c58cf6 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -45,7 +45,7 @@ #include #endif -PStatCollector GraphicsEngine::_wait_pcollector("Wait"); +PStatCollector GraphicsEngine::_wait_pcollector("Wait:Thread sync"); PStatCollector GraphicsEngine::_cycle_pcollector("App:Cycle"); PStatCollector GraphicsEngine::_app_pcollector("App:Show code"); PStatCollector GraphicsEngine::_render_frame_pcollector("App:render_frame"); @@ -640,6 +640,7 @@ render_frame() { CullTraverser::_nodes_pcollector.clear_level(); CullTraverser::_geom_nodes_pcollector.clear_level(); CullTraverser::_geoms_pcollector.clear_level(); + CullTraverser::_geoms_occluded_pcollector.clear_level(); GeomCacheManager::_geom_cache_active_pcollector.clear_level(); GeomCacheManager::_geom_cache_record_pcollector.clear_level(); GeomCacheManager::_geom_cache_erase_pcollector.clear_level(); diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index adb6a6058c..5f2b381486 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -40,6 +40,7 @@ PStatCollector CullTraverser::_nodes_pcollector("Nodes"); PStatCollector CullTraverser::_geom_nodes_pcollector("Nodes:GeomNodes"); PStatCollector CullTraverser::_geoms_pcollector("Geoms"); +PStatCollector CullTraverser::_geoms_occluded_pcollector("Geoms:Occluded"); TypeHandle CullTraverser::_type_handle; diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 91e704d369..a3868faf17 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -93,6 +93,7 @@ public: static PStatCollector _nodes_pcollector; static PStatCollector _geom_nodes_pcollector; static PStatCollector _geoms_pcollector; + static PStatCollector _geoms_occluded_pcollector; private: void show_bounds(CullTraverserData &data, bool tight); diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 1193ee648b..ed1361f73c 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -108,7 +108,9 @@ struct LevelCollectorProperties { static TimeCollectorProperties time_properties[] = { { 1, "Wait", { 0.6, 0.6, 0.6 } }, - { 0, "Wait:Mutex block", { 1.0, 0.0, 0.0 } }, + { 0, "Wait:Mutex block", { 0.5, 0.0, 1.0 } }, + { 1, "Wait:Thread sync", { 0.0, 1.0, 0.5 } }, + { 1, "Wait:Occlusion test", { 1.0, 0.5, 0.0 } }, { 1, "App", { 0.0, 0.8, 0.4 }, 1.0 / 30.0 }, { 1, "App:Collisions", { 1.0, 0.5, 0.0 } }, { 1, "App:Collisions:Reset", { 0.0, 0.0, 0.5 } }, @@ -181,6 +183,7 @@ static LevelCollectorProperties level_properties[] = { { 1, "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 }, { 1, "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } }, { 1, "Geoms", { 0.4, 0.8, 0.3 }, "", 500.0 }, + { 1, "Geoms:Occluded", { 0.8, 0.2, 0.2 } }, { 1, "Cull volumes", { 0.7, 0.6, 0.9 }, "", 500.0 }, { 1, "Cull volumes:Transforms", { 0.9, 0.6, 0.0 } }, { 1, "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 },