• 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

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

1✔
5
import type {VariableShaderType} from '../shadertypes/data-types/shader-types';
1✔
6
import type {UniformValue} from '../adapter/types/uniforms';
1✔
7
import type {Device} from '../adapter/device';
1✔
8
import {Buffer} from '../adapter/resources/buffer';
1✔
9
import {log} from '../utils/log';
1✔
10
import {UniformBlock} from './uniform-block';
1✔
11
import {UniformBufferLayout} from './uniform-buffer-layout';
1✔
12

1✔
13
/**
1✔
14
 * A uniform store holds a uniform values for one or more uniform blocks,
1✔
15
 * - It can generate binary data for any uniform buffer
1✔
16
 * - It can manage a uniform buffer for each block
1✔
17
 * - It can update managed uniform buffers with a single call
1✔
18
 * - It performs some book keeping on what has changed to minimize unnecessary writes to uniform buffers.
1✔
19
 */
1✔
20
export class UniformStore<
1✔
21
  TPropGroups extends Record<string, Record<string, unknown>> = Record<
1✔
22
    string,
1✔
23
    Record<string, unknown>
1✔
24
  >
1✔
25
> {
1✔
26
  /** Stores the uniform values for each uniform block */
21✔
27
  uniformBlocks = new Map<keyof TPropGroups, UniformBlock>();
21✔
28
  /** Can generate data for a uniform buffer for each block from data */
21✔
29
  uniformBufferLayouts = new Map<keyof TPropGroups, UniformBufferLayout>();
21✔
30
  /** Actual buffer for the blocks */
21✔
31
  uniformBuffers = new Map<keyof TPropGroups, Buffer>();
21✔
32

21✔
33
  /**
21✔
34
   * Create a new UniformStore instance
21✔
35
   * @param blocks
21✔
36
   */
21✔
37
  constructor(
21✔
38
    blocks: Record<
21✔
39
      keyof TPropGroups,
21✔
40
      {
21✔
41
        uniformTypes?: Record<string, VariableShaderType>;
21✔
42
        defaultProps?: Record<string, unknown>;
21✔
43
        defaultUniforms?: Record<string, UniformValue>;
21✔
44
      }
21✔
45
    >
21✔
46
  ) {
21✔
47
    for (const [bufferName, block] of Object.entries(blocks)) {
21✔
48
      const uniformBufferName = bufferName as keyof TPropGroups;
9✔
49

9✔
50
      // Create a layout object to help us generate correctly formatted binary uniform buffers
9✔
51
      const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes || {});
9!
52
      this.uniformBufferLayouts.set(uniformBufferName, uniformBufferLayout);
9✔
53

9✔
54
      // Create a Uniform block to store the uniforms for each buffer.
9✔
55
      const uniformBlock = new UniformBlock({name: bufferName});
9✔
56
      uniformBlock.setUniforms(block.defaultUniforms || {});
9!
57
      this.uniformBlocks.set(uniformBufferName, uniformBlock);
9✔
58
    }
9✔
59
  }
21✔
60

21✔
61
  /** Destroy any managed uniform buffers */
21✔
62
  destroy(): void {
21✔
63
    for (const uniformBuffer of this.uniformBuffers.values()) {
9!
64
      uniformBuffer.destroy();
×
65
    }
×
66
  }
9✔
67

21✔
68
  /**
21✔
69
   * Set uniforms
21✔
70
   * Makes all properties partial
21✔
71
   */
21✔
72
  setUniforms(
21✔
73
    uniforms: Partial<{[group in keyof TPropGroups]: Partial<TPropGroups[group]>}>
7✔
74
  ): void {
7✔
75
    for (const [blockName, uniformValues] of Object.entries(uniforms)) {
7!
UNCOV
76
      this.uniformBlocks.get(blockName)?.setUniforms(uniformValues);
×
UNCOV
77
      // We leverage logging in updateUniformBuffers(), even though slightly less efficient
×
UNCOV
78
      // this.updateUniformBuffer(blockName);
×
UNCOV
79
    }
×
80

7✔
81
    this.updateUniformBuffers();
7✔
82
  }
7✔
83

21✔
84
  /** Get the required minimum length of the uniform buffer */
21✔
85
  getUniformBufferByteLength(uniformBufferName: keyof TPropGroups): number {
21✔
86
    return this.uniformBufferLayouts.get(uniformBufferName)?.byteLength || 0;
9!
87
  }
9✔
88

21✔
89
  /** Get formatted binary memory that can be uploaded to a buffer */
21✔
90
  getUniformBufferData(uniformBufferName: keyof TPropGroups): Uint8Array {
21✔
UNCOV
91
    const uniformValues = this.uniformBlocks.get(uniformBufferName)?.getAllUniforms() || {};
×
UNCOV
92
    // @ts-ignore
×
UNCOV
93
    return this.uniformBufferLayouts.get(uniformBufferName)?.getData(uniformValues);
×
UNCOV
94
  }
×
95

21✔
96
  /**
21✔
97
   * Creates an unmanaged uniform buffer (umnanaged means that application is responsible for destroying it)
21✔
98
   * The new buffer is initialized with current / supplied values
21✔
99
   */
21✔
100
  createUniformBuffer(
21✔
101
    device: Device,
×
102
    uniformBufferName: keyof TPropGroups,
×
103
    uniforms?: Partial<{[group in keyof TPropGroups]: Partial<TPropGroups[group]>}>
×
104
  ): Buffer {
×
105
    if (uniforms) {
×
106
      this.setUniforms(uniforms);
×
107
    }
×
108
    const byteLength = this.getUniformBufferByteLength(uniformBufferName);
×
109
    const uniformBuffer = device.createBuffer({
×
110
      usage: Buffer.UNIFORM | Buffer.COPY_DST,
×
111
      byteLength
×
112
    });
×
113
    // Note that this clears the needs redraw flag
×
114
    const uniformBufferData = this.getUniformBufferData(uniformBufferName);
×
115
    uniformBuffer.write(uniformBufferData);
×
116
    return uniformBuffer;
×
117
  }
×
118

21✔
119
  /** Get the managed uniform buffer. "managed" resources are destroyed when the uniformStore is destroyed. */
21✔
120
  getManagedUniformBuffer(device: Device, uniformBufferName: keyof TPropGroups): Buffer {
21✔
121
    if (!this.uniformBuffers.get(uniformBufferName)) {
9✔
122
      const byteLength = this.getUniformBufferByteLength(uniformBufferName);
9✔
123
      const uniformBuffer = device.createBuffer({
9✔
124
        usage: Buffer.UNIFORM | Buffer.COPY_DST,
9✔
125
        byteLength
9✔
126
      });
9✔
127
      this.uniformBuffers.set(uniformBufferName, uniformBuffer);
9✔
128
    }
9✔
129
    // this.updateUniformBuffers();
9✔
130
    // @ts-ignore
9✔
131
    return this.uniformBuffers.get(uniformBufferName);
9✔
132
  }
9✔
133

21✔
134
  /** Updates all uniform buffers where values have changed */
21✔
135
  updateUniformBuffers(): false | string {
21✔
136
    let reason: false | string = false;
7✔
137
    for (const uniformBufferName of this.uniformBlocks.keys()) {
7!
UNCOV
138
      const bufferReason = this.updateUniformBuffer(uniformBufferName);
×
UNCOV
139
      reason ||= bufferReason;
×
UNCOV
140
    }
×
141
    if (reason) {
7!
UNCOV
142
      log.log(3, `UniformStore.updateUniformBuffers(): ${reason}`)();
×
UNCOV
143
    }
×
144
    return reason;
7✔
145
  }
7✔
146

21✔
147
  /** Update one uniform buffer. Only updates if values have changed */
21✔
148
  updateUniformBuffer(uniformBufferName: keyof TPropGroups): false | string {
21✔
UNCOV
149
    const uniformBlock = this.uniformBlocks.get(uniformBufferName);
×
UNCOV
150
    let uniformBuffer = this.uniformBuffers.get(uniformBufferName);
×
UNCOV
151

×
UNCOV
152
    let reason: false | string = false;
×
UNCOV
153
    if (uniformBuffer && uniformBlock?.needsRedraw) {
×
UNCOV
154
      reason ||= uniformBlock.needsRedraw;
×
UNCOV
155
      // This clears the needs redraw flag
×
UNCOV
156
      const uniformBufferData = this.getUniformBufferData(uniformBufferName);
×
UNCOV
157

×
UNCOV
158
      uniformBuffer = this.uniformBuffers.get(uniformBufferName);
×
UNCOV
159
      uniformBuffer?.write(uniformBufferData);
×
UNCOV
160

×
UNCOV
161
      // logging - TODO - don't query the values unnecessarily
×
UNCOV
162
      const uniformValues = this.uniformBlocks.get(uniformBufferName)?.getAllUniforms();
×
UNCOV
163
      log.log(
×
UNCOV
164
        4,
×
UNCOV
165
        `Writing to uniform buffer ${String(uniformBufferName)}`,
×
UNCOV
166
        uniformBufferData,
×
UNCOV
167
        uniformValues
×
UNCOV
168
      )();
×
UNCOV
169
    }
×
UNCOV
170
    return reason;
×
UNCOV
171
  }
×
172
}
21✔
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