Overte C++ Documentation
render/src/render/Stage.h
1 //
2 // Stage.h
3 // render/src/render
4 //
5 // Created by Sam Gateau on 6/14/2017.
6 // Copyright 2017 High Fidelity, Inc.
7 // Copyright 2024 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 //
12 
13 #ifndef hifi_render_Stage_h
14 #define hifi_render_Stage_h
15 
16 #include <map>
17 #include <memory>
18 #include <unordered_map>
19 #include <string>
20 
21 #include "IndexedContainer.h"
22 
23 namespace render {
24 
25  using ElementIndices = std::vector<indexed_container::Index>;
26 
27  class Stage {
28  public:
29  Stage() {}
30  virtual ~Stage() {}
31 
32  using Name = std::string;
33  using Index = indexed_container::Index;
34  static const Index INVALID_INDEX;
35  using IDList = indexed_container::Indices;
36 
37  static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
38  };
39 
40  using StagePointer = std::shared_ptr<Stage>;
41  using StageMap = std::map<const Stage::Name, StagePointer>;
42 
43  template<typename T>
44  class TypedStage : public Stage {
45  public:
46  TypedStage() {}
47  virtual ~TypedStage() {}
48 
49  static const Name& getName() { return _name; }
50 
51  bool checkId(Index index) const { return _elements.checkIndex(index); }
52 
53  const T& getElement(Index id) const { return _elements.get(id); }
54  T& editElement(Index id) { return _elements.edit(id); }
55  Index addElement(const T& element) {
56  Index id = _elements.newElement(element);
57  _activeElementIDs.push_back(id);
58  return id;
59  }
60 
61  void removeElement(Index index) {
62  IDList::iterator idIterator = std::find(_activeElementIDs.begin(), _activeElementIDs.end(), index);
63  if (idIterator != _activeElementIDs.end()) {
64  _activeElementIDs.erase(idIterator);
65  }
66  if (!_elements.isElementFreed(index)) {
67  _elements.freeElement(index);
68  }
69  }
70 
71  IDList::iterator begin() { return _activeElementIDs.begin(); }
72  IDList::iterator end() { return _activeElementIDs.end(); }
73  protected:
74  static Name _name;
75 
76  indexed_container::IndexedVector<T> _elements;
77  IDList _activeElementIDs;
78  };
79 
80  class Frame {
81  public:
82  Frame() {}
83 
84  using Index = indexed_container::Index;
85 
86  void clear() { _elements.clear(); }
87  void pushElement(Index index) { _elements.emplace_back(index); }
88 
89  ElementIndices _elements;
90  };
91 
92  template<typename T, typename P, typename F = Frame>
93  class PointerStage : public Stage {
94  public:
95  PointerStage() {}
96  virtual ~PointerStage() {}
97 
98  static const Name& getName() { return _name; }
99 
100  bool checkId(Index index) const { return _elements.checkIndex(index); }
101 
102  Index getNumElements() const { return _elements.getNumElements(); }
103  Index getNumFreeElements() const { return _elements.getNumFreeIndices(); }
104  Index getNumAllocatedElements() const { return _elements.getNumAllocatedIndices(); }
105 
106  P getElement(Index id) const { return _elements.get(id); }
107 
108  Index findElement(const P& element) const {
109  auto found = _elementMap.find(element);
110  if (found != _elementMap.end()) {
111  return INVALID_INDEX;
112  } else {
113  return (*found).second;
114  }
115  }
116 
117  virtual Index addElement(const P& element) {
118  auto found = _elementMap.find(element);
119  if (found == _elementMap.end()) {
120  auto id = _elements.newElement(element);
121  // Avoid failing to allocate an element, just pass
122  if (id != INVALID_INDEX) {
123  // Insert the element and its index in the reverse map
124  _elementMap[element] = id;
125  }
126  return id;
127  } else {
128  return (*found).second;
129  }
130  }
131 
132  virtual P removeElement(Index index) {
133  P removed = _elements.freeElement(index);
134 
135  if (removed) {
136  _elementMap.erase(removed);
137  }
138  return removed;
139  }
140 
141  using Frame = F;
142  using FramePointer = std::shared_ptr<F>;
143  F _currentFrame;
144 
145  protected:
146  static Name _name;
147 
148  indexed_container::IndexedPointerVector<T> _elements;
149  std::unordered_map<P, Index> _elementMap;
150  };
151 }
152 
153 #endif // hifi_render_Stage_h