Location and Component Interface
This chapter is an overview of the Location and Component Assignment chapter to help give examples, especially around some of the more extreme edge cases.
The simplest way to think about a Location
is that it is made up of four 32-bit Component
.
This means a vec4
/float4
/uvec4
/etc will fit perfectly in a single Location
.
Multiple variables can be packed into the same Location
if their Componens
do not overlap.
Locations are used for both the Input
and Output
to interface between shaders stages when possible.
Advice for general users
For most people, this chapter is much deeper into edge cases compared who developers generally use the Location
interface. For those developers, the simple advise to take away is:
-
Use less
Location
if possible. -
If you need many
Location
, make sure you are under the limits.
Basic Example
Here is a basic example:
layout(location=0) in vec4 a;
layout(location=1, component = 0) in vec2 b;
layout(location=1, component = 2) in float c;
16-bit
16-bit values always consume a full 32-bit Component
. So a vector with 16-bit elements will consume the same resources as a vector with 32-bit elements; they are not tightly packed.
layout(location=0) in f16vec3 a;
Crossing Location Boundaries
All 16-bit and 32-bit vectors must be inside a single Location
, so the following is not allowed.
The last two elements would consume component = 4
and component = 5
, which do not exist.
layout(location=0, component = 2) in vec4 a;
64-bit
64-bit are special as they can consume up to 2 Location
, but they must only start at Component
0
or 2
.
layout(location=0) in f64vec3 a;
Interleaving Components
The following attempt to have multiple variables alias the same component is not allowed.
layout(location=0) in vec2 in_a; // Components 0 and 1
layout(location=0, component=1) in float in_f; // Invalid: overlaps component 1
The following modification would make it legal as multiple variable can share a Location
, just not a `Component
`
layout(location=0) in vec2 in_a;
// Change in_f to use component 2 instead
- layout(location=0, component=1) in float in_f;
+ layout(location=0, component=2) in float in_f;
Array
An element of an array will consume all every Component
in a Location
that it would consume as a non-arrayed value, with each subsequent element consuming the next available Location
.
For example:
layout(location=0) in float a[3];
As seen, using a scalar or something such as a vec2
/float2
will leave many Component
slots unused.
It is not allowed to use any other Component
in a Location
that is being consumed by an array
layout(location=0) in float a[3];
layout(location=2, component=2) in float b;
float b
is invalid because the array consumes all of Location
2.
Some shader stages, like geometry shaders, have an array around its interface matching, this array is disregarded for the above examples. |
Matrix
A matrix is viewed as an array, which consume all 4 components.
So something like
layout(location = 0) in mat3x2 a;
From a Location
/Component
point-of-view looks like
// N == 3
// Arrays consume whole Location
layout(location = 0) in vec2 a[3];
As stated above, arrays consume the whole Location
so the following is not allowed.
layout(location = 0) in mat3x2 a;
layout(location = 2, component = 2) in float b;
float b
is invalid because the implicit array of the matrix consumes all of Location
2.