| 165 | |
| 166 | template <uint32_t Stages_> |
| 167 | struct PipelineState { |
| 168 | static constexpr uint32_t Stages = Stages_; |
| 169 | |
| 170 | int index_ = 0; |
| 171 | uint32_t phase_ = 0; |
| 172 | uint32_t count_ = 0; |
| 173 | |
| 174 | DEVICE PipelineState() : index_{}, phase_{}, count_{} {} |
| 175 | |
| 176 | DEVICE PipelineState(int index, uint32_t phase, uint32_t count) |
| 177 | : index_(index), phase_(phase), count_(count) {} |
| 178 | |
| 179 | DEVICE int index() const { return index_; } |
| 180 | |
| 181 | DEVICE uint32_t phase() const { return phase_; } |
| 182 | |
| 183 | DEVICE uint32_t count() const { return count_; } |
| 184 | |
| 185 | DEVICE void operator++() { |
| 186 | if constexpr (Stages > 0) { |
| 187 | ++index_; |
| 188 | ++count_; |
| 189 | if (index_ == Stages) { |
| 190 | index_ = 0; |
| 191 | phase_ ^= 1; |
| 192 | } |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | DEVICE PipelineState &operator=(const PipelineState &other) { |
| 197 | index_ = other.index(); |
| 198 | phase_ = other.phase(); |
| 199 | count_ = other.count(); |
| 200 | return *this; |
| 201 | } |
| 202 | |
| 203 | DEVICE PipelineState advance(uint32_t num_iterations) { |
| 204 | if constexpr (Stages > 0) { |
| 205 | // Number of iterations cross over the stage boundary => flipped phase |
| 206 | if ((num_iterations < Stages) && (index_ + num_iterations) >= Stages) { |
| 207 | phase_ ^= 1; |
| 208 | } |
| 209 | // How many times number of iterations cross over the stage boundary and |
| 210 | // end up on a odd number => flipped phase |
| 211 | if ((num_iterations >= Stages) && |
| 212 | (((index_ + num_iterations) / Stages) % 2) == 1) { |
| 213 | phase_ ^= 1; |
| 214 | } |
| 215 | index_ = (index_ + num_iterations) % Stages; |
| 216 | count_ += num_iterations; |
| 217 | } |
| 218 | return *this; |
| 219 | } |
| 220 | |
| 221 | DEVICE static PipelineState make_pipeline_state(PipelineState start_state, |
| 222 | uint32_t num_iterations) { |
| 223 | return start_state.advance(num_iterations); |
| 224 | } |