0
\$\begingroup\$

I am currently trying to write a basic program using OpenGL 3.3, and I am encountering an issue: glGetProgramInfoLog is returning an empty string while glGetProgramiv is saying that there is an error when linking my shader program.

The problematic code follows:

//load shaders
GLuint vertexShader = loadShader("shader.vert", GL_VERTEX_SHADER);
GLuint fragmentShader = loadShader("shader.frag", GL_FRAGMENT_SHADER);

//link program
programId = glCreateProgram();
glAttachShader(programId, vertexShader);
glAttachShader(programId, fragmentShader);
glLinkProgram(programId);

//check for errors
GLint success = 5; //for debugging to make sure it wasn't 0 by default and glGetProgramiv wasn't writing to it
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if(!success){
    GLchar infoLog[1024];
    glGetProgramInfoLog(programId, 1024, nullptr, infoLog);
    throw std::runtime_error(std::string("Failed to link OpenGl shader program material: ") + infoLog);
}

//delete shaders
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

When I attempt to run my program, the runtime_error is thrown with the following termination message:

terminate called after throwing an instance of 'std::runtime_error'
  what():  Failed to link OpenGl shader program material: 

I confirmed through my debugger that the success variable is bring written to (see comment in code), and that glGetProgramInfoLog is writing the first byte of infoLog to all zeroes, thus making it a null-terminated string of length 0.

What am I doing incorrectly here?

Information:
GPU: Nvidia GTX 1070
OS: Ubuntu Linux 17.10 x64
Display server: Xorg
Driver version: 384.111 (latest in official Ubuntu repositories)
Compiler: g++ (Ubuntu 7.2.0-8ubuntu3) 7.2.0
Kernel Version: 4.13.0-25-generic
Windowing Library: SFML version 2.4.2+dfsg-4 (as described here) (version from apt-cache policy command)

Things I have tried:

  • Modifying error checking code to check GL_INFO_LOG_LENGTH, which returns 0 despite GL_LINK_STATUS returning GL_FALSE (also 0.
  • Compiling the program and testing on Windows 10 running on the same hardware, since I don't have access to any sufficiently different gpu for better testing, in an attempt to rule out a driver error that may only exist on Linux. The same thing happens on Windows.

I have also posted this question to reddit, where no useful answers came up (link).

Full program source:

#include <SFML/Window.hpp>
#include <GL/glew.h>
#include <fstream>
#include <sstream>
#include <iostream>

void init();
void update();

GLuint loadShader(const std::string &shaderPath, GLenum shaderType);

sf::Window window;
GLuint programId;
GLuint vbo, vao, ebo;

int main(){
    init();
    while(true){
        update();
    }
}

void init(){
    sf::ContextSettings settings;
    settings.antialiasingLevel = 0;
    settings.majorVersion = 3;
    settings.minorVersion = 3;

    window.create(sf::VideoMode(1600, 900), "PerlinGl", sf::Style::Default, settings);
    window.setActive(true);

    if(glewInit() != GLEW_OK){
        throw std::runtime_error("Failed to initialize GLEW.");
    }

    //load shaders
    GLuint vertexShader = loadShader("shader.vert", GL_VERTEX_SHADER);
    GLuint fragmentShader = loadShader("shader.frag", GL_FRAGMENT_SHADER);

    //link program
    programId = glCreateProgram();
    glAttachShader(programId, vertexShader);
    glAttachShader(programId, fragmentShader);
    glLinkProgram(programId);

    //check for errors
    GLint success = 5;
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if(!success){
        GLchar infoLog[1024];
        glGetProgramInfoLog(programId, 1024, nullptr, infoLog);
        throw std::runtime_error(std::string("Failed to link OpenGl shader program material: ") + infoLog);
    }

    //delete shaders
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //setup "mesh"
    GLfloat vertices[] = {
            -1.0f, -1.0f, 0.0f,
            1.0f, -1.0f, 0.0f,
            1.0f, 1.0f, 0.0f,
            -1.0f, 1.0f, 0.0f
    };
    GLuint indices[] = {
            0, 1, 2,
            2, 3, 0
    };

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glGenBuffers(1, &ebo);

    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), reinterpret_cast<void*>(0));
    glEnableVertexAttribArray(0);
}

void update(){
    sf::Event event;
    while(window.pollEvent(event)){
        switch(event.type){
            case sf::Event::Closed:
                std::terminate();
                break;
        }
    }

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    window.display();
}

GLuint loadShader(const std::string &shaderPath, GLenum shaderType){
    //load source
    std::ifstream fin(shaderPath);
    std::ostringstream sout;

    while(fin){
        std::string line;
        std::getline(fin, line);
        sout << line << std::endl;
    }

    std::string shaderSource = sout.str();
    const char *shaderSourceCString = shaderSource.c_str();

    std::cout << "Shader source: " << shaderSource << std::endl;

    //create shader
    GLuint shader = glCreateShader(shaderType);
    glShaderSource(shader, 1, &shaderSourceCString, nullptr);
    glCompileShader(shader);

    //test for errors
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if(!success){
        GLchar infoLog[1024];
        glGetShaderInfoLog(shader, 1024, nullptr, infoLog);
        throw std::runtime_error("Failed to compile OpenGl shader (" + shaderPath + "): " + infoLog);
    }
}
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I managed to find the error (I should have turned on compiler warnings. that would have saved a lot of trouble). It turned out I was missing a return statement in my loadShader function. I finally found it by comparing line-by-line to a working piece of code on the Internet.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .