... | ... |
@@ -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 |
|
... | ... |
@@ -42,7 +42,7 @@ public: |
42 | 42 |
|
43 | 43 |
#if __cplusplus >= 201402L |
44 | 44 |
|
45 |
- template<typename... Value> |
|
45 |
+ template<typename T, typename... Value> |
|
46 | 46 |
struct Members |
47 | 47 |
{}; |
48 | 48 |
|
... | ... |
@@ -153,6 +153,7 @@ private: |
153 | 153 |
static constexpr auto members_(Indices<Is...>) |
154 | 154 |
{ |
155 | 155 |
return Members< |
156 |
+ T, |
|
156 | 157 |
typename ValueID<member_infos<T, Is...>().infos[Is].id>::Value... |
157 | 158 |
>{}; |
158 | 159 |
} |
... | ... |
@@ -38,6 +38,28 @@ public: |
38 | 38 |
template<std::size_t N> |
39 | 39 |
struct Texture; |
40 | 40 |
|
41 |
+ //// Member |
|
42 |
+ |
|
43 |
+ #if __cplusplus >= 201402L |
|
44 |
+ |
|
45 |
+ template<typename... Value> |
|
46 |
+ struct Members |
|
47 |
+ {}; |
|
48 |
+ |
|
49 |
+ template<typename T> |
|
50 |
+ static constexpr auto members() |
|
51 |
+ { |
|
52 |
+ static_assert( |
|
53 |
+ !std::is_empty<T>::value && |
|
54 |
+ std::is_trivially_copyable<T>::value && |
|
55 |
+ std::is_standard_layout<T>::value, |
|
56 |
+ "T must be a non-empty trivially copyable standard-layout type" |
|
57 |
+ ); |
|
58 |
+ return members_<T>(MakeIndices<member_count<T>()>{}); |
|
59 |
+ } |
|
60 |
+ |
|
61 |
+ #endif |
|
62 |
+ |
|
41 | 63 |
private: |
42 | 64 |
|
43 | 65 |
//// Helpers |
... | ... |
@@ -71,6 +93,72 @@ private: |
71 | 93 |
> |
72 | 94 |
struct Texture_; |
73 | 95 |
|
96 |
+ //// Member |
|
97 |
+ |
|
98 |
+ // Stripped down version of Boost::PFR. |
|
99 |
+ |
|
100 |
+ #if __cplusplus >= 201402L |
|
101 |
+ |
|
102 |
+ struct MemberInfo |
|
103 |
+ { |
|
104 |
+ GLenum id; |
|
105 |
+ }; |
|
106 |
+ |
|
107 |
+ template<std::size_t N> |
|
108 |
+ struct MemberInfos |
|
109 |
+ { |
|
110 |
+ MemberInfo infos[N]; |
|
111 |
+ }; |
|
112 |
+ |
|
113 |
+ struct MemberAny |
|
114 |
+ { |
|
115 |
+ MemberInfo * info; |
|
116 |
+ |
|
117 |
+ template<typename Value> |
|
118 |
+ constexpr operator Value() |
|
119 |
+ { |
|
120 |
+ return ( |
|
121 |
+ info->id = GLTraits::Value<Value>::id, |
|
122 |
+ Value{} |
|
123 |
+ ); |
|
124 |
+ } |
|
125 |
+ }; |
|
126 |
+ |
|
127 |
+ template<typename T, std::size_t I0, std::size_t... Is> |
|
128 |
+ static constexpr auto member_count_(Indices<I0, Is...>) |
|
129 |
+ -> decltype(T{(I0, MemberAny{}), (Is, MemberAny{})...}, std::size_t{}) |
|
130 |
+ { |
|
131 |
+ return 1 + sizeof...(Is); |
|
132 |
+ } |
|
133 |
+ |
|
134 |
+ template<typename T, std::size_t... Is> |
|
135 |
+ static constexpr auto member_count_(Indices<Is...>) |
|
136 |
+ { |
|
137 |
+ return member_count_<T>(MakeIndices<sizeof...(Is) - 1>{}); |
|
138 |
+ } |
|
139 |
+ |
|
140 |
+ template<typename T> |
|
141 |
+ static constexpr auto member_count() |
|
142 |
+ { |
|
143 |
+ return member_count_<T>(MakeIndices<sizeof(T)>{}); |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ template<typename T, std::size_t... Is> |
|
147 |
+ static constexpr auto member_infos(MemberInfos<sizeof...(Is)> infos = {}) |
|
148 |
+ { |
|
149 |
+ return ((void)T{MemberAny{&infos.infos[Is]}...}, infos); |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ template<typename T, std::size_t... Is> |
|
153 |
+ static constexpr auto members_(Indices<Is...>) |
|
154 |
+ { |
|
155 |
+ return Members< |
|
156 |
+ typename ValueID<member_infos<T, Is...>().infos[Is].id>::Value... |
|
157 |
+ >{}; |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ #endif |
|
161 |
+ |
|
74 | 162 |
}; |
75 | 163 |
|
76 | 164 |
//// Helpers |
... | ... |
@@ -6,6 +6,7 @@ |
6 | 6 |
|
7 | 7 |
/// Includes |
8 | 8 |
|
9 |
+#include <array> |
|
9 | 10 |
#include <cstddef> |
10 | 11 |
#include <string> |
11 | 12 |
|
... | ... |
@@ -32,6 +33,44 @@ public: |
32 | 33 |
template<GLenum object_type> |
33 | 34 |
struct Object; |
34 | 35 |
|
36 |
+ //// Texture |
|
37 |
+ |
|
38 |
+ template<std::size_t N> |
|
39 |
+ struct Texture; |
|
40 |
+ |
|
41 |
+private: |
|
42 |
+ |
|
43 |
+ //// Helpers |
|
44 |
+ |
|
45 |
+ // Stripped down version of C++14's `std::{,make_}index_sequence`. |
|
46 |
+ |
|
47 |
+ template<std::size_t... Is> |
|
48 |
+ struct Indices |
|
49 |
+ {}; |
|
50 |
+ |
|
51 |
+ template<std::size_t N, std::size_t... Is> |
|
52 |
+ struct MakeIndices_ : MakeIndices_<N - 1, N - 1, Is...> |
|
53 |
+ {}; |
|
54 |
+ |
|
55 |
+ template<std::size_t... Is> |
|
56 |
+ struct MakeIndices_<0, Is...> |
|
57 |
+ { |
|
58 |
+ using Indices_ = Indices<Is...>; |
|
59 |
+ }; |
|
60 |
+ |
|
61 |
+ template<std::size_t N> |
|
62 |
+ using MakeIndices = typename MakeIndices_<N>::Indices_; |
|
63 |
+ |
|
64 |
+ //// Texture |
|
65 |
+ |
|
66 |
+ template < |
|
67 |
+ std::size_t N, |
|
68 |
+ typename Indices, |
|
69 |
+ typename CopySizeIndices, |
|
70 |
+ typename CopyOffsetIndices |
|
71 |
+ > |
|
72 |
+ struct Texture_; |
|
73 |
+ |
|
35 | 74 |
}; |
36 | 75 |
|
37 | 76 |
//// Helpers |
... | ... |
@@ -251,6 +290,285 @@ GLTRAITS_OBJECT( SAMPLER, Sampler, Samplers, |
251 | 290 |
GLTRAITS_OBJECT( TRANSFORM_FEEDBACK, TransformFeedback, TransformFeedbacks, OMIT, 4, 0, "GL_ARB_transform_feedback2") |
252 | 291 |
GLTRAITS_OBJECT( PROGRAM_PIPELINE, ProgramPipeline, ProgramPipelines, KEEP, 4, 1, "GL_ARB_separate_shader_objects") |
253 | 292 |
|
293 |
+//// Texture |
|
294 |
+ |
|
295 |
+template<> |
|
296 |
+struct GLTraits::Texture<0> |
|
297 |
+{ |
|
298 |
+protected: |
|
299 |
+ void static defaults_( |
|
300 |
+ GLenum & internal_format, |
|
301 |
+ GLenum & format, |
|
302 |
+ GLenum & type, |
|
303 |
+ GLenum default_internal_format, |
|
304 |
+ GLenum default_format, |
|
305 |
+ GLenum default_type |
|
306 |
+ ) |
|
307 |
+ { |
|
308 |
+ if (!internal_format) internal_format = default_internal_format; |
|
309 |
+ switch (internal_format) |
|
310 |
+ { |
|
311 |
+ case GL_DEPTH_STENCIL: |
|
312 |
+ case GL_DEPTH24_STENCIL8: |
|
313 |
+ case GL_DEPTH32F_STENCIL8: |
|
314 |
+ if (!format) format = GL_DEPTH_STENCIL; |
|
315 |
+ if (!type) type = GL_UNSIGNED_INT_24_8; |
|
316 |
+ break; |
|
317 |
+ case GL_DEPTH_COMPONENT: |
|
318 |
+ case GL_DEPTH_COMPONENT16: |
|
319 |
+ case GL_DEPTH_COMPONENT24: |
|
320 |
+ case GL_DEPTH_COMPONENT32: |
|
321 |
+ case GL_DEPTH_COMPONENT32F: |
|
322 |
+ if (!format) format = GL_DEPTH_COMPONENT; |
|
323 |
+ if (!type) type = GL_UNSIGNED_INT; |
|
324 |
+ break; |
|
325 |
+ case GL_STENCIL_INDEX: |
|
326 |
+ case GL_STENCIL_INDEX1: |
|
327 |
+ case GL_STENCIL_INDEX4: |
|
328 |
+ case GL_STENCIL_INDEX8: |
|
329 |
+ case GL_STENCIL_INDEX16: |
|
330 |
+ if (!format) format = GL_STENCIL_INDEX; |
|
331 |
+ if (!type) type = GL_UNSIGNED_BYTE; |
|
332 |
+ break; |
|
333 |
+ default: |
|
334 |
+ if (!format) format = default_format; |
|
335 |
+ if (!type) type = default_type; |
|
336 |
+ } |
|
337 |
+ } |
|
338 |
+}; |
|
339 |
+ |
|
340 |
+#define GLTRAITS_TEXTURE_IMAGE( \ |
|
341 |
+ N, \ |
|
342 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
343 |
+ TYPE, NAME, \ |
|
344 |
+ V1, V2, EXT \ |
|
345 |
+) \ |
|
346 |
+ template<typename Value = GLubyte> \ |
|
347 |
+ void static TEXTURE_LOWER##_image( \ |
|
348 |
+ TYPE NAME, \ |
|
349 |
+ Size size, \ |
|
350 |
+ GLenum internal_format = 0, \ |
|
351 |
+ Value const * data = nullptr, \ |
|
352 |
+ GLenum format = 0, \ |
|
353 |
+ GLenum type = 0, \ |
|
354 |
+ GLint level = 0, \ |
|
355 |
+ GLint border = 0 \ |
|
356 |
+ ) \ |
|
357 |
+ { \ |
|
358 |
+ if (GLBase::debug() >= 1) \ |
|
359 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
360 |
+ defaults_( \ |
|
361 |
+ internal_format, \ |
|
362 |
+ format, \ |
|
363 |
+ type, \ |
|
364 |
+ GLTraits::Value<Value>::internal_format, \ |
|
365 |
+ GLTraits::Value<Value>::format, \ |
|
366 |
+ GLTraits::Value<Value>::type \ |
|
367 |
+ ); \ |
|
368 |
+ gl##TEXTURE##Image##N##D( \ |
|
369 |
+ NAME, \ |
|
370 |
+ level, \ |
|
371 |
+ (GLint)internal_format, \ |
|
372 |
+ std::get<Is>(size)..., \ |
|
373 |
+ border, \ |
|
374 |
+ format, \ |
|
375 |
+ type, \ |
|
376 |
+ data \ |
|
377 |
+ ); \ |
|
378 |
+ } |
|
379 |
+ |
|
380 |
+#define GLTRAITS_TEXTURE_STORAGE( \ |
|
381 |
+ N, \ |
|
382 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
383 |
+ TYPE, NAME, \ |
|
384 |
+ V1, V2, EXT \ |
|
385 |
+) \ |
|
386 |
+ template<typename Value = GLubyte> \ |
|
387 |
+ void static TEXTURE_LOWER##_storage( \ |
|
388 |
+ TYPE NAME, \ |
|
389 |
+ Size size, \ |
|
390 |
+ GLenum internal_format = 0, \ |
|
391 |
+ GLsizei levels = 1 \ |
|
392 |
+ ) \ |
|
393 |
+ { \ |
|
394 |
+ if (GLBase::debug() >= 1) \ |
|
395 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
396 |
+ if (!internal_format) \ |
|
397 |
+ internal_format = GLTraits::Value<Value>::internal_format; \ |
|
398 |
+ gl##TEXTURE##Storage##N##D( \ |
|
399 |
+ NAME, \ |
|
400 |
+ levels, \ |
|
401 |
+ internal_format, \ |
|
402 |
+ std::get<Is>(size)... \ |
|
403 |
+ ); \ |
|
404 |
+ } |
|
405 |
+ |
|
406 |
+#define GLTRAITS_TEXTURE_SUB_IMAGE( \ |
|
407 |
+ N, \ |
|
408 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
409 |
+ TYPE, NAME, \ |
|
410 |
+ V1, V2, EXT \ |
|
411 |
+) \ |
|
412 |
+ template<typename Value = GLubyte> \ |
|
413 |
+ void static TEXTURE_LOWER##_sub_image( \ |
|
414 |
+ TYPE NAME, \ |
|
415 |
+ Size size, \ |
|
416 |
+ Value const * data, \ |
|
417 |
+ GLenum format = 0, \ |
|
418 |
+ GLenum type = 0, \ |
|
419 |
+ Offset offset = {}, \ |
|
420 |
+ GLint level = 0 \ |
|
421 |
+ ) \ |
|
422 |
+ { \ |
|
423 |
+ if (GLBase::debug() >= 1) \ |
|
424 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
425 |
+ if (!format) format = GLTraits::Value<Value>::format; \ |
|
426 |
+ if (!type) type = GLTraits::Value<Value>::type; \ |
|
427 |
+ gl##TEXTURE##SubImage##N##D( \ |
|
428 |
+ NAME, \ |
|
429 |
+ level, \ |
|
430 |
+ std::get<Is>(offset)..., \ |
|
431 |
+ std::get<Is>(size) ..., \ |
|
432 |
+ format, \ |
|
433 |
+ type, \ |
|
434 |
+ data \ |
|
435 |
+ ); \ |
|
436 |
+ } |
|
437 |
+ |
|
438 |
+#define GLTRAITS_TEXTURE_COPY_SUB_IMAGE( \ |
|
439 |
+ N, \ |
|
440 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
441 |
+ TYPE, NAME, \ |
|
442 |
+ V1, V2, EXT \ |
|
443 |
+) \ |
|
444 |
+ void static copy_##TEXTURE_LOWER##_sub_image( \ |
|
445 |
+ TYPE NAME, \ |
|
446 |
+ CopySize copy_size, \ |
|
447 |
+ CopyOffset copy_offset = {}, \ |
|
448 |
+ Offset offset = {}, \ |
|
449 |
+ GLint level = 0 \ |
|
450 |
+ ) \ |
|
451 |
+ { \ |
|
452 |
+ if (GLBase::debug() >= 1) \ |
|
453 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
454 |
+ glCopy##TEXTURE##SubImage##N##D( \ |
|
455 |
+ NAME, \ |
|
456 |
+ level, \ |
|
457 |
+ std::get<Is> (offset) ..., \ |
|
458 |
+ std::get<CopyOffsetIs>(copy_offset)..., \ |
|
459 |
+ std::get<CopySizeIs> (copy_size) ... \ |
|
460 |
+ ); \ |
|
461 |
+ } |
|
462 |
+ |
|
463 |
+#define GLTRAITS_TEXTURE_COMPRESSED_IMAGE( \ |
|
464 |
+ N, \ |
|
465 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
466 |
+ TYPE, NAME, \ |
|
467 |
+ V1, V2, EXT \ |
|
468 |
+) \ |
|
469 |
+ void static compressed_##TEXTURE_LOWER##_image( \ |
|
470 |
+ TYPE NAME, \ |
|
471 |
+ Size size, \ |
|
472 |
+ GLenum internal_format, \ |
|
473 |
+ GLsizei data_size = 0, \ |
|
474 |
+ void const * data = nullptr, \ |
|
475 |
+ GLint level = 0, \ |
|
476 |
+ GLint border = 0 \ |
|
477 |
+ ) \ |
|
478 |
+ { \ |
|
479 |
+ if (GLBase::debug() >= 1) \ |
|
480 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
481 |
+ glCompressed##TEXTURE##Image##N##D( \ |
|
482 |
+ NAME, \ |
|
483 |
+ level, \ |
|
484 |
+ internal_format, \ |
|
485 |
+ std::get<Is>(size)..., \ |
|
486 |
+ border, \ |
|
487 |
+ data_size, \ |
|
488 |
+ data \ |
|
489 |
+ ); \ |
|
490 |
+ } |
|
491 |
+ |
|
492 |
+#define GLTRAITS_TEXTURE_COMPRESSED_SUB_IMAGE( \ |
|
493 |
+ N, \ |
|
494 |
+ TEXTURE, TEXTURE_LOWER, \ |
|
495 |
+ TYPE, NAME, \ |
|
496 |
+ V1, V2, EXT \ |
|
497 |
+) \ |
|
498 |
+ void static compressed_##TEXTURE_LOWER##_sub_image( \ |
|
499 |
+ TYPE NAME, \ |
|
500 |
+ Size size, \ |
|
501 |
+ GLsizei data_size, \ |
|
502 |
+ void const * data, \ |
|
503 |
+ GLenum internal_format, \ |
|
504 |
+ Offset offset = {}, \ |
|
505 |
+ GLint level = 0 \ |
|
506 |
+ ) \ |
|
507 |
+ { \ |
|
508 |
+ if (GLBase::debug() >= 1) \ |
|
509 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
510 |
+ glCompressed##TEXTURE##SubImage##N##D( \ |
|
511 |
+ NAME, \ |
|
512 |
+ level, \ |
|
513 |
+ std::get<Is>(offset)..., \ |
|
514 |
+ std::get<Is>(size) ..., \ |
|
515 |
+ internal_format, \ |
|
516 |
+ data_size, \ |
|
517 |
+ data \ |
|
518 |
+ ); \ |
|
519 |
+ } |
|
520 |
+ |
|
521 |
+#define GLTRAITS_TEXTURE( \ |
|
522 |
+ N, \ |
|
523 |
+ V1_1, V2_1, \ |
|
524 |
+ V1_2, V2_2 \ |
|
525 |
+) \ |
|
526 |
+ template< \ |
|
527 |
+ std::size_t... Is, \ |
|
528 |
+ std::size_t... CopySizeIs, \ |
|
529 |
+ std::size_t... CopyOffsetIs \ |
|
530 |
+ > \ |
|
531 |
+ struct GLTraits::Texture_< \ |
|
532 |
+ N, \ |
|
533 |
+ GLTraits::Indices<Is...>, \ |
|
534 |
+ GLTraits::Indices<CopySizeIs...>, \ |
|
535 |
+ GLTraits::Indices<CopyOffsetIs...> \ |
|
536 |
+ > \ |
|
537 |
+ : \ |
|
538 |
+ GLTraits::Texture<0> \ |
|
539 |
+ { \ |
|
540 |
+ using Size = std::array<GLsizei, sizeof...(Is)>; \ |
|
541 |
+ using Offset = std::array<GLsizei, sizeof...(Is)>; \ |
|
542 |
+ using CopySize = std::array<GLsizei, sizeof...(CopySizeIs)>; \ |
|
543 |
+ using CopyOffset = std::array<GLsizei, sizeof...(CopyOffsetIs)>; \ |
|
544 |
+ auto static constexpr default_target = GL_TEXTURE_##N##D; \ |
|
545 |
+ auto static constexpr default_binding = GL_TEXTURE_BINDING_##N##D; \ |
|
546 |
+ GLTRAITS_TEXTURE_IMAGE( N, Tex, tex, GLenum, target, V1_1, V2_1, {}) \ |
|
547 |
+ GLTRAITS_TEXTURE_SUB_IMAGE( N, Tex, tex, GLenum, target, V1_2, V2_2, {}) \ |
|
548 |
+ GLTRAITS_TEXTURE_COPY_SUB_IMAGE( N, Tex, tex, GLenum, target, V1_2, V2_2, {}) \ |
|
549 |
+ GLTRAITS_TEXTURE_COMPRESSED_IMAGE( N, Tex, tex, GLenum, target, 1, 3, {}) \ |
|
550 |
+ GLTRAITS_TEXTURE_COMPRESSED_SUB_IMAGE(N, Tex, tex, GLenum, target, 1, 3, {}) \ |
|
551 |
+ GLTRAITS_TEXTURE_STORAGE( N, Tex, tex, GLenum, target, 4, 2, "GL_ARB_texture_storage") \ |
|
552 |
+ GLTRAITS_TEXTURE_STORAGE( N, Texture, texture, GLuint, texture, 4, 5, "GL_ARB_direct_state_access") \ |
|
553 |
+ GLTRAITS_TEXTURE_SUB_IMAGE( N, Texture, texture, GLuint, texture, 4, 5, "GL_ARB_direct_state_access") \ |
|
554 |
+ GLTRAITS_TEXTURE_COPY_SUB_IMAGE( N, Texture, texture, GLuint, texture, 4, 5, "GL_ARB_direct_state_access") \ |
|
555 |
+ GLTRAITS_TEXTURE_COMPRESSED_SUB_IMAGE(N, Texture, texture, GLuint, texture, 4, 5, "GL_ARB_direct_state_access") \ |
|
556 |
+ }; \ |
|
557 |
+ template<> \ |
|
558 |
+ struct GLTraits::Texture<N> \ |
|
559 |
+ : \ |
|
560 |
+ Texture_< \ |
|
561 |
+ N, \ |
|
562 |
+ MakeIndices<N>, \ |
|
563 |
+ MakeIndices<N < 2 ? N : 2>, \ |
|
564 |
+ MakeIndices<2> \ |
|
565 |
+ > \ |
|
566 |
+ {}; |
|
567 |
+ |
|
568 |
+GLTRAITS_TEXTURE(1, 1, 0, 1, 1) |
|
569 |
+GLTRAITS_TEXTURE(2, 1, 0, 1, 1) |
|
570 |
+GLTRAITS_TEXTURE(3, 1, 2, 1, 2) |
|
571 |
+ |
|
254 | 572 |
|
255 | 573 |
/// Guards |
256 | 574 |
|
... | ... |
@@ -7,6 +7,7 @@ |
7 | 7 |
/// Includes |
8 | 8 |
|
9 | 9 |
#include <cstddef> |
10 |
+#include <string> |
|
10 | 11 |
|
11 | 12 |
#include <glbase.hpp> |
12 | 13 |
|
... | ... |
@@ -26,6 +27,11 @@ public: |
26 | 27 |
template<GLenum id> |
27 | 28 |
struct ValueID; |
28 | 29 |
|
30 |
+ //// Object |
|
31 |
+ |
|
32 |
+ template<GLenum object_type> |
|
33 |
+ struct Object; |
|
34 |
+ |
|
29 | 35 |
}; |
30 | 36 |
|
31 | 37 |
//// Helpers |
... | ... |
@@ -171,6 +177,80 @@ GLTRAITS_VALUE_VECTOR( glm::dvec, DOUBLE, glm::value_ptr, , |
171 | 177 |
GLTRAITS_VALUE_MATRIX( glm::dmat, DOUBLE, glm::value_ptr, GL_FALSE, , d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") |
172 | 178 |
#endif |
173 | 179 |
|
180 |
+//// Object |
|
181 |
+ |
|
182 |
+#define GLTRAITS_OBJECT_( \ |
|
183 |
+ OBJECT_TYPE, OBJECT, \ |
|
184 |
+ GEN_OBJECTS, DELETE_OBJECTS, \ |
|
185 |
+ INFO_LOG_ARGS, \ |
|
186 |
+ V1, V2, EXT \ |
|
187 |
+) \ |
|
188 |
+ template<> \ |
|
189 |
+ struct GLTraits::Object<GL_##OBJECT_TYPE> \ |
|
190 |
+ { \ |
|
191 |
+ auto static constexpr name = "GL_" #OBJECT_TYPE; \ |
|
192 |
+ template<typename... Args> \ |
|
193 |
+ void static gen_objects(GLsizei n, GLuint * objects, Args... args) \ |
|
194 |
+ { \ |
|
195 |
+ if (GLBase::debug() >= 1) \ |
|
196 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
197 |
+ GEN_OBJECTS; \ |
|
198 |
+ } \ |
|
199 |
+ void static delete_objects(GLsizei n, GLuint const * objects) \ |
|
200 |
+ { \ |
|
201 |
+ if (GLBase::debug() >= 1) \ |
|
202 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
203 |
+ DELETE_OBJECTS; \ |
|
204 |
+ } \ |
|
205 |
+ GLTRAITS_##INFO_LOG_ARGS( \ |
|
206 |
+ std::string static info_log(GLuint object) \ |
|
207 |
+ { \ |
|
208 |
+ if (GLBase::debug() >= 1) \ |
|
209 |
+ GLBase::check_supported({V1, V2}, EXT); \ |
|
210 |
+ auto length = GLint{}; \ |
|
211 |
+ glGet##OBJECT##iv(object, GL_INFO_LOG_LENGTH, &length); \ |
|
212 |
+ if (length != 0) \ |
|
213 |
+ --length; \ |
|
214 |
+ auto info_log = std::string((std::size_t)length, char{}); \ |
|
215 |
+ glGet##OBJECT##InfoLog( \ |
|
216 |
+ object, \ |
|
217 |
+ length+1, \ |
|
218 |
+ nullptr, \ |
|
219 |
+ &info_log[0] \ |
|
220 |
+ ); \ |
|
221 |
+ return info_log; \ |
|
222 |
+ } \ |
|
223 |
+ ) \ |
|
224 |
+ }; |
|
225 |
+ |
|
226 |
+#define GLTRAITS_OBJECT(OBJECT_TYPE, OBJECT, OBJECTS, ...) \ |
|
227 |
+ GLTRAITS_OBJECT_( \ |
|
228 |
+ OBJECT_TYPE, OBJECT, \ |
|
229 |
+ glGen##OBJECTS(n, objects, args...), \ |
|
230 |
+ glDelete##OBJECTS(n, objects), \ |
|
231 |
+ __VA_ARGS__ \ |
|
232 |
+ ) |
|
233 |
+ |
|
234 |
+#define GLTRAITS_OBJECT_GLSL(OBJECT_TYPE, OBJECT, OBJECTS, ...) \ |
|
235 |
+ GLTRAITS_OBJECT_( \ |
|
236 |
+ OBJECT_TYPE, OBJECT, \ |
|
237 |
+ while (n--) objects[n] = glCreate##OBJECT(args...), \ |
|
238 |
+ while (n--) glDelete##OBJECT(objects[n]), \ |
|
239 |
+ __VA_ARGS__ \ |
|
240 |
+ ) |
|
241 |
+ |
|
242 |
+GLTRAITS_OBJECT( TEXTURE, Texture, Textures, OMIT, 1, 1, {}) |
|
243 |
+GLTRAITS_OBJECT( BUFFER, Buffer, Buffers, OMIT, 1, 5, {}) |
|
244 |
+GLTRAITS_OBJECT( QUERY, Query, Queries, OMIT, 1, 5, {}) |
|
245 |
+GLTRAITS_OBJECT_GLSL(PROGRAM, Program, Programs, KEEP, 2, 0, {}) |
|
246 |
+GLTRAITS_OBJECT_GLSL(SHADER, Shader, Shaders, KEEP, 2, 0, {}) |
|
247 |
+GLTRAITS_OBJECT( VERTEX_ARRAY, VertexArray, VertexArrays, OMIT, 3, 0, "GL_ARB_vertex_array_object") |
|
248 |
+GLTRAITS_OBJECT( FRAMEBUFFER, Framebuffer, Framebuffers, OMIT, 3, 0, "GL_ARB_framebuffer_object") |
|
249 |
+GLTRAITS_OBJECT( RENDERBUFFER, Renderbuffer, Renderbuffers, OMIT, 3, 0, "GL_ARB_framebuffer_object") |
|
250 |
+GLTRAITS_OBJECT( SAMPLER, Sampler, Samplers, OMIT, 3, 3, "GL_ARB_sampler_objects") |
|
251 |
+GLTRAITS_OBJECT( TRANSFORM_FEEDBACK, TransformFeedback, TransformFeedbacks, OMIT, 4, 0, "GL_ARB_transform_feedback2") |
|
252 |
+GLTRAITS_OBJECT( PROGRAM_PIPELINE, ProgramPipeline, ProgramPipelines, KEEP, 4, 1, "GL_ARB_separate_shader_objects") |
|
253 |
+ |
|
174 | 254 |
|
175 | 255 |
/// Guards |
176 | 256 |
|
... | ... |
@@ -23,6 +23,9 @@ public: |
23 | 23 |
template<typename> |
24 | 24 |
struct Value; |
25 | 25 |
|
26 |
+ template<GLenum id> |
|
27 |
+ struct ValueID; |
|
28 |
+ |
|
26 | 29 |
}; |
27 | 30 |
|
28 | 31 |
//// Helpers |
... | ... |
@@ -69,6 +72,11 @@ public: |
69 | 72 |
auto static constexpr internal_format_compressed = GLenum{GL_COMPRESSED_##FORMAT}; \ |
70 | 73 |
auto static constexpr internal_format_compressed_srgb = GLenum{GLTRAITS_VALUE_COMPRESSED_S##FORMAT}; \ |
71 | 74 |
auto static constexpr integer = bool(*#INTEGER); \ |
75 |
+ auto static constexpr id = \ |
|
76 |
+ (glsl == GL_INT || glsl == GL_UNSIGNED_INT) && \ |
|
77 |
+ sizeof(VALUE) < sizeof(GLint) \ |
|
78 |
+ ? type \ |
|
79 |
+ : glsl; \ |
|
72 | 80 |
void static uniform(GLint location, VALUE const & value) \ |
73 | 81 |
{ \ |
74 | 82 |
if (GLBase::debug() >= 1) \ |
... | ... |
@@ -112,6 +120,11 @@ public: |
112 | 120 |
(void const *)(offset + sizeof_column * column) \ |
113 | 121 |
); \ |
114 | 122 |
} \ |
123 |
+ }; \ |
|
124 |
+ template<> \ |
|
125 |
+ struct GLTraits::ValueID<GLTraits::Value<VALUE>::id> \ |
|
126 |
+ { \ |
|
127 |
+ using Value = VALUE; \ |
|
115 | 128 |
}; |
116 | 129 |
|
117 | 130 |
#define GLTRAITS_VALUE_SCALAR( VALUE, TYPE, GLSL, INTERNAL, ...) GLTRAITS_VALUE(VALUE, 1, 1, GLSL, RED, TYPE, R ##INTERNAL, OMIT, , , , __VA_ARGS__,) |
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,164 @@ |
1 |
+/// Guards |
|
2 |
+ |
|
3 |
+#ifndef GLTRAITS_HPP_ |
|
4 |
+#define GLTRAITS_HPP_ |
|
5 |
+ |
|
6 |
+ |
|
7 |
+/// Includes |
|
8 |
+ |
|
9 |
+#include <cstddef> |
|
10 |
+ |
|
11 |
+#include <glbase.hpp> |
|
12 |
+ |
|
13 |
+ |
|
14 |
+/// GLTraits |
|
15 |
+ |
|
16 |
+class GLTraits |
|
17 |
+{ |
|
18 |
+ |
|
19 |
+public: |
|
20 |
+ |
|
21 |
+ //// Value |
|
22 |
+ |
|
23 |
+ template<typename> |
|
24 |
+ struct Value; |
|
25 |
+ |
|
26 |
+}; |
|
27 |
+ |
|
28 |
+//// Helpers |
|
29 |
+ |
|
30 |
+#define GLTRAITS_KEEP(...) __VA_ARGS__ |
|
31 |
+#define GLTRAITS_OMIT(...) |
|
32 |
+ |
|
33 |
+//// Value |
|
34 |
+ |
|
35 |
+#define GLTRAITS_VALUE_SRED GL_SR8_EXT |
|
36 |
+#define GLTRAITS_VALUE_SRG GL_SRG8_EXT |
|
37 |
+#define GLTRAITS_VALUE_SRGB GL_SRGB8 |
|
38 |
+#define GLTRAITS_VALUE_SRGBA GL_SRGB8_ALPHA8 |
|
39 |
+ |
|
40 |
+#define GLTRAITS_VALUE_COMPRESSED_SRED GL_COMPRESSED_SRGB |
|
41 |
+#define GLTRAITS_VALUE_COMPRESSED_SRG GL_COMPRESSED_SRGB |
|
42 |
+#define GLTRAITS_VALUE_COMPRESSED_SRGB GL_COMPRESSED_SRGB |
|
43 |
+#define GLTRAITS_VALUE_COMPRESSED_SRGBA GL_COMPRESSED_SRGB_ALPHA |
|
44 |
+ |
|
45 |
+#define GLTRAITS_VALUE( \ |
|
46 |
+ VALUE, \ |
|
47 |
+ COLUMNS, ROWS, \ |
|
48 |
+ GLSL, FORMAT, TYPE, INTERNAL_FORMAT, \ |
|
49 |
+ OFFSET_ARGS, PTR, \ |
|
50 |
+ V, UNIFORM, SUFFIX, ATTRIB, \ |
|
51 |
+ INTEGER, \ |
|
52 |
+ NORMALIZE_ARGS, \ |
|
53 |
+ V1U, V2U, \ |
|
54 |
+ V1A, V2A, \ |
|
55 |
+ EXTU, EXTA, \ |
|
56 |
+ ... \ |
|
57 |
+) \ |
|
58 |
+ template<> \ |
|
59 |
+ struct GLTraits::Value<VALUE> \ |
|
60 |
+ { \ |
|
61 |
+ auto static constexpr name = #VALUE; \ |
|
62 |
+ auto static constexpr columns = GLint{COLUMNS}; \ |
|
63 |
+ auto static constexpr rows = GLint{ROWS}; \ |
|
64 |
+ auto static constexpr glsl = GLenum{GL_##GLSL}; \ |
|
65 |
+ auto static constexpr format = GLenum{GL_##FORMAT##INTEGER}; \ |
|
66 |
+ auto static constexpr type = GLenum{GL_##TYPE}; \ |
|
67 |
+ auto static constexpr internal_format = GLenum{GL_##INTERNAL_FORMAT}; \ |
|
68 |
+ auto static constexpr internal_format_srgb = GLenum{GLTRAITS_VALUE_S##FORMAT}; \ |
|
69 |
+ auto static constexpr internal_format_compressed = GLenum{GL_COMPRESSED_##FORMAT}; \ |
|
70 |
+ auto static constexpr internal_format_compressed_srgb = GLenum{GLTRAITS_VALUE_COMPRESSED_S##FORMAT}; \ |
|
71 |
+ auto static constexpr integer = bool(*#INTEGER); \ |
|
72 |
+ void static uniform(GLint location, VALUE const & value) \ |
|
73 |
+ { \ |
|
74 |
+ if (GLBase::debug() >= 1) \ |
|
75 |
+ GLBase::check_supported({V1U, V2U}, EXTU); \ |
|
76 |
+ glUniform##UNIFORM##ROWS##SUFFIX##V( \ |
|
77 |
+ location, \ |
|
78 |
+ __VA_ARGS__ \ |
|
79 |
+ PTR(value) \ |
|
80 |
+ ); \ |
|
81 |
+ } \ |
|
82 |
+ void static vertex_attrib(GLint location, VALUE const & value) \ |
|
83 |
+ { \ |
|
84 |
+ if (GLBase::debug() >= 1) \ |
|
85 |
+ GLBase::check_supported({V1A, V2A}, EXTA); \ |
|
86 |
+ if (location == -1) \ |
|
87 |
+ return; \ |
|
88 |
+ for (auto column = GLuint{0}; column < columns; ++column) \ |
|
89 |
+ glVertexAttrib##ATTRIB##ROWS##SUFFIX##V( \ |
|
90 |
+ (GLuint)location + column, \ |
|
91 |
+ PTR(value) GLTRAITS_##OFFSET_ARGS(+ rows * column) \ |
|
92 |
+ ); \ |
|
93 |
+ } \ |
|
94 |
+ void static vertex_attrib_pointer( \ |
|
95 |
+ GLint location, \ |
|
96 |
+ std::size_t offset = 0, \ |
|
97 |
+ std::size_t stride = sizeof(VALUE) \ |
|
98 |
+ ) \ |
|
99 |
+ { \ |
|
100 |
+ if (GLBase::debug() >= 1) \ |
|
101 |
+ GLBase::check_supported({V1A, V2A}, EXTA); \ |
|
102 |
+ if (location == -1) \ |
|
103 |
+ return; \ |
|
104 |
+ auto constexpr sizeof_column = sizeof(VALUE) / columns; \ |
|
105 |
+ for (auto column = GLuint{0}; column < columns; ++column) \ |
|
106 |
+ glVertexAttrib##ATTRIB##Pointer( \ |
|
107 |
+ (GLuint)location + column, \ |
|
108 |
+ rows, \ |
|
109 |
+ type, \ |
|
110 |
+ GLTRAITS_##NORMALIZE_ARGS(GL_FALSE,) \ |
|
111 |
+ (GLsizei)stride, \ |
|
112 |
+ (void const *)(offset + sizeof_column * column) \ |
|
113 |
+ ); \ |
|
114 |
+ } \ |
|
115 |
+ }; |
|
116 |
+ |
|
117 |
+#define GLTRAITS_VALUE_SCALAR( VALUE, TYPE, GLSL, INTERNAL, ...) GLTRAITS_VALUE(VALUE, 1, 1, GLSL, RED, TYPE, R ##INTERNAL, OMIT, , , , __VA_ARGS__,) |
|
118 |
+#define GLTRAITS_VALUE_VECTOR_N( N, FORMAT, VALUE, TYPE, PTR, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N, 1, N, TYPE##_VEC##N, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, , __VA_ARGS__, 1,) |
|
119 |
+#define GLTRAITS_VALUE_MATRIX_N( N, FORMAT, VALUE, TYPE, PTR, T, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N, N, N, TYPE##_MAT##N, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, Matrix, __VA_ARGS__, 1, T,) |
|
120 |
+#define GLTRAITS_VALUE_MATRIX_N_M(N, M, FORMAT, VALUE, TYPE, PTR, T, INTERNAL, ...) GLTRAITS_VALUE(VALUE##N##x##M, N, M, TYPE##_MAT##N##x##M, FORMAT, TYPE, FORMAT##INTERNAL, KEEP, PTR, v, Matrix##N##x, __VA_ARGS__, 1, T,) |
|
121 |
+ |
|
122 |
+#define GLTRAITS_VALUE_VECTOR(...) \ |
|
123 |
+ GLTRAITS_VALUE_VECTOR_N( 2, RG, __VA_ARGS__) \ |
|
124 |
+ GLTRAITS_VALUE_VECTOR_N( 3, RGB, __VA_ARGS__) \ |
|
125 |
+ GLTRAITS_VALUE_VECTOR_N( 4, RGBA, __VA_ARGS__) |
|
126 |
+ |
|
127 |
+#define GLTRAITS_VALUE_MATRIX_(SUPPORT_ARGS, ...) \ |
|
128 |
+ GLTRAITS_VALUE_MATRIX_N( 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) \ |
|
129 |
+ GLTRAITS_VALUE_MATRIX_N_M(2, 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
130 |
+ GLTRAITS_VALUE_MATRIX_N_M(2, 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
131 |
+ GLTRAITS_VALUE_MATRIX_N_M(3, 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
132 |
+ GLTRAITS_VALUE_MATRIX_N( 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) \ |
|
133 |
+ GLTRAITS_VALUE_MATRIX_N_M(3, 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
134 |
+ GLTRAITS_VALUE_MATRIX_N_M(4, 2, RG, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
135 |
+ GLTRAITS_VALUE_MATRIX_N_M(4, 3, RGB, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 1, 2, 0, {}, {})) \ |
|
136 |
+ GLTRAITS_VALUE_MATRIX_N( 4, RGBA, __VA_ARGS__ GLTRAITS_##SUPPORT_ARGS(, 2, 0, 2, 0, {}, {})) |
|
137 |
+ |
|
138 |
+#define GLTRAITS_VALUE_MATRIXS(...) GLTRAITS_VALUE_MATRIX_(KEEP, __VA_ARGS__) |
|
139 |
+#define GLTRAITS_VALUE_MATRIX(...) GLTRAITS_VALUE_MATRIX_(OMIT, __VA_ARGS__) |
|
140 |
+ |
|
141 |
+GLTRAITS_VALUE_SCALAR( GLfloat, FLOAT, FLOAT, 32F, f, , , KEEP, 2, 0, 2, 0, {}, {}) |
|
142 |
+GLTRAITS_VALUE_SCALAR( bool, BYTE, BOOL, 8I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) |
|
143 |
+GLTRAITS_VALUE_SCALAR( GLbyte, BYTE, INT, 8I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) |
|
144 |
+GLTRAITS_VALUE_SCALAR( GLshort, SHORT, INT, 16I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) |
|
145 |
+GLTRAITS_VALUE_SCALAR( GLint, INT, INT, 32I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) |
|
146 |
+GLTRAITS_VALUE_SCALAR( GLubyte, UNSIGNED_BYTE, UNSIGNED_INT, 8UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) |
|
147 |
+GLTRAITS_VALUE_SCALAR( GLushort, UNSIGNED_SHORT, UNSIGNED_INT, 16UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) |
|
148 |
+GLTRAITS_VALUE_SCALAR( GLuint, UNSIGNED_INT, UNSIGNED_INT, 32UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) |
|
149 |
+GLTRAITS_VALUE_SCALAR( GLdouble, DOUBLE, DOUBLE, ED, d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") |
|
150 |
+ |
|
151 |
+#ifdef GLM_VERSION |
|
152 |
+#include <glm/gtc/type_ptr.hpp> |
|
153 |
+GLTRAITS_VALUE_VECTOR( glm::vec, FLOAT, glm::value_ptr, 32F, f, , , KEEP, 2, 0, 2, 0, {}, {}) |
|
154 |
+GLTRAITS_VALUE_MATRIXS(glm::mat, FLOAT, glm::value_ptr, GL_FALSE, 32F, f, , , KEEP) |
|
155 |
+GLTRAITS_VALUE_VECTOR( glm::ivec, INT, glm::value_ptr, 32I, i, I, _INTEGER, OMIT, 2, 0, 3, 0, {}, {}) |
|
156 |
+GLTRAITS_VALUE_VECTOR( glm::uvec, UNSIGNED_INT, glm::value_ptr, 32UI, ui, I, _INTEGER, OMIT, 3, 0, 3, 0, {}, {}) |
|
157 |
+GLTRAITS_VALUE_VECTOR( glm::dvec, DOUBLE, glm::value_ptr, , d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") |
|
158 |
+GLTRAITS_VALUE_MATRIX( glm::dmat, DOUBLE, glm::value_ptr, GL_FALSE, , d, L, , OMIT, 4, 0, 4, 1, "GL_ARB_gpu_shader_fp64", "GL_ARB_vertex_attrib_64bit") |
|
159 |
+#endif |
|
160 |
+ |
|
161 |
+ |
|
162 |
+/// Guards |
|
163 |
+ |
|
164 |
+#endif |