How Do GLSL Array Declarations and Sizing Work?

Arrays in the OpenGL Shading Language (GLSL) allow developers to store ordered collections of data of the same type, subject to strict declaration syntax, memory layout rules, and compile-time or runtime sizing constraints. Understanding these rules ensures compatibility across different shader stages, hardware architectures, and GLSL language versions.

Array Declaration Syntax

GLSL supports two primary syntaxes for declaring arrays, both of which are valid in modern versions of the language.

  1. C-Style Syntax: The brackets follow the variable name.
float values[4];
vec3 positions[10];
  1. Type-Style Syntax: The brackets follow the type specifier.
float[4] values;
vec3[10] positions;

GLSL also supports multidimensional arrays (arrays of arrays). They can be declared by appending dimension specifiers:

mat4 transforms[2][4];

Sizing Rules and Compile-Time Constants

In standard variable and uniform declarations, array sizes must be integral constant expressions evaluated at compile time.

const int SIZE = 8;
vec4 data[SIZE * 2]; // Valid: evaluated at compile time
int numbers[] = int[](1, 2, 3, 4, 5); // Inferred size of 5

Unsized Arrays in Shader Storage Buffer Objects (SSBOs)

A critical exception to the fixed compile-time size rule applies to Shader Storage Buffer Objects (SSBOs).

layout(std430, binding = 0) buffer StorageBlock {
    mat4 projection;
    float dynamicData[]; // Valid only as the final member of an SSBO
};

Array Constructors and Initialization

Arrays can be initialized using type-specific constructors. The constructor name consists of the element type followed by brackets indicating the array size.

vec2 offsets[3] = vec2[3](
    vec2(0.0, 0.0),
    vec2(1.0, 0.0),
    vec2(0.0, 1.0)
);

The number and types of arguments in the constructor must match the declared dimension and base type exactly.

Indexing Constraints

How arrays are accessed depends on the storage qualifier and shader stage:

The .length() Method

GLSL arrays provide an intrinsic .length() method that returns an int representing the total number of elements.