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
32 _num_stages(num_stages),
38 #ifdef THREADED_PIPELINE 56 _num_dirty_cyclers = 0;
62 if (num_stages != 1) {
63 pipeline_cat.warning()
64 <<
"Requested " << num_stages
65 <<
" pipeline stages but multithreaded render pipelines not enabled in build.\n";
67 #endif // THREADED_PIPELINE 69 nassertv(num_stages >= 1);
79 #ifdef THREADED_PIPELINE 80 nassertv(_num_cyclers == 0);
81 nassertv(_num_dirty_cyclers == 0);
85 #endif // THREADED_PIPELINE 95 #ifdef THREADED_PIPELINE 96 if (pipeline_cat.is_debug()) {
98 <<
"Beginning the pipeline cycle\n";
102 saved_cdatas.reserve(_num_dirty_cyclers);
105 if (_num_stages == 1) {
107 nassertv(_dirty._next == &_dirty);
116 prev_dirty.make_head();
117 prev_dirty.take_list(_dirty);
118 _num_dirty_cyclers = 0;
120 switch (_num_stages) {
122 while (prev_dirty._next != &prev_dirty) {
123 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
124 cycler->remove_from_list();
130 saved_cdatas.push_back(cycler->cycle_2());
132 if (cycler->_dirty) {
135 cycler->insert_before(&_dirty);
136 ++_num_dirty_cyclers;
139 cycler->insert_before(&_clean);
141 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
148 while (prev_dirty._next != &prev_dirty) {
149 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
150 cycler->remove_from_list();
153 saved_cdatas.push_back(cycler->cycle_3());
155 if (cycler->_dirty) {
156 cycler->insert_before(&_dirty);
157 ++_num_dirty_cyclers;
159 cycler->insert_before(&_clean);
161 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
168 while (prev_dirty._next != &prev_dirty) {
169 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)prev_dirty._next;
170 cycler->remove_from_list();
173 saved_cdatas.push_back(cycler->cycle());
175 if (cycler->_dirty) {
176 cycler->insert_before(&_dirty);
177 ++_num_dirty_cyclers;
179 cycler->insert_before(&_clean);
181 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
189 prev_dirty.clear_head();
197 saved_cdatas.clear();
199 if (pipeline_cat.is_debug()) {
201 <<
"Finished the pipeline cycle\n";
204 #endif // THREADED_PIPELINE 215 nassertv(num_stages >= 1);
216 #ifdef THREADED_PIPELINE 218 if (num_stages != _num_stages) {
223 for (links = _clean._next; links != &_clean; links = links->_next) {
224 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
225 cycler->_lock.acquire();
227 for (links = _dirty._next; links != &_dirty; links = links->_next) {
228 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
229 cycler->_lock.acquire();
232 _num_stages = num_stages;
234 for (links = _clean._next; links != &_clean; links = links->_next) {
235 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
236 cycler->set_num_stages(num_stages);
238 for (links = _dirty._next; links != &_dirty; links = links->_next) {
239 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
240 cycler->set_num_stages(num_stages);
245 for (links = _clean._next; links != &_clean; links = links->_next) {
246 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
247 cycler->_lock.release();
250 for (links = _dirty._next; links != &_dirty; links = links->_next) {
251 PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
252 cycler->_lock.release();
255 nassertv(count == _num_cyclers);
258 #else // THREADED_PIPELINE 259 if (num_stages != 1) {
260 pipeline_cat.warning()
261 <<
"Requested " << num_stages
262 <<
" pipeline stages but multithreaded render pipelines not enabled in build.\n";
265 #endif // THREADED_PIPELINE 268 #ifdef THREADED_PIPELINE 277 add_cycler(PipelineCyclerTrueImpl *cycler) {
279 nassertv(!cycler->_dirty);
282 cycler->insert_before(&_clean);
286 inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), 1);
289 #endif // THREADED_PIPELINE 291 #ifdef THREADED_PIPELINE 302 add_dirty_cycler(PipelineCyclerTrueImpl *cycler) {
303 nassertv(cycler->_lock.debug_is_locked());
306 nassertv(_num_stages != 1);
308 nassertv(!cycler->_dirty);
311 cycler->remove_from_list();
312 cycler->insert_before(&_dirty);
313 cycler->_dirty =
true;
314 ++_num_dirty_cyclers;
317 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), 1);
320 #endif // THREADED_PIPELINE 322 #ifdef THREADED_PIPELINE 331 remove_cycler(PipelineCyclerTrueImpl *cycler) {
332 nassertv(cycler->_lock.debug_is_locked());
338 cycler->remove_from_list();
341 inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
344 if (cycler->_dirty) {
345 cycler->_dirty =
false;
346 --_num_dirty_cyclers;
348 inc_cycler_type(_dirty_cycler_types, cycler->get_parent_type(), -1);
352 #endif // THREADED_PIPELINE 354 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS) 367 iterate_all_cycler_types(CallbackFunc *func,
void *data)
const {
369 TypeCount::const_iterator ci;
370 for (ci = _all_cycler_types.begin(); ci != _all_cycler_types.end(); ++ci) {
371 func((*ci).first, (*ci).second, data);
374 #endif // THREADED_PIPELINE && DEBUG_THREADS 376 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS) 386 iterate_dirty_cycler_types(CallbackFunc *func,
void *data)
const {
388 TypeCount::const_iterator ci;
389 for (ci = _dirty_cycler_types.begin(); ci != _dirty_cycler_types.end(); ++ci) {
390 func((*ci).first, (*ci).second, data);
393 #endif // THREADED_PIPELINE && DEBUG_THREADS 401 make_render_pipeline() {
403 (
"pipeline-stages", 1,
404 PRC_DESC(
"The initial number of stages in the render pipeline. This is " 405 "only meaningful if threaded pipelining is compiled into " 406 "Panda. In most cases, you should not set this at all anyway, " 407 "since the pipeline can automatically grow stages as needed, " 408 "but it will not remove stages automatically, and having more " 409 "pipeline stages than your application requires will incur " 410 "additional runtime overhead."));
412 nassertv(_render_pipeline == (
Pipeline *)NULL);
413 _render_pipeline =
new Pipeline(
"render", pipeline_stages);
416 #if defined(THREADED_PIPELINE) && defined(DEBUG_THREADS) 429 inc_cycler_type(TypeCount &count,
TypeHandle type,
int addend) {
430 TypeCount::iterator ci = count.find(type);
431 if (ci == count.end()) {
432 ci = count.insert(TypeCount::value_type(type, 0)).first;
434 (*ci).second += addend;
435 nassertv((*ci).second >= 0);
437 #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.