Panda3D
 All Classes Functions Variables Enumerations
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, DO_PIPELINING is not defined), this object
00044 //               compiles to a minimum object that presents the same
00045 //               interface but with minimal runtime overhead.
00046 //
00047 //               We define this as a struct instead of a class to
00048 //               guarantee byte placement within the object, so that
00049 //               (particularly for the trivial implementation) the
00050 //               inherited struct's data is likely to be placed by the
00051 //               compiler at the "this" pointer.
00052 ////////////////////////////////////////////////////////////////////
00053 template<class CycleDataType>
00054 struct PipelineCycler : public PipelineCyclerBase {
00055 public:
00056   INLINE PipelineCycler(Pipeline *pipeline = NULL);
00057   INLINE PipelineCycler(const PipelineCycler<CycleDataType> &copy);
00058   INLINE void operator = (const PipelineCycler<CycleDataType> &copy);
00059 
00060   INLINE const CycleDataType *read_unlocked(Thread *current_thread) const;
00061   INLINE const CycleDataType *read(Thread *current_thread) const;
00062   INLINE CycleDataType *write(Thread *current_thread);
00063   INLINE CycleDataType *write_upstream(bool force_to_0, Thread *current_thread);
00064   INLINE CycleDataType *elevate_read(const CycleDataType *pointer, Thread *current_thread);
00065   INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
00066 
00067   INLINE const CycleDataType *read_stage_unlocked(int pipeline_stage) const;
00068   INLINE const CycleDataType *read_stage(int pipeline_stage, Thread *current_thread) const;
00069   INLINE CycleDataType *elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread);
00070   INLINE CycleDataType *elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
00071   INLINE CycleDataType *write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread);
00072   INLINE CycleDataType *write_stage(int pipeline_stage, Thread *current_thread);
00073 
00074   INLINE CycleDataType *cheat() const;
00075 
00076 #ifndef DO_PIPELINING
00077 private:
00078   // If we are *not* compiling in support for pipelining, we just
00079   // store the CycleData object right here.  No pointers needed.
00080   CycleDataType _typed_data;
00081 #endif  // !DO_PIPELINING
00082 };
00083 
00084 // These macros are handy for iterating through the set of pipeline
00085 // stages.  They're particularly useful for updating cache values
00086 // upstream of the current stage, or for removing bad pointers from
00087 // all stages of the pipeline.  In each case, the variable
00088 // pipeline_stage is defined within the loop to be the current stage
00089 // of the pipeline traversed by the loop.
00090 #ifdef DO_PIPELINING
00091 
00092 // Iterates through all of the pipeline stages upstream of the current
00093 // stage, but not including the current stage.
00094 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) {        \
00095     CyclerHolder cholder(cycler);                                   \
00096     int pipeline_stage;                                             \
00097     for (pipeline_stage = current_thread->get_pipeline_stage() - 1; \
00098          pipeline_stage >= 0;                                       \
00099          --pipeline_stage)
00100 
00101 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler)     \
00102   }
00103 
00104 // Iterates through all of the pipeline stages upstream of the current
00105 // stage, and including the current stage.
00106 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
00107     CyclerHolder cholder(cycler);                                   \
00108     int pipeline_stage;                                             \
00109     for (pipeline_stage = current_thread->get_pipeline_stage();     \
00110          pipeline_stage >= 0;                                       \
00111          --pipeline_stage)
00112 
00113 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler)      \
00114   }
00115 
00116 // As above, but without holding the cycler lock during the loop.
00117 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) {  \
00118     int pipeline_stage;                                             \
00119     for (pipeline_stage = current_thread->get_pipeline_stage();    \
00120          pipeline_stage >= 0;                                       \
00121          --pipeline_stage)
00122 
00123 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler)   \
00124   }
00125 
00126 // Iterates through all of the pipeline stages.
00127 #define OPEN_ITERATE_ALL_STAGES(cycler) {                           \
00128     int pipeline_stage;                                             \
00129     for (pipeline_stage = (cycler).get_num_stages() - 1;            \
00130          pipeline_stage >= 0;                                       \
00131          --pipeline_stage)
00132 
00133 #define CLOSE_ITERATE_ALL_STAGES(cycler)        \
00134   }
00135 
00136 #else  // DO_PIPELINING
00137 
00138 // These are trivial implementations of the above macros, defined when
00139 // pipelining is not enabled, that simply operate on stage 0 without
00140 // bothering to create a for loop.
00141 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread)      \
00142   if (false) {                                  \
00143     const int pipeline_stage = -1;                   
00144 
00145 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler)     \
00146   }
00147 
00148 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) {                     \
00149     const int pipeline_stage = 0;                                       \
00150     
00151 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler)      \
00152   }
00153 
00154 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) {  \
00155     const int pipeline_stage = 0;                                       \
00156     
00157 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler)   \
00158   }
00159 
00160 #define OPEN_ITERATE_ALL_STAGES(cycler) {                               \
00161     const int pipeline_stage = 0;                                       \
00162     
00163 #define CLOSE_ITERATE_ALL_STAGES(cycler)        \
00164   }
00165 
00166 #endif  // DO_PIPELINING
00167 
00168 #include "pipelineCycler.I"
00169 
00170 #endif
00171 
 All Classes Functions Variables Enumerations