Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Buffers

Buffer is an opaque GPU buffer — no raw wgpu type appears in its public API. Build one with BufferBuilder:

let vertex_buffer = BufferBuilder::with_data(bytemuck::cast_slice(&vertices))
    .with_label("Vertex Buffer")
    .with_usage(BufferUsages::VERTEX)
    .build(&backend);

let empty = BufferBuilder::empty(1024)
    .with_usage(BufferUsages::STORAGE | BufferUsages::COPY_DST)
    .build(&backend);

.with_uniform()/.with_storage() are shortcuts for the common UNIFORM | COPY_DST and STORAGE | COPY_DST usage combos.

  • write(data) — overwrites the buffer’s contents from the start.
  • write_at(offset, data) — overwrites starting at a byte offset.
  • size() — the buffer’s size in bytes.

Reading a buffer back

read() copies the buffer’s contents back to the CPU, returning a Promise<Vec<u8>> — poll it each tick until it resolves. Requires BufferUsages::COPY_SRC:

fn kick_off(buffer: Read<SomeBuffer>, mut promise: Local<Option<Promise<Vec<u8>>>>) {
    *promise = Some(buffer.0.read());
}

fn check(mut promise: Local<Option<Promise<Vec<u8>>>>) {
    if let Some(p) = promise.as_ref() {
        if let PromiseState::Ready(bytes) = p.poll() {
            // ...
            *promise = None;
        }
    }
}

Dynamic buffers

DynamicBuffer holds many fixed-size elements, each individually writable and bindable at an aligned offset — for per-object uniform data, for example. Build one with DynamicBufferBuilder; the per-element stride is rounded up to the device’s required offset alignment for you:

let per_object = DynamicBufferBuilder::uniform(std::mem::size_of::<ObjectData>() as u64, 100)
    .build(&backend);

per_object.write_element(object_index, bytemuck::bytes_of(&data));

Bind a specific element with BindGroupBuilder::with_dynamic_buffer, then pass its byte offset (index * stride()) in the offsets slice when you set_bind_group during a render/compute pass — see Bind Groups and Layouts and Recording a Render Pass.

Material/Compute also take an existing Buffer/DynamicBuffer directly, via .with_buffer(name, buffer)/.with_dynamic_buffer(name, buffer) — see Materials.