Symbols in this topic
StructuredUniform
Low-level structured uniform buffer that computes WGSL-compatible offsets from a schema and writes typed values into one stable uniform buffer. Prefer main API (vgpu) set({ params: ... }) unless you need a reusable resource and generated WGSL struct text.
Import
TypeScript
1
2
import { StructuredUniform } from "vgpu/core";
import type { StructuredUniformOptions, UniformValues, ScalarUniformType, VectorUniformInput, UniformLayoutInfo, UniformField, WgslUniformType } from "vgpu/core";Signature
TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import type { BindVisibility, Device } from "vgpu/core";
type ScalarUniformType = "f32" | "u32" | "i32";
type VectorUniformInput = readonly number[] | Float32Array | Uint32Array | Int32Array;
type WgslUniformType =
| "f32" | "u32" | "i32"
| "vec2f" | "vec3f" | "vec4f"
| "vec2u" | "vec3u" | "vec4u"
| "vec2i" | "vec3i" | "vec4i"
| "mat3x3f" | "mat4x4f";
type UniformValues<S extends Record<string, WgslUniformType>> = {
[K in keyof S]: S[K] extends ScalarUniformType ? number : VectorUniformInput;
};
interface UniformField {
readonly name: string;
readonly type: WgslUniformType;
readonly offset: number;
readonly size: number;
readonly align: number;
}
interface UniformLayoutInfo {
readonly fields: readonly UniformField[];
readonly offsets: Readonly<Record<string, number>>;
readonly byteSize: number;
}
interface StructuredUniformOptions<S extends Record<string, WgslUniformType>> {
readonly schema: S;
readonly label?: string;
readonly visibility?: BindVisibility;
}
declare class StructuredUniform<S extends Record<string, WgslUniformType>> {
readonly device: Device;
readonly schema: S;
readonly layout: UniformLayoutInfo;
readonly byteSize: number;
readonly offsets: Readonly<Record<keyof S, number>>;
readonly buffer: import("vgpu/core").Buffer;
constructor(device: Device, opts: StructuredUniformOptions<S>);
get gpu(): GPUBuffer;
get bindGroupLayout(): GPUBindGroupLayout;
get bindGroup(): GPUBindGroup;
write(values: Partial<UniformValues<S>>): void;
wgsl(structName?: string): string;
destroy(): void;
dispose(): void;
}Parameters
| Param | Type | Required | Default | Notes |
|---|---|---|---|---|
| device | Device | ✔ | — | Core device. |
| opts | StructuredUniformOptions<S> | ✔ | — | Schema and optional labels/visibility. |
| opts.schema | S extends Record<string, WgslUniformType> | ✔ | — | Insertion order is WGSL member order. Empty schema and unsupported type strings are invalid. |
| opts.label | string | ✖ | undefined | Buffer label; lazy layout/bind group labels become ${label}.bgl and ${label}.bg. |
| opts.visibility | BindVisibility | ✖ | ["vertex", "fragment"] | Used only by lazy bindGroupLayout; ignored until that getter is read. |
| write.values | Partial<UniformValues<S>> | ✔ | — | Field patch. Scalars require number; vectors/matrices require exact-length array or typed array. |
| wgsl.structName | string | ✖ | "Uniforms" | Name for generated WGSL struct text. |
Returns: Constructor returns StructuredUniform; bindGroupLayout and bindGroup lazily create native objects; write() returns void; wgsl() returns WGSL struct source; destroy() / dispose() return void.
Throws: VGPU-CORE-INVALID-USAGE when schema is empty, contains unsupported types, writing an unknown field, writing a scalar with a non-number, writing vector/matrix data with a non-array, wrong exact length, or using the object after destroy.
Examples
TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { init } from "vgpu/mock";
import { StructuredUniform } from "vgpu/core";
const gpu = await init();
const params = new StructuredUniform(gpu.device, {
label: "params",
schema: { time: "f32", tint: "vec3f", viewProjection: "mat4x4f" },
});
params.write({
time: 1,
tint: [1, 0.5, 0.25],
viewProjection: new Float32Array(16),
});
const wgsl = params.wgsl("Params");
void wgsl;TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
import { init, draw } from "vgpu/mock";
import { StructuredUniform } from "vgpu/core";
const gpu = await init();
const params = new StructuredUniform(gpu.device, { schema: { value: "f32" } });
const drawable = draw(gpu, { shader: `
struct Params { value: f32 }
@group(0) @binding(0) var<uniform> params: Params;
@vertex fn vs_main() -> @builtin(position) vec4f { return vec4f(0, 0, 0, 1); }
@fragment fn fs_main() -> @location(0) vec4f { return vec4f(params.value); }
` });
params.write({ value: 1 });
drawable.set({ params });Notes
vec3*fields align to 16 bytes; inspectoffsets/layoutinstead of assuming tight packing.mat3x3fstores columns at 16-byte stride and needs exactly 9 values inwrite().wgsl()only emits the struct; you still declare the@group/@binding var<uniform>line in your shader.- See also:
Uniform,SharedUniforms,UniformPool,Draw.set.