2
\$\begingroup\$

In the code below I have a uniform variable named "vw_matrix" used in the calculation for gl_Position. When I run my program, a rectangle gets printed to the screen.

#version 330 core

layout (location = 0) in vec4 position;

uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);  // Rectangle!
uniform mat4 m1_matrix = mat4(1.0);  // No rectangle!
uniform mat4 mmmmm = mat4(1.0);      // No rectangle!
uniform mat4 test = mat4(1.0);       // Rectangle!
uniform mat4 aaa = mat4(1.0);        // No rectangle!

void main()
{
    gl_Position = pr_matrix * position * vw_matrix;
}

If instead I put "m1_matrix" in the gl_Position line instead of "vw_matrix". The rectangle no longer appears. I'm not getting any GLSL compile errors.

void main()
{
    gl_Position = pr_matrix * position * m1_matrix;
}

There are no calls to glUniformMatrix4fv changing the value "m1_matrix". It has the same value as "vw_matrix" so for some reason it must not be initializing.

I did some experimenting, it won't set a uniform variable if it starts with a certain letter and "m" is one of those letters. Anything that starts with a "v" or "t" works fine. I can't make this up!

Is there anything I should double check/post or is this just a rather bizarre bug? The full code is available at https://github.com/nduplessis11/Freeze

I'm running on Linux Mint 17.1 and my GL_VERSION is "OpenGL 4.4 13374 Compatibility Profile Context 15.20.2013". My video driver is AMD's fglrx version 15.200

UPDATE: Ok, I found a bug in my main program in a function that retrieves the location of a uniform.

GLint Shader::getUniformLocation(const GLchar* name)
{
  // This is a very slow operation, optimize later.
  glGetUniformLocation(m_ShaderID, name);
  return 0;
}

This was causing 0 to be passed as the location for glSetUniform* calls. I'm not sure how, but fixing this function stopped the unpredictable behavior when initializing uniform variables from within the shader program. I'm still going to take Trevor's advice and set them from within my main program.

\$\endgroup\$
3
  • \$\begingroup\$ See my comment below about "Suspected driver bugs still almost always turn out to have been technically-illegal OpenGL code which one vendor let you get away with and another didn't." In this case, if your shader uses pr_matrix and vw_matrix but not the others, pr_matrix is uniform 0 and vw_matrix is uniform 1. If the shader uses pr_matrix and m1_matrix, pr_matrix is uniform 1 and m1_matrix is uniform 0. Your code was always setting the projection matrix into uniform 0. \$\endgroup\$ Commented Jun 29, 2015 at 14:27
  • \$\begingroup\$ (note that the above is not behaviour which is mandated by the standards; it's just an explanation for what was actually failing in this particular case, using the specified ATI driver, according to some debugging.) \$\endgroup\$ Commented Jun 29, 2015 at 14:29
  • \$\begingroup\$ I've also seen some behavior on GL ES, which uniforms you don't use on the code will be striped out as if they didn't ever exist so if you try to set them from the API, you'll receive an error stating that uniform don't exist. That happens a lot when you comment certain lines to debug your program but then a uniform stop being referenced and thus, stop to exist. I haven't seen this behavior on desktop GL. \$\endgroup\$ Commented Jun 29, 2015 at 21:33

1 Answer 1

3
\$\begingroup\$

This is a known issue in some drivers. Including (at time of writing) the most recent ATI drivers across both Windows and Linux.

From the OpenGL wiki page on GLSL uniforms:

Platform Issue (Unknown): Some drivers do not implement uniform initializers correctly.

Best practice is therefore to set all of your shaders' uniforms explicitly from inside your program, or else not to declare them as uniforms.

For example, your example code works just fine using any of the current mat4 variables, if you just remove the 'uniform' keyword from the ones which aren't actually being set inside the main program.

\$\endgroup\$
8
  • 1
    \$\begingroup\$ While we're here, it's worth also mentioning that the current ATI drivers for certain GPUs also don't always correctly retain uniform values when switching between current shader programs. So not only do you need to set all your shader' uniforms explicitly, you need do it it every time you switch from one shader to another. \$\endgroup\$ Commented Jun 28, 2015 at 1:01
  • \$\begingroup\$ Ok good, I thought I was losing my mind for a minute! Setting them from inside my program did the trick. Thanks! \$\endgroup\$ Commented Jun 28, 2015 at 1:04
  • \$\begingroup\$ Dear god, this is a nightmare - it's like C programmers who find a bug in the compiler. \$\endgroup\$
    – Flafla2
    Commented Jun 29, 2015 at 1:35
  • \$\begingroup\$ @Flafla2 C compiler bugs are very rare; you're unlikely to ever bump into one unless you're working on an unusual platform. When you suspect a C compiler bug, most people won't believe you; on balance, you're more likely to be making a silly mistake than to have found a real issue. Driver bugs around details in the OpenGL specification are much, much more common and less unbelievable. Particularly in this sort of area like "what happens with a uniform variable which the host program doesn't actually set a value for" which virtually never happen in the real world. \$\endgroup\$ Commented Jun 29, 2015 at 3:14
  • \$\begingroup\$ (With that said, I've seen a lot of newly-ported-to-OpenGL games fail on certain ATI cards due to the "not retaining previously set uniform values" issue. The general wisdom is that you should remember what uniform values you last set, and not re-set them if they don't change. But on ATI cards with the official drivers, you can sometimes end up rendering using rubbish uniform values if you do that.) \$\endgroup\$ Commented Jun 29, 2015 at 3:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .