فهرست منبع

restore automatic pipeline expansion

David Rose 20 سال پیش
والد
کامیت
bf965cae20

+ 1 - 0
panda/src/display/graphicsEngine.cxx

@@ -1605,6 +1605,7 @@ 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;

+ 2 - 0
panda/src/putil/Sources.pp

@@ -51,6 +51,7 @@
     nodePointerTo.h nodePointerTo.I \
     pipeline.h pipeline.I \
     pipelineCycler.h pipelineCycler.I \
+    pipelineCyclerLinks.h pipelineCyclerLinks.I \
     pipelineCyclerBase.h  \
     pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
     pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \
@@ -152,6 +153,7 @@
     nodePointerTo.h nodePointerTo.I \
     pipeline.h pipeline.I \
     pipelineCycler.h pipelineCycler.I \
+    pipelineCyclerLinks.h pipelineCyclerLinks.I \
     pipelineCyclerBase.h \
     pipelineCyclerDummyImpl.h pipelineCyclerDummyImpl.I \
     pipelineCyclerTrivialImpl.h pipelineCyclerTrivialImpl.I \

+ 11 - 0
panda/src/putil/pipeline.I

@@ -30,6 +30,17 @@ 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

+ 70 - 9
panda/src/putil/pipeline.cxx

@@ -30,13 +30,20 @@ Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
 ////////////////////////////////////////////////////////////////////
 Pipeline::
 Pipeline(const string &name, int num_stages) :
-  Namable(name),
-  _num_stages(num_stages)
+  Namable(name)
 {
 #ifdef THREADED_PIPELINE
+  // Set up the linked list of cyclers to be a circular list that
+  // begins with this object.
+  _prev = this;
+  _next = this;
+
   _num_cyclers = 0;
   _cycling = false;
+
 #endif  // THREADED_PIPELINE
+
+  set_num_stages(num_stages);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -48,6 +55,9 @@ Pipeline::
 ~Pipeline() {
 #ifdef THREADED_PIPELINE
   nassertv(_num_cyclers == 0);
+  nassertv(_prev == this && _next == this);
+  _prev = NULL;
+  _next = NULL;
   nassertv(!_cycling);
 #endif  // THREADED_PIPELINE
 }
@@ -148,6 +158,54 @@ 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 attached to this
+    // pipeline before we can adjust the number of stages.
+    PipelineCyclerLinks *links;
+    for (links = this->_next; links != this; links = links->_next) {
+      PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
+      cycler->_lock.lock();
+    }
+
+    _num_stages = num_stages;
+
+    for (links = this->_next; links != this; links = links->_next) {
+      PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
+      cycler->set_num_stages(num_stages);
+    }
+
+    // Now release them all.
+    int count = 0;
+    for (links = this->_next; links != this; links = links->_next) {
+      PipelineCyclerTrueImpl *cycler = (PipelineCyclerTrueImpl *)links;
+      cycler->_lock.release();
+      ++count;
+    }
+    nassertv(count == _num_cyclers);
+  }
+
+#else  // THREADED_PIPELINE
+  if (_num_stages != 1) {
+    display_cat.warning()
+      << "Requested " << pipeline_stages
+      << " pipeline stages but multithreaded render pipelines not enabled in build.\n";
+  }
+  _num_stages = 1;
+#endif  // THREADED_PIPELINE
+}
+
 #ifdef THREADED_PIPELINE
 ////////////////////////////////////////////////////////////////////
 //     Function: Pipeline::add_cycler
@@ -162,7 +220,8 @@ add_cycler(PipelineCyclerTrueImpl *cycler) {
   nassertv(!cycler->_dirty);
   nassertv(!_cycling);
   ++_num_cyclers;
-
+  cycler->insert_before(this);
+  
 #ifdef DEBUG_THREADS
   inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), 1);
 #endif
@@ -213,6 +272,7 @@ remove_cycler(PipelineCyclerTrueImpl *cycler) {
   nassertv(!_cycling);
 
   --_num_cyclers;
+  cycler->remove_from_list();
 
 #ifdef DEBUG_THREADS
   inc_cycler_type(_all_cycler_types, cycler->get_parent_type(), -1);
@@ -280,12 +340,13 @@ 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."));
+     PRC_DESC("The initial number of stages in the render pipeline.  This is "
+              "only meaningful if threaded pipelining is compiled into "
+              "Panda.  In most cases, you should not set this at all anyway, "
+              "since the pipeline can automatically grow stages as needed, "
+              "but it will not remove stages automatically, and having more "
+              "pipeline stages than your application requires will incur "
+              "additional runtime overhead."));
 
   nassertv(_render_pipeline == (Pipeline *)NULL);
   _render_pipeline = new Pipeline("render", pipeline_stages);

+ 4 - 1
panda/src/putil/pipeline.h

@@ -20,6 +20,7 @@
 #define PIPELINE_H
 
 #include "pandabase.h"
+#include "pipelineCyclerLinks.h"
 #include "namable.h"
 #include "pset.h"
 #include "reMutex.h"
@@ -40,7 +41,7 @@ struct PipelineCyclerTrueImpl;
 //               pipeline.  Other specialty pipelines may be created
 //               as needed.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA Pipeline : public Namable {
+class EXPCL_PANDA Pipeline : public PipelineCyclerLinks, public Namable {
 public:
   Pipeline(const string &name, int num_stages);
   ~Pipeline();
@@ -49,6 +50,8 @@ public:
 
   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

+ 83 - 0
panda/src/putil/pipelineCyclerLinks.I

@@ -0,0 +1,83 @@
+// Filename: pipelineCyclerLinks.I
+// Created by:  drose (16Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+#ifdef THREADED_PIPELINE
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerLinks::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE PipelineCyclerLinks::
+PipelineCyclerLinks() {
+#ifndef NDEBUG
+  _next = NULL;
+  _prev = NULL;
+#endif
+}
+#endif  // THREADED_PIPELINE
+
+#ifdef THREADED_PIPELINE
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerLinks::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE PipelineCyclerLinks::
+~PipelineCyclerLinks() {
+  nassertv(_next == NULL && _prev == NULL);
+}
+#endif  // THREADED_PIPELINE
+
+#ifdef THREADED_PIPELINE
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerLinks::remove_from_list
+//       Access: Private
+//  Description: Removes a PipelineCyclerLinks record from the
+//               doubly-linked list.
+////////////////////////////////////////////////////////////////////
+INLINE void PipelineCyclerLinks::
+remove_from_list() {
+  nassertv(_prev->_next == this && _next->_prev == this);
+  _prev->_next = _next;
+  _next->_prev = _prev;
+#ifndef NDEBUG
+  _next = NULL;
+  _prev = NULL;
+#endif
+}
+#endif  // THREADED_PIPELINE
+
+#ifdef THREADED_PIPELINE
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerLinks::insert_before
+//       Access: Private
+//  Description: Adds a PipelineCyclerLinks record before the indicated
+//               node in the doubly-linked list.
+////////////////////////////////////////////////////////////////////
+INLINE void PipelineCyclerLinks::
+insert_before(PipelineCyclerLinks *node) {
+  nassertv(node->_prev->_next == node && node->_next->_prev == node);
+  nassertv(_prev == (PipelineCyclerLinks *)NULL &&
+           _next == (PipelineCyclerLinks *)NULL);
+  _prev = node->_prev;
+  _next = node;
+  _prev->_next = this;
+  node->_prev = this;
+}
+#endif  // THREADED_PIPELINE

+ 54 - 0
panda/src/putil/pipelineCyclerLinks.h

@@ -0,0 +1,54 @@
+// Filename: pipelineCyclerLinks.h
+// Created by:  drose (16Feb06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PIPELINECYCLERLINKS_H
+#define PIPELINECYCLERLINKS_H
+
+#include "pandabase.h"
+#include "selectThreadImpl.h"  // for THREADED_PIPELINE definition
+
+////////////////////////////////////////////////////////////////////
+//       Class : PipelineCyclerLinks
+// Description : This just stores the pointers to implement a
+//               doubly-linked list of PipelineCyclers for a
+//               particular Pipeline object.  We use a hand-rolled
+//               linked list rather than any STL container, because we
+//               want PipelineCyclers to be able to add and remove
+//               themselves from this list very quickly.
+//
+//               These pointers are inherited from this separate class
+//               so the Pipeline object itself can be the root of the
+//               linked list.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA PipelineCyclerLinks {
+protected:
+#ifdef THREADED_PIPELINE
+  INLINE PipelineCyclerLinks();
+  INLINE ~PipelineCyclerLinks();
+
+  INLINE void remove_from_list();
+  INLINE void insert_before(PipelineCyclerLinks *node);
+
+  PipelineCyclerLinks *_prev, *_next;
+#endif
+  friend class Pipeline;
+};
+
+#include "pipelineCyclerLinks.I"
+
+#endif

+ 3 - 3
panda/src/putil/pipelineCyclerTrueImpl.cxx

@@ -18,7 +18,7 @@
 
 #include "pipelineCyclerTrueImpl.h"
 
-#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
+#ifdef THREADED_PIPELINE
 
 #include "config_util.h"
 #include "pipeline.h"
@@ -343,8 +343,8 @@ void PipelineCyclerTrueImpl::CyclerMutex::
 output(ostream &out) const {
   _cycler->cheat()->output(out);
 }
-#endif
+#endif  // DEBUG_THREADS
 
-#endif  // DO_PIPELINING && HAVE_THREADS
+#endif  // THREADED_PIPELINE
 
 

+ 7 - 4
panda/src/putil/pipelineCyclerTrueImpl.h

@@ -21,8 +21,9 @@
 
 #include "pandabase.h"
 
-#if defined(DO_PIPELINING) && defined(HAVE_THREADS)
+#ifdef THREADED_PIPELINE
 
+#include "pipelineCyclerLinks.h"
 #include "cycleData.h"
 #include "pointerTo.h"
 #include "thread.h"
@@ -46,7 +47,9 @@ class Pipeline;
 //               mainly to be consistent with
 //               PipelineCyclerTrivialImpl.
 ////////////////////////////////////////////////////////////////////
-struct EXPCL_PANDA PipelineCyclerTrueImpl {
+struct EXPCL_PANDA PipelineCyclerTrueImpl : public PipelineCyclerLinks {
+private:
+  PipelineCyclerTrueImpl();
 public:
   PipelineCyclerTrueImpl(CycleData *initial_data, Pipeline *pipeline = NULL);
   PipelineCyclerTrueImpl(const PipelineCyclerTrueImpl &copy);
@@ -91,7 +94,7 @@ public:
 #ifdef DEBUG_THREADS
     virtual void output(ostream &out) const;
     PipelineCyclerTrueImpl *_cycler;
-#endif
+#endif  // DEBUG_THREADS
   };
 
 private:
@@ -115,7 +118,7 @@ private:
 
 #include "pipelineCyclerTrueImpl.I"
 
-#endif  // DO_PIPELINING && HAVE_THREADS
+#endif  // THREADED_PIPELINE
 
 #endif