---
title: StorageBuffer
description: Low-level user-owned storage buffer with a stable bind group at binding `0`. Use it for arrays, large data, compute scratch buffers, or storage-driven rendering when main API (`vgpu`) `storage(gpu)` is not enough.
---

# StorageBuffer



## Import

```ts
import { StorageBuffer } from "vgpu/core";
import type { StorageBufferOptions } from "vgpu/core";
```

## Signature

```ts
import type { Device } from "vgpu/core";

declare interface StorageBufferOptions {
  readonly size: number;
  readonly label?: string;
  readonly access?: "read" | "read-write";
  readonly visibility?: GPUShaderStageFlags;
  readonly bindGroupLayout?: GPUBindGroupLayout;
}

declare class StorageBuffer {
  readonly device: Device;
  readonly size: number;
  readonly access: "read" | "read-write";
  readonly buffer: import("vgpu/core").Buffer;
  readonly bindGroupLayout: GPUBindGroupLayout;
  readonly bindGroup: GPUBindGroup;
  constructor(device: Device, opts: StorageBufferOptions);
  get gpu(): GPUBuffer;
  write(data: BufferSource, offset?: number): void;
  destroy(): void;
  dispose(): void;
}
```

## Parameters

| Param                | Type                     | Required | Default                                                                            | Notes                                                                                                   |
| -------------------- | ------------------------ | -------: | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| device               | `Device`                 |        ✔ | —                                                                                  | Core device, usually `gpu.device`.                                                                      |
| opts                 | `StorageBufferOptions`   |        ✔ | —                                                                                  | Buffer/layout options.                                                                                  |
| opts.size            | `number`                 |        ✔ | —                                                                                  | Byte size. Used for storage buffer allocation and `minBindingSize`.                                     |
| opts.label           | `string`                 |        ✖ | `undefined`                                                                        | Forwarded to buffer label; layout label becomes `${label}.bgl`; bind group label becomes `${label}.bg`. |
| opts.access          | `"read" \| "read-write"` |        ✖ | `"read"`                                                                           | Chooses bind group layout type: `"read-only-storage"` or `"storage"`.                                   |
| opts.visibility      | `GPUShaderStageFlags`    |        ✖ | `GPUShaderStage.FRAGMENT \| GPUShaderStage.COMPUTE` with numeric fallback `2 \| 4` | Ignored when `opts.bindGroupLayout` is supplied. Default intentionally excludes vertex stage.           |
| opts.bindGroupLayout | `GPUBindGroupLayout`     |        ✖ | A new binding-0 storage layout                                                     | Reuse a pipeline-owned layout. Binding `0` must match size/access.                                      |
| storage.write.data   | `BufferSource`           |        ✔ | —                                                                                  | Bytes uploaded with `queue.writeBuffer`.                                                                |
| storage.write.offset | `number`                 |        ✖ | `0`                                                                                | Destination byte offset.                                                                                |

**Returns:** Constructor returns `StorageBuffer`; `gpu` returns the underlying `GPUBuffer`; `write()`, `destroy()`, and `dispose()` return `void`.

**Throws:** No custom `VGPU-*` errors are thrown directly by this class. Native/core validation can fail for invalid size, incompatible reused layouts, or bad writes. Compute aliasing with the same buffer can throw `VGPU-R1-STORAGE-ALIASING` when used through `compute(gpu)`.

## Examples

```ts
import { init, compute } from "vgpu/mock";
import { StorageBuffer } from "vgpu/core";

const gpu = await init();
const values = new StorageBuffer(gpu.device, { size: 4 * 16, label: "values" });
values.write(new Float32Array(16));

const sim = compute(gpu, `
  @group(0) @binding(0) var<storage, read> values: array<f32>;
  @compute @workgroup_size(1)
  fn cs_main(@builtin(global_invocation_id) id: vec3u) { _ = values[id.x]; }
`, { set: { values } });
sim.dispatch(1);
```

```ts
import { init, draw } from "vgpu/mock";
import { StorageBuffer } from "vgpu/core";

const gpu = await init();
const drawable = draw(gpu, { shader: `
  @group(0) @binding(0) var<storage, read> positions: array<vec4f>;
  @vertex fn vs_main(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f { return positions[vi]; }
  @fragment fn fs_main() -> @location(0) vec4f { return vec4f(1); }
` });
const positions = new StorageBuffer(gpu.device, {
  size: 3 * 16,
  visibility: GPUShaderStage.VERTEX,
  bindGroupLayout: drawable.layout(0),
});
positions.write(new Float32Array(12));
drawable.set({ positions });
```

## Notes

* Default visibility is fragment + compute, not vertex. Vertex-stage storage is legal only on adapters with the needed limits; opt in explicitly and request limits when creating the device.
* `access: "read-write"` cannot be used from the vertex stage in WebGPU.
* For main API (`vgpu`) readback and ping-pong helpers, use `storage(gpu)` and `pingPongStorage(gpu)`.
* **See also:** `Compute`, `storage()`, `Uniform`, `UniformPool`, `Draw.set`.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)