v153 · enabled by default · wgsl built-in function
bufferView
Reinterprets the memory view starting offset bytes into a buffer pointer as the host-shareable type T, returning a normal pointer to T covering [offset, bufferLength(p)). It is effectively a single-shot pointer reinterpret cast — the only way to read or write the contents of an opaque buffer value.
syntax
Two overloads (verbatim from WGSL §17.14.1) — one for runtime-sized, one for fixed-size buffer pointers; both are @must_use:
@must_use fn bufferView<T>(p : ptr<AS, buffer, AM>, offset : I) -> ptr<AS, T, AM>
@must_use fn bufferView<T>(p : ptr<AS, buffer<N>, AM>, offset : I) -> ptr<AS, T, AM>
The helper definition that drives validation (§17.14):
ArrayOffset(T)=OffsetOfMember(T, lastMemberIndex)ifTis a structure whose last member is a runtime-sized array, else0.MinTypeSize(T)=SizeOf(T)ifThas a fixed footprint;StrideOf(T)ifTis a runtime-sized array;ArrayOffset(T) + StrideOf(array<E>)ifTis a structure ending in a runtime-sized array.
inputs
| Parameter | Type | Contract |
|---|---|---|
T (template) | type | Host-shareable; must not be or contain an atomic type or a buffer type (MSL cannot cast non-atomic to atomic; views cannot chain); must satisfy the address-space layout constraints for AS |
p | ptr<AS, buffer> or ptr<AS, buffer<N>> | AS ∈ {storage, uniform, workgroup}; AM must be a valid access mode for AS (normal address-space restrictions apply — e.g. uniform is read-only) |
offset | I — u32 or i32 | Byte offset into the buffer. For i32: shader-creation error if a const-expression < 0; pipeline-creation error if an override-expression < 0; otherwise an indeterminate value may be used. Alignment rules below |
outputs
A ptr<AS, T, AM> usable like any other pointer. Formally: if the memory locations associated with p are in the range [0, bufferLength(p)), then the memory locations associated with the result are in the range [offset, bufferLength(p)) with store type T. When T has no fixed footprint (a runtime-sized array or a struct ending in one), the runtime element count derives from the buffer binding per WGSL §13.3.4, and arrayLength on the result reports it (arrayLength's AS may be uniform or workgroup only when its argument derives from bufferView/bufferArrayView — §17.4.1 note).
errors
| Condition | Behavior |
|---|---|
MinTypeSize(T) + offset > bufferLength(p) | An invalid pointer is returned (runtime path); the proposal's design note: this eliminates some in-bounds behavior but keeps implementations simple |
MinTypeSize(T) > N (fixed-size buffer) | Shader-creation error |
MinTypeSize(T) + offset > N (fixed-size buffer) | Shader-creation error if offset is a const-expression; pipeline-creation error if an override-expression |
offset % RequiredAlignOf(T, AS) != 0 | Shader-creation error (const-expression offset) / pipeline-creation error (override-expression offset); otherwise the implementation uses offset & ~(RequiredAlignOf(T, AS) - 1) — it rounds the offset down to alignment |
Negative offset (i32) | Shader-creation error (const-expression) / pipeline-creation error (override-expression) / indeterminate value may be used (otherwise) |
T atomic, containing an atomic, or a buffer type; or T violating AS layout constraints | Validation error (precondition failure) |
Size checks are performed interprocedurally, so user size reductions through function parameters are respected; the check also computes the minimum buffer size the binding must provide. The alignment-rounding rule interacts with the uniform_buffer_standard_layout language feature.
context and exposure
- Available in any shader stage; requires the
buffer_viewlanguage extension (automatic when supported; document withrequires buffer_view;). - Operates on pointers in the storage, uniform, or workgroup address spaces. Passing a buffer pointer obtained from a helper function's formal parameter additionally requires
unrestricted_pointer_parameters(see conversions); without it, the root identifier of the argument must be the originating variable. - Because
Tcannot be a buffer type, the cast is single-shot: you always cast from an unmodified root identifier (moduloletunpacking) and only once before a memory access.
lifecycle
- Declaration — a buffer variable is declared in storage/uniform/workgroup (see type rules); for storage/uniform it binds a
GPUBuffervia a bind group. - Reinterpretation —
bufferViewconverts the buffer pointer at a byte offset; validation happens at shader creation (const), pipeline creation (override), or produces an invalid pointer (runtime). - Use — the result pointer is dereferenced/read/written like any pointer of
ptr<AS, T, AM>; subsequentarrayLengthcalls account for the view's offset. - No state, cancellation, or cleanup: the function is a pure pointer reinterpretation with
@must_usesemantics.
examples
Reading a packed header word and then viewing the tail as a typed array (pattern from the proposal):
requires buffer_view;
@group(0) @binding(0) var<storage> packed_data : buffer;
fn read_header_and_tail() {
// View byte 0 as a u32 count.
let count = *bufferView<u32>(&packed_data, 0);
// View the remainder as an array of f32 starting at byte 4.
let values = bufferView<array<f32>>(&packed_data, 4);
let first = values[0]; // normal pointer indexing
let n = arrayLength(&*values); // runtime element count from the binding
}
Source: usage pattern per the proposal motivating example; signatures per WGSL §17.14.1
browser compatibility
Interim table (no BCD key for the feature or this built-in; compiled from primary sources, 2026-07-29):
| Browser | Support | Evidence |
|---|---|---|
| Chrome | Enabled by default 153 (desktop, Android, WebView) | milestone=153 listing (“Enabled by default”) |
| Edge | Not separately reported | Chromium-based; no separate position |
| Firefox | No signal | mozilla/standards-positions #1205 |
| Safari | Closed without a position | WebKit/standards-positions #294 |
security and privacy
- Out-of-contract offsets produce an invalid pointer (WebGPU out-of-bounds behavior), not raw memory access; the reinterpretation stays within the shader's own binding.
- Single-shot, non-atomic reinterpretation preserves WGSL's memory and atomicity guarantees; alignment is enforced or conservatively rounded down.
- No new JavaScript, storage, network, or fingerprinting surface (see the overview security section).