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