Ошибка GLSL: неопределенная переменная буфера макета в вычислительном шейдере, хотя она определена - PullRequest
3 голосов
/ 03 августа 2020

Я пытаюсь создать простой вычислительный шейдер с использованием буфера хранения шейдеров (SSBO) для передачи данных в шейдер. Я кодирую на C ++ с GLFW3 и GLEW. Я передаю массив целых чисел в SSBO, привязываю его к индексу 0 и ожидаю получить данные в шейдере из переменной layout buffer (как описано на различных веб-сайтах). Однако я получаю неожиданную ошибку «неопределенная переменная» при компиляции шейдера в отношении этой переменной буфера макета, хотя она явно объявлена. Вот GLSL-код вычислительного шейдера (этот скрипт находится только в начале):

#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);
}

Я получаю сообщение об ошибке: 0(12) : error C1503: undefined variable "params"

Вот сценарий C ++, который настраивает и запускает вычислительный шейдер:

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 и depth - это int переменные, определенные ранее в программе. Я привязываю массив dimensions к индексу 0 и ожидаю получить его в переменной ivec3 params.dims в шейдере. Однако переменная params считается неопределенной при использовании в функции index().

Этот сценарий - только начало, и я хотел добавить второй буфер, в который шейдер будет записывать свой результат, но Я застрял здесь. Для пояснения: в полном сценарии я ожидаю не писать в какой-либо текстуре (как показывают все онлайн-примеры), а записывать результаты во второй буфер, из которого я получу данные обратно в массив C ++ для дальнейшего использования.

1 Ответ

3 голосов
/ 03 августа 2020

params не является переменной. И это не структура или класс. Это имя интерфейсного блока . И имя интерфейсного блока на самом деле не является частью самого GLSL; это часть OpenGL . Это имя, используемое OpenGL API для представления этого конкретного блока.

Вы никогда не используете имя интерфейсного блока в самом тексте шейдера, помимо его определения.

Если вы не дадите своему интерфейсному блоку имя экземпляра, имена всех переменных в этом блоке по существу являются частью глобального пространства имен. Действительно, определение области видимости этих имен - это весь смысл присвоения блоку имени экземпляра.

Таким образом, правильный способ доступа к полю dims в блоке interfae - это «dims».

...