Browse Source

comment on threading

David Rose 20 years ago
parent
commit
0fc8016840
1 changed files with 75 additions and 0 deletions
  1. 75 0
      panda/src/display/graphicsEngine.h

+ 75 - 0
panda/src/display/graphicsEngine.h

@@ -179,6 +179,81 @@ private:
   // The WindowRenderer class records the stages of the pipeline that
   // The WindowRenderer class records the stages of the pipeline that
   // each thread (including the main thread, a.k.a. "app") should
   // each thread (including the main thread, a.k.a. "app") should
   // process, and the list of windows for each stage.
   // process, and the list of windows for each stage.
+
+  // There is one WindowRenderer instance for app, and another
+  // instance for each thread (the thread-specific WindowRenderers are
+  // actually instances of RenderThread, below, which inherits from
+  // WindowRenderer).
+
+  // The idea is that each window is associated with one or more
+  // WindowRenderer objects, according to the threads in which its
+  // rendering tasks (window, cull, and draw) are divided into.
+
+  // The "window" task is responsible for doing any updates to the
+  // window itself, such as size and placement, and is wholly
+  // responsible for any API calls to the windowing system itself,
+  // unrelated to OpenGL-type calls.  This is normally done in app
+  // (the design of X-Windows is such that all X calls must be issued
+  // in the same thread).
+
+  // The "cull" task is responsible for crawling through the scene
+  // graph and discovering all of the Geoms that are within the
+  // viewing frustum.  It assembles all such Geoms, along with their
+  // computed net state and transform, in a linked list of
+  // CullableObjects, which it stores for the "draw" task, next.
+
+  // The "draw" task is responsible for walking through the list of
+  // CullableObjects recorded by the cull task, and issuing the
+  // appropriate graphics commands to draw them.
+
+  // There is an additional task, not often used, called "cdraw".
+  // This task, if activated, will crawl through the scene graph and
+  // issue graphics commands immediately, as each Geom is discovered.
+  // It is only rarely used because it cannot perform sorting beyond
+  // basic scene graph order, making it less useful than a separate
+  // cull and draw task.
+
+  // It is possible for all three of the normal tasks: window, cull,
+  // and draw, to be handled by the same thread.  This is the normal,
+  // single-threaded model: all tasks are handled by the app thread.
+  // In this case, the window will be added to _app's _window, _cull,
+  // and _draw lists.
+
+  // On the other hand, a window's tasks may also be distributed among
+  // as many as three threads.  For instance, if the window is listed
+  // on _app's _window list, but on thread A's _cull list, and thread
+  // B's _draw list, then the window task will be handled in the app
+  // thread, while the cull task will be handled by thread A, and the
+  // draw task will be handled (in parallel) by thread B.  (In order
+  // for this to work, it will be necessary that thread A and B are
+  // configured to view different stages of the graphics pipeline.
+  // This is a more advanced topic than there is room to discuss in
+  // this comment.)
+
+  // Manipulation of the various window lists in each WindowRenderer
+  // object is always performed in the app thread.  The auxiliary
+  // threads are slaves to the app thread, and they can only perform
+  // one of a handful of specified tasks, none of which includes
+  // adding or removing windows from its lists.  The full set of tasks
+  // that a WindowRenderer may perform is enumerated in ThreadState,
+  // above; see RenderThread::thread_main().
+
+  // There is a pair of condition variables for each thread, _cv_start
+  // and _cv_done, that is used to synchronize requests made by app to
+  // a particular thread.  The usual procedure to request a thread to
+  // perform a particular task is the following: the app thread waits
+  // on the thread's _cv_done variable, stores the value corresponding
+  // to the desired task in the thread's _thread_state value, then
+  // signals the thread's _cv_start variable.  The thread, in turn,
+  // will perform its requested task, set its _thread_state to
+  // TS_wait, and signal _cv_done.  See examples in the code,
+  // e.g. open_windows(), for more details on this process.
+
+  // It is of course not necessary to signal any threads in order to
+  // perform tasks listed in the _app WindowRenderer.  For this object
+  // only, we simply call the appropriate methods on _app when we want
+  // the tasks to be performed.
+
   class WindowRenderer {
   class WindowRenderer {
   public:
   public:
     void add_gsg(GraphicsStateGuardian *gsg);
     void add_gsg(GraphicsStateGuardian *gsg);