Skip to main content

GPUTableShaderBindings

GPUTableShaderBindings owns backend-specific resources prepared by resolving one GPUTable against a fixed GPUInputSchema and ShaderLayout. It preserves table batches and returns ordinary resources suitable for Model.setAttributes() and Model.setBindings().

Use GPUTableModel for automatic integration. Use this class directly when an application owns its model or render-pipeline lifecycle.

Usage

const prepared = new GPUTableShaderBindings(device, {
table,
gpuInputSchema: PointModel.gpuInputSchema,
shaderLayout
});

const model = new Model(device, {
source,
modules: prepared.shaderModule ? [prepared.shaderModule] : [],
shaderLayout,
bufferLayout: prepared.bufferLayout,
attributes: prepared.batches[0]?.attributes,
bindings: prepared.batches[0]?.bindings
});

for (const batch of prepared.batches) {
model.setAttributes(batch.attributes);
model.setBindings(batch.bindings);
model.setConstantAttributes(prepared.constantAttributes);
model.draw(renderPass);
}

model.destroy();
prepared.destroy();

Constructor

new GPUTableShaderBindings(device, {
table,
gpuInputSchema,
shaderLayout
});

The schema and shader layout define the pipeline contract and remain fixed for the object lifetime. Use updateBindings() to replace only the table.

Properties

PropertyTypeMeaning
deviceDeviceDevice used for backend preparation.
tableGPUTableCurrently prepared table.
gpuInputSchemaGPUInputSchemaFixed logical input contract.
shaderLayoutShaderLayoutFixed shader attribute and binding contract.
bufferLayoutBufferLayout[]Final backend-ready attribute layouts.
batchesGPUTableShaderBindingBatch[]Draw-ready resources per preserved batch.
constantAttributesRecord<string, TypedArray>WebGL context constant values.
shaderModuleShaderModule | undefinedGenerated WebGPU storage row-index module.
ownedByteLengthnumberCurrent byte length of resources owned by this object.
type GPUTableShaderBindingBatch = {
attributes: Record<string, Buffer | DynamicBuffer>;
attributeBuffers: Array<Buffer | DynamicBuffer>;
bindings: Record<string, Binding>;
};

attributeBuffers follows bufferLayout order. attributes exposes the same resources by logical layout name.

updateBindings(table)

Validates and prepares a replacement table using the existing schema and shader layout. Compatible owned buffers are reused and rewritten. Obsolete owned resources are destroyed after the next state has been prepared.

The replacement table may change row count, batch count, or whether an optional input is varying or constant. A resulting attribute-layout change requires the model to apply the new bufferLayout; GPUTableModel does this automatically.

destroy()

Destroys zero-stride vertex buffers, one-row storage buffers, and the generated row multiplier uniform. It does not destroy the caller-owned table or its GPUData. Repeated calls are safe. Updating a destroyed object throws.

Attribute Resolution

For varying inputs, columnName selects the table layout and attributeName selects the shader attribute. Interleaved layouts retain only attributes selected as varying.

For WebGPU constants, compatible values with the same step mode are packed into a single buffer layout with byteStride: 0. Every draw therefore reads the same payload for every vertex or instance.

For WebGL constants, no vertex buffer is allocated. Raw memory values are converted to the float or integer values visible to the shader, including normalized integer, half-float, packed unorm10-10-10-2, and BGRA formats.

Storage Resolution

Varying columns produce batch-local Binding ranges that preserve GPUData.byteOffset and uploaded byte size. Constants produce aligned one-row storage buffers.

When storage declarations are present, shaderModule contributes:

@group(0) @binding(auto)
var<uniform> gpuTableColumns : GPUTableColumnUniforms;

fn gpuTable_getRowIndex(rowIndex : u32, rowMultiplier : u32) -> u32 {
return rowIndex * rowMultiplier;
}

Each storage binding receives a generated field named <storageBindingName>RowMultiplier:

let color = pointColors[
gpuTable_getRowIndex(
instanceIndex,
gpuTableColumns.pointColorsRowMultiplier
)
];

The multiplier is 1 for varying columns and 0 for constants. The uniform binding is added to every prepared batch as gpuTableColumns.

GPUTableModel Integration

const model = new GPUTableModel(device, {
source,
shaderLayout,
gpuInputSchema: PointModel.gpuInputSchema,
table,
tableCount: 'instance'
});

model.drawBatches(renderPass);
model.setProps({table: replacementTable});
model.destroy();

The model owns its GPUTableShaderBindings but does not own the table.

Remarks

  • Pipeline compatibility: GPUInputSchema and ShaderLayout cannot change through updateBindings(). Construct a new object for a new pipeline contract.
  • Schema validation: required inputs must exist as varying vectors. Optional fixed-width inputs may be vectors or constants if their format is listed.
  • Dynamic buffers: prepared attributes retain DynamicBuffer wrappers; storage ranges resolve their current concrete buffers when prepared.
  • Batch preservation: the class never packs table batches. batches[n] corresponds to table.batches[n].
  • Interleaving: a constant override is removed from its varying interleaved layout. Empty layouts are omitted from the pipeline.
  • Allocation reuse: update reuses an owned buffer only when purpose, usage, and byte length remain compatible.
  • Alignment: ownedByteLength reports actual allocated bytes, which may exceed GPUConstant.byteLength.
  • Failure behavior: validation runs before table state is replaced. A failed update leaves the previously published binding state active.
  • Optional absence: this class omits absent optional table resources. A shader that statically requires such a binding still needs a model-specific dummy or fallback.
  • Ownership: caller-owned GPUData, GPUVector, GPUTable, and explicit model bindings are never destroyed by this object.