Skip to main content

GPUData

From: v10Status: Work-In-Progress

GPUData describes one GPU buffer plus typed row metadata. It is the lowest-level storage object in @luma.gl/tables: each GPUData owns or borrows its own Buffer or DynamicBuffer, and higher-level table objects refer to buffers through GPUData.

GPUDataView is the non-owning physical counterpart: one fixed-width format, value count, byte offset, and byte stride over any buffer-like resource.

Usage

import {GPUData} from '@luma.gl/tables';

const gpuData = new GPUData({
buffer,
format: 'float32x3',
length,
byteStride: 12,
ownsBuffer: true
});

Interleaved rows can use a physical struct format. Field declarations use the same fixed-width format strings as GPUVectorFormat:

import {GPUData} from '@luma.gl/tables';

const data = new GPUData({
buffer,
length,
format: {
a: 'sint32',
b: 'float32'
},
layout: 'packed'
});
const b = data.getChild('b'); // GPUDataView<'float32'> | null

getChild() follows the Apache Arrow-style child API. It creates a borrowed strided view of the selected field without allocating storage or copying bytes.

When the input starts as Apache Arrow, prefer makeGPUDataFromArrowData() from @luma.gl/arrow; it uploads Arrow values into GPU buffers and fills in the required format, layout, and readback metadata.

Struct Formats

An object passed to GPUData.format describes several named fixed-width fields stored in each row. GPUData resolves the physical offsets and retains the canonical GPUDataStructFormat in its format property. The declaration describes bytes in the buffer and does not declare a parallel shader struct type.

The supported layout strings are:

LayoutMeaning
wgsl-storageDefault. Aligns raw field carrier types using WGSL storage-struct rules. Compact formats such as unorm8x4 use u32 carriers.
packedApplies the minimum padding required by WebGPU vertex-buffer layout rules.

For packed, each field offset is aligned to min(4, byteLength(format)), and the final byteStride is rounded up to four bytes. It therefore means minimally padded and vertex-valid, not unconditional byte concatenation. For example, {tag: 'uint8', value: 'float32'} uses offsets 0 and 4 with an eight-byte stride. These are WebGPU vertex-buffer rules, not an additional WGSL memory layout, so there is no wgsl-vertex layout name.

The returned format contains:

PropertyMeaning
typeAlways struct.
layoutwgsl-storage or packed.
fieldsFields in declaration order, each with format, byteOffset, and byteLength.
componentsTotal scalar components represented by one row.
rowByteLengthBytes through the end of the final physical field, excluding trailing row padding.
byteStrideBytes between adjacent rows, including required trailing padding.

For wgsl-storage, layout is based on raw carriers for the stored bytes, not decoded shader value types. For example, unorm8x4 occupies a u32 carrier; a storage shader must explicitly decode it, while vertex fetch exposes normalized values. The public format remains physical and does not publish a parallel shader struct declaration.

Use getBufferLayoutFromGPUDataStructFormat(name, format, options?) to lower a struct format into an interleaved BufferLayout. The helper preserves field order, offsets, formats, row stride, and optional stepMode.

Constructor

new GPUData(props)

PropTypeDefaultMeaning
bufferBuffer | DynamicBufferRequiredGPU buffer containing this chunk's bytes.
formatGPUVectorFormat | GPUDataStructFieldsundefinedA scalar/list format string or an inline record of named fixed-width field formats.
layoutwgsl-storage | packedwgsl-storagePhysical packing rules for an inline struct format. Invalid with a scalar/list format.
lengthnumberRequiredNumber of logical rows in this chunk.
valueLengthnumberlengthNumber of fixed rows or flattened vertex-list element values.
stridenumberDerived from formatNumber of scalar values represented by one fixed row or flattened element.
byteOffsetnumber0Byte offset of the first logical row in this chunk's buffer. Most adapters use 0 because chunks own their uploaded buffers.
byteStridenumberDerived from formatBytes between adjacent fixed rows or flattened elements.
rowByteLengthnumberDerived from formatBytes occupied by one fixed row or flattened element payload.
ownsBufferbooleanfalseWhether destroy() releases the backing buffer.
readbackMetadataunknownundefinedProducer-owned metadata retained for adapter-level readback.
dataTypeunknownundefinedDeprecated adapter-owned logical metadata retained during migration.

Properties

PropertyTypeMeaning
bufferBuffer | DynamicBufferGPU buffer containing this chunk's bytes.
formatGPUDataFormat | undefinedCanonical memory-layout descriptor when this chunk has a typed physical view.
typeunknownDeprecated adapter-owned logical metadata.
dataTypeunknownDeprecated adapter-owned logical metadata.
lengthnumberNumber of logical rows in this chunk.
valueLengthnumberNumber of fixed rows or flattened vertex-list element values.
stridenumberNumber of scalar values represented by one fixed row or flattened element.
byteOffsetnumberByte offset of the first logical row.
byteStridenumberBytes between adjacent fixed rows or flattened elements.
rowByteLengthnumberBytes occupied by one fixed row or flattened element payload.
readbackMetadataunknownOptional producer-owned metadata.
ownsBufferbooleanWhether this data range currently owns its backing buffer.

Methods

getChild(name): GPUDataView | null

Returns a borrowed, precisely typed field view for struct-formatted data. The view combines the parent byte offset with the field offset and preserves the parent row stride. Literal field names return the corresponding precise view type; a runtime string returns the union of the struct's child view types. Returns null for an unknown field or non-struct data.

getChildAt(index): GPUDataView | null

Returns a borrowed field view by declaration order, or null when the index is out of range or the data is not struct-formatted.

destroy(): void

Destroys the backing buffer only when ownsBuffer is true. Borrowed buffers are left alive.

Ownership

GPUData is the storage-owning layer. GPUVector, GPURecordBatch, and GPUTable follow their ownership graph down to GPUData, but buffer destruction is controlled here.

GPUData should not be used as a cheap view into a larger aggregate table buffer. If a streaming adapter receives a new source batch, it should create new GPUData objects with their own buffers and append those chunks to a GPUVector.