Browse code

Add validate

Robert Cranston authored on 27/02/2021 00:19:43
Showing 5 changed files

... ...
@@ -28,9 +28,18 @@ int main()
28 28
         "player.vert",
29 29
         "player.frag", "lighting.frag",
30 30
     });
31
+
32
+    // Use.
33
+    player
34
+        .validate();
31 35
 }
32 36
 ```
33 37
 
38
+All public (non-static) member functions return a reference to the current
39
+object, allowing [method chaining][].
40
+
41
+[method chaining]: https://en.wikipedia.org/wiki/Method_chaining
42
+
34 43
 ### Errors
35 44
 
36 45
 Errors are handled by throwing [`std::runtime_error`][] with a [`what()`][]
... ...
@@ -100,6 +109,22 @@ a separating `"/"` if non-empty, to all paths (defaults to `""`).
100 109
 [shader stage]: https://www.khronos.org/opengl/wiki/Shader#Stages
101 110
 [OpenGL / OpenGL ES Reference Compiler]: https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
102 111
 
112
+### Validation
113
+
114
+By calling `validate()` the shader can be [validate][]d against the current
115
+OpenGL state to make sure that a subsequent draw call would succeed. An error
116
+is thrown if a problem is detected.
117
+
118
+Additional issues that are not typically detected by [`glValidateProgram`][]
119
+are checked for.
120
+
121
+If the macro [`NDEBUG`][] is defined, the check is optimised out. Therefore, it
122
+is recommended to always call `validate()` before issuing draw calls.
123
+
124
+[validate]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgram.xhtml
125
+[`glValidateProgram`]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgram.xhtml
126
+[`NDEBUG`]: https://en.cppreference.com/w/c/error/assert
127
+
103 128
 ## Dependencies
104 129
 
105 130
 Public (interface):
106 131
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+#version 110
2
+
3
+
4
+uniform sampler1D sampler1;
5
+uniform sampler2D sampler2;
6
+
7
+
8
+void main()
9
+{
10
+    gl_Position =
11
+        texture1D(sampler1, 0.0) +
12
+        texture2D(sampler2, vec2(0.0));
13
+}
... ...
@@ -25,14 +25,27 @@ public:
25 25
 
26 26
     GLuint program() const;
27 27
 
28
+    Shader & validate();
29
+
28 30
 protected:
29 31
 
32
+    void validate_() const;
33
+
30 34
     GLuint             program_;
31 35
     std::string        program_name_;
32 36
     std::string static root_;
33 37
 };
34 38
 
35 39
 
40
+// Debug macros.
41
+
42
+#ifndef NDEBUG
43
+    #define GLSHADER_DEBUG_(...) __VA_ARGS__
44
+#else
45
+    #define GLSHADER_DEBUG_(...)
46
+#endif // NDEBUG
47
+
48
+
36 49
 // Inline definitions.
37 50
 
38 51
 #define GLSHADER_SET_(TYPE, NAME) \
... ...
@@ -47,5 +60,11 @@ inline GLuint Shader::program() const
47 60
     return program_;
48 61
 }
49 62
 
63
+inline Shader & Shader::validate()
64
+{
65
+    GLSHADER_DEBUG_(validate_();)
66
+    return *this;
67
+}
68
+
50 69
 
51 70
 #endif // GLSHADER_SHADER_HPP_
... ...
@@ -216,3 +216,17 @@ Shader::~Shader()
216 216
     if (program_)
217 217
         glDeleteProgram(program_);
218 218
 }
219
+
220
+
221
+void Shader::validate_() const
222
+{
223
+    // Set error.
224
+    auto const validate_error = STR("Failed to validate " << program_name_);
225
+
226
+    // Validate program.
227
+    info_log_action_(
228
+        validate_error,
229
+        glValidateProgram, program_,
230
+        GL_VALIDATE_STATUS, glGetProgramiv, glGetProgramInfoLog
231
+    );
232
+}
... ...
@@ -39,11 +39,21 @@ GLTEST(2, 0, 640, 480, glshader)
39 39
         "error: vertex shader does not write to `gl_Position'. \n"
40 40
     )
41 41
 
42
+    // Validate.
43
+    GLTEST_EXPECT_EXCEPTION(true,
44
+        Shader({"tests/validate_bad_samplers.vert"}).validate(),
45
+        "Failed to validate shader program 'tests/validate_bad_samplers.vert':\n"
46
+        "active samplers with a different type refer to the same texture image unit"
47
+    )
48
+
42 49
     auto all = Shader({
43 50
         "tests/all.vert",
44 51
         "tests/all.frag",
45 52
     });
46 53
 
54
+    all
55
+        .validate();
56
+
47 57
     constexpr auto size = 0.5F;
48 58
     glBegin(GL_TRIANGLE_STRIP);
49 59
     glVertex3f(-size, -size, 0.0F);