8
votes

I must admit this is my first time implementing shaders, previously I have only worked with fixed function pipeline; however, though I am certain that everything I did is correct - there must be an error.

glLinkProgram(program) - returns GL_FALSE when queried for GL_LINK_STATUS. In addition, the info log is empty (when I query the log length - it is 1, which is the null terminator per the docs, it checks out). So linker errors, and no logs. In addition, I had just discovered that the linker problems occur as soon as I make any use of gl_Position variable in vertex shader, both during assignment and if I use it for calculations. I tried all sorts of shader variations, it errors but it fails to produce the logs - it just seems to return GL_FALSE any time gl_Position is touched. Interestingly enough, fragment shader doesn't cause any problems.

Both fragment and vertex shaders compile fine with no errors. When I introduce syntax errors, they are detected, printed, and the process is aborted prior to program creation (so it seems to work fine). I debugged and made sure that files get loaded properly, source is null terminated, sizes are correct, I checked the number of attached programs after attachment and it is 2 (correct lol). It is removed for clarity, I have the checkForErrors() method that checks and prints opengl errors - none are detected.

I am stumped, please someone help! I've been losing sleep over this for 2 days now...

This is the code to load the shader:

FILE *file = fopen(fileName.c_str(), "rb");

if(file == NULL)
{
    Log::error("file does not exist: \"" + fileName + "\"");
    return NULL;
}

// Calculate file size
fseek(file , 0 , SEEK_END);
int size = ftell(file);
rewind(file);

// If file size is 0
if(size == 0)
{
    Log::error("file is empty: \"" + fileName + "\"");
    return NULL;
}

char **source = new char*[1];
source[0] = new char[size+1];
source[0][size] = '\0';

// If we weren't able to read the entire file into memory
int readSize = fread(source[0], sizeof(char), size, file);
if(size != readSize)
{
    int fileError = ferror(file);

    // Free the source, log an error and return false
    delete source[0];
    delete [] source;
    fclose(file);
    Log::error("couldn't load file into memory [ferror(" + toString<int>(fileError) + ")]: \"" + fileName + "\" (Size: " + toString<int>(readSize) + "/" + toString<int>(size) + " bytes)");
    return NULL;
}

// Close the file
fclose(file);




// Create the shader object


// shaderType is GLenum that is set based on the file extension. I assure you it is correctly set to either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
GLuint shaderID = glCreateShader(shaderType);

// If we could not create the shader object, check for OpenGL errors and return false
if(shaderID == 0)
{
    checkForErrors();
    Log::error("error creating shader \"" + name);
    delete source[0];
    delete [] source;
    return NULL;
}

// Load shader source and compile it
glShaderSource(shaderID, 1, (const GLchar**)source, NULL);
glCompileShader(shaderID);

GLint success;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
if(!success)
{
    GLchar error[1024];
    glGetShaderInfoLog(shaderID, 1024, NULL, error);
    Log::error("error compiling shader \"" + name + "\"\n    Log:\n" + error);
    delete source[0];
    delete [] source;
    return NULL;
}
else
{
    Log::debug("success! Loaded shader \"" + name + "\"");
}

// Clean up
delete source[0];
delete [] source;

Quick note: glShaderSource - I cast to (const GLchar**) because GCC complains about const to non-const char pointers; Otherwise, I believe I'm entirely compliant.

No errors there, by the way. The shaders (below) compile without any errors.

Vertex Shader:

void main()
{
    // If I comment the line below, the link status is GL_TRUE.
    gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
}

Fragment Shader:

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Below is the code that creates the shader program, attaches objects and links etc.:

// Create a new shader program
GLuint program = glCreateProgram();
if(program == 0)
{
    Log::error("RenderSystem::loadShaderProgram() - could not create OpenGL shader program; This one is fatal, sorry.");
    getContext()->fatalErrorIn("RenderSystem::loadShaderProgram(shader1, shader2)", "OpenGL failed to create object using glCreateProgram()");
    return NULL;
}

// Attach shader objects to program
glAttachShader(program, vertexShaderID);
glAttachShader(program, fragmentShaderID);

// Link the program
GLint success = GL_FALSE;
glLinkProgram(program);
checkForErrors();
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(success == GL_FALSE)
{
    GLchar errorLog[1024] = {0};
    glGetProgramInfoLog(program, 1024, NULL, errorLog);
    Log::error(std::string() + "error linking program: " + errorLog);
    return NULL;
}

success = GL_FALSE;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &success);
if(success == GL_FALSE)
{
    GLchar errorLog[1024] = {0};
    glGetProgramInfoLog(program, 1024, NULL, errorLog);
    checkForErrors();
    Log::error(std::string() + "error validating shader program; Details: " + errorLog);
    return NULL;
}

Usually it doesn't even get as far as validating the program... I'm so frustrated with this, it's very hard not to be vulgar.

Your help is needed and any assistance is genuinely appreciated!

EDIT: I'm running everything on Intel HD 3000 (with support for OpenGL up to 3.1). My target OpenGL version is 2.0.

EDIT2: I would also like to note that I had some issues with reading the shaders from text files if I set the "r" or "rt" flags in fopen - the read size was smaller than actual size by about 10 bytes (consistently on all files) - and feof() would return true. When I switched to reading in binary ("rb") the problem went away and files were read in fully. I did try several alternative implementations and they all produced the same error during linking (and I print shader source to console right after reading the file to ensure it looks correct, it does.).

1
Where is your #version declaration in your shader?Nicol Bolas
I didn't include one... could that be it? I will google it, but if I may - what would be an appropriate shader version for OpenGL 2.0 target?Kaa
I tried using #version 150, #version 140, and #version 130 in three separate tests (same version for both shaders), and the results are the same - link status returns GL_FALSE, and no info log :(Kaa
You had me up until the driver settings. Wish my problem was the same thing, I even have intel graphics.Josh C

1 Answers

15
votes

OK, I knew when I was posting that this was going to be embarrassing, but it is quite bad: the Intel graphics config application that usually accompanies an Intel driver has 3D settings tab; Now, the "custom settings" check box was unchecked, but the grayed out option under the setting "Vertex Processing" spelled out "Enable Software Processing". Even though it was unchecked and everything was grayed out I simply entered the custom settings and checked everything to "Application Settings".

That fixed it! Everything links like it should! Don't know who thought of that option, why would that ever be useful?! Its the only option that looks stunningly out of place.

I went through several driver re-installs, intense debugging and configuration research, I had to speculate and second guess on absolutely everything! Terrible, wouldn't wish it on my worst enemies.