From 3fe690f2d64c4e8ce525da1c9732b7f3aa6fe370 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 4 Aug 2024 13:10:15 +0100 Subject: Specific exception for shader compile error Outputs more details, including shader source --- gfx/gl/shader.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++----------- gfx/gl/shader.h | 6 ++++-- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/gfx/gl/shader.cpp b/gfx/gl/shader.cpp index 47d36d0..931c372 100644 --- a/gfx/gl/shader.cpp +++ b/gfx/gl/shader.cpp @@ -1,4 +1,5 @@ #include "shader.h" +#include "msgException.h" #include #include #include @@ -18,6 +19,39 @@ namespace { constexpr std::array, 1> LOOKUPS {{ {"GL_MAX_GEOMETRY_OUTPUT_VERTICES", GL_MAX_GEOMETRY_OUTPUT_VERTICES, getInt}, }}; + + struct ShaderCompileError : public MsgException { + explicit ShaderCompileError(GLuint shader, Shader::Source src) : + MsgException {"Error compiling shader"}, shader {shader}, source {src}, + msg {getShaderText(GL_INFO_LOG_LENGTH, glGetShaderInfoLog)} + { + } + + [[nodiscard]] std::string + getMsg() const noexcept override + { + return std::format("Error compiling shader: '{}'\nSource:\n{}", + getShaderText(GL_INFO_LOG_LENGTH, glGetShaderInfoLog), source); + } + + private: + std::string + getShaderText(GLenum param, auto getTextFunc) const + { + std::string text; + text.resize_and_overwrite(static_cast(Shader::getShaderParam(shader, param)), + [this, getTextFunc](auto buf, auto len) { + GLsizei outLen {}; + getTextFunc(shader, static_cast(len), &outLen, buf); + return outLen; + }); + return text; + } + + const GLuint shader; + const Shader::Source source; + const std::string msg; + }; } Shader::ShaderRef @@ -46,21 +80,22 @@ Shader::compile() const } glCompileShader(shader); - checkShaderError(shader, GL_COMPILE_STATUS, "Error compiling shader!"); + checkShaderError(shader); return shader; } void -Shader::checkShaderError(GLuint shader, GLuint flag, std::string_view errorMessage) const +Shader::checkShaderError(GLuint shader) const { - GLint success = 0; - - glGetShaderiv(shader, flag, &success); - - if (success == GL_FALSE) { - std::array error {}; - glGetShaderInfoLog(shader, error.size(), nullptr, error.data()); - - throw std::runtime_error {std::format("{}: '{}'", errorMessage, error.data())}; + if (getShaderParam(shader, GL_COMPILE_STATUS) == GL_FALSE) { + throw ShaderCompileError {shader, text}; } } + +GLint +Shader::getShaderParam(GLuint shader, GLenum pname) +{ + GLint pvalue {}; + glGetShaderiv(shader, pname, &pvalue); + return pvalue; +} diff --git a/gfx/gl/shader.h b/gfx/gl/shader.h index 1e4a2ee..ce97734 100644 --- a/gfx/gl/shader.h +++ b/gfx/gl/shader.h @@ -7,6 +7,7 @@ class Shader { public: + using Source = std::basic_string_view; using ShaderRef = glRef; constexpr Shader(const GLchar * text, GLuint type) : @@ -16,10 +17,11 @@ public: [[nodiscard]] ShaderRef compile() const; + [[nodiscard]] static GLint getShaderParam(GLuint shader, GLenum pname); + private: - using Source = std::basic_string_view; + void checkShaderError(GLuint shader) const; - void checkShaderError(GLuint shader, GLuint flag, std::string_view errorMessage) const; const Source text; GLuint type; bool lookups; -- cgit v1.2.3