Skip to content

Uniform Module

src/uniform/ contains the lightweight abstraction we use for WebGPU uniform buffers. It wraps a GPU buffer, keeps a CPU-side cache, enforces size/alignment rules, and exposes helpers for packing data into std140-friendly layouts. The renderer, preprocessors, and managers all rely on these helpers to keep camera and render-setting uniforms in sync every frame.

Responsibilities

  • Normalize any ArrayBuffer/typed-array input into a GPU uniform buffer with the correct usage flags.
  • Maintain a CPU-side copy of the data so multiple updates can be batched before a single flush() call.
  • Provide a shared bindGroupLayout so pipelines can bind uniforms without recreating layouts.
  • Offer packing/alignment helpers (UniformUtils) for vec/mat data that must obey WebGPU’s 16-byte rules.

Components

Component Path Purpose
UniformBuffer uniform_buffer.ts Concrete implementation of IUniformBuffer. Owns the GPU buffer, bind group, cached data, and flush/clone/destroy methods.
UniformUtils index.ts Static helpers for aligning sizes and packing vec/mat data with padding.
IUniformBuffer, UniformConfig, UniformData index.ts Interfaces and types shared across modules.

Data flow

CPU struct (camera/settings/params)
   �?setData()
UniformBuffer cache (ArrayBuffer)
   �?flush()
GPU uniform buffer �?shaders (via cached bind group)
  • setData(view) copies typed-array bytes into the CPU cache (size must match exactly).
  • flush(device?) uploads the cached bytes via queue.writeBuffer. If no device is passed, it uses the one provided at construction.
  • data getter returns a copy of the cache when debugging or hot-reloading settings.

Usage example

import { UniformBuffer, UniformUtils } from 'src/uniform';

const cameraBytes = UniformUtils.createAlignedBuffer(272);
const cameraUniform = new UniformBuffer(device, cameraBytes, 'camera');

function updateCamera(cameraData: ArrayBufferView) {
  cameraUniform.setData(cameraData);
  cameraUniform.flush();
}

renderPass.setBindGroup(0, cameraUniform.bindGroup);

For small structs (e.g., render settings) you can build a Float32Array, call setData, and flush once per frame. Batch multiple uniforms by writing all caches first, then calling flush() on each before encoding compute/render passes.

Integration points

  • Renderer (GaussianRenderer) �?holds cameraUniforms, settingsUniforms, modelParamsUniforms. Every frame it packs data via UniformBuffer.setData() and flushes before dispatching preprocess or render passes.
  • Preprocessor (GaussianPreprocessor) �?packs camera and render settings into UniformBuffers prior to each compute pass; ONNX paths overwrite sections via queue.copyBufferToBuffer using the same buffers.
  • Point cloud model params �?each PointCloud owns a UniformBuffer (modelParamsUniforms) that shaders read in preprocess/render pipelines.

Because uniforms sit on the hot path for every command buffer, the module keeps the API minimal: construct once, reuse the GPU buffer, and only touch the CPU cache when values actually change.

  • Architecture – Layout diagrams, std140 padding strategies, and binding lifecycle.
  • API ReferenceUniformBuffer methods, config interfaces, and helper utilities.
  • Renderer Module – Shows how camera/settings uniforms are consumed per frame.
  • Preprocess Module – Details the compute uniforms fed to projection shaders.
  • Point Cloud Module – Explains how per-model parameter buffers are produced.