Control Flow
Demonstrates control-flow constructs: if/else if/else, break (including nested), explicit return statements, and match/switch with literal, or-patterns, and const patterns.
if_example
Demonstrates if statements: simple if, if/else, if/else if/else chains, and nested if.
Rust Source
#![allow(unused)]
fn main() {
#[wgsl]
#[allow(dead_code)]
pub mod if_example {
//! Demonstrates if statements including:
//! - Simple if
//! - if/else
//! - if/else if/else chains
//! - Nested if statements
use wgsl_rs::std::*;
#[fragment]
pub fn test_simple_if() -> Vec4f {
let mut result = 0.0;
if true {
result = 1.0;
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
pub fn test_if_else() -> Vec4f {
let mut result = 0.0;
if result < 1.0 {
result = 1.0;
} else {
result = 2.0;
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
#[allow(unused_assignments)]
pub fn test_if_else_if_else() -> Vec4f {
let x = 5;
let mut result = 0.0;
if x < 3 {
result = 1.0;
} else if x < 7 {
result = 2.0;
} else {
result = 3.0;
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
pub fn test_nested_if() -> Vec4f {
let x = 5;
let y = 10;
let mut result = 0.0;
if x > 0 {
if y > 5 {
result = 1.0;
} else {
result = 0.5;
}
}
vec4f(result, 0.0, 0.0, 1.0)
}
}
}
Generated WGSL
@fragment fn test_simple_if() -> @location(0) vec4f {
var result = 0.0;
if true {
result = 1.0;
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_if_else() -> @location(0) vec4f {
var result = 0.0;
if result < 1.0 {
result = 1.0;
} else {
result = 2.0;
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_if_else_if_else() -> @location(0) vec4f {
let x = 5;
var result = 0.0;
if x < 3 {
result = 1.0;
} else if x < 7 {
result = 2.0;
} else {
result = 3.0;
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_nested_if() -> @location(0) vec4f {
let x = 5;
let y = 10;
var result = 0.0;
if x > 0 {
if y > 5 {
result = 1.0;
} else {
result = 0.5;
}
}
return vec4f(result, 0.0, 0.0, 1.0);
}
break_example
Demonstrates break statements inside while loops, including conditional breaks and nested break.
Rust Source
#![allow(unused)]
fn main() {
#[wgsl]
#[allow(dead_code, unused_assignments)]
pub mod break_example {
use wgsl_rs::std::*;
#[fragment]
pub fn test_break_in_while() -> Vec4f {
let mut i = 0;
let mut sum = 0.0;
while i < 100 {
if i >= 10 {
break;
}
sum += f32(i);
i += 1;
}
vec4f(sum / 100.0, 0.0, 0.0, 1.0)
}
#[fragment]
pub fn test_break_with_condition() -> Vec4f {
let mut value = 1.0;
let mut iterations = 0;
while iterations < 100 {
value *= 1.1;
iterations += 1;
if value > 50.0 {
break;
}
}
vec4f(value / 100.0, f32(iterations) / 100.0, 0.0, 1.0)
}
#[fragment]
pub fn test_nested_break() -> Vec4f {
let mut i = 0;
let mut j = 0;
let mut found = 0;
while i < 10 {
j = 0;
while j < 10 {
if i * 10 + j == 55 {
found = 1;
break;
}
j += 1;
}
if found == 1 {
break;
}
i += 1;
}
vec4f(f32(i) / 10.0, f32(j) / 10.0, f32(found), 1.0)
}
}
}
Generated WGSL
@fragment fn test_break_in_while() -> @location(0) vec4f {
var i = 0;
var sum = 0.0;
while i < 100 {
if i >= 10 {
break;
}
sum += f32(i);
i += 1;
}
return vec4f(sum / 100.0, 0.0, 0.0, 1.0);
}
@fragment fn test_break_with_condition() -> @location(0) vec4f {
var value = 1.0;
var iterations = 0;
while iterations < 100 {
value *= 1.1;
iterations += 1;
if value > 50.0 {
break;
}
}
return vec4f(value / 100.0, f32(iterations) / 100.0, 0.0, 1.0);
}
@fragment fn test_nested_break() -> @location(0) vec4f {
var i = 0;
var j = 0;
var found = 0;
while i < 10 {
j = 0;
while j < 10 {
if i * 10 + j == 55 {
found = 1;
break;
}
j += 1;
}
if found == 1 {
break;
}
i += 1;
}
return vec4f(f32(i) / 10.0, f32(j) / 10.0, f32(found), 1.0);
}
return_example
Demonstrates explicit return statements: early returns, return with expressions, and mixed explicit/implicit returns.
Rust Source
#![allow(unused)]
fn main() {
#[wgsl]
#[allow(dead_code, clippy::needless_return, clippy::mixed_attributes_style)]
pub mod return_example {
//! Demonstrates explicit return statements including:
//! - Early returns from functions
//! - Return with expressions
//! - Mixed explicit and implicit returns
use wgsl_rs::std::*;
// Helper function with early return
pub fn clamp_positive(x: f32) -> f32 {
if x < 0.0 {
return 0.0;
}
return x;
}
// Function with multiple return paths
pub fn sign(x: f32) -> f32 {
if x > 0.0 {
return 1.0;
}
if x < 0.0 {
return -1.0;
}
return 0.0;
}
// Mixed explicit and implicit return
pub fn abs_or_zero(x: f32, threshold: f32) -> f32 {
if abs(x) < threshold {
return 0.0;
}
abs(x)
}
#[fragment]
pub fn test_explicit_returns() -> Vec4f {
let pos = clamp_positive(-5.0); // 0.0
let neg = clamp_positive(3.0); // 3.0
let s1 = sign(5.0); // 1.0
let s2 = sign(-2.0); // -1.0
let a1 = abs_or_zero(0.1, 0.5); // 0.0
let a2 = abs_or_zero(2.0, 0.5); // 2.0
vec4f(pos + neg / 10.0, s1 + s2, a1 + a2 / 10.0, 1.0)
}
}
}
Generated WGSL
fn clamp_positive(x: f32) -> f32 {
if x < 0.0 {
return 0.0;
}
return x;
}
fn sign(x: f32) -> f32 {
if x > 0.0 {
return 1.0;
}
if x < 0.0 {
return -1.0;
}
return 0.0;
}
fn abs_or_zero(x: f32, threshold: f32) -> f32 {
if abs(x) < threshold {
return 0.0;
}
return abs(x);
}
@fragment fn test_explicit_returns() -> @location(0) vec4f {
let pos = clamp_positive(-5.0);
let neg = clamp_positive(3.0);
let s1 = sign(5.0);
let s2 = sign(-2.0);
let a1 = abs_or_zero(0.1, 0.5);
let a2 = abs_or_zero(2.0, 0.5);
return vec4f(pos + neg / 10.0, s1 + s2, a1 + a2 / 10.0, 1.0);
}
switch_example
Demonstrates match/switch support: simple integer matching, or-patterns (multiple cases), default cases, auto-generated default when missing, and const patterns (with warning suppression).
Rust Source
#![allow(unused)]
fn main() {
#[wgsl]
#[allow(dead_code, unused_assignments)]
pub mod switch_example {
//! Demonstrates switch/match statement support including:
//! - Simple integer matching
//! - Or-patterns (multiple cases)
//! - Default cases
//! - Auto-generated default when missing
//! - Const patterns (with warning suppression)
use wgsl_rs::std::*;
const LOW: i32 = 0;
const MID: i32 = 1;
const HIGH: i32 = 2;
#[fragment]
pub fn test_simple_switch() -> Vec4f {
let x: i32 = 2;
let mut result = 0.0;
match x {
0 => {
result = 0.0;
}
1 => {
result = 0.25;
}
2 => {
result = 0.5;
}
_ => {
result = 1.0;
}
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
#[allow(clippy::manual_range_patterns)]
pub fn test_or_patterns() -> Vec4f {
let x: u32 = 5;
let mut result = 0.0;
match x {
1 | 2 | 3 => {
result = 0.25;
}
4 | 5 | 6 => {
result = 0.5;
}
_ => {
result = 1.0;
}
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
pub fn test_missing_default() -> Vec4f {
let x: i32 = 1;
let mut result = 0.0;
// No default arm - WGSL will get auto-generated `default: {}`
// But Rust requires exhaustive matching, so we use a catch-all underscore
// that will be optimized out in the test below
match x {
0 => {
result = 0.0;
}
1 => {
result = 1.0;
}
_ => {}
}
vec4f(result, 0.0, 0.0, 1.0)
}
#[fragment]
pub fn test_const_patterns() -> Vec4f {
let level: i32 = 1;
let mut brightness = 0.0;
#[wgsl_allow(non_literal_match_statement_patterns)]
match level {
LOW => {
brightness = 0.0;
}
MID => {
brightness = 0.5;
}
HIGH => {
brightness = 1.0;
}
_ => {
brightness = 0.0;
}
}
vec4f(brightness, 0.0, 0.0, 1.0)
}
}
}
Generated WGSL
const LOW: i32 = 0;
const MID: i32 = 1;
const HIGH: i32 = 2;
@fragment fn test_simple_switch() -> @location(0) vec4f {
let x: i32 = 2;
var result = 0.0;
switch x {
case 0: {
result = 0.0;
}
case 1: {
result = 0.25;
}
case 2: {
result = 0.5;
}
default: {
result = 1.0;
}
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_or_patterns() -> @location(0) vec4f {
let x: u32 = 5;
var result = 0.0;
switch x {
case 1, 2, 3: {
result = 0.25;
}
case 4, 5, 6: {
result = 0.5;
}
default: {
result = 1.0;
}
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_missing_default() -> @location(0) vec4f {
let x: i32 = 1;
var result = 0.0;
switch x {
case 0: {
result = 0.0;
}
case 1: {
result = 1.0;
}
default: {
}
}
return vec4f(result, 0.0, 0.0, 1.0);
}
@fragment fn test_const_patterns() -> @location(0) vec4f {
let level: i32 = 1;
var brightness = 0.0;
switch level {
case LOW: {
brightness = 0.0;
}
case MID: {
brightness = 0.5;
}
case HIGH: {
brightness = 1.0;
}
default: {
brightness = 0.0;
}
}
return vec4f(brightness, 0.0, 0.0, 1.0);
}
Notes
- Rust
matchbecomes WGSLswitch. The_arm maps todefault. - Or-patterns (
1 | 2 | 3) become comma-separated case selectors (case 1, 2, 3:). #[wgsl_allow(non_literal_match_statement_patterns)]is required when match arms referenceconstvalues rather than literals, since WGSL cases must be literals — the transpiler emits the const names directly (naga substitutes them).- A missing
defaultarm in Rust (with a_ => {}catch-all) emits an emptydefault: {}in WGSL.