| Type | Description |
|---|---|
bool | Boolean (true/false) |
int | Signed 32-bit integer |
uint | Unsigned 32-bit integer |
float | 32-bit floating point |
half | 16-bit floating point |
Vectors of 2-4 components: vec2, vec3, vec4 (float), ivec2-ivec4 (int), uvec2-uvec4 (uint), bvec2-bvec4 (bool).
Constructors:
let v = vec3(1.0, 2.0, 3.0)
let v2 = vec4(v, 1.0) -- expand vec3 to vec4
Swizzling (xyzw, rgba, stpq):
let xy = v.xy -- vec2
let zzz = v.zzz -- vec3
let r = color.r -- float
Square: mat2, mat3, mat4. Non-square: mat2x3, mat3x4, etc.
Matrix-vector multiplication uses *:
let clip = view_proj * model * vec4(pos, 1.0)
Fixed-size arrays: [N]T.
@group(0) @binding(0)
buffer lights: [16]Light
-- Access by index
let first = lights[0]
sampler2D represents a combined texture/sampler. During compilation, it is automatically split into separate texture and sampler bindings for backends that require it.
@group(1) @binding(0)
uniform tex: sampler2D
-- In shader body:
let color = sample(tex, uv)
let mipped = sample_level(tex, uv, 2.0)
struct MyStruct
field1: vec3
field2: float
end
struct VertexInput
@location(0) position: vec3
@location(1) normal: vec3
@builtin(vertex_index) vid: uint
end
@varying structs are shared between vertex output and fragment input. Fragment inputs automatically skip @builtin fields.
@varying
struct Interpolated
@builtin(position) position: vec4
@location(0) uv: vec2
end
function helper(a: vec3, b: vec3) -> float
return dot(a, b)
end
Functions cannot be recursive. All functions are inlined or statically dispatched.
vertex main
in position: vec3 @location(0)
in uv: vec2 @location(1)
out clip: vec4 @builtin(position)
out uv: vec2
do
clip = vec4(position, 1.0)
out.uv = uv
end
fragment shade
in uv: vec2
out color: vec4
do
return vec4(uv, 0.0, 1.0)
end
compute simulate @workgroup_size(64, 1, 1)
do
let i = work.global_id.x
-- write storage buffers/resources
end
return expr is only fragment single-output top-level sugar. Vertex stages use explicit out assignments. Compute stages do not return and cannot declare out slots.
Workflow output assignments can appear in control flow if every non-discard path definitely assigns every output before stage exit. Overwrites are allowed.
The older annotation syntax remains supported:
@entry(vertex)
function main(input: VertexInput) -> VertexOutput
-- ...
end
@entry(fragment)
function main(@location(0) uv: vec2) -> (color: vec4)
return vec4(uv, 0.0, 1.0)
end
let x = 1.0 -- immutable, type inferred
let y: float = 2.0 -- explicit type
Assignment requires mutable variables (loop variables, shared memory, buffer elements):
for i = 0, 10 do
shared_data[i] = float(i)
end
const PI = 3.14159
const MAX_LIGHTS: int = 16
@spec(0) const TILE_SIZE: int = 8
@spec(1) const USE_NORMAL_MAP: bool = true
group frame = 0
@binding(0) uniform camera: CameraData
end
group sim = 0
@binding(1) buffer particles: ParticleBuffer
end
group material = 1
@binding(0) texture diffuse: sampler2D
end
@group defaults to 0. @binding auto-increments within each group:
uniform a: TypeA -- group=0, binding=0
uniform b: TypeB -- group=0, binding=1
@group(1)
uniform c: sampler2D -- group=1, binding=0 (texture), binding=1 (sampler)
group material = 1
texture c: sampler2D
end
Workgroup-shared memory for compute shaders:
shared tile: [64]float
compute main @workgroup_size(64, 1, 1)
do
let idx = work.local_index
tile[idx] = float(idx)
barrier()
-- all threads can now read tile
end
if x > 0.0 then
-- ...
elseif x < 0.0 then
-- ...
else
-- ...
end
for i = 0, 10 do -- i goes from 0 to 9
-- ...
end
for i = 0, 100, 2 do -- step of 2
-- ...
end
while dist > 0.001 do
-- ...
end
| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, % |
| Comparison | ==, ~=, <, >, <=, >= |
| Logical | and, or, not |
| Unary | - (negate), not |
#include "common.luma"
Include paths are resolved relative to the source file and any --include-dir paths.
| Name | Type | Description |
|---|---|---|
position | vec4 | Clip-space position (output) |
vertex_index | uint | Vertex index (input) |
instance_index | uint | Instance index (input) |
| Name | Type | Description |
|---|---|---|
position | vec4 | Fragment coord (input) |
front_facing | bool | Front-facing (input) |
frag_depth | float | Depth override (output) |
| Name | Type | Description |
|---|---|---|
global_invocation_id | uvec3 | Global thread ID |
local_invocation_id | uvec3 | Local thread ID |
workgroup_id | uvec3 | Workgroup ID |
num_workgroups | uvec3 | Total workgroups |
local_invocation_index | uint | Flattened local index |