统一的显式位置和绑定点索引

时间:2019-04-18 16:40:05

标签: opengl glsl

我在GLSL中遇到以下错误。这是片段着色器:

#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设置为统一时,我从驱动程序得到以下错误:

  

GL_INVALID_OPERATION错误生成。值是   无效;预期的GL_INT或GL_UNSIGNED_INT64_NV。

但是我希望得到这样的错误:

  

GL_INVALID_OPERATION错误生成。 “ location”无效。

因为如果我未设置SOME_SPECIAL_CASE预处理程序标志,则没有位置具有这样的索引(0)。然后,我决定检查我所穿的制服,要求GL_INTGL_UNSIGNED_INT64_NV,因此我根据制服的位置(零)查询了制服的名称:

 char buff[20];
 GLsizei len = 0;
 glGetActiveUniformName(prog.progHandle, 0, 20, &len, buff);

并获得名称“ colorTex”,这是具有绑定索引DIFFUSE_TEX_UNIT的sampler2D制服的名称,该索引也为零。 到目前为止,我相信统一的位置和绑定点不会使用相同的索引,但我仍然相信它们不会使用相同的索引,因为否则此着色器在使用SOME_SPECIAL_CASE active编译时会失败,以及我编写的许多其他着色器通过我的工作历史。因此,当我设置不存在的统一位置时,为什么sampler2D统一绑定索引会受到影响,而且我还使用特定类型(GLSL-uint),这看起来很奇怪

glProgramUniform1ui(prog, location, (GLuint)value);

这也与sampler2D的类型不匹配(因此该错误至少在类型不匹配方面是正确的)。 是驱动程序错误吗?

还有一件事,我试图检查docs是否绑定和位置索引确实重叠并发现以下语句:

  

将同一制服位置分配给两个制服是非法的   相同的着色器或相同的程序。即使那两个制服   具有相同的名称和类型,并且在不同的着色器阶段定义,   明确为其分配相同的统一位置是不合法的;一种   链接器错误将会发生。

这是绝对错误的!我已经做了多年了。阅读这些内容后,再次尝试。在顶点着色器和片段着色器中具有相同的制服,相同的位置可以编译并正常工作。

我的设置:

  • NVIDIA Quadro P2000,驱动程序419.17
  • OpenGL 4.5
  • Windows 10 64位

关于在相同位置(至少在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; 
}

1 个答案:

答案 0 :(得分:3)

  

是驱动程序错误吗?

不。 glGetActiveUniformName采用统一的索引,而不采用统一的位置。无法从着色器设置索引;它们只是所有统一变量,从0到有效统一数量。索引仅用于introspecting properties of uniforms

无法采取统一的位置并要求统一变量的统一索引(或名称)。

  

但是我希望得到这样的错误:   ...   因为如果不设置SOME_SPECIAL_CASE预处理器标志,则没有位置具有这样的索引(0)。

当然可以。不使用显式位置的统一变量永远不会与没有的具有显式位置的统一变量具有相同的位置。 但是,这不是这里发生的事情。

如果未定义SOME_SPECIAL_CASE,则u_blendMode 的声明不存在。由于位置0从未被显式统一变量使用,因此现在可用于隐式位置分配。

因此,实现可以将colorTex的位置分配为零(请注意,这与将binding的分配为零是不同)。

如果您想始终保留位置0,则u_blendMode的声明必须始终可见,即使您从未使用过它也是如此。该规范允许实现仍然优化掉这样的声明,但是显式位置 itself 并没有被优化掉。因此,如果将location = 0用于未使用的制服,则位置0可能是有效位置,也可能不是有效位置。但是,如果有效,它将总是引用u_blendMode


  

关于在相同位置(至少在NVIDIA GPU上)使用相同制服的功能,以下编译并可以正常运行:

...好吧,这里似乎存在很大的规范矛盾。一方面,这似乎是绝对禁止的:

  

即使未使用它们,程序中的两个默认块统一变量也不能具有相同的位置,否则将生成编译时或链接时错误。

另一方面,这似乎是完全允许的:

  

当链接到程序或可分离程序时,着色器中的制服都共享一个全局全局名称空间。因此,具有相同名称的所有静态使用的统一变量的类型,初始值设定项和任何位置说明符,必须在链接到单个程序的所有着色器中匹配。

已添加重点。

仅在GLSL 4.60中添加了强调的文字;您不会在早期的GLSL版本中找到它,也不会在ARB_explicit_uniform_location 本身中找到它。

说实话...我不知道这是什么意思。因此,我提交了OpenGL specification bug on it