• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / luma.gl / 28672862455

03 Jul 2026 04:33PM UTC coverage: 72.367% (+0.08%) from 72.287%
28672862455

Pull #2726

github

web-flow
Merge 8e5fabf0e into fca0f30c0
Pull Request #2726: feat(experimental): add multi-chunk graph primitives

10895 of 16944 branches covered (64.3%)

Branch coverage included in aggregate %.

145 of 154 new or added lines in 4 files covered. (94.16%)

3 existing lines in 3 files now uncovered.

21317 of 27568 relevant lines covered (77.33%)

5690.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.63
/modules/experimental/src/gpu-primitives/graph-data-view-utils.ts
1
// luma.gl
2
// SPDX-License-Identifier: MIT
3
// Copyright (c) vis.gl contributors
4

5
import {Buffer, type Binding} from '@luma.gl/core';
6
import {getGPUVectorFormatInfo, type GPUVectorFormat} from '@luma.gl/tables';
7
import {GPUCommandGraph, GraphVectorView, type GraphDataView} from './gpu-command-graph';
8

9
const UINT32_BYTE_LENGTH = Uint32Array.BYTES_PER_ELEMENT;
11✔
10
const STORAGE_BINDING_ALIGNMENT = 256;
11✔
11

12
/** @internal */
13
export type GPUScalarFormat = 'uint32' | 'sint32' | 'float32';
14

15
/** @internal */
16
export function validatePackedView<T extends GPUVectorFormat>(
17
  view: GraphDataView,
18
  formats: readonly T[],
19
  name: string
20
): asserts view is GraphDataView<T> {
21
  const formatInfo = getGPUVectorFormatInfo(view.format);
361✔
22
  if (
361✔
23
    !formats.includes(view.format as T) ||
1,444✔
24
    view.byteStride !== formatInfo.byteLength ||
25
    view.rowByteLength !== formatInfo.byteLength ||
26
    view.byteOffset % UINT32_BYTE_LENGTH !== 0
27
  ) {
28
    throw new Error(`${name} must be packed, uint32-aligned ${formats.join(' or ')} GPU data`);
2✔
29
  }
30
}
31

32
/** @internal */
33
export function validatePackedUint32View(view: GraphDataView, name: string): void {
34
  validatePackedView(view, ['uint32'], name);
272✔
35
}
36

37
/** @internal */
38
export function getViewBinding(
39
  view: GraphDataView,
40
  getBuffer: (view: GraphDataView) => Buffer
41
): Binding {
42
  const alignedByteOffset =
43
    Math.floor(view.byteOffset / STORAGE_BINDING_ALIGNMENT) * STORAGE_BINDING_ALIGNMENT;
1,382✔
44
  const prefixByteLength = view.byteOffset - alignedByteOffset;
1,382✔
45
  const viewByteLength =
46
    view.length === 0
1,382!
47
      ? view.rowByteLength
48
      : (view.length - 1) * view.byteStride + view.rowByteLength;
49
  return {
1,382✔
50
    buffer: getBuffer(view),
51
    offset: alignedByteOffset,
52
    size: prefixByteLength + Math.max(viewByteLength, view.rowByteLength)
53
  };
54
}
55

56
/** Offset in 32-bit components from the aligned storage binding. @internal */
57
export function getViewElementOffset(view: GraphDataView): number {
58
  return (view.byteOffset % STORAGE_BINDING_ALIGNMENT) / UINT32_BYTE_LENGTH;
1,364✔
59
}
60

61
/** @internal */
62
export function createTransientView<T extends GPUVectorFormat, Parameters>(
63
  graph: GPUCommandGraph<Parameters>,
64
  id: string,
65
  format: T,
66
  length: number
67
): GraphDataView<T> {
68
  const formatInfo = getGPUVectorFormatInfo(format);
325✔
69
  const buffer = graph.createTransientBuffer({
325✔
70
    id,
71
    byteLength: Math.max(length, 1) * formatInfo.byteLength,
72
    usage: Buffer.STORAGE
73
  });
74
  return graph.createDataView(buffer, {format, length});
325✔
75
}
76

77
/** Creates graph-owned scratch storage with the same chunk topology as a vector. @internal */
78
export function createTransientVectorView<T extends GPUVectorFormat, Parameters>(
79
  graph: GPUCommandGraph<Parameters>,
80
  id: string,
81
  template: GraphVectorView<T>
82
): GraphVectorView<T> {
83
  return new GraphVectorView({
1✔
84
    id,
85
    name: id,
86
    format: template.format,
87
    length: template.length,
88
    valueLength: template.valueLength,
89
    stride: template.stride,
90
    byteStride: template.byteStride,
91
    rowByteLength: template.rowByteLength,
92
    data: template.data.map((chunk, chunkIndex) =>
93
      createTransientView(graph, `${id}-chunk-${chunkIndex}`, template.format, chunk.length)
3✔
94
    )
95
  });
96
}
97

98
/** Validates that two vectors have identical ordered chunk lengths. @internal */
99
export function validateMatchingVectorTopology(
100
  first: GraphVectorView,
101
  second: GraphVectorView,
102
  name: string
103
): void {
104
  if (
4!
105
    first.length !== second.length ||
12✔
106
    first.data.length !== second.data.length ||
107
    first.data.some((chunk, chunkIndex) => chunk.length !== second.data[chunkIndex].length)
12✔
108
  ) {
NEW
109
    throw new Error(`${name} must preserve the same chunk topology`);
×
110
  }
111
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc