Skip to content

Syntax

Functions in WGSL are declared using the fn keyword. Each function must explicitly specify its parameters and return type if it yields a value.


Function Signature Template

A user-defined function has the following structure:

fn name(parameters) -> return_type { body }

  • name is the unique identifier of the function (e.g., average).
  • parameters is a comma-separated list of inputs in the form identifier : type.
  • return_type is the explicit type of the value the function returns.
  • body is the enclosed block of statements executing the subroutine.

Zero Implicit Coercion (Strict Type Matching)

WGSL enforces strict typing with absolutely no implicit type conversion. When calling a function, the arguments you pass must exactly match the declared types of the parameters.

Strict Type Matching

If a parameter is declared as f32, passing an integer literal like 5 or an i32 variable will result in a compile-time error. You must explicitly cast the value: e.g., 5.0 or f32(my_int).


Implicit Parameter Immutability (Read-Only)

All function parameters in WGSL are implicitly read-only. You cannot re-assign or modify the value of a parameter variable within the function body. If you need a mutable copy, you must explicitly declare a local variable using var and copy the parameter into it.

fn square_and_add(val : f32) -> f32 {
  // val = val * val; // COMPILE ERROR: cannot assign to parameter 'val'
  var local_val = val;
  local_val = local_val * local_val; // OK
  return local_val + 1.0;
}

GPU-Specific Type Restrictions

To maintain deterministic execution on GPU hardware, WGSL places strict restrictions on what types can be passed to or returned from user-defined functions:

  • No Textures or Samplers as Parameters: Unlike GLSL or HLSL, you cannot pass texture or sampler variables as parameters into user-defined functions. They must instead be accessed as global variables.
  • Constructible Return Types Only: A user-defined function can only return constructible types (such as scalars, vectors, matrices, arrays, and structs). Pointers, textures, and samplers are not constructible and cannot be returned.

Declaring Void Functions (No Return Value)

If a function does not return a value, the arrow -> and return type are completely omitted from the signature:

Example: Function returning nothing
fn print_or_store_value(val : f32) {
  // Perform side effects, e.g., updating storage or handle
  // No return statement is needed
}

Declaring Returning Functions

Functions that return a value specify the type after the parameter list and must terminate all code paths with a matching return statement:

Example: Calculating an average
fn average(a : f32, b : f32) -> f32 {
  return (a + b) / 2.0;
}

Use the playground to see these functions compile and return values in real-time.