Local Variables
Local variables are mutable storage locations allocated within the scope of a function. They reside in the function address space, meaning they are allocated on the executing thread's local stack or register file and are strictly private to that specific thread invocation.
Syntax & Scoping
A local variable is declared inside a function body using the var keyword. The address space function can be explicitly specified, but because it is the implicit default for all function-scoped variables, it is typically omitted.
The following syntax templates are valid for local variables:
var<function> name: Type;
var<function> name = initializer;
var name: Type = initializer;
Technical Constraints & Rules
- Mutability: Local variables are fully mutable. Their values can be updated at runtime using the assignment operator (
=). - Implicit Default Address Space: Omitting the
<function>address space is the standard idiom in WGSL. Declaringvar x: i32is semantically identical tovar<function> x: i32. - Initialization & Zero-Initialization: If a local variable is declared without an initializer, the compiler automatically zero-initializes it according to its type (e.g.,
0for numeric types,falsefor booleans, or zeroed fields for structures). - Runtime Initializers: Unlike module-scope variables (such as private or workgroup variables), local variables can be initialized using any runtime-stage expression, including function parameters, dynamic mathematics, or other variable states.
- Thread-Isolation: Each executing shader thread (invocation) has its own separate instance of local variables. Modifying a local variable in one thread has no effect on any other executing thread.
- Evaluation Stage: Accessing or utilizing a local variable always produces a runtime-stage expression.
Reference Examples
The following example demonstrates explicit, implicit, and inferred local variable declarations within a function body:
fn perform_calculations(base_value: f32) -> f32 {
// 1. Explicit address space with zero-initialization
var<function> accumulator: f32; // Value is 0.0
// 2. Omitted address space with type inference
var scale_factor = 2.5; // Type is inferred as f32
// 3. Runtime-expression initialization
var initial_product: f32 = base_value * scale_factor;
// Mutating variables
accumulator = initial_product + 10.0;
accumulator = accumulator * 2.0;
return accumulator;
}
/*
* Copyright ©2026 Michael R. Bernstein. All new modifications licensed under Apache 2.0.
* Upstream lineage ©2023 governed by original BSD 3-Clause. See README.md.
*/
fn f() -> i32 {
// var 'i' of type 'i32' is initialized with a value of 10
var i : i32 = 10;
// var 'j' of type 'i32' is automatically zero initialized
var j : i32;
// var 'k' of inferred type 'i32' is initialized with the value of 'i + j'
var k = i + j;
// vars are mutable, so they can be reassigned with new values
k = k + 1;
return k;
}