16 #include "pipelineCyclerTrueImpl.h"
17 #include "reMutexHolder.h"
18 #include "configVariableInt.h"
19 #include "config_pipeline.h"
29 Pipeline(
const string &name,
int num_stages) :
31 #ifdef THREADED_PIPELINE
35 #ifdef THREADED_PIPELINE
54 _num_dirty_cyclers = 0;
59 #endif // THREADED_PIPELINE
61 set_num_stages(num_stages);
71 #ifdef THREADED_PIPELINE
72 nassertv(_num_cyclers == 0);
73 nassertv(_num_dirty_cyclers == 0);
77 #endif // THREADED_PIPELINE
87 #ifdef THREADED_PIPELINE
88 if (pipeline_cat.is_debug()) {
90 <<
"Beginning the pipeline cycle\n";
94 saved_cdatas.reserve(_num_dirty_cyclers);
97 if (_num_stages == 1) {
99 nassertv(_dirty._next == &_dirty);
108 prev_dirty.make_head();
109 prev_dirty.take_list(_dirty);
110 _num_dirty_cyclers = 0;
112 switch (_num_stages) {
114 while (prev_dirty._next != &prev_dirty) {
115 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
116 cycler->remove_from_list();
122 saved_cdatas.push_back(cycler->cycle_2());
124 if (cycler->_dirty) {
127 cycler->insert_before(&_dirty);
128 ++_num_dirty_cyclers;
131 cycler->insert_before(&_clean);
133 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
140 while (prev_dirty._next != &prev_dirty) {
141 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
142 cycler->remove_from_list();
145 saved_cdatas.push_back(cycler->cycle_3());
147 if (cycler->_dirty) {
148 cycler->insert_before(&_dirty);
149 ++_num_dirty_cyclers;
151 cycler->insert_before(&_clean);
153 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
160 while (prev_dirty._next != &prev_dirty) {
161 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
162 cycler->remove_from_list();
165 saved_cdatas.push_back(cycler->cycle());
167 if (cycler->_dirty) {
168 cycler->insert_before(&_dirty);
169 ++_num_dirty_cyclers;
171 cycler->insert_before(&_clean);
173 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
181 prev_dirty.clear_head();
189 saved_cdatas.clear();
191 if (pipeline_cat.is_debug()) {
193 <<
"Finished the pipeline cycle\n";
196 #endif // THREADED_PIPELINE
207 nassertv(num_stages >= 1);
208 #ifdef THREADED_PIPELINE
210 if (num_stages != _num_stages) {
215 for (links = _clean._next; links != &_clean; links = links->_next) {
216 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
217 cycler->_lock.acquire();
219 for (links = _dirty._next; links != &_dirty; links = links->_next) {
220 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
221 cycler->_lock.acquire();
224 _num_stages = num_stages;
226 for (links = _clean._next; links != &_clean; links = links->_next) {
227 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
228 cycler->set_num_stages(num_stages);
230 for (links = _dirty._next; links != &_dirty; links = links->_next) {
231 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
232 cycler->set_num_stages(num_stages);
237 for (links = _clean._next; links != &_clean; links = links->_next) {
238 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
239 cycler->_lock.release();
242 for (links = _dirty._next; links != &_dirty; links = links->_next) {
243 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
244 cycler->_lock.release();
247 nassertv(count == _num_cyclers);
250 #else // THREADED_PIPELINE
251 if (num_stages != 1) {
252 pipeline_cat.warning()
253 <<
"Requested " << num_stages
254 <<
" pipeline stages but multithreaded render pipelines not enabled in build.\n";
257 #endif // THREADED_PIPELINE
260 #ifdef THREADED_PIPELINE
269 add_cycler(PipelineCyclerTrueImpl *cycler) {
271 nassertv(!cycler->_dirty);
274 cycler->insert_before(&_clean);
278 inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), 1);
281 #endif // THREADED_PIPELINE
283 #ifdef THREADED_PIPELINE
294 add_dirty_cycler(PipelineCyclerTrueImpl *cycler) {
295 nassertv(cycler->_lock.debug_is_locked());
298 nassertv(_num_stages != 1);
300 nassertv(!cycler->_dirty);
303 cycler->remove_from_list();
304 cycler->insert_before(&_dirty);
305 cycler->_dirty =
true;
306 ++_num_dirty_cyclers;
309 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), 1);
312 #endif // THREADED_PIPELINE
314 #ifdef THREADED_PIPELINE
323 remove_cycler(PipelineCyclerTrueImpl *cycler) {
324 nassertv(cycler->_lock.debug_is_locked());
330 cycler->remove_from_list();
333 inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
336 if (cycler->_dirty) {
337 cycler->_dirty =
false;
338 --_num_dirty_cyclers;
340 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
344 #endif // THREADED_PIPELINE
346 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
359 iterate_all_cycler_types(CallbackFunc *func,
void *data)
const {
361 TypeCount::const_iterator ci;
362 for (ci = _all_cycler_types.begin(); ci != _all_cycler_types.end(); ++ci) {
363 func((*ci).first, (*ci).second, data);
366 #endif // THREADED_PIPELINE && DEBUG_THREADS
368 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
378 iterate_dirty_cycler_types(CallbackFunc *func,
void *data)
const {
380 TypeCount::const_iterator ci;
381 for (ci = _dirty_cycler_types.begin(); ci != _dirty_cycler_types.end(); ++ci) {
382 func((*ci).first, (*ci).second, data);
385 #endif // THREADED_PIPELINE && DEBUG_THREADS
393 make_render_pipeline() {
395 (
"pipeline-stages", 1,
396 PRC_DESC(
"The initial number of stages in the render pipeline. This is "
397 "only meaningful if threaded pipelining is compiled into "
398 "Panda. In most cases, you should not set this at all anyway, "
399 "since the pipeline can automatically grow stages as needed, "
400 "but it will not remove stages automatically, and having more "
401 "pipeline stages than your application requires will incur "
402 "additional runtime overhead."));
404 nassertv(_render_pipeline == (
Pipeline *)NULL);
405 _render_pipeline =
new Pipeline(
"render", pipeline_stages);
408 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS)
421 inc_cycler_type(TypeCount &count,
TypeHandle type,
int addend) {
422 TypeCount::iterator ci = count.find(type);
423 if (ci == count.end()) {
424 ci = count.insert(TypeCount::value_type(type, 0)).first;
426 (*ci).second += addend;
427 nassertv((*ci).second >= 0);
429 #endif // THREADED_PIPELINE && DEBUG_THREADS
void set_num_stages(int num_stages)
Specifies the number of stages required for the pipeline.
This just stores the pointers to implement a doubly-linked list of PipelineCyclers for a particular P...
This is our own Panda specialization on the default STL vector.
void cycle()
Flows all the pipeline data down to the next stage.
A base class for all things which can have a name.
Similar to MutexHolder, but for a reentrant mutex.
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
This is a convenience class to specialize ConfigVariable as an integer type.
TypeHandle is the identifier used to differentiate C++ class types.