... | ... |
@@ -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): |
... | ... |
@@ -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); |