Skip to main content

GPU Memory Layouts

GPU buffers are byte ranges. A layout describes how shader-visible rows and columns are mapped onto those bytes.

This page uses three layout terms:

  • Packed - one logical column in one tightly packed buffer.
  • Interleaved - multiple columns share one buffer, with each row storing all columns together.
  • Segmented - multiple packed columns share one buffer, stored as separate contiguous byte ranges.

Layout Shapes

Packed

A packed buffer stores one column with no unrelated data between rows.

positions buffer
row 0: position
row 1: position
row 2: position

Use packed layout when a column is updated, transferred, or bound independently.

Interleaved

An interleaved buffer stores multiple columns inside each row.

instance buffer
row 0: position, color, radius
row 1: position, color, radius
row 2: position, color, radius

Use interleaved layout when columns are usually consumed together by a render or transform pipeline.

Segmented

A segmented buffer stores multiple packed columns in one buffer.

table buffer
segment 0: position row 0, position row 1, position row 2
segment 1: color row 0, color row 1, color row 2
segment 2: radius row 0, radius row 1, radius row 2

Use segmented layout when a table should have one allocation but columns should remain columnar for storage-buffer access.

Terminology

TermColumns per bufferRow layoutColumn layoutTypical use
Packed1One column value per rowContiguousIndependent attributes, storage arrays
InterleavedManyAll column values per rowStridedVertex attributes consumed together
SegmentedManyOne column value per row inside each segmentContiguous per segmentStorage-buffer tables, grouped allocations

Packed and segmented are both columnar. The difference is allocation: packed uses one buffer per column, while segmented stores several packed columns in one buffer.

Interleaved and segmented both store multiple columns in one buffer. The difference is order: interleaved is row-major, while segmented is column-major.

GPU Pipeline Compatibility

LayoutRender vertex attributesWebGL transform feedbackWebGPU compute storage buffersBuffer copy commands
PackedDirectDirectDirectDirect
InterleavedDirect with BufferLayout.attributesDirect as input or output, not in-placeUsable with explicit strided readsRow ranges are not contiguous per column
SegmentedUsable as separate attribute bindings into one buffer rangeUsable with explicit offsetsDirect for columnar storage readsColumn segments are contiguous

Render pipelines use BufferLayout and vertex formats to interpret bytes. This supports normalized attributes such as unorm8x4 because vertex fetch converts them to shader-visible values.

Compute pipelines use storage bindings. They read raw storage values, so normalized formats are not decoded unless the compute shader does that work explicitly.

luma.gl Concepts

ConceptPackedInterleavedSegmented
BufferOne buffer per columnOne buffer for several columnsOne buffer for several column segments
BufferLayoutname plus formatattributes with offsets and shared byteStrideMultiple layouts or explicit segment metadata
ArrowGPUVectorNumeric Arrow typeBinary plus bufferLayoutNumeric or Binary view plus segment metadata
ArrowGPUTableMultiple vectorsInterleaved vector contributes multiple attributesFuture table layout can map names to segments

Operation Patterns

OperationPacked inputInterleaved inputSegmented input
addDirectDeinterleave or use strided shader readsDirect by segment
interleaveProduces an interleaved bufferAppends or rebuilds interleaved rowsReads segments and writes row-major output
deinterleaveNo-op or copyExtracts one attribute to a packed bufferSelects or copies one segment
froundDirect for packed Float64Requires attribute extraction or strided readsDirect by segment

In-place operations require stricter ownership and aliasing rules. They are practical with WebGPU read-write storage buffers when the input and output have compatible byte layouts. They are not a good fit for WebGL transform feedback, where input and output buffers should not alias.

Choosing a Layout

NeedPrefer
Bind one attribute independentlyPacked
Minimize vertex-buffer bindings for attributes consumed togetherInterleaved
Keep table columns in one allocation for computeSegmented
Use normalized vertex formatsPacked or interleaved render attributes
Run compute over raw storage valuesPacked or segmented
Extract one column frequentlyPacked or segmented

Arrow Notes

Arrow is naturally columnar. A normal Arrow column maps cleanly to a packed GPU vector.

Interleaved GPU buffers do not map to a single numeric Arrow column. In luma.gl they are represented as ArrowGPUVector<Binary> with bufferLayout metadata describing the attributes inside each row.

Segmented buffers are still columnar, but the columns share one GPU allocation. They need table-level segment metadata so each column name can resolve to a buffer, byte offset, row count, row stride, and Arrow type.