如果没有错误,为什么 GL 函数调用返回的位置是 -1?
Why is the location returned by GL function call -1 if there's no error?
在下面的程序中,最后一个打印函数打印 -1,这是名为 num 的制服的位置。我为函数 glGetUniformLocation() 提供了正确的参数,但结果却得到了 -1,不知道为什么?
P.S。着色器编译成功。
GLuint program = glCreateProgram();
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
const GLchar* const shaderSrc = {
"#version 310 es\n"
"\n"
"// Input layout qualifier declaring a 16 x 16 (x 1) local\n" "// workgroup size\n"
"layout (local_size_x = 16, local_size_y = 16) in;\n"
"uniform int num;\n"
"\n"
"void main(void)\n"
"{\n"
"//Do Nothing \n"
"}\n"
};
glShaderSource(computeShader, 1, &shaderSrc, NULL);
glCompileShader(computeShader);
int result;
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &result);
if(result == GL_FALSE){
int length;
glGetShaderiv(computeShader, GL_INFO_LOG_LENGTH, &length);
char* message = static_cast<char*>(malloc(length));
glGetShaderInfoLog(computeShader, length, &length, message);
__android_log_print(ANDROID_LOG_INFO, "MyLog", "Shader Compile Error: %s", message);
free(message);
}
GL_CALL(glAttachShader(program, computeShader));
GL_CALL(glLinkProgram(program));
GL_CALL(glValidateProgram(program));
GL_CALL(glUseProgram(program));
auto location = glGetUniformLocation(program, "num");
__android_log_print(ANDROID_LOG_INFO, "MyLog", "Location %d", location);
统一变量num
不是活动的程序资源,因为它没有在着色器程序中使用。编译器和链接器优化代码并确定不需要该变量。因此,您将无法获得有效的统一位置。
此外@Rabbid76's answer我想具体解决一下你标题中的问题:
Why is the location returned by GL function call -1 if there's no error?
因为没有错误,位置-1 不是错误条件。
只有 active 制服有位置。查询非活动制服的位置定义为 return -1
。另请注意以下内容:
glUniform1f(-1, someValue)
在 GL 中完全有效,也不会根据规范产生任何错误。它只会被默默地忽略。
因为对于一个 non-active uniform 变量来说,不可能 影响你的着色器程序的输出,它的值是无关紧要的,而且 GL 没有打扰。
请注意,API中的这种设计选择是相当合理的。在客户端,您可以使用一组要提供给着色器的制服。但是您可以为这些着色器提供不同的替代方案,每个替代方案都访问这些制服中的特定 sub-set。客户端代码可以相同地对待每个变体,它不必知道(或查询)每个变体使用哪个制服。它只是不能将位置 -1 视为错误,因为它不是错误。至少如果您的客户端代码不能绝对确定此变量 必须 处于活动状态。
警告:查询non-active制服的值实际上是一个错误!
如果您使用 glGetUniformfv(program,location,params)
之类的函数并将 location
设置为 -1
,这实际上 是 一个错误条件。该调用只会 return GL_INVALID_OPERATION
并且没有其他影响(这也意味着 params
指向的内存内容不会被修改 - 它不会 return此类事物的任何默认值)。这种行为也很合理,因为 non-active 统一变量不能有值,你不能查询它们,试图这样做是错误的。
警告:顶点属性的情况略有不同
对于顶点属性,有glGetAttribLocation
,这也会return GLint
,对于不存在或不活跃的属性使用-1
.查询这些也没有错误。但是采用这些属性位置(如 glVertexAttribPointer
、glEnableVertexAttribPointer
)的 GL 函数通常使用 GLuint
类型,并且
glVertexAttribPointer(-1, ...);
将生成一个GL_INALID_VALUE
GL错误,因为(GLuint)-1
最有可能大于您实现的GL_MAX_VERTEX_ATTRIBS
值(即使它你不是没有得到你想要的结果吗。
因此对于属性位置,您的客户端代码必须检查 -1
...
在下面的程序中,最后一个打印函数打印 -1,这是名为 num 的制服的位置。我为函数 glGetUniformLocation() 提供了正确的参数,但结果却得到了 -1,不知道为什么?
P.S。着色器编译成功。
GLuint program = glCreateProgram();
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
const GLchar* const shaderSrc = {
"#version 310 es\n"
"\n"
"// Input layout qualifier declaring a 16 x 16 (x 1) local\n" "// workgroup size\n"
"layout (local_size_x = 16, local_size_y = 16) in;\n"
"uniform int num;\n"
"\n"
"void main(void)\n"
"{\n"
"//Do Nothing \n"
"}\n"
};
glShaderSource(computeShader, 1, &shaderSrc, NULL);
glCompileShader(computeShader);
int result;
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &result);
if(result == GL_FALSE){
int length;
glGetShaderiv(computeShader, GL_INFO_LOG_LENGTH, &length);
char* message = static_cast<char*>(malloc(length));
glGetShaderInfoLog(computeShader, length, &length, message);
__android_log_print(ANDROID_LOG_INFO, "MyLog", "Shader Compile Error: %s", message);
free(message);
}
GL_CALL(glAttachShader(program, computeShader));
GL_CALL(glLinkProgram(program));
GL_CALL(glValidateProgram(program));
GL_CALL(glUseProgram(program));
auto location = glGetUniformLocation(program, "num");
__android_log_print(ANDROID_LOG_INFO, "MyLog", "Location %d", location);
统一变量num
不是活动的程序资源,因为它没有在着色器程序中使用。编译器和链接器优化代码并确定不需要该变量。因此,您将无法获得有效的统一位置。
此外@Rabbid76's answer我想具体解决一下你标题中的问题:
Why is the location returned by GL function call -1 if there's no error?
因为没有错误,位置-1 不是错误条件。
只有 active 制服有位置。查询非活动制服的位置定义为 return -1
。另请注意以下内容:
glUniform1f(-1, someValue)
在 GL 中完全有效,也不会根据规范产生任何错误。它只会被默默地忽略。
因为对于一个 non-active uniform 变量来说,不可能 影响你的着色器程序的输出,它的值是无关紧要的,而且 GL 没有打扰。
请注意,API中的这种设计选择是相当合理的。在客户端,您可以使用一组要提供给着色器的制服。但是您可以为这些着色器提供不同的替代方案,每个替代方案都访问这些制服中的特定 sub-set。客户端代码可以相同地对待每个变体,它不必知道(或查询)每个变体使用哪个制服。它只是不能将位置 -1 视为错误,因为它不是错误。至少如果您的客户端代码不能绝对确定此变量 必须 处于活动状态。
警告:查询non-active制服的值实际上是一个错误!
如果您使用 glGetUniformfv(program,location,params)
之类的函数并将 location
设置为 -1
,这实际上 是 一个错误条件。该调用只会 return GL_INVALID_OPERATION
并且没有其他影响(这也意味着 params
指向的内存内容不会被修改 - 它不会 return此类事物的任何默认值)。这种行为也很合理,因为 non-active 统一变量不能有值,你不能查询它们,试图这样做是错误的。
警告:顶点属性的情况略有不同
对于顶点属性,有glGetAttribLocation
,这也会return GLint
,对于不存在或不活跃的属性使用-1
.查询这些也没有错误。但是采用这些属性位置(如 glVertexAttribPointer
、glEnableVertexAttribPointer
)的 GL 函数通常使用 GLuint
类型,并且
glVertexAttribPointer(-1, ...);
将生成一个GL_INALID_VALUE
GL错误,因为(GLuint)-1
最有可能大于您实现的GL_MAX_VERTEX_ATTRIBS
值(即使它你不是没有得到你想要的结果吗。
因此对于属性位置,您的客户端代码必须检查 -1
...