v153 · enabled by default · wgsl built-in function
bufferLength
Returns the byte size of a buffer pointer — but “the size” is the minimum size encountered for the originating variable across the call stack, so a helper that takes a buffer<256> parameter sees 256 even when the caller's variable is larger.
syntax
Two overloads (verbatim from WGSL §17.14.3); both are @must_use:
@must_use fn bufferLength(p : ptr<AS, buffer, AM>) -> u32
@must_use fn bufferLength(p : ptr<AS, buffer<N>, AM>) -> u32
Source: WGSL §17.14.3 (fetched 2026-07-29)
inputs
| Parameter | Type | Contract |
|---|---|---|
p | ptr<AS, buffer> or ptr<AS, buffer<N>> | AS ∈ {storage, uniform, workgroup}; AM a valid access mode for AS |
outputs
A u32 byte size, defined as the minimum of:
- the size of the originating variable (
Nfor a fixed-size variable; the size of the bound WebGPUGPUBufferfor a runtime-sized variable), and - the minimum fixed-size buffer encountered as a formal parameter anywhere in the call stack that the argument travelled through.
So if N is specified the function returns N; buffer sizes cannot be grown through function calls. The value is produced by interprocedural analysis, and the same minimum is the size used when validating bufferView and bufferArrayView calls on the same buffer.
errors
The function has no author-reachable error surface beyond its preconditions: passing a pointer whose AS is not storage/uniform/workgroup, or whose access mode is invalid for the address space, is a validation error. It performs no memory access itself, so there is no bounds behavior of its own — the value it returns is what other built-ins validate against.
context and exposure
- Available in any shader stage with the
buffer_viewextension; same pointer-parameter rules as the other built-ins (unrestricted_pointer_parametersneeded to pass buffer pointers through user functions — see conversions). - Without
unrestricted_pointer_parameterssupport, the root identifier of the argument must be the originating variable.
lifecycle
Pure query, @must_use, no state transitions: it reports the statically-tracked minimum size for the argument's provenance chain. Typical usage is defensive — computing how much room remains before constructing a view, or sizing a loop over a runtime-sized buffer.
examples
The specification's own example (WGSL §17.14.3, “bufferLength values”), showing how the formal parameter's size wins through the call stack:
requires buffer_view;
requires unrestricted_pointer_parameters;
@group(0) @binding(0) var<storage> b1 : buffer<2048>;
@group(0) @binding(1) var<storage> b2 : buffer<4096>;
fn foobar(p : ptr<storage, buffer>) -> u32 {
return bufferLength(p);
}
fn bar(p : ptr<storage, buffer<1024>>) -> u32 {
return foobar(p);
}
fn foo(p : ptr<storage, buffer<256>>) -> u32 {
return bufferLength(p);
}
@compute @workgroup_size(1)
fn main() {
let len1 = bufferLength(&b1); // 2048
let len2 = bufferLength(&b2); // 4096
let len3 = foo(&b1); // 256 — the formal parameter is smaller
let len4 = bar(&b2); // 1024 — smallest size on the call stack
}
Note: the spec example declares both variables at @binding(0); the second is shown here at @binding(1) because two bindings at the same address in one bind group would be a bind-group validation error. The semantics illustrated are unchanged.
browser compatibility
Interim table (no BCD key; compiled from primary sources, 2026-07-29):
| Browser | Support | Evidence |
|---|---|---|
| Chrome | Enabled by default 153 (desktop, Android, WebView) | milestone=153 listing |
| Edge | Not separately reported | Chromium-based |
| Firefox | No signal | mozilla/standards-positions #1205 |
| Safari | Closed without a position | WebKit/standards-positions #294 |
security and privacy
- Read-only query with no memory access of its own; it exists precisely so shaders can stay within validated bounds.
- The minimum-size rule prevents a callee from observing or exploiting a larger buffer than its parameter types declare.
- No new JS/storage/network/fingerprinting surface (see overview security).