#version 450 core
#define DIFFUSE_TEX_UNIT 0
#define INDEX_UNIFORM_LOC 0
layout(binding = DIFFUSE_TEX_UNIT) uniform sampler2D colorTex;
#ifdef SOME_SPECIAL_CASE
layout (location = INDEX_UNIFORM_LOC) uniform uint u_blendMode;
//...more code here related to the case
#endif
//... rest of the code(not important)
当我编译此着色器成程序时,没有声明SOME_SPECIAL_CASE,并且在运行时设置u_blendMode uniform变量,驱动程序会生成以下错误:
GL_INVALID_OPERATION 错误生成。value是无效的;期望 GL_INT 或 GL_UNSIGNED_INT64_NV。
但我希望得到这样的错误:
GL_INVALID_OPERATION 错误生成。‘location’ 无效。
因为如果我不设置SOME_SPECIAL_CASE预处理器标志,则没有该索引(0)的位置。然后我决定检查我拥有的uniform变量,它需要GL_INT或GL_UNSIGNED_INT64_NV,所以我基于其位置(零)查询uniform变量名称:
char buff[20];
GLsizei len = 0;
glGetActiveUniformName(prog.progHandle, 0, 20, &len, buff);
获得名称为'colorTex',这是一个名为DIFFUSE_TEX_UNIT
的sampler2D uniform的绑定索引,该索引也为零。
到目前为止,我认为uniform位置和绑定点不使用相同的索引,我仍然相信它们不会,因为否则当使用SOME_SPECIAL_CASE
编译此着色器时,它将失败,就像我在工作历史中编写的许多其他着色器一样。因此,当我设置不存在的uniform位置并且使用特定类型(GLSL - uint)时,sampler2D uniform绑定索引为什么会受到影响看起来非常奇怪。
glProgramUniform1ui(prog, location, (GLuint)value);
这也与sampler2D的类型不匹配(因此错误至少在类型不匹配方面是正确的)。这是一个驱动程序的错误吗?
还有一件事,我尝试在文档中检查绑定和位置索引是否真正重叠,并找到了这个声明:
在同一个着色器或同一个程序中将相同的统一变量位置分配给两个统一变量是非法的。即使这两个统一变量具有相同的名称和类型,并且定义在不同的着色器阶段中,也不允许显式地为它们分配相同的统一变量位置;将出现链接器错误。
这是完全错误的!我已经这样做了好多年。在读完这些文字后,我再次尝试了一下。在顶点着色器和片段着色器中具有相同位置的相同uniform编译并正常工作。
我的设置:
- NVIDIA Quadro P2000,驱动程序版本419.17
- OpenGL 4.5
- Windows 10 64位
关于能否在相同位置使用相同的uniform,在至少NVIDIA GPU上,以下代码可以编译并正常运行:
顶点着色器:
#version 450 core
#define MVP_UNIFORM_LOC 2
layout(location = 0) in vec2 v_Position;
layout(location = MVP_UNIFORM_LOC) uniform mat4 u_MVP;
smooth out vec2 texCoord;
void main()
{
texCoord = v_Position;
gl_Position = u_MVP * vec4(v_Position,0.0,1.0);
}
片段着色器:
#version 450 core
#define MVP_UNIFORM_LOC 2
#define TEX_MAP_UNIT 5
layout(binding = TEX_MAP_UNIT ) uniform sampler2D texMap;
layout(location = MVP_UNIFORM_LOC) uniform mat4 u_MVP;
smooth in vec2 texCoord;
out vec4 OUTPUT;
void main()
{
vec4 tex = texture(texMap, texCoord);
OUTPUT = u_MVP * tex;
}
glGetActiveUniformName
该函数使用 uniform 的 indices,而不是 uniform 的 locations。对于所有 uniform introspection functions 都会使用 indices(除非它接受名称)。 - Nicol Bolas