Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: (SFML + OpenGL) GL_INVALID_OPERATION on glLinkProgram  (Read 4070 times)

0 Members and 1 Guest are viewing this topic.

lolz123

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
(SFML + OpenGL) GL_INVALID_OPERATION on glLinkProgram
« on: May 01, 2014, 07:53:45 pm »
Hello,

I am having some difficulties resolving a OpenGL related error. I am posting on these forums since I never had these issues with SDL, but with SFML I do, so it might be related to SFML.

Basically, I made a custom shader loader (the same one I used to use with SDL), but glLinkProgram generates GL_INVALID_VALUE.

The specs say:

Quote
GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.

for glLinkProgram.

This would seem to indicate that the program handle I passed it is bogus. But, I generated the ID a mere 8 lines before that, and it is non-zero.

Loading the shader is first thing my application does after opening a window and calling glewInit.

This error does not affect the program for my machine, it runs fine, but it doesn't work on others. It runs on mine (ATI) but not on that of my friend (NVidia). However, my machine does still throw the error, but it only shows itself when I am running it through gDEBugger.

I also noticed through gDEBugger that SFML is creating 3 OpenGL contexts for some reason.

Anybody have any ideas as to what may be going on?
Have you heard about the new Cray super computer?  It’s so fast, it executes an infinite loop in 6 seconds.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: (SFML + OpenGL) GL_INVALID_OPERATION on glLinkProgram
« Reply #1 on: May 01, 2014, 08:06:06 pm »
Yes... SFML creates 3 contexts even if you only have a single window. This is an internal detail. Might change in the future.

Can you show the lines around where the window is created and where the shader is loaded? What exactly do you do between them? Do you use multiple threads? Do you use any of the SFML API between those sections?

We need more information. There are so many things that might go wrong, and the easiest way to rule things out is by seeing some concrete code.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

lolz123

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
Re: (SFML + OpenGL) GL_INVALID_OPERATION on glLinkProgram
« Reply #2 on: May 01, 2014, 08:16:52 pm »
Thanks for the reply.

I am working on a complete minimal example that displays the problem, but this will take some time. Until then, here is the code surrounding the glLingProgram call:

bool Shader::createAsset(const std::string &name) {
        // Name contains vertex shader file name and the fragment shader file name, so extract those
        std::istringstream is(name);

        std::string geomName, fragName, vertName;
        is >> geomName >> vertName >> fragName;

        // Load the shaders
        if(geomName != "NONE")
                if(!loadGeometryShader(geomName, _geomID)) {
                        std::cerr << "Could not load geometry shader!" << std::endl;
                        return false;
                }

        if(vertName != "NONE")
                if(!loadVertexShader(vertName, _vertID)) {
                        std::cerr << "Could not load vertex shader!" << std::endl;
                        return false;
                }

        if(fragName != "NONE")
                if(!loadFragmentShader(fragName, _fragID)) {
                        std::cerr << "Could not load fragment shader!" << std::endl;
                        return false;
                }

        // Create the main shader
        _progID = glCreateProgram();

        // Attach the shader components (vertex and fragment) to the program
        if(_geomID != 0)
                glAttachShader(_progID, _geomID);

        if(_vertID != 0)
                glAttachShader(_progID, _vertID);

        if(_fragID != 0)
                glAttachShader(_progID, _fragID);

        if(!link(_progID)) {
                std::cerr << "- in " << name << std::endl;

                return false;
        }

        D3D_GL_ERROR_CHECK();

        return true;
}
 

the load___shader calls just load and compile a shader, it works fine.

Shader::link looks like this:

bool Shader::link(GLuint id) {
        glLinkProgram(id);

        int result;

        // Check if linking was successful
        glGetProgramiv(id, GL_LINK_STATUS, &result);

        if(result == GL_FALSE) {
                // Not validated, print out the log
                int logLength;

                glGetProgramiv(id, GL_INFO_LOG_LENGTH, &logLength);

                if(logLength <= 0) {
                        std::cerr << "Unable to link program: Error: Invalid log length \"" << logLength << "\": Could not retrieve error log!" << std::endl;

                        return false;
                }

                // Allocate the string
                std::string log;

                log.resize(logLength);

                glGetProgramInfoLog(id, logLength, &result, &log[0]);

                std::cerr << "Unable to link program: " << log << std::endl;

                return false;
        }

        D3D_GL_ERROR_CHECK();

        return true;
}
 

It crashes on the glLinkProgram.

The main looks like this:

int main() {
        std::ofstream out("out.txt");
        std::cout.rdbuf(out.rdbuf());

        std::ofstream err("err.txt");
        std::cerr.rdbuf(err.rdbuf());

        sf::RenderWindow window;
        sf::ContextSettings settings;

        settings.majorVersion = 4;
        settings.minorVersion = 3;
        settings.stencilBits = 0;
        settings.antialiasingLevel = 0;

        window.create(sf::VideoMode(1280, 720), "d3d", sf::Style::Default, settings);

        window.setVerticalSyncEnabled(true);
        window.setFramerateLimit(60);

        GLenum error = glewInit();

        assert(error == GLEW_NO_ERROR);

        // -------------------------------- OpenGL Setup --------------------------------

        d3d::sfmloglSetup();

        glViewport(0, 0, window.getSize().x, window.getSize().y);

        d3d::checkForGLError();

        // -------------------------------- Scene Setup --------------------------------

        std::unique_ptr<d3d::RenderScene> scene(new d3d::RenderScene());

        {
                std::shared_ptr<d3d::Shader> gBufferRender(new d3d::Shader());
                std::shared_ptr<d3d::Shader> gBufferRenderNormal(new d3d::Shader());
                std::shared_ptr<d3d::Shader> gBufferRenderHeightNormal(new d3d::Shader());
                std::shared_ptr<d3d::Texture2D> whiteTexture(new d3d::Texture2D());

                gBufferRender->createAsset("NONE resources/shaders/gbufferrender/gBufferRender.vert resources/shaders/gbufferrender/gBufferRender.frag");
                gBufferRenderNormal->createAsset("NONE resources/shaders/gbufferrender/gBufferRenderBump.vert resources/shaders/gbufferrender/gBufferRenderBump.frag");
                gBufferRenderHeightNormal->createAsset("NONE resources/shaders/gbufferrender/gBufferRenderParallax.vert resources/shaders/gbufferrender/gBufferRenderParallax.frag");
                whiteTexture->createAsset("resources/shaders/white.png");

                scene->createRenderScene(8, d3d::AABB3D(d3d::Vec3f(-1.0f, -1.0f, -1.0f), d3d::Vec3f(1.0f, 1.0f, 1.0f)), &window,
                        gBufferRender, gBufferRenderNormal, gBufferRenderHeightNormal, whiteTexture);

                scene->_logicCamera._projectionMatrix = d3d::Matrix4x4f::perspectiveMatrix(d3d::_piOver4, static_cast<float>(window.getSize().x) / static_cast<float>(window.getSize().y), 0.1f, 10000.0f);
                scene->_logicCamera._position = d3d::Vec3f(1.5f, 1.5f, 1.5f);
                scene->_logicCamera._rotation = d3d::Quaternion::getFromMatrix(d3d::Matrix4x4f::cameraDirectionMatrix(-scene->_logicCamera._position.normalized(), d3d::Vec3f(0.0f, 1.0f, 0.0f)));
        }
 

the crash occurs when trying to load the first shader.

sfmloglSetup just sets some GL states like so:

void d3d::sfmloglSetup() {
        glGenVertexArrays(1, &_vaoID);
        glBindVertexArray(_vaoID);

        glEnableVertexAttribArray(D3D_ATTRIB_POSITION);
        glEnableVertexAttribArray(D3D_ATTRIB_NORMAL);
        glEnableVertexAttribArray(D3D_ATTRIB_TEXCOORD);

        glFrontFace(GL_CCW);

        glEnable(GL_CULL_FACE);

        glClearDepth(1.0f);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        glDepthFunc(GL_LESS);
        glEnable(GL_DEPTH_TEST);
}
 
Have you heard about the new Cray super computer?  It’s so fast, it executes an infinite loop in 6 seconds.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: (SFML + OpenGL) GL_INVALID_OPERATION on glLinkProgram
« Reply #3 on: May 01, 2014, 08:49:24 pm »
Hmm... according to your code, there isn't much that can be going wrong. Since shaders should be shareable between contexts, there shouldn't be an issue of not being able to access the shader ID because of a context switch between those calls. You could always break in gDEBugger and see in which context the OpenGL calls are being executed. If you notice any strange context juggling going on, that can probably be a cause for the GL_INVALID_VALUE. I wouldn't rule out false positives either, gDEBugger is already quite old, and since you are using AMD hardware, I would recommend switching to CodeXL. It is what came out of gDEBugger when AMD bought it off.

You might also want to try using an sf::Window instead of sf::RenderWindow. The former is meant for pure OpenGL rendering, which is the case here, and thus has less overhead than the latter.

You can also try creating an explicit context that you create and leave active throughout your program so you have more control over which context is activated instead of relying on SFML context management automatically choosing one for you.

Other than that, I guess the only thing you can do is strip away bits of code until the problem disappears and try to figure out which lines might be causing it.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).