mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
better pipelining
This commit is contained in:
parent
a75df81dfb
commit
c75b55eb98
@ -46,6 +46,7 @@
|
||||
#endif
|
||||
|
||||
PStatCollector GraphicsEngine::_wait_pcollector("Wait");
|
||||
PStatCollector GraphicsEngine::_cycle_pcollector("App:Cycle");
|
||||
PStatCollector GraphicsEngine::_app_pcollector("App");
|
||||
PStatCollector GraphicsEngine::_yield_pcollector("App:Yield");
|
||||
PStatCollector GraphicsEngine::_cull_pcollector("Cull");
|
||||
@ -490,9 +491,32 @@ render_frame() {
|
||||
|
||||
} else {
|
||||
new_windows.push_back(win);
|
||||
|
||||
// Let's calculate each scene's bounding volume here in App,
|
||||
// before we cycle the pipeline. The cull traversal will
|
||||
// calculate it anyway, but if we calculate it in App first
|
||||
// before it gets calculated in the Cull thread, it will be more
|
||||
// likely to stick for subsequent frames, so we won't have to
|
||||
// recompute it each frame.
|
||||
int num_drs = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_drs; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
if (dr != (DisplayRegion *)NULL) {
|
||||
NodePath camera_np = dr->get_camera();
|
||||
if (!camera_np.is_empty()) {
|
||||
Camera *camera = DCAST(Camera, camera_np.node());
|
||||
NodePath scene = camera->get_scene();
|
||||
if (scene.is_empty()) {
|
||||
scene = camera_np.get_top();
|
||||
}
|
||||
if (!scene.is_empty()) {
|
||||
scene.get_bounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
new_windows.swap(_windows);
|
||||
|
||||
// Now it's time to do any drawing from the main frame--after all of
|
||||
// the App code has executed, but before we begin the next frame.
|
||||
@ -500,13 +524,13 @@ render_frame() {
|
||||
|
||||
// Grab each thread's mutex again after all windows have flipped,
|
||||
// and wait for the thread to finish.
|
||||
{
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
@ -514,7 +538,10 @@ render_frame() {
|
||||
}
|
||||
|
||||
// Now cycle the pipeline and officially begin the next frame.
|
||||
{
|
||||
PStatTimer timer(_cycle_pcollector);
|
||||
_pipeline->cycle();
|
||||
}
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
global_clock->tick();
|
||||
if (global_clock->check_errors()) {
|
||||
@ -539,6 +566,7 @@ render_frame() {
|
||||
}
|
||||
|
||||
// Now signal all of our threads to begin their next frame.
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
@ -589,17 +617,16 @@ open_windows() {
|
||||
|
||||
_app.do_windows(this);
|
||||
|
||||
{
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv_start.signal();
|
||||
@ -612,18 +639,16 @@ open_windows() {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsEngine::sync_frame
|
||||
@ -1008,13 +1033,13 @@ do_flip_frame() {
|
||||
// First, wait for all the threads to finish their current frame, if
|
||||
// necessary. Grabbing the mutex (and waiting for TS_wait) should
|
||||
// achieve that.
|
||||
{
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
@ -1023,6 +1048,9 @@ do_flip_frame() {
|
||||
|
||||
// Now signal all of our threads to flip the windows.
|
||||
_app.do_flip(this);
|
||||
|
||||
{
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
nassertv(thread->_thread_state == TS_wait);
|
||||
@ -1030,6 +1058,7 @@ do_flip_frame() {
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
}
|
||||
|
||||
_flip_state = FS_flip;
|
||||
}
|
||||
@ -1157,6 +1186,9 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
|
||||
}
|
||||
}
|
||||
|
||||
static PStatCollector traverse("Cull:Traverse");
|
||||
PStatTimer timer2(traverse);
|
||||
|
||||
trav.traverse(scene_setup->get_scene_root(), get_portal_cull());
|
||||
}
|
||||
|
||||
@ -1327,6 +1359,10 @@ void GraphicsEngine::
|
||||
terminate_threads() {
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
// We spend almost our entire time in this method just waiting for
|
||||
// threads. Time it appropriately.
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
|
||||
// First, wait for all the threads to finish their current frame.
|
||||
// Grabbing the mutex should achieve that.
|
||||
Threads::const_iterator ti;
|
||||
@ -1339,12 +1375,9 @@ terminate_threads() {
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
thread->_thread_state = TS_do_release;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
@ -1354,6 +1387,9 @@ terminate_threads() {
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Now tell them to close their windows and terminate.
|
||||
@ -1416,7 +1452,7 @@ get_window_renderer(const string &name) {
|
||||
|
||||
PT(RenderThread) thread = new RenderThread(name, this);
|
||||
thread->set_pipeline_stage(1);
|
||||
Pipeline::get_render_pipeline()->set_num_stages(2);
|
||||
_pipeline->set_min_stages(2);
|
||||
|
||||
thread->start(TP_normal, true, true);
|
||||
_threads[name] = thread;
|
||||
|
@ -246,6 +246,7 @@ private:
|
||||
Mutex _lock;
|
||||
|
||||
static PStatCollector _wait_pcollector;
|
||||
static PStatCollector _cycle_pcollector;
|
||||
static PStatCollector _app_pcollector;
|
||||
static PStatCollector _yield_pcollector;
|
||||
static PStatCollector _cull_pcollector;
|
||||
|
@ -150,6 +150,18 @@ set_pipeline_stage(int pipeline_stage) {
|
||||
_pipeline_stage = pipeline_stage;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::set_min_pipeline_stage
|
||||
// Access: Published
|
||||
// Description: Sets this thread's pipeline stage number to at least
|
||||
// the indicated value, unless it is already larger.
|
||||
// See set_pipeline_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Thread::
|
||||
set_min_pipeline_stage(int min_pipeline_stage) {
|
||||
_pipeline_stage = max(_pipeline_stage, min_pipeline_stage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_main_thread
|
||||
// Access: Published, Static
|
||||
|
@ -63,6 +63,7 @@ PUBLISHED:
|
||||
|
||||
INLINE int get_pipeline_stage() const;
|
||||
INLINE void set_pipeline_stage(int pipeline_stage);
|
||||
INLINE void set_min_pipeline_stage(int min_pipeline_stage);
|
||||
|
||||
INLINE static Thread *get_main_thread();
|
||||
INLINE static Thread *get_external_thread();
|
||||
|
@ -82,6 +82,9 @@ private:
|
||||
INLINE void operator = (const CData ©);
|
||||
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return BoundedObject::get_class_type();
|
||||
}
|
||||
|
||||
int _flags;
|
||||
BoundingVolumeType _bound_type;
|
||||
|
@ -177,6 +177,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return Geom::get_class_type();
|
||||
}
|
||||
|
||||
PT(GeomVertexData) _data;
|
||||
Primitives _primitives;
|
||||
|
@ -209,6 +209,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return GeomPrimitive::get_class_type();
|
||||
}
|
||||
|
||||
ShadeModel _shade_model;
|
||||
int _first_vertex;
|
||||
|
@ -123,6 +123,9 @@ private:
|
||||
void *extra_data) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager,
|
||||
void *extra_data);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return GeomVertexArrayData::get_class_type();
|
||||
}
|
||||
|
||||
UsageHint _usage_hint;
|
||||
PTA_uchar _data;
|
||||
|
@ -234,6 +234,18 @@ get_modified() const {
|
||||
return cdata->_modified;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexData::clear_cache
|
||||
// Access: Published
|
||||
// Description: Removes all of the previously-cached results of
|
||||
// convert_to().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void GeomVertexData::
|
||||
clear_cache() {
|
||||
CDWriter cdata(_cycler);
|
||||
do_clear_cache(cdata);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexData::has_vertex
|
||||
// Access: Public
|
||||
|
@ -152,7 +152,7 @@ operator = (const GeomVertexData ©) {
|
||||
_morphs_pcollector = copy._morphs_pcollector;
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -218,7 +218,7 @@ set_usage_hint(GeomVertexData::UsageHint usage_hint) {
|
||||
}
|
||||
(*ai)->set_usage_hint(usage_hint);
|
||||
}
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -265,7 +265,7 @@ clear_rows() {
|
||||
}
|
||||
(*ai)->clear_rows();
|
||||
}
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices.clear();
|
||||
}
|
||||
@ -291,7 +291,7 @@ modify_array(int i) {
|
||||
if (cdata->_arrays[i]->get_ref_count() > 1) {
|
||||
cdata->_arrays[i] = new GeomVertexArrayData(*cdata->_arrays[i]);
|
||||
}
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
@ -311,7 +311,7 @@ set_array(int i, const GeomVertexArrayData *array) {
|
||||
CDWriter cdata(_cycler);
|
||||
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
|
||||
cdata->_arrays[i] = (GeomVertexArrayData *)array;
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -331,7 +331,7 @@ set_transform_table(const TransformTable *table) {
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_transform_table = (TransformTable *)table;
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -354,7 +354,7 @@ modify_transform_blend_table() {
|
||||
if (cdata->_transform_blend_table->get_ref_count() > 1) {
|
||||
cdata->_transform_blend_table = new TransformBlendTable(*cdata->_transform_blend_table);
|
||||
}
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
@ -374,7 +374,7 @@ void GeomVertexData::
|
||||
set_transform_blend_table(const TransformBlendTable *table) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_transform_blend_table = (TransformBlendTable *)table;
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -396,7 +396,7 @@ set_slider_table(const SliderTable *table) {
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_slider_table = (SliderTable *)table;
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices_modified = UpdateSeq();
|
||||
}
|
||||
@ -1069,26 +1069,6 @@ write(ostream &out, int indent_level) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexData::clear_cache
|
||||
// Access: Published
|
||||
// Description: Removes all of the previously-cached results of
|
||||
// convert_to().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
clear_cache() {
|
||||
// Probably we shouldn't do anything at all here unless we are
|
||||
// running in pipeline stage 0.
|
||||
CData *cdata = CDWriter(_cycler);
|
||||
for (Cache::iterator ci = cdata->_cache.begin();
|
||||
ci != cdata->_cache.end();
|
||||
++ci) {
|
||||
CacheEntry *entry = (*ci);
|
||||
entry->erase();
|
||||
}
|
||||
cdata->_cache.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexData::get_array_info
|
||||
// Access: Public
|
||||
@ -1263,7 +1243,7 @@ uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
|
||||
// Description: The private implementation of set_num_rows().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GeomVertexData::
|
||||
do_set_num_rows(int n, GeomVertexData::CDWriter &cdata) {
|
||||
do_set_num_rows(int n, GeomVertexData::CData *cdata) {
|
||||
nassertr(_format->get_num_arrays() == (int)cdata->_arrays.size(), false);
|
||||
|
||||
bool any_changed = false;
|
||||
@ -1324,7 +1304,7 @@ do_set_num_rows(int n, GeomVertexData::CDWriter &cdata) {
|
||||
}
|
||||
|
||||
if (any_changed) {
|
||||
clear_cache();
|
||||
do_clear_cache(cdata);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
cdata->_animated_vertices.clear();
|
||||
}
|
||||
@ -1340,7 +1320,7 @@ do_set_num_rows(int n, GeomVertexData::CDWriter &cdata) {
|
||||
// existing animated_vertices object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
update_animated_vertices(GeomVertexData::CDWriter &cdata) {
|
||||
update_animated_vertices(GeomVertexData::CData *cdata) {
|
||||
int num_rows = get_num_rows();
|
||||
|
||||
if (gobj_cat.is_debug()) {
|
||||
@ -1474,6 +1454,24 @@ update_animated_vertices(GeomVertexData::CDWriter &cdata) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomVertexData::do_clear_cache
|
||||
// Access: Private
|
||||
// Description: The private implementation of clear_cache().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomVertexData::
|
||||
do_clear_cache(GeomVertexData::CData *cdata) {
|
||||
// Probably we shouldn't do anything at all here unless we are
|
||||
// running in pipeline stage 0.
|
||||
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
|
||||
// Access: Public, Static
|
||||
|
@ -142,7 +142,7 @@ PUBLISHED:
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
void clear_cache();
|
||||
INLINE void clear_cache();
|
||||
|
||||
public:
|
||||
bool get_array_info(const InternalName *name,
|
||||
@ -224,6 +224,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return GeomVertexData::get_class_type();
|
||||
}
|
||||
|
||||
UsageHint _usage_hint;
|
||||
Arrays _arrays;
|
||||
@ -241,8 +244,9 @@ private:
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
private:
|
||||
bool do_set_num_rows(int n, CDWriter &cdata);
|
||||
void update_animated_vertices(CDWriter &cdata);
|
||||
bool do_set_num_rows(int n, CData *cdata);
|
||||
void update_animated_vertices(CData *cdata);
|
||||
void do_clear_cache(CData *cdata);
|
||||
|
||||
static PStatCollector _convert_pcollector;
|
||||
static PStatCollector _scale_color_pcollector;
|
||||
|
@ -89,6 +89,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return SliderTable::get_class_type();
|
||||
}
|
||||
|
||||
UpdateSeq _modified;
|
||||
};
|
||||
|
@ -99,6 +99,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return TransformBlendTable::get_class_type();
|
||||
}
|
||||
|
||||
UpdateSeq _modified;
|
||||
UpdateSeq _global_modified;
|
||||
|
@ -81,6 +81,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return TransformTable::get_class_type();
|
||||
}
|
||||
|
||||
UpdateSeq _modified;
|
||||
};
|
||||
|
@ -50,6 +50,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return UserVertexSlider::get_class_type();
|
||||
}
|
||||
|
||||
float _slider;
|
||||
};
|
||||
|
@ -55,6 +55,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return UserVertexTransform::get_class_type();
|
||||
}
|
||||
|
||||
LMatrix4f _matrix;
|
||||
};
|
||||
|
@ -74,6 +74,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return VertexSlider::get_class_type();
|
||||
}
|
||||
|
||||
UpdateSeq _modified;
|
||||
};
|
||||
|
@ -73,6 +73,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return VertexTransform::get_class_type();
|
||||
}
|
||||
|
||||
UpdateSeq _modified;
|
||||
};
|
||||
|
@ -197,6 +197,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return RopeNode::get_class_type();
|
||||
}
|
||||
|
||||
PT(NurbsCurveEvaluator) _curve;
|
||||
RenderMode _render_mode;
|
||||
|
@ -84,6 +84,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return SheetNode::get_class_type();
|
||||
}
|
||||
|
||||
PT(NurbsSurfaceEvaluator) _surface;
|
||||
bool _use_vertex_color;
|
||||
|
@ -69,6 +69,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return DirectionalLight::get_class_type();
|
||||
}
|
||||
|
||||
Colorf _specular_color;
|
||||
LPoint3f _point;
|
||||
|
@ -111,6 +111,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return GeomNode::get_class_type();
|
||||
}
|
||||
|
||||
Geoms _geoms;
|
||||
};
|
||||
|
@ -106,6 +106,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return Light::get_class_type();
|
||||
}
|
||||
|
||||
Colorf _color;
|
||||
|
||||
|
@ -104,6 +104,9 @@ protected:
|
||||
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return LODNode::get_class_type();
|
||||
}
|
||||
|
||||
LPoint3f _center;
|
||||
SwitchVector _switch_vector;
|
||||
|
@ -82,6 +82,9 @@ private:
|
||||
INLINE CData();
|
||||
CData(const CData ©);
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return NodePathComponent::get_class_type();
|
||||
}
|
||||
|
||||
PT(NodePathComponent) _next;
|
||||
int _length;
|
||||
|
@ -322,6 +322,9 @@ private:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return PandaNode::get_class_type();
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
void inc_py_refs();
|
||||
|
@ -70,6 +70,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return PlaneNode::get_class_type();
|
||||
}
|
||||
|
||||
Planef _plane;
|
||||
};
|
||||
|
@ -69,6 +69,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return PointLight::get_class_type();
|
||||
}
|
||||
|
||||
Colorf _specular_color;
|
||||
LVecBase3f _attenuation;
|
||||
|
@ -89,6 +89,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return Spotlight::get_class_type();
|
||||
}
|
||||
|
||||
float _exponent;
|
||||
Colorf _specular_color;
|
||||
|
@ -54,6 +54,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return SwitchNode::get_class_type();
|
||||
}
|
||||
|
||||
int _visible_child;
|
||||
};
|
||||
|
@ -95,6 +95,9 @@ private:
|
||||
virtual CycleData *make_copy() const;
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual TypeHandle get_parent_type() const {
|
||||
return AnimInterface::get_class_type();
|
||||
}
|
||||
|
||||
void play(double from, double to);
|
||||
void loop(bool restart, double from, double to);
|
||||
|
@ -85,3 +85,25 @@ void CycleData::
|
||||
fillin(DatagramIterator &, BamReader *, void *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::get_parent_type
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the type of the container that owns the
|
||||
// CycleData. This is useful mainly for debugging.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle CycleData::
|
||||
get_parent_type() const {
|
||||
return TypeHandle::none();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CycleData::output
|
||||
// Access: Public, Virtual
|
||||
// Description: Formats the contents of the CycleData in some
|
||||
// meaningful way for humans. This is useful mainly for
|
||||
// debugging.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CycleData::
|
||||
output(ostream &out) const {
|
||||
out << get_parent_type() << "::CData";
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define CYCLEDATA_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "referenceCount.h"
|
||||
|
||||
class BamWriter;
|
||||
@ -64,8 +64,17 @@ public:
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
virtual void fillin(DatagramIterator &scan, BamReader *manager,
|
||||
void *extra_data);
|
||||
|
||||
virtual TypeHandle get_parent_type() const;
|
||||
virtual void output(ostream &out) const;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const CycleData &cd) {
|
||||
cd.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "cycleData.I"
|
||||
|
||||
#endif
|
||||
|
@ -29,3 +29,14 @@ 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()));
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "pipeline.h"
|
||||
#include "pipelineCyclerTrueImpl.h"
|
||||
#include "mutexHolder.h"
|
||||
|
||||
Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
|
||||
|
||||
@ -53,6 +54,7 @@ Pipeline::
|
||||
void Pipeline::
|
||||
cycle() {
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
MutexHolder holder(_lock);
|
||||
Cyclers::iterator ci;
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->cycle();
|
||||
@ -69,18 +71,34 @@ cycle() {
|
||||
void Pipeline::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(num_stages >= 1);
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
MutexHolder 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;
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
Cyclers::iterator ci;
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->set_num_stages(num_stages);
|
||||
}
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
|
||||
// Now release them all.
|
||||
for (ci = _cyclers.begin(); ci != _cyclers.end(); ++ci) {
|
||||
(*ci)->_lock.release();
|
||||
}
|
||||
}
|
||||
|
||||
#else // DO_PIPELINING && HAVE_THREADS
|
||||
_num_stages = num_stages;
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Pipeline::get_num_stages
|
||||
// Access: Public
|
||||
@ -103,6 +121,7 @@ get_num_stages() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
add_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
MutexHolder holder(_lock);
|
||||
bool inserted = _cyclers.insert(cycler).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
@ -118,6 +137,7 @@ add_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Pipeline::
|
||||
remove_cycler(PipelineCyclerTrueImpl *cycler) {
|
||||
MutexHolder holder(_lock);
|
||||
Cyclers::iterator ci = _cyclers.find(cycler);
|
||||
nassertv(ci != _cyclers.end());
|
||||
_cyclers.erase(ci);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "pandabase.h"
|
||||
#include "namable.h"
|
||||
#include "pset.h"
|
||||
#include "pmutex.h"
|
||||
|
||||
class PipelineCyclerTrueImpl;
|
||||
|
||||
@ -48,6 +49,7 @@ public:
|
||||
void cycle();
|
||||
|
||||
void set_num_stages(int num_stages);
|
||||
INLINE void set_min_stages(int min_stages);
|
||||
int get_num_stages() const;
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
@ -64,6 +66,8 @@ private:
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
typedef pset<PipelineCyclerTrueImpl *> Cyclers;
|
||||
Cyclers _cyclers;
|
||||
|
||||
Mutex _lock;
|
||||
#endif // DO_PIPELINING && HAVE_THREADS
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@ INLINE const CycleData *PipelineCyclerTrueImpl::
|
||||
read() const {
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
_lock.lock();
|
||||
return _data[pipeline_stage]._cycle_data;
|
||||
}
|
||||
|
||||
@ -44,6 +45,12 @@ read() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
increment_read(const CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
||||
nassertv(_data[pipeline_stage]._cycle_data == pointer);
|
||||
#endif
|
||||
_lock.lock();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -54,6 +61,12 @@ increment_read(const CycleData *pointer) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_read(const CycleData *pointer) const {
|
||||
#ifndef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
|
||||
nassertv(_data[pipeline_stage]._cycle_data == pointer);
|
||||
#endif
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -75,8 +88,7 @@ release_read(const CycleData *pointer) const {
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
write() {
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
|
||||
return _data[pipeline_stage]._cycle_data;
|
||||
return write_stage(pipeline_stage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -90,7 +102,9 @@ write() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
elevate_read(const CycleData *pointer) {
|
||||
return (CycleData *)pointer;
|
||||
CycleData *new_pointer = write();
|
||||
_lock.release();
|
||||
return new_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -101,6 +115,12 @@ elevate_read(const CycleData *pointer) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write(CycleData *pointer) {
|
||||
#ifdef NDEBUG
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
return release_write_stage(pipeline_stage);
|
||||
#else
|
||||
_lock.release();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -123,23 +143,11 @@ get_num_stages() {
|
||||
INLINE bool PipelineCyclerTrueImpl::
|
||||
is_stage_unique(int n) const {
|
||||
nassertr(n >= 0 && n < _num_stages, false);
|
||||
if (n == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return _data[n]._cycle_data == _data[n - 1]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CycleData *PipelineCyclerTrueImpl::
|
||||
write_stage(int n) {
|
||||
nassertr(n >= 0 && n < _num_stages, (CycleData *)NULL);
|
||||
return _data[n]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -150,7 +158,11 @@ write_stage(int n) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PipelineCyclerTrueImpl::
|
||||
release_write_stage(int n, CycleData *pointer) {
|
||||
#ifndef NDEBUG
|
||||
nassertv(n >= 0 && n < _num_stages);
|
||||
nassertv(_data[n]._cycle_data == pointer);
|
||||
#endif
|
||||
_lock.release();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -179,7 +191,10 @@ cheat() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_read_count() const {
|
||||
return 0;
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, 0);
|
||||
_lock.lock();
|
||||
return _lock.get_lock_count();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -192,5 +207,8 @@ get_read_count() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PipelineCyclerTrueImpl::
|
||||
get_write_count() const {
|
||||
return 0;
|
||||
int pipeline_stage = Thread::get_current_thread()->get_pipeline_stage();
|
||||
nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, 0);
|
||||
_lock.lock();
|
||||
return _lock.get_lock_count();
|
||||
}
|
||||
|
@ -20,7 +20,9 @@
|
||||
|
||||
#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
|
||||
|
||||
#include "config_util.h"
|
||||
#include "pipeline.h"
|
||||
#include "reMutexHolder.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -40,7 +42,7 @@ PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline) :
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
_data = new StageData[_num_stages];
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i]._cycle_data = initial_data->make_copy();
|
||||
_data[i]._cycle_data = initial_data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +57,7 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
||||
{
|
||||
_pipeline->add_cycler(this);
|
||||
|
||||
ReMutexHolder holder(copy._lock);
|
||||
_num_stages = _pipeline->get_num_stages();
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
_data = new StageData[_num_stages];
|
||||
@ -70,9 +73,12 @@ PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl ©) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
operator = (const PipelineCyclerTrueImpl ©) {
|
||||
ReMutexHolder holder1(_lock);
|
||||
ReMutexHolder holder2(copy._lock);
|
||||
|
||||
nassertv(_num_stages == copy._num_stages);
|
||||
for (int i = 0; i < _num_stages; ++i) {
|
||||
_data[i]._cycle_data = copy._data[i]._cycle_data->make_copy();
|
||||
_data[i]._cycle_data = copy._data[i]._cycle_data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,11 +89,77 @@ operator = (const PipelineCyclerTrueImpl ©) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PipelineCyclerTrueImpl::
|
||||
~PipelineCyclerTrueImpl() {
|
||||
ReMutexHolder holder(_lock);
|
||||
_pipeline->remove_cycler(this);
|
||||
|
||||
delete[] _data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::write_stage
|
||||
// Access: Public
|
||||
// Description: Returns a pointer suitable for writing to the nth
|
||||
// stage of the pipeline. This is for special
|
||||
// applications that need to update the entire pipeline
|
||||
// at once (for instance, to remove an invalid pointer).
|
||||
// This pointer should later be released with
|
||||
// release_write_stage().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *PipelineCyclerTrueImpl::
|
||||
write_stage(int n) {
|
||||
_lock.lock();
|
||||
|
||||
#ifndef NDEBUG
|
||||
nassertd(n >= 0 && n < _num_stages) {
|
||||
_lock.release();
|
||||
return NULL;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
CycleData *old_data = _data[n]._cycle_data;
|
||||
|
||||
if (old_data->get_ref_count() != 1) {
|
||||
// Copy-on-write.
|
||||
|
||||
// There's a special problem that happens when we write to a stage
|
||||
// other than stage 0. If we do this, when the next frame cycles,
|
||||
// the changes that we record to stage n will be lost when the
|
||||
// data from stage (n - 1) is cycled into place. This can be
|
||||
// wasteful, especially if we are updating a cached value (which
|
||||
// is generally the case when we are writing to stages other than
|
||||
// stage 0).
|
||||
|
||||
// To minimize this, we make a special exception: whenever we
|
||||
// write to stage n, if stage (n - 1) has the same pointer, we
|
||||
// will write to stage (n - 1) at the same time, and so on all the
|
||||
// way back to stage 0 or the last different stage.
|
||||
|
||||
// On the other hand, if *all* of the instances of this pointer
|
||||
// are found in stages k .. n, then we don't need to do anything
|
||||
// at all.
|
||||
int count = old_data->get_ref_count() - 1;
|
||||
int k = n - 1;
|
||||
while (k >= 0 && _data[k]._cycle_data == old_data) {
|
||||
--k;
|
||||
--count;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
PT(CycleData) new_data = old_data->make_copy();
|
||||
|
||||
int k = n - 1;
|
||||
while (k >= 0 && _data[k]._cycle_data == old_data) {
|
||||
_data[k]._cycle_data = new_data;
|
||||
--k;
|
||||
}
|
||||
|
||||
_data[n]._cycle_data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
return _data[n]._cycle_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PipelineCyclerTrueImpl::cycle
|
||||
// Access: Private
|
||||
@ -96,10 +168,11 @@ PipelineCyclerTrueImpl::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
cycle() {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
for (int i = _num_stages - 1; i > 0; --i) {
|
||||
_data[i] = _data[i - 1];
|
||||
}
|
||||
_data[0]._cycle_data = _data[0]._cycle_data->make_copy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -110,8 +183,11 @@ cycle() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PipelineCyclerTrueImpl::
|
||||
set_num_stages(int num_stages) {
|
||||
nassertv(_lock.debug_is_locked());
|
||||
|
||||
if (num_stages <= _num_stages) {
|
||||
// Don't bother to reallocate the array.
|
||||
// Don't bother to reallocate the array smaller; we just won't use
|
||||
// the rest of the array.
|
||||
for (int i = _num_stages; i < num_stages; ++i) {
|
||||
_data[i]._cycle_data.clear();
|
||||
}
|
||||
@ -120,14 +196,14 @@ set_num_stages(int num_stages) {
|
||||
|
||||
|
||||
} else {
|
||||
// Increase the array.
|
||||
// To increase the array, we must reallocate it larger.
|
||||
StageData *new_data = new StageData[num_stages];
|
||||
int i;
|
||||
for (i = 0; i < _num_stages; ++i) {
|
||||
new_data[i] = _data[i];
|
||||
}
|
||||
for (i = _num_stages; i < num_stages; ++i) {
|
||||
new_data[i]._cycle_data = _data[_num_stages - 1]._cycle_data->make_copy();
|
||||
new_data[i]._cycle_data = _data[_num_stages - 1]._cycle_data;
|
||||
}
|
||||
delete[] _data;
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "cycleData.h"
|
||||
#include "pointerTo.h"
|
||||
#include "thread.h"
|
||||
#include "reMutex.h"
|
||||
|
||||
class Pipeline;
|
||||
|
||||
@ -61,7 +62,7 @@ public:
|
||||
|
||||
INLINE int get_num_stages();
|
||||
INLINE bool is_stage_unique(int n) const;
|
||||
INLINE CycleData *write_stage(int n);
|
||||
CycleData *write_stage(int n);
|
||||
INLINE void release_write_stage(int n, CycleData *pointer);
|
||||
|
||||
INLINE CycleData *cheat() const;
|
||||
@ -83,6 +84,8 @@ private:
|
||||
StageData *_data;
|
||||
int _num_stages;
|
||||
|
||||
ReMutex _lock;
|
||||
|
||||
friend class Pipeline;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user