Persistent linking error with compute shaders in openGL

Compute Shader Linking Issue in OpenGL

Hi there!

I have been struggling recently with getting a compute shader program to properly link in C++ with OpenGL. I will show a stripped-back version of my code below, and if anyone can offer advice, that would be great.

I have checked that I have a version of OpenGL and GLSL that should be working (4.6.0). I also have a class that creates a shader program from a vertex and fragment shader, which has almost identical code but just for two source files instead of one—this class works entirely as intended.

When I run the code, I have also checked that compilation is happening correctly. The only thing I’m getting is the following output from my compileErrors() method.

Code Snippet

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "computeShader.h"

const GLuint width = 800;
const GLuint height = 800;

using namespace std;

float testArray1[100];
float testArray2[200];
float result[100];

int main() {
    if (!glfwInit()) {
        cout << "Failed to initialise GLFW" << endl;
        return -1;
    }
    GLFWwindow* window = glfwCreateWindow(800, 800, "window", NULL, NULL);
    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK) {
        cout << "Failed to initialise GLEW" << endl;
        glfwTerminate();
        return -1;
    }

    computeShader comp("compShader.comp"); 

    glfwTerminate();
    return 0;
}

## Code Snippet

```cpp
#ifndef COMPUTESHADER_H
#define COMPUTESHADER_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cerrno>
#include <vector>

class computeShader {
public:
    // Shader program ID
    GLuint ID;

    // Constructor that builds the Compute Shader Program from source code
    computeShader(const char* filename);

    // Activates the Compute Shader Program
    void Activate();

    // Deletes the Compute Shader Program
    void Delete();

private:
    // Checks if the Compute Shader has compiled properly
    void compileErrors(unsigned int shader, const char* type);
};

#endif

## Code Snippet

```cpp
#include "computeShader.h"

// Constructor that builds the Compute Shader Program from a file
computeShader::computeShader(const char* filename) {
    // Load shader source code from file
    std::string sourceCode;
    std::ifstream in(filename, std::ios::binary);
    if (in) {
        in.seekg(0, std::ios::end);
        sourceCode.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&sourceCode[0], sourceCode.size());
        in.close();
    }
    else {
        std::cerr << "Error: Could not open file " << filename << std::endl;
        throw std::runtime_error("Failed to load compute shader source code.");
    }
    const char* source = sourceCode.c_str();

    cout << source << endl;

    // Create shader object
    GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);

    // Attach source code to shader object
    glShaderSource(computeShader, 1, &source, nullptr);

    // Compile the shader
    glCompileShader(computeShader);

    // Check for compilation errors
    compileErrors(computeShader, "COMPUTE");

    // Create shader program and link shader
    ID = glCreateProgram();
    glAttachShader(ID, computeShader);
    glLinkProgram(ID);

    // Check for linking errors
    compileErrors(ID, "PROGRAM");

    // Delete the now unnecessary compute shader object
    glDeleteShader(computeShader);
}

// Checks if the shader or program has compiled/linked properly
void computeShader::compileErrors(unsigned int shader, const char* type) {
    GLint hasCompiled;
    GLint hasLinked;
    char infoLog[1024];

    if (type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &hasCompiled);
        if (hasCompiled == GL_FALSE) {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            std::cout << "SHADER_COMPILATION_ERROR for: " << type << "\n" << infoLog << std::endl;
        }
    }
    else {
        glGetProgramiv(shader, GL_LINK_STATUS, &hasLinked);
        if (hasLinked == GL_FALSE) {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            std::cout << "SHADER_LINKING_ERROR for: " << type << "\n" << infoLog << std::endl;
        }
    }
}

This is unreliable, as it’s comparing pointers rather than values. It only works if the compiler/linker take steps to ensure that string literals are unique. Either convert both to std::string, or use strcmp.

Apart from that, nothing stands out.

Also: you might want to display the logs regardless of status; sometimes the log contains useful information even when compilation and linking succeed.