Browse Source

Improved shader:getWarnings() to return shader compiler warnings as well as shader program linker and usage warnings

Alex Szpakowski 12 years ago
parent
commit
cfe6014b68
2 changed files with 46 additions and 19 deletions
  1. 40 19
      src/modules/graphics/opengl/Shader.cpp
  2. 6 0
      src/modules/graphics/opengl/Shader.h

+ 40 - 19
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);
 
-	GLint status;
-	glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
+	// Get any warnings the shader compiler may have produced
+	GLint infologlen;
+	glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
 
-	if (status == GL_FALSE)
-	{
-		GLint infologlen;
-		glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
+	GLchar *infolog = new GLchar[infologlen + 1];
+	glGetShaderInfoLog(shaderid, infologlen, NULL, infolog);
 
-		GLchar *errorlog = new GLchar[infologlen + 1];
-		glGetShaderInfoLog(shaderid, infologlen, NULL, errorlog);
+	// Save any warnings for later querying
+	if (infologlen > 0)
+		shaderWarnings[type] = shadertypestr + std::string(" shader:\n") + infolog;
 
-		std::string tmp(errorlog);
+	delete[] infolog;
 
-		delete[] errorlog;
-		glDeleteShader(shaderid);
+	GLint status;
+	glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
 
-		throw love::Exception("Cannot compile %s shader code:\n%s", shadertypename, tmp.c_str());
+	if (status == GL_FALSE)
+	{
+		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<GLuint> &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<ShaderType, std::string>::const_iterator it;
+	for (it = shaderWarnings.begin(); it != shaderWarnings.end(); ++it)
+		warnings += it->second;
+
+	warnings += getProgramWarnings();
+
 	return warnings;
 }
 

+ 6 - 0
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<ShaderType, std::string> shaderWarnings;
+
 	GLuint program; // volatile
 
 	// Uniform location buffer map