Store munged states more efficiently, without weak key maps

This commit is contained in:
rdb 2017-10-17 23:21:38 +02:00
parent 8078fa2b38
commit 6ecfcb1fd3
6 changed files with 40 additions and 12 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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() {