Search code examples
c++glslglfwcompute-shader

GLSL Error : Undefined layout buffer variable in compute shader, though it is defined


I'm trying to make a simple compute shader using a Shader Storage Buffer (SSBO) to pass data to the shader. I'm coding in C++ with GLFW3 and GLEW. I'm passing an array of integers into an SSBO, binding it to the index 0, and expecting to retrieve the data in the shader from a layout buffer variable (as explained on various websites). However, I get an unexpected "undefined variable" error on shader compilation concerning this layout buffer variable, though it is clearly declared. Here is the GLSL code of the compute shader (this script is only at its beginning) :

#version 430

layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

layout (std430, binding = 0) buffer params
{
    ivec3 dims;
};


int index(ivec3 coords){
    ivec3 dims = params.dims;
    return coords.x + dims.y * coords.y + dims.x * dims.y * coords.z;
}

void main() {
    ivec3 coords = ivec3(gl_GlobalInvocationID);

    int i = index(coords);
}

I get the error : 0(12) : error C1503: undefined variable "params"

Here is the C++ script that setups and runs the compute shader :

int dimensions[] {width, height, depth};

GLuint paramSSBO;
glGenBuffers(1, &paramSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, paramSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(dimensions), &dimensions, GL_STREAM_READ);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, paramSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

GLuint computeShaderID;
GLuint csProgramID;

char* computeSource;

loadShaderSource(computeSource, "compute.glsl");
computeShaderID = glCreateShader(GL_COMPUTE_SHADER);
compileShader(computeShaderID, computeSource);

delete[] computeSource;

csProgramID = glCreateProgram();
glAttachShader(csProgramID, computeShaderID);
glLinkProgram(csProgramID);
glDeleteShader(computeShaderID);

glUseProgram(csProgramID);
glDispatchCompute(width, height, depth);
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
glUseProgram(0);

glDeleteBuffers(1, &paramSSBO);

width, height and depth are int variables defined earlier in the program. I'm binding the dimensions array to the index 0 and I expect to retrieve it in the ivec3 params.dims variable in the shader. However the params variable is said to be undefined when used in the index() function.

This script is just the beginning and I wanted to add a second buffer where the shader would actually write its result, but I'm stuck here. For clarification : in the complete script I expect not to write in any texture (as all online examples show), but write the results in the second buffer from which I will get the data back into a C++ array for further use.


Solution

  • params is not a variable. Nor is it a struct or class. It is the name of an interface block. And the name of an interface block is not really part of GLSL itself; it's part of OpenGL. It's the name used by the OpenGL API to represent that particular block.

    You never use an interface block's name in the shader text itself, outside of defining it.

    Unless you give your interface block an instance name, the names of all variables within that block are essentially part of the global namespace. Indeed, scoping those names is the whole point of giving the block an instance name.

    So the correct way to access the dims field in the interfae block is as "dims".