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