Vectors Overview
WGSL supports 2-element, 3-element and 4-element vectors of scalar types.
Vectors are declared with the form vecN<T>, where N is the number of elements in the vector, and T is the element type.
| Vector Type | Description |
|---|---|
vec2<f32> |
A two-element vector of f32. |
vec3<u32> |
A three-element vector of u32. |
vec4<bool> |
A four-element vector of bool. |
WGSL also predeclares the aliases vecNS, where S is one of i, u or f:
vecNiis an alias tovecN<i32>vecNuis an alias tovecN<u32>vecNfis an alias tovecN<f32>
| Alias | Full Representation |
|---|---|
vec2f |
vec2<f32> (a two-element vector of f32) |
vec3u |
vec3<u32> (a three-element vector of u32) |
vec4i |
vec4<i32> (a four-element vector of i32) |
Vector Dimensionality Constraint
WGSL strictly limits vector dimensions to 2, 3, or 4 elements. This restriction reflects fundamental hardware and mathematical design constraints:
- GPU Register & Memory Alignment: Graphics hardware architectures are highly optimized for power-of-two memory layouts (such as 64-bit or 128-bit memory bus widths). A 2-element vector of 32-bit floats (
vec2f) takes 8 bytes, and a 4-element vector (vec4f) takes 16 bytes. A 5-element float vector would require 20 bytes, breaking power-of-two memory boundaries and complicating register packing, cache line alignment, and GPU memory bus utilization. - Graphics Pipeline Design: Shader vectors are designed to map directly to graphics concepts, such as homogeneous spatial coordinates \((x, y, z, w)\) or color channels with transparency \((r, g, b, a)\). There are no common graphics primitives or rendering pipeline operations that require 5-element or larger vectors.
- Alternative Containers: For collections of 5 or more components, you should use standard
array<T, N>types or define a customstructwith explicitly ordered fields. This allows the compiler to optimize the alignment and memory packing explicitly.
The Scalar-Only Constraint
The underlying element type T in the vector definition vecN<T> is strictly limited to constructible scalar types: f32, i32, u32, f16 (if enabled), and bool.
This restriction excludes other container or reference types:
- No Vectors of Vectors: You cannot nest vectors (such as
vec3<vec2f>). To represent multi-dimensional coordinate fields, use matrices (e.g.mat3x3f) or collections of vectors. - No Vectors of Pointers: You cannot construct a vector containing references or pointers (such as
vec4<ptr<private, f32>>). - Only Concrete Scalars: Vector elements must be standard scalar types (
f32,i32,u32,f16, orbool). WGSL lacks sub-16-bit scalar floats; see Basic Scalars for details on scalar precision limitations. - GPU Hardware Foundations: Because WGSL vectors map directly to physical hardware SIMD vector registers, they must hold uniform, raw, contiguous scalar values.
Vectors vs. Lists
WGSL vectors represent physical, short mathematical coordinate/color tuples. They do not represent dynamically-allocated heap collections like C++'s std::vector or Java's java.util.Vector. For dynamic or nested multi-dimensional elements, you must utilize matrices, fixed-size array<T, N> types, or custom struct definitions.
Next Steps
Vector operations and usage:
- Vector Constructors: Initialization forms including splat, element-wise, and type-inferring constructors.
- Components & Swizzling: Individual component access, spatial/color naming styles, and swizzling rules.
/*
* Copyright ©2026 Michael R. Bernstein. Licensed under Apache 2.0.
* See root README.md for global project-wide upstream attributions.
*/
// Demonstrates that vec2<f32> is fully equivalent to its short-hand alias vec2f.
fn a(v : vec2<f32>) {}
fn b(v : vec2f) {
a(v); // No conversion needed: vec2<f32> and vec2f are identical types
}
// Computes and returns a 2-element vector of 32-bit floating point values (f32)
fn test_vec2f() -> vec2f {
// vec2f is initialized with components (x = 1.5, y = 2.5)
let my_vector: vec2f = vec2f(1.5, 2.5);
b(my_vector);
return my_vector;
}
// Computes and returns a 3-element vector of unsigned 32-bit integers (u32)
fn test_vec3u() -> vec3u {
// vec3u is initialized with components (x = 10, y = 20, z = 30)
return vec3u(10u, 20u, 30u);
}
// Computes and returns a 4-element vector of signed 32-bit integers (i32)
fn test_vec4i() -> vec4i {
// vec4i is initialized with components (x = -1, y = 0, z = 1, w = 2)
return vec4i(-1, 0, 1, 2);
}