Panda3D
|
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> ©); 00058 INLINE void operator = (const PipelineCycler<CycleDataType> ©); 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