SPIR-V Compatibility Types
In addition to arrays, Wyn provides vector types that directly correspond to SPIR-V/GLSL types. These are distinct types optimized for GPU operations and are required for certain shader interfaces and built-in variables.
Vector Types
Wyn supports vector types using the naming convention vecNT where:
Nis the number of components (2, 3, or 4)Tis the element type (i32, f32, etc.)
Common vector types:
| Component Type | 2-component | 3-component | 4-component |
|---|---|---|---|
i32 (signed) | vec2i32 | vec3i32 | vec4i32 |
f32 (32-bit float) | vec2f32 | vec3f32 | vec4f32 |
Vector types are distinct from array types and have different semantics:
- Vectors are fixed-size, optimized for SIMD operations
- Arrays are more general containers with runtime length operations
Example usage:
-- Vector types for graphics operations (using @[...] literal syntax)
let position: vec3f32 = @[1.0, 2.0, 3.0]
let color: vec4f32 = @[1.0, 0.0, 0.0, 1.0]
-- Alternative: explicit constructor syntax
let pos2: vec3f32 = vec3 1.0f32 2.0f32 3.0f32
-- Built-in variables often require vector types
#[vertex]
entry vertex_main() #[builtin(position)] vec4f32 =
@[0.0, 0.0, 0.0, 1.0]
Vector Swizzles
A vector’s components are accessed with field syntax (v.x). Wyn
supports WGSL-style swizzles: one to four letters drawn from a single
“swizzle set”. The two sets and their component indices are:
| Set | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| xyzw | x | y | z | w |
| rgba | r | g | b | a |
rgba is an alias set for xyzw (r == x, g == y, b == z,
a == w) — the two sets address the same underlying components and
produce identical values. Mixing letters from the two sets in one
swizzle (.xg, .rbw) is a type error.
A single-letter swizzle produces the scalar component; a 2-, 3-, or 4-letter swizzle produces a new vector of that length. Letters may repeat and may be in any order.
Each referenced component must lie within the source vector’s length —
.z (or .b) on a vec2 is a type error.
let v: vec4f32 = @[1.0, 2.0, 3.0, 4.0]
let first: f32 = v.x -- 1.0
let alpha: f32 = v.a -- 4.0 (same as v.w)
let rgb: vec3f32 = v.rgb -- (1.0, 2.0, 3.0)
let rev: vec4f32 = v.wzyx -- (4.0, 3.0, 2.0, 1.0)
let splat: vec3f32 = v.xxx -- (1.0, 1.0, 1.0)
Vector Constructors
Vectors can be constructed in two ways:
1. Literal syntax (@[...]) - Preferred for most cases:
let v1: vec3f32 = @[1.0, 2.0, 3.0]
let v2: vec4f32 = @[1.0, 0.0, 0.0, 1.0]
2. Explicit constructor syntax (vecN) - Useful when type suffix is needed:
let v1: vec3f32 = vec3 1.0f32 2.0f32 3.0f32
let v2: vec4f32 = vec4 1.0f32 2.0f32 3.0f32 4.0f32
The element type is inferred from the arguments or the context.
Implementation Details
- Attributes are parsed directly into SPIR-V enum values for type safety
- Built-in names follow SPIR-V specification (e.g.,
VertexIndex,Position) - Location numbers must be non-negative integers
- Each shader stage has specific allowed built-ins
- The compiler automatically generates appropriate SPIR-V decorations
Type Safety
The attribute system is statically type-checked:
- Built-in attributes must be applied to compatible types
- Location attributes can be used with any serializable type
- Shader stage compatibility is verified at compile time
- Interface matching between vertex and fragment shaders is validated