| ... | ... |
@@ -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 |
|