GLSL Multi-Dimensional Array Syntax Rules

This article provides a complete overview of the syntax rules for declaring multi-dimensional arrays with explicit dimensions in the OpenGL Shading Language (GLSL). It covers version requirements, bracket placement rules, size constraint specifications, and initialization patterns required to implement arrays of arrays correctly in your shaders.

Version Support

Multi-dimensional arrays (formally known as "arrays of arrays") are natively supported starting in GLSL version 4.30. For shaders targeting earlier versions (down to GLSL 3.30 or OpenGL 3.1+), you must explicitly enable the extension:

#version 330
#extension GL_ARB_arrays_of_arrays : enable

In #version 430 or higher, multi-dimensional array support is enabled by default.

Basic Declaration Syntax

GLSL allows multi-dimensional array dimensions to be declared on the variable identifier, on the data type, or across both.

1. Dimensions on the Variable Identifier

The most common approach places all dimension qualifiers after the variable name:

float grid[4][8]; // An array of 4 arrays of 8 floats

2. Dimensions on the Type Specifier

Dimensions can be attached directly to the type specifier:

float[4][8] grid; // Identical in type and memory layout to float grid[4][8]

3. Split Dimensions

You can split dimensions between the type specifier and the variable name:

float[4] grid[8]; // An array of 8 arrays of 4 floats

When dimensions are split, GLSL resolves the outer dimensions from the variable identifier first, followed by the dimensions on the type from right to left. In float[4] grid[8], grid is an array of size 8, whose elements are float[4].

Dimension Size Requirements

When declaring an array with explicit dimensions, each dimension expression must satisfy the following constraints:

  • Compile-Time Constant Expressions: Every dimension size must be an integral constant expression (e.g., literal integers or variables declared with the const qualifier).
  • Positive Non-Zero Values: Dimension sizes must evaluate to a signed or unsigned integer strictly greater than zero (> 0).
  • Integral Types: Sizes can be typed as int or uint.
const int ROWS = 3;
const uint COLS = 5u;

vec3 transformMatrix[ROWS][COLS]; // Valid: constant integral expressions

Initialization Syntax

Multi-dimensional arrays with explicit dimensions can be initialized using constructors or aggregate initializer lists.

Array Constructors

You can initialize an array by explicitly invoking the array type constructor recursively:

// Declaring and constructing a 2x2 matrix using type constructors
int[2][2] matrix = int[2][2](
    int[2](1, 2),
    int[2](3, 4)
);

Initializer Lists

GLSL 4.30 and above supports C-style nested initializer lists:

int matrix[2][2] = int[2][2](
    { 1, 2 },
    { 3, 4 }
);

// Or using direct assignment syntax:
int matrix[2][2] = {
    { 1, 2 },
    { 3, 4 }
};

The number of elements in the initializer must exactly match the declared explicit dimensions.

Function Parameter Syntax

When passing multi-dimensional arrays with explicit dimensions into functions, the dimensions must be fully qualified in the parameter declaration:

void processGrid(float data[4][8]) {
    // Function body
}

// Or with type-bound dimensions:
void processGrid(float[4][8] data) {
    // Function body
}

Array parameters in GLSL are passed by value unless explicitly decorated with parameter qualifiers like in, out, or inout. Explicit dimensions ensure strict type checking during shader compilation.