# webgpufundamentals.org

Fix, Fork, Contribute

# WGSL Function Reference

## Bit Reinterpretation Built-in Functions

FunctionParameter TypesDescription
` fn bitcast<T>(e : T) -> T `
T is a concrete numeric scalar or concrete numeric vector Identity transform.
Component-wise when `T` is a vector.
The result is `e`.
` fn bitcast<T>(e : S) -> T `
S is i32, u32, or f32 T is not S and is i32, u32, or f32 Reinterpretation of bits as `T`.
The result is the reintepretation of bits in `e` as a `T` value.
` fn bitcast<vecN<T>>(e : vecN<S>) -> T `
S is i32, u32, or f32 T is not S and is i32, u32, or f32 Component-wise reinterpretation of bits as `T`.
The result is the reintepretation of bits in `e` as a `vecN<T>` value.
` fn bitcast<T>(e : vec2<f16>) -> T `
T is i32, u32, or f32 Component-wise reinterpretation of bits as `T`.
The result is the reintepretation of the 32 bits in `e` as a `T` value, following the internal layout rules.
` fn bitcast<vec2<T>>(e : vec4<f16>) -> vec2<T> `
T is i32, u32, or f32 Component-wise reinterpretation of bits as `T`.
The result is the reintepretation of the 64 bits in `e` as a `T` value, following the internal layout rules.
` fn bitcast<vec2<f16>>(e : T) -> vec2<f16> `
T is i32, u32, or f32 Component-wise reinterpretation of bits as f16.
The result is the reintepretation of the 32 bits in `e` as an f16 value, following the internal layout rules.
` fn bitcast<vec4<f16>>(e : vec2<T>) -> vec4<f16> `
T is i32, u32, or f32 Component-wise reinterpretation of bits as `vec2<f16>`.
The result is the reintepretation of the 64 bits in `e` as an f16 value, following the internal layout rules.

## Logical Built-in Functions

FunctionParameter TypesDescription
` fn all(e: vecN<bool>) -> bool `
Returns true if each component of `e` is true.
` fn all(e: bool) -> bool `
Returns `e`.
` fn any(e: vecN<bool>) -> bool `
Returns true if any component of `e` is true.
` fn any(e: bool) -> bool `
Returns `e`.
` fn select(f: T, t: T, cond: bool) -> T `
T is scalar or vector Returns `t` when `cond` is true, and `f` otherwise.
` fn select(f: vecN<T>, t: vecN<T>, cond: vecN<bool>) -> vecN<T> `
T is scalar Component-wise selection. Result component `i` is evaluated as `select(f[i], t[i], cond[i])`.

## Array Built-in Functions

FunctionParameter TypesDescription
` fn arrayLength(p: ptr<storage, array<E>, AM>) -> u32 `
E is an element type for a runtime-sized array, access mode AM is read or read_write Returns NRuntime, the number of elements in the runtime-sized array.

See § 10.3.4 Buffer Binding Determines Runtime-Sized Array Element Count

## Numeric Built-in Functions

FunctionParameter TypesDescription
` fn abs(e: T ) -> T `
S is AbstractInt, AbstractFloat, i32, u32, f32, or f16T is S, or vecN<S> The absolute value of `e`. Component-wise when `T` is a vector.

If `e` is a floating-point type, then the result is `e` with a positive sign bit. If `e` is an unsigned integer scalar type, then the result is `e`. If `e` is a signed integer scalar type and evaluates to the largest negative value, then the result is `e`.

` fn acos(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful when `abs(e)` > 1.

` fn acosh(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful when `e` < 1.

` fn asin(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful when `abs(e)` > 1.

` fn asinh(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the inverse hyperbolic sine (sinh-1) of `e`, as a hyperbolic angle in radians.
That is, approximates `x` such that `sinh`(`x`) = `e`.

Component-wise when `T` is a vector.

` fn atan(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the principal value, in radians, of the inverse tangent (tan-1) of `e`.
That is, approximates `x` with π/2 ≤ `x` ≤ π/2, such that `tan`(`x`) = `e`.

Component-wise when `T` is a vector.

` fn atanh(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful when `abs(e)` ≥ 1.

` fn atan2(y: T, x: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns an angle, in radians, in the interval [-π, π] whose tangent is `y`÷`x`.

The quadrant selected by the result depends on the signs of `y` and `x`. For example, the function may be implemented as:

• `atan(y/x)` when `x` > 0

• `atan(y/x)` + π when (`x` < 0) and (`y` > 0)

• `atan(y/x)` - π when (`x` < 0) and (`y` < 0)

Note: atan2 is ill-defined when `y/x` is ill-defined, at the origin (`x`,`y`) = (0,0), and when `y` is non-normal or infinite.

Component-wise when `T` is a vector.

` fn ceil(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the ceiling of `e`. Component-wise when `T` is a vector.
` fn clamp(e: T, low: T, high: T) -> T `
S is AbstractInt, AbstractFloat, i32, u32, f32, or f16T is S, or vecN<S> Restricts the value of `e` within a range.

If `T` is an integer type, then the result is `min(max(e, low), high)`.

If `T` is a floating-point type, then the result is either `min(max(e, low), high)`, or the median of the three values `e`, `low`, `high`.

Component-wise when `T` is a vector.

If `low` is greater than `high`, then:

• It is a shader-creation error if `low` and `high` are const-expressions.

• It is a pipeline-creation error if `low` and `high` are override-expressions.

` fn cos(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the cosine of `e`, where `e` is in radians. Component-wise when `T` is a vector.
` fn cosh(arg: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the hyperbolic cosine of `arg`, where `arg` is a hyperbolic angle in radians. Approximates the pure mathematical function (earg + e−arg)÷2, but not necessarily computed that way.

Component-wise when `T` is a vector

` fn countLeadingZeros(e: T) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> The number of consecutive 0 bits starting from the most significant bit of `e`, when `T` is a scalar type.
Component-wise when `T` is a vector.
Also known as "clz" in some languages.
` fn countOneBits(e: T) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> The number of 1 bits in the representation of `e`.
Also known as "population count".
Component-wise when `T` is a vector.
` fn countTrailingZeros(e: T) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> The number of consecutive 0 bits starting from the least significant bit of `e`, when `T` is a scalar type.
Component-wise when `T` is a vector.
Also known as "ctz" in some languages.
` fn cross(e1: vec3<T>, e2: vec3<T>) -> vec3<T> `
T is AbstractFloat, f32, or f16 Returns the cross product of `e1` and `e2`.
` fn degrees(e1: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Converts radians to degrees, approximating `e1` × 180 ÷ π. Component-wise when `T` is a vector
` fn determinant(e: matCxC<T>) -> T `
T is AbstractFloat, f32, or f16 Returns the determinant of `e`.
` fn distance(e1: T, e2: T) -> S `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the distance between `e1` and `e2` (e.g. `length(e1 - e2)`).
` fn dot(e1: vecN<T>, e2: vecN<T>) -> T `
T is AbstractInt, AbstractFloat, i32, u32, f32, or f16 Returns the dot product of `e1` and `e2`.
` fn exp(e1: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the natural exponentiation of `e1` (e.g. `e``e1`). Component-wise when `T` is a vector.
` fn exp2(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns 2 raised to the power `e` (e.g. `2``e`). Component-wise when `T` is a vector.
` fn extractBits(e: T, offset: u32, count: u32) -> T `
T is i32 or vecN<i32> Reads bits from an integer, with sign extension.

When `T` is a scalar type, then:

• `w` is the bit width of `T`
• `o = min(offset, w)`
• `c = min(count, w - o)`
• The result is 0 if `c` is 0.
• Otherwise, bits `0..c - 1` of the result are copied from bits `o..o + c - 1` of `e`. Other bits of the result are the same as bit `c - 1` of the result.
Component-wise when `T` is a vector.

If `count` + `offset` is greater than `w`, then:

• It is a shader-creation error if `count` and `offset` are const-expressions.

• It is a pipeline-creation error if `count` and `offset` are override-expressions.

` fn extractBits(e: T, offset: u32, count: u32) -> T `
T is u32 or vecN<u32> Reads bits from an integer, without sign extension.

When `T` is a scalar type, then:

• `w` is the bit width of `T`
• `o = min(offset, w)`
• `c = min(count, w - o)`
• The result is 0 if `c` is 0.
• Otherwise, bits `0..c - 1` of the result are copied from bits `o..o + c - 1` of `e`. Other bits of the result are 0.
Component-wise when `T` is a vector.

If `count` + `offset` is greater than `w`, then:

• It is a shader-creation error if `count` and `offset` are const-expressions.

• It is a pipeline-creation error if `count` and `offset` are override-expressions.

` fn faceForward(e1: T, e2: T, e3: T) -> T `
T is vecN<AbstractFloat>, vecN<f32>, or vecN<f16> Returns `e1` if `dot(e2, e3)` is negative, and `-e1` otherwise.
` fn firstLeadingBit(e: T) -> T `
T is i32 or vecN<i32>

Note: Since signed integers use twos-complement representation, the sign bit appears in the most significant bit position.

` fn firstLeadingBit(e: T) -> T `
T is u32 or vecN<u32> For scalar `T`, the result is:
• `T(-1)` if `e` is zero.
• Otherwise the position of the most significant 1 bit in `e`.
Component-wise when `T` is a vector.
` fn firstTrailingBit(e: T) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> For scalar `T`, the result is:
• `T(-1)` if `e` is zero.
• Otherwise the position of the least significant 1 bit in `e`.
Component-wise when `T` is a vector.
` fn floor(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the floor of `e`. Component-wise when `T` is a vector.
` fn fma(e1: T, e2: T, e3: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns `e1 * e2 + e3`. Component-wise when `T` is a vector.

Note: The name `fma` is short for "fused multiply add".

Note: The IEEE-754 `fusedMultiplyAdd` operation computes the intermediate results as if with unbounded range and precision, and only the final result is rounded to the destination type. However, the § 14.6.1 Floating Point Accuracy rule for `fma` allows an implementation which performs an ordinary multiply to the target type followed by an ordinary addition. In this case the intermediate values may overflow or lose accuracy, and the overall operation is not "fused" at all.

` fn fract(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: Valid results are in the closed interval [0, 1.0]. For example, if `e` is a very small negative number, then `fract(e)` may be 1.0.

` fn frexp(e: T) -> __frexp_result_f32 `
T is f32

Note: A value cannot be explicitly declared with the type `__frexp_result_f32`, but a value may infer the type.

` fn frexp(e: T) -> __frexp_result_f16 `
T is f16

Note: A value cannot be explicitly declared with the type `__frexp_result_f16`, but a value may infer the type.

` fn frexp(e: T) -> __frexp_result_abstract `
T is AbstractFloat

Note: A value cannot be explicitly declared with the type `__frexp_result_abstract`, but a value may infer the type.

` fn frexp(e: T) -> __frexp_result_vecN_f32 `
T is vecN<f32>

Note: A value cannot be explicitly declared with the type `__frexp_result_vecN_f32`, but a value may infer the type.

` fn frexp(e: T) -> __frexp_result_vecN_f16 `
T is vecN<f16>

Note: A value cannot be explicitly declared with the type `__frexp_result_vecN_f16`, but a value may infer the type.

` fn frexp(e: T) -> __frexp_result_vecN_abstract `
T is vecN<AbstractFloat>

Note: A value cannot be explicitly declared with the type `__frexp_result_vecN_abstract`, but a value may infer the type.

` fn insertBits(e: T, newbits: T, offset: u32, count: u32) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> Sets bits in an integer.

When `T` is a scalar type, then:

• `w` is the bit width of `T`
• `o = min(offset, w)`
• `c = min(count, w - o)`
• The result is `e` if `c` is 0.
• Otherwise, bits `o..o + c - 1` of the result are copied from bits `0..c - 1` of `newbits`. Other bits of the result are copied from `e`.
Component-wise when `T` is a vector.

If `count` + `offset` is greater than `w`, then:

• It is a shader-creation error if `count` and `offset` are const-expressions.

• It is a pipeline-creation error if `count` and `offset` are override-expressions.

` fn inverseSqrt(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful if `e` ≤ 0.

` fn ldexp(e1: T, e2: I) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> I is AbstractInt, i32, vecN<AbstractInt>, or vecN<i32> I is a vector if and only if T is a vector I is concrete if and only if T is a concrete Returns `e1 * 2``e2`, except:
• The result may be zero if `e2` + bias ≤ 0.

• If `e2` > bias + 1

• It is a shader-creation error if `e2` is a const-expression.

• It is a pipeline-creation error if `e2` is an override-expression.

• Otherwise the result is an indeterminate value for `T`.

Here, bias is the exponent bias of the floating point format:

• 15 for `f16`

• 127 for `f32`

• 1023 for AbstractFloat, when AbstractFloat is IEEE-754 binary64

If `x` is zero or a finite normal value for its type, then:

x = ldexp(frexp(x).fract, frexp(x).exp)

Component-wise when `T` is a vector.

Note: A mnemonic for the name `ldexp` is "load exponent". The name may have been taken from the corresponding instruction in the floating point unit of the PDP-11.

` fn length(e: T) -> S `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the length of `e`.
Evaluates to the absolute value of `e` if `T` is scalar.
Evaluates to `sqrt(e``2` `+ e``2` `+ ...)` if `T` is a vector type.

Note: The scalar case may be evaluated as `sqrt(e * e)`, which may unnecessarily overflow or lose accuracy.

` fn log(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful if `e` < 0.

` fn log2(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S>

Note: The result is not mathematically meaningful if `e` < 0.

` fn max(e1: T, e2: T) -> T `
S is AbstractInt, AbstractFloat, i32, u32, f32, or f16T is S, or vecN<S> Returns `e2` if `e1` is less than `e2`, and `e1` otherwise. Component-wise when `T` is a vector.

If `e1` and `e2` are floating-point values, then:

• If both `e1` and `e2` are denormalized, then the result may be either value.

• If one operand is a NaN, the other is returned.

• If both operands are NaNs, a NaN is returned.

` fn min(e1: T, e2: T) -> T `
S is AbstractInt, AbstractFloat, i32, u32, f32, or f16T is S, or vecN<S> Returns `e2` if `e2` is less than `e1`, and `e1` otherwise. Component-wise when `T` is a vector.

If `e1` and `e2` are floating-point values, then:

• If both `e1` and `e2` are denormalized, then the result may be either value.

• If one operand is a NaN, the other is returned.

• If both operands are NaNs, a NaN is returned.

` fn mix(e1: T, e2: T, e3: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the linear blend of `e1` and `e2` (e.g. `e1 * (1 - e3) + e2 * e3`). Component-wise when `T` is a vector.
` fn mix(e1: T2, e2: T2, e3: T) -> T2 `
T is AbstractFloat, f32, or f16 T2 is vecN<T> Returns the component-wise linear blend of `e1` and `e2`, using scalar blending factor `e3` for each component.
Same as `mix(e1, e2, T2(e3))`.
` fn modf(e: T) -> __modf_result_f32 `
T is f32

Note: A value cannot be explicitly declared with the type `__modf_result_f32`, but a value may infer the type.

` fn modf(e: T) -> __modf_result_f16 `
T is f16

Note: A value cannot be explicitly declared with the type `__modf_result_f16`, but a value may infer the type.

` fn modf(e: T) -> __modf_result_abstract `
T is AbstractFloat

Note: A value cannot be explicitly declared with the type `__modf_result_abstract`, but a value may infer the type.

` fn modf(e: T) -> __modf_result_vecN_f32 `
T is vecN<f32>

Note: A value cannot be explicitly declared with the type `__modf_result_vecN_f32`, but a value may infer the type.

` fn modf(e: T) -> __modf_result_vecN_f16 `
T is vecN<f16>

Note: A value cannot be explicitly declared with the type `__modf_result_vecN_f16`, but a value may infer the type.

` fn modf(e: T) -> __modf_result_vecN_abstract `
T is vecN<AbstractFloat>

Note: A value cannot be explicitly declared with the type `__modf_result_vecN_abstract`, but a value may infer the type.

` fn normalize(e: vecN<T> ) -> vecN<T> `
T is AbstractFloat, f32, or f16 Returns a unit vector in the same direction as `e`.
` fn pow(e1: T, e2: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns `e1` raised to the power `e2`. Component-wise when `T` is a vector.
` fn quantizeToF16(e: T) -> T `
T is f32 or vecN<f32>

Note: The vec2<f32> case is the same as `unpack2x16float(pack2x16float(e))`.

` fn radians(e1: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Converts degrees to radians, approximating `e1` × π ÷ 180. Component-wise when `T` is a vector
` fn reflect(e1: T, e2: T) -> T `
T is vecN<AbstractFloat>, vecN<f32>, or vecN<f16> For the incident vector `e1` and surface orientation `e2`, returns the reflection direction `e1 - 2 * dot(e2, e1) * e2`.
` fn refract(e1: T, e2: T, e3: I) -> T `
T is vecN<I> I is AbstractFloat, f32, or f16 For the incident vector `e1` and surface normal `e2`, and the ratio of indices of refraction `e3`, let `k = 1.0 - e3 * e3 * (1.0 - dot(e2, e1) * dot(e2, e1))`. If `k < 0.0`, returns the refraction vector 0.0, otherwise return the refraction vector `e3 * e1 - (e3 * dot(e2, e1) + sqrt(k)) * e2`.
` fn reverseBits(e: T) -> T `
T is i32, u32, vecN<i32>, or vecN<u32> Reverses the bits in `e`: The bit at position `k` of the result equals the bit at position `31 -k` of `e`.
Component-wise when `T` is a vector.
` fn round(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Result is the integer `k` nearest to `e`, as a floating point value.
When `e` lies halfway between integers `k` and `k + 1`, the result is `k` when `k` is even, and `k + 1` when `k` is odd.
Component-wise when `T` is a vector.
` fn saturate(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns `clamp(e, 0.0, 1.0)`. Component-wise when `T` is a vector.
` fn sign(e: T) -> T `
S is AbstractInt, AbstractFloat, i32, f32, or f16T is S, or vecN<S> Result is:
• 1 when `e` > 0
• 0 when `e` = 0
• -1 when `e` < 0

Component-wise when `T` is a vector.

` fn sin(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the sine of `e`, where `e` is in radians. Component-wise when `T` is a vector.
` fn sinh(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the hyperbolic sine of `e`, where `e` is a hyperbolic angle in radians. Approximates the pure mathematical function (earge−arg)÷2, but not necessarily computed that way.

Component-wise when `T` is a vector.

` fn smoothstep(low: T, high: T, x: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the smooth Hermite interpolation between 0 and 1. Component-wise when `T` is a vector.

For scalar `T`, the result is `t * t * (3.0 - 2.0 * t)`, where `t = clamp((x - low) / (high - low), 0.0, 1.0)`.

` fn sqrt(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the square root of `e`. Component-wise when `T` is a vector.
` fn step(edge: T, x: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns 1.0 if `edge``x`, and 0.0 otherwise. Component-wise when `T` is a vector.
` fn tan(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the tangent of `e`, where `e` is in radians. Component-wise when `T` is a vector.
` fn tanh(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns the hyperbolic tangent of `e`, where `e` is a hyperbolic angle in radians. Approximates the pure mathematical function (earge−arg) ÷ (earg + e−arg) but not necessarily computed that way.

Component-wise when `T` is a vector.

` fn transpose(e: matRxC<T>) -> matCxR<T> `
T is AbstractFloat, f32, or f16 Returns the transpose of `e`.
` fn trunc(e: T) -> T `
S is AbstractFloat, f32, or f16T is S or vecN<S> Returns truncate(`e`), the nearest whole number whose absolute value is less than or equal to the absolute value of `e`. Component-wise when `T` is a vector.

## Derivative Built-in Functions

FunctionParameter TypesDescription
` fn dpdx(e: T) -> T `
T is f32 or vecN<f32> Partial derivative of `e` with respect to window x coordinates. The result is the same as either `dpdxFine(e)` or `dpdxCoarse(e)`.

Returns an indeterminate value if called in non-uniform control flow.

` fn dpdxCoarse(e: T) -> T `
T is f32 or vecN<f32> Returns the partial derivative of `e` with respect to window x coordinates using local differences. This may result in fewer unique positions that `dpdxFine(e)`.

Returns an indeterminate value if called in non-uniform control flow.

` fn dpdxFine(e: T) -> T `
T is f32 or vecN<f32> Returns the partial derivative of `e` with respect to window x coordinates.

Returns an indeterminate value if called in non-uniform control flow.

` fn dpdy(e: T) -> T `
T is f32 or vecN<f32> Partial derivative of `e` with respect to window y coordinates. The result is the same as either `dpdyFine(e)` or `dpdyCoarse(e)`.

Returns an indeterminate value if called in non-uniform control flow.

` fn dpdyCoarse(e: T) -> T `
T is f32 or vecN<f32> Returns the partial derivative of `e` with respect to window y coordinates using local differences. This may result in fewer unique positions that `dpdyFine(e)`.

Returns an indeterminate value if called in non-uniform control flow.

` fn dpdyFine(e: T) -> T `
T is f32 or vecN<f32> Returns the partial derivative of `e` with respect to window y coordinates.

Returns an indeterminate value if called in non-uniform control flow.

` fn fwidth(e: T) -> T `
T is f32 or vecN<f32> Returns `abs(dpdx(e)) + abs(dpdy(e))`.

Returns an indeterminate value if called in non-uniform control flow.

` fn fwidthCoarse(e: T) -> T `
T is f32 or vecN<f32> Returns `abs(dpdxCoarse(e)) + abs(dpdyCoarse(e))`.

Returns an indeterminate value if called in non-uniform control flow.

` fn fwidthFine(e: T) -> T `
T is f32 or vecN<f32> Returns `abs(dpdxFine(e)) + abs(dpdyFine(e))`.

Returns an indeterminate value if called in non-uniform control flow.

## Texture Built-in Functions

FunctionParameter TypesDescription
` fn textureDimensions(t: T) -> u32 `
ST is i32, u32, or f32 F is a texel format A is an access mode T is texture_1d<ST> or texture_storage_1d<F,A>
` fn textureDimensions(t: T, level: L) -> u32 `
ST is i32, u32, or f32 T is texture_1d<ST> L is i32, or u32
` fn textureDimensions(t: T) -> vec2<u32> `
ST is i32, u32, or f32 F is a texel format A is an access mode T is texture_2d<ST>, texture_2d_array<ST>, texture_cube<ST>, texture_cube_array<ST>, texture_multisampled_2d<ST>, texture_depth_2d, texture_depth_2d_array, texture_depth_cube, texture_depth_cube_array, texture_depth_multisampled_2d, texture_storage_2d<F,A>, texture_storage_2d_array<F,A>, or texture_external
` fn textureDimensions(t: T, level: L) -> vec2<u32> `
ST is i32, u32, or f32 T is texture_2d<ST>, texture_2d_array<ST>, texture_cube<ST>, texture_cube_array<ST>, texture_depth_2d, texture_depth_2d_array, texture_depth_cube, or texture_depth_cube_array L is i32, or u32
` fn textureDimensions(t: T) -> vec3<u32> `
ST is i32, u32, or f32 F is a texel format A is an access mode T is texture_3d<ST> or texture_storage_3d<F,A>
` fn textureDimensions(t: T, level: L) -> vec3<u32> `
ST is i32, u32, or f32 T is texture_3d<ST> L is i32, or u32

Returns:

The coordinate dimensions of the texture.

That is, the result provides the integer bounds on the coordinates of the logical texel address, excluding the mip level count, array size, and sample count.

For textures based on cubes, the results are the dimensions of each face of the cube. Cube faces are square, so the x and y components of the result are equal.

If `level` is outside the range `[0, textureNumLevels(t))` then an indeterminate value for the return type may be returned.

` fn textureGather(component: C, t: texture_2d<ST>, s: sampler, coords: vec2<f32>) -> vec4<ST> `
C is i32, or u32 ST is i32, u32, or f32
` fn textureGather(component: C, t: texture_2d<ST>, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<ST> `
C is i32, or u32 ST is i32, u32, or f32
` fn textureGather(component: C, t: texture_2d_array<ST>, s: sampler, coords: vec2<f32>, array_index: A) -> vec4<ST> `
C is i32, or u32 A is i32, or u32 ST is i32, u32, or f32
` fn textureGather(component: C, t: texture_2d_array<ST>, s: sampler, coords: vec2<f32>, array_index: A, offset: vec2<i32>) -> vec4<ST> `
C is i32, or u32 A is i32, or u32 ST is i32, u32, or f32
` fn textureGather(component: C, t: texture_cube<ST>, s: sampler, coords: vec3<f32>) -> vec4<ST> `
C is i32, or u32 ST is i32, u32, or f32
` fn textureGather(component: C, t: texture_cube_array<ST>, s: sampler, coords: vec3<f32>, array_index: A) -> vec4<ST> `
C is i32, or u32 A is i32, or u32 ST is i32, u32, or f32
` fn textureGather(t: texture_depth_2d, s: sampler, coords: vec2<f32>) -> vec4<f32> `
` fn textureGather(t: texture_depth_2d, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32> `
` fn textureGather(t: texture_depth_cube, s: sampler, coords: vec3<f32>) -> vec4<f32> `
` fn textureGather(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A) -> vec4<f32> `
A is i32, or u32
` fn textureGather(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureGather(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: A) -> vec4<f32> `
A is i32, or u32

Returns:

A four component vector with components extracted from the specified channel from the selected texels, as described above.

EXAMPLE: Gather components from texels in 2D texture
```@group(0) @binding(0) var t: texture_2d<f32>;
@group(0) @binding(1) var dt: texture_depth_2d;
@group(0) @binding(2) var s: sampler;

fn gather_x_components(c: vec2<f32>) -> vec4<f32> {
return textureGather(0,t,s,c);
}
fn gather_y_components(c: vec2<f32>) -> vec4<f32> {
return textureGather(1,t,s,c);
}
fn gather_z_components(c: vec2<f32>) -> vec4<f32> {
return textureGather(2,t,s,c);
}
fn gather_depth_components(c: vec2<f32>) -> vec4<f32> {
return textureGather(dt,s,c);
}
```
` fn textureGatherCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> vec4<f32> `
` fn textureGatherCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> vec4<f32> `
` fn textureGatherCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> vec4<f32> `
A is i32, or u32
` fn textureGatherCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureGatherCompare(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> vec4<f32> `
` fn textureGatherCompare(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: A, depth_ref: f32) -> vec4<f32> `
A is i32, or u32

Returns:

A four component vector with comparison result for the selected texels, as described above.

EXAMPLE: Gather depth comparison
```@group(0) @binding(0) var dt: texture_depth_2d;
@group(0) @binding(1) var s: sampler;

fn gather_depth_compare(c: vec2<f32>, depth_ref: f32) -> vec4<f32> {
return textureGatherCompare(dt,s,c,depth_ref);
}
```
` fn textureLoad(t: texture_1d<ST>, coords: C, level: L) -> vec4<ST> `
C is i32, or u32 L is i32, or u32 ST is i32, u32, or f32
` fn textureLoad(t: texture_2d<ST>, coords: vec2<C>, level: L) -> vec4<ST> `
C is i32, or u32 L is i32, or u32 ST is i32, u32, or f32
` fn textureLoad(t: texture_2d_array<ST>, coords: vec2<C>, array_index: A, level: L) -> vec4<ST> `
C is i32, or u32 A is i32, or u32 L is i32, or u32 ST is i32, u32, or f32
` fn textureLoad(t: texture_3d<ST>, coords: vec3<C>, level: L) -> vec4<ST> `
C is i32, or u32 L is i32, or u32 ST is i32, u32, or f32
` fn textureLoad(t: texture_multisampled_2d<ST>, coords: vec2<C>, sample_index: S)-> vec4<ST> `
C is i32, or u32 S is i32, or u32 ST is i32, u32, or f32
` fn textureLoad(t: texture_depth_2d, coords: vec2<C>, level: L) -> f32 `
C is i32, or u32 L is i32, or u32
` fn textureLoad(t: texture_depth_2d_array, coords: vec2<C>, array_index: A, level: L) -> f32 `
C is i32, or u32 A is i32, or u32 L is i32, or u32
` fn textureLoad(t: texture_depth_multisampled_2d, coords: vec2<C>, sample_index: S)-> f32 `
C is i32, or u32 S is i32, or u32
` fn textureLoad(t: texture_external, coords: vec2<C>) -> vec4<f32> `
C is i32, or u32

Returns:

The unfiltered texel data.

The logical texel address is invalid if:

• any element of `coords` is outside the range `[0, textureDimensions(t, level))` for the corresponding element, or

• `array_index` is outside the range `[0, textureNumLayers(t))`, or

• `level` is outside the range `[0, textureNumLevels(t))`, or

• `sample_index` is outside the range `[0, textureNumSamples(s))`

If the logical texel addresss is invalid, the built-in function returns one of:

• The data for some texel within bounds of the texture

• A vector (0,0,0,0) or (0,0,0,1) of the appropriate type for non-depth textures

• 0.0 for depth textures

` fn textureNumLayers(t: T) -> u32 `
F is a texel format A is an access mode ST is i32, u32, or f32 T is texture_2d_array<ST>, texture_cube_array<ST>, texture_depth_2d_array, texture_depth_cube_array, or texture_storage_2d_array<F,A>

Returns:

If the texture is based on cubes, returns the number of cubes in the cube arrayed texture.

Otherwise returns the number of layers (homogeneous grids of texels) in the arrayed texture.

` fn textureNumLevels(t: T) -> u32 `
ST is i32, u32, or f32 T is texture_1d<ST>, texture_2d<ST>, texture_2d_array<ST>, texture_3d<ST>, texture_cube<ST>, texture_cube_array<ST>, texture_depth_2d, texture_depth_2d_array, texture_depth_cube, or texture_depth_cube_array

Returns:

The mip level count for the texture.

` fn textureNumSamples(t: T) -> u32 `
ST is i32, u32, or f32 T is texture_multisampled_2d<ST> or texture_depth_multisampled_2d

Returns:

The sample count for the multisampled texture.

` fn textureSample(t: texture_1d<f32>, s: sampler, coords: f32) -> vec4<f32> `
` fn textureSample(t: texture_2d<f32>, s: sampler, coords: vec2<f32>) -> vec4<f32> `
` fn textureSample(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> vec4<f32> `
` fn textureSample(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A) -> vec4<f32> `
A is i32, or u32
` fn textureSample(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureSample(t: T, s: sampler, coords: vec3<f32>) -> vec4<f32> `
T is texture_3d<f32>, or texture_cube<f32>
` fn textureSample(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, offset: vec3<i32>) -> vec4<f32> `
` fn textureSample(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: A) -> vec4<f32> `
A is i32, or u32
` fn textureSample(t: texture_depth_2d, s: sampler, coords: vec2<f32>) -> f32 `
` fn textureSample(t: texture_depth_2d, s: sampler, coords: vec2<f32>, offset: vec2<i32>) -> f32 `
` fn textureSample(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A) -> f32 `
A is i32, or u32
` fn textureSample(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A, offset: vec2<i32>) -> f32 `
A is i32, or u32
` fn textureSample(t: texture_depth_cube, s: sampler, coords: vec3<f32>) -> f32 `
` fn textureSample(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: A) -> f32 `
A is i32, or u32

Returns:

The sampled value.

An indeterminate value results if called in non-uniform control flow.

` fn textureSampleBias(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, bias: f32) -> vec4<f32> `
` fn textureSampleBias(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, bias: f32, offset: vec2<i32>) -> vec4<f32> `
` fn textureSampleBias(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, bias: f32) -> vec4<f32> `
A is i32, or u32
` fn textureSampleBias(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, bias: f32, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureSampleBias(t: T, s: sampler, coords: vec3<f32>, bias: f32) -> vec4<f32> `
T is texture_3d<f32>, or texture_cube<f32>
` fn textureSampleBias(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, bias: f32, offset: vec3<i32>) -> vec4<f32> `
` fn textureSampleBias(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: A, bias: f32) -> vec4<f32> `
A is i32, or u32

Returns:

The sampled value.

An indeterminate value results if called in non-uniform control flow.

` fn textureSampleCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32 `
` fn textureSampleCompare(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32 `
` fn textureSampleCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> f32 `
A is i32, or u32
` fn textureSampleCompare(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32, offset: vec2<i32>) -> f32 `
A is i32, or u32
` fn textureSampleCompare(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32 `
` fn textureSampleCompare(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: A, depth_ref: f32) -> f32 `
A is i32, or u32

Returns:

A value in the range `[0.0..1.0]`.

Each sampled texel is compared against the reference value using the comparison operator defined by the `sampler_comparison`, resulting in either a `0` or `1` value for each texel.

If the sampler uses bilinear filtering then the returned value is the filtered average of these values, otherwise the comparison result of a single texel is returned.

An indeterminate value results if called in non-uniform control flow.

` fn textureSampleCompareLevel(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32) -> f32 `
` fn textureSampleCompareLevel(t: texture_depth_2d, s: sampler_comparison, coords: vec2<f32>, depth_ref: f32, offset: vec2<i32>) -> f32 `
` fn textureSampleCompareLevel(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32) -> f32 `
A is i32, or u32
` fn textureSampleCompareLevel(t: texture_depth_2d_array, s: sampler_comparison, coords: vec2<f32>, array_index: A, depth_ref: f32, offset: vec2<i32>) -> f32 `
A is i32, or u32
` fn textureSampleCompareLevel(t: texture_depth_cube, s: sampler_comparison, coords: vec3<f32>, depth_ref: f32) -> f32 `
` fn textureSampleCompareLevel(t: texture_depth_cube_array, s: sampler_comparison, coords: vec3<f32>, array_index: A, depth_ref: f32) -> f32 `
A is i32, or u32

Returns:

A value in the range `[0.0..1.0]`.

The `textureSampleCompareLevel` function is the same as `textureSampleCompare`, except that:

• `textureSampleCompareLevel` always samples texels from mip level 0.

• The function does not compute derivatives.

• There is no requirement for `textureSampleCompareLevel` to be invoked in uniform control flow.

• `textureSampleCompareLevel` may be invoked in any shader stage.

` fn textureSampleGrad(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> `
` fn textureSampleGrad(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32> `
` fn textureSampleGrad(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, ddx: vec2<f32>, ddy: vec2<f32>) -> vec4<f32> `
A is i32, or u32
` fn textureSampleGrad(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, ddx: vec2<f32>, ddy: vec2<f32>, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureSampleGrad(t: T, s: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32> `
T is texture_3d<f32>, or texture_cube<f32>
` fn textureSampleGrad(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, ddx: vec3<f32>, ddy: vec3<f32>, offset: vec3<i32>) -> vec4<f32> `
` fn textureSampleGrad(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: A, ddx: vec3<f32>, ddy: vec3<f32>) -> vec4<f32> `
A is i32, or u32

Returns:

The sampled value.

` fn textureSampleLevel(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, level: f32) -> vec4<f32> `
` fn textureSampleLevel(t: texture_2d<f32>, s: sampler, coords: vec2<f32>, level: f32, offset: vec2<i32>) -> vec4<f32> `
` fn textureSampleLevel(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, level: f32) -> vec4<f32> `
A is i32, or u32
` fn textureSampleLevel(t: texture_2d_array<f32>, s: sampler, coords: vec2<f32>, array_index: A, level: f32, offset: vec2<i32>) -> vec4<f32> `
A is i32, or u32
` fn textureSampleLevel(t: T, s: sampler, coords: vec3<f32>, level: f32) -> vec4<f32> `
T is texture_3d<f32>, or texture_cube<f32>
` fn textureSampleLevel(t: texture_3d<f32>, s: sampler, coords: vec3<f32>, level: f32, offset: vec3<i32>) -> vec4<f32> `
` fn textureSampleLevel(t: texture_cube_array<f32>, s: sampler, coords: vec3<f32>, array_index: A, level: f32) -> vec4<f32> `
A is i32, or u32
` fn textureSampleLevel(t: texture_depth_2d, s: sampler, coords: vec2<f32>, level: L) -> f32 `
L is i32, or u32
` fn textureSampleLevel(t: texture_depth_2d, s: sampler, coords: vec2<f32>, level: L, offset: vec2<i32>) -> f32 `
L is i32, or u32
` fn textureSampleLevel(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A, level: L) -> f32 `
A is i32, or u32 L is i32, or u32
` fn textureSampleLevel(t: texture_depth_2d_array, s: sampler, coords: vec2<f32>, array_index: A, level: L, offset: vec2<i32>) -> f32 `
A is i32, or u32 L is i32, or u32
` fn textureSampleLevel(t: texture_depth_cube, s: sampler, coords: vec3<f32>, level: L) -> f32 `
L is i32, or u32
` fn textureSampleLevel(t: texture_depth_cube_array, s: sampler, coords: vec3<f32>, array_index: A, level: L) -> f32 `
A is i32, or u32 L is i32, or u32

Returns:

The sampled value.

` fn textureSampleBaseClampToEdge(t: T, s: sampler, coords: vec2<f32>) -> vec4<f32> `
T is texture_2d<f32> or texture_external

Returns:

The sampled value.

` fn textureStore(t: texture_storage_1d<F,write>, coords: C, value: vec4<CF>) `
F is a texel format C is i32, or u32 CF depends on the storage texel format F. See the texel format table for the mapping of texel format to channel format.
` fn textureStore(t: texture_storage_2d<F,write>, coords: vec2<C>, value: vec4<CF>) `
F is a texel format C is i32, or u32 CF depends on the storage texel format F. See the texel format table for the mapping of texel format to channel format.
` fn textureStore(t: texture_storage_2d_array<F,write>, coords: vec2<C>, array_index: A, value: vec4<CF>) `
F is a texel format C is i32, or u32 A is i32, or u32 CF depends on the storage texel format F. See the texel format table for the mapping of texel format to channel format.
` fn textureStore(t: texture_storage_3d<F,write>, coords: vec3<C>, value: vec4<CF>) `
F is a texel format C is i32, or u32 CF depends on the storage texel format F. See the texel format table for the mapping of texel format to channel format.

## Atomic Built-in Functions

FunctionParameter TypesDescription
`fn atomicLoad(atomic_ptr: ptr<AS, atomic<T>, read_write>) -> T `
`fn atomicStore(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) `
`fn atomicAdd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicSub(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicMax(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicMin(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicAnd(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicOr(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T fn atomicXor(atomic_ptr: ptr<AS, atomic<T>, read_write>, v: T) -> T `

## Data Packing Built-in Functions

FunctionParameter TypesDescription
` fn pack4x8snorm(e: vec4<f32>) -> u32 `
Converts four normalized floating point values to 8-bit signed integers, and then combines them into one `u32` value.
Component `e[i]` of the input is converted to an 8-bit twos complement integer value ⌊ 0.5 + 127 × min(1, max(-1, e[i])) ⌋ which is then placed in bits 8 × `i` through 8 × `i` + 7 of the result.
` fn pack4x8unorm(e: vec4<f32>) -> u32 `
Converts four normalized floating point values to 8-bit unsigned integers, and then combines them into one `u32` value.
Component `e[i]` of the input is converted to an 8-bit unsigned integer value ⌊ 0.5 + 255 × min(1, max(0, e[i])) ⌋ which is then placed in bits 8 × `i` through 8 × `i` + 7 of the result.
` fn pack2x16snorm(e: vec2<f32>) -> u32 `
Converts two normalized floating point values to 16-bit signed integers, and then combines them into one `u32` value.
Component `e[i]` of the input is converted to a 16-bit twos complement integer value ⌊ 0.5 + 32767 × min(1, max(-1, e[i])) ⌋ which is then placed in bits 16 × `i` through 16 × `i` + 15 of the result.
` fn pack2x16unorm(e: vec2<f32>) -> u32 `
Converts two normalized floating point values to 16-bit unsigned integers, and then combines them into one `u32` value.
Component `e[i]` of the input is converted to a 16-bit unsigned integer value ⌊ 0.5 + 65535 × min(1, max(0, e[i])) ⌋ which is then placed in bits 16 × `i` through 16 × `i` + 15 of the result.
` fn pack2x16float(e: vec2<f32>) -> u32 `
Converts two floating point values to half-precision floating point numbers, and then combines them into one `u32` value.
Component `e[i]` of the input is converted to a IEEE-754 binary16 value, which is then placed in bits 16 × `i` through 16 × `i` + 15 of the result. See § 14.6.2 Floating Point Conversion.

If either `e` or `e` is outside the finite range of binary16 then:

• It is a shader-creation error if `e` is a const-expression.

• It is a pipeline-creation error if `e` is an override-expression.

• Otherwise the result is an indeterminate value for u32.

## Data Unpacking Built-in Functions

FunctionParameter TypesDescription
` fn unpack4x8snorm(e: u32) -> vec4<f32> `
Decomposes a 32-bit value into four 8-bit chunks, then reinterprets each chunk as a signed normalized floating point value.
Component `i` of the result is max(v ÷ 127, -1), where `v` is the interpretation of bits 8×`i` through 8×`i + 7` of `e` as a twos-complement signed integer.
` fn unpack4x8unorm(e: u32) -> vec4<f32> `
Decomposes a 32-bit value into four 8-bit chunks, then reinterprets each chunk as an unsigned normalized floating point value.
Component `i` of the result is `v` ÷ 255, where `v` is the interpretation of bits 8×`i` through 8×`i + 7` of `e` as an unsigned integer.
` fn unpack2x16snorm(e: u32) -> vec2<f32> `
Decomposes a 32-bit value into two 16-bit chunks, then reinterprets each chunk as a signed normalized floating point value.
Component `i` of the result is max(v ÷ 32767, -1), where `v` is the interpretation of bits 16×`i` through 16×`i + 15` of `e` as a twos-complement signed integer.
` fn unpack2x16unorm(e: u32) -> vec2<f32> `
Decomposes a 32-bit value into two 16-bit chunks, then reinterprets each chunk as an unsigned normalized floating point value.
Component `i` of the result is `v` ÷ 65535, where `v` is the interpretation of bits 16×`i` through 16×`i + 15` of `e` as an unsigned integer.
` fn unpack2x16float(e: u32) -> vec2<f32> `
Decomposes a 32-bit value into two 16-bit chunks, and reinterpets each chunk as a floating point value.
Component `i` of the result is the f32 representation of `v`, where `v` is the interpretation of bits 16×`i` through 16×`i + 15` of `e` as an IEEE-754 binary16 value. See § 14.6.2 Floating Point Conversion.

## Synchronization Built-in Functions

FunctionParameter TypesDescription
` fn storageBarrier() `
Executes a control barrier synchronization function that affects memory and atomic operations in the storage address space.
` fn workgroupBarrier() `
Executes a control barrier synchronization function that affects memory and atomic operations in the workgroup address space.
` fn workgroupUniformLoad(p : ptr<workgroup, T>) -> T `
T is a concrete plain type with a fixed footprint that does not contain any atomic types Returns the value pointed to by `p` to all invocations in the workgroup. The return value is uniform. `p` must be a uniform value.

Executes a control barrier synchronization function that affects memory and atomic operations in the workgroup address space.