glGetUniformLocation() unwantedly returns -1

Hello,

I’m in a desperate situation, please help me.

The past two weeks I’ve had difficulty using uniform variables in my shader programs. The problem arises as the glGetUniformLocation() function call returns the value -1.
I’ve done plenty of research recently on the topic myself and I think I have the right function calls at the right places. I’m also aware that the glsl driver optimizes out certain variables that it sees not affecting the output of the program, but I do not understand why the heck it would do that in my case. The variables for I’m calling the glGetUniformLocation() are put in a good use calculating the result values in my shaders. What is even more incomprehensible to me is the haphazard results I get after I run my program. Same binary, different runtime results each time. It sometimes works perfectly as intended, sometimes it fails getting the uniform locations. I’ve extracted the problem to a simplified build and loaded it to a github repository. It can be found here https://github.com/Motonen/Uniform. Here is the vertex shader


#version 330 core
layout (location = 0) in vec4 vPosition;

uniform mat4 projMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;


void main()
{
    vec4 m = modelMatrix * vPosition;
    vec4 mv = viewMatrix * m;
    vec4 mvp = projMatrix * mv;
    gl_Position = mvp;
}

The glsl driver in this case shouldn’t optimize out any of those uniform matrices right? It does it nevertheless sometimes.

Enlighten me about my situation. Thank you guys in advance.

Nope.

It does it nevertheless sometimes.

Hmmm. Let’s see the code you’re using to compile your shader and link your program. Make sure that you’re checking for compile and link failures and printing out the compile and link error strings on failure. Also make sure you are actually adding your shader to your program.

Also, what GL driver is this? I can tell you on NVidia drivers, it doesn’t optimize these away (I tossed this in a small, stand-alone GLUT test program and verified that.)

[QUOTE=Dark Photon;1288561]Nope.

Hmmm. Let’s see the code you’re using to compile your shader and link your program. Make sure that you’re checking for compile and link failures and printing out the compile and link error strings on failure. Also make sure you are actually adding your shader to your program.

[/QUOTE]

 
#include "LoadShaders.h"

std::string readFile(const char *filename)
{
    std::ifstream inputFile(filename); 
    
    if(!inputFile)
        std::cerr << "Couldn't open file " << filename << '
';

    std::stringstream inputStream;
    inputStream << inputFile.rdbuf();
    inputFile.close();
    
    return inputStream.str();    
}

GLuint loadFromFile(const char *filename, int type)
{
    
    GLint status;
    GLchar infoLog[512];
    

    const GLchar *shaderCode = readFile(filename).c_str();
    GLuint shaderID = glCreateShader(type);
    glShaderSource(shaderID, 1, &shaderCode, NULL);
    glCompileShader(shaderID);

    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
    
    if(!status)
    {
        glGetShaderInfoLog(shaderID, 512, nullptr, infoLog);
        std::cerr << infoLog << "
" << filename << '
';
    }

    return shaderID;
}





GLuint loadShaders(const char *vertexFile, const char *fragmentFile)
{
    GLuint vertexID = loadFromFile(vertexFile, GL_VERTEX_SHADER);
    GLuint fragmentID = loadFromFile(fragmentFile, GL_FRAGMENT_SHADER);

    GLuint programID = glCreateProgram();
    glAttachShader(programID, vertexID);
    glAttachShader(programID, fragmentID);
    
    glLinkProgram(programID);
    glValidateProgram(programID);
    
    return programID;
}


Here is the code for loading the shaders, I don’t see anything wrong with it.

Those functions are being called in the main.




    GLuint program = loadShaders("vertexFile", "fragmentFile");
    GLint viewLoc, projLoc, modelLoc;
    
    const char *viewId = "viewMatrix";
    const char *projId = "projMatrix";
    const char *modelId = "modelMatrix";

    glUseProgram(program);

    viewLoc = glGetUniformLocation(program, viewId);    
    projLoc = glGetUniformLocation(program, projId);    
    modelLoc = glGetUniformLocation(program, modelId);    





    std::cout << glGetString(GL_VENDOR) << '
';
    std::cout << glGetString(GL_RENDERER) << '
';
    std::cout << glGetString(GL_VERSION) << '
';


This code provides the output:

Intel Inc.
Intel HD Graphics 5000 OpenGL Engine
4.1 INTEL-10.25.17

No errors reported after the link and validation of your shader and after the call of glGetUniformLocation ?

No, the error code is never provoked as I run the program. Only the uniform check I included there notifies me that it fails to get the uniform location for the matrix variables I have. This only happens sometimes.




bool verify(GLint loc, const char *name)
{
    if(loc < 0)
        return false;
    return true;
}

bool initShaders()
{
    GLuint program = loadShaders("vertexFile", "fragmentFile");
    GLuint viewLoc, projLoc, modelLoc;

    const char *viewId = "viewMatrix";
    const char *projId = "projMatrix";
    const char *modelId = "modelMatrix";

    glUseProgram(program);

    viewLoc = glGetUniformLocation(program, viewId);    
    projLoc = glGetUniformLocation(program, projId);    
    modelLoc = glGetUniformLocation(program, modelId);    
   
    bool result1 = verify(viewLoc, viewId);
    bool result2 = verify(projLoc, projId);
    bool result3 = verify(modelLoc, modelId);
    
    return (result1 && result2 && result3);
}


int main()
{
    GLuint vao, vbo;
    int vertexCount = 6; 
    Display display;
    int numTries = 0;
    int successes = 0;
    while(1)
    {
        numTries++;
        bool result = initShaders();
        if(result)
            successes++;
        std::cout << "\rTries: " << numTries << "Successes: " << successes << std::flush;

    }   
} 

I wrote this code snippet to see what is the success/failure rate of the initialization of the shader program.
As I ran the program a few times, it seems that the failure rate is about 9%. So with this build opengl fails 9% of the time to initialize the shaders. 91 % of the time it works smoothly. For other implementations of mine where there are even more uniform variables, I get much worse success/failure ratio.
I’m completely lost.

So you mean you are calling glGetError, and you never face any OpenGL errors ?

And in case it can help other people:
It seems the OP is on Mac.
He requests a forward compatible OpenGL 3.3 context.
And he actually sets all the uniform variables to some values just right after he asks for their locations.

Ah, I hadn’t included the glGetError. I called the function and it returned OpenGL error: 1282, GL_INVALID_OPERATION.
I get GL_INVALID_OPERATION because I’m calling the getUniformLocation with a uniform variable name that doesn’t exist in the shader program, even though it actually does. The variable name gets optimized out 9 % of the time.
Yeah, I’m using mac and I’m calling the necessary compatibility functions in the constructor of Display.

No, I’m just asking the locations.

[QUOTE=Motonen;1288574]Ah, I hadn’t included the glGetError. I called the function and it returned OpenGL error: 1282, GL_INVALID_OPERATION.
I get GL_INVALID_ERROR because I’m calling the getUniformLocation with a uniform variable name that doesn’t exist in the shader program, even though it actually does. The variable name gets optimized out 9 % of the time.
Yeah, I’m using mac and I’m calling the necessary compatibility functions in the constructor of Display.[/QUOTE]

Please, refer to this. It just says whether your program is not a program or it did not linked correctly.
Please, check the OpenGL errors (with glGetError) when compiling and linking your shader.

[QUOTE=Motonen;1288574]
No, I’m just asking the locations.[/QUOTE]

You do:

From https://github.com/Motonen/Uniform/blob/master/src/main.cpp, line 54:


glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(m));  
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(m));  
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(m)); 

Alright so I was wrong about the glGetError. The GL_INVALID_OPERATION comes from a failure to compile/link the shaders most likely.
I called the glGetError in the midst of the compilation process and I received sometimes the flag GL_INVALID_OPERATION. Most of the time it worked fine.
I think the root of the problem lies on the loadShaders function.

Thank you Silence.

However, I still haven’t figured out why the loadShaders function produces such randomness.

Alright guys, I think I’ve solved the problem. In the end, the problem was not fault of opengl. It was just my sloppy string conversion in the loadShader function that created the randomness.
The readFile function reads the input to stringstream and returns a string inputStream.str(). In the loadFromFile function the shader code was received like this: const GLchar *shaderCode = readFile(filename).c_str(); This line is the root of the problem. It depends on luck how it gets the data into GLchar *shaderCode. This additional line fixes the problem:


std::string temp = readFile(filename);
GLchar *shaderCode = temp.c_str();

I’m grateful for Silence for pointing me to the right direction, thank you.