Troubleshooting: The InfoLog
Prev: Setup Example | Next: Cleaning Up |
Debugging a shader is hard. There is no printf yet and probably never will be, although developer tools with debugging capability are to be expected in the future. It is true that you can use some tricks now but these are not trivial by any means. All is not lost and some functions are provided to check if your code compiled and linked successfully.
The status of the compile steps can be queried in OpenGL 2.0 with the following function:
void glGetShaderiv(GLuint object, GLenum type, int *param);
Parameters:
- object – the handler to the object. Either a shader or a program
- type – GL_COMPILE_STATUS.
- param – the return value, GL_TRUE if OK, GL_FALSE otherwise.
The status of the link step can be queried in OpenGL 2.0 with the following function:
void glGetProgramiv(GLuint object, GLenum type, int *param);
Parameters:
- object – the handler to the object. Either a shader or a program
- type – GL_LINK_STATUS.
- param – the return value, GL_TRUE if OK, GL_FALSE otherwise.
With ARB extensions a single function is used to check both the compile and link status (depending on a parameter):
void glGetObjectParameterivARB(GLhandleARB object, GLenum type, int *param);
Parameters:
- object – the handler to the object. Either a shader or a program
- type – GL_OBJECT_LINK_STATUS_ARB or GL_OBJECT_COMPILE_STATUS_ARB.
- param – the return value, 1 for OK, 0 for problems.
There are more options regarding the second parameter, type, however these won’t be explored in here.
When errors are reported it is possible to get further information with the InfoLog. This log stores information about the last operation performed, such as warnings and errors in the compilation, problems during the link step. The log can even tell you if your shaders will run in software, meaning your hardware does not support some feature you’re using, or hardware, the ideal situation. Unfortunately there is no specification for the InfoLog messages, so different drivers/hardware may produce different logs.
In order to get the InfoLog for a particular shader or program in OpenGL 2.0 use the following functions:
void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);
void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);
Parameters:
- object – the handler to the object. Either a shader or a program
- maxLen – The maximum number of chars to retrieve from the InfoLog.
- len – returns the actual length of the retrieved InfoLog.
- log – The log itself.
Again, using the ARB extensions, a single function is required to query both the shader and program info logs:
void glGetInfoLogARB(GLhandleARB object, int maxLen, int *len, char *log);
Parameters:
- object – the handler to the object. Either a shader or a program
- maxLen – The maximum number of chars to retrieve from the InfoLog.
- len – returns the actual length of the retrieved InfoLog.
- log – The log itself.
The GLSL specification could have been nicer in here. You must know the length of the InfoLog to retrieve it. To find this precious bit of information use the following functions (in OpenGL notation):
void glGetShaderiv(GLuint object, GLenum type, int *param);
void glGetProgramiv(GLuint object, GLenum type, int *param);
Parameters:
- object – the handler to the object. Either a shader or a program
- type – GL_INFO_LOG_LENGTH.
- param – the return value, the length of the InfoLog.
Once again the ARB syntax is simpler. Only one function is required:
void glGetObjectParameterivARB(GLhandleARB object, GLenum type, int *param);
Parameters:
- object – the handler to the object. Either a shader or a program
- type – GL_OBJECT_INFO_LOG_LENGTH_ARB.
- param – the return value, the length of the InfoLog.
The following functions can be used to print the contents of the infoLog in OpenGL 2.0:
void printShaderInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}
void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}
Using the ARB extension the process is the same for both shaders and programs:
void printInfoLog(GLhandleARB obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}
Prev: Setup Example | Next: Cleaning Up |