GLSL Error : Undefined layout buffer variable in compute shader, though it is defined
GLSL Error : Undefined layout buffer variable in compute shader, though it is defined
我正在尝试制作一个简单的计算着色器,使用着色器存储缓冲区 (SSBO) 将数据传递给着色器。我正在使用 GLFW3 和 GLEW 使用 C++ 进行编码。我将整数数组传递给 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, ¶mSSBO);
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, ¶mSSBO);
width
、height
和 depth
是程序前面定义的 int
变量。我将 dimensions
数组绑定到索引 0,我希望在着色器的 ivec3
params.dims
变量中检索它。然而,params
变量在 index()
函数中使用时被认为是未定义的。
这个脚本只是开始,我想添加第二个缓冲区,着色器将实际写入其结果,但我被困在这里。澄清一下:在完整的脚本中,我希望不要写任何纹理(如所有在线示例所示),而是将结果写在第二个缓冲区中,我将从中将数据返回到 C++ 数组中以供进一步使用。
params
不是变量。它也不是结构或 class。就是name of an interface block。接口块的名称实际上并不是 GLSL 本身的一部分;它是 OpenGL 的一部分。这是 OpenGL API 用来表示特定块的名称。
你从不在着色器文本本身中使用接口块的名称,而不是定义它。
除非您为接口块指定一个实例名称,否则该块中所有变量的名称本质上都是全局命名空间的一部分。实际上,限定这些名称的范围是为块提供实例名称的全部意义。
因此访问接口块中 dims
字段的正确方法是“dims
”。
我正在尝试制作一个简单的计算着色器,使用着色器存储缓冲区 (SSBO) 将数据传递给着色器。我正在使用 GLFW3 和 GLEW 使用 C++ 进行编码。我将整数数组传递给 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, ¶mSSBO);
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, ¶mSSBO);
width
、height
和 depth
是程序前面定义的 int
变量。我将 dimensions
数组绑定到索引 0,我希望在着色器的 ivec3
params.dims
变量中检索它。然而,params
变量在 index()
函数中使用时被认为是未定义的。
这个脚本只是开始,我想添加第二个缓冲区,着色器将实际写入其结果,但我被困在这里。澄清一下:在完整的脚本中,我希望不要写任何纹理(如所有在线示例所示),而是将结果写在第二个缓冲区中,我将从中将数据返回到 C++ 数组中以供进一步使用。
params
不是变量。它也不是结构或 class。就是name of an interface block。接口块的名称实际上并不是 GLSL 本身的一部分;它是 OpenGL 的一部分。这是 OpenGL API 用来表示特定块的名称。
你从不在着色器文本本身中使用接口块的名称,而不是定义它。
除非您为接口块指定一个实例名称,否则该块中所有变量的名称本质上都是全局命名空间的一部分。实际上,限定这些名称的范围是为块提供实例名称的全部意义。
因此访问接口块中 dims
字段的正确方法是“dims
”。