mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 00:06:44 -04:00
pgraph: take advantage of constant initialization for states maps
SimpleHashMap has a constexpr default constructor, so there is no static init ordering issue that requires us to allocate the states maps on the heap and then to leak them.
This commit is contained in:
parent
441e1e3d66
commit
193ae8a3a6
@ -301,9 +301,9 @@ GraphicsStateGuardian::
|
||||
// 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();
|
||||
size_t size = RenderState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = RenderState::_states->get_key(si);
|
||||
const RenderState *state = RenderState::_states.get_key(si);
|
||||
state->_mungers.remove(_id);
|
||||
state->_munged_states.remove(_id);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
using std::ostream;
|
||||
|
||||
LightReMutex *RenderAttrib::_attribs_lock = nullptr;
|
||||
RenderAttrib::Attribs *RenderAttrib::_attribs = nullptr;
|
||||
RenderAttrib::Attribs RenderAttrib::_attribs;
|
||||
TypeHandle RenderAttrib::_type_handle;
|
||||
|
||||
size_t RenderAttrib::_garbage_index = 0;
|
||||
@ -33,7 +33,7 @@ PStatCollector RenderAttrib::_garbage_collect_pcollector("*:State Cache:Garbage
|
||||
*/
|
||||
RenderAttrib::
|
||||
RenderAttrib() {
|
||||
if (_attribs == nullptr) {
|
||||
if (_attribs_lock == nullptr) {
|
||||
init_attribs();
|
||||
}
|
||||
_saved_entry = -1;
|
||||
@ -156,11 +156,7 @@ write(ostream &out, int indent_level) const {
|
||||
int RenderAttrib::
|
||||
get_num_attribs() {
|
||||
LightReMutexHolder holder(*_attribs_lock);
|
||||
|
||||
if (_attribs == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return _attribs->get_num_entries();
|
||||
return _attribs.get_num_entries();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,10 +168,10 @@ void RenderAttrib::
|
||||
list_attribs(ostream &out) {
|
||||
LightReMutexHolder holder(*_attribs_lock);
|
||||
|
||||
size_t size = _attribs->get_num_entries();
|
||||
size_t size = _attribs.get_num_entries();
|
||||
out << size << " attribs:\n";
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderAttrib *attrib = _attribs->get_key(si);
|
||||
const RenderAttrib *attrib = _attribs.get_key(si);
|
||||
attrib->write(out, 2);
|
||||
}
|
||||
}
|
||||
@ -186,16 +182,16 @@ list_attribs(ostream &out) {
|
||||
*/
|
||||
int RenderAttrib::
|
||||
garbage_collect() {
|
||||
if (_attribs == nullptr || !garbage_collect_states) {
|
||||
if (!garbage_collect_states) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_attribs_lock);
|
||||
|
||||
PStatTimer timer(_garbage_collect_pcollector);
|
||||
size_t orig_size = _attribs->get_num_entries();
|
||||
size_t orig_size = _attribs.get_num_entries();
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertr(_attribs->validate(), 0);
|
||||
nassertr(_attribs.validate(), 0);
|
||||
#endif
|
||||
|
||||
// How many elements to process this pass?
|
||||
@ -214,7 +210,7 @@ garbage_collect() {
|
||||
size_t stop_at_element = (si + num_this_pass) % size;
|
||||
|
||||
do {
|
||||
RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
|
||||
RenderAttrib *attrib = (RenderAttrib *)_attribs.get_key(si);
|
||||
if (attrib->get_ref_count() == 1) {
|
||||
// This attrib has recently been unreffed to 1 (the one we added when
|
||||
// we stored it in the cache). Now it's time to delete it. This is
|
||||
@ -238,15 +234,15 @@ garbage_collect() {
|
||||
} while (si != stop_at_element);
|
||||
_garbage_index = si;
|
||||
|
||||
nassertr(_attribs->get_num_entries() == size, 0);
|
||||
nassertr(_attribs.get_num_entries() == size, 0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertr(_attribs->validate(), 0);
|
||||
nassertr(_attribs.validate(), 0);
|
||||
#endif
|
||||
|
||||
// If we just cleaned up a lot of attribs, see if we can reduce the table in
|
||||
// size. This will help reduce iteration overhead in the future.
|
||||
_attribs->consider_shrink_table();
|
||||
_attribs.consider_shrink_table();
|
||||
|
||||
return (int)orig_size - (int)size;
|
||||
}
|
||||
@ -259,17 +255,17 @@ garbage_collect() {
|
||||
bool RenderAttrib::
|
||||
validate_attribs() {
|
||||
LightReMutexHolder holder(*_attribs_lock);
|
||||
if (_attribs->is_empty()) {
|
||||
if (_attribs.is_empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_attribs->validate()) {
|
||||
if (!_attribs.validate()) {
|
||||
pgraph_cat.error()
|
||||
<< "RenderAttrib::_attribs cache is invalid!\n";
|
||||
|
||||
size_t size = _attribs->get_num_entries();
|
||||
size_t size = _attribs.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderAttrib *attrib = _attribs->get_key(si);
|
||||
const RenderAttrib *attrib = _attribs.get_key(si);
|
||||
//cerr << si << ": " << attrib << "\n";
|
||||
attrib->write(std::cerr, 2);
|
||||
}
|
||||
@ -277,16 +273,16 @@ validate_attribs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = _attribs->get_num_entries();
|
||||
size_t size = _attribs.get_num_entries();
|
||||
size_t si = 0;
|
||||
nassertr(si < size, false);
|
||||
nassertr(_attribs->get_key(si)->get_ref_count() >= 0, false);
|
||||
nassertr(_attribs.get_key(si)->get_ref_count() >= 0, false);
|
||||
size_t snext = si;
|
||||
++snext;
|
||||
while (snext < size) {
|
||||
nassertr(_attribs->get_key(snext)->get_ref_count() >= 0, false);
|
||||
const RenderAttrib *ssi = _attribs->get_key(si);
|
||||
const RenderAttrib *ssnext = _attribs->get_key(snext);
|
||||
nassertr(_attribs.get_key(snext)->get_ref_count() >= 0, false);
|
||||
const RenderAttrib *ssi = _attribs.get_key(si);
|
||||
const RenderAttrib *ssnext = _attribs.get_key(snext);
|
||||
int c = ssi->compare_to(*ssnext);
|
||||
int ci = ssnext->compare_to(*ssi);
|
||||
if ((ci < 0) != (c > 0) ||
|
||||
@ -356,19 +352,19 @@ return_unique(RenderAttrib *attrib) {
|
||||
LightReMutexHolder holder(*_attribs_lock);
|
||||
|
||||
if (attrib->_saved_entry != -1) {
|
||||
// This attrib is already in the cache. nassertr(_attribs->find(attrib)
|
||||
// This attrib is already in the cache. nassertr(_attribs.find(attrib)
|
||||
// == attrib->_saved_entry, attrib);
|
||||
return attrib;
|
||||
}
|
||||
|
||||
int si = _attribs->find(attrib);
|
||||
int si = _attribs.find(attrib);
|
||||
if (si != -1) {
|
||||
// There's an equivalent attrib already in the set. Return it. If this
|
||||
// is a newly created RenderAttrib, though, be sure to delete it.
|
||||
if (attrib->get_ref_count() == 0) {
|
||||
delete attrib;
|
||||
}
|
||||
return _attribs->get_key(si);
|
||||
return _attribs.get_key(si);
|
||||
}
|
||||
|
||||
// Not already in the set; add it.
|
||||
@ -378,7 +374,7 @@ return_unique(RenderAttrib *attrib) {
|
||||
// deleted while it's in it.
|
||||
attrib->ref();
|
||||
}
|
||||
si = _attribs->store(attrib, nullptr);
|
||||
si = _attribs.store(attrib, nullptr);
|
||||
|
||||
// Save the index and return the input attrib.
|
||||
attrib->_saved_entry = si;
|
||||
@ -495,7 +491,7 @@ release_new() {
|
||||
|
||||
if (_saved_entry != -1) {
|
||||
_saved_entry = -1;
|
||||
nassertv_always(_attribs->remove(this));
|
||||
nassertv_always(_attribs.remove(this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,8 +504,6 @@ release_new() {
|
||||
*/
|
||||
void RenderAttrib::
|
||||
init_attribs() {
|
||||
_attribs = new Attribs;
|
||||
|
||||
// TODO: we should have a global Panda mutex to allow us to safely create
|
||||
// _attribs_lock without a startup race condition. For the meantime, this
|
||||
// is OK because we guarantee that this method is called at static init
|
||||
|
@ -186,7 +186,7 @@ private:
|
||||
// This mutex protects _attribs.
|
||||
static LightReMutex *_attribs_lock;
|
||||
typedef SimpleHashMap<const RenderAttrib *, std::nullptr_t, indirect_compare_to_hash<const RenderAttrib *> > Attribs;
|
||||
static Attribs *_attribs;
|
||||
static Attribs _attribs;
|
||||
|
||||
int _saved_entry;
|
||||
size_t _hash;
|
||||
|
@ -91,9 +91,9 @@ register_slot(TypeHandle type_handle, int sort, RenderAttrib *default_attrib) {
|
||||
|
||||
if (default_attrib->_saved_entry == -1) {
|
||||
// If this attribute was already registered, something odd is going on.
|
||||
nassertr(RenderAttrib::_attribs->find(default_attrib) == -1, 0);
|
||||
nassertr(RenderAttrib::_attribs.find(default_attrib) == -1, 0);
|
||||
default_attrib->_saved_entry =
|
||||
RenderAttrib::_attribs->store(default_attrib, nullptr);
|
||||
RenderAttrib::_attribs.store(default_attrib, nullptr);
|
||||
}
|
||||
|
||||
// It effectively lives forever. Might as well make it official.
|
||||
|
@ -39,7 +39,7 @@
|
||||
using std::ostream;
|
||||
|
||||
LightReMutex *RenderState::_states_lock = nullptr;
|
||||
RenderState::States *RenderState::_states = nullptr;
|
||||
RenderState::States RenderState::_states;
|
||||
const RenderState *RenderState::_empty_state = nullptr;
|
||||
UpdateSeq RenderState::_last_cycle_detect;
|
||||
size_t RenderState::_garbage_index = 0;
|
||||
@ -68,7 +68,7 @@ RenderState() :
|
||||
_flags(0),
|
||||
_lock("RenderState")
|
||||
{
|
||||
if (_states == nullptr) {
|
||||
if (_states_lock == nullptr) {
|
||||
init_states();
|
||||
}
|
||||
_saved_entry = -1;
|
||||
@ -716,11 +716,8 @@ get_max_priority() {
|
||||
*/
|
||||
int RenderState::
|
||||
get_num_states() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
return _states->get_num_entries();
|
||||
return _states.get_num_entries();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -738,9 +735,6 @@ get_num_states() {
|
||||
*/
|
||||
int RenderState::
|
||||
get_num_unused_states() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
// First, we need to count the number of times each RenderState object is
|
||||
@ -748,9 +742,9 @@ get_num_unused_states() {
|
||||
typedef pmap<const RenderState *, int> StateCount;
|
||||
StateCount state_count;
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = _states->get_key(si);
|
||||
const RenderState *state = _states.get_key(si);
|
||||
|
||||
size_t i;
|
||||
size_t cache_size = state->_composition_cache.get_num_entries();
|
||||
@ -821,13 +815,10 @@ get_num_unused_states() {
|
||||
*/
|
||||
int RenderState::
|
||||
clear_cache() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
PStatTimer timer(_cache_update_pcollector);
|
||||
int orig_size = _states->get_num_entries();
|
||||
int orig_size = _states.get_num_entries();
|
||||
|
||||
// First, we need to copy the entire set of states to a temporary vector,
|
||||
// reference-counting each object. That way we can walk through the copy,
|
||||
@ -838,9 +829,9 @@ clear_cache() {
|
||||
TempStates temp_states;
|
||||
temp_states.reserve(orig_size);
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = _states->get_key(si);
|
||||
const RenderState *state = _states.get_key(si);
|
||||
temp_states.push_back(state);
|
||||
}
|
||||
|
||||
@ -879,7 +870,7 @@ clear_cache() {
|
||||
// the various objects' caches will go away.
|
||||
}
|
||||
|
||||
int new_size = _states->get_num_entries();
|
||||
int new_size = _states.get_num_entries();
|
||||
return orig_size - new_size;
|
||||
}
|
||||
|
||||
@ -895,14 +886,14 @@ int RenderState::
|
||||
garbage_collect() {
|
||||
int num_attribs = RenderAttrib::garbage_collect();
|
||||
|
||||
if (_states == nullptr || !garbage_collect_states) {
|
||||
if (!garbage_collect_states) {
|
||||
return num_attribs;
|
||||
}
|
||||
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
PStatTimer timer(_garbage_collect_pcollector);
|
||||
size_t orig_size = _states->get_num_entries();
|
||||
size_t orig_size = _states.get_num_entries();
|
||||
|
||||
// How many elements to process this pass?
|
||||
size_t size = orig_size;
|
||||
@ -922,7 +913,7 @@ garbage_collect() {
|
||||
size_t stop_at_element = (si + num_this_pass) % size;
|
||||
|
||||
do {
|
||||
RenderState *state = (RenderState *)_states->get_key(si);
|
||||
RenderState *state = (RenderState *)_states.get_key(si);
|
||||
if (break_and_uniquify) {
|
||||
if (state->get_cache_ref_count() > 0 &&
|
||||
state->get_ref_count() == state->get_cache_ref_count()) {
|
||||
@ -959,15 +950,15 @@ garbage_collect() {
|
||||
} while (si != stop_at_element);
|
||||
_garbage_index = si;
|
||||
|
||||
nassertr(_states->get_num_entries() == size, 0);
|
||||
nassertr(_states.get_num_entries() == size, 0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertr(_states->validate(), 0);
|
||||
nassertr(_states.validate(), 0);
|
||||
#endif
|
||||
|
||||
// If we just cleaned up a lot of states, see if we can reduce the table in
|
||||
// size. This will help reduce iteration overhead in the future.
|
||||
_states->consider_shrink_table();
|
||||
_states.consider_shrink_table();
|
||||
|
||||
return (int)orig_size - (int)size + num_attribs;
|
||||
}
|
||||
@ -980,9 +971,9 @@ void RenderState::
|
||||
clear_munger_cache() {
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
RenderState *state = (RenderState *)(_states->get_key(si));
|
||||
RenderState *state = (RenderState *)(_states.get_key(si));
|
||||
state->_mungers.clear();
|
||||
state->_munged_states.clear();
|
||||
state->_last_mi = -1;
|
||||
@ -1004,18 +995,15 @@ clear_munger_cache() {
|
||||
*/
|
||||
void RenderState::
|
||||
list_cycles(ostream &out) {
|
||||
if (_states == nullptr) {
|
||||
return;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
typedef pset<const RenderState *> VisitedStates;
|
||||
VisitedStates visited;
|
||||
CompositionCycleDesc cycle_desc;
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = _states->get_key(si);
|
||||
const RenderState *state = _states.get_key(si);
|
||||
|
||||
bool inserted = visited.insert(state).second;
|
||||
if (inserted) {
|
||||
@ -1081,16 +1069,12 @@ list_cycles(ostream &out) {
|
||||
*/
|
||||
void RenderState::
|
||||
list_states(ostream &out) {
|
||||
if (_states == nullptr) {
|
||||
out << "0 states:\n";
|
||||
return;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
out << size << " states:\n";
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = _states->get_key(si);
|
||||
const RenderState *state = _states.get_key(si);
|
||||
state->write(out, 2);
|
||||
}
|
||||
}
|
||||
@ -1103,33 +1087,29 @@ list_states(ostream &out) {
|
||||
*/
|
||||
bool RenderState::
|
||||
validate_states() {
|
||||
if (_states == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PStatTimer timer(_state_validate_pcollector);
|
||||
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
if (_states->is_empty()) {
|
||||
if (_states.is_empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_states->validate()) {
|
||||
if (!_states.validate()) {
|
||||
pgraph_cat.error()
|
||||
<< "RenderState::_states cache is invalid!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
size_t si = 0;
|
||||
nassertr(si < size, false);
|
||||
nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
|
||||
nassertr(_states.get_key(si)->get_ref_count() >= 0, false);
|
||||
size_t snext = si;
|
||||
++snext;
|
||||
while (snext < size) {
|
||||
nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
|
||||
const RenderState *ssi = _states->get_key(si);
|
||||
const RenderState *ssnext = _states->get_key(snext);
|
||||
nassertr(_states.get_key(snext)->get_ref_count() >= 0, false);
|
||||
const RenderState *ssi = _states.get_key(si);
|
||||
const RenderState *ssnext = _states.get_key(snext);
|
||||
int c = ssi->compare_to(*ssnext);
|
||||
int ci = ssnext->compare_to(*ssi);
|
||||
if ((ci < 0) != (c > 0) ||
|
||||
@ -1299,7 +1279,7 @@ return_unique(RenderState *state) {
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
if (state->_saved_entry != -1) {
|
||||
// This state is already in the cache. nassertr(_states->find(state) ==
|
||||
// This state is already in the cache. nassertr(_states.find(state) ==
|
||||
// state->_saved_entry, pt_state);
|
||||
return state;
|
||||
}
|
||||
@ -1318,7 +1298,7 @@ return_unique(RenderState *state) {
|
||||
}
|
||||
}
|
||||
|
||||
int si = _states->find(state);
|
||||
int si = _states.find(state);
|
||||
if (si != -1) {
|
||||
// There's an equivalent state already in the set. Return it. The state
|
||||
// that was passed may be newly created and therefore may not be
|
||||
@ -1326,7 +1306,7 @@ return_unique(RenderState *state) {
|
||||
if (state->get_ref_count() == 0) {
|
||||
delete state;
|
||||
}
|
||||
return _states->get_key(si);
|
||||
return _states.get_key(si);
|
||||
}
|
||||
|
||||
// Not already in the set; add it.
|
||||
@ -1336,7 +1316,7 @@ return_unique(RenderState *state) {
|
||||
// deleted while it's in it.
|
||||
state->cache_ref();
|
||||
}
|
||||
si = _states->store(state, nullptr);
|
||||
si = _states.store(state, nullptr);
|
||||
|
||||
// Save the index and return the input state.
|
||||
state->_saved_entry = si;
|
||||
@ -1612,7 +1592,7 @@ release_new() {
|
||||
|
||||
if (_saved_entry != -1) {
|
||||
_saved_entry = -1;
|
||||
nassertv_always(_states->remove(this));
|
||||
nassertv_always(_states.remove(this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1849,8 +1829,6 @@ update_pstats(int old_referenced_bits, int new_referenced_bits) {
|
||||
*/
|
||||
void RenderState::
|
||||
init_states() {
|
||||
_states = new States;
|
||||
|
||||
// TODO: we should have a global Panda mutex to allow us to safely create
|
||||
// _states_lock without a startup race condition. For the meantime, this is
|
||||
// OK because we guarantee that this method is called at static init time,
|
||||
@ -1863,7 +1841,7 @@ init_states() {
|
||||
// is declared globally, and lives forever.
|
||||
RenderState *state = new RenderState;
|
||||
state->local_object();
|
||||
state->_saved_entry = _states->store(state, nullptr);
|
||||
state->_saved_entry = _states.store(state, nullptr);
|
||||
_empty_state = state;
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ private:
|
||||
// _invert_composition_cache.
|
||||
static LightReMutex *_states_lock;
|
||||
typedef SimpleHashMap<const RenderState *, std::nullptr_t, indirect_compare_to_hash<const RenderState *> > States;
|
||||
static States *_states;
|
||||
static States _states;
|
||||
static const RenderState *_empty_state;
|
||||
|
||||
// This iterator records the entry corresponding to this RenderState object
|
||||
|
@ -118,18 +118,15 @@ get_invert_composition_cache() const {
|
||||
PyObject *Extension<RenderState>::
|
||||
get_states() {
|
||||
extern struct Dtool_PyTypedObject Dtool_RenderState;
|
||||
if (RenderState::_states == nullptr) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
LightReMutexHolder holder(*RenderState::_states_lock);
|
||||
|
||||
size_t num_states = RenderState::_states->get_num_entries();
|
||||
size_t num_states = RenderState::_states.get_num_entries();
|
||||
PyObject *list = PyList_New(num_states);
|
||||
size_t i = 0;
|
||||
|
||||
size_t size = RenderState::_states->get_num_entries();
|
||||
size_t size = RenderState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = RenderState::_states->get_key(si);
|
||||
const RenderState *state = RenderState::_states.get_key(si);
|
||||
state->ref();
|
||||
PyObject *a =
|
||||
DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState,
|
||||
@ -142,6 +139,4 @@ get_states() {
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
@ -27,7 +27,7 @@
|
||||
using std::ostream;
|
||||
|
||||
LightReMutex *TransformState::_states_lock = nullptr;
|
||||
TransformState::States *TransformState::_states = nullptr;
|
||||
TransformState::States TransformState::_states;
|
||||
CPT(TransformState) TransformState::_identity_state;
|
||||
CPT(TransformState) TransformState::_invalid_state;
|
||||
UpdateSeq TransformState::_last_cycle_detect;
|
||||
@ -57,7 +57,7 @@ TypeHandle TransformState::_type_handle;
|
||||
*/
|
||||
TransformState::
|
||||
TransformState() : _lock("TransformState") {
|
||||
if (_states == nullptr) {
|
||||
if (_states_lock == nullptr) {
|
||||
init_states();
|
||||
}
|
||||
_saved_entry = -1;
|
||||
@ -988,11 +988,8 @@ write_composition_cache(ostream &out, int indent_level) const {
|
||||
*/
|
||||
int TransformState::
|
||||
get_num_states() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
return _states->get_num_entries();
|
||||
return _states.get_num_entries();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1010,9 +1007,6 @@ get_num_states() {
|
||||
*/
|
||||
int TransformState::
|
||||
get_num_unused_states() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
// First, we need to count the number of times each TransformState object is
|
||||
@ -1021,9 +1015,9 @@ get_num_unused_states() {
|
||||
typedef pmap<const TransformState *, int> StateCount;
|
||||
StateCount state_count;
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = _states->get_key(si);
|
||||
const TransformState *state = _states.get_key(si);
|
||||
|
||||
size_t i;
|
||||
size_t cache_size = state->_composition_cache.get_num_entries();
|
||||
@ -1095,13 +1089,10 @@ get_num_unused_states() {
|
||||
*/
|
||||
int TransformState::
|
||||
clear_cache() {
|
||||
if (_states == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
PStatTimer timer(_cache_update_pcollector);
|
||||
int orig_size = _states->get_num_entries();
|
||||
int orig_size = _states.get_num_entries();
|
||||
|
||||
// First, we need to copy the entire set of states to a temporary vector,
|
||||
// reference-counting each object. That way we can walk through the copy,
|
||||
@ -1112,9 +1103,9 @@ clear_cache() {
|
||||
TempStates temp_states;
|
||||
temp_states.reserve(orig_size);
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = _states->get_key(si);
|
||||
const TransformState *state = _states.get_key(si);
|
||||
temp_states.push_back(state);
|
||||
}
|
||||
|
||||
@ -1153,7 +1144,7 @@ clear_cache() {
|
||||
// the various objects' caches will go away.
|
||||
}
|
||||
|
||||
int new_size = _states->get_num_entries();
|
||||
int new_size = _states.get_num_entries();
|
||||
return orig_size - new_size;
|
||||
}
|
||||
|
||||
@ -1165,14 +1156,14 @@ clear_cache() {
|
||||
*/
|
||||
int TransformState::
|
||||
garbage_collect() {
|
||||
if (_states == nullptr || !garbage_collect_states) {
|
||||
if (!garbage_collect_states) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
PStatTimer timer(_garbage_collect_pcollector);
|
||||
size_t orig_size = _states->get_num_entries();
|
||||
size_t orig_size = _states.get_num_entries();
|
||||
|
||||
// How many elements to process this pass?
|
||||
size_t size = orig_size;
|
||||
@ -1192,7 +1183,7 @@ garbage_collect() {
|
||||
size_t stop_at_element = (si + num_this_pass) % size;
|
||||
|
||||
do {
|
||||
TransformState *state = (TransformState *)_states->get_key(si);
|
||||
TransformState *state = (TransformState *)_states.get_key(si);
|
||||
if (break_and_uniquify) {
|
||||
if (state->get_cache_ref_count() > 0 &&
|
||||
state->get_ref_count() == state->get_cache_ref_count()) {
|
||||
@ -1229,15 +1220,15 @@ garbage_collect() {
|
||||
} while (si != stop_at_element);
|
||||
_garbage_index = si;
|
||||
|
||||
nassertr(_states->get_num_entries() == size, 0);
|
||||
nassertr(_states.get_num_entries() == size, 0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertr(_states->validate(), 0);
|
||||
nassertr(_states.validate(), 0);
|
||||
#endif
|
||||
|
||||
// If we just cleaned up a lot of states, see if we can reduce the table in
|
||||
// size. This will help reduce iteration overhead in the future.
|
||||
_states->consider_shrink_table();
|
||||
_states.consider_shrink_table();
|
||||
|
||||
return (int)orig_size - (int)size;
|
||||
}
|
||||
@ -1257,18 +1248,15 @@ garbage_collect() {
|
||||
*/
|
||||
void TransformState::
|
||||
list_cycles(ostream &out) {
|
||||
if (_states == nullptr) {
|
||||
return;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
typedef pset<const TransformState *> VisitedStates;
|
||||
VisitedStates visited;
|
||||
CompositionCycleDesc cycle_desc;
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = _states->get_key(si);
|
||||
const TransformState *state = _states.get_key(si);
|
||||
|
||||
bool inserted = visited.insert(state).second;
|
||||
if (inserted) {
|
||||
@ -1334,16 +1322,12 @@ list_cycles(ostream &out) {
|
||||
*/
|
||||
void TransformState::
|
||||
list_states(ostream &out) {
|
||||
if (_states == nullptr) {
|
||||
out << "0 states:\n";
|
||||
return;
|
||||
}
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
out << size << " states:\n";
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = _states->get_key(si);
|
||||
const TransformState *state = _states.get_key(si);
|
||||
state->write(out, 2);
|
||||
}
|
||||
}
|
||||
@ -1356,36 +1340,32 @@ list_states(ostream &out) {
|
||||
*/
|
||||
bool TransformState::
|
||||
validate_states() {
|
||||
if (_states == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PStatTimer timer(_transform_validate_pcollector);
|
||||
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
if (_states->is_empty()) {
|
||||
if (_states.is_empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_states->validate()) {
|
||||
if (!_states.validate()) {
|
||||
pgraph_cat.error()
|
||||
<< "TransformState::_states cache is invalid!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = _states->get_num_entries();
|
||||
size_t size = _states.get_num_entries();
|
||||
size_t si = 0;
|
||||
nassertr(si < size, false);
|
||||
nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
|
||||
nassertr(_states.get_key(si)->get_ref_count() >= 0, false);
|
||||
size_t snext = si;
|
||||
++snext;
|
||||
while (snext < size) {
|
||||
nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
|
||||
const TransformState *ssi = _states->get_key(si);
|
||||
nassertr(_states.get_key(snext)->get_ref_count() >= 0, false);
|
||||
const TransformState *ssi = _states.get_key(si);
|
||||
if (!ssi->validate_composition_cache()) {
|
||||
return false;
|
||||
}
|
||||
const TransformState *ssnext = _states->get_key(snext);
|
||||
const TransformState *ssnext = _states.get_key(snext);
|
||||
bool c = (*ssi) == (*ssnext);
|
||||
bool ci = (*ssnext) == (*ssi);
|
||||
if (c != ci) {
|
||||
@ -1415,8 +1395,6 @@ validate_states() {
|
||||
*/
|
||||
void TransformState::
|
||||
init_states() {
|
||||
_states = new States;
|
||||
|
||||
ConfigVariableBool uniquify_matrix
|
||||
("uniquify-matrix", true,
|
||||
PRC_DESC("Set this true to look up arbitrary 4x4 transform matrices in "
|
||||
@ -1483,7 +1461,7 @@ return_unique(TransformState *state) {
|
||||
LightReMutexHolder holder(*_states_lock);
|
||||
|
||||
if (state->_saved_entry != -1) {
|
||||
// This state is already in the cache. nassertr(_states->find(state) ==
|
||||
// This state is already in the cache. nassertr(_states.find(state) ==
|
||||
// state->_saved_entry, state);
|
||||
return state;
|
||||
}
|
||||
@ -1492,10 +1470,10 @@ return_unique(TransformState *state) {
|
||||
// of this function if no one else uses it.
|
||||
CPT(TransformState) pt_state = state;
|
||||
|
||||
int si = _states->find(state);
|
||||
int si = _states.find(state);
|
||||
if (si != -1) {
|
||||
// There's an equivalent state already in the set. Return it.
|
||||
return _states->get_key(si);
|
||||
return _states.get_key(si);
|
||||
}
|
||||
|
||||
// Not already in the set; add it.
|
||||
@ -1505,7 +1483,7 @@ return_unique(TransformState *state) {
|
||||
// deleted while it's in it.
|
||||
state->cache_ref();
|
||||
}
|
||||
si = _states->store(state, nullptr);
|
||||
si = _states.store(state, nullptr);
|
||||
|
||||
// Save the index and return the input state.
|
||||
state->_saved_entry = si;
|
||||
@ -1893,7 +1871,7 @@ release_new() {
|
||||
|
||||
if (_saved_entry != -1) {
|
||||
_saved_entry = -1;
|
||||
nassertv_always(_states->remove(this));
|
||||
nassertv_always(_states.remove(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ private:
|
||||
// _invert_composition_cache.
|
||||
static LightReMutex *_states_lock;
|
||||
typedef SimpleHashMap<const TransformState *, std::nullptr_t, indirect_equals_hash<const TransformState *> > States;
|
||||
static States *_states;
|
||||
static States _states;
|
||||
static CPT(TransformState) _identity_state;
|
||||
static CPT(TransformState) _invalid_state;
|
||||
|
||||
|
@ -132,18 +132,15 @@ get_invert_composition_cache() const {
|
||||
PyObject *Extension<TransformState>::
|
||||
get_states() {
|
||||
extern struct Dtool_PyTypedObject Dtool_TransformState;
|
||||
if (TransformState::_states == nullptr) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
LightReMutexHolder holder(*TransformState::_states_lock);
|
||||
|
||||
size_t num_states = TransformState::_states->get_num_entries();
|
||||
size_t num_states = TransformState::_states.get_num_entries();
|
||||
PyObject *list = PyList_New(num_states);
|
||||
size_t i = 0;
|
||||
|
||||
size_t size = TransformState::_states->get_num_entries();
|
||||
size_t size = TransformState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = TransformState::_states->get_key(si);
|
||||
const TransformState *state = TransformState::_states.get_key(si);
|
||||
state->ref();
|
||||
PyObject *a =
|
||||
DTool_CreatePyInstanceTyped((void *)state, Dtool_TransformState,
|
||||
@ -163,15 +160,12 @@ get_states() {
|
||||
PyObject *Extension<TransformState>::
|
||||
get_unused_states() {
|
||||
extern struct Dtool_PyTypedObject Dtool_TransformState;
|
||||
if (TransformState::_states == nullptr) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
LightReMutexHolder holder(*TransformState::_states_lock);
|
||||
|
||||
PyObject *list = PyList_New(0);
|
||||
size_t size = TransformState::_states->get_num_entries();
|
||||
size_t size = TransformState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const TransformState *state = TransformState::_states->get_key(si);
|
||||
const TransformState *state = TransformState::_states.get_key(si);
|
||||
if (state->get_cache_ref_count() == state->get_ref_count()) {
|
||||
state->ref();
|
||||
PyObject *a =
|
||||
|
@ -580,9 +580,9 @@ rehash_generated_shaders() {
|
||||
|
||||
// With uniquify-states turned on, we can actually go through all the states
|
||||
// and check whether their generated shader is still OK.
|
||||
size_t size = RenderState::_states->get_num_entries();
|
||||
size_t size = RenderState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = RenderState::_states->get_key(si);
|
||||
const RenderState *state = RenderState::_states.get_key(si);
|
||||
|
||||
if (state->_generated_shader != nullptr) {
|
||||
ShaderKey key;
|
||||
@ -619,9 +619,9 @@ void ShaderGenerator::
|
||||
clear_generated_shaders() {
|
||||
LightReMutexHolder holder(*RenderState::_states_lock);
|
||||
|
||||
size_t size = RenderState::_states->get_num_entries();
|
||||
size_t size = RenderState::_states.get_num_entries();
|
||||
for (size_t si = 0; si < size; ++si) {
|
||||
const RenderState *state = RenderState::_states->get_key(si);
|
||||
const RenderState *state = RenderState::_states.get_key(si);
|
||||
state->_generated_shader.clear();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user