Opengl 统一显式位置和绑定点索引
我在GLSL中遇到以下错误。以下是片段着色器:Opengl 统一显式位置和绑定点索引,opengl,glsl,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_b
#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)
#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;
}
现在,当我将此着色器编译到程序中而不声明某些特殊情况,并且在运行时仍将u\u blendMode
uniform设置时,我从驱动程序中得到以下错误:
生成GL\u无效\u操作错误。价值是
无效的应为GL_INT或GL_UNSIGNED_INT64_NV
但我希望得到这样一个错误:
生成GL\u无效\u操作错误。'位置“”无效
因为如果我不设置SOME\u SPECIAL\u CASE
preprocessor标志,就没有这样一个索引(0)的位置。然后我决定检查我得到的制服,这需要GL\u INT
或GL\u UNSIGNED\u INT64\u NV
,因此我根据制服的位置(零)查询制服名称:
并得到了名称“colorTex”,这是具有绑定索引DIFFUSE\u TEX\u UNIT
的sampler2D uniform的名称,也是零。
到目前为止,我认为统一位置和绑定点不使用相同的索引,我仍然认为它们不使用相同的索引,因为如果使用某些特殊情况活动编译此着色器,则会失败,以及我在工作历史中编写的许多其他着色器。因此,当我设置不存在的统一位置时,为什么sampler2D统一绑定索引会受到影响,并且我还使用特定类型(GLSL-uint),这看起来非常奇怪
这也与sampler2D的类型不匹配(因此至少关于类型不匹配的错误是正确的)。
这是一个驱动程序错误吗
还有一件事,我试图检查绑定和位置索引是否真的重叠,并发现以下语句:
将同一制服位置分配给两套制服是违法的
相同的着色器或相同的程序。即使那两套制服
相同的名称和类型,并在不同的着色器阶段中定义,则
明确指定同一统一地点是不合法的;A.
将发生链接器错误
这是完全错误的!我已经做了很多年了。在读了这些台词之后,我又试了一次。在顶点和片段着色器中具有相同的一致性和相同的位置可以编译并运行良好
我的设置:
- 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 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)
#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
采用统一的索引,而不是统一的位置。无法从着色器设置索引;它们只是从0到活动制服数量的所有制服变量。索引仅用于
无法获取统一位置并要求统一变量的统一索引(或名称)
但我希望得到这样一个错误:
...
因为如果我不设置一些特殊情况预处理器标志,就没有这样一个索引(0)的位置
当然有。不使用显式位置的统一变量永远不会与具有显式位置的统一变量具有相同的位置。然而,这不是这里发生的事情
如果未定义SOME\u SPECIAL\u CASE
,则u blendMode
的声明不存在。由于位置0从未被显式统一变量使用,因此它现在可用于隐式位置分配
因此,实现可以将colorTex
的位置指定为零(注意,这与将绑定
指定为零不同)
如果要始终保留位置0,则u_blendMode
的声明必须始终可见,即使从未使用过它。该规范允许实现仍然优化这些声明,但是显式位置本身并没有优化。因此,如果您对未使用的制服使用location=0
,那么位置0可能是也可能不是有效位置。但如果它有效,它将始终引用u\u blendMode
关于在相同位置使用相同制服的能力,至少在NVIDIA GPU上,以下编译和运行良好:
GLSL规范已经解决了这一问题,只要这两个声明本身是相同的。因此,交叉着色器阶段的统一位置应该有效。glGetActiveUniformName
FYI:此函数采用统一索引,而不是统一位置。索引是用于所有统一的(除非它有一个名称)。最初,我非常确定Wiki在这方面是正确的(毕竟是我写的)。然而,我发现了这句话“因此,所有静态使用的统一变量的类型、初始值设定项和任何位置说明符必须在链接到单个程序的所有着色器中匹配”,这让一切都变得可疑。因为现在的问题是。。。是否再次声明了这两个“变量”或同一个变量?应注意的是,GLSL 4.60中添加了“任意位置说明符”的措辞;它在以前的版本中不存在,在ARB_显式_统一_位置中也不存在。所以这感觉就像某种从未被提及的bug修复