Uniform Module API Reference
This document covers the exports from src/uniform/: the UniformBuffer implementation, supporting interfaces, and the UniformUtils helper class.
Types & interfaces
UniformData
Any typed array (e.g., Float32Array, Uint32Array, DataView) or raw ArrayBuffer can be passed to the UniformBuffer constructor.
IUniformBuffer
interface IUniformBuffer {
readonly buffer: GPUBuffer;
readonly bindGroup: GPUBindGroup;
readonly size: number;
readonly label?: string;
readonly data: ArrayBuffer;
setData(view: ArrayBufferView): void;
flush(device?: GPUDevice): void;
clone(device?: GPUDevice): IUniformBuffer;
destroy(): void;
}
UniformBuffer implements this interface.
UniformConfig
interface UniformConfig {
device: GPUDevice;
data: UniformData;
label?: string;
usage?: GPUBufferUsageFlags; // optional extra usage bits
}
The current implementation takes (device, data, label?), but the config interface is exported for future pooling/usage overrides.
Class: UniformBuffer
class UniformBuffer implements IUniformBuffer {
constructor(device: GPUDevice, init: UniformData, label?: string);
static bindGroupLayout(device: GPUDevice): GPUBindGroupLayout;
readonly buffer: GPUBuffer;
readonly bindGroup: GPUBindGroup;
readonly label?: string;
readonly size: number;
get data(): ArrayBuffer;
set dataBytes(bytes: ArrayBuffer);
setData(view: ArrayBufferView): void;
flush(device?: GPUDevice): void;
clone(device?: GPUDevice): UniformBuffer;
destroy(): void;
}
Constructor
- Copies the initial data into an internal
ArrayBuffercache. - Allocates a GPU buffer with
GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST. - Writes the initial bytes to the GPU and creates a bind group using the shared layout.
static bindGroupLayout(device)
Returns (and lets WebGPU cache) the canonical uniform bind group layout:
entry: {
binding: 0,
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,
buffer: { type: 'uniform' },
}
setData(view)
Copies a typed array into the CPU cache. Throws if view.byteLength !== size.
flush(device?)
Uploads the cached bytes to the GPU via queue.writeBuffer. If no device is provided it uses the one stored from construction.
data / dataBytes
datareturns a clonedArrayBufferof the cache (for debugging or serialization).dataBytes = newBytesreplaces the cache entirely (size must match).
clone(device?)
Constructs a new UniformBuffer with the same bytes (useful when duplicating per-camera uniforms).
destroy()
Calls buffer.destroy(); does not null the bind group (caller manages references).
Class: UniformUtils
class UniformUtils {
static alignSize(size: number): number;
static createAlignedBuffer(size: number): ArrayBuffer;
static packFloat32Array(values: number[], targetSize?: number): Float32Array;
static packVec(values: number[], vecSize: 2 | 3 | 4): Float32Array;
static packMat4(matrix: Float32Array | number[]): Float32Array;
}
alignSize�?rounds up to the next multiple of 16 bytes.createAlignedBuffer�?returns anArrayBufferalready aligned (zero-filled).packFloat32Array�?writes an array of numbers into aFloat32Arrayof a given length (padding with zeros if needed).packVec�?handles vec2/vec3/vec4 padding (vec3promoted tovec4).packMat4�?ensures the input has 16 elements and returns a column-majorFloat32Array(pass an existingFloat32Arrayto avoid copies).
Usage snippets
Creating and binding a uniform
import { UniformBuffer } from 'src/uniform';
const projBytes = new Float32Array(16); // 64 bytes
const projUniform = new UniformBuffer(device, projBytes, 'projection');
renderPass.setBindGroup(0, projUniform.bindGroup);
Updating per frame
function updateCamera(cameraBytes: Float32Array) {
cameraUniform.setData(cameraBytes);
cameraUniform.flush();
}
Packing structs
const settingsData = new Float32Array(20); // 80 bytes
// Fill clipping boxes, scaling, etc.
settingsUniform.setData(settingsData);
settingsUniform.flush();
Cloning for multiple cameras
const mainCam = new UniformBuffer(device, mainData, 'main-camera');
const debugCam = mainCam.clone();
Notes
- Every
UniformBufferkeeps its own CPU cache. If you need to share bytes between buffers, write to the cache once (setData) and callclone(). - All helpers assume WebGPU’s 16-byte alignment. When constructing structs manually, prefer
UniformUtils.createAlignedBufferto avoid off-by-one mistakes. - The module does not automatically flush; callers decide when GPU uploads happen so they can batch updates before encoding passes.