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

visgl / luma.gl / 14683349798

26 Apr 2025 05:08PM UTC coverage: 74.055% (-0.9%) from 74.913%
14683349798

push

github

web-flow
feat(core): TextureFormat generics (#2377)

2019 of 2652 branches covered (76.13%)

Branch coverage included in aggregate %.

62 of 262 new or added lines in 15 files covered. (23.66%)

196 existing lines in 9 files now uncovered.

26575 of 35960 relevant lines covered (73.9%)

47.35 hits per line

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

54.55
/modules/core/src/portable/uniform-buffer-layout.ts
1
// luma.gl
1✔
2
// SPDX-License-Identifier: MIT
1✔
3
// Copyright (c) vis.gl contributors
1✔
4

1✔
5
import type {PrimitiveDataType} from '../shadertypes/data-types/data-types';
1✔
6
import type {VariableShaderType} from '../shadertypes/data-types/shader-types';
1✔
7
import {alignTo} from '../shadertypes/data-types/decode-data-types';
1✔
8
import {getVariableShaderTypeInfo} from '../shadertypes/data-types/decode-shader-types';
1✔
9

1✔
10
import type {UniformValue} from '../adapter/types/uniforms';
1✔
11
import {getScratchArrayBuffer} from '../utils/array-utils-flat';
1✔
12
import {isNumberArray} from '../utils/is-array';
1✔
13
import {log} from '../utils/log';
1✔
14

1✔
15
/**
1✔
16
 * Smallest buffer size that can be used for uniform buffers.
1✔
17
 * TODO - does this depend on device?
1✔
18
 */
1✔
19
const minBufferSize: number = 1024;
1✔
20

1✔
21
/**
1✔
22
 * Std140 layout for uniform buffers
1✔
23
 * Supports manual listing of uniforms
1✔
24
 */
1✔
25
export class UniformBufferLayout {
1✔
26
  readonly layout: Record<string, {offset: number; size: number; type: PrimitiveDataType}> = {};
9✔
27

9✔
28
  /** number of bytes needed for buffer allocation */
9✔
29
  readonly byteLength: number;
9✔
30

9✔
31
  /** Create a new UniformBufferLayout given a map of attributes. */
9✔
32
  constructor(uniformTypes: Record<string, VariableShaderType>) {
9✔
33
    /** number of 4 byte slots taken */
9✔
34
    let size: number = 0;
9✔
35

9✔
36
    // Add layout (type, size and offset) definitions for each uniform in the layout
9✔
37
    for (const [key, uniformType] of Object.entries(uniformTypes)) {
9✔
38
      const typeAndComponents = getVariableShaderTypeInfo(uniformType);
114✔
39
      const {type, components: count} = typeAndComponents;
114✔
40
      // First, align (bump) current offset to an even multiple of current object (1, 2, 4)
114✔
41
      size = alignTo(size, count);
114✔
42
      // Use the aligned size as the offset of the current uniform.
114✔
43
      const offset = size;
114✔
44
      // Then, add our object's padded size ((1, 2, multiple of 4) to the current offset
114✔
45
      size += count;
114✔
46
      this.layout[key] = {type, size: count, offset};
114✔
47
    }
114✔
48
    size += (4 - (size % 4)) % 4;
9✔
49

9✔
50
    const actualByteLength = size * 4;
9✔
51
    this.byteLength = Math.max(actualByteLength, minBufferSize);
9✔
52
  }
9✔
53

9✔
54
  /** Get the data for the complete buffer */
9✔
55
  getData(uniformValues: Record<string, UniformValue>): Uint8Array {
9✔
UNCOV
56
    const bufferSize = Math.max(this.byteLength, minBufferSize);
×
UNCOV
57

×
UNCOV
58
    // Allocate three typed arrays pointing at same memory
×
UNCOV
59
    const arrayBuffer = getScratchArrayBuffer(bufferSize);
×
UNCOV
60
    const typedArrays = {
×
UNCOV
61
      i32: new Int32Array(arrayBuffer),
×
UNCOV
62
      u32: new Uint32Array(arrayBuffer),
×
UNCOV
63
      f32: new Float32Array(arrayBuffer),
×
UNCOV
64
      // TODO not implemented
×
UNCOV
65
      f16: new Uint16Array(arrayBuffer)
×
UNCOV
66
    };
×
UNCOV
67
    // TODO is this needed?
×
UNCOV
68
    // typedArrays.i32.fill(0);
×
UNCOV
69

×
UNCOV
70
    for (const [name, value] of Object.entries(uniformValues)) {
×
UNCOV
71
      const uniformLayout = this.layout[name];
×
UNCOV
72
      if (!uniformLayout) {
×
73
        log.warn(`Supplied uniform value ${name} not present in uniform block layout`)();
×
74
        // eslint-disable-next-line no-continue
×
75
        continue;
×
76
      }
×
UNCOV
77

×
UNCOV
78
      const {type, size, offset} = uniformLayout;
×
UNCOV
79
      const typedArray = typedArrays[type];
×
UNCOV
80
      if (size === 1) {
×
UNCOV
81
        if (typeof value !== 'number' && typeof value !== 'boolean') {
×
82
          log.warn(
×
83
            `Supplied value for single component uniform ${name} is not a number: ${value}`
×
84
          )();
×
85
          // eslint-disable-next-line no-continue
×
86
          continue;
×
87
        }
×
UNCOV
88
        // single value -> just set it
×
UNCOV
89
        typedArray[offset] = Number(value);
×
UNCOV
90
      } else {
×
91
        if (!isNumberArray(value)) {
×
92
          log.warn(
×
93
            `Supplied value for multi component / array uniform ${name} is not a numeric array: ${value}`
×
94
          )();
×
95
          // eslint-disable-next-line no-continue
×
96
          continue;
×
97
        }
×
98
        // vector/matrix -> copy the supplied (typed) array, starting from offset
×
99
        // TODO: we should limit or check size in case the supplied data overflows
×
100
        typedArray.set(value, offset);
×
101
      }
×
UNCOV
102
    }
×
UNCOV
103

×
UNCOV
104
    return new Uint8Array(arrayBuffer);
×
UNCOV
105
  }
×
106

9✔
107
  /** Does this layout have a field with specified name */
9✔
108
  has(name: string) {
9✔
109
    return Boolean(this.layout[name]);
×
110
  }
×
111

9✔
112
  /** Get offset and size for a field with specified name */
9✔
113
  get(name: string): {offset: number; size: number} | undefined {
9✔
114
    const layout = this.layout[name];
×
115
    return layout;
×
116
  }
×
117
}
9✔
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