automatically premunge on load

This commit is contained in:
David Rose 2007-05-21 22:36:27 +00:00
parent 6b913ae195
commit c7fb9cd0ab
14 changed files with 229 additions and 89 deletions

View File

@ -1727,11 +1727,6 @@ do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
gsg->_pipe = pipe;
gsg->_engine = this;
// If there was no global GSG previously, this becomes the one.
if (GraphicsStateGuardian::get_global_gsg() == NULL) {
gsg->make_global_gsg();
}
WindowRenderer *draw =
get_window_renderer(threading_model.get_draw_name(),
threading_model.get_draw_stage());

View File

@ -166,7 +166,7 @@ get_threading_model() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::prefers_triangle_strips
// Access: Published
// Access: Published, Virtual
// Description: Returns true if this GSG strongly prefers triangle
// strips to individual triangles (such as SGI), or
// false if it prefers to minimize the number of
@ -180,7 +180,7 @@ prefers_triangle_strips() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_max_vertices_per_array
// Access: Published
// Access: Published, Virtual
// Description: Returns the maximum number of vertices that should be
// put into any one GeomVertexData object for use with
// this GSG.
@ -192,7 +192,7 @@ get_max_vertices_per_array() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_max_vertices_per_primitive
// Access: Published
// Access: Published, Virtual
// Description: Returns the maximum number of vertex indices that
// should be put into any one GeomPrimitive object for
// use with this GSG.
@ -648,35 +648,6 @@ get_coordinate_system() const {
return _coordinate_system;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::make_global_gsg
// Access: Published
// Description: Marks this particular GraphicsStateGuardian as the
// "global" GSG, which is used for optimization hints by
// operations like NodePath::flatten_strong().
////////////////////////////////////////////////////////////////////
INLINE void GraphicsStateGuardian::
make_global_gsg() {
_global_gsg = this;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_global_gsg
// Access: Published, Static
// Description: Returns the "global" GSG, which is to say, the
// GraphicsStateGuardian object that has most recently
// had make_global_gsg() called for it. It may return
// NULL if there is no such GSG.
//
// This object should be used for optimization hints
// where appropriate, for instance by operations like
// NodePath::flatten_strong().
////////////////////////////////////////////////////////////////////
INLINE GraphicsStateGuardian *GraphicsStateGuardian::
get_global_gsg() {
return _global_gsg;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::reset_if_new
// Access: Public

View File

@ -71,7 +71,6 @@ PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear");
PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush");
PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL;
GraphicsStateGuardian *GraphicsStateGuardian::_global_gsg = NULL;
TypeHandle GraphicsStateGuardian::_type_handle;
@ -185,9 +184,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
////////////////////////////////////////////////////////////////////
GraphicsStateGuardian::
~GraphicsStateGuardian() {
if (_global_gsg == this) {
_global_gsg = NULL;
}
remove_gsg(this);
if (_stencil_render_states) {
delete _stencil_render_states;

View File

@ -98,9 +98,9 @@ PUBLISHED:
INLINE GraphicsEngine *get_engine() const;
INLINE const GraphicsThreadingModel &get_threading_model() const;
INLINE bool prefers_triangle_strips() const;
INLINE int get_max_vertices_per_array() const;
INLINE int get_max_vertices_per_primitive() const;
virtual INLINE bool prefers_triangle_strips() const;
virtual INLINE int get_max_vertices_per_array() const;
virtual INLINE int get_max_vertices_per_primitive() const;
INLINE int get_max_texture_stages() const;
INLINE int get_max_texture_dimension() const;
@ -149,9 +149,6 @@ PUBLISHED:
INLINE CoordinateSystem get_coordinate_system() const;
virtual CoordinateSystem get_internal_coordinate_system() const;
INLINE void make_global_gsg();
INLINE static GraphicsStateGuardian *get_global_gsg();
virtual PreparedGraphicsObjects *get_prepared_objects();
public:

View File

@ -1167,6 +1167,10 @@ reset() {
}
#endif
// Now that the GSG has been initialized, make it available for
// optimizations.
add_gsg(this);
}

View File

@ -17,5 +17,93 @@
////////////////////////////////////////////////////////////////////
#include "graphicsStateGuardianBase.h"
#include "mutexHolder.h"
GraphicsStateGuardianBase::GSGs GraphicsStateGuardianBase::_gsgs;
GraphicsStateGuardianBase *GraphicsStateGuardianBase::_default_gsg;
TypeHandle GraphicsStateGuardianBase::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardianBase::get_default_gsg
// Access: Published, Static
// Description: Returns a pointer to the "default" GSG. This is
// typically the first GSG created in an application; in
// a single-window application, it will be the only GSG.
// This GSG is used to determine default optimization
// choices for loaded geometry.
//
// The return value may be NULL if a GSG has not been
// created.
////////////////////////////////////////////////////////////////////
GraphicsStateGuardianBase *GraphicsStateGuardianBase::
get_default_gsg() {
MutexHolder holder(_lock);
return _default_gsg;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardianBase::set_default_gsg
// Access: Published, Static
// Description: Specifies a particular GSG to use as the "default"
// GSG. See get_default_gsg().
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardianBase::
set_default_gsg(GraphicsStateGuardianBase *default_gsg) {
MutexHolder holder(_lock);
if (find(_gsgs.begin(), _gsgs.end(), default_gsg) == _gsgs.end()) {
// The specified GSG doesn't exist or it has already destructed.
nassertv(false);
return;
}
_default_gsg = default_gsg;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardianBase::add_gsg
// Access: Public, Static
// Description: Called by a GSG after it has been initialized, to add
// a new GSG to the available list.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardianBase::
add_gsg(GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
if (find(_gsgs.begin(), _gsgs.end(), gsg) != _gsgs.end()) {
// Already on the list.
return;
}
_gsgs.push_back(gsg);
if (_default_gsg == (GraphicsStateGuardianBase *)NULL) {
_default_gsg = gsg;
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardianBase::remove_gsg
// Access: Public, Static
// Description: Called by a GSG destructor to remove a GSG from the
// available list.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardianBase::
remove_gsg(GraphicsStateGuardianBase *gsg) {
MutexHolder holder(_lock);
GSGs::iterator gi = find(_gsgs.begin(), _gsgs.end(), gsg);
if (gi == _gsgs.end()) {
// Already removed, or never added.
return;
}
_gsgs.erase(gi);
if (_default_gsg == gsg) {
if (_gsgs.empty()) {
_default_gsg = *_gsgs.begin();
} else {
_default_gsg = NULL;
}
}
}

View File

@ -23,6 +23,7 @@
#include "typedWritableReferenceCount.h"
#include "luse.h"
#include "pmutex.h"
// A handful of forward references.
@ -111,6 +112,10 @@ class Lens;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount {
PUBLISHED:
virtual bool prefers_triangle_strips() const=0;
virtual int get_max_vertices_per_array() const=0;
virtual int get_max_vertices_per_primitive() const=0;
virtual bool get_supports_multisample() const=0;
virtual int get_supported_geom_rendering() const=0;
virtual bool get_supports_occlusion_query() const=0;
@ -203,11 +208,23 @@ public:
int light_id) { }
PUBLISHED:
static GraphicsStateGuardianBase *get_default_gsg();
static void set_default_gsg(GraphicsStateGuardianBase *default_gsg);
public:
static void add_gsg(GraphicsStateGuardianBase *gsg);
static void remove_gsg(GraphicsStateGuardianBase *gsg);
private:
typedef pvector<GraphicsStateGuardianBase *> GSGs;
static GSGs _gsgs;
static GraphicsStateGuardianBase *_default_gsg;
static Mutex _lock;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
public:
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "GraphicsStateGuardianBase",

View File

@ -30,6 +30,7 @@
#include "vector_int.h"
#include "userVertexTransform.h"
#include "geomMunger.h"
#include "config_pgraph.h"
static PStatCollector apply_vertex_collector("*:Flatten:apply:vertex");
static PStatCollector apply_texcoord_collector("*:Flatten:apply:texcoord");

View File

@ -29,6 +29,8 @@
#include "string_utils.h"
#include "bamCache.h"
#include "bamCacheRecord.h"
#include "sceneGraphReducer.h"
#include "renderState.h"
bool Loader::_file_types_loaded = false;
TypeHandle Loader::_type_handle;
@ -215,7 +217,10 @@ load_file(const Filename &filename, const LoaderOptions &options) const {
loader_cat.info()
<< "Model " << path << " found in disk cache.\n";
}
return DCAST(PandaNode, record->extract_data());
PT(PandaNode) result = DCAST(PandaNode, record->extract_data());
SceneGraphReducer sgr;
sgr.premunge(result, RenderState::make_empty());
return result;
}
}
}
@ -228,6 +233,8 @@ load_file(const Filename &filename, const LoaderOptions &options) const {
cache->store(record);
}
SceneGraphReducer sgr;
sgr.premunge(result, RenderState::make_empty());
return result;
}
}

View File

@ -5593,8 +5593,8 @@ premunge_scene(GraphicsStateGuardianBase *gsg) {
state = get_parent().get_net_state();
}
SceneGraphReducer gr;
gr.premunge(node(), gsg, state);
SceneGraphReducer gr(gsg);
gr.premunge(node(), state);
}
////////////////////////////////////////////////////////////////////

View File

@ -793,7 +793,7 @@ PUBLISHED:
// Miscellaneous
bool verify_complete(Thread *current_thread = Thread::get_current_thread()) const;
void premunge_scene(GraphicsStateGuardianBase *gsg);
void premunge_scene(GraphicsStateGuardianBase *gsg = NULL);
void prepare_scene(GraphicsStateGuardianBase *gsg);
void show_bounds();

View File

@ -23,9 +23,10 @@
// Description:
////////////////////////////////////////////////////////////////////
INLINE SceneGraphReducer::
SceneGraphReducer() :
SceneGraphReducer(GraphicsStateGuardianBase *gsg) :
_combine_radius(0.0f)
{
set_gsg(gsg);
}
////////////////////////////////////////////////////////////////////
@ -37,6 +38,19 @@ INLINE SceneGraphReducer::
~SceneGraphReducer() {
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::get_gsg
// Access: Published
// Description: Returns the particular GraphicsStateGuardian that
// this object will attempt to optimize to.
// See set_gsg().
////////////////////////////////////////////////////////////////////
INLINE GraphicsStateGuardianBase *SceneGraphReducer::
get_gsg() const {
return _gsg;
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::set_combine_radius
// Access: Published
@ -145,34 +159,21 @@ make_nonindexed(PandaNode *root, int nonindexed_bits) {
return r_make_nonindexed(root, nonindexed_bits);
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::unify
// Access: Published
// Description: Calls unify() on every GeomNode at this level and
// below. This attempts to reduce the total number of
// individual Geoms and GeomPrimitives by combining
// these objects wherever possible. See
// GeomNode::unify().
////////////////////////////////////////////////////////////////////
INLINE void SceneGraphReducer::
unify(PandaNode *root) {
PStatTimer timer(_unify_collector);
r_unify(root);
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::premunge
// Access: Published
// Description: Walks the scene graph rooted at this node and below,
// and uses the indicated GSG to premunge every Geom
// found to optimize it for eventual rendering on the
// indicated GSG.
// indicated GSG. If there is no GSG indicated for the
// SceneGraphReducer, this is a no-op.
//
// This operation will also apply to stashed children.
////////////////////////////////////////////////////////////////////
INLINE void SceneGraphReducer::
premunge(PandaNode *root, GraphicsStateGuardianBase *gsg,
const RenderState *initial_state) {
premunge(PandaNode *root, const RenderState *initial_state) {
if (_gsg != (GraphicsStateGuardianBase *)NULL) {
PStatTimer timer(_premunge_collector);
r_premunge(root, gsg, initial_state);
r_premunge(root, initial_state);
}
}

View File

@ -33,6 +33,46 @@ PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make non
PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify");
PStatCollector SceneGraphReducer::_premunge_collector("*:Premunge");
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::set_gsg
// Access: Published
// Description: Specifies the particular GraphicsStateGuardian that
// this object will attempt to optimize to. The GSG may
// specify parameters such as maximum number of vertices
// per vertex data, max number of vertices per
// primitive, and whether triangle strips are preferred.
// It also affects the types of vertex column data that
// is created by premunge().
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
set_gsg(GraphicsStateGuardianBase *gsg) {
if (gsg != (GraphicsStateGuardianBase *)NULL) {
_gsg = gsg;
} else {
_gsg = GraphicsStateGuardianBase::get_default_gsg();
}
if (_gsg != (GraphicsStateGuardianBase *)NULL) {
_transformer.set_max_collect_vertices(_gsg->get_max_vertices_per_array());
} else {
_transformer.set_max_collect_vertices(max_collect_vertices);
}
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::clear_gsg
// Access: Published
// Description: Specifies that no particular GraphicsStateGuardian
// will be used to guide the optimization. The
// SceneGraphReducer will instead use config variables
// such as max-collect-vertices and max-collect-indices.
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
clear_gsg() {
_gsg = NULL;
_transformer.set_max_collect_vertices(max_collect_vertices);
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::flatten
// Access: Published
@ -87,6 +127,25 @@ flatten(PandaNode *root, int combine_siblings_bits) {
return num_total_nodes;
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::unify
// Access: Published
// Description: Calls unify() on every GeomNode at this level and
// below. This attempts to reduce the total number of
// individual Geoms and GeomPrimitives by combining
// these objects wherever possible. See
// GeomNode::unify().
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
unify(PandaNode *root) {
PStatTimer timer(_unify_collector);
if (_gsg != (GraphicsStateGuardianBase *)NULL) {
r_unify(root, _gsg->get_max_vertices_per_primitive());
} else {
r_unify(root, max_collect_indices);
}
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::r_apply_attribs
// Access: Protected
@ -727,16 +786,16 @@ r_make_nonindexed(PandaNode *node, int nonindexed_bits) {
// Description: The recursive implementation of unify().
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
r_unify(PandaNode *node) {
r_unify(PandaNode *node, int max_indices) {
if (node->is_geom_node()) {
GeomNode *geom_node = DCAST(GeomNode, node);
geom_node->unify(max_collect_indices);
geom_node->unify(max_indices);
}
PandaNode::Children children = node->get_children();
int num_children = children.get_num_children();
for (int i = 0; i < num_children; ++i) {
r_unify(children.get_child(i));
r_unify(children.get_child(i), max_indices);
}
}
@ -746,25 +805,24 @@ r_unify(PandaNode *node) {
// Description: The recursive implementation of premunge().
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
r_premunge(PandaNode *node, GraphicsStateGuardianBase *gsg,
const RenderState *state) {
r_premunge(PandaNode *node, const RenderState *state) {
CPT(RenderState) next_state = state->compose(node->get_state());
if (node->is_geom_node()) {
GeomNode *geom_node = DCAST(GeomNode, node);
geom_node->do_premunge(gsg, next_state, _transformer);
geom_node->do_premunge(_gsg, next_state, _transformer);
}
int i;
PandaNode::Children children = node->get_children();
int num_children = children.get_num_children();
for (i = 0; i < num_children; ++i) {
r_premunge(children.get_child(i), gsg, next_state);
r_premunge(children.get_child(i), next_state);
}
PandaNode::Stashed stashed = node->get_stashed();
int num_stashed = stashed.get_num_stashed();
for (i = 0; i < num_stashed; ++i) {
r_premunge(stashed.get_stashed(i), gsg, next_state);
r_premunge(stashed.get_stashed(i), next_state);
}
}

View File

@ -29,6 +29,7 @@
#include "pStatTimer.h"
#include "typedObject.h"
#include "pointerTo.h"
#include "graphicsStateGuardianBase.h"
class PandaNode;
@ -45,7 +46,7 @@ class PandaNode;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA SceneGraphReducer {
PUBLISHED:
INLINE SceneGraphReducer();
INLINE SceneGraphReducer(GraphicsStateGuardianBase *gsg = NULL);
INLINE ~SceneGraphReducer();
enum AttribTypes {
@ -121,6 +122,10 @@ PUBLISHED:
MN_avoid_dynamic = 0x004,
};
void set_gsg(GraphicsStateGuardianBase *gsg);
void clear_gsg();
INLINE GraphicsStateGuardianBase *get_gsg() const;
INLINE void set_combine_radius(float combine_radius);
INLINE float get_combine_radius() const;
@ -132,10 +137,9 @@ PUBLISHED:
INLINE int collect_vertex_data(PandaNode *root, int collect_bits = ~0);
INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0);
INLINE void unify(PandaNode *root);
void unify(PandaNode *root);
INLINE void premunge(PandaNode *root, GraphicsStateGuardianBase *gsg,
const RenderState *initial_state);
INLINE void premunge(PandaNode *root, const RenderState *initial_state);
protected:
void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
@ -165,12 +169,12 @@ protected:
int r_collect_vertex_data(PandaNode *node, int collect_bits,
GeomTransformer &transformer);
int r_make_nonindexed(PandaNode *node, int collect_bits);
void r_unify(PandaNode *node);
void r_unify(PandaNode *node, int max_indices);
void r_premunge(PandaNode *node, GraphicsStateGuardianBase *gsg,
const RenderState *state);
void r_premunge(PandaNode *node, const RenderState *state);
private:
PT(GraphicsStateGuardianBase) _gsg;
float _combine_radius;
GeomTransformer _transformer;