diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 3efacffc3b..31224f5a90 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -499,6 +499,7 @@ render_frame() { // Reset our pcollectors that track data across the frame. CullTraverser::_nodes_pcollector.clear_level(); CullTraverser::_geom_nodes_pcollector.clear_level(); + CullTraverser::_geoms_pcollector.clear_level(); _transform_states_pcollector.set_level(TransformState::get_num_states()); _render_states_pcollector.set_level(RenderState::get_num_states()); diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index f7650d04c0..7ba0b4fbc1 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -393,7 +393,7 @@ set_state(const RenderState *state) { if (state != _state) { #ifndef NDEBUG if (gsg_cat.is_spam()) { - gsg_cat.spam() << "Setting GSG state to:\n"; + gsg_cat.spam() << "Setting GSG state to " << (void *)state << ":\n"; state->write(gsg_cat.spam(false), 2); } #endif diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 04827092d7..95d66bca16 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -2609,8 +2609,6 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) { bool DXGraphicsStateGuardian8:: begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, const qpGeomVertexData *vertex_data) { - DO_PSTATS_STUFF(_draw_primitive_pcollector.start()); - if (!GraphicsStateGuardian::begin_draw_primitives(geom, munger, vertex_data)) { return false; } @@ -2718,7 +2716,6 @@ draw_tristrips(const qpGeomTristrips *primitive) { void DXGraphicsStateGuardian8:: end_draw_primitives() { GraphicsStateGuardian::end_draw_primitives(); - DO_PSTATS_STUFF(_draw_primitive_pcollector.stop()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 8e58845734..87ce1d210c 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -31,6 +31,7 @@ cullBinFixed.I cullBinFixed.h \ cullBinFrontToBack.I cullBinFrontToBack.h \ cullBinManager.I cullBinManager.h \ + cullBinStateSorted.I cullBinStateSorted.h \ cullBinUnsorted.I cullBinUnsorted.h \ cullFaceAttrib.I cullFaceAttrib.h \ cullHandler.I cullHandler.h \ @@ -127,6 +128,7 @@ cullBinFixed.cxx \ cullBinFrontToBack.cxx \ cullBinManager.cxx \ + cullBinStateSorted.cxx \ cullBinUnsorted.cxx \ cullFaceAttrib.cxx \ cullHandler.cxx \ @@ -221,6 +223,7 @@ cullBinFixed.I cullBinFixed.h \ cullBinFrontToBack.I cullBinFrontToBack.h \ cullBinManager.I cullBinManager.h \ + cullBinStateSorted.I cullBinStateSorted.h \ cullBinUnsorted.I cullBinUnsorted.h \ cullFaceAttrib.I cullFaceAttrib.h \ cullHandler.I cullHandler.h \ diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 6c107461c2..74f517b541 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -36,6 +36,7 @@ #include "cullBinBackToFront.h" #include "cullBinFixed.h" #include "cullBinFrontToBack.h" +#include "cullBinStateSorted.h" #include "cullBinUnsorted.h" #include "cullTraverser.h" #include "cullableObject.h" @@ -236,6 +237,7 @@ init_libpgraph() { CullBinBackToFront::init_type(); CullBinFixed::init_type(); CullBinFrontToBack::init_type(); + CullBinStateSorted::init_type(); CullBinUnsorted::init_type(); CullTraverser::init_type(); CullableObject::init_type(); diff --git a/panda/src/pgraph/cullBinManager.cxx b/panda/src/pgraph/cullBinManager.cxx index 04f6865b5e..f9127aaa61 100644 --- a/panda/src/pgraph/cullBinManager.cxx +++ b/panda/src/pgraph/cullBinManager.cxx @@ -20,6 +20,7 @@ #include "cullBinBackToFront.h" #include "cullBinFrontToBack.h" #include "cullBinFixed.h" +#include "cullBinStateSorted.h" #include "cullBinUnsorted.h" #include "renderState.h" #include "cullResult.h" @@ -212,6 +213,9 @@ make_new_bin(int bin_index, GraphicsStateGuardianBase *gsg) { case BT_fixed: return new CullBinFixed(name, gsg); + case BT_state_sorted: + return new CullBinStateSorted(name, gsg); + default: return new CullBinUnsorted(name, gsg); } diff --git a/panda/src/pgraph/cullBinStateSorted.I b/panda/src/pgraph/cullBinStateSorted.I new file mode 100644 index 0000000000..f712cf77dc --- /dev/null +++ b/panda/src/pgraph/cullBinStateSorted.I @@ -0,0 +1,71 @@ +// Filename: cullBinStateSorted.I +// Created by: drose (22Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::ObjectData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullBinStateSorted::ObjectData:: +ObjectData(CullableObject *object) : + _object(object) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::ObjectData::operator < +// Access: Public +// Description: Specifies the correct sort ordering for these +// objects. +//////////////////////////////////////////////////////////////////// +INLINE bool CullBinStateSorted::ObjectData:: +operator < (const ObjectData &other) const { + const RenderState *sa = _object->_state; + const RenderState *sb = other._object->_state; + + if (sa != sb) { + // First, group objects by texture, since conventional wisdom is + // that texture changes are the most expensive state changes in a + // graphics context. + const TextureAttrib *ta = sa->get_texture(); + const TextureAttrib *tb = sb->get_texture(); + if (ta != tb) { + return ta < tb; + } + + // Then, sort by all the other states, in no particular order, + // just as long as objects with identical state are all grouped + // together. + return sa < sb; + } + + return 0; +} + + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullBinStateSorted:: +CullBinStateSorted(const string &name, GraphicsStateGuardianBase *gsg) : + CullBin(name, gsg) +{ +} diff --git a/panda/src/pgraph/cullBinStateSorted.cxx b/panda/src/pgraph/cullBinStateSorted.cxx new file mode 100644 index 0000000000..1f27f10f56 --- /dev/null +++ b/panda/src/pgraph/cullBinStateSorted.cxx @@ -0,0 +1,87 @@ +// Filename: cullBinStateSorted.cxx +// Created by: drose (22Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "cullBinStateSorted.h" +#include "graphicsStateGuardianBase.h" +#include "geometricBoundingVolume.h" +#include "cullableObject.h" +#include "cullHandler.h" +#include "pStatTimer.h" + +#include + + +TypeHandle CullBinStateSorted::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CullBinStateSorted:: +~CullBinStateSorted() { + Objects::iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi)._object; + delete object; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::add_object +// Access: Public, Virtual +// Description: Adds a geom, along with its associated state, to +// the bin for rendering. +//////////////////////////////////////////////////////////////////// +void CullBinStateSorted:: +add_object(CullableObject *object) { + _objects.push_back(ObjectData(object)); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::finish_cull +// Access: Public +// Description: Called after all the geoms have been added, this +// indicates that the cull process is finished for this +// frame and gives the bins a chance to do any +// post-processing (like sorting) before moving on to +// draw. +//////////////////////////////////////////////////////////////////// +void CullBinStateSorted:: +finish_cull() { + PStatTimer timer(_cull_this_pcollector); + sort(_objects.begin(), _objects.end()); +} + + +//////////////////////////////////////////////////////////////////// +// Function: CullBinStateSorted::draw +// Access: Public +// Description: Draws all the geoms in the bin, in the appropriate +// order. +//////////////////////////////////////////////////////////////////// +void CullBinStateSorted:: +draw() { + PStatTimer timer(_draw_this_pcollector); + Objects::const_iterator oi; + for (oi = _objects.begin(); oi != _objects.end(); ++oi) { + CullableObject *object = (*oi)._object; + CullHandler::draw(object, _gsg); + } +} + diff --git a/panda/src/pgraph/cullBinStateSorted.h b/panda/src/pgraph/cullBinStateSorted.h new file mode 100644 index 0000000000..bea8d52693 --- /dev/null +++ b/panda/src/pgraph/cullBinStateSorted.h @@ -0,0 +1,86 @@ +// Filename: cullBinStateSorted.h +// Created by: drose (22Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CULLBINSTATESORTED_H +#define CULLBINSTATESORTED_H + +#include "pandabase.h" + +#include "cullBin.h" +#include "geom.h" +#include "transformState.h" +#include "renderState.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : CullBinStateSorted +// Description : A specific kind of CullBin that sorts geometry to +// collect items of the same state together, so that +// minimal state changes are required on the GSG to +// render them. +// +// This also sorts objects front-to-back within a +// particular state, to take advantage of hierarchical +// Z-buffer algorithms which can early-out when an +// object appears behind another one. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullBinStateSorted : public CullBin { +public: + INLINE CullBinStateSorted(const string &name, GraphicsStateGuardianBase *gsg); + virtual ~CullBinStateSorted(); + + virtual void add_object(CullableObject *object); + virtual void finish_cull(); + virtual void draw(); + +private: + class ObjectData { + public: + INLINE ObjectData(CullableObject *object); + INLINE bool operator < (const ObjectData &other) const; + + CullableObject *_object; + }; + + typedef pvector Objects; + Objects _objects; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + CullBin::init_type(); + register_type(_type_handle, "CullBinStateSorted", + CullBin::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "cullBinStateSorted.I" + +#endif + + + diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index e04676f140..e66d4fa9a7 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -36,6 +36,7 @@ PStatCollector CullTraverser::_nodes_pcollector("Nodes"); PStatCollector CullTraverser::_geom_nodes_pcollector("Nodes:GeomNodes"); +PStatCollector CullTraverser::_geoms_pcollector("Geoms"); TypeHandle CullTraverser::_type_handle; @@ -210,6 +211,7 @@ traverse_below(CullTraverserData &data) { // Get all the Geoms, with no decalling. int num_geoms = geom_node->get_num_geoms(); + _geoms_pcollector.add_level(num_geoms); for (int i = 0; i < num_geoms; i++) { CullableObject *object = new CullableObject(data, geom_node, i); _cull_handler->record_object(object); @@ -264,6 +266,7 @@ show_bounds(CullTraverserData &data) { PT(Geom) bounds_viz = make_bounds_viz(node->get_bound()); if (bounds_viz != (Geom *)NULL) { + _geoms_pcollector.add_level(2); CullableObject *outer_viz = new CullableObject(bounds_viz, get_bounds_outer_viz_state(), data._render_transform); @@ -417,6 +420,7 @@ start_decal(const CullTraverserData &data) { CullableObject *object = separator; GeomNode *geom_node = DCAST(GeomNode, node); int num_geoms = geom_node->get_num_geoms(); + _geoms_pcollector.add_level(num_geoms); for (int i = num_geoms - 1; i >= 0; i--) { object = new CullableObject(data, geom_node, i, object); } @@ -474,6 +478,7 @@ r_get_decals(CullTraverserData &data, CullableObject *decals) { GeomNode *geom_node = DCAST(GeomNode, node); int num_geoms = geom_node->get_num_geoms(); + _geoms_pcollector.add_level(num_geoms); for (int i = num_geoms - 1; i >= 0; i--) { decals = new CullableObject(data, geom_node, i, decals); } diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 19add50513..eb46cbb213 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -89,6 +89,7 @@ public: // Statistics static PStatCollector _nodes_pcollector; static PStatCollector _geom_nodes_pcollector; + static PStatCollector _geoms_pcollector; private: void show_bounds(CullTraverserData &data); diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index 14d125a962..e509339a39 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -19,6 +19,7 @@ #include "cullBinFixed.cxx" #include "cullBinFrontToBack.cxx" #include "cullBinManager.cxx" +#include "cullBinStateSorted.cxx" #include "cullBinUnsorted.cxx" #include "cullFaceAttrib.cxx" #include "cullHandler.cxx" diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index a3b340d737..3d8de10386 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -165,6 +165,7 @@ static LevelCollectorProperties level_properties[] = { { 1, "Vertices:Display lists", { 0.8, 0.5, 1.0 } }, { 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, "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 },