mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
Store munged states more efficiently, without weak key maps
This commit is contained in:
parent
8078fa2b38
commit
6ecfcb1fd3
@ -281,6 +281,11 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
|
||||
|
||||
_gamma = 1.0f;
|
||||
_texture_quality_override = Texture::QL_default;
|
||||
|
||||
// Give it a unique identifier. Unlike a pointer, we can guarantee that
|
||||
// this value will never be reused.
|
||||
static size_t next_index = 0;
|
||||
_id = next_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,6 +295,19 @@ GraphicsStateGuardian::
|
||||
~GraphicsStateGuardian() {
|
||||
remove_gsg(this);
|
||||
GeomMunger::unregister_mungers_for_gsg(this);
|
||||
|
||||
// Remove the munged states for this GSG. This requires going through all
|
||||
// states, although destructing a GSG should be rare enough for this not to
|
||||
// matter too much.
|
||||
// Note that if uniquify-states is false, we can't iterate over all the
|
||||
// states, and some GSGs will linger. Let's hope this isn't a problem.
|
||||
LightReMutexHolder holder(*RenderState::_states_lock);
|
||||
size_t size = RenderState::_states->get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = RenderState::_states->get_key(si);
|
||||
state->_mungers.remove(_id);
|
||||
state->_munged_states.remove(_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -743,7 +761,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) {
|
||||
// multiple times during a frame. Also, this might well be the only GSG
|
||||
// in the world anyway.
|
||||
int mi = state->_last_mi;
|
||||
if (mi >= 0 && mungers.has_element(mi) && mungers.get_key(mi) == this) {
|
||||
if (mi >= 0 && mi < mungers.get_num_entries() && mungers.get_key(mi) == _id) {
|
||||
PT(GeomMunger) munger = mungers.get_data(mi);
|
||||
if (munger->is_registered()) {
|
||||
return munger;
|
||||
@ -751,7 +769,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) {
|
||||
}
|
||||
|
||||
// Nope, we have to look it up in the map.
|
||||
mi = mungers.find(this);
|
||||
mi = mungers.find(_id);
|
||||
if (mi >= 0) {
|
||||
PT(GeomMunger) munger = mungers.get_data(mi);
|
||||
if (munger->is_registered()) {
|
||||
@ -769,7 +787,7 @@ get_geom_munger(const RenderState *state, Thread *current_thread) {
|
||||
nassertr(munger != (GeomMunger *)NULL && munger->is_registered(), munger);
|
||||
nassertr(munger->is_of_type(StateMunger::get_class_type()), munger);
|
||||
|
||||
state->_last_mi = mungers.store(this, munger);
|
||||
state->_last_mi = mungers.store(_id, munger);
|
||||
return munger;
|
||||
}
|
||||
|
||||
|
@ -235,6 +235,8 @@ public:
|
||||
static void add_gsg(GraphicsStateGuardianBase *gsg);
|
||||
static void remove_gsg(GraphicsStateGuardianBase *gsg);
|
||||
|
||||
size_t _id;
|
||||
|
||||
private:
|
||||
struct GSGList {
|
||||
LightMutex _lock;
|
||||
|
@ -987,6 +987,7 @@ clear_munger_cache() {
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
RenderState *state = (RenderState *)(_states->get_key(si));
|
||||
state->_mungers.clear();
|
||||
state->_munged_states.clear();
|
||||
state->_last_mi = -1;
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,8 @@
|
||||
#include "lightMutex.h"
|
||||
#include "deletedChain.h"
|
||||
#include "simpleHashMap.h"
|
||||
#include "weakKeyHashMap.h"
|
||||
#include "cacheStats.h"
|
||||
#include "renderAttribRegistry.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
class FactoryParams;
|
||||
class ShaderAttrib;
|
||||
@ -264,10 +262,15 @@ private:
|
||||
// in the RenderState pointer than vice-versa, since there are likely to be
|
||||
// far fewer GSG's than RenderStates. The code to manage this map lives in
|
||||
// GraphicsStateGuardian::get_geom_munger().
|
||||
typedef WeakKeyHashMap<GraphicsStateGuardianBase, PT(GeomMunger) > Mungers;
|
||||
typedef SimpleHashMap<size_t, PT(GeomMunger), size_t_hash> Mungers;
|
||||
mutable Mungers _mungers;
|
||||
mutable int _last_mi;
|
||||
|
||||
// Similarly, this is a cache of munged states. This map is managed by
|
||||
// StateMunger::munge_state().
|
||||
typedef SimpleHashMap<size_t, WCPT(RenderState), size_t_hash> MungedStates;
|
||||
mutable MungedStates _munged_states;
|
||||
|
||||
// This is used to mark nodes as we visit them to detect cycles.
|
||||
UpdateSeq _cycle_detect;
|
||||
static UpdateSeq _last_cycle_detect;
|
||||
@ -360,6 +363,7 @@ private:
|
||||
friend class GraphicsStateGuardian;
|
||||
friend class RenderAttribRegistry;
|
||||
friend class Extension<RenderState>;
|
||||
friend class StateMunger;
|
||||
};
|
||||
|
||||
// We can safely redefine this as a no-op.
|
||||
|
@ -27,15 +27,20 @@ StateMunger::
|
||||
*/
|
||||
CPT(RenderState) StateMunger::
|
||||
munge_state(const RenderState *state) {
|
||||
int mi = _state_map.find(state);
|
||||
RenderState::MungedStates &munged_states = state->_munged_states;
|
||||
|
||||
int id = get_gsg()->_id;
|
||||
int mi = munged_states.find(id);
|
||||
if (mi != -1) {
|
||||
if (!_state_map.get_data(mi).was_deleted()) {
|
||||
return _state_map.get_data(mi).p();
|
||||
if (!munged_states.get_data(mi).was_deleted()) {
|
||||
return munged_states.get_data(mi).p();
|
||||
} else {
|
||||
munged_states.remove_element(mi);
|
||||
}
|
||||
}
|
||||
|
||||
CPT(RenderState) result = munge_state_impl(state);
|
||||
_state_map.store(state, result.p());
|
||||
munged_states.store(id, result.p());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ public:
|
||||
protected:
|
||||
virtual CPT(RenderState) munge_state_impl(const RenderState *state);
|
||||
|
||||
typedef WeakKeyHashMap<RenderState, WCPT(RenderState) > StateMap;
|
||||
StateMap _state_map;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user