From cfe6014b68242b9b2ac239427aac5f96e78df0ba Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 6 Apr 2013 14:02:24 -0300 Subject: [PATCH] Improved shader:getWarnings() to return shader compiler warnings as well as shader program linker and usage warnings --- src/modules/graphics/opengl/Shader.cpp | 59 +++++++++++++++++--------- src/modules/graphics/opengl/Shader.h | 6 +++ 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 4453433bc..55e1a0fe3 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -97,17 +97,17 @@ Shader::~Shader() GLuint Shader::compileCode(ShaderType type, const std::string &code) { GLenum glshadertype; - const char *shadertypename = NULL; + const char *shadertypestr = NULL; switch (type) { case TYPE_VERTEX: glshadertype = GL_VERTEX_SHADER; - shadertypename = "vertex"; + shadertypestr = "vertex"; break; case TYPE_PIXEL: glshadertype = GL_FRAGMENT_SHADER; - shadertypename = "pixel"; + shadertypestr = "pixel"; break; default: throw love::Exception("Cannot create shader object: unknown shader type."); @@ -124,9 +124,9 @@ GLuint Shader::compileCode(ShaderType type, const std::string &code) GLenum err = glGetError(); if (err == GL_INVALID_ENUM) // invalid or unsupported shader type - throw love::Exception("Cannot create %s shader object: %s shaders not supported.", shadertypename, shadertypename); + throw love::Exception("Cannot create %s shader object: %s shaders not supported.", shadertypestr, shadertypestr); else // other errors should only happen between glBegin() and glEnd() - throw love::Exception("Cannot create %s shader object.", shadertypename); + throw love::Exception("Cannot create %s shader object.", shadertypestr); } const char *src = code.c_str(); @@ -135,23 +135,26 @@ GLuint Shader::compileCode(ShaderType type, const std::string &code) glCompileShader(shaderid); + // Get any warnings the shader compiler may have produced + GLint infologlen; + glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen); + + GLchar *infolog = new GLchar[infologlen + 1]; + glGetShaderInfoLog(shaderid, infologlen, NULL, infolog); + + // Save any warnings for later querying + if (infologlen > 0) + shaderWarnings[type] = shadertypestr + std::string(" shader:\n") + infolog; + + delete[] infolog; + GLint status; glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { - GLint infologlen; - glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen); - - GLchar *errorlog = new GLchar[infologlen + 1]; - glGetShaderInfoLog(shaderid, infologlen, NULL, errorlog); - - std::string tmp(errorlog); - - delete[] errorlog; - glDeleteShader(shaderid); - - throw love::Exception("Cannot compile %s shader code:\n%s", shadertypename, tmp.c_str()); + throw love::Exception("Cannot compile %s shader code:\n%s", + shadertypestr, shaderWarnings[type].c_str()); } return shaderid; @@ -177,7 +180,7 @@ void Shader::createProgram(const std::vector &shaderids) if (status == GL_FALSE) { - std::string warnings = getWarnings(); + std::string warnings = getProgramWarnings(); glDeleteProgram(program); throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str()); @@ -236,12 +239,15 @@ void Shader::unloadVolatile() // same with uniform location list uniforms.clear(); + + shaderWarnings.clear(); } -std::string Shader::getWarnings() const +std::string Shader::getProgramWarnings() const { GLint strlen, nullpos; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strlen); + char *tempstr = new char[strlen+1]; // be extra sure that the error string will be 0-terminated memset(tempstr, '\0', strlen+1); @@ -250,6 +256,21 @@ std::string Shader::getWarnings() const std::string warnings(tempstr); delete[] tempstr; + + return warnings; +} + +std::string Shader::getWarnings() const +{ + std::string warnings; + + // Get the individual shader stage warnings + std::map::const_iterator it; + for (it = shaderWarnings.begin(); it != shaderWarnings.end(); ++it) + warnings += it->second; + + warnings += getProgramWarnings(); + return warnings; } diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 1bb2cc0e3..1284be0aa 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -133,9 +133,15 @@ private: void sendTexture(const std::string &name, GLuint texture); + // Get any warnings or errors generated only by the shader program object. + std::string getProgramWarnings() const; + // List of all shader code attached to this Shader ShaderSources shaderSources; + // Shader compiler warning strings for individual shader stages. + std::map shaderWarnings; + GLuint program; // volatile // Uniform location buffer map