I am experiencing the following error in GLSL. Here is the fragment shader:
#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)
Now,when I compile this shader into program without declaring SOME_SPECIAL_CASE,and still set u_blendMode uniform during runtime,I am getting the following error from driver:
GL_INVALID_OPERATION error generated. value is
invalid; expected GL_INT or GL_UNSIGNED_INT64_NV.
But I would expect to get an error like this:
GL_INVALID_OPERATION error generated. ' location ' is invalid.
Because there is no location with such an index (0) if I don't set SOME_SPECIAL_CASE preprocessor flag. Then I decided to check what uniform I have got, which requires GL_INT or GL_UNSIGNED_INT64_NV,so I queried uniform name based on its location (zero):
char buff[20];
GLsizei len = 0;
glGetActiveUniformName(prog.progHandle, 0, 20, &len, buff);
And got the name 'colorTex',which is the name of sampler2D uniform that has binding index DIFFUSE_TEX_UNIT ,that is also zero.
Untill now,I believed uniform location and binding points do not use same indices and I still believe they don't,because otherwise this shader,when compiled with SOME_SPECIAL_CASE active would fail,as well as many other shaders I have written thru my work history.Hence it looks utterly weird why that sampler2D uniform binding index is affected when I am setting non-existing uniform location,and I also use specific type (GLSL - uint)
glProgramUniform1ui(prog, location, (GLuint)value);
Which also doesn't match the type of sampler2D (so the error is kinda right at least about type mismatch).
Is it a driver bug?
One more thing,I tried to check in docs if binding and location indices really overlap and found this statement:
It is illegal to assign the same uniform location to two uniforms in
the same shader or the same program. Even if those two uniforms have
the same name and type, and are defined in different shader stages, it
is not legal to explicitly assign them the same uniform location; a
linker error will occur.
This is just absolutely wrong! I have been doing this for years. And tried that again after reading those lines. Having same uniform,with same location in both vertex and fragment shader compiles and works fine.
My setup:
NVIDIA Quadro P2000, driver 419.17
OpenGL 4.5
Windows 10 64bit
Regarding the ability to use same uniform on same location,at least on NVIDIA GPU the following compiles and runs fine:
Vertex shader
#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);
}
Fragment shader:
#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;
}
Is it a driver bug?
No. glGetActiveUniformName takes uniform indices, not uniform locations. Indices cannot be set from the shader; they're just all of the uniform variables, from 0 to the number of active uniforms. Indices are only used for introspecting properties of uniforms.
There's no way to take a uniform location and ask for the uniform index (or name) of the uniform variable.
But I would expect to get an error like this:
...
Because there is no location with such an index (0) if I don't set SOME_SPECIAL_CASE preprocessor flag.
Sure there is. Uniform variables which do not use explicit locations will never have the same location as a uniform variable that does have an explicit location. However, that's not what's happening here.
If SOME_SPECIAL_CASE is not defined, then the declaration of u_blendMode does not exist. Since location 0 was never used by an explicit uniform variable, it is now available for implicit location assignment.
So the implementation can assign the location of colorTex to zero (note that this is different from assigning the binding to zero).
If you want to reserve location 0 always, then the declaration of u_blendMode must always be visible, even if you never use it. The specification allows implementations to still optimize away such declarations, but the explicit location itself is not optimized away. So if you use location = 0 for a uniform that goes unused, then location 0 may or may not be a valid location. But if it is valid, it will always refer to u_blendMode.
Regarding the ability to use same uniform on same location,at least on NVIDIA GPU the following compiles and runs fine:
The GLSL specification has worked this out, and it is now OK to have two explicit uniform locations that are the same, so long as the two declarations are themselves identical. So cross-shader-stage uniform locations are supposed to work.
Related
My fragment shader contains the following struct variable.
struct Material
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material material;
// another uniform
uniform float tmp;
In vispy on using
self.program['material.ambient'] = [1,1,1]
self.program['material.diffuse'] = [1,0.7,1]
self.program['material.specular'] = [0.5,1,1]
self.program['material.shininess'] = 32
self.program['tmp'] = 10
I am getting following errors
WARNING: Value provided for 'material.diffuse', but this variable was not found in the shader program.
WARNING: Value provided for 'material.ambient', but this variable was not found in the shader program.
WARNING: Value provided for 'material.specular', but this variable was not found in the shader program.
WARNING: Value provided for 'material.shininess', but this variable was not found in the shader program.
INFO: Program has unset variables: { 'material.specular', 'material.shininess', 'material.diffuse', 'material.ambient'}
I am using the correct shader program and have linked the right fragment shader.
I think vispy dont supports struct types yet, is there any work around by which I can pass these values ?
According to khronos.org,
GL_MAX_UNIFORM_BLOCK_SIZE refers to the maximum size in basic machine units of a uniform block. The value must be at least 16384.
I have a fragment shader, where I declared a uniform interface block and attached a uniform buffer object to it.
#version 460 core
layout(std140, binding=2) uniform primitives{
vec3 foo[3430];
};
...
If I query the size of GL_MAX_UNIFORM_BLOCK_SIZEwith:
GLuint info;
glGetUniformiv(shaderProgram.getShaderProgram_id(), GL_MAX_UNIFORM_BLOCK_SIZE, reinterpret_cast<GLint *>(&info));
cout << "GL_MAX_UNIFORM_BLOCK_SIZE: " << info << endl;
I get: GL_MAX_UNIFORM_BLOCK_SIZE: 22098. It is ok, but for example: when I changes the size of the array to 3000 (instead of 3430), I get GL_MAX_UNIFORM_BLOCK_SIZE: 21956
As far as I know, GL_MAX_UNIFORM_BLOCK_SIZE should be a constant depending on my GPU. Then why does it change, when I modify the size of the array?
GL_MAX_UNIFORM_BLOCK_SIZE is properly queried with glGetIntegerv. It is a constant defined by the implementation which tells you the implementation-defined maximum. glGetUniform returns the value of a uniform in the given program. You probably got an OpenGL error of some kind, since GL_MAX_UNIFORM_BLOCK_SIZE is not a valid uniform location, and therefore your integer was never written to. So you're just reading uninitialized data.
I'm trying to draw 2 simple triangles nothing special and this is the shader code :
#version 430 core
layout(location=0) in vec4 vPosition;
void
main()
{
gl_position=vPosition;
}
As you can see the shader code is really small and has nothing special.
When I try to compile this code I get a
undefined variable "gl_position"
I don't understand why because I thought all the gl_... variables were global variables.
What can I do ?
GLSL is case sensitive (as most programming languages), so its gl_Position, not gl_position.
It is gl_Position. P is uppercase.
My vertex shader is ,
uniform Block1{ vec4 offset_x1; vec4 offset_x2;}block1;
out float value;
in vec4 position;
void main()
{
value = block1.offset_x1.x + block1.offset_x2.x;
gl_Position = position;
}
The code I am using to pass values is :
GLfloat color_values[8];// contains valid values
glGenBuffers(1,&buffer_object);
glBindBuffer(GL_UNIFORM_BUFFER,buffer_object);
glBufferData(GL_UNIFORM_BUFFER,sizeof(color_values),color_values,GL_STATIC_DRAW);
glUniformBlockBinding(psId,blockIndex,0);
glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,0,16);
glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,16,16);
Here what I am expecting is, to pass 16 bytes for each vec4 uniform. I get GL_INVALID_VALUE error for offset=16 , size = 16.
I am confused with offset value. Spec says it is corresponding to "buffer_object".
There is an alignment restriction for UBOs when binding. Any glBindBufferRange/Base's offset must be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. This alignment could be anything, so you have to query it before building your array of uniform buffers. That means you can't do it directly in compile-time C++ logic; it has to be runtime logic.
Speaking of querying things at runtime, your code is horribly broken in many other ways. You did not define a layout qualifier for your uniform block; therefore, the default is used: shared. And you cannot use `shared* layout without querying the layout of each block's members from OpenGL. Ever.
If you had done a query, you would have quickly discovered that your uniform block is at least 32 bytes in size, not 16. And since you only provided 16 bytes in your range, undefined behavior (which includes the possibility of program termination) results.
If you want to be able to define C/C++ objects that map exactly to the uniform block definition, you need to use std140 layout and follow the rules of std140's layout in your C/C++ object.
So we have in C:
auto if break int case long char register
continue return default short do sizeof
double static else struct entry switch extern
typedef float union for unsigned
goto while enum void const signed volatile
What new keywords OpenGL (ES) Shader Language provide to us?
I am new to GLSL and I want to create some highlight editing util for ease of use.
Math words included into GLSL will count as keywords..?
New ones (excluding the ones you listed above) according to the latest spec document:
attribute uniform varying
layout
centroid flat smooth noperspective
patch sample
subroutine
in out inout
invariant
discard
mat2 mat3 mat4 dmat2 dmat3 dmat4
mat2x2 mat2x3 mat2x4 dmat2x2 dmat2x3 dmat2x4
mat3x2 mat3x3 mat3x4 dmat3x2 dmat3x3 dmat3x4
mat4x2 mat4x3 mat4x4 dmat4x2 dmat4x3 dmat4x4
vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 dvec2 dvec3 dvec4
uvec2 uvec3 uvec4
lowp mediump highp precision
sampler1D sampler2D sampler3D samplerCube
sampler1DShadow sampler2DShadow samplerCubeShadow
sampler1DArray sampler2DArray
sampler1DArrayShadow sampler2DArrayShadow
isampler1D isampler2D isampler3D isamplerCube
isampler1DArray isampler2DArray
usampler1D usampler2D usampler3D usamplerCube
usampler1DArray usampler2DArray
sampler2DRect sampler2DRectShadow isampler2DRect usampler2DRect
samplerBuffer isamplerBuffer usamplerBuffer
sampler2DMS isampler2DMS usampler2DMS
sampler2DMSArray isampler2DMSArray usampler2DMSArray
samplerCubeArray samplerCubeArrayShadow isamplerCubeArray usamplerCubeArray
Reserved for future use (will cause error at the moment):
common partition active
asm
class union enum typedef template this packed
goto
inline noinline volatile public static extern external interface
long short half fixed unsigned superp
input output
hvec2 hvec3 hvec4 fvec2 fvec3 fvec4
sampler3DRect
filter
image1D image2D image3D imageCube
iimage1D iimage2D iimage3D iimageCube
uimage1D uimage2D uimage3D uimageCube
image1DArray image2DArray
iimage1DArray iimage2DArray uimage1DArray uimage2DArray
image1DShadow image2DShadow
image1DArrayShadow image2DArrayShadow
imageBuffer iimageBuffer uimageBuffer
sizeof cast
namespace using
row_major
You probably want to get the OpenGL ES GLSL language specification. §3.6 lists the keywords (plus a number of reserved words that aren't keywords, but you're not supposed to use anyway, so they probably merit some sort of color coding as well).
Edit: Oops, I grabbed the wrong link there. My apologies. The current specs are:
OpenGL 4.1 GLSL
OpenGL ES 2.0 GLSL
Besides the above answers, there are also reserved identifiers, eg. in GLSL ES 3.0 spec:
Identifiers starting with gl_ are reserved for use by OpenGL ES, and may not be declared in a shader as either a variable or a function. It is an error to redeclare a variable, including those starting “gl_”.
And other things beyond these are reserved:
In addition, all identifiers containing two consecutive underscores (__) are reserved for use by underlying software layers. Defining such a name in a shader does not itself result in an error, but may result in unintended behaviors that stem from having multiple definitions of the same name.
It is relevant for syntax coloring and correctness checking.
Similarly, macros starting with GL_, and a bunch of things with __.