report different types of cyclers in pstats
This commit is contained in:
parent
11337e4c20
commit
7b1b8bb4af
|
|
@ -60,7 +60,7 @@ PStatCollector GraphicsEngine::_transform_states_unused_pcollector("TransformSta
|
|||
PStatCollector GraphicsEngine::_render_states_pcollector("RenderStates");
|
||||
PStatCollector GraphicsEngine::_render_states_unused_pcollector("RenderStates:Unused");
|
||||
PStatCollector GraphicsEngine::_cyclers_pcollector("PipelineCyclers");
|
||||
PStatCollector GraphicsEngine::_dirty_cyclers_pcollector("PipelineCyclers:Dirty");
|
||||
PStatCollector GraphicsEngine::_dirty_cyclers_pcollector("Dirty PipelineCyclers");
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::Constructor
|
||||
|
|
@ -540,10 +540,18 @@ render_frame() {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
#if defined(THREADED_PIPELINE) && defined(DO_PSTATS)
|
||||
_cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
|
||||
_dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
if (PStatClient::is_connected()) {
|
||||
_pipeline->iterate_all_cycler_types(pstats_count_cycler_type, this);
|
||||
_pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type, this);
|
||||
}
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#endif // THREADED_PIPELINE && DO_PSTATS
|
||||
|
||||
// Now cycle the pipeline and officially begin the next frame.
|
||||
{
|
||||
|
|
@ -1458,6 +1466,42 @@ terminate_threads() {
|
|||
_threads.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::pstats_count_cycler_type
|
||||
// Access: Private, Static
|
||||
// Description: A callback function for
|
||||
// Pipeline::iterate_all_cycler_types() to report the
|
||||
// cycler types to PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
pstats_count_cycler_type(TypeHandle type, int count, void *data) {
|
||||
GraphicsEngine *self = (GraphicsEngine *)data;
|
||||
CyclerTypeCounters::iterator ci = self->_all_cycler_types.find(type);
|
||||
if (ci == self->_all_cycler_types.end()) {
|
||||
PStatCollector collector(_cyclers_pcollector, type.get_name());
|
||||
ci = self->_all_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
|
||||
}
|
||||
(*ci).second.set_level(count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::pstats_count_dirty_cycler_type
|
||||
// Access: Private, Static
|
||||
// Description: A callback function for
|
||||
// Pipeline::iterate_dirty_cycler_types() to report the
|
||||
// cycler types to PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsEngine::
|
||||
pstats_count_dirty_cycler_type(TypeHandle type, int count, void *data) {
|
||||
GraphicsEngine *self = (GraphicsEngine *)data;
|
||||
CyclerTypeCounters::iterator ci = self->_dirty_cycler_types.find(type);
|
||||
if (ci == self->_dirty_cycler_types.end()) {
|
||||
PStatCollector collector(_dirty_cyclers_pcollector, type.get_name());
|
||||
ci = self->_dirty_cycler_types.insert(CyclerTypeCounters::value_type(type, collector)).first;
|
||||
}
|
||||
(*ci).second.set_level(count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::get_invert_polygon_state
|
||||
// Access: Protected, Static
|
||||
|
|
@ -1505,11 +1549,12 @@ get_window_renderer(const string &name, int pipeline_stage) {
|
|||
|
||||
PT(RenderThread) thread = new RenderThread(name, this);
|
||||
thread->set_min_pipeline_stage(pipeline_stage);
|
||||
_pipeline->set_min_stages(pipeline_stage + 1);
|
||||
|
||||
thread->start(TP_normal, true, true);
|
||||
_threads[name] = thread;
|
||||
|
||||
nassertr(pipeline_stage < _pipeline->get_num_stages(), thread.p());
|
||||
|
||||
return thread.p();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,14 @@ private:
|
|||
void do_resort_windows();
|
||||
void terminate_threads();
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
typedef map<TypeHandle, PStatCollector> CyclerTypeCounters;
|
||||
CyclerTypeCounters _all_cycler_types;
|
||||
CyclerTypeCounters _dirty_cycler_types;
|
||||
static void pstats_count_cycler_type(TypeHandle type, int count, void *data);
|
||||
static void pstats_count_dirty_cycler_type(TypeHandle type, int count, void *data);
|
||||
#endif // DO_PSTATS
|
||||
|
||||
static const RenderState *get_invert_polygon_state();
|
||||
|
||||
// The WindowRenderer class records the stages of the pipeline that
|
||||
|
|
|
|||
|
|
@ -211,8 +211,8 @@ static LevelCollectorProperties level_properties[] = {
|
|||
{ 1, "RenderStates:On nodes", { 0.2, 0.8, 1.0 } },
|
||||
{ 1, "RenderStates:Cached", { 1.0, 0.0, 0.2 } },
|
||||
{ 1, "RenderStates:Unused", { 0.2, 0.2, 0.2 } },
|
||||
{ 1, "PipelineCyclers", { 0.5, 0.5, 1.0 }, "", 5000 },
|
||||
{ 1, "PipelineCyclers:Dirty", { 0.2, 0.2, 0.2 } },
|
||||
{ 1, "PipelineCyclers", { 0.5, 0.5, 1.0 }, "", 50000 },
|
||||
{ 1, "Dirty PipelineCyclers", { 0.2, 0.2, 0.2 }, "", 5000 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,17 +30,6 @@ get_render_pipeline() {
|
|||
return _render_pipeline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::set_min_stages
|
||||
// Access: Public
|
||||
// Description: Ensures that at least the indicated number of stages
|
||||
// are in the pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Pipeline::
|
||||
set_min_stages(int min_stages) {
|
||||
set_num_stages(max(min_stages, get_num_stages()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_stages
|
||||
// Access: Public
|
||||
|
|
@ -62,7 +51,7 @@ get_num_stages() const {
|
|||
INLINE int Pipeline::
|
||||
get_num_cyclers() const {
|
||||
ReMutexHolder holder(_lock);
|
||||
return _cyclers.size();
|
||||
return _num_cyclers;
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "pipeline.h"
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
#include "reMutexHolder.h"
|
||||
#include "configVariableInt.h"
|
||||
|
||||
Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
|
||||
|
||||
|
|
@ -28,12 +29,12 @@ Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Pipeline::
|
||||
Pipeline(const string &name) :
|
||||
Namable(name)
|
||||
Pipeline(const string &name, int num_stages) :
|
||||
Namable(name),
|
||||
_num_stages(num_stages)
|
||||
{
|
||||
_num_stages = 1;
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
_num_cyclers = 0;
|
||||
_cycling = false;
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
|
@ -46,7 +47,7 @@ Pipeline(const string &name) :
|
|||
Pipeline::
|
||||
~Pipeline() {
|
||||
#ifdef THREADED_PIPELINE
|
||||
nassertv(_cyclers.empty());
|
||||
nassertv(_num_cyclers == 0);
|
||||
nassertv(!_cycling);
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
|
@ -91,6 +92,10 @@ cycle() {
|
|||
// set for next time.
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -104,6 +109,10 @@ cycle() {
|
|||
if (cycler->_dirty) {
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -117,6 +126,10 @@ cycle() {
|
|||
if (cycler->_dirty) {
|
||||
bool inserted = next_dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
} else {
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -135,44 +148,6 @@ cycle() {
|
|||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::set_num_stages
|
||||
// Access: Public
|
||||
// Description: Specifies the number of stages required for the
|
||||
// pipeline.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(num_stages >= 1);
|
||||
#ifdef THREADED_PIPELINE
|
||||
ReMutexHolder holder(_lock);
|
||||
if (num_stages != _num_stages) {
|
||||
|
||||
// We need to lock every PipelineCycler object in the world before
|
||||
// we can adjust the number of stages.
|
||||
Cyclers::iterator ci;
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->_lock.lock();
|
||||
}
|
||||
|
||||
_num_stages = num_stages;
|
||||
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->set_num_stages(num_stages);
|
||||
}
|
||||
|
||||
// Now release them all.
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
#else // THREADED_PIPELINE
|
||||
_num_stages = num_stages;
|
||||
#endif // THREADED_PIPELINE
|
||||
}
|
||||
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::add_cycler
|
||||
|
|
@ -186,8 +161,11 @@ add_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||
ReMutexHolder holder(_lock);
|
||||
nassertv(!cycler->_dirty);
|
||||
nassertv(!_cycling);
|
||||
bool inserted = _cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
++_num_cyclers;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), 1);
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
|
|
@ -212,6 +190,10 @@ add_dirty_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||
|
||||
bool inserted = _dirty_cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), 1);
|
||||
#endif
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
|
|
@ -229,20 +211,66 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertv(!_cycling);
|
||||
|
||||
Cyclers::iterator ci = _cyclers.find(cycler);
|
||||
nassertv(ci != _cyclers.end());
|
||||
_cyclers.erase(ci);
|
||||
|
||||
--_num_cyclers;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
|
||||
if (cycler->_dirty) {
|
||||
cycler->_dirty = false;
|
||||
Cyclers::iterator ci = _dirty_cyclers.find(cycler);
|
||||
nassertv(ci != _dirty_cyclers.end());
|
||||
_dirty_cyclers.erase(ci);
|
||||
#ifdef DEBUG_THREADS
|
||||
inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::iterate_all_cycler_types
|
||||
// Access: Public
|
||||
// Description: Walks through the list of all the different
|
||||
// PipelineCycler types in the universe. For each one,
|
||||
// calls the indicated callback function with the
|
||||
// TypeHandle of the respective type (actually, the
|
||||
// result of cycler::get_parent_type()) and the count of
|
||||
// pipeline cyclers of that type. Mainly used for
|
||||
// PStats reporting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
iterate_all_cycler_types(CallbackFunc *func, void *data) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
TypeCount::const_iterator ci;
|
||||
for (ci = _all_cycler_types.begin(); ci != _all_cycler_types.end(); ++ci) {
|
||||
func((*ci).first, (*ci).second, data);
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::iterate_dirty_cycler_types
|
||||
// Access: Public
|
||||
// Description: Walks through the list of all the different
|
||||
// PipelineCycler types, for only the dirty
|
||||
// PipelineCyclers. See also
|
||||
// iterate_all_cycler_types().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
iterate_dirty_cycler_types(CallbackFunc *func, void *data) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
TypeCount::const_iterator ci;
|
||||
for (ci = _dirty_cycler_types.begin(); ci != _dirty_cycler_types.end(); ++ci) {
|
||||
func((*ci).first, (*ci).second, data);
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::make_render_pipeline
|
||||
// Access: Private, Static
|
||||
|
|
@ -250,6 +278,38 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
make_render_pipeline() {
|
||||
ConfigVariableInt pipeline_stages
|
||||
("pipeline-stages", 1,
|
||||
PRC_DESC("The number of stages in the render pipeline. This is only "
|
||||
"meaningful if threaded pipelining is compiled into Panda, in "
|
||||
"which case you should set this to 1, 2, or 3, according to "
|
||||
"your application's threading model. You may set it larger "
|
||||
"than your application requires, but this will incur additional "
|
||||
"overhead."));
|
||||
|
||||
nassertv(_render_pipeline == (Pipeline *)NULL);
|
||||
_render_pipeline = new Pipeline("render");
|
||||
_render_pipeline = new Pipeline("render", pipeline_stages);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::inc_cycler_type
|
||||
// Access: Private, Static
|
||||
// Description: Increments (or decrements, according to added) the
|
||||
// value for TypeHandle in the indicated TypeCount map.
|
||||
// This is used in DEBUG_THREADS mode to track the types
|
||||
// of PipelineCyclers that are coming and going, mainly
|
||||
// for PStats reporting.
|
||||
//
|
||||
// It is assumed the lock is held during this call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
inc_cycler_type(TypeCount &count, TypeHandle type, int addend) {
|
||||
TypeCount::iterator ci = count.find(type);
|
||||
if (ci == count.end()) {
|
||||
ci = count.insert(TypeCount::value_type(type, 0)).first;
|
||||
}
|
||||
(*ci).second += addend;
|
||||
nassertv((*ci).second >= 0);
|
||||
}
|
||||
#endif // DEBUG_THREADS
|
||||
|
|
|
|||
|
|
@ -42,15 +42,13 @@ struct PipelineCyclerTrueImpl;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA Pipeline : public Namable {
|
||||
public:
|
||||
Pipeline(const string &name);
|
||||
Pipeline(const string &name, int num_stages);
|
||||
~Pipeline();
|
||||
|
||||
INLINE static Pipeline *get_render_pipeline();
|
||||
|
||||
void cycle();
|
||||
|
||||
void set_num_stages(int num_stages);
|
||||
INLINE void set_min_stages(int min_stages);
|
||||
INLINE int get_num_stages() const;
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
|
|
@ -60,6 +58,13 @@ public:
|
|||
|
||||
INLINE int get_num_cyclers() const;
|
||||
INLINE int get_num_dirty_cyclers() const;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
typedef void CallbackFunc(TypeHandle type, int count, void *data);
|
||||
void iterate_all_cycler_types(CallbackFunc *func, void *data) const;
|
||||
void iterate_dirty_cycler_types(CallbackFunc *func, void *data) const;
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
#endif // THREADED_PIPELINE
|
||||
|
||||
private:
|
||||
|
|
@ -69,10 +74,17 @@ private:
|
|||
static Pipeline *_render_pipeline;
|
||||
|
||||
#ifdef THREADED_PIPELINE
|
||||
int _num_cyclers;
|
||||
typedef pset<PipelineCyclerTrueImpl *> Cyclers;
|
||||
Cyclers _cyclers;
|
||||
Cyclers _dirty_cyclers;
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
typedef pmap<TypeHandle, int> TypeCount;
|
||||
TypeCount _all_cycler_types, _dirty_cycler_types;
|
||||
|
||||
static void inc_cycler_type(TypeCount &count, TypeHandle type, int addend);
|
||||
#endif // DEBUG_THREADS
|
||||
|
||||
// This is true only during cycle().
|
||||
bool _cycling;
|
||||
|
||||
|
|
|
|||
|
|
@ -368,6 +368,17 @@ release_write_stage(int n, CycleData *pointer) {
|
|||
_write_count--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerDummyImpl::
|
||||
get_parent_type() const {
|
||||
return _data->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerDummyImpl::cheat
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ public:
|
|||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
|
|
|||
|
|
@ -339,6 +339,17 @@ INLINE void PipelineCyclerTrivialImpl::
|
|||
release_write_stage(int, CycleData *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerTrivialImpl::
|
||||
get_parent_type() const {
|
||||
return cheat()->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrivialImpl::cheat
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ public:
|
|||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
|
|
|||
|
|
@ -266,6 +266,17 @@ release_write_stage(int n, CycleData *pointer) {
|
|||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::get_parent_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of object that owns this cycler, as
|
||||
// reported by CycleData::get_parent_type().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle PipelineCyclerTrueImpl::
|
||||
get_parent_type() const {
|
||||
return _data[0]->get_parent_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cheat
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -37,13 +37,14 @@ PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
|||
if (_pipeline == (Pipeline *)NULL) {
|
||||
_pipeline = Pipeline::get_render_pipeline();
|
||||
}
|
||||
_pipeline->add_cycler(this);
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i] = initial_data;
|
||||
}
|
||||
|
||||
_pipeline->add_cycler(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -58,23 +59,19 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
|||
_lock(this)
|
||||
{
|
||||
ReMutexHolder holder(_lock);
|
||||
_pipeline->add_cycler(this);
|
||||
if (copy._dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
_data = new PT(CycleData)[_num_stages];
|
||||
|
||||
|
||||
// It's no longer critically important that we preserve pointerwise
|
||||
// equivalence between different stages in the copy, but it doesn't
|
||||
// cost much and might be a little more efficient, so we do it
|
||||
// anyway.
|
||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||
Pointers pointers;
|
||||
|
||||
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
PT(CycleData) &new_pt = pointers[copy._data[i]];
|
||||
if (new_pt == NULL) {
|
||||
|
|
@ -82,6 +79,11 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
|||
}
|
||||
_data[i] = new_pt;
|
||||
}
|
||||
|
||||
_pipeline->add_cycler(this);
|
||||
if (copy._dirty) {
|
||||
_pipeline->add_dirty_cycler(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -93,8 +95,7 @@ void PipelineCyclerTrueImpl::
|
|||
operator = (const PipelineCyclerTrueImpl ©) {
|
||||
ReMutexHolder holder1(_lock);
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
nassertv(get_parent_type() == copy.get_parent_type());
|
||||
|
||||
typedef pmap<CycleData *, PT(CycleData) > Pointers;
|
||||
Pointers pointers;
|
||||
|
|
@ -120,11 +121,12 @@ operator = (const PipelineCyclerTrueImpl ©) {
|
|||
PipelineCyclerTrueImpl::
|
||||
~PipelineCyclerTrueImpl() {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
_pipeline->remove_cycler(this);
|
||||
|
||||
delete[] _data;
|
||||
_data = NULL;
|
||||
_num_stages = 0;
|
||||
|
||||
_pipeline->remove_cycler(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public:
|
|||
INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE TypeHandle get_parent_type() const;
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
INLINE int get_read_count() const;
|
||||
INLINE int get_write_count() const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue