Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/api-reference/core/attribute-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Summary:
* auto reallocates attributes when needed
* auto updates attributes with registered updater functions
* allows overriding with application supplied buffers
* can publish multiple logical attributes through one shared WebGPU vertex buffer

For more information consult the [Attribute Management](../../developer-guide/custom-layers/attribute-management.md) article.

Expand Down Expand Up @@ -67,6 +68,8 @@ Takes a single parameter as a map of attribute descriptor objects:
* `stepMode` (string, optional) - One of `'vertex'`, `'instance'` and `'dynamic'`. If set to `'dynamic'`, will be resolved to `'instance'` when this attribute is applied to an instanced model, and `'vertex'` otherwise. Default `'vertex'`.
* `isIndexed` (boolean, optional) - if this is an index attribute
(a.k.a. indices). Default to `false`.
* `bufferGroup` (string, optional) - Opts the attribute into a shared WebGPU vertex buffer. Attributes with the same `bufferGroup` keep independent CPU-side values and invalidation behavior, but are uploaded into one GPU buffer and emitted as one `BufferLayout`.
* `bufferGroupOrder` (number, optional) - Stable ordering of attributes inside a `bufferGroup`.
* `accessor` (string | string[] | Function) - accessor name(s) that will
trigger an update of this attribute when changed. Used with
[`updateTriggers`](./layer.md#updatetriggers).
Expand Down Expand Up @@ -156,9 +159,53 @@ Parameters:
* `modelInfo` (object) - a luma.gl `Model` or a similarly shaped object
+ `isInstanced` (boolean) - used to resolve `stepMode: 'dynamic'`

Notes:

* On WebGPU, attributes that share the same `bufferGroup` are collapsed into a single layout entry.
* Packed groups are currently intended for non-indexed attributes that do not use fp64 emulation.
* Packing is not interleaving in the traditional sense: each logical attribute occupies its own contiguous region inside the shared GPU buffer, and is addressed with byte offsets.


## Remarks

### Packed Buffers on WebGPU

WebGPU limits the number of vertex buffer bindings that may be used by a pipeline. Some layers, especially text and billboard-style layers, naturally accumulate many small per-instance attributes and can hit that limit before they run out of total buffer space.

`AttributeManager` can reduce binding pressure by grouping multiple logical attributes into one shared GPU buffer:

```js
attributeManager.addInstanced({
instanceSizes: {
size: 1,
accessor: 'getSize',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 0
},
instanceAngles: {
size: 1,
accessor: 'getAngle',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 1
},
instanceColors: {
size: 4,
type: 'unorm8',
accessor: 'getColor',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 2
}
});
```

This preserves the existing attribute update model:

* each attribute still has its own updater/accessor
* each attribute can still be invalidated independently
* `shaderAttributes` still work inside a grouped attribute

What changes is only how the GPU-facing buffer is published on WebGPU.

### Attribute Type

The following `type` values are supported for attribute definitions:
Expand Down
38 changes: 38 additions & 0 deletions docs/developer-guide/custom-layers/attribute-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,42 @@ The application provided update functions describe how attributes should be upda

Note that the attribute manager intentionally does not do advanced change detection, but instead makes it easy to build such detection by offering the ability to "invalidate" each attribute separately.

On WebGPU, `AttributeManager` can also reduce vertex-buffer binding pressure by publishing multiple logical attributes through one shared GPU buffer. This is useful for layers with many small per-instance attributes, where the WebGPU vertex-buffer binding limit can become the main constraint.

Grouped attributes still behave like separate attributes on the CPU:

* they keep separate typed-array values
* they are invalidated independently
* they may still use `shaderAttributes`

Only the GPU-facing publication step changes.

```js
attributeManager.addInstanced({
instanceSizes: {
size: 1,
accessor: 'getSize',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 0
},
instanceAngles: {
size: 1,
accessor: 'getAngle',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 1
},
instanceColors: {
size: 4,
type: 'unorm8',
accessor: 'getColor',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 2
}
});
```

This packing is non-interleaved: each attribute occupies its own contiguous region within the shared GPU buffer and is addressed by byte offset in the generated `BufferLayout`.


### Accessors, Shallow Comparisons and updateTriggers

Expand All @@ -49,6 +85,8 @@ While this allows for ultimate performance and control of updates, as well as po

**Note:** The application can provide some buffers and let others be managed by the layer. As an example management of the `instancePickingColors` buffer is normally left to the layer.

When using `bufferGroup`, external buffers are still supplied per logical attribute. Grouping only affects how deck.gl republishes those attributes to WebGPU when binding model inputs.


## More information

Expand Down
2 changes: 2 additions & 0 deletions docs/developer-guide/custom-layers/primitive-layers.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ initializeState() {
}
```

On WebGPU, multiple logical attributes may also be grouped into one shared GPU buffer by assigning the same `bufferGroup`. This is mainly useful for layers with many per-instance attributes and does not change how those attributes are updated on the CPU.

### Handling property updates

[`updateState()`](../../api-reference/core/layer.md#updatestate) - This is the method that you may want to implement to handle property changes.
Expand Down
38 changes: 38 additions & 0 deletions docs/developer-guide/webgpu.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,44 @@ The table below covers the public effect classes exported by `@deck.gl/core`.
| Base map overlays | ❌ | Transparent overlay integration still requires premultiplied-alpha work across deck and the base map stack. |
| Base map interleaving | ❌ | No current base map integration path supports WebGPU interleaving. |

## Attribute Packing

One practical difference between WebGL and WebGPU is that WebGPU enforces a relatively small limit on the number of vertex buffer bindings used by a pipeline. Layers with many small instance attributes can hit that limit even when the total amount of attribute data is modest.

To address this, `AttributeManager` supports shared WebGPU buffers via `bufferGroup`:

```ts
attributeManager.addInstanced({
instanceSizes: {
size: 1,
accessor: 'getSize',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 0
},
instanceAngles: {
size: 1,
accessor: 'getAngle',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 1
},
instanceColors: {
size: 4,
type: 'unorm8',
accessor: 'getColor',
bufferGroup: 'label-instance-data',
bufferGroupOrder: 2
}
});
```

This keeps the existing attribute lifecycle intact:

* attributes are still updated and invalidated independently
* attributes may still define `shaderAttributes`
* applications may still supply external attributes per logical attribute

The change is only in the WebGPU publication step: grouped attributes are emitted as one `BufferLayout` and one shared GPU buffer with byte offsets for each logical attribute.

## Background

While the visible WebGPU surface is still limited, much of the groundwork has already happened in luma.gl, the GPU framework powering deck.gl. deck.gl is following that work by porting its shader modules, layers, and render features incrementally.
Expand Down
Loading
Loading