@luma.gl/engine 9.2.6 → 9.3.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-loop/animation-loop.d.ts +11 -5
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +83 -47
- package/dist/animation-loop/animation-loop.js.map +1 -1
- package/dist/animation-loop/make-animation-loop.js +7 -1
- package/dist/animation-loop/make-animation-loop.js.map +1 -1
- package/dist/animation-loop/request-animation-frame.d.ts.map +1 -1
- package/dist/animation-loop/request-animation-frame.js +23 -6
- package/dist/animation-loop/request-animation-frame.js.map +1 -1
- package/dist/compute/computation.d.ts +3 -7
- package/dist/compute/computation.d.ts.map +1 -1
- package/dist/compute/computation.js +16 -13
- package/dist/compute/computation.js.map +1 -1
- package/dist/compute/swap.d.ts +2 -0
- package/dist/compute/swap.d.ts.map +1 -1
- package/dist/compute/swap.js +10 -5
- package/dist/compute/swap.js.map +1 -1
- package/dist/dist.dev.js +2639 -1290
- package/dist/dist.min.js +325 -210
- package/dist/dynamic-texture/dynamic-texture.d.ts +102 -0
- package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -0
- package/dist/dynamic-texture/dynamic-texture.js +556 -0
- package/dist/dynamic-texture/dynamic-texture.js.map +1 -0
- package/dist/dynamic-texture/texture-data.d.ts +144 -0
- package/dist/dynamic-texture/texture-data.d.ts.map +1 -0
- package/dist/dynamic-texture/texture-data.js +208 -0
- package/dist/dynamic-texture/texture-data.js.map +1 -0
- package/dist/geometries/cone-geometry.d.ts +3 -1
- package/dist/geometries/cone-geometry.d.ts.map +1 -1
- package/dist/geometries/cone-geometry.js.map +1 -1
- package/dist/geometries/cylinder-geometry.d.ts +2 -1
- package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
- package/dist/geometries/cylinder-geometry.js.map +1 -1
- package/dist/geometry/gpu-geometry.d.ts.map +1 -1
- package/dist/geometry/gpu-geometry.js +8 -3
- package/dist/geometry/gpu-geometry.js.map +1 -1
- package/dist/index.cjs +2497 -1212
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +20 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/material/material-factory.d.ts +73 -0
- package/dist/material/material-factory.d.ts.map +1 -0
- package/dist/material/material-factory.js +111 -0
- package/dist/material/material-factory.js.map +1 -0
- package/dist/material/material.d.ts +84 -0
- package/dist/material/material.d.ts.map +1 -0
- package/dist/material/material.js +176 -0
- package/dist/material/material.js.map +1 -0
- package/dist/model/model.d.ts +47 -16
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +113 -47
- package/dist/model/model.js.map +1 -1
- package/dist/model/split-uniforms-and-bindings.d.ts +4 -3
- package/dist/model/split-uniforms-and-bindings.d.ts.map +1 -1
- package/dist/model/split-uniforms-and-bindings.js +2 -2
- package/dist/model/split-uniforms-and-bindings.js.map +1 -1
- package/dist/models/billboard-texture-model.d.ts +8 -5
- package/dist/models/billboard-texture-model.d.ts.map +1 -1
- package/dist/models/billboard-texture-model.js +77 -23
- package/dist/models/billboard-texture-model.js.map +1 -1
- package/dist/models/billboard-texture-module.d.ts +1 -1
- package/dist/models/billboard-texture-module.js +1 -1
- package/dist/models/clip-space.js +7 -7
- package/dist/models/directional-light-model.d.ts +7 -0
- package/dist/models/directional-light-model.d.ts.map +1 -0
- package/dist/models/directional-light-model.js +23 -0
- package/dist/models/directional-light-model.js.map +1 -0
- package/dist/models/light-model-utils.d.ts +69 -0
- package/dist/models/light-model-utils.d.ts.map +1 -0
- package/dist/models/light-model-utils.js +395 -0
- package/dist/models/light-model-utils.js.map +1 -0
- package/dist/models/point-light-model.d.ts +7 -0
- package/dist/models/point-light-model.d.ts.map +1 -0
- package/dist/models/point-light-model.js +22 -0
- package/dist/models/point-light-model.js.map +1 -0
- package/dist/models/spot-light-model.d.ts +7 -0
- package/dist/models/spot-light-model.d.ts.map +1 -0
- package/dist/models/spot-light-model.js +23 -0
- package/dist/models/spot-light-model.js.map +1 -0
- package/dist/modules/picking/color-picking.d.ts +5 -9
- package/dist/modules/picking/color-picking.d.ts.map +1 -1
- package/dist/modules/picking/color-picking.js +122 -115
- package/dist/modules/picking/color-picking.js.map +1 -1
- package/dist/modules/picking/index-picking.d.ts +4 -4
- package/dist/modules/picking/index-picking.d.ts.map +1 -1
- package/dist/modules/picking/index-picking.js +36 -16
- package/dist/modules/picking/index-picking.js.map +1 -1
- package/dist/modules/picking/legacy-color-picking.d.ts +26 -0
- package/dist/modules/picking/legacy-color-picking.d.ts.map +1 -0
- package/dist/modules/picking/legacy-color-picking.js +7 -0
- package/dist/modules/picking/legacy-color-picking.js.map +1 -0
- package/dist/modules/picking/picking-manager.d.ts +29 -3
- package/dist/modules/picking/picking-manager.d.ts.map +1 -1
- package/dist/modules/picking/picking-manager.js +188 -41
- package/dist/modules/picking/picking-manager.js.map +1 -1
- package/dist/modules/picking/picking-uniforms.d.ts +13 -12
- package/dist/modules/picking/picking-uniforms.d.ts.map +1 -1
- package/dist/modules/picking/picking-uniforms.js +27 -14
- package/dist/modules/picking/picking-uniforms.js.map +1 -1
- package/dist/modules/picking/picking.d.ts +25 -0
- package/dist/modules/picking/picking.d.ts.map +1 -0
- package/dist/modules/picking/picking.js +18 -0
- package/dist/modules/picking/picking.js.map +1 -0
- package/dist/passes/get-fragment-shader.js +12 -27
- package/dist/passes/get-fragment-shader.js.map +1 -1
- package/dist/passes/shader-pass-renderer.d.ts +5 -7
- package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
- package/dist/passes/shader-pass-renderer.js +16 -42
- package/dist/passes/shader-pass-renderer.js.map +1 -1
- package/dist/scenegraph/group-node.d.ts +5 -0
- package/dist/scenegraph/group-node.d.ts.map +1 -1
- package/dist/scenegraph/group-node.js +12 -0
- package/dist/scenegraph/group-node.js.map +1 -1
- package/dist/scenegraph/model-node.d.ts +2 -2
- package/dist/scenegraph/model-node.d.ts.map +1 -1
- package/dist/scenegraph/model-node.js.map +1 -1
- package/dist/scenegraph/scenegraph-node.d.ts +1 -1
- package/dist/scenegraph/scenegraph-node.d.ts.map +1 -1
- package/dist/scenegraph/scenegraph-node.js +23 -15
- package/dist/scenegraph/scenegraph-node.js.map +1 -1
- package/dist/shader-inputs.d.ts +9 -7
- package/dist/shader-inputs.d.ts.map +1 -1
- package/dist/shader-inputs.js +84 -4
- package/dist/shader-inputs.js.map +1 -1
- package/dist/utils/buffer-layout-order.d.ts.map +1 -1
- package/dist/utils/buffer-layout-order.js +12 -2
- package/dist/utils/buffer-layout-order.js.map +1 -1
- package/dist/utils/shader-module-utils.d.ts +7 -0
- package/dist/utils/shader-module-utils.d.ts.map +1 -0
- package/dist/utils/shader-module-utils.js +46 -0
- package/dist/utils/shader-module-utils.js.map +1 -0
- package/package.json +6 -6
- package/src/animation-loop/animation-loop.ts +89 -50
- package/src/animation-loop/make-animation-loop.ts +13 -5
- package/src/animation-loop/request-animation-frame.ts +32 -6
- package/src/compute/computation.ts +32 -17
- package/src/compute/swap.ts +13 -7
- package/src/dynamic-texture/dynamic-texture.ts +732 -0
- package/src/dynamic-texture/texture-data.ts +336 -0
- package/src/geometries/cone-geometry.ts +6 -1
- package/src/geometries/cylinder-geometry.ts +5 -1
- package/src/geometry/gpu-geometry.ts +8 -3
- package/src/index.ts +38 -8
- package/src/material/material-factory.ts +157 -0
- package/src/material/material.ts +254 -0
- package/src/model/model.ts +158 -67
- package/src/model/split-uniforms-and-bindings.ts +8 -6
- package/src/models/billboard-texture-model.ts +88 -27
- package/src/models/billboard-texture-module.ts +1 -1
- package/src/models/clip-space.ts +7 -7
- package/src/models/directional-light-model.ts +32 -0
- package/src/models/light-model-utils.ts +587 -0
- package/src/models/point-light-model.ts +31 -0
- package/src/models/spot-light-model.ts +32 -0
- package/src/modules/picking/color-picking.ts +123 -122
- package/src/modules/picking/index-picking.ts +36 -16
- package/src/modules/picking/legacy-color-picking.ts +8 -0
- package/src/modules/picking/picking-manager.ts +252 -50
- package/src/modules/picking/picking-uniforms.ts +39 -24
- package/src/modules/picking/picking.ts +22 -0
- package/src/passes/get-fragment-shader.ts +12 -27
- package/src/passes/shader-pass-renderer.ts +25 -48
- package/src/scenegraph/group-node.ts +16 -0
- package/src/scenegraph/model-node.ts +2 -2
- package/src/scenegraph/scenegraph-node.ts +27 -16
- package/src/shader-inputs.ts +165 -15
- package/src/utils/buffer-layout-order.ts +18 -2
- package/src/utils/shader-module-utils.ts +65 -0
- package/dist/async-texture/async-texture.d.ts +0 -166
- package/dist/async-texture/async-texture.d.ts.map +0 -1
- package/dist/async-texture/async-texture.js +0 -386
- package/dist/async-texture/async-texture.js.map +0 -1
- package/dist/factories/pipeline-factory.d.ts +0 -37
- package/dist/factories/pipeline-factory.d.ts.map +0 -1
- package/dist/factories/pipeline-factory.js +0 -181
- package/dist/factories/pipeline-factory.js.map +0 -1
- package/dist/factories/shader-factory.d.ts +0 -22
- package/dist/factories/shader-factory.d.ts.map +0 -1
- package/dist/factories/shader-factory.js +0 -88
- package/dist/factories/shader-factory.js.map +0 -1
- package/src/async-texture/async-texture.ts +0 -551
- package/src/factories/pipeline-factory.ts +0 -224
- package/src/factories/shader-factory.ts +0 -103
- /package/src/{async-texture/texture-setters.ts.disabled → dynamic-texture/texture-data.ts.disabled} +0 -0
package/src/model/model.ts
CHANGED
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
// A lot of imports, but then Model is where it all comes together...
|
|
6
|
-
import type
|
|
7
|
-
import type {
|
|
8
|
-
RenderPipelineProps,
|
|
9
|
-
RenderPipelineParameters,
|
|
10
|
-
BufferLayout,
|
|
11
|
-
Shader,
|
|
12
|
-
VertexArray,
|
|
13
|
-
TransformFeedback,
|
|
14
|
-
AttributeInfo,
|
|
15
|
-
Binding,
|
|
16
|
-
PrimitiveTopology
|
|
17
|
-
} from '@luma.gl/core';
|
|
6
|
+
import {type TypedArray} from '@math.gl/types';
|
|
18
7
|
import {
|
|
8
|
+
type RenderPipelineProps,
|
|
9
|
+
type RenderPipelineParameters,
|
|
10
|
+
type BufferLayout,
|
|
11
|
+
type Shader,
|
|
12
|
+
type VertexArray,
|
|
13
|
+
type TransformFeedback,
|
|
14
|
+
type AttributeInfo,
|
|
15
|
+
type Binding,
|
|
16
|
+
type BindingsByGroup,
|
|
17
|
+
type PrimitiveTopology,
|
|
19
18
|
Device,
|
|
20
19
|
DeviceFeature,
|
|
21
20
|
Buffer,
|
|
@@ -24,27 +23,33 @@ import {
|
|
|
24
23
|
Sampler,
|
|
25
24
|
RenderPipeline,
|
|
26
25
|
RenderPass,
|
|
26
|
+
PipelineFactory,
|
|
27
|
+
ShaderFactory,
|
|
27
28
|
UniformStore,
|
|
28
29
|
log,
|
|
29
|
-
|
|
30
|
-
getAttributeInfosFromLayouts
|
|
30
|
+
dataTypeDecoder,
|
|
31
|
+
getAttributeInfosFromLayouts,
|
|
32
|
+
normalizeBindingsByGroup
|
|
31
33
|
} from '@luma.gl/core';
|
|
32
34
|
|
|
33
|
-
import type {ShaderModule, PlatformInfo} from '@luma.gl/shadertools';
|
|
34
|
-
import {ShaderAssembler
|
|
35
|
+
import type {ShaderBindingDebugRow, ShaderModule, PlatformInfo} from '@luma.gl/shadertools';
|
|
36
|
+
import {ShaderAssembler} from '@luma.gl/shadertools';
|
|
35
37
|
|
|
36
38
|
import type {Geometry} from '../geometry/geometry';
|
|
37
39
|
import {GPUGeometry, makeGPUGeometry} from '../geometry/gpu-geometry';
|
|
38
|
-
import {PipelineFactory} from '../factories/pipeline-factory';
|
|
39
|
-
import {ShaderFactory} from '../factories/shader-factory';
|
|
40
40
|
import {getDebugTableForShaderLayout} from '../debug/debug-shader-layout';
|
|
41
41
|
import {debugFramebuffer} from '../debug/debug-framebuffer';
|
|
42
42
|
import {deepEqual} from '../utils/deep-equal';
|
|
43
43
|
import {BufferLayoutHelper} from '../utils/buffer-layout-helper';
|
|
44
44
|
import {sortedBufferLayoutByShaderSourceLocations} from '../utils/buffer-layout-order';
|
|
45
|
+
import {
|
|
46
|
+
mergeShaderModuleBindingsIntoLayout,
|
|
47
|
+
shaderModuleHasUniforms
|
|
48
|
+
} from '../utils/shader-module-utils';
|
|
45
49
|
import {uid} from '../utils/uid';
|
|
46
50
|
import {ShaderInputs} from '../shader-inputs';
|
|
47
|
-
import {
|
|
51
|
+
import {DynamicTexture} from '../dynamic-texture/dynamic-texture';
|
|
52
|
+
import {Material} from '../material/material';
|
|
48
53
|
|
|
49
54
|
const LOG_DRAW_PRIORITY = 2;
|
|
50
55
|
const LOG_DRAW_TIMEOUT = 10000;
|
|
@@ -62,8 +67,12 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
|
62
67
|
|
|
63
68
|
/** Shader inputs, used to generated uniform buffers and bindings */
|
|
64
69
|
shaderInputs?: ShaderInputs;
|
|
70
|
+
/** Material-owned group-3 bindings */
|
|
71
|
+
material?: Material;
|
|
65
72
|
/** Bindings */
|
|
66
|
-
bindings?: Record<string, Binding |
|
|
73
|
+
bindings?: Record<string, Binding | DynamicTexture>;
|
|
74
|
+
/** WebGL-only uniforms */
|
|
75
|
+
uniforms?: Record<string, unknown>;
|
|
67
76
|
/** Parameters that are built into the pipeline */
|
|
68
77
|
parameters?: RenderPipelineParameters;
|
|
69
78
|
|
|
@@ -103,12 +112,19 @@ export type ModelProps = Omit<RenderPipelineProps, 'vs' | 'fs' | 'bindings'> & {
|
|
|
103
112
|
};
|
|
104
113
|
|
|
105
114
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
115
|
+
* High level draw API for luma.gl.
|
|
116
|
+
*
|
|
117
|
+
* A `Model` encapsulates shaders, geometry attributes, bindings and render
|
|
118
|
+
* pipeline state into a single object. It automatically reuses and rebuilds
|
|
119
|
+
* pipelines as render parameters change and exposes convenient hooks for
|
|
120
|
+
* updating uniforms and attributes.
|
|
121
|
+
*
|
|
122
|
+
* Features:
|
|
123
|
+
* - Reuses and lazily recompiles {@link RenderPipeline | pipelines} as needed.
|
|
124
|
+
* - Integrates with `@luma.gl/shadertools` to assemble GLSL or WGSL from shader modules.
|
|
125
|
+
* - Manages geometry attributes and buffer bindings.
|
|
126
|
+
* - Accepts textures, samplers and uniform buffers as bindings, including `DynamicTexture`.
|
|
127
|
+
* - Provides detailed debug logging and optional shader source inspection.
|
|
112
128
|
*/
|
|
113
129
|
export class Model {
|
|
114
130
|
static defaultProps: Required<ModelProps> = {
|
|
@@ -125,6 +141,8 @@ export class Model {
|
|
|
125
141
|
indexBuffer: null,
|
|
126
142
|
attributes: {},
|
|
127
143
|
constantAttributes: {},
|
|
144
|
+
bindings: {},
|
|
145
|
+
uniforms: {},
|
|
128
146
|
varyings: [],
|
|
129
147
|
|
|
130
148
|
isInstanced: undefined!,
|
|
@@ -132,6 +150,7 @@ export class Model {
|
|
|
132
150
|
vertexCount: 0,
|
|
133
151
|
|
|
134
152
|
shaderInputs: undefined!,
|
|
153
|
+
material: undefined!,
|
|
135
154
|
pipelineFactory: undefined!,
|
|
136
155
|
shaderFactory: undefined!,
|
|
137
156
|
transformFeedback: undefined!,
|
|
@@ -141,16 +160,24 @@ export class Model {
|
|
|
141
160
|
disableWarnings: undefined!
|
|
142
161
|
};
|
|
143
162
|
|
|
163
|
+
/** Device that created this model */
|
|
144
164
|
readonly device: Device;
|
|
165
|
+
/** Application provided identifier */
|
|
145
166
|
readonly id: string;
|
|
167
|
+
/** WGSL shader source when using unified shader */
|
|
146
168
|
// @ts-expect-error assigned in function called from constructor
|
|
147
169
|
readonly source: string;
|
|
170
|
+
/** GLSL vertex shader source */
|
|
148
171
|
// @ts-expect-error assigned in function called from constructor
|
|
149
172
|
readonly vs: string;
|
|
173
|
+
/** GLSL fragment shader source */
|
|
150
174
|
// @ts-expect-error assigned in function called from constructor
|
|
151
175
|
readonly fs: string;
|
|
176
|
+
/** Factory used to create render pipelines */
|
|
152
177
|
readonly pipelineFactory: PipelineFactory;
|
|
178
|
+
/** Factory used to create shaders */
|
|
153
179
|
readonly shaderFactory: ShaderFactory;
|
|
180
|
+
/** User-supplied per-model data */
|
|
154
181
|
userData: {[key: string]: any} = {};
|
|
155
182
|
|
|
156
183
|
// Fixed properties (change can trigger pipeline rebuild)
|
|
@@ -179,7 +206,7 @@ export class Model {
|
|
|
179
206
|
/** Constant-valued attributes */
|
|
180
207
|
constantAttributes: Record<string, TypedArray> = {};
|
|
181
208
|
/** Bindings (textures, samplers, uniform buffers) */
|
|
182
|
-
bindings: Record<string, Binding |
|
|
209
|
+
bindings: Record<string, Binding | DynamicTexture> = {};
|
|
183
210
|
|
|
184
211
|
/**
|
|
185
212
|
* VertexArray
|
|
@@ -197,6 +224,7 @@ export class Model {
|
|
|
197
224
|
/** ShaderInputs instance */
|
|
198
225
|
// @ts-expect-error Assigned in function called by constructor
|
|
199
226
|
shaderInputs: ShaderInputs;
|
|
227
|
+
material: Material | null = null;
|
|
200
228
|
// @ts-expect-error Assigned in function called by constructor
|
|
201
229
|
_uniformStore: UniformStore;
|
|
202
230
|
|
|
@@ -210,6 +238,7 @@ export class Model {
|
|
|
210
238
|
|
|
211
239
|
/** "Time" of last draw. Monotonically increasing timestamp */
|
|
212
240
|
_lastDrawTimestamp: number = -1;
|
|
241
|
+
private _bindingTable: ShaderBindingDebugRow[] = [];
|
|
213
242
|
|
|
214
243
|
get [Symbol.toStringTag](): string {
|
|
215
244
|
return 'Model';
|
|
@@ -227,6 +256,8 @@ export class Model {
|
|
|
227
256
|
|
|
228
257
|
Object.assign(this.userData, props.userData);
|
|
229
258
|
|
|
259
|
+
this.material = props.material || null;
|
|
260
|
+
|
|
230
261
|
// Setup shader module inputs
|
|
231
262
|
const moduleMap = Object.fromEntries(
|
|
232
263
|
this.props.modules?.map(module => [module.name, module]) || []
|
|
@@ -246,6 +277,9 @@ export class Model {
|
|
|
246
277
|
// @ts-ignore shaderInputs is assigned in setShaderInputs above.
|
|
247
278
|
(this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
|
|
248
279
|
|
|
280
|
+
this.props.shaderLayout =
|
|
281
|
+
mergeShaderModuleBindingsIntoLayout(this.props.shaderLayout, modules) || null;
|
|
282
|
+
|
|
249
283
|
const isWebGPU = this.device.type === 'webgpu';
|
|
250
284
|
|
|
251
285
|
// WebGPU
|
|
@@ -253,7 +287,7 @@ export class Model {
|
|
|
253
287
|
// TODO - this is wrong, compile a single shader
|
|
254
288
|
if (isWebGPU && this.props.source) {
|
|
255
289
|
// WGSL
|
|
256
|
-
const {source, getUniforms} = this.props.shaderAssembler.assembleWGSLShader({
|
|
290
|
+
const {source, getUniforms, bindingTable} = this.props.shaderAssembler.assembleWGSLShader({
|
|
257
291
|
platformInfo,
|
|
258
292
|
...this.props,
|
|
259
293
|
modules
|
|
@@ -261,8 +295,16 @@ export class Model {
|
|
|
261
295
|
this.source = source;
|
|
262
296
|
// @ts-expect-error
|
|
263
297
|
this._getModuleUniforms = getUniforms;
|
|
298
|
+
this._bindingTable = bindingTable;
|
|
264
299
|
// Extract shader layout after modules have been added to WGSL source, to include any bindings added by modules
|
|
265
|
-
|
|
300
|
+
const inferredShaderLayout = (
|
|
301
|
+
device as Device & {getShaderLayout?: (source: string) => any}
|
|
302
|
+
).getShaderLayout?.(this.source);
|
|
303
|
+
this.props.shaderLayout =
|
|
304
|
+
mergeShaderModuleBindingsIntoLayout(
|
|
305
|
+
this.props.shaderLayout || inferredShaderLayout || null,
|
|
306
|
+
modules
|
|
307
|
+
) || null;
|
|
266
308
|
} else {
|
|
267
309
|
// GLSL
|
|
268
310
|
const {vs, fs, getUniforms} = this.props.shaderAssembler.assembleGLSLShaderPair({
|
|
@@ -275,6 +317,7 @@ export class Model {
|
|
|
275
317
|
this.fs = fs;
|
|
276
318
|
// @ts-expect-error
|
|
277
319
|
this._getModuleUniforms = getUniforms;
|
|
320
|
+
this._bindingTable = [];
|
|
278
321
|
}
|
|
279
322
|
|
|
280
323
|
this.vertexCount = this.props.vertexCount;
|
|
@@ -333,9 +376,6 @@ export class Model {
|
|
|
333
376
|
if (props.transformFeedback) {
|
|
334
377
|
this.transformFeedback = props.transformFeedback;
|
|
335
378
|
}
|
|
336
|
-
|
|
337
|
-
// Catch any access to non-standard props
|
|
338
|
-
Object.seal(this);
|
|
339
379
|
}
|
|
340
380
|
|
|
341
381
|
destroy(): void {
|
|
@@ -344,7 +384,7 @@ export class Model {
|
|
|
344
384
|
this.pipelineFactory.release(this.pipeline);
|
|
345
385
|
// Release the shaders
|
|
346
386
|
this.shaderFactory.release(this.pipeline.vs);
|
|
347
|
-
if (this.pipeline.fs) {
|
|
387
|
+
if (this.pipeline.fs && this.pipeline.fs !== this.pipeline.vs) {
|
|
348
388
|
this.shaderFactory.release(this.pipeline.fs);
|
|
349
389
|
}
|
|
350
390
|
this._uniformStore.destroy();
|
|
@@ -372,6 +412,12 @@ export class Model {
|
|
|
372
412
|
this._needsRedraw ||= reason;
|
|
373
413
|
}
|
|
374
414
|
|
|
415
|
+
/** Returns WGSL binding debug rows for the assembled shader. Returns an empty array for GLSL models. */
|
|
416
|
+
getBindingDebugTable(): readonly ShaderBindingDebugRow[] {
|
|
417
|
+
return this._bindingTable;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** Update uniforms and pipeline state prior to drawing. */
|
|
375
421
|
predraw(): void {
|
|
376
422
|
// Update uniform buffers if needed
|
|
377
423
|
this.updateShaderInputs();
|
|
@@ -379,6 +425,11 @@ export class Model {
|
|
|
379
425
|
this.pipeline = this._updatePipeline();
|
|
380
426
|
}
|
|
381
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Issue one draw call.
|
|
430
|
+
* @param renderPass - render pass to draw into
|
|
431
|
+
* @returns `true` if the draw call was executed, `false` if resources were not ready.
|
|
432
|
+
*/
|
|
382
433
|
draw(renderPass: RenderPass): boolean {
|
|
383
434
|
const loadingBinding = this._areBindingsLoading();
|
|
384
435
|
if (loadingBinding) {
|
|
@@ -403,14 +454,8 @@ export class Model {
|
|
|
403
454
|
// Application can call Model.predraw() to avoid this.
|
|
404
455
|
this.pipeline = this._updatePipeline();
|
|
405
456
|
|
|
406
|
-
// Set pipeline state, we may be sharing a pipeline so we need to set all state on every draw
|
|
407
|
-
// Any caching needs to be done inside the pipeline functions
|
|
408
|
-
// TODO this is a busy initialized check for all bindings every frame
|
|
409
|
-
|
|
410
457
|
const syncBindings = this._getBindings();
|
|
411
|
-
this.
|
|
412
|
-
disableWarnings: this.props.disableWarnings
|
|
413
|
-
});
|
|
458
|
+
const syncBindGroups = this._getBindGroups();
|
|
414
459
|
|
|
415
460
|
const {indexBuffer} = this.vertexArray;
|
|
416
461
|
const indexCount = indexBuffer
|
|
@@ -425,6 +470,13 @@ export class Model {
|
|
|
425
470
|
instanceCount: this.instanceCount,
|
|
426
471
|
indexCount,
|
|
427
472
|
transformFeedback: this.transformFeedback || undefined,
|
|
473
|
+
// Pipelines may be shared across models when caching is enabled, so bindings
|
|
474
|
+
// and WebGL uniforms must be supplied on every draw instead of being stored
|
|
475
|
+
// on the pipeline instance.
|
|
476
|
+
bindings: syncBindings,
|
|
477
|
+
bindGroups: syncBindGroups,
|
|
478
|
+
_bindGroupCacheKeys: this._getBindGroupCacheKeys(),
|
|
479
|
+
uniforms: this.props.uniforms,
|
|
428
480
|
// WebGL shares underlying cached pipelines even for models that have different parameters and topology,
|
|
429
481
|
// so we must provide our unique parameters to each draw
|
|
430
482
|
// (In WebGPU most parameters are encoded in the pipeline and cannot be changed per draw call)
|
|
@@ -549,21 +601,26 @@ export class Model {
|
|
|
549
601
|
/** Set the shader inputs */
|
|
550
602
|
setShaderInputs(shaderInputs: ShaderInputs): void {
|
|
551
603
|
this.shaderInputs = shaderInputs;
|
|
552
|
-
this._uniformStore = new UniformStore(this.shaderInputs.modules);
|
|
604
|
+
this._uniformStore = new UniformStore(this.device, this.shaderInputs.modules);
|
|
553
605
|
// Create uniform buffer bindings for all modules that actually have uniforms
|
|
554
606
|
for (const [moduleName, module] of Object.entries(this.shaderInputs.modules)) {
|
|
555
|
-
if (shaderModuleHasUniforms(module)) {
|
|
556
|
-
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(
|
|
607
|
+
if (shaderModuleHasUniforms(module) && !this.material?.ownsModule(moduleName)) {
|
|
608
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(moduleName);
|
|
557
609
|
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
558
610
|
}
|
|
559
611
|
}
|
|
560
612
|
this.setNeedsRedraw('shaderInputs');
|
|
561
613
|
}
|
|
562
614
|
|
|
615
|
+
setMaterial(material: Material | null): void {
|
|
616
|
+
this.material = material;
|
|
617
|
+
this.setNeedsRedraw('material');
|
|
618
|
+
}
|
|
619
|
+
|
|
563
620
|
/** Update uniform buffers from the model's shader inputs */
|
|
564
621
|
updateShaderInputs(): void {
|
|
565
622
|
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
566
|
-
this.setBindings(this.shaderInputs.getBindingValues());
|
|
623
|
+
this.setBindings(this._getNonMaterialBindings(this.shaderInputs.getBindingValues()));
|
|
567
624
|
// TODO - this is already tracked through buffer/texture update times?
|
|
568
625
|
this.setNeedsRedraw('shaderInputs');
|
|
569
626
|
}
|
|
@@ -571,7 +628,7 @@ export class Model {
|
|
|
571
628
|
/**
|
|
572
629
|
* Sets bindings (textures, samplers, uniform buffers)
|
|
573
630
|
*/
|
|
574
|
-
setBindings(bindings: Record<string, Binding |
|
|
631
|
+
setBindings(bindings: Record<string, Binding | DynamicTexture>): void {
|
|
575
632
|
Object.assign(this.bindings, bindings);
|
|
576
633
|
this.setNeedsRedraw('bindings');
|
|
577
634
|
}
|
|
@@ -678,7 +735,12 @@ export class Model {
|
|
|
678
735
|
/** Check that bindings are loaded. Returns id of first binding that is still loading. */
|
|
679
736
|
_areBindingsLoading(): string | false {
|
|
680
737
|
for (const binding of Object.values(this.bindings)) {
|
|
681
|
-
if (binding instanceof
|
|
738
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
739
|
+
return binding.id;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
for (const binding of Object.values(this.material?.bindings || {})) {
|
|
743
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
682
744
|
return binding.id;
|
|
683
745
|
}
|
|
684
746
|
}
|
|
@@ -690,7 +752,7 @@ export class Model {
|
|
|
690
752
|
const validBindings: Record<string, Binding> = {};
|
|
691
753
|
|
|
692
754
|
for (const [name, binding] of Object.entries(this.bindings)) {
|
|
693
|
-
if (binding instanceof
|
|
755
|
+
if (binding instanceof DynamicTexture) {
|
|
694
756
|
// Check that async textures are loaded
|
|
695
757
|
if (binding.isReady) {
|
|
696
758
|
validBindings[name] = binding.texture;
|
|
@@ -703,6 +765,32 @@ export class Model {
|
|
|
703
765
|
return validBindings;
|
|
704
766
|
}
|
|
705
767
|
|
|
768
|
+
_getBindGroups(): BindingsByGroup {
|
|
769
|
+
const shaderLayout = this.pipeline?.shaderLayout || this.props.shaderLayout || {bindings: []};
|
|
770
|
+
const bindGroups = shaderLayout.bindings.length
|
|
771
|
+
? normalizeBindingsByGroup(shaderLayout, this._getBindings())
|
|
772
|
+
: {0: this._getBindings()};
|
|
773
|
+
|
|
774
|
+
if (!this.material) {
|
|
775
|
+
return bindGroups;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
for (const [groupKey, groupBindings] of Object.entries(this.material.getBindingsByGroup())) {
|
|
779
|
+
const group = Number(groupKey);
|
|
780
|
+
bindGroups[group] = {
|
|
781
|
+
...(bindGroups[group] || {}),
|
|
782
|
+
...groupBindings
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return bindGroups;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
_getBindGroupCacheKeys(): Partial<Record<number, object>> {
|
|
790
|
+
const bindGroupCacheKey = this.material?.getBindGroupCacheKey(3);
|
|
791
|
+
return bindGroupCacheKey ? {3: bindGroupCacheKey} : {};
|
|
792
|
+
}
|
|
793
|
+
|
|
706
794
|
/** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
|
|
707
795
|
_getBindingsUpdateTimestamp(): number {
|
|
708
796
|
let timestamp = 0;
|
|
@@ -711,7 +799,7 @@ export class Model {
|
|
|
711
799
|
timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
|
|
712
800
|
} else if (binding instanceof Buffer || binding instanceof Texture) {
|
|
713
801
|
timestamp = Math.max(timestamp, binding.updateTimestamp);
|
|
714
|
-
} else if (binding instanceof
|
|
802
|
+
} else if (binding instanceof DynamicTexture) {
|
|
715
803
|
timestamp = binding.texture
|
|
716
804
|
? Math.max(timestamp, binding.texture.updateTimestamp)
|
|
717
805
|
: // The texture will become available in the future
|
|
@@ -720,7 +808,7 @@ export class Model {
|
|
|
720
808
|
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
721
809
|
}
|
|
722
810
|
}
|
|
723
|
-
return timestamp;
|
|
811
|
+
return Math.max(timestamp, this.material?.getBindingsUpdateTimestamp() || 0);
|
|
724
812
|
}
|
|
725
813
|
|
|
726
814
|
/**
|
|
@@ -792,12 +880,11 @@ export class Model {
|
|
|
792
880
|
|
|
793
881
|
this.pipeline = this.pipelineFactory.createRenderPipeline({
|
|
794
882
|
...this.props,
|
|
883
|
+
bindings: undefined,
|
|
795
884
|
bufferLayout: this.bufferLayout,
|
|
796
885
|
topology: this.topology,
|
|
797
886
|
parameters: this.parameters,
|
|
798
|
-
|
|
799
|
-
// Should we expose a BindGroup abstraction?
|
|
800
|
-
bindings: this._getBindings(),
|
|
887
|
+
bindGroups: this._getBindGroups(),
|
|
801
888
|
vs,
|
|
802
889
|
fs
|
|
803
890
|
});
|
|
@@ -808,7 +895,9 @@ export class Model {
|
|
|
808
895
|
);
|
|
809
896
|
|
|
810
897
|
if (prevShaderVs) this.shaderFactory.release(prevShaderVs);
|
|
811
|
-
if (prevShaderFs
|
|
898
|
+
if (prevShaderFs && prevShaderFs !== prevShaderVs) {
|
|
899
|
+
this.shaderFactory.release(prevShaderFs);
|
|
900
|
+
}
|
|
812
901
|
}
|
|
813
902
|
return this.pipeline;
|
|
814
903
|
}
|
|
@@ -896,15 +985,27 @@ export class Model {
|
|
|
896
985
|
|
|
897
986
|
// TODO - fix typing of luma data types
|
|
898
987
|
_getBufferOrConstantValues(attribute: Buffer | TypedArray, dataType: any): string {
|
|
899
|
-
const TypedArrayConstructor = getTypedArrayConstructor(dataType);
|
|
988
|
+
const TypedArrayConstructor = dataTypeDecoder.getTypedArrayConstructor(dataType);
|
|
900
989
|
const typedArray =
|
|
901
990
|
attribute instanceof Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
902
991
|
return typedArray.toString();
|
|
903
992
|
}
|
|
904
|
-
}
|
|
905
993
|
|
|
906
|
-
|
|
907
|
-
|
|
994
|
+
private _getNonMaterialBindings(
|
|
995
|
+
bindings: Record<string, Binding | DynamicTexture>
|
|
996
|
+
): Record<string, Binding | DynamicTexture> {
|
|
997
|
+
if (!this.material) {
|
|
998
|
+
return bindings;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
const filteredBindings: Record<string, Binding | DynamicTexture> = {};
|
|
1002
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
1003
|
+
if (!this.material.ownsBinding(name)) {
|
|
1004
|
+
filteredBindings[name] = binding;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return filteredBindings;
|
|
1008
|
+
}
|
|
908
1009
|
}
|
|
909
1010
|
|
|
910
1011
|
// HELPERS
|
|
@@ -920,13 +1021,3 @@ export function getPlatformInfo(device: Device): PlatformInfo {
|
|
|
920
1021
|
features: device.features as unknown as Set<DeviceFeature>
|
|
921
1022
|
};
|
|
922
1023
|
}
|
|
923
|
-
|
|
924
|
-
/** Returns true if given object is empty, false otherwise. */
|
|
925
|
-
function isObjectEmpty(obj: object): boolean {
|
|
926
|
-
// @ts-ignore key is unused
|
|
927
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
928
|
-
for (const key in obj) {
|
|
929
|
-
return false;
|
|
930
|
-
}
|
|
931
|
-
return true;
|
|
932
|
-
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {Binding, CompositeShaderType, UniformValue} from '@luma.gl/core';
|
|
6
|
+
import type {ShaderModuleUniformValue} from '@luma.gl/shadertools';
|
|
6
7
|
import {isNumericArray} from '@math.gl/types';
|
|
7
8
|
|
|
8
9
|
export function isUniformValue(value: unknown): value is UniformValue {
|
|
@@ -11,19 +12,20 @@ export function isUniformValue(value: unknown): value is UniformValue {
|
|
|
11
12
|
|
|
12
13
|
type UniformsAndBindings = {
|
|
13
14
|
bindings: Record<string, Binding>;
|
|
14
|
-
uniforms: Record<string,
|
|
15
|
+
uniforms: Record<string, ShaderModuleUniformValue>;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export function splitUniformsAndBindings(
|
|
18
|
-
uniforms: Record<string, Binding |
|
|
19
|
+
uniforms: Record<string, Binding | ShaderModuleUniformValue>,
|
|
20
|
+
uniformTypes: Readonly<Record<string, CompositeShaderType>> = {}
|
|
19
21
|
): UniformsAndBindings {
|
|
20
22
|
const result: UniformsAndBindings = {bindings: {}, uniforms: {}};
|
|
21
23
|
Object.keys(uniforms).forEach(name => {
|
|
22
24
|
const uniform = uniforms[name];
|
|
23
|
-
if (isUniformValue(uniform)) {
|
|
24
|
-
result.uniforms[name] = uniform;
|
|
25
|
+
if (Object.prototype.hasOwnProperty.call(uniformTypes, name) || isUniformValue(uniform)) {
|
|
26
|
+
result.uniforms[name] = uniform as ShaderModuleUniformValue;
|
|
25
27
|
} else {
|
|
26
|
-
result.bindings[name] = uniform;
|
|
28
|
+
result.bindings[name] = uniform as Binding;
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
|