Panda3D
pipelineCycler.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pipelineCycler.h
10  * @author drose
11  * @date 2002-02-21
12  */
13 
14 #ifndef PIPELINECYCLER_H
15 #define PIPELINECYCLER_H
16 
17 #include "pandabase.h"
18 #include "pipelineCyclerBase.h"
19 #include "cyclerHolder.h"
20 #include "thread.h"
21 
22 /**
23  * This class maintains different copies of a page of data between stages of
24  * the graphics pipeline (or any other pipelining context).
25  *
26  * The class object maintains up to n copies of a CycleData structure, one for
27  * each stage of the pipeline. The head of the pipeline is responsible for
28  * making changes to its copy, which are then cycled through the pipeline at
29  * each frame.
30  *
31  * To access the data, you must first ask for a readable pointer. In order to
32  * make changes to the data, you must ask for a writable pointer. Both kinds
33  * of pointers should be released when you are done, as a sanity check. The
34  * CycleDataReader and CycleDataWriter classes transparently handle this.
35  *
36  * If pipelining support is not enabled at compile time (that is,
37  * DO_PIPELINING is not defined), this object compiles to a minimum object
38  * that presents the same interface but with minimal runtime overhead.
39  *
40  * We define this as a struct instead of a class to guarantee byte placement
41  * within the object, so that (particularly for the trivial implementation)
42  * the inherited struct's data is likely to be placed by the compiler at the
43  * "this" pointer.
44  */
45 template<class CycleDataType>
47 public:
48  INLINE PipelineCycler(Pipeline *pipeline = nullptr);
49  INLINE PipelineCycler(CycleDataType &&initial_data, Pipeline *pipeline = nullptr);
50 
52  INLINE void operator = (const PipelineCycler<CycleDataType> &copy);
53 
54  INLINE const CycleDataType *read_unlocked(Thread *current_thread) const;
55  INLINE const CycleDataType *read(Thread *current_thread) const;
56  INLINE CycleDataType *write(Thread *current_thread);
57  INLINE CycleDataType *write_upstream(bool force_to_0, Thread *current_thread);
58  INLINE CycleDataType *elevate_read(const CycleDataType *pointer, Thread *current_thread);
59  INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
60 
61  INLINE const CycleDataType *read_stage_unlocked(int pipeline_stage) const;
62  INLINE const CycleDataType *read_stage(int pipeline_stage, Thread *current_thread) const;
63  INLINE CycleDataType *elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread);
64  INLINE CycleDataType *elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
65  INLINE CycleDataType *write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread);
66  INLINE CycleDataType *write_stage(int pipeline_stage, Thread *current_thread);
67 
68  INLINE CycleDataType *cheat() const;
69 
70 #ifndef DO_PIPELINING
71 private:
72  // If we are *not* compiling in support for pipelining, we just store the
73  // CycleData object right here. No pointers needed.
74  CycleDataType _typed_data;
75 #endif // !DO_PIPELINING
76 };
77 
78 // These macros are handy for iterating through the set of pipeline stages.
79 // They're particularly useful for updating cache values upstream of the
80 // current stage, or for removing bad pointers from all stages of the
81 // pipeline. In each case, the variable pipeline_stage is defined within the
82 // loop to be the current stage of the pipeline traversed by the loop.
83 #ifdef DO_PIPELINING
84 
85 // Iterates through all of the pipeline stages upstream of the current stage,
86 // but not including the current stage.
87 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) { \
88  CyclerHolder cholder(cycler); \
89  int pipeline_stage; \
90  for (pipeline_stage = current_thread->get_pipeline_stage() - 1; \
91  pipeline_stage >= 0; \
92  --pipeline_stage)
93 
94 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler) \
95  }
96 
97 // Iterates through all of the pipeline stages upstream of the current stage,
98 // and including the current stage.
99 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
100  CyclerHolder cholder(cycler); \
101  int pipeline_stage; \
102  for (pipeline_stage = current_thread->get_pipeline_stage(); \
103  pipeline_stage >= 0; \
104  --pipeline_stage)
105 
106 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler) \
107  }
108 
109 // As above, but without holding the cycler lock during the loop.
110 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) { \
111  int pipeline_stage; \
112  for (pipeline_stage = current_thread->get_pipeline_stage(); \
113  pipeline_stage >= 0; \
114  --pipeline_stage)
115 
116 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) \
117  }
118 
119 // Iterates through all of the pipeline stages.
120 #define OPEN_ITERATE_ALL_STAGES(cycler) { \
121  int pipeline_stage; \
122  for (pipeline_stage = (cycler).get_num_stages() - 1; \
123  pipeline_stage >= 0; \
124  --pipeline_stage)
125 
126 #define CLOSE_ITERATE_ALL_STAGES(cycler) \
127  }
128 
129 #else // DO_PIPELINING
130 
131 // These are trivial implementations of the above macros, defined when
132 // pipelining is not enabled, that simply operate on stage 0 without bothering
133 // to create a for loop.
134 #define OPEN_ITERATE_UPSTREAM_ONLY(cycler, current_thread) \
135  if (false) { \
136  const int pipeline_stage = -1;
137 
138 #define CLOSE_ITERATE_UPSTREAM_ONLY(cycler) \
139  }
140 
141 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM(cycler, current_thread) { \
142  const int pipeline_stage = 0; \
143 
144 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM(cycler) \
145  }
146 
147 #define OPEN_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler, current_thread) { \
148  const int pipeline_stage = 0; \
149 
150 #define CLOSE_ITERATE_CURRENT_AND_UPSTREAM_NOLOCK(cycler) \
151  }
152 
153 #define OPEN_ITERATE_ALL_STAGES(cycler) { \
154  const int pipeline_stage = 0; \
155 
156 #define CLOSE_ITERATE_ALL_STAGES(cycler) \
157  }
158 
159 #endif // DO_PIPELINING
160 
161 #include "pipelineCycler.I"
162 
163 #endif
This class maintains different copies of a page of data between stages of the graphics pipeline (or a...
CycleDataType * elevate_read(const CycleDataType *pointer, Thread *current_thread)
See PipelineCyclerBase::elevate_read().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the trivial, non-threaded implementation of PipelineCyclerBase.
CycleDataType * cheat() const
Returns a pointer without counting it.
CycleDataType * elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::elevate_read_stage_upstream().
const CycleDataType * read_stage(int pipeline_stage, Thread *current_thread) const
See PipelineCyclerBase::read_stage().
CycleDataType * elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread)
See PipelineCyclerBase::elevate_read_stage().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CycleDataType * write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::write_stage_upstream().
CycleDataType * write_stage(int pipeline_stage, Thread *current_thread)
See PipelineCyclerBase::write_stage().
This class manages a staged pipeline of data, for instance the render pipeline, so that each stage of...
Definition: pipeline.h:38
CycleDataType * write(Thread *current_thread)
See PipelineCyclerBase::write().
CycleDataType * elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::elevate_read_upstream().
const CycleDataType * read_unlocked(Thread *current_thread) const
See PipelineCyclerBase::read_unlocked().
A thread; that is, a lightweight process.
Definition: thread.h:46
const CycleDataType * read_stage_unlocked(int pipeline_stage) const
See PipelineCyclerBase::read_stage_unlocked().
CycleDataType * write_upstream(bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::write_upstream().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const CycleDataType * read(Thread *current_thread) const
See PipelineCyclerBase::read().