I'm attempting to retrieve the binary from a program that has been validly compiled and linked. I've received the length of it with GL_PROGRAM_BINARY_LENGTH. The documentation says there's two instances in which the GL_INVALID_OPERATION can occur - a failed link and bufSize being less than the size of the program. I've read that some have gotten this error when failing to give GL_PROGRAM_BINARY_RETRIEVABLE_HINT prior to linking, which is not the case for me. I've also validated the program, to be certain...and verified that GL_ARB_get_program_binary is supported.
We have a glDebugMessageCallbackARB hooked up, which gives this for some extra info: "GL_INVALID_OPERATION error generated. Object is not a program or shader object." I found nothing by searching for that extra bit in the error message.
OGL version 4.2, glsl 1.5. This is on an nVidia GeForce GTX 660 with latest drivers. Windows 7.
Here's the relevant code:
GLuint compileShaderBlock(GLenum type, const char* shaderCode, const int shaderSize)
{
GLuint shaderId = 0;
if (shaderCode != NULL)
{
shaderId= glCreateShader(type);
glShaderSource(shaderId, 1, &shaderCode, &shaderSize);
glCompileShader(shaderId);
}
return shaderId;
};
static GLchar errBuff[4096];
bool validateShader(GLuint shaderID)
{
GLint compiled;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compiled);
GLsizei length = 0;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length);
char* buffer = new char[length];
if (!compiled && length > 0)
{
GLsizei outputlen;
glGetShaderInfoLog(shaderID, length, &outputlen, buffer);
GLsizei size = 0;
glGetShaderSource(shaderID, 4096, &size, errBuff);
}
assert(compiled == GL_TRUE, "Shader compile error: \n%s", buffer);
delete[] buffer;
return compiled == GL_TRUE;
}
bool validateLink(GLuint programID)
{
GLint linkResult = GL_TRUE;
glGetProgramiv(programID, GL_LINK_STATUS, &linkResult);
if (linkResult == GL_FALSE)
{
GLsizei outputlen, length = 0;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &length);
char* buffer = new char[length];
glGetProgramInfoLog(programID, length, &outputlen, buffer);
assert(linkResult == GL_TRUE, "Program %d link error %s", programID, buffer);
delete[] buffer;
return GL_FALSE;
}
return GL_TRUE;
}
....
shader->vertexShaderId = compileShaderBlock(GL_VERTEX_SHADER, vsDataString.ToChar(), vsDataString.Length());
shader->fragmentShaderId = compileShaderBlock(GL_FRAGMENT_SHADER, fsDataString.ToChar(), fsDataString.Length());
validateShader(shader->vertexShaderId, "");
validateShader(shader->fragmentShaderId, "");
shader->programId = glCreateProgram();
glAttachShader(shader->programId, shader->vertexShaderId);
glAttachShader(shader->programId, shader->fragmentShaderId);
//Care about outputs
glBindFragDataLocation(shader->programId, 0, "outColor0");
glBindFragDataLocation(shader->programId, 1, "outColor1");
glBindFragDataLocation(shader->programId, 2, "outColor2");
glBindFragDataLocation(shader->programId, 3, "outColor3");
// let it know we plan on retrieving a binary
glProgramParameteri(shader->programId, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
glLinkProgram(shader->programId);
... set attributes and uniforms (removing this doesn't change anything)
... do mock render (removing this doesn't change anything)
validateLink(shader->programId);
glValidateProgram((shader->programID);
GLint validateStatus;
glGetProgramiv((shader->programID, GL_VALIDATE_STATUS, &validateStatus);
glUseProgram(shader->programId);
GLint len = 0;
glGetProgramiv(shader->programId, GL_PROGRAM_BINARY_LENGTH, &len);
if (len > 0)
{
uint8* binary = new uint8[len];
GLenum binaryFormat;
**ERROR** --> glGetProgramBinary(shader->programId, len, NULL, &binaryFormat, binary);
}
I feel like this doesn't make any sense, is there something I'm missing???