18 #ifndef ION_GFXUTILS_BUFFERTOATTRIBUTEBINDER_H_
19 #define ION_GFXUTILS_BUFFERTOATTRIBUTEBINDER_H_
23 #include "base/integral_types.h"
43 template <
typename T> ION_API
100 template <
typename T>
104 : base_address_(reinterpret_cast<const char*>(&base_struct)) {
113 const size_t num_bindings = bindings_.size();
114 for (
size_t i = 0; i < num_bindings; ++i) {
115 const size_t element_index = bo->AddSpec(
116 bindings_[i].
type, bindings_[i].count, bindings_[i].
offset);
134 size_t struct_size = 0;
135 bool struct_is_packed =
true;
136 const size_t num_bindings = bindings_.size();
137 for (
size_t i = 0; i < num_bindings; ++i) {
138 if (reg.
Contains(bindings_[i].name)) {
139 struct_size += bindings_[i].size;
141 if (bindings_[i].
offset) {
143 if (!IsBindingPacked(i, &closest)) {
145 <<
"Attribute '" << bindings_[i].name <<
"' is not"
146 <<
" tightly packed, performance may suffer. The closest"
147 <<
" binding before it is '" << bindings_[closest].name
148 <<
",' but it ends at offset "
149 << (bindings_[closest].offset + bindings_[closest].size)
150 <<
", while '" << bindings_[i].
name <<
"' starts at offset "
151 << bindings_[i].offset;
152 struct_is_packed =
false;
157 if (struct_size !=
sizeof(
T)) {
158 LOG(
WARNING) <<
"Vertex struct is not tightly packed ("
159 << (
sizeof(
T) - struct_size)
160 <<
" byte(s) are wasted), performance may suffer.";
161 struct_is_packed =
false;
163 return struct_is_packed;
166 template <
typename FieldType>
168 const std::string& attribute_name) {
169 return BindInternal(field, attribute_name,
false, 0);
172 template <
typename FieldType>
174 const std::string& attribute_name) {
175 return BindInternal(field, attribute_name,
true, 0);
178 template <
typename FieldType>
180 const std::string& attribute_name,
181 unsigned int divisor) {
182 return BindInternal(field, attribute_name,
false, divisor);
185 template <
typename FieldType>
187 const std::string& attribute_name,
188 unsigned int divisor) {
189 return BindInternal(field, attribute_name,
true, divisor);
194 typedef base::Variant<int8, uint8, int16, uint16, int32, uint32,
196 math::VectorBase1i8, math::VectorBase1ui8,
197 math::VectorBase1i16, math::VectorBase1ui16,
198 math::VectorBase1i, math::VectorBase1ui,
200 math::VectorBase2i8, math::VectorBase2ui8,
201 math::VectorBase2i16, math::VectorBase2ui16,
202 math::VectorBase2i, math::VectorBase2ui,
204 math::VectorBase3i8, math::VectorBase3ui8,
205 math::VectorBase3i16, math::VectorBase3ui16,
206 math::VectorBase3i, math::VectorBase3ui,
208 math::VectorBase4i8, math::VectorBase4ui8,
209 math::VectorBase4i16, math::VectorBase4ui16,
210 math::VectorBase4i, math::VectorBase4ui,
215 Binding(
size_t offset_in,
size_t count_in,
size_t size_in,
216 const std::string& name_in,
218 unsigned int divisor_in)
224 normalize(normalize_in),
225 divisor(divisor_in) {}
232 unsigned int divisor;
236 BufferToAttributeBinder()
237 : base_address_(NULL) {}
239 template <
typename FieldType>
241 const std::string& attribute_name,
242 bool normalize,
unsigned int divisor) {
243 typedef typename base::VariantTypeResolver<
246 "Cannot resolve attribute type to bind");
247 const char* field_address =
reinterpret_cast<const char*
>(&field);
248 const ssize_t
offset = field_address - base_address_;
249 bindings_.push_back(Binding(offset, GetComponentCount<ResolvedFieldType>(),
250 sizeof(FieldType), attribute_name,
251 GetComponentType<ResolvedFieldType>(),
252 normalize, divisor));
258 bool IsBindingPacked(
size_t i,
size_t* closest) {
262 size_t closest_index = i;
263 size_t closest_distance = 0;
264 const size_t num_bindings = bindings_.size();
265 for (
size_t j = 0; j < num_bindings; ++j) {
268 const size_t end_of_binding = bindings_[j].offset + bindings_[j].size;
269 if (end_of_binding == bindings_[i].offset) {
274 }
else if (end_of_binding < bindings_[i].offset &&
275 end_of_binding > closest_distance) {
279 closest_distance = end_of_binding;
283 *closest = closest_index;
287 const char* base_address_;
288 std::vector<Binding> bindings_;
294 #endif // ION_GFXUTILS_BUFFERTOATTRIBUTEBINDER_H_
BufferToAttributeBinder & Bind(const FieldType &field, const std::string &attribute_name, unsigned int divisor)
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
BufferToAttributeBinder & BindAndNormalize(const FieldType &field, const std::string &attribute_name)
Matrix< 3, float > Matrix3f
ION_API gfx::BufferObject::ComponentType GetComponentType()
These functions must be specialized for every type used in a vertex.
Structure for clients to use to encapsulate Elements.
void SetDivisor(unsigned int divisor)
The Matrix class defines a square N-dimensional matrix.
The Variant class is similar to boost::variant.
~BufferToAttributeBinder()
ComponentType
The type of the components of a spec.
BufferToAttributeBinder is a simple interface to insert a set of Attributes containing BufferObjectEl...
Copyright 2016 Google Inc.
BufferToAttributeBinder & Bind(const FieldType &field, const std::string &attribute_name)
Matrix< 2, float > Matrix2f
Dimension- and type-specific typedefs.
void SetFixedPointNormalized(bool normalize)
#define ION_STATIC_ASSERT(expr, message)
Copyright 2016 Google Inc.
ION_API size_t GetComponentCount()
bool AreBindingsPacked(const gfx::ShaderInputRegistry ®)
Validates that the bindings within the binder are consistent with a packed struct, logging warning messages if they are not.
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
BufferToAttributeBinder & BindAndNormalize(const FieldType &field, const std::string &attribute_name, unsigned int divisor)
BufferToAttributeBinder(const T &base_struct)
void Apply(const gfx::ShaderInputRegistryPtr ®, const gfx::AttributeArrayPtr &aa, const gfx::BufferObjectPtr &bo)