Panda3D

pipelineCycler.h

00001 // Filename: pipelineCycler.h
00002 // Created by:  drose (21Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef PIPELINECYCLER_H
00016 #define PIPELINECYCLER_H
00017 
00018 #include "pandabase.h"
00019 #include "pipelineCyclerBase.h"
00020 #include "cyclerHolder.h"
00021 #include "thread.h"
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //       Class : PipelineCycler
00025 // Description : This class maintains different copies of a page of
00026 //               data between stages of the graphics pipeline (or any
00027 //               other pipelining context).
00028 //
00029 //               The class object maintains up to n copies of a
00030 //               CycleData structure, one for each stage of the
00031 //               pipeline.  The head of the pipeline is responsible
00032 //               for making changes to its copy, which are then cycled
00033 //               through the pipeline at each frame.
00034 //
00035 //               To access the data, you must first ask for a readable
00036 //               pointer.  In order to make changes to the data, you
00037 //               must ask for a writable pointer.  Both kinds of
00038 //               pointers should be released when you are done, as a
00039 //               sanity check.  The CycleDataReader and
00040 //               CycleDataWriter classes transparently handle this.
00041 //
00042 //               If pipelining support is not enabled at compile time
00043 //               (that is, SUPPORT_PIPELINING is not defined), this
00044 //               object compiles to a minimum object that presents the
00045 //               same interface but with minimal runtime overhead.
00046 //               (Actually, this isn't true yet, but it will be one
00047 //               day.)
00048 //
00049 //               We define this as a struct instead of a class to
00050 //               guarantee byte placement within the object, so that
00051 //               (particularly for the trivial implementation) the
00052 //               inherited struct's data is likely to be placed by the
00053 //               compiler at the "this" pointer.
00054 ////////////////////////////////////////////////////////////////////
00055 template<class CycleDataType>
00056 struct PipelineCycler : public PipelineCyclerBase {
00057 public:
00058   INLINE PipelineCycler(Pipeline *pipeline = NULL);
00059   INLINE PipelineCycler(const PipelineCycler<CycleDataType> &copy);
00060   INLINE void operator = (const PipelineCycler<CycleDataType> &copy);
00061 
00062   INLINE const CycleDataType *read_unlocked(Thread *current_thread) const;
00063   INLINE const CycleDataType *read(Thread *current_thread) const;
00064   INLINE CycleDataType *write(Thread *current_thread);
00065   INLINE CycleDataType *write_upstream(bool force_to_0, Thread *current_thread);
00066   INLINE CycleDataType *elevate_read(const CycleDataType *pointer, Thread *current_thread);
00067   INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
00068 
00069   INLINE const CycleDataType *read_stage_unlocked(int pipeline_stage) const;
00070   INLINE const CycleDataType *read_stage(int pipeline_stage, Thread *current_thread) const;
00071   INLINE CycleDataType *elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread);
00072   INLINE CycleDataType *elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
00073   INLINE CycleDataType *write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread);
00074   INLINE CycleDataType *write_stage(int pipeline_stage, Thread *current_thread);
00075 
00076   INLINE CycleDataType *cheat() const;
00077 
00078 #ifndef DO_PIPELINING
00079 private:
00080   // If we are *not* compiling in support for pipelining, we just
00081   // store the CycleData object right here.  No pointers needed.
00082   CycleDataType _typed_data;
00083 #endif  // !DO_PIPELINING
00084 };
00085 
00086 // These macros are handy for iterating through the set of pipeline
00087 // stages.  They're particularly useful for updating cache values
00088 // upstream of the current stage, or for removing bad pointers from
00089 // all stages of the pipeline.  In each case, the variable
00090 // pipeline_stage is defined within the loop to be the current stage
00091 // of the pipeline traversed by the loop.
00092 #ifdef DO_PIPELINING
00093 
00094 // Iterates through all of the pipeline stages upstream of the current
00095 // stage, but not including the current stage.
00096 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) {        \
00097     CyclerHolder cholder(cycler);                                   \
00098     int pipeline_stage;                                             \
00099     for (pipeline_stage = current_thread->get_pipeline_stage() - 1; \
00100          pipeline_stage >= 0;                                       \
00101          --pipeline_stage)
00102 
00103 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler)     \
00104   }
00105 
00106 // Iterates through all of the pipeline stages upstream of the current
00107 // stage, and including the current stage.
00108 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
00109     CyclerHolder cholder(cycler);                                   \
00110     int pipeline_stage;                                             \
00111     for (pipeline_stage = current_thread->get_pipeline_stage();     \
00112          pipeline_stage >= 0;                                       \
00113          --pipeline_stage)
00114 
00115 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler)      \
00116   }
00117 
00118 // As above, but without holding the cycler lock during the loop.
00119 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) {  \
00120     int pipeline_stage;                                             \
00121     for (pipeline_stage = current_thread->get_pipeline_stage();    \
00122          pipeline_stage >= 0;                                       \
00123          --pipeline_stage)
00124 
00125 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler)   \
00126   }
00127 
00128 // Iterates through all of the pipeline stages.
00129 #define OPEN_ITERATE_ALL_STAGES(cycler) {                           \
00130     int pipeline_stage;                                             \
00131     for (pipeline_stage = (cycler).get_num_stages() - 1;            \
00132          pipeline_stage >= 0;                                       \
00133          --pipeline_stage)
00134 
00135 #define CLOSE_ITERATE_ALL_STAGES(cycler)        \
00136   }
00137 
00138 #else  // DO_PIPELINING
00139 
00140 // These are trivial implementations of the above macros, defined when
00141 // pipelining is not enabled, that simply operate on stage 0 without
00142 // bothering to create a for loop.
00143 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread)      \
00144   if (false) {                                  \
00145     const int pipeline_stage = -1;                   
00146 
00147 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler)     \
00148   }
00149 
00150 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) {                     \
00151     const int pipeline_stage = 0;                                       \
00152     
00153 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler)      \
00154   }
00155 
00156 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) {  \
00157     const int pipeline_stage = 0;                                       \
00158     
00159 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler)   \
00160   }
00161 
00162 #define OPEN_ITERATE_ALL_STAGES(cycler) {                               \
00163     const int pipeline_stage = 0;                                       \
00164     
00165 #define CLOSE_ITERATE_ALL_STAGES(cycler)        \
00166   }
00167 
00168 #endif  // DO_PIPELINING
00169 
00170 #include "pipelineCycler.I"
00171 
00172 #endif
00173 
 All Classes Functions Variables Enumerations