mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
fix cache in threaded pipeline
This commit is contained in:
parent
4e4302b308
commit
2bb5462a4c
@ -137,7 +137,7 @@ modify_primitive(int i) {
|
|||||||
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
|
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
|
||||||
cdata->_got_usage_hint = false;
|
cdata->_got_usage_hint = false;
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
if (cdata->_primitives[i]->get_ref_count() > 1) {
|
if (cdata->_primitives[i]->get_ref_count() > 1) {
|
||||||
cdata->_primitives[i] = cdata->_primitives[i]->make_copy();
|
cdata->_primitives[i] = cdata->_primitives[i]->make_copy();
|
||||||
}
|
}
|
||||||
@ -320,17 +320,73 @@ mark_internal_bounds_stale(CData *cdata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Geom::CacheEntry::Constructor
|
// Function: Geom::CDataCache::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE Geom::CDataCache::
|
||||||
|
CDataCache() :
|
||||||
|
_source(NULL),
|
||||||
|
_geom_result(NULL),
|
||||||
|
_data_result(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::CDataCache::Copy Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE Geom::CDataCache::
|
||||||
|
CDataCache(const Geom::CDataCache ©) :
|
||||||
|
_source(copy._source),
|
||||||
|
_geom_result(copy._geom_result),
|
||||||
|
_data_result(copy._data_result)
|
||||||
|
{
|
||||||
|
if (_geom_result != _source && _geom_result != (Geom *)NULL) {
|
||||||
|
_geom_result->ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::CDataCache::set_result
|
||||||
|
// Access: Public
|
||||||
|
// Description: Stores the geom_result and data_result on the cache,
|
||||||
|
// upping and/or dropping the reference count
|
||||||
|
// appropriately.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void Geom::CDataCache::
|
||||||
|
set_result(const Geom *geom_result, const GeomVertexData *data_result) {
|
||||||
|
if (geom_result != _geom_result) {
|
||||||
|
if (_geom_result != _source && _geom_result != (Geom *)NULL) {
|
||||||
|
unref_delete(_geom_result);
|
||||||
|
}
|
||||||
|
_geom_result = geom_result;
|
||||||
|
if (_geom_result != _source && _geom_result != (Geom *)NULL) {
|
||||||
|
_geom_result->ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_data_result = data_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::CacheEntry::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description: This constructor makes an invalid CacheEntry that
|
||||||
|
// holds no data. CacheEntries like this are normally
|
||||||
|
// not stored in the cache; this is usually used as a
|
||||||
|
// key to find an existing (valid) CacheEntry already in
|
||||||
|
// the cache.
|
||||||
|
//
|
||||||
|
// However, it is possible for an empty CacheEntry to
|
||||||
|
// end up in the cache if its data gets cleared by
|
||||||
|
// clear_cache_stage().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE Geom::CacheEntry::
|
INLINE Geom::CacheEntry::
|
||||||
CacheEntry(const GeomVertexData *source_data, const GeomMunger *modifier) :
|
CacheEntry(const GeomVertexData *source_data, const GeomMunger *modifier) :
|
||||||
_source(NULL),
|
_source(NULL),
|
||||||
_source_data(source_data),
|
_source_data(source_data),
|
||||||
_modifier(modifier),
|
_modifier(modifier)
|
||||||
_geom_result(NULL),
|
|
||||||
_data_result(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,17 +397,11 @@ CacheEntry(const GeomVertexData *source_data, const GeomMunger *modifier) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE Geom::CacheEntry::
|
INLINE Geom::CacheEntry::
|
||||||
CacheEntry(Geom *source, const GeomVertexData *source_data,
|
CacheEntry(Geom *source, const GeomVertexData *source_data,
|
||||||
const GeomMunger *modifier, const Geom *geom_result,
|
const GeomMunger *modifier) :
|
||||||
const GeomVertexData *data_result) :
|
|
||||||
_source(source),
|
_source(source),
|
||||||
_source_data(source_data),
|
_source_data(source_data),
|
||||||
_modifier(modifier),
|
_modifier(modifier)
|
||||||
_geom_result(geom_result),
|
|
||||||
_data_result(data_result)
|
|
||||||
{
|
{
|
||||||
if (_geom_result != _source) {
|
|
||||||
_geom_result->ref();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -64,11 +64,7 @@ void Geom::
|
|||||||
operator = (const Geom ©) {
|
operator = (const Geom ©) {
|
||||||
TypedWritableReferenceCount::operator = (copy);
|
TypedWritableReferenceCount::operator = (copy);
|
||||||
|
|
||||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
clear_cache();
|
||||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
|
||||||
do_clear_cache(cdata);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
|
||||||
|
|
||||||
_cycler = copy._cycler;
|
_cycler = copy._cycler;
|
||||||
|
|
||||||
@ -86,15 +82,7 @@ operator = (const Geom ©) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
Geom::
|
Geom::
|
||||||
~Geom() {
|
~Geom() {
|
||||||
// When we destruct, we should ensure that all of our cached
|
clear_cache();
|
||||||
// entries, across all pipeline stages, are properly removed from
|
|
||||||
// the cache manager.
|
|
||||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
|
||||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
|
||||||
do_clear_cache(cdata);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
|
||||||
|
|
||||||
release_all();
|
release_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +123,7 @@ set_usage_hint(Geom::UsageHint usage_hint) {
|
|||||||
(*pi)->set_usage_hint(usage_hint);
|
(*pi)->set_usage_hint(usage_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +147,7 @@ modify_vertex_data() {
|
|||||||
if (cdata->_data->get_ref_count() > 1) {
|
if (cdata->_data->get_ref_count() > 1) {
|
||||||
cdata->_data = new GeomVertexData(*cdata->_data);
|
cdata->_data = new GeomVertexData(*cdata->_data);
|
||||||
}
|
}
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
mark_internal_bounds_stale(cdata);
|
mark_internal_bounds_stale(cdata);
|
||||||
return cdata->_data;
|
return cdata->_data;
|
||||||
}
|
}
|
||||||
@ -179,7 +167,7 @@ set_vertex_data(const GeomVertexData *data) {
|
|||||||
nassertv(check_will_be_valid(data));
|
nassertv(check_will_be_valid(data));
|
||||||
CDWriter cdata(_cycler, true);
|
CDWriter cdata(_cycler, true);
|
||||||
cdata->_data = (GeomVertexData *)data;
|
cdata->_data = (GeomVertexData *)data;
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
mark_internal_bounds_stale(cdata);
|
mark_internal_bounds_stale(cdata);
|
||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
}
|
}
|
||||||
@ -222,7 +210,7 @@ offset_vertices(const GeomVertexData *data, int offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
nassertv(all_is_valid);
|
nassertv(all_is_valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +278,7 @@ make_nonindexed(bool composite_only) {
|
|||||||
cdata->_data = new_data;
|
cdata->_data = new_data;
|
||||||
cdata->_primitives.swap(new_prims);
|
cdata->_primitives.swap(new_prims);
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_changed;
|
return num_changed;
|
||||||
@ -335,7 +323,7 @@ set_primitive(int i, const GeomPrimitive *primitive) {
|
|||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
cdata->_got_usage_hint = false;
|
cdata->_got_usage_hint = false;
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -379,7 +367,7 @@ add_primitive(const GeomPrimitive *primitive) {
|
|||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
cdata->_got_usage_hint = false;
|
cdata->_got_usage_hint = false;
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -403,7 +391,7 @@ remove_primitive(int i) {
|
|||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
cdata->_got_usage_hint = false;
|
cdata->_got_usage_hint = false;
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -425,7 +413,7 @@ clear_primitives() {
|
|||||||
cdata->_primitive_type = PT_none;
|
cdata->_primitive_type = PT_none;
|
||||||
cdata->_shade_model = SM_uniform;
|
cdata->_shade_model = SM_uniform;
|
||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -460,7 +448,7 @@ decompose_in_place() {
|
|||||||
|
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
|
|
||||||
nassertv(all_is_valid);
|
nassertv(all_is_valid);
|
||||||
}
|
}
|
||||||
@ -496,7 +484,7 @@ rotate_in_place() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
|
|
||||||
nassertv(all_is_valid);
|
nassertv(all_is_valid);
|
||||||
}
|
}
|
||||||
@ -568,7 +556,7 @@ unify_in_place() {
|
|||||||
cdata->_primitives.push_back(new_prim);
|
cdata->_primitives.push_back(new_prim);
|
||||||
|
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
reset_geom_rendering(cdata);
|
reset_geom_rendering(cdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,14 +790,42 @@ write(ostream &out, int indent_level) const {
|
|||||||
// Description: Removes all of the previously-cached results of
|
// Description: Removes all of the previously-cached results of
|
||||||
// munge_geom().
|
// munge_geom().
|
||||||
//
|
//
|
||||||
|
// This blows away the entire cache, upstream and
|
||||||
|
// downstream the pipeline. Use clear_cache_stage()
|
||||||
|
// instead if you only want to blow away the cache at
|
||||||
|
// the current stage and upstream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void Geom::
|
||||||
|
clear_cache() {
|
||||||
|
for (Cache::iterator ci = _cache.begin();
|
||||||
|
ci != _cache.end();
|
||||||
|
++ci) {
|
||||||
|
CacheEntry *entry = (*ci);
|
||||||
|
entry->erase();
|
||||||
|
}
|
||||||
|
_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::clear_cache_stage
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes all of the previously-cached results of
|
||||||
|
// munge_geom(), at the current pipeline stage and
|
||||||
|
// upstream. Does not affect the downstream cache.
|
||||||
|
//
|
||||||
// Don't call this in a downstream thread unless you
|
// Don't call this in a downstream thread unless you
|
||||||
// don't mind it blowing away other changes you might
|
// don't mind it blowing away other changes you might
|
||||||
// have recently made in an upstream thread.
|
// have recently made in an upstream thread.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void Geom::
|
void Geom::
|
||||||
clear_cache() {
|
clear_cache_stage() {
|
||||||
CDWriter cdata(_cycler, true);
|
for (Cache::iterator ci = _cache.begin();
|
||||||
do_clear_cache(cdata);
|
ci != _cache.end();
|
||||||
|
++ci) {
|
||||||
|
CacheEntry *entry = (*ci);
|
||||||
|
CDCacheWriter cdata(entry->_cycler);
|
||||||
|
cdata->set_result(NULL, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1061,22 +1077,6 @@ check_will_be_valid(const GeomVertexData *vertex_data) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: Geom::do_clear_cache
|
|
||||||
// Access: Private
|
|
||||||
// Description: The private implementation of clear_cache().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void Geom::
|
|
||||||
do_clear_cache(Geom::CData *cdata) {
|
|
||||||
for (Cache::iterator ci = cdata->_cache.begin();
|
|
||||||
ci != cdata->_cache.end();
|
|
||||||
++ci) {
|
|
||||||
CacheEntry *entry = (*ci);
|
|
||||||
entry->erase();
|
|
||||||
}
|
|
||||||
cdata->_cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Geom::do_draw
|
// Function: Geom::do_draw
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -1238,15 +1238,23 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Geom::CacheEntry::Destructor
|
// Function: Geom::CDataCache::Destructor
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
Geom::CacheEntry::
|
Geom::CDataCache::
|
||||||
~CacheEntry() {
|
~CDataCache() {
|
||||||
if (_geom_result != _source) {
|
set_result(NULL, NULL);
|
||||||
unref_delete(_geom_result);
|
}
|
||||||
}
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Geom::CDataCache::make_copy
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CycleData *Geom::CDataCache::
|
||||||
|
make_copy() const {
|
||||||
|
return new CDataCache(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1257,13 +1265,10 @@ Geom::CacheEntry::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void Geom::CacheEntry::
|
void Geom::CacheEntry::
|
||||||
evict_callback() {
|
evict_callback() {
|
||||||
OPEN_ITERATE_ALL_STAGES(_source->_cycler) {
|
Cache::iterator ci = _source->_cache.find(this);
|
||||||
CDStageWriter cdata(_source->_cycler, pipeline_stage);
|
nassertv(ci != _source->_cache.end());
|
||||||
// Because of the multistage pipeline, we might not actually have
|
nassertv((*ci) == this);
|
||||||
// a cache entry at every stage. No big deal if we don't.
|
_source->_cache.erase(ci);
|
||||||
cdata->_cache.erase(this);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_source->_cycler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -111,6 +111,7 @@ PUBLISHED:
|
|||||||
virtual void write(ostream &out, int indent_level = 0) const;
|
virtual void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
void clear_cache();
|
void clear_cache();
|
||||||
|
void clear_cache_stage();
|
||||||
|
|
||||||
void prepare(PreparedGraphicsObjects *prepared_objects);
|
void prepare(PreparedGraphicsObjects *prepared_objects);
|
||||||
bool release(PreparedGraphicsObjects *prepared_objects);
|
bool release(PreparedGraphicsObjects *prepared_objects);
|
||||||
@ -152,7 +153,6 @@ private:
|
|||||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||||
bool check_will_be_valid(const GeomVertexData *vertex_data) const;
|
bool check_will_be_valid(const GeomVertexData *vertex_data) const;
|
||||||
|
|
||||||
void do_clear_cache(CData *cdata);
|
|
||||||
void do_draw(GraphicsStateGuardianBase *gsg,
|
void do_draw(GraphicsStateGuardianBase *gsg,
|
||||||
const GeomMunger *munger,
|
const GeomMunger *munger,
|
||||||
const GeomVertexData *vertex_data,
|
const GeomVertexData *vertex_data,
|
||||||
@ -169,26 +169,49 @@ private:
|
|||||||
// cache needs to be stored in the CycleData, which makes accurate
|
// cache needs to be stored in the CycleData, which makes accurate
|
||||||
// cleanup more difficult. We use the GeomCacheManager class to
|
// cleanup more difficult. We use the GeomCacheManager class to
|
||||||
// avoid cache bloat.
|
// avoid cache bloat.
|
||||||
|
|
||||||
|
// Note: the above comment is no longer true. The cache is not
|
||||||
|
// stored in the CycleData, which just causes problems; instead, we
|
||||||
|
// cycle each individual CacheEntry as needed. Need to investigate
|
||||||
|
// if we could simplify the cache system now.
|
||||||
|
|
||||||
|
// The pipelined data with each CacheEntry.
|
||||||
|
class CDataCache : public CycleData {
|
||||||
|
public:
|
||||||
|
INLINE CDataCache();
|
||||||
|
INLINE CDataCache(const CDataCache ©);
|
||||||
|
virtual ~CDataCache();
|
||||||
|
virtual CycleData *make_copy() const;
|
||||||
|
virtual TypeHandle get_parent_type() const {
|
||||||
|
return Geom::get_class_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void set_result(const Geom *geom_result, const GeomVertexData *data_result);
|
||||||
|
|
||||||
|
Geom *_source; // A back pointer to the containing Geom
|
||||||
|
const Geom *_geom_result; // ref-counted if not NULL and not same as _source
|
||||||
|
CPT(GeomVertexData) _data_result;
|
||||||
|
};
|
||||||
|
typedef CycleDataReader<CDataCache> CDCacheReader;
|
||||||
|
typedef CycleDataWriter<CDataCache> CDCacheWriter;
|
||||||
|
|
||||||
class CacheEntry : public GeomCacheEntry {
|
class CacheEntry : public GeomCacheEntry {
|
||||||
public:
|
public:
|
||||||
INLINE CacheEntry(const GeomVertexData *source_data,
|
INLINE CacheEntry(const GeomVertexData *source_data,
|
||||||
const GeomMunger *modifier);
|
const GeomMunger *modifier);
|
||||||
INLINE CacheEntry(Geom *source,
|
INLINE CacheEntry(Geom *source,
|
||||||
const GeomVertexData *source_data,
|
const GeomVertexData *source_data,
|
||||||
const GeomMunger *modifier,
|
const GeomMunger *modifier);
|
||||||
const Geom *geom_result,
|
|
||||||
const GeomVertexData *data_result);
|
|
||||||
virtual ~CacheEntry();
|
|
||||||
INLINE bool operator < (const CacheEntry &other) const;
|
INLINE bool operator < (const CacheEntry &other) const;
|
||||||
|
|
||||||
virtual void evict_callback();
|
virtual void evict_callback();
|
||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
Geom *_source;
|
Geom *_source; // A back pointer to the containing Geom
|
||||||
CPT(GeomVertexData) _source_data;
|
CPT(GeomVertexData) _source_data;
|
||||||
CPT(GeomMunger) _modifier;
|
CPT(GeomMunger) _modifier;
|
||||||
const Geom *_geom_result; // ref-counted if not same as _source
|
|
||||||
CPT(GeomVertexData) _data_result;
|
PipelineCycler<CDataCache> _cycler;
|
||||||
};
|
};
|
||||||
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
||||||
|
|
||||||
@ -213,7 +236,6 @@ private:
|
|||||||
UsageHint _usage_hint;
|
UsageHint _usage_hint;
|
||||||
bool _got_usage_hint;
|
bool _got_usage_hint;
|
||||||
UpdateSeq _modified;
|
UpdateSeq _modified;
|
||||||
Cache _cache;
|
|
||||||
|
|
||||||
CPT(BoundingVolume) _internal_bounds;
|
CPT(BoundingVolume) _internal_bounds;
|
||||||
bool _internal_bounds_stale;
|
bool _internal_bounds_stale;
|
||||||
@ -226,6 +248,8 @@ private:
|
|||||||
typedef CycleDataStageReader<CData> CDStageReader;
|
typedef CycleDataStageReader<CData> CDStageReader;
|
||||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||||
|
|
||||||
|
Cache _cache;
|
||||||
|
|
||||||
// This works just like the Texture contexts: each Geom keeps a
|
// This works just like the Texture contexts: each Geom keeps a
|
||||||
// record of all the PGO objects that hold the Geom, and vice-versa.
|
// record of all the PGO objects that hold the Geom, and vice-versa.
|
||||||
typedef pmap<PreparedGraphicsObjects *, GeomContext *> Contexts;
|
typedef pmap<PreparedGraphicsObjects *, GeomContext *> Contexts;
|
||||||
|
@ -109,35 +109,37 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data) {
|
|||||||
|
|
||||||
// Look up the munger in the geom's cache--maybe we've recently
|
// Look up the munger in the geom's cache--maybe we've recently
|
||||||
// applied it.
|
// applied it.
|
||||||
{
|
PT(Geom::CacheEntry) entry;
|
||||||
Geom::CDReader cdata(geom->_cycler);
|
|
||||||
Geom::CacheEntry temp_entry(source_data, this);
|
Geom::CacheEntry temp_entry(source_data, this);
|
||||||
temp_entry.local_object();
|
temp_entry.local_object();
|
||||||
Geom::Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
|
Geom::Cache::const_iterator ci = geom->_cache.find(&temp_entry);
|
||||||
if (ci != cdata->_cache.end()) {
|
if (ci != geom->_cache.end()) {
|
||||||
Geom::CacheEntry *entry = (*ci);
|
entry = (*ci);
|
||||||
|
nassertv(entry->_source == geom);
|
||||||
|
|
||||||
if (geom->get_modified() <= entry->_geom_result->get_modified() &&
|
// Here's an element in the cache for this computation. Record a
|
||||||
data->get_modified() <= entry->_data_result->get_modified()) {
|
// cache hit, so this element will stay in the cache a while
|
||||||
|
// longer.
|
||||||
|
entry->refresh();
|
||||||
|
|
||||||
|
// Now check that it's fresh.
|
||||||
|
Geom::CDCacheReader cdata(entry->_cycler);
|
||||||
|
nassertv(cdata->_source == geom);
|
||||||
|
if (cdata->_geom_result != (Geom *)NULL &&
|
||||||
|
geom->get_modified() <= cdata->_geom_result->get_modified() &&
|
||||||
|
data->get_modified() <= cdata->_data_result->get_modified()) {
|
||||||
// The cache entry is still good; use it.
|
// The cache entry is still good; use it.
|
||||||
|
|
||||||
// Record a cache hit, so this element will stay in the cache a
|
geom = cdata->_geom_result;
|
||||||
// while longer.
|
data = cdata->_data_result;
|
||||||
entry->refresh();
|
|
||||||
geom = entry->_geom_result;
|
|
||||||
data = entry->_data_result;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The cache entry is stale, remove it.
|
// The cache entry is stale, but we'll recompute it below. Note
|
||||||
if (gobj_cat.is_debug()) {
|
// that there's a small race condition here; another thread might
|
||||||
gobj_cat.debug()
|
// recompute the cache at the same time. No big deal, since it'll
|
||||||
<< "Cache entry " << *entry << " is stale, removing.\n";
|
// compute the same result.
|
||||||
}
|
|
||||||
entry->erase();
|
|
||||||
Geom::CDWriter cdataw(((Geom *)geom.p())->_cycler, cdata);
|
|
||||||
cdataw->_cache.erase(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, invoke the munger.
|
// Ok, invoke the munger.
|
||||||
@ -147,22 +149,23 @@ munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data) {
|
|||||||
data = munge_data(data);
|
data = munge_data(data);
|
||||||
munge_geom_impl(geom, data);
|
munge_geom_impl(geom, data);
|
||||||
|
|
||||||
{
|
|
||||||
// Record the new result in the cache.
|
// Record the new result in the cache.
|
||||||
Geom::CacheEntry *entry;
|
if (entry == (Geom::CacheEntry *)NULL) {
|
||||||
{
|
// Create a new entry for the result.
|
||||||
Geom::CDWriter cdata(((Geom *)orig_geom.p())->_cycler);
|
entry = new Geom::CacheEntry((Geom *)orig_geom.p(), source_data, this);
|
||||||
entry = new Geom::CacheEntry((Geom *)orig_geom.p(), source_data, this,
|
bool inserted = ((Geom *)orig_geom.p())->_cache.insert(entry).second;
|
||||||
geom, data);
|
|
||||||
bool inserted = cdata->_cache.insert(entry).second;
|
|
||||||
nassertv(inserted);
|
nassertv(inserted);
|
||||||
}
|
|
||||||
|
|
||||||
// And tell the cache manager about the new entry. (It might
|
// And tell the cache manager about the new entry. (It might
|
||||||
// immediately request a delete from the cache of the thing we
|
// immediately request a delete from the cache of the thing we
|
||||||
// just added.)
|
// just added.)
|
||||||
entry->record();
|
entry->record();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, store the cached result on the entry.
|
||||||
|
Geom::CDCacheWriter cdata(entry->_cycler, true);
|
||||||
|
cdata->_source = (Geom *)orig_geom.p();
|
||||||
|
cdata->set_result(geom, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -238,22 +238,6 @@ get_modified() const {
|
|||||||
return cdata->_modified;
|
return cdata->_modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GeomVertexData::clear_cache
|
|
||||||
// Access: Published
|
|
||||||
// Description: Removes all of the previously-cached results of
|
|
||||||
// convert_to().
|
|
||||||
//
|
|
||||||
// Don't call this in a downstream thread unless you
|
|
||||||
// don't mind it blowing away other changes you might
|
|
||||||
// have recently made in an upstream thread.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE void GeomVertexData::
|
|
||||||
clear_cache() {
|
|
||||||
CDWriter cdata(_cycler, true);
|
|
||||||
do_clear_cache(cdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::has_vertex
|
// Function: GeomVertexData::has_vertex
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -383,15 +367,42 @@ add_transform(TransformTable *table, const VertexTransform *transform,
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::CacheEntry::Constructor
|
// Function: GeomVertexData::CDataCache::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE GeomVertexData::CDataCache::
|
||||||
|
CDataCache() {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::CDataCache::Copy Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE GeomVertexData::CDataCache::
|
||||||
|
CDataCache(const GeomVertexData::CDataCache ©) :
|
||||||
|
_result(copy._result)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::CacheEntry::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description: This constructor makes an invalid CacheEntry that
|
||||||
|
// holds no data. CacheEntries like this are normally
|
||||||
|
// not stored in the cache; this is usually used as a
|
||||||
|
// key to find an existing (valid) CacheEntry already in
|
||||||
|
// the cache.
|
||||||
|
//
|
||||||
|
// However, it is possible for an empty CacheEntry to
|
||||||
|
// end up in the cache if its data gets cleared by
|
||||||
|
// clear_cache_stage().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE GeomVertexData::CacheEntry::
|
INLINE GeomVertexData::CacheEntry::
|
||||||
CacheEntry(const GeomVertexFormat *modifier) :
|
CacheEntry(const GeomVertexFormat *modifier) :
|
||||||
_source(NULL),
|
_source(NULL),
|
||||||
_modifier(modifier),
|
_modifier(modifier)
|
||||||
_result(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,11 +413,9 @@ CacheEntry(const GeomVertexFormat *modifier) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE GeomVertexData::CacheEntry::
|
INLINE GeomVertexData::CacheEntry::
|
||||||
CacheEntry(GeomVertexData *source,
|
CacheEntry(GeomVertexData *source,
|
||||||
const GeomVertexFormat *modifier,
|
const GeomVertexFormat *modifier) :
|
||||||
const GeomVertexData *result) :
|
|
||||||
_source(source),
|
_source(source),
|
||||||
_modifier(modifier),
|
_modifier(modifier)
|
||||||
_result(result)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,11 +154,7 @@ void GeomVertexData::
|
|||||||
operator = (const GeomVertexData ©) {
|
operator = (const GeomVertexData ©) {
|
||||||
TypedWritableReferenceCount::operator = (copy);
|
TypedWritableReferenceCount::operator = (copy);
|
||||||
|
|
||||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
clear_cache();
|
||||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
|
||||||
do_clear_cache(cdata);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
|
||||||
|
|
||||||
_name = copy._name;
|
_name = copy._name;
|
||||||
_format = copy._format;
|
_format = copy._format;
|
||||||
@ -183,14 +179,7 @@ operator = (const GeomVertexData ©) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
GeomVertexData::
|
GeomVertexData::
|
||||||
~GeomVertexData() {
|
~GeomVertexData() {
|
||||||
// When we destruct, we should ensure that all of our cached
|
clear_cache();
|
||||||
// entries, across all pipeline stages, are properly removed from
|
|
||||||
// the cache manager.
|
|
||||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
|
||||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
|
||||||
do_clear_cache(cdata);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -232,7 +221,7 @@ set_usage_hint(GeomVertexData::UsageHint usage_hint) {
|
|||||||
}
|
}
|
||||||
(*ai)->set_usage_hint(usage_hint);
|
(*ai)->set_usage_hint(usage_hint);
|
||||||
}
|
}
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
}
|
}
|
||||||
@ -283,7 +272,7 @@ clear_rows() {
|
|||||||
}
|
}
|
||||||
(*ai)->clear_rows();
|
(*ai)->clear_rows();
|
||||||
}
|
}
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices.clear();
|
cdata->_animated_vertices.clear();
|
||||||
}
|
}
|
||||||
@ -313,7 +302,7 @@ modify_array(int i) {
|
|||||||
if (cdata->_arrays[i]->get_ref_count() > 1) {
|
if (cdata->_arrays[i]->get_ref_count() > 1) {
|
||||||
cdata->_arrays[i] = new GeomVertexArrayData(*cdata->_arrays[i]);
|
cdata->_arrays[i] = new GeomVertexArrayData(*cdata->_arrays[i]);
|
||||||
}
|
}
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
|
|
||||||
@ -337,7 +326,7 @@ set_array(int i, const GeomVertexArrayData *array) {
|
|||||||
CDWriter cdata(_cycler, true);
|
CDWriter cdata(_cycler, true);
|
||||||
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
|
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
|
||||||
cdata->_arrays[i] = (GeomVertexArrayData *)array;
|
cdata->_arrays[i] = (GeomVertexArrayData *)array;
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
}
|
}
|
||||||
@ -361,7 +350,7 @@ set_transform_table(const TransformTable *table) {
|
|||||||
|
|
||||||
CDWriter cdata(_cycler, true);
|
CDWriter cdata(_cycler, true);
|
||||||
cdata->_transform_table = (TransformTable *)table;
|
cdata->_transform_table = (TransformTable *)table;
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
}
|
}
|
||||||
@ -388,7 +377,7 @@ modify_transform_blend_table() {
|
|||||||
if (cdata->_transform_blend_table->get_ref_count() > 1) {
|
if (cdata->_transform_blend_table->get_ref_count() > 1) {
|
||||||
cdata->_transform_blend_table = new TransformBlendTable(*cdata->_transform_blend_table);
|
cdata->_transform_blend_table = new TransformBlendTable(*cdata->_transform_blend_table);
|
||||||
}
|
}
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
|
|
||||||
@ -412,7 +401,7 @@ void GeomVertexData::
|
|||||||
set_transform_blend_table(const TransformBlendTable *table) {
|
set_transform_blend_table(const TransformBlendTable *table) {
|
||||||
CDWriter cdata(_cycler, true);
|
CDWriter cdata(_cycler, true);
|
||||||
cdata->_transform_blend_table = (TransformBlendTable *)table;
|
cdata->_transform_blend_table = (TransformBlendTable *)table;
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
}
|
}
|
||||||
@ -438,7 +427,7 @@ set_slider_table(const SliderTable *table) {
|
|||||||
|
|
||||||
CDWriter cdata(_cycler, true);
|
CDWriter cdata(_cycler, true);
|
||||||
cdata->_slider_table = (SliderTable *)table;
|
cdata->_slider_table = (SliderTable *)table;
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices_modified = UpdateSeq();
|
cdata->_animated_vertices_modified = UpdateSeq();
|
||||||
}
|
}
|
||||||
@ -723,18 +712,29 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||||||
|
|
||||||
// Look up the new format in our cache--maybe we've recently applied
|
// Look up the new format in our cache--maybe we've recently applied
|
||||||
// it.
|
// it.
|
||||||
{
|
PT(CacheEntry) entry;
|
||||||
CDReader cdata(_cycler);
|
|
||||||
CacheEntry temp_entry(new_format);
|
CacheEntry temp_entry(new_format);
|
||||||
temp_entry.local_object();
|
temp_entry.local_object();
|
||||||
Cache::const_iterator ci = cdata->_cache.find(&temp_entry);
|
Cache::const_iterator ci = _cache.find(&temp_entry);
|
||||||
if (ci != cdata->_cache.end()) {
|
if (ci != _cache.end()) {
|
||||||
CacheEntry *entry = (*ci);
|
entry = (*ci);
|
||||||
// Record a cache hit, so this element will stay in the cache a
|
nassertr(entry->_source == this, NULL);
|
||||||
// while longer.
|
|
||||||
|
// Here's an element in the cache for this computation. Record a
|
||||||
|
// cache hit, so this element will stay in the cache a while
|
||||||
|
// longer.
|
||||||
entry->refresh();
|
entry->refresh();
|
||||||
return entry->_result;
|
|
||||||
|
CDCacheReader cdata(entry->_cycler);
|
||||||
|
if (cdata->_result != (GeomVertexData *)NULL) {
|
||||||
|
return cdata->_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The cache entry is stale, but we'll recompute it below. Note
|
||||||
|
// that there's a small race condition here; another thread might
|
||||||
|
// recompute the cache at the same time. No big deal, since it'll
|
||||||
|
// compute the same result.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, convert the data to the new format.
|
// Okay, convert the data to the new format.
|
||||||
@ -752,15 +752,12 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||||||
|
|
||||||
new_data->copy_from(this, false);
|
new_data->copy_from(this, false);
|
||||||
|
|
||||||
{
|
|
||||||
// Record the new result in the cache.
|
// Record the new result in the cache.
|
||||||
CacheEntry *entry;
|
if (entry == (CacheEntry *)NULL) {
|
||||||
{
|
// Create a new entry for the result.
|
||||||
CDWriter cdata(((GeomVertexData *)this)->_cycler, false);
|
entry = new CacheEntry((GeomVertexData *)this, new_format);
|
||||||
entry = new CacheEntry((GeomVertexData *)this, new_format, new_data);
|
bool inserted = ((GeomVertexData *)this)->_cache.insert(entry).second;
|
||||||
bool inserted = cdata->_cache.insert(entry).second;
|
|
||||||
nassertr(inserted, new_data);
|
nassertr(inserted, new_data);
|
||||||
}
|
|
||||||
|
|
||||||
// And tell the cache manager about the new entry. (It might
|
// And tell the cache manager about the new entry. (It might
|
||||||
// immediately request a delete from the cache of the thing we
|
// immediately request a delete from the cache of the thing we
|
||||||
@ -768,6 +765,10 @@ convert_to(const GeomVertexFormat *new_format) const {
|
|||||||
entry->record();
|
entry->record();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, store the cached result on the entry.
|
||||||
|
CDCacheWriter cdata(entry->_cycler, true);
|
||||||
|
cdata->_result = new_data;
|
||||||
|
|
||||||
return new_data;
|
return new_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1119,6 +1120,50 @@ write(ostream &out, int indent_level) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::clear_cache
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes all of the previously-cached results of
|
||||||
|
// convert_to().
|
||||||
|
//
|
||||||
|
// This blows away the entire cache, upstream and
|
||||||
|
// downstream the pipeline. Use clear_cache_stage()
|
||||||
|
// instead if you only want to blow away the cache at
|
||||||
|
// the current stage and upstream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
clear_cache() {
|
||||||
|
for (Cache::iterator ci = _cache.begin();
|
||||||
|
ci != _cache.end();
|
||||||
|
++ci) {
|
||||||
|
CacheEntry *entry = (*ci);
|
||||||
|
entry->erase();
|
||||||
|
}
|
||||||
|
_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::clear_cache_stage
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes all of the previously-cached results of
|
||||||
|
// convert_to(), at the current pipeline stage and
|
||||||
|
// upstream. Does not affect the downstream cache.
|
||||||
|
//
|
||||||
|
// Don't call this in a downstream thread unless you
|
||||||
|
// don't mind it blowing away other changes you might
|
||||||
|
// have recently made in an upstream thread.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void GeomVertexData::
|
||||||
|
clear_cache_stage() {
|
||||||
|
for (Cache::iterator ci = _cache.begin();
|
||||||
|
ci != _cache.end();
|
||||||
|
++ci) {
|
||||||
|
CacheEntry *entry = (*ci);
|
||||||
|
CDCacheWriter cdata(entry->_cycler);
|
||||||
|
cdata->_result = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::get_array_info
|
// Function: GeomVertexData::get_array_info
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -1354,7 +1399,7 @@ do_set_num_rows(int n, GeomVertexData::CData *cdata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (any_changed) {
|
if (any_changed) {
|
||||||
do_clear_cache(cdata);
|
clear_cache_stage();
|
||||||
cdata->_modified = Geom::get_next_modified();
|
cdata->_modified = Geom::get_next_modified();
|
||||||
cdata->_animated_vertices.clear();
|
cdata->_animated_vertices.clear();
|
||||||
}
|
}
|
||||||
@ -1504,22 +1549,6 @@ update_animated_vertices(GeomVertexData::CData *cdata) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: GeomVertexData::do_clear_cache
|
|
||||||
// Access: Private
|
|
||||||
// Description: The private implementation of clear_cache().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void GeomVertexData::
|
|
||||||
do_clear_cache(GeomVertexData::CData *cdata) {
|
|
||||||
for (Cache::iterator ci = cdata->_cache.begin();
|
|
||||||
ci != cdata->_cache.end();
|
|
||||||
++ci) {
|
|
||||||
CacheEntry *entry = (*ci);
|
|
||||||
entry->erase();
|
|
||||||
}
|
|
||||||
cdata->_cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::register_with_read_factory
|
// Function: GeomVertexData::register_with_read_factory
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
@ -1655,6 +1684,16 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
manager->read_cdata(scan, _cycler);
|
manager->read_cdata(scan, _cycler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: GeomVertexData::CDataCache::make_copy
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CycleData *GeomVertexData::CDataCache::
|
||||||
|
make_copy() const {
|
||||||
|
return new CDataCache(*this);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: GeomVertexData::CacheEntry::evict_callback
|
// Function: GeomVertexData::CacheEntry::evict_callback
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -1663,13 +1702,10 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GeomVertexData::CacheEntry::
|
void GeomVertexData::CacheEntry::
|
||||||
evict_callback() {
|
evict_callback() {
|
||||||
OPEN_ITERATE_ALL_STAGES(_source->_cycler) {
|
Cache::iterator ci = _source->_cache.find(this);
|
||||||
CDStageWriter cdata(_source->_cycler, pipeline_stage);
|
nassertv(ci != _source->_cache.end());
|
||||||
// Because of the multistage pipeline, we might not actually have
|
nassertv((*ci) == this);
|
||||||
// a cache entry at every stage. No big deal if we don't.
|
_source->_cache.erase(ci);
|
||||||
cdata->_cache.erase(this);
|
|
||||||
}
|
|
||||||
CLOSE_ITERATE_ALL_STAGES(_source->_cycler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -144,7 +144,8 @@ PUBLISHED:
|
|||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
INLINE void clear_cache();
|
void clear_cache();
|
||||||
|
void clear_cache_stage();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool get_array_info(const InternalName *name,
|
bool get_array_info(const InternalName *name,
|
||||||
@ -200,20 +201,35 @@ private:
|
|||||||
|
|
||||||
typedef pvector< PT(GeomVertexArrayData) > Arrays;
|
typedef pvector< PT(GeomVertexArrayData) > Arrays;
|
||||||
|
|
||||||
|
// The pipelined data with each CacheEntry.
|
||||||
|
class CDataCache : public CycleData {
|
||||||
|
public:
|
||||||
|
INLINE CDataCache();
|
||||||
|
INLINE CDataCache(const CDataCache ©);
|
||||||
|
virtual CycleData *make_copy() const;
|
||||||
|
virtual TypeHandle get_parent_type() const {
|
||||||
|
return GeomVertexData::get_class_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPT(GeomVertexData) _result;
|
||||||
|
};
|
||||||
|
typedef CycleDataReader<CDataCache> CDCacheReader;
|
||||||
|
typedef CycleDataWriter<CDataCache> CDCacheWriter;
|
||||||
|
|
||||||
class CacheEntry : public GeomCacheEntry {
|
class CacheEntry : public GeomCacheEntry {
|
||||||
public:
|
public:
|
||||||
INLINE CacheEntry(const GeomVertexFormat *modifier);
|
INLINE CacheEntry(const GeomVertexFormat *modifier);
|
||||||
INLINE CacheEntry(GeomVertexData *source,
|
INLINE CacheEntry(GeomVertexData *source,
|
||||||
const GeomVertexFormat *modifier,
|
const GeomVertexFormat *modifier);
|
||||||
const GeomVertexData *result);
|
|
||||||
INLINE bool operator < (const CacheEntry &other) const;
|
INLINE bool operator < (const CacheEntry &other) const;
|
||||||
|
|
||||||
virtual void evict_callback();
|
virtual void evict_callback();
|
||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
|
|
||||||
GeomVertexData *_source;
|
GeomVertexData *_source; // A back pointer to the containing GeomVertexData
|
||||||
CPT(GeomVertexFormat) _modifier;
|
CPT(GeomVertexFormat) _modifier;
|
||||||
CPT(GeomVertexData) _result;
|
|
||||||
|
PipelineCycler<CDataCache> _cycler;
|
||||||
};
|
};
|
||||||
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
typedef pset<PT(CacheEntry), IndirectLess<CacheEntry> > Cache;
|
||||||
|
|
||||||
@ -238,7 +254,6 @@ private:
|
|||||||
PT(GeomVertexData) _animated_vertices;
|
PT(GeomVertexData) _animated_vertices;
|
||||||
UpdateSeq _animated_vertices_modified;
|
UpdateSeq _animated_vertices_modified;
|
||||||
UpdateSeq _modified;
|
UpdateSeq _modified;
|
||||||
Cache _cache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineCycler<CData> _cycler;
|
PipelineCycler<CData> _cycler;
|
||||||
@ -247,10 +262,11 @@ private:
|
|||||||
typedef CycleDataStageReader<CData> CDStageReader;
|
typedef CycleDataStageReader<CData> CDStageReader;
|
||||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||||
|
|
||||||
|
Cache _cache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool do_set_num_rows(int n, CData *cdata);
|
bool do_set_num_rows(int n, CData *cdata);
|
||||||
void update_animated_vertices(CData *cdata);
|
void update_animated_vertices(CData *cdata);
|
||||||
void do_clear_cache(CData *cdata);
|
|
||||||
|
|
||||||
static PStatCollector _convert_pcollector;
|
static PStatCollector _convert_pcollector;
|
||||||
static PStatCollector _scale_color_pcollector;
|
static PStatCollector _scale_color_pcollector;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user