Browse code

Add Object

Robert Cranston authored on 28/02/2023 02:19:27
Showing 5 changed files

... ...
@@ -17,6 +17,7 @@ add_library(${PROJECT_NAME} INTERFACE)
17 17
 include(common.cmake)
18 18
 common(
19 19
     CXX_STANDARD 11
20
+    DISABLE_CPPCHECK # GLTRAITS_TEST_OBJECT(template gen_objects<Args...>)
20 21
     PACKAGES
21 22
         glm
22 23
     FETCHCONTENT
... ...
@@ -154,6 +154,56 @@ alias for `glm::vec3`.
154 154
 [`glDisableVertexAttribArray`]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml
155 155
 [`glEnableVertexAttribArray`]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml
156 156
 
157
+### Object
158
+
159
+The [empty][] `struct GLTraits::Object<GLenum object_type>` is template
160
+specialized on the following values.
161
+
162
+-   `GL_TEXTURE`
163
+-   `GL_BUFFER`
164
+-   `GL_QUERY`
165
+-   `GL_PROGRAM`
166
+-   `GL_SHADER`
167
+-   `GL_VERTEX_ARRAY`
168
+-   `GL_FRAMEBUFFER`
169
+-   `GL_RENDERBUFFER`
170
+-   `GL_SAMPLER`
171
+-   `GL_TRANSFORM_FEEDBACK`
172
+-   `GL_PROGRAM_PIPELINE`
173
+
174
+`GLTraits::Object` contains the following `static constexpr` member variables.
175
+
176
+-   `char const name[]`
177
+
178
+`GLTraits::Object` contains the following `static` member functions.
179
+
180
+-   ```cpp
181
+    template<typename... Args>
182
+    void gen_objects(GLsizei n, GLuint * objects, Args... args)
183
+    ```
184
+
185
+    Generalization of `glGen*s` and `glCreate`.
186
+
187
+-   ```cpp
188
+    void delete_objects(GLsizei n, GLuint * objects)
189
+    ```
190
+
191
+    Generalization of `glDelete*s` and `glDelete*`.
192
+
193
+For `object_types` equal to  `GL_SHADER`, `GL_PROGRAM`, and
194
+`GL_PROGRAM_PIPELINE`, `GLTraits::Object` additionally contains the following
195
+`static` member functions.
196
+
197
+-   ```cpp
198
+    std::string info_log(GLuint object)
199
+    ```
200
+
201
+    Generalization of `glGet*InfoLog`.
202
+
203
+`GLTRAITS_OBJECT*` macros are defined to ease the definition of new template
204
+specializations of `GLTraits::Object`. Consult the source for the definitions
205
+and usage examples.
206
+
157 207
 ## Building
158 208
 
159 209
 See [`BUILDING.md`][].
... ...
@@ -5,6 +5,8 @@ class GLTraits
5 5
     template <typename> struct Value;
6 6
 
7 7
     template <GLenum id> struct ValueID;
8
+
9
+    template <GLenum object_type> struct Object;
8 10
 };
9 11
 
10 12
 template <> struct GLTraits::Value<GLfloat>
... ...
@@ -2382,3 +2384,252 @@ template <> struct GLTraits::ValueID<GLTraits::Value<glm::dmat4>::id>
2382 2384
     using Value = glm::dmat4;
2383 2385
 };
2384 2386
 
2387
+template <> struct GLTraits::Object<GL_TEXTURE>
2388
+{
2389
+    auto static constexpr name = "GL_"
2390
+                                 "TEXTURE";
2391
+    template <typename... Args>
2392
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2393
+    {
2394
+        if (GLBase::debug() >= 1)
2395
+            GLBase::check_supported({1, 1}, {});
2396
+        glGenTextures(n, objects, args...);
2397
+    }
2398
+    void static delete_objects(GLsizei n, GLuint const * objects)
2399
+    {
2400
+        if (GLBase::debug() >= 1)
2401
+            GLBase::check_supported({1, 1}, {});
2402
+        glDeleteTextures(n, objects);
2403
+    }
2404
+};
2405
+
2406
+template <> struct GLTraits::Object<GL_BUFFER>
2407
+{
2408
+    auto static constexpr name = "GL_"
2409
+                                 "BUFFER";
2410
+    template <typename... Args>
2411
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2412
+    {
2413
+        if (GLBase::debug() >= 1)
2414
+            GLBase::check_supported({1, 5}, {});
2415
+        glGenBuffers(n, objects, args...);
2416
+    }
2417
+    void static delete_objects(GLsizei n, GLuint const * objects)
2418
+    {
2419
+        if (GLBase::debug() >= 1)
2420
+            GLBase::check_supported({1, 5}, {});
2421
+        glDeleteBuffers(n, objects);
2422
+    }
2423
+};
2424
+
2425
+template <> struct GLTraits::Object<GL_QUERY>
2426
+{
2427
+    auto static constexpr name = "GL_"
2428
+                                 "QUERY";
2429
+    template <typename... Args>
2430
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2431
+    {
2432
+        if (GLBase::debug() >= 1)
2433
+            GLBase::check_supported({1, 5}, {});
2434
+        glGenQueries(n, objects, args...);
2435
+    }
2436
+    void static delete_objects(GLsizei n, GLuint const * objects)
2437
+    {
2438
+        if (GLBase::debug() >= 1)
2439
+            GLBase::check_supported({1, 5}, {});
2440
+        glDeleteQueries(n, objects);
2441
+    }
2442
+};
2443
+
2444
+template <> struct GLTraits::Object<GL_PROGRAM>
2445
+{
2446
+    auto static constexpr name = "GL_"
2447
+                                 "PROGRAM";
2448
+    template <typename... Args>
2449
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2450
+    {
2451
+        if (GLBase::debug() >= 1)
2452
+            GLBase::check_supported({2, 0}, {});
2453
+        while (n--)
2454
+            objects[n] = glCreateProgram(args...);
2455
+    }
2456
+    void static delete_objects(GLsizei n, GLuint const * objects)
2457
+    {
2458
+        if (GLBase::debug() >= 1)
2459
+            GLBase::check_supported({2, 0}, {});
2460
+        while (n--)
2461
+            glDeleteProgram(objects[n]);
2462
+    }
2463
+    std::string static info_log(GLuint object)
2464
+    {
2465
+        if (GLBase::debug() >= 1)
2466
+            GLBase::check_supported({2, 0}, {});
2467
+        auto length = GLint{};
2468
+        glGetProgramiv(object, GL_INFO_LOG_LENGTH, &length);
2469
+        if (length != 0)
2470
+            --length;
2471
+        auto info_log = std::string((std::size_t)length, char{});
2472
+        glGetProgramInfoLog(object, length + 1, nullptr, &info_log[0]);
2473
+        return info_log;
2474
+    }
2475
+};
2476
+
2477
+template <> struct GLTraits::Object<GL_SHADER>
2478
+{
2479
+    auto static constexpr name = "GL_"
2480
+                                 "SHADER";
2481
+    template <typename... Args>
2482
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2483
+    {
2484
+        if (GLBase::debug() >= 1)
2485
+            GLBase::check_supported({2, 0}, {});
2486
+        while (n--)
2487
+            objects[n] = glCreateShader(args...);
2488
+    }
2489
+    void static delete_objects(GLsizei n, GLuint const * objects)
2490
+    {
2491
+        if (GLBase::debug() >= 1)
2492
+            GLBase::check_supported({2, 0}, {});
2493
+        while (n--)
2494
+            glDeleteShader(objects[n]);
2495
+    }
2496
+    std::string static info_log(GLuint object)
2497
+    {
2498
+        if (GLBase::debug() >= 1)
2499
+            GLBase::check_supported({2, 0}, {});
2500
+        auto length = GLint{};
2501
+        glGetShaderiv(object, GL_INFO_LOG_LENGTH, &length);
2502
+        if (length != 0)
2503
+            --length;
2504
+        auto info_log = std::string((std::size_t)length, char{});
2505
+        glGetShaderInfoLog(object, length + 1, nullptr, &info_log[0]);
2506
+        return info_log;
2507
+    }
2508
+};
2509
+
2510
+template <> struct GLTraits::Object<GL_VERTEX_ARRAY>
2511
+{
2512
+    auto static constexpr name = "GL_"
2513
+                                 "VERTEX_ARRAY";
2514
+    template <typename... Args>
2515
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2516
+    {
2517
+        if (GLBase::debug() >= 1)
2518
+            GLBase::check_supported({3, 0}, "GL_ARB_vertex_array_object");
2519
+        glGenVertexArrays(n, objects, args...);
2520
+    }
2521
+    void static delete_objects(GLsizei n, GLuint const * objects)
2522
+    {
2523
+        if (GLBase::debug() >= 1)
2524
+            GLBase::check_supported({3, 0}, "GL_ARB_vertex_array_object");
2525
+        glDeleteVertexArrays(n, objects);
2526
+    }
2527
+};
2528
+
2529
+template <> struct GLTraits::Object<GL_FRAMEBUFFER>
2530
+{
2531
+    auto static constexpr name = "GL_"
2532
+                                 "FRAMEBUFFER";
2533
+    template <typename... Args>
2534
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2535
+    {
2536
+        if (GLBase::debug() >= 1)
2537
+            GLBase::check_supported({3, 0}, "GL_ARB_framebuffer_object");
2538
+        glGenFramebuffers(n, objects, args...);
2539
+    }
2540
+    void static delete_objects(GLsizei n, GLuint const * objects)
2541
+    {
2542
+        if (GLBase::debug() >= 1)
2543
+            GLBase::check_supported({3, 0}, "GL_ARB_framebuffer_object");
2544
+        glDeleteFramebuffers(n, objects);
2545
+    }
2546
+};
2547
+
2548
+template <> struct GLTraits::Object<GL_RENDERBUFFER>
2549
+{
2550
+    auto static constexpr name = "GL_"
2551
+                                 "RENDERBUFFER";
2552
+    template <typename... Args>
2553
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2554
+    {
2555
+        if (GLBase::debug() >= 1)
2556
+            GLBase::check_supported({3, 0}, "GL_ARB_framebuffer_object");
2557
+        glGenRenderbuffers(n, objects, args...);
2558
+    }
2559
+    void static delete_objects(GLsizei n, GLuint const * objects)
2560
+    {
2561
+        if (GLBase::debug() >= 1)
2562
+            GLBase::check_supported({3, 0}, "GL_ARB_framebuffer_object");
2563
+        glDeleteRenderbuffers(n, objects);
2564
+    }
2565
+};
2566
+
2567
+template <> struct GLTraits::Object<GL_SAMPLER>
2568
+{
2569
+    auto static constexpr name = "GL_"
2570
+                                 "SAMPLER";
2571
+    template <typename... Args>
2572
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2573
+    {
2574
+        if (GLBase::debug() >= 1)
2575
+            GLBase::check_supported({3, 3}, "GL_ARB_sampler_objects");
2576
+        glGenSamplers(n, objects, args...);
2577
+    }
2578
+    void static delete_objects(GLsizei n, GLuint const * objects)
2579
+    {
2580
+        if (GLBase::debug() >= 1)
2581
+            GLBase::check_supported({3, 3}, "GL_ARB_sampler_objects");
2582
+        glDeleteSamplers(n, objects);
2583
+    }
2584
+};
2585
+
2586
+template <> struct GLTraits::Object<GL_TRANSFORM_FEEDBACK>
2587
+{
2588
+    auto static constexpr name = "GL_"
2589
+                                 "TRANSFORM_FEEDBACK";
2590
+    template <typename... Args>
2591
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2592
+    {
2593
+        if (GLBase::debug() >= 1)
2594
+            GLBase::check_supported({4, 0}, "GL_ARB_transform_feedback2");
2595
+        glGenTransformFeedbacks(n, objects, args...);
2596
+    }
2597
+    void static delete_objects(GLsizei n, GLuint const * objects)
2598
+    {
2599
+        if (GLBase::debug() >= 1)
2600
+            GLBase::check_supported({4, 0}, "GL_ARB_transform_feedback2");
2601
+        glDeleteTransformFeedbacks(n, objects);
2602
+    }
2603
+};
2604
+
2605
+template <> struct GLTraits::Object<GL_PROGRAM_PIPELINE>
2606
+{
2607
+    auto static constexpr name = "GL_"
2608
+                                 "PROGRAM_PIPELINE";
2609
+    template <typename... Args>
2610
+    void static gen_objects(GLsizei n, GLuint * objects, Args... args)
2611
+    {
2612
+        if (GLBase::debug() >= 1)
2613
+            GLBase::check_supported({4, 1}, "GL_ARB_separate_shader_objects");
2614
+        glGenProgramPipelines(n, objects, args...);
2615
+    }
2616
+    void static delete_objects(GLsizei n, GLuint const * objects)
2617
+    {
2618
+        if (GLBase::debug() >= 1)
2619
+            GLBase::check_supported({4, 1}, "GL_ARB_separate_shader_objects");
2620
+        glDeleteProgramPipelines(n, objects);
2621
+    }
2622
+    std::string static info_log(GLuint object)
2623
+    {
2624
+        if (GLBase::debug() >= 1)
2625
+            GLBase::check_supported({4, 1}, "GL_ARB_separate_shader_objects");
2626
+        auto length = GLint{};
2627
+        glGetProgramPipelineiv(object, GL_INFO_LOG_LENGTH, &length);
2628
+        if (length != 0)
2629
+            --length;
2630
+        auto info_log = std::string((std::size_t)length, char{});
2631
+        glGetProgramPipelineInfoLog(object, length + 1, nullptr, &info_log[0]);
2632
+        return info_log;
2633
+    }
2634
+};
2635
+
... ...
@@ -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
 
... ...
@@ -61,6 +61,26 @@ struct GLTraitsTest : protected GLBase
61 61
             << "  " << GLTraits::Value<typename Traits::Value>::name << "\n";
62 62
     }
63 63
 
64
+    template<GLenum object_type, typename... Args>
65
+    void static test_object()
66
+    {
67
+        using Traits = GLTraits::Object<object_type>;
68
+        static_assert(
69
+            std::is_empty<Traits>::value,
70
+            "GLTraits::Object must be empty"
71
+        );
72
+        #define GLTRAITS_TEST_OBJECT(NAME) \
73
+            << std::left << std::setw(33) \
74
+            << "  " #NAME ":" \
75
+            << (void *)Traits::NAME \
76
+            << "\n"
77
+        std::cout
78
+            << "Object<" << Traits::name << ">" << "\n"
79
+            GLTRAITS_TEST_OBJECT(template gen_objects<Args...>)
80
+            GLTRAITS_TEST_OBJECT(delete_objects)
81
+            GLTRAITS_TEST_OBJECT(info_log);
82
+    }
83
+
64 84
 };
65 85
 
66 86
 
... ...
@@ -81,4 +101,7 @@ int main()
81 101
     GLTraitsTest::test_value_id<GL_FLOAT_MAT4x3>();
82 102
     GLTraitsTest::test_value_id<GL_UNSIGNED_INT_VEC2>();
83 103
     GLTraitsTest::test_value_id<GL_DOUBLE_VEC2>();
104
+
105
+    GLTraitsTest::test_object<GL_SHADER, GLenum>();
106
+    GLTraitsTest::test_object<GL_PROGRAM_PIPELINE>();
84 107
 }