Functions
Every function is a function of the module. There are no function values, no environment to close over and no call stack.
-
Shadowing a module value
A parameter or body local can use the name of a module value. Closures resolve the nearest declaration; duplicates in the same scope remain errors.
TypeScript const gain: f32 = 0.25;function scale(gain: f32): f32 { return gain * 2.; }export function answer(): f32 {const gain: f32 = 1.;return scale(gain);}Emitted WGSL fn scale(gain: f32) -> f32 {return (gain * 2.0);}fn answer() -> f32 {return scale(1.0);} -
Parameter reassignment
A local copy receives the input value. Reassigning it leaves the caller’s value unchanged.
TypeScript export function brighter(value: f32): f32 {value += 0.25;return value;}Emitted WGSL fn brighter(value: f32) -> f32 {var value_1: f32 = value;value_1 += 0.25;return value_1;} -
Top-level function
A module function of the same name, parameters and return type.
TypeScript export function lum(c: vec3): f32 {return dot(c, vec3(0.2126, 0.7152, 0.0722))}Emitted WGSL fn lum(c: vec3<f32>) -> f32 {return dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));} -
Local function
A function of the module, named after the function that declares it.
TypeScript export function ramp(x: f32): f32 {const twice = (v: f32): f32 => v * 2.return twice(x)}Emitted WGSL fn ramp_twice(v: f32) -> f32 {return (v * 2.0);}fn ramp(x: f32) -> f32 {return ramp_twice(x);} -
Closure over a name
The local function takes each name it reads from the function around it as a parameter, and a name it writes by reference.
TypeScript export function ramp(x: f32): f32 {const twice = (v: f32): f32 => v * xreturn twice(x)}Emitted WGSL fn ramp_twice(x: f32, v: f32) -> f32 {return (v * x);}fn ramp(x: f32) -> f32 {return ramp_twice(x, x);} -
Default argument
Every parameter stays, and the argument left out is written at the call. default-args
TypeScript function vignette(uv: vec2, strength: f32 = 0.8): f32 {return 1. - length(uv) * strength}Emitted WGSL fn vignette(uv: vec2<f32>, strength: f32) -> f32 {return (1.0 - (length(uv) * strength));}fn shade(uv: vec2<f32>) -> f32 {return vignette(uv, 0.8);} -
Overload signature
The signatures are skipped and the implementation is lowered once.
TypeScript export function lum(c: vec3): f32export function lum(c: vec3): f32 {return dot(c, vec3(0.2126, 0.7152, 0.0722))}Emitted WGSL fn lum(c: vec3<f32>) -> f32 {return dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));} -
Recursive call
RefusedWGSL has no call stack, and the check reads the call graph.
TypeScript export function fall(x: f32): f32 {return fall(x * 0.5)}Compiler diagnostic
TS8031 Recursive call: "fall" -> "fall". WGSL has no call stack, so a function must not take part in a call cycle.
-
Call as a statement
A statement of its own. A value-returning builtin standing alone computes nothing, so the optimizer drops it.
TypeScript @compute([64, 1, 1])export function main_k(@builtin("global_invocation_id") gid: vec3u): void {store(gid.x, 1.)}Emitted WGSL @compute @workgroup_size(64)fn main_k(@builtin(global_invocation_id) gid: vec3<u32>) {store(gid.x, 1.0);} -
Call with an effect
A builtin that returns a value and has an effect takes WGSL's phony assignment,
_ =, since Tint treats it as must-use. atomic-histogramTypeScript @compute([64, 1, 1])export function main_k(@builtin("global_invocation_id") gid: vec3u): void {atomicAdd(hits[gid.x], 1)}Emitted WGSL @compute @workgroup_size(64)fn main_k(@builtin(global_invocation_id) gid: vec3<u32>) {_ = atomicAdd(&hits[gid.x], 1u);} -
MathnamesMath.sinis the same builtin assin, andMath.PIfolds to its value.TypeScript export function wave(x: f32): f32 {return Math.sin(x * Math.PI)}Emitted WGSL fn wave(x: f32) -> f32 {return sin((x * 3.141592653589793));}