WGSL Builtin Functions and Values
Call the right WGSL builtin function and declare builtin input/output values with
the correct stage, direction, and type, without triggering shader-creation errors.
Quick Reference
WGSL is the shading language of WebGPU 1.0-stable (Chrome 113+, Safari 26+,
Firefox 141+). Builtin functions need no import. Builtin values bind to system
inputs/outputs via the @builtin(name) attribute on entry-point parameters and
return members.
Builtin function categories
| Category |
Functions |
| Math/numeric |
abs, clamp, min, max, floor, ceil, round, trunc, fract, sign, mix, step, smoothstep, saturate, fma, pow, sqrt, inverseSqrt, exp, exp2, log, log2, modf, frexp, ldexp, quantizeToF16 |
| Trigonometric |
sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh, degrees, radians |
| Geometric/vector |
dot, cross, length, distance, normalize, reflect, refract, faceForward |
| Matrix |
transpose, determinant |
| Integer/bit |
countOneBits, countLeadingZeros, countTrailingZeros, firstLeadingBit, firstTrailingBit, extractBits, insertBits, reverseBits, dot4U8Packed, dot4I8Packed |
| Pack/unpack |
pack4x8snorm, pack4x8unorm, pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, pack2x16snorm, pack2x16unorm, pack2x16float + unpack* inverses |
| Texture (fragment-restricted variants) |
textureSample, textureSampleBias, textureSampleCompare, textureGather, textureGatherCompare |
| Texture (any stage) |
textureSampleLevel, textureSampleGrad, textureSampleCompareLevel, textureLoad, textureStore, textureDimensions, textureNumLayers, textureNumLevels, textureNumSamples |
| Derivative (fragment only) |
dpdx, dpdy, fwidth + Coarse/Fine variants |
| Atomic (workgroup/storage memory) |
atomicLoad, atomicStore, atomicAdd, atomicSub, atomicMax, atomicMin, atomicAnd, atomicOr, atomicXor, atomicExchange, atomicCompareExchangeWeak |
| Synchronization (compute only) |
workgroupBarrier, storageBarrier, textureBarrier, workgroupUniformLoad |
| Array |
arrayLength |
Texture builtins are documented in detail in webgpu-wgsl-textures. Atomic and
synchronization builtins are documented in webgpu-wgsl-compute-shaders and
webgpu-wgsl-uniformity. This skill lists them and states their stage rule only.
Builtin values via @builtin(name)
| Builtin |
Stage |
Direction |
Type |
vertex_index |
vertex |
input |
u32 |
instance_index |
vertex |
input |
u32 |
position |
vertex |
output |
vec4<f32> |
position |
fragment |
input |
vec4<f32> |
clip_distances |
vertex |
output |
array<f32, N> |
front_facing |
fragment |
input |
bool |
frag_depth |
fragment |
output |
f32 |
sample_index |
fragment |
input |
u32 |
sample_mask |
fragment |
input/output |
u32 |
local_invocation_id |
compute |
input |
vec3<u32> |
local_invocation_index |
compute |
input |
u32 |
global_invocation_id |
compute |
input |
vec3<u32> |
workgroup_id |
compute |
input |
vec3<u32> |
num_workgroups |
compute |
input |
vec3<u32> |
subgroup_invocation_id |
compute/fragment |
input |
u32 |
subgroup_size |
compute/fragment |
input |
u32 |
clip_distances needs the clip-distances device feature. subgroup_invocation_id
and subgroup_size need the subgroups device feature plus enable subgroups; in
the shader. All other builtin values are core WGSL 1.0 with no feature gate.
Decision Tree
Need to read or sample a texture in WGSL?
├── Entry point is @fragment AND control flow is uniform?
│ └── textureSample / textureSampleBias / textureSampleCompare /
│ textureGather / textureGatherCompare (implicit-derivative builtins)
└── Entry point is @vertex or @compute, OR control flow is non-uniform?
└── textureSampleLevel (explicit LOD) / textureSampleGrad (explicit grad) /
textureLoad (no sampler) (no implicit derivative)
Need a screen-space derivative (dpdx / dpdy / fwidth)?
└── Legal ONLY in @fragment. NEVER call from @vertex or @compute.
Need to synchronize compute invocations (workgroupBarrier / storageBarrier)?
└── Legal ONLY in @compute, and ONLY in uniform control flow.
See webgpu-wgsl-uniformity.
Need an atomic operation (atomicAdd, atomicCompareExchangeWeak, ...)?
└── Pointer must target workgroup or storage memory with read_write access.
See webgpu-wgsl-compute-shaders.
Core Patterns
ALWAYS use textureSampleLevel or textureLoad outside the fragment stage
textureSample and the other implicit-derivative texture builtins compute the LOD
from screen-space derivatives. Derivatives exist ONLY in the fragment stage. In
@vertex or @compute, ALWAYS supply an explicit level with textureSampleLevel
or use textureLoad.
@compute @workgroup_size(8, 8)
fn cs(@builtin(global_invocation_id) gid : vec3u) {
let texel = textureLoad(src, vec2i(gid.xy), 0); // explicit mip level 0
}
ALWAYS mark integer builtin inputs that cross stages with @interpolate(flat)
Integer inter-stage values cannot be interpolated. A u32/i32 @location varying
ALWAYS needs @interpolate(flat) on both the vertex output and the fragment input,
or shader creation fails. Builtin values themselves are not user varyings, but values
derived from vertex_index/instance_index and passed via @location follow this
rule.
struct VSOut {
@builtin(position) clip_pos : vec4f,
@location(0) @interpolate(flat) material_id : u32,
}
ALWAYS treat instance_index as including the draw firstInstance base
@builtin(instance_index) includes the firstInstance argument of draw /
drawIndexed. To index a per-instance array from element 0, ALWAYS subtract the
known base, or set firstInstance to 0.
@vertex fn vs(@builtin(instance_index) ii : u32) -> @builtin(position) vec4f {
let xform = instances[ii]; // ii is already firstInstance + local index
...
}
NEVER write @builtin(frag_depth) unless the depth-stencil state writes depth
frag_depth is meaningful ONLY when the pipeline has a depthStencil state with
depthWriteEnabled: true. Writing frag_depth also disables early-Z: the GPU
cannot reject the fragment before running the shader.
ALWAYS use the const-evaluable builtins on const operands to fold at compile time
Math builtins (sqrt, pow, clamp, mix, etc.) const-evaluate when every
argument is a const-expression. This lets a const declaration hold a precomputed
value with zero runtime cost. Users cannot annotate their own functions as const.
NEVER call a synchronization builtin in divergent control flow
workgroupBarrier, storageBarrier, and textureBarrier ALWAYS run in uniform
control flow. Calling one inside an if whose condition varies per invocation is a
uniformity violation with undefined results. See webgpu-wgsl-uniformity.
Common Anti-Patterns
Calling textureSample or dpdx/dpdy/fwidth from a @vertex or @compute
entry point. WHY it fails: implicit derivatives do not exist outside the fragment
stage, so this is a shader-creation error. Use textureSampleLevel/textureLoad.
Indexing a per-instance buffer with instance_index while firstInstance is
non-zero. WHY it fails: instance_index includes the firstInstance base, so the
index runs past the array end and reads garbage or fails bounds-checking.
Writing @builtin(frag_depth) and expecting early depth rejection. WHY it fails:
any explicit frag_depth write forces the depth test after the fragment shader,
so early-Z is disabled and overdraw cost rises.
Critical Warnings
- NEVER call
textureSample, textureSampleBias, textureSampleCompare,
textureGather, or textureGatherCompare outside the fragment stage.
- NEVER call
dpdx, dpdy, fwidth, or their Coarse/Fine variants outside the
fragment stage.
- NEVER call
workgroupBarrier, storageBarrier, or textureBarrier outside the
compute stage or in non-uniform control flow.
- NEVER call
discard from a @vertex or @compute entry point; discard is a
fragment-stage statement.
- NEVER put
@location and @builtin on the same struct member or parameter.
- NEVER use a
subgroup_* builtin without the subgroups device feature and
enable subgroups;; NEVER use clip_distances without the clip-distances
feature.
- NEVER assume a builtin value is writable: only
position (vertex), frag_depth,
sample_mask, and clip_distances are outputs. All others are inputs.
Reference Files
references/methods.md : every builtin function by category and the complete
builtin-value table with stage, direction, and type.
references/examples.md : verified WGSL snippets using builtin functions and
builtin values across all three shader stages.
references/anti-patterns.md : builtin mistakes with WHY-it-fails explanations.
Related Skills
webgpu-wgsl-syntax : WGSL types, declarations, operators, control flow.
webgpu-wgsl-textures : texture and sampler handle types, full texture builtins.
webgpu-wgsl-uniformity : uniform control flow rules for derivatives and barriers.
webgpu-wgsl-compute-shaders : compute stage, atomics, workgroup memory.
1---2name: webgpu-wgsl-builtins3description: Use when calling WGSL builtin functions (math, geometric, integer, pack) or declaring builtin input and output values in shaders. Prevents shader-creation errors from stage-restricted builtins and wrong builtin value types. Covers WGSL builtin functions by category and the builtin values per shader stage with their direction and type. Keywords: WGSL builtin, dot, cross, normalize, mix, clamp, pow, atomicAdd, dpdx, pack4x8unorm, builtin position, global_invocation_id, vertex_index, builtin value, what WGSL functions are available.4license: MIT5---67# WGSL Builtin Functions and Values89Call the right WGSL builtin function and declare builtin input/output values with10the correct stage, direction, and type, without triggering shader-creation errors.1112## Quick Reference1314WGSL is the shading language of WebGPU 1.0-stable (Chrome 113+, Safari 26+,15Firefox 141+). Builtin functions need no import. Builtin values bind to system16inputs/outputs via the `@builtin(name)` attribute on entry-point parameters and17return members.1819### Builtin function categories2021| Category | Functions |22|----------|-----------|23| Math/numeric | `abs`, `clamp`, `min`, `max`, `floor`, `ceil`, `round`, `trunc`, `fract`, `sign`, `mix`, `step`, `smoothstep`, `saturate`, `fma`, `pow`, `sqrt`, `inverseSqrt`, `exp`, `exp2`, `log`, `log2`, `modf`, `frexp`, `ldexp`, `quantizeToF16` |24| Trigonometric | `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `degrees`, `radians` |25| Geometric/vector | `dot`, `cross`, `length`, `distance`, `normalize`, `reflect`, `refract`, `faceForward` |26| Matrix | `transpose`, `determinant` |27| Integer/bit | `countOneBits`, `countLeadingZeros`, `countTrailingZeros`, `firstLeadingBit`, `firstTrailingBit`, `extractBits`, `insertBits`, `reverseBits`, `dot4U8Packed`, `dot4I8Packed` |28| Pack/unpack | `pack4x8snorm`, `pack4x8unorm`, `pack4xI8`, `pack4xU8`, `pack4xI8Clamp`, `pack4xU8Clamp`, `pack2x16snorm`, `pack2x16unorm`, `pack2x16float` + `unpack*` inverses |29| Texture (fragment-restricted variants) | `textureSample`, `textureSampleBias`, `textureSampleCompare`, `textureGather`, `textureGatherCompare` |30| Texture (any stage) | `textureSampleLevel`, `textureSampleGrad`, `textureSampleCompareLevel`, `textureLoad`, `textureStore`, `textureDimensions`, `textureNumLayers`, `textureNumLevels`, `textureNumSamples` |31| Derivative (fragment only) | `dpdx`, `dpdy`, `fwidth` + `Coarse`/`Fine` variants |32| Atomic (workgroup/storage memory) | `atomicLoad`, `atomicStore`, `atomicAdd`, `atomicSub`, `atomicMax`, `atomicMin`, `atomicAnd`, `atomicOr`, `atomicXor`, `atomicExchange`, `atomicCompareExchangeWeak` |33| Synchronization (compute only) | `workgroupBarrier`, `storageBarrier`, `textureBarrier`, `workgroupUniformLoad` |34| Array | `arrayLength` |3536Texture builtins are documented in detail in `webgpu-wgsl-textures`. Atomic and37synchronization builtins are documented in `webgpu-wgsl-compute-shaders` and38`webgpu-wgsl-uniformity`. This skill lists them and states their stage rule only.3940### Builtin values via @builtin(name)4142| Builtin | Stage | Direction | Type |43|---------|-------|-----------|------|44| `vertex_index` | vertex | input | `u32` |45| `instance_index` | vertex | input | `u32` |46| `position` | vertex | output | `vec4<f32>` |47| `position` | fragment | input | `vec4<f32>` |48| `clip_distances` | vertex | output | `array<f32, N>` |49| `front_facing` | fragment | input | `bool` |50| `frag_depth` | fragment | output | `f32` |51| `sample_index` | fragment | input | `u32` |52| `sample_mask` | fragment | input/output | `u32` |53| `local_invocation_id` | compute | input | `vec3<u32>` |54| `local_invocation_index` | compute | input | `u32` |55| `global_invocation_id` | compute | input | `vec3<u32>` |56| `workgroup_id` | compute | input | `vec3<u32>` |57| `num_workgroups` | compute | input | `vec3<u32>` |58| `subgroup_invocation_id` | compute/fragment | input | `u32` |59| `subgroup_size` | compute/fragment | input | `u32` |6061`clip_distances` needs the `clip-distances` device feature. `subgroup_invocation_id`62and `subgroup_size` need the `subgroups` device feature plus `enable subgroups;` in63the shader. All other builtin values are core WGSL 1.0 with no feature gate.6465## Decision Tree6667```68Need to read or sample a texture in WGSL?69├── Entry point is @fragment AND control flow is uniform?70│ └── textureSample / textureSampleBias / textureSampleCompare /71│ textureGather / textureGatherCompare (implicit-derivative builtins)72└── Entry point is @vertex or @compute, OR control flow is non-uniform?73 └── textureSampleLevel (explicit LOD) / textureSampleGrad (explicit grad) /74 textureLoad (no sampler) (no implicit derivative)7576Need a screen-space derivative (dpdx / dpdy / fwidth)?77└── Legal ONLY in @fragment. NEVER call from @vertex or @compute.7879Need to synchronize compute invocations (workgroupBarrier / storageBarrier)?80└── Legal ONLY in @compute, and ONLY in uniform control flow.81 See webgpu-wgsl-uniformity.8283Need an atomic operation (atomicAdd, atomicCompareExchangeWeak, ...)?84└── Pointer must target workgroup or storage memory with read_write access.85 See webgpu-wgsl-compute-shaders.86```8788## Core Patterns8990### ALWAYS use textureSampleLevel or textureLoad outside the fragment stage9192`textureSample` and the other implicit-derivative texture builtins compute the LOD93from screen-space derivatives. Derivatives exist ONLY in the fragment stage. In94`@vertex` or `@compute`, ALWAYS supply an explicit level with `textureSampleLevel`95or use `textureLoad`.9697```wgsl98@compute @workgroup_size(8, 8)99fn cs(@builtin(global_invocation_id) gid : vec3u) {100 let texel = textureLoad(src, vec2i(gid.xy), 0); // explicit mip level 0101}102```103104### ALWAYS mark integer builtin inputs that cross stages with @interpolate(flat)105106Integer inter-stage values cannot be interpolated. A `u32`/`i32` `@location` varying107ALWAYS needs `@interpolate(flat)` on both the vertex output and the fragment input,108or shader creation fails. Builtin values themselves are not user varyings, but values109derived from `vertex_index`/`instance_index` and passed via `@location` follow this110rule.111112```wgsl113struct VSOut {114 @builtin(position) clip_pos : vec4f,115 @location(0) @interpolate(flat) material_id : u32,116}117```118119### ALWAYS treat instance_index as including the draw firstInstance base120121`@builtin(instance_index)` includes the `firstInstance` argument of `draw` /122`drawIndexed`. To index a per-instance array from element 0, ALWAYS subtract the123known base, or set `firstInstance` to 0.124125```wgsl126@vertex fn vs(@builtin(instance_index) ii : u32) -> @builtin(position) vec4f {127 let xform = instances[ii]; // ii is already firstInstance + local index128 ...129}130```131132### NEVER write @builtin(frag_depth) unless the depth-stencil state writes depth133134`frag_depth` is meaningful ONLY when the pipeline has a `depthStencil` state with135`depthWriteEnabled: true`. Writing `frag_depth` also disables early-Z: the GPU136cannot reject the fragment before running the shader.137138### ALWAYS use the const-evaluable builtins on const operands to fold at compile time139140Math builtins (`sqrt`, `pow`, `clamp`, `mix`, etc.) const-evaluate when every141argument is a const-expression. This lets a `const` declaration hold a precomputed142value with zero runtime cost. Users cannot annotate their own functions as const.143144### NEVER call a synchronization builtin in divergent control flow145146`workgroupBarrier`, `storageBarrier`, and `textureBarrier` ALWAYS run in uniform147control flow. Calling one inside an `if` whose condition varies per invocation is a148uniformity violation with undefined results. See `webgpu-wgsl-uniformity`.149150## Common Anti-Patterns1511521. Calling `textureSample` or `dpdx`/`dpdy`/`fwidth` from a `@vertex` or `@compute`153 entry point. WHY it fails: implicit derivatives do not exist outside the fragment154 stage, so this is a shader-creation error. Use `textureSampleLevel`/`textureLoad`.1551562. Indexing a per-instance buffer with `instance_index` while `firstInstance` is157 non-zero. WHY it fails: `instance_index` includes the `firstInstance` base, so the158 index runs past the array end and reads garbage or fails bounds-checking.1591603. Writing `@builtin(frag_depth)` and expecting early depth rejection. WHY it fails:161 any explicit `frag_depth` write forces the depth test after the fragment shader,162 so early-Z is disabled and overdraw cost rises.163164## Critical Warnings165166- NEVER call `textureSample`, `textureSampleBias`, `textureSampleCompare`,167 `textureGather`, or `textureGatherCompare` outside the fragment stage.168- NEVER call `dpdx`, `dpdy`, `fwidth`, or their `Coarse`/`Fine` variants outside the169 fragment stage.170- NEVER call `workgroupBarrier`, `storageBarrier`, or `textureBarrier` outside the171 compute stage or in non-uniform control flow.172- NEVER call `discard` from a `@vertex` or `@compute` entry point; `discard` is a173 fragment-stage statement.174- NEVER put `@location` and `@builtin` on the same struct member or parameter.175- NEVER use a `subgroup_*` builtin without the `subgroups` device feature and176 `enable subgroups;`; NEVER use `clip_distances` without the `clip-distances`177 feature.178- NEVER assume a builtin value is writable: only `position` (vertex), `frag_depth`,179 `sample_mask`, and `clip_distances` are outputs. All others are inputs.180181## Reference Files182183- `references/methods.md` : every builtin function by category and the complete184 builtin-value table with stage, direction, and type.185- `references/examples.md` : verified WGSL snippets using builtin functions and186 builtin values across all three shader stages.187- `references/anti-patterns.md` : builtin mistakes with WHY-it-fails explanations.188189## Related Skills190191- `webgpu-wgsl-syntax` : WGSL types, declarations, operators, control flow.192- `webgpu-wgsl-textures` : texture and sampler handle types, full texture builtins.193- `webgpu-wgsl-uniformity` : uniform control flow rules for derivatives and barriers.194- `webgpu-wgsl-compute-shaders` : compute stage, atomics, workgroup memory.