Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
shaderinputregistry.cc
Go to the documentation of this file.
1 
19 
20 #include <stdint.h>
21 
22 #include <algorithm>
23 
24 #include "ion/base/lockguards.h"
26 #include "ion/math/matrix.h"
27 #include "ion/port/atomic.h"
28 #include "ion/port/mutex.h"
29 
30 namespace ion {
31 namespace gfx {
32 
33 namespace {
34 
36 
41 
42 
45 static const Uniform CombineMatrices(const Uniform& old_value,
46  const Uniform& new_value) {
47  DCHECK_EQ(kMatrix4x4Uniform, old_value.GetType());
48  DCHECK_EQ(kMatrix4x4Uniform, new_value.GetType());
49 
50  const math::Matrix4f& m0 = old_value.GetValue<math::Matrix4f>();
51  const math::Matrix4f& m1 = new_value.GetValue<math::Matrix4f>();
52 
53  Uniform result = old_value;
54  result.SetValue(m0 * m1);
55  return result;
56 }
57 
58 } // anonymous namespace
59 
61 
66 
67 
68 class ShaderInputRegistry::StaticData {
69  public:
71  StaticData()
72  : registry_count_(0), largest_registry_size_(0) {}
73 
75  int32_t GetRegistryCount() const {
76  return registry_count_;
77  }
78 
80  int32_t GetUniqueId() const {
81  return ++registry_count_;
82  }
83 
85  int32_t GetLargestRegistrySize() const {
86  return largest_registry_size_;
87  }
88 
91  void UpdateLargestRegistrySize(int32_t size) const {
92  int32_t largest_size = largest_registry_size_.load();
93  bool succeeded = false;
97  while (size > largest_size && !succeeded) {
98  succeeded = largest_registry_size_.compare_exchange_strong(
99  largest_size, size);
101  }
102  }
103 
104  private:
106  mutable std::atomic<int32_t> registry_count_;
107 
109  mutable std::atomic<int32_t> largest_registry_size_;
110 };
111 
113 
118 
119 
120 class ShaderInputRegistry::StaticGlobalRegistryData {
121  public:
123  StaticGlobalRegistryData()
124  : global_registry_(new(base::kLongTerm) ShaderInputRegistry) {
125  global_registry_->Add(AttributeSpec(
126  "aVertex", kBufferObjectElementAttribute, "Vertex position."));
127  global_registry_->Add(AttributeSpec(
128  "aColor", kBufferObjectElementAttribute, "Vertex color."));
129  global_registry_->Add(AttributeSpec(
130  "aNormal", kBufferObjectElementAttribute, "Normal direction."));
131  global_registry_->Add(AttributeSpec(
132  "aTexCoords", kBufferObjectElementAttribute, "Texture coordinates."));
133 
134  global_registry_->Add(UniformSpec(
135  "uViewportSize", kIntVector2Uniform, "Viewport Size."));
136  global_registry_->Add(UniformSpec(
137  "uProjectionMatrix", kMatrix4x4Uniform, "Projection matrix."));
138  global_registry_->Add(UniformSpec("uModelviewMatrix",
140  "Cumulative modelview matrix.",
141  CombineMatrices));
142  global_registry_->Add(UniformSpec(
143  "uBaseColor", kFloatVector4Uniform, "Base color for shapes."));
144  }
145 
148  return global_registry_;
149  }
150 
151  private:
153  ShaderInputRegistryPtr global_registry_;
154 };
155 
157 
162 
163 
165  : uniform_specs_(kUniformAdded,
166  base::AllocDeque<UniformSpec>(*this),
167  this),
168  attribute_specs_(*this),
169  includes_(*this),
170  spec_map_(*this) {
171  id_ = GetStaticData()->GetUniqueId();
172 }
173 
175 }
176 
177 bool ShaderInputRegistry::Contains(const std::string& name) const {
178  const SpecMapType::const_iterator it = spec_map_.find(name);
179  if (it == spec_map_.end()) {
181  const size_t num_includes = includes_.size();
182  for (size_t i = 0; i < num_includes; ++i)
183  if (includes_[i]->Contains(name))
184  return true;
185  return false;
186  } else {
189  return true;
190  }
191 }
192 
194  if (!reg.Get())
195  return false;
196 
198  if (reg.Get() == this) {
199  LOG(ERROR) << "Can't include registry " << reg->GetId() << " in registry "
200  << GetId() << " because a registry cannot include itself";
201  return false;
202  }
203 
206  const SpecMapType specs = GetAllSpecEntries();
207  for (SpecMapType::const_iterator it = specs.begin(); it != specs.end();
208  ++it) {
209  if (reg->Contains(it->first)) {
210  LOG(ERROR) << "Can't include registry " << reg->GetId() << " in registry "
211  << GetId() << " because they or their includes both define the"
212  << " shader input '" << it->first << "'";
213  return false;
214  }
215  }
216 
217  includes_.push_back(reg);
218  return true;
219 }
220 
222  return Include(GetStaticGlobalRegistryData()->GetGlobalRegistry());
223 }
224 
226  bool duplicates_found = false;
227  SpecMapType specs = spec_map_;
228  const size_t num_includes = includes_.size();
229  for (size_t i = 0; i < num_includes; ++i) {
230  const SpecMapType& included_specs = includes_[i]->GetAllSpecEntries();
232  for (SpecMapType::const_iterator it = included_specs.begin();
233  it != included_specs.end(); ++it) {
234  if (specs.count(it->first)) {
235  LOG(WARNING) << "Registry " << specs[it->first].registry_id
236  << " defines duplicate input '" << it->first << "' which"
237  << " is also defined in registry "
238  << it->second.registry_id;
239  duplicates_found = true;
240  }
241  }
242  specs.insert(included_specs.begin(), included_specs.end());
243  }
244  return !duplicates_found;
245 }
246 
248 ShaderInputRegistry::GetMutableSpecs() {
249  return &attribute_specs_;
250 }
251 
253 ShaderInputRegistry::GetMutableSpecs() {
254  return uniform_specs_.GetMutable();
255 }
256 
258 ShaderInputRegistry::GetAllSpecEntries() const {
259  SpecMapType specs = spec_map_;
260  const size_t num_includes = includes_.size();
261  for (size_t i = 0; i < num_includes; ++i) {
262  const SpecMapType& included_specs = includes_[i]->GetAllSpecEntries();
263  specs.insert(included_specs.begin(), included_specs.end());
264  }
265  return specs;
266 }
267 
268 template <>
269 ION_API const base::AllocDeque<ShaderInputRegistry::AttributeSpec>&
271  return attribute_specs_;
272 }
273 
274 template <>
277  return uniform_specs_.Get();
278 }
279 
281  return GetStaticGlobalRegistryData()->GetGlobalRegistry();
282 }
283 
284 void ShaderInputRegistry::UpdateLargestRegistrySize(size_t size) {
285  GetStaticData()->UpdateLargestRegistrySize(static_cast<int32_t>(size));
286 }
287 
288 ShaderInputRegistry::StaticData* ShaderInputRegistry::GetStaticData() {
289  ION_DECLARE_SAFE_STATIC_POINTER(StaticData, s_static_data);
290  return s_static_data;
291 }
292 
293 ShaderInputRegistry::StaticGlobalRegistryData*
294 ShaderInputRegistry::GetStaticGlobalRegistryData() {
295  ION_DECLARE_SAFE_STATIC_POINTER(StaticGlobalRegistryData,
296  s_static_registry_data);
297  return s_static_registry_data;
298 }
299 
300 } // namespace gfx
301 } // namespace ion
Matrix< 4, float > Matrix4f
Definition: matrix.h:371
bool CheckInputsAreUnique() const
Returns whether the inputs in this registry and its includes are unique.
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
bool Include(const ShaderInputRegistryPtr &reg)
Includes another ShaderInputRegistry in this one.
This struct is stored for each registered ShaderInput.
static const ShaderInputRegistryPtr & GetGlobalRegistry()
Returns the ShaderInputRegistry instance representing all supported global uniforms and attributes...
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
size_t GetId() const
Each ShaderInputRegistry instance is assigned a unique integer ID.
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
std::string name
Definition: printer.cc:324
This class can be used in place of std::deque to allow an Ion Allocator to be used for memory allocat...
Definition: allocdeque.h:50
~ShaderInputRegistry() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
bool Contains(const std::string &name) const
Returns if a Spec for an input of the passed name exists in the registry or its includes.
#define DCHECK_EQ(val1, val2)
Definition: logging.h:332
base::ReferentPtr< ShaderInputRegistry >::Type ShaderInputRegistryPtr
Convenience typedef for shared pointer to a ShaderInputRegistry.
bool IncludeGlobalRegistry()
Includes the global registry in this registry.
kLongTerm is used for objects that have persistent lifetimes, such as managers.
Definition: allocator.h:44
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
ShaderInputRegistry()
ShaderInputRegistry class definition.
const base::AllocDeque< Spec< T > > & GetSpecs() const
Returns a vector of all Specs of type T added to this registry.