... | ... |
@@ -399,8 +399,15 @@ either |
399 | 399 |
- `T` itself, if `T` is a [scalar][] |
400 | 400 |
|
401 | 401 |
then `constexpr auto GLTraits::members<T>()` returns an instance of the |
402 |
-[empty][] `struct GLTraits::Members<typename T, typename... Values>` where |
|
403 |
-`Values...` are the ("member") types above, in the order they occur in `T`. |
|
402 |
+[empty][] `struct GLTraits::Members<typename T, typename... Members>` where |
|
403 |
+each of `Members...` is `GLTraits::Member<typename Value, std::size_t offset>` |
|
404 |
+that describe the ("member") types above, in the order they occur in `T`. |
|
405 |
+`Value` is the type of the member and `offset` is the offset of the member in |
|
406 |
+`T`. Note that `offset` is only correct if the padding in `T` is minimal while |
|
407 |
+still satisfying the [`alignof`][] of the member types. The author knows of no |
|
408 |
+compiler that breaks this assumption unless explicitly instructed (e.g. with |
|
409 |
+[`alignas`][], which are not taken into account), however the standard allows |
|
410 |
+it. |
|
404 | 411 |
|
405 | 412 |
An example use case would be along the lines of: |
406 | 413 |
|
... | ... |
@@ -408,26 +415,22 @@ An example use case would be along the lines of: |
408 | 415 |
template< |
409 | 416 |
typename T, |
410 | 417 |
typename Value, |
411 |
- typename... Values |
|
418 |
+ std::size_t offset, |
|
419 |
+ typename... Members |
|
412 | 420 |
> |
413 | 421 |
void vertex_setup( |
414 |
- GLTraits::Members<T, Value, Values...>, |
|
415 |
- std::size_t offset = 0, |
|
416 |
- GLint location = 0 |
|
422 |
+ GLTraits::Members<T, GLTraits::Member<Value, offset>, Members...>, |
|
423 |
+ GLint location = 0 |
|
417 | 424 |
) |
418 | 425 |
{ |
419 |
- auto unaligned = offset % alignof(Value); |
|
420 |
- if (unaligned) |
|
421 |
- offset += alignof(Value) - unaligned; |
|
422 | 426 |
GLTraits::Value<Value>::vertex_attrib_pointer(location, offset, sizeof(T)); |
423 | 427 |
vertex_setup( |
424 |
- GLTraits::Members<T, Values...>{}, |
|
425 |
- offset + sizeof(Value), |
|
428 |
+ GLTraits::Members<T, Members...>{}, |
|
426 | 429 |
location + GLTraits::Value<Value>::columns |
427 | 430 |
); |
428 | 431 |
} |
429 | 432 |
template<typename T> |
430 |
-void vertex_setup(GLTraits::Members<T>, std::size_t, GLint) |
|
433 |
+void vertex_setup(GLTraits::Members<T>, GLint) |
|
431 | 434 |
{} |
432 | 435 |
|
433 | 436 |
struct Vertex |
... | ... |
@@ -462,6 +465,8 @@ version [`magic_get`][]) on whose talks this implementation is based: |
462 | 465 |
[class]: https://en.cppreference.com/w/cpp/types/is_class |
463 | 466 |
[array]: https://en.cppreference.com/w/cpp/types/is_array |
464 | 467 |
[scalar]: https://en.cppreference.com/w/cpp/types/is_scalar |
468 |
+[`alignof`]: https://en.cppreference.com/w/cpp/language/alignof |
|
469 |
+[`alignas`]: https://en.cppreference.com/w/cpp/language/alignas |
|
465 | 470 |
[`tests/vertex_setup.cpp`]: tests/vertex_setup.cpp |
466 | 471 |
[`doc/vertex_setup`]: doc/vertex_setup |
467 | 472 |
[`doc/vertex_setup.i`]: doc/vertex_setup.i |
... | ... |
@@ -42,7 +42,11 @@ public: |
42 | 42 |
|
43 | 43 |
#if __cplusplus >= 201402L |
44 | 44 |
|
45 |
- template<typename T, typename... Value> |
|
45 |
+ template<typename Value, std::size_t offset> |
|
46 |
+ struct Member |
|
47 |
+ {}; |
|
48 |
+ |
|
49 |
+ template<typename T, typename... Member> |
|
46 | 50 |
struct Members |
47 | 51 |
{}; |
48 | 52 |
|
... | ... |
@@ -101,7 +105,8 @@ private: |
101 | 105 |
|
102 | 106 |
struct MemberInfo |
103 | 107 |
{ |
104 |
- GLenum id; |
|
108 |
+ GLenum id; |
|
109 |
+ std::size_t offset; |
|
105 | 110 |
}; |
106 | 111 |
|
107 | 112 |
template<std::size_t N> |
... | ... |
@@ -114,11 +119,18 @@ private: |
114 | 119 |
{ |
115 | 120 |
MemberInfo * info; |
116 | 121 |
|
122 |
+ constexpr static auto align(std::size_t align, std::size_t offset) |
|
123 |
+ { |
|
124 |
+ return ((offset - 1) / align + 1) * align; |
|
125 |
+ } |
|
126 |
+ |
|
117 | 127 |
template<typename Value> |
118 | 128 |
constexpr operator Value() |
119 | 129 |
{ |
120 | 130 |
return ( |
121 |
- info->id = GLTraits::Value<Value>::id, |
|
131 |
+ info[0].id = GLTraits::Value<Value>::id, |
|
132 |
+ info[0].offset = align(alignof(Value), info[0].offset), |
|
133 |
+ info[1].offset = info[0].offset + sizeof(Value), |
|
122 | 134 |
Value{} |
123 | 135 |
); |
124 | 136 |
} |
... | ... |
@@ -144,7 +156,7 @@ private: |
144 | 156 |
} |
145 | 157 |
|
146 | 158 |
template<typename T, std::size_t... Is> |
147 |
- static constexpr auto member_infos(MemberInfos<sizeof...(Is)> infos = {}) |
|
159 |
+ static constexpr auto member_infos(MemberInfos<sizeof...(Is)+1> infos = {}) |
|
148 | 160 |
{ |
149 | 161 |
return ((void)T{MemberAny{&infos.infos[Is]}...}, infos); |
150 | 162 |
} |
... | ... |
@@ -154,7 +166,10 @@ private: |
154 | 166 |
{ |
155 | 167 |
return Members< |
156 | 168 |
T, |
157 |
- typename ValueID<member_infos<T, Is...>().infos[Is].id>::Value... |
|
169 |
+ Member< |
|
170 |
+ typename ValueID<member_infos<T, Is...>().infos[Is].id>::Value, |
|
171 |
+ member_infos<T, Is...>().infos[Is].offset |
|
172 |
+ >... |
|
158 | 173 |
>{}; |
159 | 174 |
} |
160 | 175 |
|
... | ... |
@@ -113,24 +113,25 @@ struct GLTraitsTest : protected GLBase |
113 | 113 |
template< |
114 | 114 |
typename T, |
115 | 115 |
typename Value, |
116 |
- typename... Values |
|
116 |
+ std::size_t offset, |
|
117 |
+ typename... Members |
|
117 | 118 |
> |
118 | 119 |
void static test_members( |
119 |
- GLTraits::Members<T, Value, Values...>, |
|
120 |
- std::size_t offset = 0 |
|
120 |
+ GLTraits::Members<T, GLTraits::Member<Value, offset>, Members...> |
|
121 | 121 |
) |
122 | 122 |
{ |
123 |
- auto unaligned = offset % alignof(Value); |
|
124 |
- if (unaligned) |
|
125 |
- offset += alignof(Value) - unaligned; |
|
126 |
- auto end = offset + sizeof(Value); |
|
123 |
+ auto constexpr end = offset + sizeof(Value); |
|
127 | 124 |
using Traits = GLTraits::Value<Value>; |
128 | 125 |
static_assert( |
129 | 126 |
std::is_empty<GLTraits::Members< |
130 |
- T, Value, Values... |
|
127 |
+ T, GLTraits::Member<Value, offset>, Members... |
|
131 | 128 |
>>::value, |
132 | 129 |
"GLTraits::Members must be empty" |
133 | 130 |
); |
131 |
+ static_assert( |
|
132 |
+ std::is_empty<GLTraits::Member<Value, offset>>::value, |
|
133 |
+ "GLTraits::Member must be empty" |
|
134 |
+ ); |
|
134 | 135 |
#define GLTRAITS_TEST_MEMBERS(IND, NAME, OFFSET, END) \ |
135 | 136 |
std::cout \ |
136 | 137 |
<< std::left << std::setw(IND) << "" \ |
... | ... |
@@ -138,10 +139,10 @@ struct GLTraitsTest : protected GLBase |
138 | 139 |
<< std::right << std::setw(2) << std::dec << OFFSET << " " \ |
139 | 140 |
<< std::right << std::setw(3) << std::dec << END << "\n"; |
140 | 141 |
GLTRAITS_TEST_MEMBERS(2, Traits::name, offset, end) |
141 |
- test_members(GLTraits::Members<T, Values...>{}, end); |
|
142 |
+ test_members(GLTraits::Members<T, Members...>{}); |
|
142 | 143 |
} |
143 | 144 |
template<typename T> |
144 |
- void static test_members(GLTraits::Members<T>, std::size_t) |
|
145 |
+ void static test_members(GLTraits::Members<T>) |
|
145 | 146 |
{} |
146 | 147 |
#endif |
147 | 148 |
|
... | ... |
@@ -9,26 +9,22 @@ |
9 | 9 |
template< |
10 | 10 |
typename T, |
11 | 11 |
typename Value, |
12 |
- typename... Values |
|
12 |
+ std::size_t offset, |
|
13 |
+ typename... Members |
|
13 | 14 |
> |
14 | 15 |
void vertex_setup( |
15 |
- GLTraits::Members<T, Value, Values...>, |
|
16 |
- std::size_t offset = 0, |
|
17 |
- GLint location = 0 |
|
16 |
+ GLTraits::Members<T, GLTraits::Member<Value, offset>, Members...>, |
|
17 |
+ GLint location = 0 |
|
18 | 18 |
) |
19 | 19 |
{ |
20 |
- auto unaligned = offset % alignof(Value); |
|
21 |
- if (unaligned) |
|
22 |
- offset += alignof(Value) - unaligned; |
|
23 | 20 |
GLTraits::Value<Value>::vertex_attrib_pointer(location, offset, sizeof(T)); |
24 | 21 |
vertex_setup( |
25 |
- GLTraits::Members<T, Values...>{}, |
|
26 |
- offset + sizeof(Value), |
|
22 |
+ GLTraits::Members<T, Members...>{}, |
|
27 | 23 |
location + GLTraits::Value<Value>::columns |
28 | 24 |
); |
29 | 25 |
} |
30 | 26 |
template<typename T> |
31 |
-void vertex_setup(GLTraits::Members<T>, std::size_t, GLint) |
|
27 |
+void vertex_setup(GLTraits::Members<T>, GLint) |
|
32 | 28 |
{} |
33 | 29 |
|
34 | 30 |
|