2

In a GLSL shader, if I have the following layout specifications:

layout (location = 0) uniform mat4 modelMatrix;
layout (location = 1) uniform mat4 viewMatrix;
layout (location = 5) uniform mat4 projMatrix;
layout (location = 30) uniform vec3 diffuseColor;
layout (location = 40) uniform vec3 specularColor;

void main()
{
   ...
}

Does it matter that there are gaps between the locations? Do these gaps have any impacts in terms of actual memory layout of the data or performance?

j00hi
  • 5,420
  • 3
  • 45
  • 82
  • 1
    The relevant chapter in the specification is [4.4.1 Input Layout Qualifiers](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). But as far as I know it is just an ID and has no direct effect on memory. – Rabbid76 Nov 30 '17 at 09:37
  • Interesting question, but I'm not sure if someone can give an answer to the it: The spec doesn't define how shader memory is laid out. But maybe someone knows how this is implemented by different vendors. – BDL Nov 30 '17 at 10:44

2 Answers2

2

Whether it affects performance cannot be known without testing on various implementations. However, as far as the OpenGL specification is concerned, uniform locations are just numbers; they do not represent anything specific about the hardware. So gaps in locations are fine, from a standardization point of view.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
2

Most OpenGL implementations do have an upper limit on the number of bindings afforded to Attributes, Uniforms, etc. So if you specify a number above the maximum limit, the GL might not handle it correctly.

But a lot of it is implementation specific. An implementation might, for example, only allow up to 16* attribute locations, but has no problem indexing any valid integer value so long as the number of unique locations doesn't exceed 16.

More importantly, there's no limit on simply skipping locations:

layout(location = 0) in vec2 vertex;
layout(location = 1) in vec4 color;
layout(location = 3) in uint indicator;
layout(location = 7) in vec2 tex;

Which, of course, you bind as expected:

glEnableVertexArrayAttrib(0);
glEnableVertexArrayAttrib(1);
glEnableVertexArrayAttrib(3);
glEnableVertexArrayAttrib(7);

//Assuming all the data is tightly packed in a single Array Buffer
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, (void*)(36));
glVertexAttribPointer(1, 4, GL_FLOAT, false, 8, (void*)(36));
glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 24, (void*)(36));
glVertexAttribPointer(7, 2, GL_FLOAT, false, 28, (void*)(36));

*I haven't looked it up, but I do know OpenGL guarantees that implementations support at least some number of Attribute and Uniform locations and bindings. I don't know what that number is, but the number '84' keeps popping into my head for some reason.

Xirema
  • 19,889
  • 4
  • 32
  • 68
  • You've definitely got a point there, because with vertex attributes it is somewhat clear that the locations do not affect memory layout at all, otherwise there would be no point in specifying the memory layout via `glVertexAttribPointer` and the `stride` parameter. I get the feeling that the layout should not affect the memory layout of uniforms, either. – j00hi Dec 01 '17 at 06:35