@luma.gl/engine 9.0.11 → 9.1.0-alpha.1

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.
Files changed (138) hide show
  1. package/LICENSE +34 -0
  2. package/dist/animation/key-frames.d.ts.map +1 -1
  3. package/dist/animation/key-frames.js +3 -0
  4. package/dist/animation-loop/animation-loop-template.d.ts.map +1 -1
  5. package/dist/animation-loop/animation-loop-template.js +3 -0
  6. package/dist/animation-loop/animation-loop.d.ts +1 -1
  7. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  8. package/dist/animation-loop/animation-loop.js +5 -4
  9. package/dist/animation-loop/animation-props.d.ts.map +1 -1
  10. package/dist/animation-loop/animation-props.js +3 -0
  11. package/dist/animation-loop/request-animation-frame.d.ts +3 -0
  12. package/dist/animation-loop/request-animation-frame.d.ts.map +1 -0
  13. package/dist/animation-loop/request-animation-frame.js +16 -0
  14. package/dist/application-utils/load-file.d.ts +22 -0
  15. package/dist/application-utils/load-file.d.ts.map +1 -0
  16. package/dist/application-utils/load-file.js +43 -0
  17. package/dist/application-utils/random.d.ts +3 -0
  18. package/dist/application-utils/random.d.ts.map +1 -0
  19. package/dist/application-utils/random.js +16 -0
  20. package/dist/async-texture/async-texture.d.ts +50 -0
  21. package/dist/async-texture/async-texture.d.ts.map +1 -0
  22. package/dist/async-texture/async-texture.js +77 -0
  23. package/dist/computation.d.ts +4 -3
  24. package/dist/computation.d.ts.map +1 -1
  25. package/dist/computation.js +14 -6
  26. package/dist/debug/copy-texture-to-image.d.ts.map +1 -1
  27. package/dist/debug/copy-texture-to-image.js +4 -1
  28. package/dist/debug/debug-framebuffer.d.ts.map +1 -1
  29. package/dist/debug/debug-framebuffer.js +17 -12
  30. package/dist/debug/pixel-data-utils.d.ts +1 -1
  31. package/dist/dist.dev.js +1193 -473
  32. package/dist/dist.min.js +27 -25
  33. package/dist/geometries/cone-geometry.d.ts.map +1 -1
  34. package/dist/geometries/cone-geometry.js +4 -1
  35. package/dist/geometries/cube-geometry.d.ts.map +1 -1
  36. package/dist/geometries/cube-geometry.js +4 -1
  37. package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
  38. package/dist/geometries/cylinder-geometry.js +4 -1
  39. package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
  40. package/dist/geometries/ico-sphere-geometry.js +4 -1
  41. package/dist/geometries/plane-geometry.d.ts.map +1 -1
  42. package/dist/geometries/plane-geometry.js +4 -1
  43. package/dist/geometries/sphere-geometry.d.ts.map +1 -1
  44. package/dist/geometries/sphere-geometry.js +4 -1
  45. package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
  46. package/dist/geometries/truncated-cone-geometry.js +4 -1
  47. package/dist/geometry/geometry-table.d.ts +2 -1
  48. package/dist/geometry/geometry-table.d.ts.map +1 -1
  49. package/dist/geometry/geometry-utils.d.ts.map +1 -1
  50. package/dist/geometry/geometry-utils.js +3 -1
  51. package/dist/geometry/geometry.d.ts +5 -4
  52. package/dist/geometry/geometry.d.ts.map +1 -1
  53. package/dist/geometry/geometry.js +9 -5
  54. package/dist/geometry/gpu-geometry.d.ts +1 -1
  55. package/dist/geometry/gpu-geometry.d.ts.map +1 -1
  56. package/dist/geometry/gpu-geometry.js +18 -6
  57. package/dist/geometry/gpu-table.js +3 -0
  58. package/dist/index.cjs +491 -244
  59. package/dist/index.cjs.map +4 -4
  60. package/dist/index.d.ts +5 -0
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +8 -0
  63. package/dist/lib/clip-space.d.ts.map +1 -1
  64. package/dist/lib/clip-space.js +3 -0
  65. package/dist/lib/pipeline-factory.d.ts +3 -2
  66. package/dist/lib/pipeline-factory.d.ts.map +1 -1
  67. package/dist/lib/pipeline-factory.js +12 -8
  68. package/dist/lib/shader-factory.d.ts +3 -2
  69. package/dist/lib/shader-factory.d.ts.map +1 -1
  70. package/dist/lib/shader-factory.js +11 -4
  71. package/dist/model/model.d.ts +10 -6
  72. package/dist/model/model.d.ts.map +1 -1
  73. package/dist/model/model.js +65 -8
  74. package/dist/model/split-uniforms-and-bindings.d.ts +9 -0
  75. package/dist/model/split-uniforms-and-bindings.d.ts.map +1 -0
  76. package/dist/model/split-uniforms-and-bindings.js +20 -0
  77. package/dist/scenegraph/group-node.d.ts +1 -1
  78. package/dist/scenegraph/group-node.d.ts.map +1 -1
  79. package/dist/scenegraph/group-node.js +3 -0
  80. package/dist/scenegraph/model-node.d.ts +2 -2
  81. package/dist/scenegraph/model-node.d.ts.map +1 -1
  82. package/dist/scenegraph/model-node.js +6 -3
  83. package/dist/scenegraph/scenegraph-node.d.ts +5 -6
  84. package/dist/scenegraph/scenegraph-node.d.ts.map +1 -1
  85. package/dist/scenegraph/scenegraph-node.js +11 -8
  86. package/dist/shader-inputs.d.ts +0 -1
  87. package/dist/shader-inputs.d.ts.map +1 -1
  88. package/dist/shader-inputs.js +5 -3
  89. package/dist/transform/buffer-transform.d.ts.map +1 -1
  90. package/dist/transform/buffer-transform.js +8 -2
  91. package/dist/transform/texture-transform.d.ts +2 -2
  92. package/dist/transform/texture-transform.d.ts.map +1 -1
  93. package/dist/transform/texture-transform.js +1 -0
  94. package/dist/utils/deep-equal.d.ts +9 -0
  95. package/dist/utils/deep-equal.d.ts.map +1 -0
  96. package/dist/utils/deep-equal.js +50 -0
  97. package/dist/utils/uid.d.ts +7 -0
  98. package/dist/utils/uid.d.ts.map +1 -0
  99. package/dist/utils/uid.js +14 -0
  100. package/package.json +7 -6
  101. package/src/animation/key-frames.ts +4 -0
  102. package/src/animation-loop/animation-loop-template.ts +4 -0
  103. package/src/animation-loop/animation-loop.ts +6 -4
  104. package/src/animation-loop/animation-props.ts +4 -0
  105. package/src/animation-loop/request-animation-frame.ts +19 -0
  106. package/src/application-utils/load-file.ts +53 -0
  107. package/src/application-utils/random.ts +18 -0
  108. package/src/async-texture/async-texture.ts +140 -0
  109. package/src/computation.ts +17 -9
  110. package/src/debug/copy-texture-to-image.ts +4 -1
  111. package/src/debug/debug-framebuffer.ts +18 -12
  112. package/src/debug/pixel-data-utils.ts +1 -1
  113. package/src/geometries/cone-geometry.ts +5 -1
  114. package/src/geometries/cube-geometry.ts +5 -1
  115. package/src/geometries/cylinder-geometry.ts +5 -1
  116. package/src/geometries/ico-sphere-geometry.ts +5 -1
  117. package/src/geometries/plane-geometry.ts +5 -1
  118. package/src/geometries/sphere-geometry.ts +5 -1
  119. package/src/geometries/truncated-cone-geometry.ts +5 -1
  120. package/src/geometry/geometry-table.ts +2 -1
  121. package/src/geometry/geometry-utils.ts +3 -1
  122. package/src/geometry/geometry.ts +16 -19
  123. package/src/geometry/gpu-geometry.ts +20 -14
  124. package/src/geometry/gpu-table.ts +4 -0
  125. package/src/index.ts +15 -0
  126. package/src/lib/clip-space.ts +4 -0
  127. package/src/lib/pipeline-factory.ts +17 -16
  128. package/src/lib/shader-factory.ts +13 -6
  129. package/src/model/model.ts +71 -17
  130. package/src/model/split-uniforms-and-bindings.ts +31 -0
  131. package/src/scenegraph/group-node.ts +4 -0
  132. package/src/scenegraph/model-node.ts +9 -5
  133. package/src/scenegraph/scenegraph-node.ts +17 -13
  134. package/src/shader-inputs.ts +5 -3
  135. package/src/transform/buffer-transform.ts +8 -9
  136. package/src/transform/texture-transform.ts +2 -1
  137. package/src/utils/deep-equal.ts +51 -0
  138. package/src/utils/uid.ts +16 -0
package/dist/dist.dev.js CHANGED
@@ -55,6 +55,7 @@ var __exports__ = (() => {
55
55
  __export(bundle_exports, {
56
56
  AnimationLoop: () => AnimationLoop,
57
57
  AnimationLoopTemplate: () => AnimationLoopTemplate,
58
+ AsyncTexture: () => AsyncTexture,
58
59
  BufferTransform: () => BufferTransform,
59
60
  ClipSpace: () => ClipSpace,
60
61
  Computation: () => Computation,
@@ -77,7 +78,13 @@ var __exports__ = (() => {
77
78
  Timeline: () => Timeline,
78
79
  TruncatedConeGeometry: () => TruncatedConeGeometry,
79
80
  _ShaderInputs: () => ShaderInputs,
80
- makeAnimationLoop: () => makeAnimationLoop
81
+ cancelAnimationFrame: () => cancelAnimationFrame,
82
+ loadImage: () => loadImage,
83
+ loadImageBitmap: () => loadImageBitmap,
84
+ makeAnimationLoop: () => makeAnimationLoop,
85
+ makeRandomGenerator: () => makeRandomGenerator,
86
+ requestAnimationFrame: () => requestAnimationFrame,
87
+ setPathPrefix: () => setPathPrefix
81
88
  });
82
89
  __reExport(bundle_exports, __toESM(require_core(), 1));
83
90
 
@@ -254,7 +261,14 @@ var __exports__ = (() => {
254
261
 
255
262
  // src/animation-loop/animation-loop.ts
256
263
  var import_core = __toESM(require_core(), 1);
257
- var import_core2 = __toESM(require_core(), 1);
264
+
265
+ // src/animation-loop/request-animation-frame.ts
266
+ function requestAnimationFrame(callback) {
267
+ return typeof window !== "undefined" && window.requestAnimationFrame ? window.requestAnimationFrame(callback) : setTimeout(callback, 1e3 / 60);
268
+ }
269
+ function cancelAnimationFrame(timerId) {
270
+ return typeof window !== "undefined" && window.cancelAnimationFrame ? window.cancelAnimationFrame(timerId) : clearTimeout(timerId);
271
+ }
258
272
 
259
273
  // ../../node_modules/@probe.gl/stats/dist/utils/hi-res-timestamp.js
260
274
  function getHiResTimestamp() {
@@ -273,8 +287,6 @@ var __exports__ = (() => {
273
287
  // ../../node_modules/@probe.gl/stats/dist/lib/stat.js
274
288
  var Stat = class {
275
289
  constructor(name, type) {
276
- this.name = void 0;
277
- this.type = void 0;
278
290
  this.sampleSize = 1;
279
291
  this.time = 0;
280
292
  this.count = 0;
@@ -309,26 +321,31 @@ var __exports__ = (() => {
309
321
  this.sampleSize = samples;
310
322
  return this;
311
323
  }
324
+ /** Call to increment count (+1) */
312
325
  incrementCount() {
313
326
  this.addCount(1);
314
327
  return this;
315
328
  }
329
+ /** Call to decrement count (-1) */
316
330
  decrementCount() {
317
331
  this.subtractCount(1);
318
332
  return this;
319
333
  }
334
+ /** Increase count */
320
335
  addCount(value) {
321
336
  this._count += value;
322
337
  this._samples++;
323
338
  this._checkSampling();
324
339
  return this;
325
340
  }
341
+ /** Decrease count */
326
342
  subtractCount(value) {
327
343
  this._count -= value;
328
344
  this._samples++;
329
345
  this._checkSampling();
330
346
  return this;
331
347
  }
348
+ /** Add an arbitrary timing and bump the count */
332
349
  addTime(time) {
333
350
  this._time += time;
334
351
  this.lastTiming = time;
@@ -336,11 +353,13 @@ var __exports__ = (() => {
336
353
  this._checkSampling();
337
354
  return this;
338
355
  }
356
+ /** Start a timer */
339
357
  timeStart() {
340
358
  this._startTime = getHiResTimestamp();
341
359
  this._timerPending = true;
342
360
  return this;
343
361
  }
362
+ /** End a timer. Adds to time and bumps the timing count. */
344
363
  timeEnd() {
345
364
  if (!this._timerPending) {
346
365
  return this;
@@ -353,18 +372,22 @@ var __exports__ = (() => {
353
372
  getSampleAverageCount() {
354
373
  return this.sampleSize > 0 ? this.lastSampleCount / this.sampleSize : 0;
355
374
  }
375
+ /** Calculate average time / count for the previous window */
356
376
  getSampleAverageTime() {
357
377
  return this.sampleSize > 0 ? this.lastSampleTime / this.sampleSize : 0;
358
378
  }
379
+ /** Calculate counts per second for the previous window */
359
380
  getSampleHz() {
360
381
  return this.lastSampleTime > 0 ? this.sampleSize / (this.lastSampleTime / 1e3) : 0;
361
382
  }
362
383
  getAverageCount() {
363
384
  return this.samples > 0 ? this.count / this.samples : 0;
364
385
  }
386
+ /** Calculate average time / count */
365
387
  getAverageTime() {
366
388
  return this.samples > 0 ? this.time / this.samples : 0;
367
389
  }
390
+ /** Calculate counts per second */
368
391
  getHz() {
369
392
  return this.time > 0 ? this.samples / (this.time / 1e3) : 0;
370
393
  }
@@ -385,23 +408,20 @@ var __exports__ = (() => {
385
408
  // ../../node_modules/@probe.gl/stats/dist/lib/stats.js
386
409
  var Stats = class {
387
410
  constructor(options) {
388
- this.id = void 0;
389
411
  this.stats = {};
390
412
  this.id = options.id;
391
413
  this.stats = {};
392
414
  this._initializeStats(options.stats);
393
415
  Object.seal(this);
394
416
  }
395
- get(name) {
396
- let type = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "count";
397
- return this._getOrCreate({
398
- name,
399
- type
400
- });
417
+ /** Acquire a stat. Create if it doesn't exist. */
418
+ get(name, type = "count") {
419
+ return this._getOrCreate({ name, type });
401
420
  }
402
421
  get size() {
403
422
  return Object.keys(this.stats).length;
404
423
  }
424
+ /** Reset all stats */
405
425
  reset() {
406
426
  for (const stat of Object.values(this.stats)) {
407
427
  stat.reset();
@@ -425,15 +445,11 @@ var __exports__ = (() => {
425
445
  });
426
446
  return table;
427
447
  }
428
- _initializeStats() {
429
- let stats = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : [];
448
+ _initializeStats(stats = []) {
430
449
  stats.forEach((stat) => this._getOrCreate(stat));
431
450
  }
432
451
  _getOrCreate(stat) {
433
- const {
434
- name,
435
- type
436
- } = stat;
452
+ const { name, type } = stat;
437
453
  let result = this.stats[name];
438
454
  if (!result) {
439
455
  if (stat instanceof Stat) {
@@ -645,13 +661,13 @@ var __exports__ = (() => {
645
661
  if (!this._running) {
646
662
  return;
647
663
  }
648
- this._animationFrameId = (0, import_core2.requestAnimationFrame)(this._animationFrame.bind(this));
664
+ this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
649
665
  }
650
666
  _cancelAnimationFrame() {
651
667
  if (this._animationFrameId === null) {
652
668
  return;
653
669
  }
654
- (0, import_core2.cancelAnimationFrame)(this._animationFrameId);
670
+ cancelAnimationFrame(this._animationFrameId);
655
671
  this._animationFrameId = null;
656
672
  }
657
673
  _animationFrame() {
@@ -669,7 +685,7 @@ var __exports__ = (() => {
669
685
  return;
670
686
  }
671
687
  this.props.onRender(this._getAnimationProps());
672
- this.device.submit();
688
+ this.device?.submit();
673
689
  }
674
690
  _clearNeedsRedraw() {
675
691
  this.needsRedraw = false;
@@ -680,13 +696,14 @@ var __exports__ = (() => {
680
696
  }
681
697
  // Initialize the object that will be passed to app callbacks
682
698
  _initializeAnimationProps() {
683
- if (!this.device) {
699
+ const canvas2 = this.device?.canvasContext?.canvas;
700
+ if (!this.device || !canvas2) {
684
701
  throw new Error("loop");
685
702
  }
686
703
  this.animationProps = {
687
704
  animationLoop: this,
688
705
  device: this.device,
689
- canvas: this.device?.canvasContext?.canvas,
706
+ canvas: canvas2,
690
707
  timeline: this.timeline,
691
708
  // Initial values
692
709
  useDevicePixels: this.props.useDevicePixels,
@@ -827,10 +844,10 @@ var __exports__ = (() => {
827
844
  };
828
845
 
829
846
  // src/animation-loop/make-animation-loop.ts
830
- var import_core3 = __toESM(require_core(), 1);
847
+ var import_core2 = __toESM(require_core(), 1);
831
848
  function makeAnimationLoop(AnimationLoopTemplateCtor, props) {
832
849
  let renderLoop = null;
833
- const device = props?.device || import_core3.luma.createDevice();
850
+ const device = props?.device || import_core2.luma.createDevice();
834
851
  const animationLoop = new AnimationLoop({
835
852
  ...props,
836
853
  device,
@@ -848,10 +865,10 @@ var __exports__ = (() => {
848
865
  }
849
866
 
850
867
  // src/model/model.ts
868
+ var import_core8 = __toESM(require_core(), 1);
851
869
  var import_core9 = __toESM(require_core(), 1);
852
870
  var import_core10 = __toESM(require_core(), 1);
853
871
  var import_core11 = __toESM(require_core(), 1);
854
- var import_core12 = __toESM(require_core(), 1);
855
872
 
856
873
  // ../shadertools/src/lib/glsl-utils/highlight.ts
857
874
  var glsl = (x) => `${x}`;
@@ -1178,40 +1195,6 @@ ${moduleSource}
1178
1195
  }
1179
1196
  };
1180
1197
 
1181
- // ../shadertools/src/lib/shader-assembly/select-shaders.ts
1182
- function selectShaders(props) {
1183
- if (props.source && props.platformInfo.type === "webgpu") {
1184
- const propsCopy = { ...props, vs: void 0, fs: void 0 };
1185
- return propsCopy;
1186
- }
1187
- if (!props.vs) {
1188
- throw new Error("no vertex shader");
1189
- }
1190
- const vs = getShaderSource(props.platformInfo, props.vs);
1191
- let fs;
1192
- if (props.fs) {
1193
- fs = getShaderSource(props.platformInfo, props.fs);
1194
- }
1195
- return { ...props, vs, fs };
1196
- }
1197
- function getShaderSource(platformInfo, shader) {
1198
- if (typeof shader === "string") {
1199
- return shader;
1200
- }
1201
- switch (platformInfo.type) {
1202
- case "webgpu":
1203
- if (shader?.wgsl) {
1204
- return shader.wgsl;
1205
- }
1206
- throw new Error("WebGPU does not support GLSL shaders");
1207
- default:
1208
- if (shader?.glsl) {
1209
- return shader.glsl;
1210
- }
1211
- throw new Error("WebGL does not support WGSL shaders");
1212
- }
1213
- }
1214
-
1215
1198
  // ../shadertools/src/lib/shader-assembly/resolve-modules.ts
1216
1199
  function resolveModules(modules) {
1217
1200
  const instances = ShaderModuleInstance.instantiateModules(modules);
@@ -1423,10 +1406,10 @@ ${DECLARATION_INJECT_MARKER}
1423
1406
  var FRAGMENT_SHADER_PROLOGUE = glsl`\
1424
1407
  precision highp float;
1425
1408
  `;
1426
- function assembleShaderWGSL(options) {
1409
+ function assembleWGSLShader(options) {
1427
1410
  const modules = resolveModules(options.modules || []);
1428
1411
  return {
1429
- source: assembleWGSLShader(options.platformInfo, {
1412
+ source: assembleShaderWGSL(options.platformInfo, {
1430
1413
  ...options,
1431
1414
  source: options.source,
1432
1415
  stage: "vertex",
@@ -1435,36 +1418,19 @@ precision highp float;
1435
1418
  getUniforms: assembleGetUniforms(modules)
1436
1419
  };
1437
1420
  }
1438
- function assembleShaderPairWGSL(options) {
1439
- const modules = resolveModules(options.modules || []);
1440
- return {
1441
- vs: assembleWGSLShader(options.platformInfo, {
1442
- ...options,
1443
- source: options.vs,
1444
- stage: "vertex",
1445
- modules
1446
- }),
1447
- fs: assembleWGSLShader(options.platformInfo, {
1448
- ...options,
1449
- source: options.fs,
1450
- stage: "fragment",
1451
- modules
1452
- }),
1453
- getUniforms: assembleGetUniforms(modules)
1454
- };
1455
- }
1456
- function assembleShaderPairGLSL(options) {
1421
+ function assembleGLSLShaderPair(options) {
1457
1422
  const { vs, fs } = options;
1458
1423
  const modules = resolveModules(options.modules || []);
1459
1424
  return {
1460
- vs: assembleGLSLShader(options.platformInfo, {
1425
+ vs: assembleShaderGLSL(options.platformInfo, {
1461
1426
  ...options,
1462
1427
  source: vs,
1463
1428
  stage: "vertex",
1464
1429
  modules
1465
1430
  }),
1466
- fs: assembleGLSLShader(options.platformInfo, {
1431
+ fs: assembleShaderGLSL(options.platformInfo, {
1467
1432
  ...options,
1433
+ // @ts-expect-error
1468
1434
  source: fs,
1469
1435
  stage: "fragment",
1470
1436
  modules
@@ -1472,7 +1438,7 @@ precision highp float;
1472
1438
  getUniforms: assembleGetUniforms(modules)
1473
1439
  };
1474
1440
  }
1475
- function assembleWGSLShader(platformInfo, options) {
1441
+ function assembleShaderWGSL(platformInfo, options) {
1476
1442
  const {
1477
1443
  // id,
1478
1444
  source,
@@ -1537,7 +1503,7 @@ precision highp float;
1537
1503
  assembledSource = injectShader(assembledSource, stage, mainInjections);
1538
1504
  return assembledSource;
1539
1505
  }
1540
- function assembleGLSLShader(platformInfo, options) {
1506
+ function assembleShaderGLSL(platformInfo, options) {
1541
1507
  const {
1542
1508
  id,
1543
1509
  source,
@@ -1666,6 +1632,29 @@ ${getApplicationDefines(allDefines)}
1666
1632
  return sourceText;
1667
1633
  }
1668
1634
 
1635
+ // ../shadertools/src/lib/preprocessor/preprocessor.ts
1636
+ var IFDEF_REGEXP = /^\s*\#\s*ifdef\s*([a-zA-Z_]+)\s*$/;
1637
+ var ENDIF_REGEXP = /^\s*\#\s*endif\s*$/;
1638
+ function preprocess(source, options) {
1639
+ const lines = source.split("\n");
1640
+ const output = [];
1641
+ let conditional = true;
1642
+ let currentDefine = null;
1643
+ for (const line of lines) {
1644
+ const matchIf = line.match(IFDEF_REGEXP);
1645
+ const matchEnd = line.match(ENDIF_REGEXP);
1646
+ if (matchIf) {
1647
+ currentDefine = matchIf[1];
1648
+ conditional = Boolean(options?.defines?.[currentDefine]);
1649
+ } else if (matchEnd) {
1650
+ conditional = true;
1651
+ } else if (conditional) {
1652
+ output.push(line);
1653
+ }
1654
+ }
1655
+ return output.join("\n");
1656
+ }
1657
+
1669
1658
  // ../shadertools/src/lib/shader-assembler.ts
1670
1659
  var _ShaderAssembler = class {
1671
1660
  /** Hook functions */
@@ -1709,22 +1698,23 @@ ${getApplicationDefines(allDefines)}
1709
1698
  this._hookFunctions.push(hook);
1710
1699
  }
1711
1700
  /**
1712
- * Assemble a pair of shaders into a single shader program
1701
+ * Assemble a WGSL unified shader
1713
1702
  * @param platformInfo
1714
1703
  * @param props
1715
1704
  * @returns
1716
1705
  */
1717
- assembleShader(props) {
1706
+ assembleWGSLShader(props) {
1718
1707
  const modules = this._getModuleList(props.modules);
1719
1708
  const hookFunctions = this._hookFunctions;
1720
- const options = selectShaders(props);
1721
- const assembled = assembleShaderWGSL({
1722
- platformInfo: props.platformInfo,
1723
- ...options,
1709
+ const { source, getUniforms } = assembleWGSLShader({
1710
+ ...props,
1711
+ // @ts-expect-error
1712
+ source: props.source,
1724
1713
  modules,
1725
1714
  hookFunctions
1726
1715
  });
1727
- return { ...assembled, modules };
1716
+ const preprocessedSource = props.platformInfo.shaderLanguage === "wgsl" ? preprocess(source) : source;
1717
+ return { source: preprocessedSource, getUniforms, modules };
1728
1718
  }
1729
1719
  /**
1730
1720
  * Assemble a pair of shaders into a single shader program
@@ -1732,13 +1722,18 @@ ${getApplicationDefines(allDefines)}
1732
1722
  * @param props
1733
1723
  * @returns
1734
1724
  */
1735
- assembleShaderPair(props) {
1736
- const options = selectShaders(props);
1725
+ assembleGLSLShaderPair(props) {
1737
1726
  const modules = this._getModuleList(props.modules);
1738
1727
  const hookFunctions = this._hookFunctions;
1739
- const { platformInfo } = props;
1740
- const isWGSL = props.platformInfo.shaderLanguage === "wgsl";
1741
- const assembled = isWGSL ? assembleShaderPairWGSL({ platformInfo, ...options, modules, hookFunctions }) : assembleShaderPairGLSL({ platformInfo, ...options, modules, hookFunctions });
1728
+ const assembled = assembleGLSLShaderPair({
1729
+ ...props,
1730
+ // @ts-expect-error
1731
+ vs: props.vs,
1732
+ // @ts-expect-error
1733
+ fs: props.fs,
1734
+ modules,
1735
+ hookFunctions
1736
+ });
1742
1737
  return { ...assembled, modules };
1743
1738
  }
1744
1739
  /**
@@ -1827,9 +1822,9 @@ void main() {
1827
1822
  }
1828
1823
 
1829
1824
  // ../shadertools/src/lib/wgsl/get-shader-layout-wgsl.ts
1830
- var import_core4 = __toESM(require_core(), 1);
1825
+ var import_core3 = __toESM(require_core(), 1);
1831
1826
 
1832
- // ../shadertools/src/libs/wgsl-reflect/wgsl_reflect.module.js
1827
+ // ../../node_modules/wgsl_reflect/wgsl_reflect.module.js
1833
1828
  var ParseContext = class {
1834
1829
  constructor() {
1835
1830
  this.constants = /* @__PURE__ */ new Map();
@@ -1852,23 +1847,50 @@ void main() {
1852
1847
  evaluateString(context) {
1853
1848
  return this.evaluate(context).toString();
1854
1849
  }
1850
+ search(callback) {
1851
+ }
1852
+ searchBlock(block, callback) {
1853
+ if (block) {
1854
+ callback(_BlockStart.instance);
1855
+ for (const node of block) {
1856
+ if (node instanceof Array) {
1857
+ this.searchBlock(node, callback);
1858
+ } else {
1859
+ node.search(callback);
1860
+ }
1861
+ }
1862
+ callback(_BlockEnd.instance);
1863
+ }
1864
+ }
1855
1865
  };
1866
+ var _BlockStart = class extends Node {
1867
+ };
1868
+ _BlockStart.instance = new _BlockStart();
1869
+ var _BlockEnd = class extends Node {
1870
+ };
1871
+ _BlockEnd.instance = new _BlockEnd();
1856
1872
  var Statement = class extends Node {
1857
1873
  constructor() {
1858
1874
  super();
1859
1875
  }
1860
1876
  };
1861
1877
  var Function = class extends Statement {
1862
- constructor(name, args, returnType, body) {
1878
+ constructor(name, args, returnType, body, startLine, endLine) {
1863
1879
  super();
1880
+ this.calls = /* @__PURE__ */ new Set();
1864
1881
  this.name = name;
1865
1882
  this.args = args;
1866
1883
  this.returnType = returnType;
1867
1884
  this.body = body;
1885
+ this.startLine = startLine;
1886
+ this.endLine = endLine;
1868
1887
  }
1869
1888
  get astNodeType() {
1870
1889
  return "function";
1871
1890
  }
1891
+ search(callback) {
1892
+ this.searchBlock(this.body, callback);
1893
+ }
1872
1894
  };
1873
1895
  var StaticAssert = class extends Statement {
1874
1896
  constructor(expression) {
@@ -1878,6 +1900,9 @@ void main() {
1878
1900
  get astNodeType() {
1879
1901
  return "staticAssert";
1880
1902
  }
1903
+ search(callback) {
1904
+ this.expression.search(callback);
1905
+ }
1881
1906
  };
1882
1907
  var While = class extends Statement {
1883
1908
  constructor(condition, body) {
@@ -1888,6 +1913,10 @@ void main() {
1888
1913
  get astNodeType() {
1889
1914
  return "while";
1890
1915
  }
1916
+ search(callback) {
1917
+ this.condition.search(callback);
1918
+ this.searchBlock(this.body, callback);
1919
+ }
1891
1920
  };
1892
1921
  var Continuing = class extends Statement {
1893
1922
  constructor(body) {
@@ -1897,6 +1926,9 @@ void main() {
1897
1926
  get astNodeType() {
1898
1927
  return "continuing";
1899
1928
  }
1929
+ search(callback) {
1930
+ this.searchBlock(this.body, callback);
1931
+ }
1900
1932
  };
1901
1933
  var For = class extends Statement {
1902
1934
  constructor(init, condition, increment, body) {
@@ -1909,6 +1941,13 @@ void main() {
1909
1941
  get astNodeType() {
1910
1942
  return "for";
1911
1943
  }
1944
+ search(callback) {
1945
+ var _a2, _b, _c;
1946
+ (_a2 = this.init) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
1947
+ (_b = this.condition) === null || _b === void 0 ? void 0 : _b.search(callback);
1948
+ (_c = this.increment) === null || _c === void 0 ? void 0 : _c.search(callback);
1949
+ this.searchBlock(this.body, callback);
1950
+ }
1912
1951
  };
1913
1952
  var Var = class extends Statement {
1914
1953
  constructor(name, type, storage, access, value) {
@@ -1922,6 +1961,11 @@ void main() {
1922
1961
  get astNodeType() {
1923
1962
  return "var";
1924
1963
  }
1964
+ search(callback) {
1965
+ var _a2;
1966
+ callback(this);
1967
+ (_a2 = this.value) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
1968
+ }
1925
1969
  };
1926
1970
  var Override = class extends Statement {
1927
1971
  constructor(name, type, value) {
@@ -1933,6 +1977,10 @@ void main() {
1933
1977
  get astNodeType() {
1934
1978
  return "override";
1935
1979
  }
1980
+ search(callback) {
1981
+ var _a2;
1982
+ (_a2 = this.value) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
1983
+ }
1936
1984
  };
1937
1985
  var Let = class extends Statement {
1938
1986
  constructor(name, type, storage, access, value) {
@@ -1946,6 +1994,11 @@ void main() {
1946
1994
  get astNodeType() {
1947
1995
  return "let";
1948
1996
  }
1997
+ search(callback) {
1998
+ var _a2;
1999
+ callback(this);
2000
+ (_a2 = this.value) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
2001
+ }
1949
2002
  };
1950
2003
  var Const = class extends Statement {
1951
2004
  constructor(name, type, storage, access, value) {
@@ -1962,6 +2015,11 @@ void main() {
1962
2015
  evaluate(context) {
1963
2016
  return this.value.evaluate(context);
1964
2017
  }
2018
+ search(callback) {
2019
+ var _a2;
2020
+ callback(this);
2021
+ (_a2 = this.value) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
2022
+ }
1965
2023
  };
1966
2024
  var IncrementOperator;
1967
2025
  (function(IncrementOperator2) {
@@ -1986,6 +2044,9 @@ void main() {
1986
2044
  get astNodeType() {
1987
2045
  return "increment";
1988
2046
  }
2047
+ search(callback) {
2048
+ this.variable.search(callback);
2049
+ }
1989
2050
  };
1990
2051
  var AssignOperator;
1991
2052
  (function(AssignOperator2) {
@@ -2004,9 +2065,10 @@ void main() {
2004
2065
  (function(AssignOperator2) {
2005
2066
  function parse(val) {
2006
2067
  const key = val;
2007
- if (key == "parse")
2068
+ if (key == "parse") {
2008
2069
  throw new Error("Invalid value for AssignOperator");
2009
- return AssignOperator2[key];
2070
+ }
2071
+ return key;
2010
2072
  }
2011
2073
  AssignOperator2.parse = parse;
2012
2074
  })(AssignOperator || (AssignOperator = {}));
@@ -2020,6 +2082,9 @@ void main() {
2020
2082
  get astNodeType() {
2021
2083
  return "assign";
2022
2084
  }
2085
+ search(callback) {
2086
+ this.value.search(callback);
2087
+ }
2023
2088
  };
2024
2089
  var Call = class extends Statement {
2025
2090
  constructor(name, args) {
@@ -2030,6 +2095,12 @@ void main() {
2030
2095
  get astNodeType() {
2031
2096
  return "call";
2032
2097
  }
2098
+ search(callback) {
2099
+ for (const node of this.args) {
2100
+ node.search(callback);
2101
+ }
2102
+ callback(this);
2103
+ }
2033
2104
  };
2034
2105
  var Loop = class extends Statement {
2035
2106
  constructor(body, continuing) {
@@ -2062,6 +2133,12 @@ void main() {
2062
2133
  get astNodeType() {
2063
2134
  return "if";
2064
2135
  }
2136
+ search(callback) {
2137
+ this.condition.search(callback);
2138
+ this.searchBlock(this.body, callback);
2139
+ this.searchBlock(this.elseif, callback);
2140
+ this.searchBlock(this.else, callback);
2141
+ }
2065
2142
  };
2066
2143
  var Return = class extends Statement {
2067
2144
  constructor(value) {
@@ -2071,6 +2148,10 @@ void main() {
2071
2148
  get astNodeType() {
2072
2149
  return "return";
2073
2150
  }
2151
+ search(callback) {
2152
+ var _a2;
2153
+ (_a2 = this.value) === null || _a2 === void 0 ? void 0 : _a2.search(callback);
2154
+ }
2074
2155
  };
2075
2156
  var Enable = class extends Statement {
2076
2157
  constructor(name) {
@@ -2081,6 +2162,16 @@ void main() {
2081
2162
  return "enable";
2082
2163
  }
2083
2164
  };
2165
+ var Diagnostic = class extends Statement {
2166
+ constructor(severity, rule) {
2167
+ super();
2168
+ this.severity = severity;
2169
+ this.rule = rule;
2170
+ }
2171
+ get astNodeType() {
2172
+ return "diagnostic";
2173
+ }
2174
+ };
2084
2175
  var Alias = class extends Statement {
2085
2176
  constructor(name, type) {
2086
2177
  super();
@@ -2131,9 +2222,11 @@ void main() {
2131
2222
  }
2132
2223
  };
2133
2224
  var Struct = class extends Type {
2134
- constructor(name, members) {
2225
+ constructor(name, members, startLine, endLine) {
2135
2226
  super(name);
2136
2227
  this.members = members;
2228
+ this.startLine = startLine;
2229
+ this.endLine = endLine;
2137
2230
  }
2138
2231
  get astNodeType() {
2139
2232
  return "struct";
@@ -2224,6 +2317,12 @@ void main() {
2224
2317
  get astNodeType() {
2225
2318
  return "createExpr";
2226
2319
  }
2320
+ search(callback) {
2321
+ callback(this);
2322
+ for (const node of this.args) {
2323
+ node.search(callback);
2324
+ }
2325
+ }
2227
2326
  };
2228
2327
  var CallExpr = class extends Expression {
2229
2328
  constructor(name, args) {
@@ -2317,6 +2416,12 @@ void main() {
2317
2416
  throw new Error("Non const function: " + this.name);
2318
2417
  }
2319
2418
  }
2419
+ search(callback) {
2420
+ for (const node of this.args) {
2421
+ node.search(callback);
2422
+ }
2423
+ callback(this);
2424
+ }
2320
2425
  };
2321
2426
  var VariableExpr = class extends Expression {
2322
2427
  constructor(name) {
@@ -2326,6 +2431,16 @@ void main() {
2326
2431
  get astNodeType() {
2327
2432
  return "varExpr";
2328
2433
  }
2434
+ search(callback) {
2435
+ callback(this);
2436
+ }
2437
+ evaluate(context) {
2438
+ const constant = context.constants.get(this.name);
2439
+ if (!constant) {
2440
+ throw new Error("Cannot evaluate node");
2441
+ }
2442
+ return constant.evaluate(context);
2443
+ }
2329
2444
  };
2330
2445
  var ConstExpr = class extends Expression {
2331
2446
  constructor(name, initializer) {
@@ -2351,6 +2466,9 @@ void main() {
2351
2466
  }
2352
2467
  return this.initializer.evaluate(context);
2353
2468
  }
2469
+ search(callback) {
2470
+ this.initializer.search(callback);
2471
+ }
2354
2472
  };
2355
2473
  var LiteralExpr = class extends Expression {
2356
2474
  constructor(value) {
@@ -2373,6 +2491,9 @@ void main() {
2373
2491
  get astNodeType() {
2374
2492
  return "bitcastExpr";
2375
2493
  }
2494
+ search(callback) {
2495
+ this.value.search(callback);
2496
+ }
2376
2497
  };
2377
2498
  var TypecastExpr = class extends Expression {
2378
2499
  constructor(type, args) {
@@ -2386,6 +2507,9 @@ void main() {
2386
2507
  evaluate(context) {
2387
2508
  return this.args[0].evaluate(context);
2388
2509
  }
2510
+ search(callback) {
2511
+ this.searchBlock(this.args, callback);
2512
+ }
2389
2513
  };
2390
2514
  var GroupingExpr = class extends Expression {
2391
2515
  constructor(contents) {
@@ -2398,6 +2522,9 @@ void main() {
2398
2522
  evaluate(context) {
2399
2523
  return this.contents[0].evaluate(context);
2400
2524
  }
2525
+ search(callback) {
2526
+ this.searchBlock(this.contents, callback);
2527
+ }
2401
2528
  };
2402
2529
  var Operator = class extends Expression {
2403
2530
  constructor() {
@@ -2427,6 +2554,9 @@ void main() {
2427
2554
  throw new Error("Unknown unary operator: " + this.operator);
2428
2555
  }
2429
2556
  }
2557
+ search(callback) {
2558
+ this.right.search(callback);
2559
+ }
2430
2560
  };
2431
2561
  var BinaryOperator = class extends Operator {
2432
2562
  constructor(operator, left, right) {
@@ -2470,6 +2600,10 @@ void main() {
2470
2600
  throw new Error(`Unknown operator ${this.operator}`);
2471
2601
  }
2472
2602
  }
2603
+ search(callback) {
2604
+ this.left.search(callback);
2605
+ this.right.search(callback);
2606
+ }
2473
2607
  };
2474
2608
  var SwitchCase = class extends Node {
2475
2609
  constructor() {
@@ -2485,6 +2619,9 @@ void main() {
2485
2619
  get astNodeType() {
2486
2620
  return "case";
2487
2621
  }
2622
+ search(callback) {
2623
+ this.searchBlock(this.body, callback);
2624
+ }
2488
2625
  };
2489
2626
  var Default = class extends SwitchCase {
2490
2627
  constructor(body) {
@@ -2494,6 +2631,9 @@ void main() {
2494
2631
  get astNodeType() {
2495
2632
  return "default";
2496
2633
  }
2634
+ search(callback) {
2635
+ this.searchBlock(this.body, callback);
2636
+ }
2497
2637
  };
2498
2638
  var Argument = class extends Node {
2499
2639
  constructor(name, type, attributes) {
@@ -2515,6 +2655,10 @@ void main() {
2515
2655
  get astNodeType() {
2516
2656
  return "elseif";
2517
2657
  }
2658
+ search(callback) {
2659
+ this.condition.search(callback);
2660
+ this.searchBlock(this.body, callback);
2661
+ }
2518
2662
  };
2519
2663
  var Member = class extends Node {
2520
2664
  constructor(name, type, attributes) {
@@ -2632,6 +2776,7 @@ void main() {
2632
2776
  discard: new TokenType("discard", TokenClass.keyword, "discard"),
2633
2777
  else: new TokenType("else", TokenClass.keyword, "else"),
2634
2778
  enable: new TokenType("enable", TokenClass.keyword, "enable"),
2779
+ diagnostic: new TokenType("diagnostic", TokenClass.keyword, "diagnostic"),
2635
2780
  fallthrough: new TokenType("fallthrough", TokenClass.keyword, "fallthrough"),
2636
2781
  false: new TokenType("false", TokenClass.keyword, "false"),
2637
2782
  fn: new TokenType("fn", TokenClass.keyword, "fn"),
@@ -2704,7 +2849,7 @@ void main() {
2704
2849
  hex_float_literal: new TokenType("hex_float_literal", TokenClass.token, /-?0x((([0-9a-fA-F]*\.[0-9a-fA-F]+|[0-9a-fA-F]+\.[0-9a-fA-F]*)((p|P)(\+|-)?[0-9]+f?)?)|([0-9a-fA-F]+(p|P)(\+|-)?[0-9]+f?))/),
2705
2850
  int_literal: new TokenType("int_literal", TokenClass.token, /-?0x[0-9a-fA-F]+|0i?|-?[1-9][0-9]*i?/),
2706
2851
  uint_literal: new TokenType("uint_literal", TokenClass.token, /0x[0-9a-fA-F]+u|0u|[1-9][0-9]*u/),
2707
- ident: new TokenType("ident", TokenClass.token, /[a-zA-Z][0-9a-zA-Z_]*/),
2852
+ ident: new TokenType("ident", TokenClass.token, /[_a-zA-Z][0-9a-zA-Z_]*/),
2708
2853
  and: new TokenType("and", TokenClass.token, "&"),
2709
2854
  and_and: new TokenType("and_and", TokenClass.token, "&&"),
2710
2855
  arrow: new TokenType("arrow ", TokenClass.token, "->"),
@@ -2925,8 +3070,9 @@ void main() {
2925
3070
  scanTokens() {
2926
3071
  while (!this._isAtEnd()) {
2927
3072
  this._start = this._current;
2928
- if (!this.scanToken())
3073
+ if (!this.scanToken()) {
2929
3074
  throw `Invalid syntax at line ${this._line}`;
3075
+ }
2930
3076
  }
2931
3077
  this._tokens.push(new Token(TokenTypes.eof, "", this._line));
2932
3078
  return this._tokens;
@@ -2944,8 +3090,9 @@ void main() {
2944
3090
  if (lexeme == "/") {
2945
3091
  if (this._peekAhead() == "/") {
2946
3092
  while (lexeme != "\n") {
2947
- if (this._isAtEnd())
3093
+ if (this._isAtEnd()) {
2948
3094
  return true;
3095
+ }
2949
3096
  lexeme = this._advance();
2950
3097
  }
2951
3098
  this._line++;
@@ -2954,8 +3101,9 @@ void main() {
2954
3101
  this._advance();
2955
3102
  let commentLevel = 1;
2956
3103
  while (commentLevel > 0) {
2957
- if (this._isAtEnd())
3104
+ if (this._isAtEnd()) {
2958
3105
  return true;
3106
+ }
2959
3107
  lexeme = this._advance();
2960
3108
  if (lexeme == "\n") {
2961
3109
  this._line++;
@@ -3010,8 +3158,9 @@ void main() {
3010
3158
  }
3011
3159
  }
3012
3160
  if (matchedType === TokenTypes.none) {
3013
- if (matchType === TokenTypes.none)
3161
+ if (matchType === TokenTypes.none) {
3014
3162
  return false;
3163
+ }
3015
3164
  this._current--;
3016
3165
  this._addToken(matchType);
3017
3166
  return true;
@@ -3020,12 +3169,14 @@ void main() {
3020
3169
  this._current += lookAhead + 1;
3021
3170
  }
3022
3171
  matchType = matchedType;
3023
- if (this._isAtEnd())
3172
+ if (this._isAtEnd()) {
3024
3173
  break;
3174
+ }
3025
3175
  lexeme += this._advance();
3026
3176
  }
3027
- if (matchType === TokenTypes.none)
3177
+ if (matchType === TokenTypes.none) {
3028
3178
  return false;
3179
+ }
3029
3180
  this._addToken(matchType);
3030
3181
  return true;
3031
3182
  }
@@ -3051,8 +3202,9 @@ void main() {
3051
3202
  }
3052
3203
  } else {
3053
3204
  const match = rule.exec(lexeme);
3054
- if (match && match.index == 0 && match[0] == lexeme)
3205
+ if (match && match.index == 0 && match[0] == lexeme) {
3055
3206
  return true;
3207
+ }
3056
3208
  }
3057
3209
  return false;
3058
3210
  }
@@ -3071,8 +3223,9 @@ void main() {
3071
3223
  }
3072
3224
  _peekAhead(offset = 0) {
3073
3225
  offset = offset || 0;
3074
- if (this._current + offset >= this._source.length)
3226
+ if (this._current + offset >= this._source.length) {
3075
3227
  return "\0";
3228
+ }
3076
3229
  return this._source[this._current + offset];
3077
3230
  }
3078
3231
  _addToken(type) {
@@ -3084,17 +3237,40 @@ void main() {
3084
3237
  constructor() {
3085
3238
  this._tokens = [];
3086
3239
  this._current = 0;
3240
+ this._currentLine = 0;
3087
3241
  this._context = new ParseContext();
3242
+ this._deferArrayCountEval = [];
3088
3243
  }
3089
3244
  parse(tokensOrCode) {
3090
3245
  this._initialize(tokensOrCode);
3091
- let statements = [];
3246
+ this._deferArrayCountEval.length = 0;
3247
+ const statements = [];
3092
3248
  while (!this._isAtEnd()) {
3093
3249
  const statement = this._global_decl_or_directive();
3094
- if (!statement)
3250
+ if (!statement) {
3095
3251
  break;
3252
+ }
3096
3253
  statements.push(statement);
3097
3254
  }
3255
+ if (this._deferArrayCountEval.length > 0) {
3256
+ for (const arrayDecl of this._deferArrayCountEval) {
3257
+ const arrayType = arrayDecl["arrayType"];
3258
+ const countNode = arrayDecl["countNode"];
3259
+ if (countNode instanceof VariableExpr) {
3260
+ const variable = countNode;
3261
+ const name = variable.name;
3262
+ const constant = this._context.constants.get(name);
3263
+ if (constant) {
3264
+ try {
3265
+ const count = constant.evaluate(this._context);
3266
+ arrayType.count = count;
3267
+ } catch (e) {
3268
+ }
3269
+ }
3270
+ }
3271
+ }
3272
+ this._deferArrayCountEval.length = 0;
3273
+ }
3098
3274
  return statements;
3099
3275
  }
3100
3276
  _initialize(tokensOrCode) {
@@ -3111,7 +3287,6 @@ void main() {
3111
3287
  this._current = 0;
3112
3288
  }
3113
3289
  _error(token, message) {
3114
- console.error(token, message);
3115
3290
  return {
3116
3291
  token,
3117
3292
  message,
@@ -3141,24 +3316,29 @@ void main() {
3141
3316
  return false;
3142
3317
  }
3143
3318
  _consume(types, message) {
3144
- if (this._check(types))
3319
+ if (this._check(types)) {
3145
3320
  return this._advance();
3321
+ }
3146
3322
  throw this._error(this._peek(), message);
3147
3323
  }
3148
3324
  _check(types) {
3149
- if (this._isAtEnd())
3325
+ if (this._isAtEnd()) {
3150
3326
  return false;
3327
+ }
3151
3328
  const tk = this._peek();
3152
3329
  if (types instanceof Array) {
3153
- let t = tk.type;
3154
- let index2 = types.indexOf(t);
3330
+ const t = tk.type;
3331
+ const index2 = types.indexOf(t);
3155
3332
  return index2 != -1;
3156
3333
  }
3157
3334
  return tk.type == types;
3158
3335
  }
3159
3336
  _advance() {
3160
- if (!this._isAtEnd())
3337
+ var _a2, _b;
3338
+ this._currentLine = (_b = (_a2 = this._peek()) === null || _a2 === void 0 ? void 0 : _a2.line) !== null && _b !== void 0 ? _b : -1;
3339
+ if (!this._isAtEnd()) {
3161
3340
  this._current++;
3341
+ }
3162
3342
  return this._previous();
3163
3343
  }
3164
3344
  _peek() {
@@ -3175,6 +3355,11 @@ void main() {
3175
3355
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
3176
3356
  return type;
3177
3357
  }
3358
+ if (this._match(TokenTypes.keywords.diagnostic)) {
3359
+ const directive = this._diagnostic();
3360
+ this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
3361
+ return directive;
3362
+ }
3178
3363
  if (this._match(TokenTypes.keywords.enable)) {
3179
3364
  const enable = this._enable_directive();
3180
3365
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'");
@@ -3183,56 +3368,65 @@ void main() {
3183
3368
  const attrs = this._attribute();
3184
3369
  if (this._check(TokenTypes.keywords.var)) {
3185
3370
  const _var = this._global_variable_decl();
3186
- if (_var != null)
3371
+ if (_var != null) {
3187
3372
  _var.attributes = attrs;
3373
+ }
3188
3374
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
3189
3375
  return _var;
3190
3376
  }
3191
3377
  if (this._check(TokenTypes.keywords.override)) {
3192
3378
  const _override = this._override_variable_decl();
3193
- if (_override != null)
3379
+ if (_override != null) {
3194
3380
  _override.attributes = attrs;
3381
+ }
3195
3382
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
3196
3383
  return _override;
3197
3384
  }
3198
3385
  if (this._check(TokenTypes.keywords.let)) {
3199
3386
  const _let = this._global_let_decl();
3200
- if (_let != null)
3387
+ if (_let != null) {
3201
3388
  _let.attributes = attrs;
3389
+ }
3202
3390
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
3203
3391
  return _let;
3204
3392
  }
3205
3393
  if (this._check(TokenTypes.keywords.const)) {
3206
3394
  const _const = this._global_const_decl();
3207
- if (_const != null)
3395
+ if (_const != null) {
3208
3396
  _const.attributes = attrs;
3397
+ }
3209
3398
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
3210
3399
  return _const;
3211
3400
  }
3212
3401
  if (this._check(TokenTypes.keywords.struct)) {
3213
3402
  const _struct = this._struct_decl();
3214
- if (_struct != null)
3403
+ if (_struct != null) {
3215
3404
  _struct.attributes = attrs;
3405
+ }
3216
3406
  return _struct;
3217
3407
  }
3218
3408
  if (this._check(TokenTypes.keywords.fn)) {
3219
3409
  const _fn = this._function_decl();
3220
- if (_fn != null)
3410
+ if (_fn != null) {
3221
3411
  _fn.attributes = attrs;
3412
+ }
3222
3413
  return _fn;
3223
3414
  }
3224
3415
  return null;
3225
3416
  }
3226
3417
  _function_decl() {
3227
- if (!this._match(TokenTypes.keywords.fn))
3418
+ if (!this._match(TokenTypes.keywords.fn)) {
3228
3419
  return null;
3420
+ }
3421
+ const startLine = this._currentLine;
3229
3422
  const name = this._consume(TokenTypes.tokens.ident, "Expected function name.").toString();
3230
3423
  this._consume(TokenTypes.tokens.paren_left, "Expected '(' for function arguments.");
3231
3424
  const args = [];
3232
3425
  if (!this._check(TokenTypes.tokens.paren_right)) {
3233
3426
  do {
3234
- if (this._check(TokenTypes.tokens.paren_right))
3427
+ if (this._check(TokenTypes.tokens.paren_right)) {
3235
3428
  break;
3429
+ }
3236
3430
  const argAttrs = this._attribute();
3237
3431
  const name2 = this._consume(TokenTypes.tokens.ident, "Expected argument name.").toString();
3238
3432
  this._consume(TokenTypes.tokens.colon, "Expected ':' for argument type.");
@@ -3249,19 +3443,22 @@ void main() {
3249
3443
  if (this._match(TokenTypes.tokens.arrow)) {
3250
3444
  const attrs = this._attribute();
3251
3445
  _return = this._type_decl();
3252
- if (_return != null)
3446
+ if (_return != null) {
3253
3447
  _return.attributes = attrs;
3448
+ }
3254
3449
  }
3255
3450
  const body = this._compound_statement();
3256
- return new Function(name, args, _return, body);
3451
+ const endLine = this._currentLine;
3452
+ return new Function(name, args, _return, body, startLine, endLine);
3257
3453
  }
3258
3454
  _compound_statement() {
3259
3455
  const statements = [];
3260
3456
  this._consume(TokenTypes.tokens.brace_left, "Expected '{' for block.");
3261
3457
  while (!this._check(TokenTypes.tokens.brace_right)) {
3262
3458
  const statement = this._statement();
3263
- if (statement !== null)
3459
+ if (statement !== null) {
3264
3460
  statements.push(statement);
3461
+ }
3265
3462
  }
3266
3463
  this._consume(TokenTypes.tokens.brace_right, "Expected '}' for block.");
3267
3464
  return statements;
@@ -3269,65 +3466,79 @@ void main() {
3269
3466
  _statement() {
3270
3467
  while (this._match(TokenTypes.tokens.semicolon) && !this._isAtEnd())
3271
3468
  ;
3272
- if (this._check(TokenTypes.keywords.if))
3469
+ if (this._check(TokenTypes.keywords.if)) {
3273
3470
  return this._if_statement();
3274
- if (this._check(TokenTypes.keywords.switch))
3471
+ }
3472
+ if (this._check(TokenTypes.keywords.switch)) {
3275
3473
  return this._switch_statement();
3276
- if (this._check(TokenTypes.keywords.loop))
3474
+ }
3475
+ if (this._check(TokenTypes.keywords.loop)) {
3277
3476
  return this._loop_statement();
3278
- if (this._check(TokenTypes.keywords.for))
3477
+ }
3478
+ if (this._check(TokenTypes.keywords.for)) {
3279
3479
  return this._for_statement();
3280
- if (this._check(TokenTypes.keywords.while))
3480
+ }
3481
+ if (this._check(TokenTypes.keywords.while)) {
3281
3482
  return this._while_statement();
3282
- if (this._check(TokenTypes.keywords.continuing))
3483
+ }
3484
+ if (this._check(TokenTypes.keywords.continuing)) {
3283
3485
  return this._continuing_statement();
3284
- if (this._check(TokenTypes.keywords.static_assert))
3486
+ }
3487
+ if (this._check(TokenTypes.keywords.static_assert)) {
3285
3488
  return this._static_assert_statement();
3286
- if (this._check(TokenTypes.tokens.brace_left))
3489
+ }
3490
+ if (this._check(TokenTypes.tokens.brace_left)) {
3287
3491
  return this._compound_statement();
3492
+ }
3288
3493
  let result = null;
3289
- if (this._check(TokenTypes.keywords.return))
3494
+ if (this._check(TokenTypes.keywords.return)) {
3290
3495
  result = this._return_statement();
3291
- else if (this._check([
3496
+ } else if (this._check([
3292
3497
  TokenTypes.keywords.var,
3293
3498
  TokenTypes.keywords.let,
3294
3499
  TokenTypes.keywords.const
3295
- ]))
3500
+ ])) {
3296
3501
  result = this._variable_statement();
3297
- else if (this._match(TokenTypes.keywords.discard))
3502
+ } else if (this._match(TokenTypes.keywords.discard)) {
3298
3503
  result = new Discard();
3299
- else if (this._match(TokenTypes.keywords.break))
3504
+ } else if (this._match(TokenTypes.keywords.break)) {
3300
3505
  result = new Break();
3301
- else if (this._match(TokenTypes.keywords.continue))
3506
+ } else if (this._match(TokenTypes.keywords.continue)) {
3302
3507
  result = new Continue();
3303
- else
3508
+ } else {
3304
3509
  result = this._increment_decrement_statement() || this._func_call_statement() || this._assignment_statement();
3305
- if (result != null)
3510
+ }
3511
+ if (result != null) {
3306
3512
  this._consume(TokenTypes.tokens.semicolon, "Expected ';' after statement.");
3513
+ }
3307
3514
  return result;
3308
3515
  }
3309
3516
  _static_assert_statement() {
3310
- if (!this._match(TokenTypes.keywords.static_assert))
3517
+ if (!this._match(TokenTypes.keywords.static_assert)) {
3311
3518
  return null;
3312
- let expression = this._optional_paren_expression();
3519
+ }
3520
+ const expression = this._optional_paren_expression();
3313
3521
  return new StaticAssert(expression);
3314
3522
  }
3315
3523
  _while_statement() {
3316
- if (!this._match(TokenTypes.keywords.while))
3524
+ if (!this._match(TokenTypes.keywords.while)) {
3317
3525
  return null;
3318
- let condition = this._optional_paren_expression();
3526
+ }
3527
+ const condition = this._optional_paren_expression();
3319
3528
  const block = this._compound_statement();
3320
3529
  return new While(condition, block);
3321
3530
  }
3322
3531
  _continuing_statement() {
3323
- if (!this._match(TokenTypes.keywords.continuing))
3532
+ if (!this._match(TokenTypes.keywords.continuing)) {
3324
3533
  return null;
3534
+ }
3325
3535
  const block = this._compound_statement();
3326
3536
  return new Continuing(block);
3327
3537
  }
3328
3538
  _for_statement() {
3329
- if (!this._match(TokenTypes.keywords.for))
3539
+ if (!this._match(TokenTypes.keywords.for)) {
3330
3540
  return null;
3541
+ }
3331
3542
  this._consume(TokenTypes.tokens.paren_left, "Expected '('.");
3332
3543
  const init = !this._check(TokenTypes.tokens.semicolon) ? this._for_init() : null;
3333
3544
  this._consume(TokenTypes.tokens.semicolon, "Expected ';'.");
@@ -3347,11 +3558,13 @@ void main() {
3347
3558
  _variable_statement() {
3348
3559
  if (this._check(TokenTypes.keywords.var)) {
3349
3560
  const _var = this._variable_decl();
3350
- if (_var === null)
3561
+ if (_var === null) {
3351
3562
  throw this._error(this._peek(), "Variable declaration expected.");
3563
+ }
3352
3564
  let value = null;
3353
- if (this._match(TokenTypes.tokens.equal))
3565
+ if (this._match(TokenTypes.tokens.equal)) {
3354
3566
  value = this._short_circuit_or_expression();
3567
+ }
3355
3568
  return new Var(_var.name, _var.type, _var.storage, _var.access, value);
3356
3569
  }
3357
3570
  if (this._match(TokenTypes.keywords.let)) {
@@ -3360,8 +3573,9 @@ void main() {
3360
3573
  if (this._match(TokenTypes.tokens.colon)) {
3361
3574
  const typeAttrs = this._attribute();
3362
3575
  type = this._type_decl();
3363
- if (type != null)
3576
+ if (type != null) {
3364
3577
  type.attributes = typeAttrs;
3578
+ }
3365
3579
  }
3366
3580
  this._consume(TokenTypes.tokens.equal, "Expected '=' for let.");
3367
3581
  const value = this._short_circuit_or_expression();
@@ -3373,8 +3587,9 @@ void main() {
3373
3587
  if (this._match(TokenTypes.tokens.colon)) {
3374
3588
  const typeAttrs = this._attribute();
3375
3589
  type = this._type_decl();
3376
- if (type != null)
3590
+ if (type != null) {
3377
3591
  type.attributes = typeAttrs;
3592
+ }
3378
3593
  }
3379
3594
  this._consume(TokenTypes.tokens.equal, "Expected '=' for const.");
3380
3595
  const value = this._short_circuit_or_expression();
@@ -3385,8 +3600,9 @@ void main() {
3385
3600
  _increment_decrement_statement() {
3386
3601
  const savedPos = this._current;
3387
3602
  const _var = this._unary_expression();
3388
- if (_var == null)
3603
+ if (_var == null) {
3389
3604
  return null;
3605
+ }
3390
3606
  if (!this._check(TokenTypes.increment_operators)) {
3391
3607
  this._current = savedPos;
3392
3608
  return null;
@@ -3396,20 +3612,24 @@ void main() {
3396
3612
  }
3397
3613
  _assignment_statement() {
3398
3614
  let _var = null;
3399
- if (this._check(TokenTypes.tokens.brace_right))
3615
+ if (this._check(TokenTypes.tokens.brace_right)) {
3400
3616
  return null;
3617
+ }
3401
3618
  let isUnderscore = this._match(TokenTypes.tokens.underscore);
3402
- if (!isUnderscore)
3619
+ if (!isUnderscore) {
3403
3620
  _var = this._unary_expression();
3404
- if (!isUnderscore && _var == null)
3621
+ }
3622
+ if (!isUnderscore && _var == null) {
3405
3623
  return null;
3624
+ }
3406
3625
  const type = this._consume(TokenTypes.assignment_operators, "Expected assignment operator.");
3407
3626
  const value = this._short_circuit_or_expression();
3408
3627
  return new Assign(AssignOperator.parse(type.lexeme), _var, value);
3409
3628
  }
3410
3629
  _func_call_statement() {
3411
- if (!this._check(TokenTypes.tokens.ident))
3630
+ if (!this._check(TokenTypes.tokens.ident)) {
3412
3631
  return null;
3632
+ }
3413
3633
  const savedPos = this._current;
3414
3634
  const name = this._consume(TokenTypes.tokens.ident, "Expected function name.");
3415
3635
  const args = this._argument_expression_list();
@@ -3420,8 +3640,9 @@ void main() {
3420
3640
  return new Call(name.lexeme, args);
3421
3641
  }
3422
3642
  _loop_statement() {
3423
- if (!this._match(TokenTypes.keywords.loop))
3643
+ if (!this._match(TokenTypes.keywords.loop)) {
3424
3644
  return null;
3645
+ }
3425
3646
  this._consume(TokenTypes.tokens.brace_left, "Expected '{' for loop.");
3426
3647
  const statements = [];
3427
3648
  let statement = this._statement();
@@ -3436,19 +3657,22 @@ void main() {
3436
3657
  statement = this._statement();
3437
3658
  }
3438
3659
  let continuing = null;
3439
- if (this._match(TokenTypes.keywords.continuing))
3660
+ if (this._match(TokenTypes.keywords.continuing)) {
3440
3661
  continuing = this._compound_statement();
3662
+ }
3441
3663
  this._consume(TokenTypes.tokens.brace_right, "Expected '}' for loop.");
3442
3664
  return new Loop(statements, continuing);
3443
3665
  }
3444
3666
  _switch_statement() {
3445
- if (!this._match(TokenTypes.keywords.switch))
3667
+ if (!this._match(TokenTypes.keywords.switch)) {
3446
3668
  return null;
3669
+ }
3447
3670
  const condition = this._optional_paren_expression();
3448
3671
  this._consume(TokenTypes.tokens.brace_left, "Expected '{' for switch.");
3449
3672
  const body = this._switch_body();
3450
- if (body == null || body.length == 0)
3673
+ if (body == null || body.length == 0) {
3451
3674
  throw this._error(this._previous(), "Expected 'case' or 'default'.");
3675
+ }
3452
3676
  this._consume(TokenTypes.tokens.brace_right, "Expected '}' for switch.");
3453
3677
  return new Switch(condition, body);
3454
3678
  }
@@ -3476,12 +3700,12 @@ void main() {
3476
3700
  return cases;
3477
3701
  }
3478
3702
  _case_selectors() {
3479
- var _a2, _b, _c, _d;
3480
3703
  const selectors = [
3481
- (_b = (_a2 = this._shift_expression()) === null || _a2 === void 0 ? void 0 : _a2.evaluate(this._context).toString()) !== null && _b !== void 0 ? _b : ""
3704
+ this._shift_expression()
3705
+ //?.evaluate(this._context).toString() ?? "",
3482
3706
  ];
3483
3707
  while (this._match(TokenTypes.tokens.comma)) {
3484
- selectors.push((_d = (_c = this._shift_expression()) === null || _c === void 0 ? void 0 : _c.evaluate(this._context).toString()) !== null && _d !== void 0 ? _d : "");
3708
+ selectors.push(this._shift_expression());
3485
3709
  }
3486
3710
  return selectors;
3487
3711
  }
@@ -3491,19 +3715,22 @@ void main() {
3491
3715
  return [];
3492
3716
  }
3493
3717
  let statement = this._statement();
3494
- if (statement == null)
3718
+ if (statement == null) {
3495
3719
  return [];
3720
+ }
3496
3721
  if (!(statement instanceof Array)) {
3497
3722
  statement = [statement];
3498
3723
  }
3499
3724
  const nextStatement = this._case_body();
3500
- if (nextStatement.length == 0)
3725
+ if (nextStatement.length == 0) {
3501
3726
  return statement;
3727
+ }
3502
3728
  return [...statement, nextStatement[0]];
3503
3729
  }
3504
3730
  _if_statement() {
3505
- if (!this._match(TokenTypes.keywords.if))
3731
+ if (!this._match(TokenTypes.keywords.if)) {
3506
3732
  return null;
3733
+ }
3507
3734
  const condition = this._optional_paren_expression();
3508
3735
  const block = this._compound_statement();
3509
3736
  let elseif = [];
@@ -3511,8 +3738,9 @@ void main() {
3511
3738
  elseif = this._elseif_statement(elseif);
3512
3739
  }
3513
3740
  let _else = null;
3514
- if (this._match(TokenTypes.keywords.else))
3741
+ if (this._match(TokenTypes.keywords.else)) {
3515
3742
  _else = this._compound_statement();
3743
+ }
3516
3744
  return new If(condition, block, elseif, _else);
3517
3745
  }
3518
3746
  _match_elseif() {
@@ -3533,8 +3761,9 @@ void main() {
3533
3761
  return elseif;
3534
3762
  }
3535
3763
  _return_statement() {
3536
- if (!this._match(TokenTypes.keywords.return))
3764
+ if (!this._match(TokenTypes.keywords.return)) {
3537
3765
  return null;
3766
+ }
3538
3767
  const value = this._short_circuit_or_expression();
3539
3768
  return new Return(value);
3540
3769
  }
@@ -3701,12 +3930,14 @@ void main() {
3701
3930
  return new TypecastExpr(type, args);
3702
3931
  }
3703
3932
  _argument_expression_list() {
3704
- if (!this._match(TokenTypes.tokens.paren_left))
3933
+ if (!this._match(TokenTypes.tokens.paren_left)) {
3705
3934
  return null;
3935
+ }
3706
3936
  const args = [];
3707
3937
  do {
3708
- if (this._check(TokenTypes.tokens.paren_right))
3938
+ if (this._check(TokenTypes.tokens.paren_right)) {
3709
3939
  break;
3940
+ }
3710
3941
  const arg = this._short_circuit_or_expression();
3711
3942
  args.push(arg);
3712
3943
  } while (this._match(TokenTypes.tokens.comma));
@@ -3726,8 +3957,10 @@ void main() {
3726
3957
  return new GroupingExpr([expr]);
3727
3958
  }
3728
3959
  _struct_decl() {
3729
- if (!this._match(TokenTypes.keywords.struct))
3960
+ if (!this._match(TokenTypes.keywords.struct)) {
3730
3961
  return null;
3962
+ }
3963
+ const startLine = this._currentLine;
3731
3964
  const name = this._consume(TokenTypes.tokens.ident, "Expected name for struct.").toString();
3732
3965
  this._consume(TokenTypes.tokens.brace_left, "Expected '{' for struct body.");
3733
3966
  const members = [];
@@ -3737,8 +3970,9 @@ void main() {
3737
3970
  this._consume(TokenTypes.tokens.colon, "Expected ':' for struct member type.");
3738
3971
  const typeAttrs = this._attribute();
3739
3972
  const memberType = this._type_decl();
3740
- if (memberType != null)
3973
+ if (memberType != null) {
3741
3974
  memberType.attributes = typeAttrs;
3975
+ }
3742
3976
  if (!this._check(TokenTypes.tokens.brace_right))
3743
3977
  this._consume(TokenTypes.tokens.comma, "Expected ',' for struct member.");
3744
3978
  else
@@ -3746,32 +3980,37 @@ void main() {
3746
3980
  members.push(new Member(memberName, memberType, memberAttrs));
3747
3981
  }
3748
3982
  this._consume(TokenTypes.tokens.brace_right, "Expected '}' after struct body.");
3749
- const structNode = new Struct(name, members);
3983
+ const endLine = this._currentLine;
3984
+ const structNode = new Struct(name, members, startLine, endLine);
3750
3985
  this._context.structs.set(name, structNode);
3751
3986
  return structNode;
3752
3987
  }
3753
3988
  _global_variable_decl() {
3754
3989
  const _var = this._variable_decl();
3755
- if (_var && this._match(TokenTypes.tokens.equal))
3990
+ if (_var && this._match(TokenTypes.tokens.equal)) {
3756
3991
  _var.value = this._const_expression();
3992
+ }
3757
3993
  return _var;
3758
3994
  }
3759
3995
  _override_variable_decl() {
3760
3996
  const _override = this._override_decl();
3761
- if (_override && this._match(TokenTypes.tokens.equal))
3997
+ if (_override && this._match(TokenTypes.tokens.equal)) {
3762
3998
  _override.value = this._const_expression();
3999
+ }
3763
4000
  return _override;
3764
4001
  }
3765
4002
  _global_const_decl() {
3766
- if (!this._match(TokenTypes.keywords.const))
4003
+ if (!this._match(TokenTypes.keywords.const)) {
3767
4004
  return null;
4005
+ }
3768
4006
  const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
3769
4007
  let type = null;
3770
4008
  if (this._match(TokenTypes.tokens.colon)) {
3771
4009
  const attrs = this._attribute();
3772
4010
  type = this._type_decl();
3773
- if (type != null)
4011
+ if (type != null) {
3774
4012
  type.attributes = attrs;
4013
+ }
3775
4014
  }
3776
4015
  let value = null;
3777
4016
  if (this._match(TokenTypes.tokens.equal)) {
@@ -3794,15 +4033,17 @@ void main() {
3794
4033
  return c;
3795
4034
  }
3796
4035
  _global_let_decl() {
3797
- if (!this._match(TokenTypes.keywords.let))
4036
+ if (!this._match(TokenTypes.keywords.let)) {
3798
4037
  return null;
4038
+ }
3799
4039
  const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
3800
4040
  let type = null;
3801
4041
  if (this._match(TokenTypes.tokens.colon)) {
3802
4042
  const attrs = this._attribute();
3803
4043
  type = this._type_decl();
3804
- if (type != null)
4044
+ if (type != null) {
3805
4045
  type.attributes = attrs;
4046
+ }
3806
4047
  }
3807
4048
  let value = null;
3808
4049
  if (this._match(TokenTypes.tokens.equal)) {
@@ -3811,23 +4052,26 @@ void main() {
3811
4052
  return new Let(name.toString(), type, "", "", value);
3812
4053
  }
3813
4054
  _const_expression() {
3814
- if (this._match(TokenTypes.const_literal))
4055
+ if (this._match(TokenTypes.const_literal)) {
3815
4056
  return new StringExpr(this._previous().toString());
4057
+ }
3816
4058
  const type = this._type_decl();
3817
4059
  this._consume(TokenTypes.tokens.paren_left, "Expected '('.");
3818
4060
  let args = [];
3819
4061
  while (!this._check(TokenTypes.tokens.paren_right)) {
3820
4062
  args.push(this._const_expression());
3821
- if (!this._check(TokenTypes.tokens.comma))
4063
+ if (!this._check(TokenTypes.tokens.comma)) {
3822
4064
  break;
4065
+ }
3823
4066
  this._advance();
3824
4067
  }
3825
4068
  this._consume(TokenTypes.tokens.paren_right, "Expected ')'.");
3826
4069
  return new CreateExpr(type, args);
3827
4070
  }
3828
4071
  _variable_decl() {
3829
- if (!this._match(TokenTypes.keywords.var))
4072
+ if (!this._match(TokenTypes.keywords.var)) {
3830
4073
  return null;
4074
+ }
3831
4075
  let storage = "";
3832
4076
  let access = "";
3833
4077
  if (this._match(TokenTypes.tokens.less_than)) {
@@ -3841,24 +4085,35 @@ void main() {
3841
4085
  if (this._match(TokenTypes.tokens.colon)) {
3842
4086
  const attrs = this._attribute();
3843
4087
  type = this._type_decl();
3844
- if (type != null)
4088
+ if (type != null) {
3845
4089
  type.attributes = attrs;
4090
+ }
3846
4091
  }
3847
4092
  return new Var(name.toString(), type, storage, access, null);
3848
4093
  }
3849
4094
  _override_decl() {
3850
- if (!this._match(TokenTypes.keywords.override))
4095
+ if (!this._match(TokenTypes.keywords.override)) {
3851
4096
  return null;
4097
+ }
3852
4098
  const name = this._consume(TokenTypes.tokens.ident, "Expected variable name");
3853
4099
  let type = null;
3854
4100
  if (this._match(TokenTypes.tokens.colon)) {
3855
4101
  const attrs = this._attribute();
3856
4102
  type = this._type_decl();
3857
- if (type != null)
4103
+ if (type != null) {
3858
4104
  type.attributes = attrs;
4105
+ }
3859
4106
  }
3860
4107
  return new Override(name.toString(), type, null);
3861
4108
  }
4109
+ _diagnostic() {
4110
+ this._consume(TokenTypes.tokens.paren_left, "Expected '('");
4111
+ const severity = this._consume(TokenTypes.tokens.ident, "Expected severity control name.");
4112
+ this._consume(TokenTypes.tokens.comma, "Expected ','");
4113
+ const rule = this._consume(TokenTypes.tokens.ident, "Expected diagnostic rule name.");
4114
+ this._consume(TokenTypes.tokens.paren_right, "Expected ')'");
4115
+ return new Diagnostic(severity.toString(), rule.toString());
4116
+ }
3862
4117
  _enable_directive() {
3863
4118
  const name = this._consume(TokenTypes.tokens.ident, "identity expected.");
3864
4119
  return new Enable(name.toString());
@@ -3897,8 +4152,9 @@ void main() {
3897
4152
  return new Type(type2.toString());
3898
4153
  }
3899
4154
  let type = this._texture_sampler_types();
3900
- if (type)
4155
+ if (type) {
3901
4156
  return type;
4157
+ }
3902
4158
  if (this._check(TokenTypes.template_types)) {
3903
4159
  let type2 = this._advance().toString();
3904
4160
  let format = null;
@@ -3906,8 +4162,9 @@ void main() {
3906
4162
  if (this._match(TokenTypes.tokens.less_than)) {
3907
4163
  format = this._type_decl();
3908
4164
  access = null;
3909
- if (this._match(TokenTypes.tokens.comma))
4165
+ if (this._match(TokenTypes.tokens.comma)) {
3910
4166
  access = this._consume(TokenTypes.access_mode, "Expected access_mode for pointer").toString();
4167
+ }
3911
4168
  this._consume(TokenTypes.tokens.greater_than, "Expected '>' for type.");
3912
4169
  }
3913
4170
  return new TemplateType(type2, format, access);
@@ -3919,8 +4176,9 @@ void main() {
3919
4176
  this._consume(TokenTypes.tokens.comma, "Expected ',' for pointer.");
3920
4177
  const decl = this._type_decl();
3921
4178
  let access = null;
3922
- if (this._match(TokenTypes.tokens.comma))
4179
+ if (this._match(TokenTypes.tokens.comma)) {
3923
4180
  access = this._consume(TokenTypes.access_mode, "Expected access_mode for pointer").toString();
4181
+ }
3924
4182
  this._consume(TokenTypes.tokens.greater_than, "Expected '>' for pointer.");
3925
4183
  return new PointerType(pointer, storage.toString(), decl, access);
3926
4184
  }
@@ -3929,6 +4187,7 @@ void main() {
3929
4187
  let format = null;
3930
4188
  let countInt = -1;
3931
4189
  const array = this._previous();
4190
+ let countNode = null;
3932
4191
  if (this._match(TokenTypes.tokens.less_than)) {
3933
4192
  format = this._type_decl();
3934
4193
  if (this._context.aliases.has(format.name)) {
@@ -3936,21 +4195,32 @@ void main() {
3936
4195
  }
3937
4196
  let count = "";
3938
4197
  if (this._match(TokenTypes.tokens.comma)) {
3939
- let c = this._shift_expression();
3940
- count = c.evaluate(this._context).toString();
4198
+ countNode = this._shift_expression();
4199
+ try {
4200
+ count = countNode.evaluate(this._context).toString();
4201
+ countNode = null;
4202
+ } catch (e) {
4203
+ count = "1";
4204
+ }
3941
4205
  }
3942
4206
  this._consume(TokenTypes.tokens.greater_than, "Expected '>' for array.");
3943
4207
  countInt = count ? parseInt(count) : 0;
3944
4208
  }
3945
- return new ArrayType(array.toString(), attrs, format, countInt);
4209
+ const arrayType = new ArrayType(array.toString(), attrs, format, countInt);
4210
+ if (countNode) {
4211
+ this._deferArrayCountEval.push({ arrayType, countNode });
4212
+ }
4213
+ return arrayType;
3946
4214
  }
3947
4215
  return null;
3948
4216
  }
3949
4217
  _texture_sampler_types() {
3950
- if (this._match(TokenTypes.sampler_type))
4218
+ if (this._match(TokenTypes.sampler_type)) {
3951
4219
  return new SamplerType(this._previous().toString(), null, null);
3952
- if (this._match(TokenTypes.depth_texture_type))
4220
+ }
4221
+ if (this._match(TokenTypes.depth_texture_type)) {
3953
4222
  return new SamplerType(this._previous().toString(), null, null);
4223
+ }
3954
4224
  if (this._match(TokenTypes.sampled_texture_type) || this._match(TokenTypes.multisampled_texture_type)) {
3955
4225
  const sampler = this._previous();
3956
4226
  this._consume(TokenTypes.tokens.less_than, "Expected '<' for sampler type.");
@@ -4013,8 +4283,9 @@ void main() {
4013
4283
  }
4014
4284
  this._consume(TokenTypes.tokens.attr_right, "Expected ']]' after attribute declarations");
4015
4285
  }
4016
- if (attributes.length == 0)
4286
+ if (attributes.length == 0) {
4017
4287
  return null;
4288
+ }
4018
4289
  return attributes;
4019
4290
  }
4020
4291
  };
@@ -4072,6 +4343,9 @@ void main() {
4072
4343
  super(name, attributes);
4073
4344
  this.members = [];
4074
4345
  this.align = 0;
4346
+ this.startLine = -1;
4347
+ this.endLine = -1;
4348
+ this.inUse = false;
4075
4349
  }
4076
4350
  get isStruct() {
4077
4351
  return true;
@@ -4177,6 +4451,11 @@ void main() {
4177
4451
  this.stage = null;
4178
4452
  this.inputs = [];
4179
4453
  this.outputs = [];
4454
+ this.resources = [];
4455
+ this.startLine = -1;
4456
+ this.endLine = -1;
4457
+ this.inUse = false;
4458
+ this.calls = /* @__PURE__ */ new Set();
4180
4459
  this.name = name;
4181
4460
  this.stage = stage;
4182
4461
  }
@@ -4196,6 +4475,14 @@ void main() {
4196
4475
  this.id = id;
4197
4476
  }
4198
4477
  };
4478
+ var _FunctionResources = class {
4479
+ constructor(node) {
4480
+ this.resources = null;
4481
+ this.inUse = false;
4482
+ this.info = null;
4483
+ this.node = node;
4484
+ }
4485
+ };
4199
4486
  var WgslReflect = class {
4200
4487
  constructor(code) {
4201
4488
  this.uniforms = [];
@@ -4206,7 +4493,9 @@ void main() {
4206
4493
  this.overrides = [];
4207
4494
  this.structs = [];
4208
4495
  this.entry = new EntryFunctions();
4496
+ this.functions = [];
4209
4497
  this._types = /* @__PURE__ */ new Map();
4498
+ this._functions = /* @__PURE__ */ new Map();
4210
4499
  if (code) {
4211
4500
  this.update(code);
4212
4501
  }
@@ -4217,14 +4506,20 @@ void main() {
4217
4506
  update(code) {
4218
4507
  const parser = new WgslParser();
4219
4508
  const ast = parser.parse(code);
4509
+ for (const node of ast) {
4510
+ if (node instanceof Function) {
4511
+ this._functions.set(node.name, new _FunctionResources(node));
4512
+ }
4513
+ }
4220
4514
  for (const node of ast) {
4221
4515
  if (node instanceof Struct) {
4222
4516
  const info = this._getTypeInfo(node, null);
4223
4517
  if (info instanceof StructInfo) {
4224
4518
  this.structs.push(info);
4225
4519
  }
4226
- continue;
4227
4520
  }
4521
+ }
4522
+ for (const node of ast) {
4228
4523
  if (node instanceof Alias) {
4229
4524
  this.aliases.push(this._getAliasInfo(node));
4230
4525
  continue;
@@ -4283,8 +4578,15 @@ void main() {
4283
4578
  const fragmentStage = this._getAttribute(node, "fragment");
4284
4579
  const computeStage = this._getAttribute(node, "compute");
4285
4580
  const stage = vertexStage || fragmentStage || computeStage;
4581
+ const fn = new FunctionInfo(node.name, stage === null || stage === void 0 ? void 0 : stage.name);
4582
+ fn.startLine = node.startLine;
4583
+ fn.endLine = node.endLine;
4584
+ this.functions.push(fn);
4585
+ this._functions.get(node.name).info = fn;
4286
4586
  if (stage) {
4287
- const fn = new FunctionInfo(node.name, stage.name);
4587
+ this._functions.get(node.name).inUse = true;
4588
+ fn.inUse = true;
4589
+ fn.resources = this._findResources(node, !!stage);
4288
4590
  fn.inputs = this._getInputs(node.args);
4289
4591
  fn.outputs = this._getOutputs(node.returnType);
4290
4592
  this.entry[stage.name].push(fn);
@@ -4292,48 +4594,214 @@ void main() {
4292
4594
  continue;
4293
4595
  }
4294
4596
  }
4597
+ for (const fn of this._functions.values()) {
4598
+ if (fn.info) {
4599
+ fn.info.inUse = fn.inUse;
4600
+ this._addCalls(fn.node, fn.info.calls);
4601
+ }
4602
+ }
4603
+ for (const u of this.uniforms) {
4604
+ this._markStructsInUse(u.type);
4605
+ }
4606
+ for (const s of this.storage) {
4607
+ this._markStructsInUse(s.type);
4608
+ }
4295
4609
  }
4296
- getBindGroups() {
4297
- const groups = [];
4298
- function _makeRoom(group, binding) {
4299
- if (group >= groups.length)
4300
- groups.length = group + 1;
4301
- if (groups[group] === void 0)
4302
- groups[group] = [];
4303
- if (binding >= groups[group].length)
4304
- groups[group].length = binding + 1;
4610
+ _markStructsInUse(type) {
4611
+ if (type.isStruct) {
4612
+ type.inUse = true;
4613
+ for (const m of type.members) {
4614
+ this._markStructsInUse(m.type);
4615
+ }
4616
+ } else if (type.isArray) {
4617
+ this._markStructsInUse(type.format);
4618
+ } else if (type.isTemplate) {
4619
+ this._markStructsInUse(type.format);
4620
+ } else {
4621
+ const alias = this._getAlias(type.name);
4622
+ if (alias) {
4623
+ this._markStructsInUse(alias);
4624
+ }
4625
+ }
4626
+ }
4627
+ _addCalls(fn, calls) {
4628
+ var _a2;
4629
+ for (const call of fn.calls) {
4630
+ const info = (_a2 = this._functions.get(call.name)) === null || _a2 === void 0 ? void 0 : _a2.info;
4631
+ if (info) {
4632
+ calls.add(info);
4633
+ }
4305
4634
  }
4635
+ }
4636
+ /// Find a resource by its group and binding.
4637
+ findResource(group, binding) {
4306
4638
  for (const u of this.uniforms) {
4307
- _makeRoom(u.group, u.binding);
4308
- const group = groups[u.group];
4309
- group[u.binding] = u;
4639
+ if (u.group == group && u.binding == binding) {
4640
+ return u;
4641
+ }
4310
4642
  }
4311
- for (const u of this.storage) {
4312
- _makeRoom(u.group, u.binding);
4313
- const group = groups[u.group];
4314
- group[u.binding] = u;
4643
+ for (const s of this.storage) {
4644
+ if (s.group == group && s.binding == binding) {
4645
+ return s;
4646
+ }
4315
4647
  }
4316
4648
  for (const t of this.textures) {
4317
- _makeRoom(t.group, t.binding);
4318
- const group = groups[t.group];
4319
- group[t.binding] = t;
4649
+ if (t.group == group && t.binding == binding) {
4650
+ return t;
4651
+ }
4320
4652
  }
4321
- for (const t of this.samplers) {
4322
- _makeRoom(t.group, t.binding);
4323
- const group = groups[t.group];
4324
- group[t.binding] = t;
4653
+ for (const s of this.samplers) {
4654
+ if (s.group == group && s.binding == binding) {
4655
+ return s;
4656
+ }
4325
4657
  }
4326
- return groups;
4658
+ return null;
4327
4659
  }
4328
- _getOutputs(type, outputs = void 0) {
4329
- if (outputs === void 0)
4330
- outputs = [];
4660
+ _findResource(name) {
4661
+ for (const u of this.uniforms) {
4662
+ if (u.name == name) {
4663
+ return u;
4664
+ }
4665
+ }
4666
+ for (const s of this.storage) {
4667
+ if (s.name == name) {
4668
+ return s;
4669
+ }
4670
+ }
4671
+ for (const t of this.textures) {
4672
+ if (t.name == name) {
4673
+ return t;
4674
+ }
4675
+ }
4676
+ for (const s of this.samplers) {
4677
+ if (s.name == name) {
4678
+ return s;
4679
+ }
4680
+ }
4681
+ return null;
4682
+ }
4683
+ _markStructsFromAST(type) {
4684
+ const info = this._getTypeInfo(type, null);
4685
+ this._markStructsInUse(info);
4686
+ }
4687
+ _findResources(fn, isEntry) {
4688
+ const resources = [];
4689
+ const self = this;
4690
+ const varStack = [];
4691
+ fn.search((node) => {
4692
+ if (node instanceof _BlockStart) {
4693
+ varStack.push({});
4694
+ } else if (node instanceof _BlockEnd) {
4695
+ varStack.pop();
4696
+ } else if (node instanceof Var) {
4697
+ const v = node;
4698
+ if (isEntry && v.type !== null) {
4699
+ this._markStructsFromAST(v.type);
4700
+ }
4701
+ if (varStack.length > 0) {
4702
+ varStack[varStack.length - 1][v.name] = v;
4703
+ }
4704
+ } else if (node instanceof CreateExpr) {
4705
+ const c = node;
4706
+ if (isEntry && c.type !== null) {
4707
+ this._markStructsFromAST(c.type);
4708
+ }
4709
+ } else if (node instanceof Let) {
4710
+ const v = node;
4711
+ if (isEntry && v.type !== null) {
4712
+ this._markStructsFromAST(v.type);
4713
+ }
4714
+ if (varStack.length > 0) {
4715
+ varStack[varStack.length - 1][v.name] = v;
4716
+ }
4717
+ } else if (node instanceof VariableExpr) {
4718
+ const v = node;
4719
+ if (varStack.length > 0) {
4720
+ const varInfo2 = varStack[varStack.length - 1][v.name];
4721
+ if (varInfo2) {
4722
+ return;
4723
+ }
4724
+ }
4725
+ const varInfo = self._findResource(v.name);
4726
+ if (varInfo) {
4727
+ resources.push(varInfo);
4728
+ }
4729
+ } else if (node instanceof CallExpr) {
4730
+ const c = node;
4731
+ const callFn = self._functions.get(c.name);
4732
+ if (callFn) {
4733
+ if (isEntry) {
4734
+ callFn.inUse = true;
4735
+ }
4736
+ fn.calls.add(callFn.node);
4737
+ if (callFn.resources === null) {
4738
+ callFn.resources = self._findResources(callFn.node, isEntry);
4739
+ }
4740
+ resources.push(...callFn.resources);
4741
+ }
4742
+ } else if (node instanceof Call) {
4743
+ const c = node;
4744
+ const callFn = self._functions.get(c.name);
4745
+ if (callFn) {
4746
+ if (isEntry) {
4747
+ callFn.inUse = true;
4748
+ }
4749
+ fn.calls.add(callFn.node);
4750
+ if (callFn.resources === null) {
4751
+ callFn.resources = self._findResources(callFn.node, isEntry);
4752
+ }
4753
+ resources.push(...callFn.resources);
4754
+ }
4755
+ }
4756
+ });
4757
+ return [...new Map(resources.map((r) => [r.name, r])).values()];
4758
+ }
4759
+ getBindGroups() {
4760
+ const groups = [];
4761
+ function _makeRoom(group, binding) {
4762
+ if (group >= groups.length) {
4763
+ groups.length = group + 1;
4764
+ }
4765
+ if (groups[group] === void 0) {
4766
+ groups[group] = [];
4767
+ }
4768
+ if (binding >= groups[group].length) {
4769
+ groups[group].length = binding + 1;
4770
+ }
4771
+ }
4772
+ for (const u of this.uniforms) {
4773
+ _makeRoom(u.group, u.binding);
4774
+ const group = groups[u.group];
4775
+ group[u.binding] = u;
4776
+ }
4777
+ for (const u of this.storage) {
4778
+ _makeRoom(u.group, u.binding);
4779
+ const group = groups[u.group];
4780
+ group[u.binding] = u;
4781
+ }
4782
+ for (const t of this.textures) {
4783
+ _makeRoom(t.group, t.binding);
4784
+ const group = groups[t.group];
4785
+ group[t.binding] = t;
4786
+ }
4787
+ for (const t of this.samplers) {
4788
+ _makeRoom(t.group, t.binding);
4789
+ const group = groups[t.group];
4790
+ group[t.binding] = t;
4791
+ }
4792
+ return groups;
4793
+ }
4794
+ _getOutputs(type, outputs = void 0) {
4795
+ if (outputs === void 0) {
4796
+ outputs = [];
4797
+ }
4331
4798
  if (type instanceof Struct) {
4332
4799
  this._getStructOutputs(type, outputs);
4333
4800
  } else {
4334
4801
  const output = this._getOutputInfo(type);
4335
- if (output !== null)
4802
+ if (output !== null) {
4336
4803
  outputs.push(output);
4804
+ }
4337
4805
  }
4338
4806
  return outputs;
4339
4807
  }
@@ -4363,15 +4831,17 @@ void main() {
4363
4831
  return null;
4364
4832
  }
4365
4833
  _getInputs(args, inputs = void 0) {
4366
- if (inputs === void 0)
4834
+ if (inputs === void 0) {
4367
4835
  inputs = [];
4836
+ }
4368
4837
  for (const arg of args) {
4369
4838
  if (arg.type instanceof Struct) {
4370
4839
  this._getStructInputs(arg.type, inputs);
4371
4840
  } else {
4372
4841
  const input = this._getInputInfo(arg);
4373
- if (input !== null)
4842
+ if (input !== null) {
4374
4843
  inputs.push(input);
4844
+ }
4375
4845
  }
4376
4846
  }
4377
4847
  return inputs;
@@ -4382,8 +4852,9 @@ void main() {
4382
4852
  this._getStructInputs(m.type, inputs);
4383
4853
  } else {
4384
4854
  const input = this._getInputInfo(m);
4385
- if (input !== null)
4855
+ if (input !== null) {
4386
4856
  inputs.push(input);
4857
+ }
4387
4858
  }
4388
4859
  }
4389
4860
  }
@@ -4416,8 +4887,9 @@ void main() {
4416
4887
  }
4417
4888
  _getAlias(name) {
4418
4889
  for (const a of this.aliases) {
4419
- if (a.name == name)
4890
+ if (a.name == name) {
4420
4891
  return a.type;
4892
+ }
4421
4893
  }
4422
4894
  return null;
4423
4895
  }
@@ -4441,6 +4913,8 @@ void main() {
4441
4913
  if (type instanceof Struct) {
4442
4914
  const s = type;
4443
4915
  const info2 = new StructInfo(s.name, attributes);
4916
+ info2.startLine = s.startLine;
4917
+ info2.endLine = s.endLine;
4444
4918
  for (const m of s.members) {
4445
4919
  const t = this._getTypeInfo(m.type, m.attributes);
4446
4920
  info2.members.push(new MemberInfo(m.name, t, m.attributes));
@@ -4493,8 +4967,9 @@ void main() {
4493
4967
  for (let mi = 0, ml = struct.members.length; mi < ml; ++mi) {
4494
4968
  const member = struct.members[mi];
4495
4969
  const sizeInfo = this._getTypeSize(member);
4496
- if (!sizeInfo)
4970
+ if (!sizeInfo) {
4497
4971
  continue;
4972
+ }
4498
4973
  (_a2 = this._getAlias(member.type.name)) !== null && _a2 !== void 0 ? _a2 : member.type;
4499
4974
  const align = sizeInfo.align;
4500
4975
  const size = sizeInfo.size;
@@ -4511,12 +4986,14 @@ void main() {
4511
4986
  }
4512
4987
  _getTypeSize(type) {
4513
4988
  var _a2;
4514
- if (type === null || type === void 0)
4989
+ if (type === null || type === void 0) {
4515
4990
  return null;
4991
+ }
4516
4992
  const explicitSize = this._getAttributeNum(type.attributes, "size", 0);
4517
4993
  const explicitAlign = this._getAttributeNum(type.attributes, "align", 0);
4518
- if (type instanceof MemberInfo)
4994
+ if (type instanceof MemberInfo) {
4519
4995
  type = type.type;
4996
+ }
4520
4997
  if (type instanceof TypeInfo) {
4521
4998
  const alias = this._getAlias(type.name);
4522
4999
  if (alias !== null) {
@@ -4549,8 +5026,9 @@ void main() {
4549
5026
  const N = arrayType.count;
4550
5027
  const stride = this._getAttributeNum((_a2 = type === null || type === void 0 ? void 0 : type.attributes) !== null && _a2 !== void 0 ? _a2 : null, "stride", this._roundUp(align, size));
4551
5028
  size = N * stride;
4552
- if (explicitSize)
5029
+ if (explicitSize) {
4553
5030
  size = explicitSize;
5031
+ }
4554
5032
  return new _TypeSize(Math.max(explicitAlign, align), Math.max(explicitSize, size));
4555
5033
  }
4556
5034
  if (type instanceof StructInfo) {
@@ -4587,18 +5065,21 @@ void main() {
4587
5065
  }
4588
5066
  _getAttribute(node, name) {
4589
5067
  const obj = node;
4590
- if (!obj || !obj["attributes"])
5068
+ if (!obj || !obj["attributes"]) {
4591
5069
  return null;
5070
+ }
4592
5071
  const attrs = obj["attributes"];
4593
5072
  for (let a of attrs) {
4594
- if (a.name == name)
5073
+ if (a.name == name) {
4595
5074
  return a;
5075
+ }
4596
5076
  }
4597
5077
  return null;
4598
5078
  }
4599
5079
  _getAttributeNum(attributes, name, defaultValue) {
4600
- if (attributes === null)
5080
+ if (attributes === null) {
4601
5081
  return defaultValue;
5082
+ }
4602
5083
  for (let a of attributes) {
4603
5084
  if (a.name == name) {
4604
5085
  let v = a !== null && a.value !== null ? a.value : defaultValue;
@@ -4653,15 +5134,15 @@ void main() {
4653
5134
  try {
4654
5135
  parsedWGSL = parseWGSL(source);
4655
5136
  } catch (error) {
4656
- import_core4.log.error(error.message)();
5137
+ import_core3.log.error(error.message)();
4657
5138
  return shaderLayout;
4658
5139
  }
4659
5140
  for (const uniform of parsedWGSL.uniforms) {
4660
5141
  const members = [];
4661
- for (const member of uniform.type.members) {
5142
+ for (const attribute of uniform.type?.members || []) {
4662
5143
  members.push({
4663
- name: member.name,
4664
- type: getType(member.type)
5144
+ name: attribute.name,
5145
+ type: getType(attribute.type)
4665
5146
  });
4666
5147
  }
4667
5148
  shaderLayout.bindings.push({
@@ -4681,7 +5162,7 @@ void main() {
4681
5162
  const type = getType(wgslAttribute.type);
4682
5163
  shaderLayout.attributes.push({
4683
5164
  name: wgslAttribute.name,
4684
- location: wgslAttribute.location,
5165
+ location: Number(wgslAttribute.location),
4685
5166
  type
4686
5167
  });
4687
5168
  }
@@ -6599,7 +7080,17 @@ void main() {
6599
7080
  }
6600
7081
 
6601
7082
  // src/geometry/gpu-geometry.ts
6602
- var import_core5 = __toESM(require_core(), 1);
7083
+ var import_core4 = __toESM(require_core(), 1);
7084
+
7085
+ // src/utils/uid.ts
7086
+ var uidCounters = {};
7087
+ function uid(id = "id") {
7088
+ uidCounters[id] = uidCounters[id] || 1;
7089
+ const count = uidCounters[id]++;
7090
+ return `${id}-${count}`;
7091
+ }
7092
+
7093
+ // src/geometry/gpu-geometry.ts
6603
7094
  var GPUGeometry = class {
6604
7095
  id;
6605
7096
  userData = {};
@@ -6610,14 +7101,16 @@ void main() {
6610
7101
  indices;
6611
7102
  attributes;
6612
7103
  constructor(props) {
6613
- this.id = props.id || (0, import_core5.uid)("geometry");
7104
+ this.id = props.id || uid("geometry");
6614
7105
  this.topology = props.topology;
6615
7106
  this.indices = props.indices || null;
6616
7107
  this.attributes = props.attributes;
6617
7108
  this.vertexCount = props.vertexCount;
6618
7109
  this.bufferLayout = props.bufferLayout || [];
6619
7110
  if (this.indices) {
6620
- (0, import_core5.assert)(this.indices.usage === import_core5.Buffer.INDEX);
7111
+ if (!(this.indices.usage & import_core4.Buffer.INDEX)) {
7112
+ throw new Error("Index buffer must have INDEX usage");
7113
+ }
6621
7114
  }
6622
7115
  }
6623
7116
  destroy() {
@@ -6633,7 +7126,7 @@ void main() {
6633
7126
  return this.attributes;
6634
7127
  }
6635
7128
  getIndexes() {
6636
- return this.indices;
7129
+ return this.indices || null;
6637
7130
  }
6638
7131
  _calculateVertexCount(positions) {
6639
7132
  const vertexCount = positions.byteLength / 12;
@@ -6659,7 +7152,7 @@ void main() {
6659
7152
  return void 0;
6660
7153
  }
6661
7154
  const data = geometry.indices.value;
6662
- return device.createBuffer({ usage: import_core5.Buffer.INDEX, data });
7155
+ return device.createBuffer({ usage: import_core4.Buffer.INDEX, data });
6663
7156
  }
6664
7157
  function getAttributeBuffersFromGeometry(device, geometry) {
6665
7158
  const bufferLayout = [];
@@ -6680,124 +7173,40 @@ void main() {
6680
7173
  name = "colors";
6681
7174
  break;
6682
7175
  }
6683
- attributes[name] = device.createBuffer({ data: attribute.value, id: `${attributeName}-buffer` });
6684
- const { value, size, normalized } = attribute;
6685
- bufferLayout.push({ name, format: (0, import_core5.getVertexFormatFromAttribute)(value, size, normalized) });
7176
+ if (attribute) {
7177
+ attributes[name] = device.createBuffer({
7178
+ data: attribute.value,
7179
+ id: `${attributeName}-buffer`
7180
+ });
7181
+ const { value, size, normalized } = attribute;
7182
+ bufferLayout.push({ name, format: (0, import_core4.getVertexFormatFromAttribute)(value, size, normalized) });
7183
+ }
6686
7184
  }
6687
7185
  const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
6688
7186
  return { attributes, bufferLayout, vertexCount };
6689
7187
  }
6690
7188
 
6691
- // src/shader-inputs.ts
6692
- var import_core6 = __toESM(require_core(), 1);
6693
- var ShaderInputs = class {
6694
- /**
6695
- * The map of modules
6696
- * @todo should should this include the resolved dependencies?
6697
- */
6698
- modules;
6699
- /** Stores the uniform values for each module */
6700
- moduleUniforms;
6701
- /** Stores the uniform bindings for each module */
6702
- moduleBindings;
6703
- /** Tracks if uniforms have changed */
6704
- moduleUniformsChanged;
6705
- /**
6706
- * Create a new UniformStore instance
6707
- * @param modules
6708
- */
6709
- constructor(modules) {
6710
- const allModules = resolveModules(Object.values(modules));
6711
- import_core6.log.log(
6712
- 1,
6713
- "Creating ShaderInputs with modules",
6714
- allModules.map((m) => m.name)
6715
- )();
6716
- this.modules = modules;
6717
- this.moduleUniforms = {};
6718
- this.moduleBindings = {};
6719
- for (const [name, module] of Object.entries(modules)) {
6720
- const moduleName = name;
6721
- this.moduleUniforms[moduleName] = module.defaultUniforms || {};
6722
- this.moduleBindings[moduleName] = {};
6723
- }
6724
- }
6725
- /** Destroy */
6726
- destroy() {
6727
- }
6728
- /**
6729
- * Set module props
6730
- */
6731
- setProps(props) {
6732
- for (const name of Object.keys(props)) {
6733
- const moduleName = name;
6734
- const moduleProps = props[moduleName];
6735
- const module = this.modules[moduleName];
6736
- if (!module) {
6737
- import_core6.log.warn(`Module ${name} not found`)();
6738
- continue;
6739
- }
6740
- const oldUniforms = this.moduleUniforms[moduleName];
6741
- const uniforms = module.getUniforms?.(moduleProps, this.moduleUniforms[moduleName]) || moduleProps;
6742
- this.moduleUniforms[moduleName] = { ...oldUniforms, ...uniforms };
6743
- }
6744
- }
6745
- /** Merges all bindings for the shader (from the various modules) */
6746
- // getUniformBlocks(): Record<string, Texture | Sampler> {
6747
- // return this.moduleUniforms;
6748
- // }
6749
- /**
6750
- * Return the map of modules
6751
- * @todo should should this include the resolved dependencies?
6752
- */
6753
- getModules() {
6754
- return Object.values(this.modules);
6755
- }
6756
- /** Get all uniform values for all modules */
6757
- getUniformValues() {
6758
- return this.moduleUniforms;
6759
- }
6760
- /** Merges all bindings for the shader (from the various modules) */
6761
- getBindings() {
6762
- const bindings = {};
6763
- for (const moduleBindings of Object.values(this.moduleBindings)) {
6764
- Object.assign(bindings, moduleBindings);
6765
- }
6766
- return bindings;
6767
- }
6768
- getDebugTable() {
6769
- const table = {};
6770
- for (const [moduleName, module] of Object.entries(this.moduleUniforms)) {
6771
- for (const [key, value] of Object.entries(module)) {
6772
- table[`${moduleName}.${key}`] = {
6773
- type: this.modules[moduleName].uniformTypes?.[key],
6774
- value: String(value)
6775
- };
6776
- }
6777
- }
6778
- return table;
6779
- }
6780
- };
6781
-
6782
7189
  // src/lib/pipeline-factory.ts
6783
- var import_core7 = __toESM(require_core(), 1);
7190
+ var import_core5 = __toESM(require_core(), 1);
6784
7191
  var _PipelineFactory = class {
6785
- device;
6786
- _hashCounter = 0;
6787
- _hashes = {};
6788
- _renderPipelineCache = {};
6789
- _computePipelineCache = {};
6790
7192
  /** Get the singleton default pipeline factory for the specified device */
6791
7193
  static getDefaultPipelineFactory(device) {
6792
7194
  device._lumaData.defaultPipelineFactory = device._lumaData.defaultPipelineFactory || new _PipelineFactory(device);
6793
7195
  return device._lumaData.defaultPipelineFactory;
6794
7196
  }
7197
+ device;
7198
+ destroyPolicy;
7199
+ _hashCounter = 0;
7200
+ _hashes = {};
7201
+ _renderPipelineCache = {};
7202
+ _computePipelineCache = {};
6795
7203
  constructor(device) {
6796
7204
  this.device = device;
7205
+ this.destroyPolicy = device.props._factoryDestroyPolicy;
6797
7206
  }
6798
7207
  /** Return a RenderPipeline matching props. Reuses a similar pipeline if already created. */
6799
7208
  createRenderPipeline(props) {
6800
- const allProps = { ...import_core7.RenderPipeline.defaultProps, ...props };
7209
+ const allProps = { ...import_core5.RenderPipeline.defaultProps, ...props };
6801
7210
  const hash = this._hashRenderPipeline(allProps);
6802
7211
  if (!this._renderPipelineCache[hash]) {
6803
7212
  const pipeline = this.device.createRenderPipeline({
@@ -6811,7 +7220,7 @@ void main() {
6811
7220
  return this._renderPipelineCache[hash].pipeline;
6812
7221
  }
6813
7222
  createComputePipeline(props) {
6814
- const allProps = { ...import_core7.ComputePipeline.defaultProps, ...props };
7223
+ const allProps = { ...import_core5.ComputePipeline.defaultProps, ...props };
6815
7224
  const hash = this._hashComputePipeline(allProps);
6816
7225
  if (!this._computePipelineCache[hash]) {
6817
7226
  const pipeline = this.device.createComputePipeline({
@@ -6826,11 +7235,13 @@ void main() {
6826
7235
  }
6827
7236
  release(pipeline) {
6828
7237
  const hash = pipeline.hash;
6829
- const cache = pipeline instanceof import_core7.ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
7238
+ const cache = pipeline instanceof import_core5.ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
6830
7239
  cache[hash].useCount--;
6831
7240
  if (cache[hash].useCount === 0) {
6832
- cache[hash].pipeline.destroy();
6833
- delete cache[hash];
7241
+ if (this.destroyPolicy === "unused") {
7242
+ cache[hash].pipeline.destroy();
7243
+ delete cache[hash];
7244
+ }
6834
7245
  }
6835
7246
  }
6836
7247
  // PRIVATE
@@ -6840,7 +7251,7 @@ void main() {
6840
7251
  }
6841
7252
  /** Calculate a hash based on all the inputs for a render pipeline */
6842
7253
  _hashRenderPipeline(props) {
6843
- const vsHash = this._getHash(props.vs.source);
7254
+ const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
6844
7255
  const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
6845
7256
  const varyingHash = "-";
6846
7257
  const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
@@ -6860,21 +7271,23 @@ void main() {
6860
7271
  }
6861
7272
  };
6862
7273
  var PipelineFactory = _PipelineFactory;
6863
- __publicField(PipelineFactory, "defaultProps", { ...import_core7.RenderPipeline.defaultProps });
7274
+ __publicField(PipelineFactory, "defaultProps", { ...import_core5.RenderPipeline.defaultProps });
6864
7275
 
6865
7276
  // src/lib/shader-factory.ts
6866
- var import_core8 = __toESM(require_core(), 1);
7277
+ var import_core6 = __toESM(require_core(), 1);
6867
7278
  var _ShaderFactory = class {
6868
- device;
6869
- _cache = {};
6870
7279
  /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
6871
7280
  static getDefaultShaderFactory(device) {
6872
7281
  device._lumaData.defaultShaderFactory ||= new _ShaderFactory(device);
6873
7282
  return device._lumaData.defaultShaderFactory;
6874
7283
  }
7284
+ device;
7285
+ destroyPolicy;
7286
+ _cache = {};
6875
7287
  /** @internal */
6876
7288
  constructor(device) {
6877
7289
  this.device = device;
7290
+ this.destroyPolicy = device.props._factoryDestroyPolicy;
6878
7291
  }
6879
7292
  /** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
6880
7293
  createShader(props) {
@@ -6897,8 +7310,10 @@ void main() {
6897
7310
  if (cacheEntry) {
6898
7311
  cacheEntry.useCount--;
6899
7312
  if (cacheEntry.useCount === 0) {
6900
- delete this._cache[key];
6901
- cacheEntry.shader.destroy();
7313
+ if (this.destroyPolicy === "unused") {
7314
+ delete this._cache[key];
7315
+ cacheEntry.shader.destroy();
7316
+ }
6902
7317
  }
6903
7318
  }
6904
7319
  }
@@ -6908,7 +7323,7 @@ void main() {
6908
7323
  }
6909
7324
  };
6910
7325
  var ShaderFactory = _ShaderFactory;
6911
- __publicField(ShaderFactory, "defaultProps", { ...import_core8.Shader.defaultProps });
7326
+ __publicField(ShaderFactory, "defaultProps", { ...import_core6.Shader.defaultProps });
6912
7327
 
6913
7328
  // src/debug/debug-shader-layout.ts
6914
7329
  function getDebugTableForShaderLayout(layout, name) {
@@ -6961,15 +7376,275 @@ void main() {
6961
7376
  canvas.style.height = "400px";
6962
7377
  }
6963
7378
  const color = fbo.device.readPixelsToArrayWebGL(fbo);
6964
- const imageData = ctx.createImageData(fbo.width, fbo.height);
6965
- const offset = 0;
6966
- for (let i = 0; i < color.length; i += 4) {
6967
- imageData.data[offset + i + 0] = color[i + 0] * rgbaScale;
6968
- imageData.data[offset + i + 1] = color[i + 1] * rgbaScale;
6969
- imageData.data[offset + i + 2] = color[i + 2] * rgbaScale;
6970
- imageData.data[offset + i + 3] = opaque ? 255 : color[i + 3] * rgbaScale;
6971
- }
6972
- ctx.putImageData(imageData, 0, 0);
7379
+ const imageData = ctx?.createImageData(fbo.width, fbo.height);
7380
+ if (imageData) {
7381
+ const offset = 0;
7382
+ for (let i = 0; i < color.length; i += 4) {
7383
+ imageData.data[offset + i + 0] = color[i + 0] * rgbaScale;
7384
+ imageData.data[offset + i + 1] = color[i + 1] * rgbaScale;
7385
+ imageData.data[offset + i + 2] = color[i + 2] * rgbaScale;
7386
+ imageData.data[offset + i + 3] = opaque ? 255 : color[i + 3] * rgbaScale;
7387
+ }
7388
+ ctx?.putImageData(imageData, 0, 0);
7389
+ }
7390
+ }
7391
+
7392
+ // src/utils/deep-equal.ts
7393
+ function deepEqual(a, b, depth) {
7394
+ if (a === b) {
7395
+ return true;
7396
+ }
7397
+ if (!depth || !a || !b) {
7398
+ return false;
7399
+ }
7400
+ if (Array.isArray(a)) {
7401
+ if (!Array.isArray(b) || a.length !== b.length) {
7402
+ return false;
7403
+ }
7404
+ for (let i = 0; i < a.length; i++) {
7405
+ if (!deepEqual(a[i], b[i], depth - 1)) {
7406
+ return false;
7407
+ }
7408
+ }
7409
+ return true;
7410
+ }
7411
+ if (Array.isArray(b)) {
7412
+ return false;
7413
+ }
7414
+ if (typeof a === "object" && typeof b === "object") {
7415
+ const aKeys = Object.keys(a);
7416
+ const bKeys = Object.keys(b);
7417
+ if (aKeys.length !== bKeys.length) {
7418
+ return false;
7419
+ }
7420
+ for (const key of aKeys) {
7421
+ if (!b.hasOwnProperty(key)) {
7422
+ return false;
7423
+ }
7424
+ if (!deepEqual(a[key], b[key], depth - 1)) {
7425
+ return false;
7426
+ }
7427
+ }
7428
+ return true;
7429
+ }
7430
+ return false;
7431
+ }
7432
+
7433
+ // ../../node_modules/@math.gl/types/dist/is-array.js
7434
+ function isTypedArray(value) {
7435
+ return ArrayBuffer.isView(value) && !(value instanceof DataView) ? value : null;
7436
+ }
7437
+ function isNumericArray(value) {
7438
+ if (Array.isArray(value)) {
7439
+ return value.length === 0 || typeof value[0] === "number" ? value : null;
7440
+ }
7441
+ return isTypedArray(value);
7442
+ }
7443
+
7444
+ // src/model/split-uniforms-and-bindings.ts
7445
+ function isUniformValue(value) {
7446
+ return isNumericArray(value) !== null || typeof value === "number" || typeof value === "boolean";
7447
+ }
7448
+ function splitUniformsAndBindings(uniforms) {
7449
+ const result = { bindings: {}, uniforms: {} };
7450
+ Object.keys(uniforms).forEach((name) => {
7451
+ const uniform = uniforms[name];
7452
+ if (isUniformValue(uniform)) {
7453
+ result.uniforms[name] = uniform;
7454
+ } else {
7455
+ result.bindings[name] = uniform;
7456
+ }
7457
+ });
7458
+ return result;
7459
+ }
7460
+
7461
+ // src/shader-inputs.ts
7462
+ var import_core7 = __toESM(require_core(), 1);
7463
+ var ShaderInputs = class {
7464
+ /**
7465
+ * The map of modules
7466
+ * @todo should should this include the resolved dependencies?
7467
+ */
7468
+ // @ts-expect-error Fix typings
7469
+ modules;
7470
+ /** Stores the uniform values for each module */
7471
+ moduleUniforms;
7472
+ /** Stores the uniform bindings for each module */
7473
+ moduleBindings;
7474
+ /** Tracks if uniforms have changed */
7475
+ // moduleUniformsChanged: Record<keyof ShaderPropsT, false | string>;
7476
+ /**
7477
+ * Create a new UniformStore instance
7478
+ * @param modules
7479
+ */
7480
+ // @ts-expect-error Fix typings
7481
+ constructor(modules) {
7482
+ const allModules = resolveModules(Object.values(modules));
7483
+ import_core7.log.log(
7484
+ 1,
7485
+ "Creating ShaderInputs with modules",
7486
+ allModules.map((m) => m.name)
7487
+ )();
7488
+ this.modules = modules;
7489
+ this.moduleUniforms = {};
7490
+ this.moduleBindings = {};
7491
+ for (const [name, module] of Object.entries(modules)) {
7492
+ const moduleName = name;
7493
+ this.moduleUniforms[moduleName] = module.defaultUniforms || {};
7494
+ this.moduleBindings[moduleName] = {};
7495
+ }
7496
+ }
7497
+ /** Destroy */
7498
+ destroy() {
7499
+ }
7500
+ /**
7501
+ * Set module props
7502
+ */
7503
+ setProps(props) {
7504
+ for (const name of Object.keys(props)) {
7505
+ const moduleName = name;
7506
+ const moduleProps = props[moduleName] || {};
7507
+ const module = this.modules[moduleName];
7508
+ if (!module) {
7509
+ import_core7.log.warn(`Module ${name} not found`)();
7510
+ continue;
7511
+ }
7512
+ const oldUniforms = this.moduleUniforms[moduleName];
7513
+ const uniforms = module.getUniforms?.(moduleProps, this.moduleUniforms[moduleName]) || moduleProps;
7514
+ this.moduleUniforms[moduleName] = { ...oldUniforms, ...uniforms };
7515
+ }
7516
+ }
7517
+ /** Merges all bindings for the shader (from the various modules) */
7518
+ // getUniformBlocks(): Record<string, Texture | Sampler> {
7519
+ // return this.moduleUniforms;
7520
+ // }
7521
+ /**
7522
+ * Return the map of modules
7523
+ * @todo should should this include the resolved dependencies?
7524
+ */
7525
+ getModules() {
7526
+ return Object.values(this.modules);
7527
+ }
7528
+ /** Get all uniform values for all modules */
7529
+ getUniformValues() {
7530
+ return this.moduleUniforms;
7531
+ }
7532
+ /** Merges all bindings for the shader (from the various modules) */
7533
+ getBindings() {
7534
+ const bindings = {};
7535
+ for (const moduleBindings of Object.values(this.moduleBindings)) {
7536
+ Object.assign(bindings, moduleBindings);
7537
+ }
7538
+ return bindings;
7539
+ }
7540
+ getDebugTable() {
7541
+ const table = {};
7542
+ for (const [moduleName, module] of Object.entries(this.moduleUniforms)) {
7543
+ for (const [key, value] of Object.entries(module)) {
7544
+ table[`${moduleName}.${key}`] = {
7545
+ type: this.modules[moduleName].uniformTypes?.[key],
7546
+ value: String(value)
7547
+ };
7548
+ }
7549
+ }
7550
+ return table;
7551
+ }
7552
+ };
7553
+
7554
+ // src/application-utils/load-file.ts
7555
+ var pathPrefix = "";
7556
+ function setPathPrefix(prefix) {
7557
+ pathPrefix = prefix;
7558
+ }
7559
+ async function loadImageBitmap(url, opts) {
7560
+ const image = new Image();
7561
+ image.crossOrigin = opts?.crossOrigin || "anonymous";
7562
+ image.src = url.startsWith("http") ? url : pathPrefix + url;
7563
+ await image.decode();
7564
+ return await createImageBitmap(image);
7565
+ }
7566
+ async function loadImage(url, opts) {
7567
+ return await new Promise((resolve, reject) => {
7568
+ try {
7569
+ const image = new Image();
7570
+ image.onload = () => resolve(image);
7571
+ image.onerror = () => reject(new Error(`Could not load image ${url}.`));
7572
+ image.crossOrigin = opts?.crossOrigin || "anonymous";
7573
+ image.src = url.startsWith("http") ? url : pathPrefix + url;
7574
+ } catch (error) {
7575
+ reject(error);
7576
+ }
7577
+ });
7578
+ }
7579
+
7580
+ // src/async-texture/async-texture.ts
7581
+ var AsyncTexture = class {
7582
+ device;
7583
+ // TODO - should we type these as possibly `null`? It will make usage harder?
7584
+ // @ts-expect-error
7585
+ texture;
7586
+ // @ts-expect-error
7587
+ sampler;
7588
+ // @ts-expect-error
7589
+ view;
7590
+ ready;
7591
+ isReady = false;
7592
+ destroyed = false;
7593
+ resolveReady = () => {
7594
+ };
7595
+ rejectReady = () => {
7596
+ };
7597
+ constructor(device, props) {
7598
+ this.device = device;
7599
+ if (typeof props?.data === "string" && props.dimension === "2d") {
7600
+ props = { ...props, data: loadImageBitmap(props.data) };
7601
+ }
7602
+ this.ready = new Promise((resolve, reject) => {
7603
+ this.resolveReady = () => {
7604
+ this.isReady = true;
7605
+ resolve();
7606
+ };
7607
+ this.rejectReady = reject;
7608
+ });
7609
+ this.initAsync(props);
7610
+ }
7611
+ async initAsync(props) {
7612
+ let resolveReady;
7613
+ let rejectReady;
7614
+ const asyncData = props.data;
7615
+ const data = await awaitAllPromises(asyncData).then(resolveReady, rejectReady);
7616
+ if (this.destroyed) {
7617
+ return;
7618
+ }
7619
+ const syncProps = { ...props, data };
7620
+ this.texture = this.device.createTexture(syncProps);
7621
+ this.sampler = this.texture.sampler;
7622
+ this.view = this.texture.view;
7623
+ this.isReady = true;
7624
+ }
7625
+ destroy() {
7626
+ if (this.texture) {
7627
+ this.texture.destroy();
7628
+ this.texture = null;
7629
+ }
7630
+ this.destroyed = true;
7631
+ }
7632
+ // We could implement resize by replacing the texture
7633
+ // resize(width: number, height: number): boolean {
7634
+ // throw new Error('Not implemented');
7635
+ // // return false;
7636
+ // }
7637
+ };
7638
+ async function awaitAllPromises(x) {
7639
+ x = await x;
7640
+ if (Array.isArray(x)) {
7641
+ return x.map(awaitAllPromises);
7642
+ }
7643
+ if (x && typeof x === "object" && x.constructor === Object) {
7644
+ const entries = Object.entries(x).map(([key, value]) => [key, awaitAllPromises(value)]);
7645
+ return Object.fromEntries(entries);
7646
+ }
7647
+ return x;
6973
7648
  }
6974
7649
 
6975
7650
  // src/model/model.ts
@@ -6978,8 +7653,11 @@ void main() {
6978
7653
  var _Model = class {
6979
7654
  device;
6980
7655
  id;
7656
+ // @ts-expect-error assigned in function called from constructor
6981
7657
  source;
7658
+ // @ts-expect-error assigned in function called from constructor
6982
7659
  vs;
7660
+ // @ts-expect-error assigned in function called from constructor
6983
7661
  fs;
6984
7662
  pipelineFactory;
6985
7663
  shaderFactory;
@@ -7019,7 +7697,9 @@ void main() {
7019
7697
  /** The underlying GPU "program". @note May be recreated if parameters change */
7020
7698
  pipeline;
7021
7699
  /** ShaderInputs instance */
7700
+ // @ts-expect-error Assigned in function called by constructor
7022
7701
  shaderInputs;
7702
+ // @ts-expect-error Assigned in function called by constructor
7023
7703
  _uniformStore;
7024
7704
  _attributeInfos = {};
7025
7705
  _gpuGeometry = null;
@@ -7033,7 +7713,7 @@ void main() {
7033
7713
  constructor(device, props) {
7034
7714
  this.props = { ..._Model.defaultProps, ...props };
7035
7715
  props = this.props;
7036
- this.id = props.id || (0, import_core11.uid)("model");
7716
+ this.id = props.id || uid("model");
7037
7717
  this.device = device;
7038
7718
  Object.assign(this.userData, props.userData);
7039
7719
  const moduleMap = Object.fromEntries(
@@ -7041,11 +7721,14 @@ void main() {
7041
7721
  );
7042
7722
  this.setShaderInputs(props.shaderInputs || new ShaderInputs(moduleMap));
7043
7723
  const platformInfo = getPlatformInfo(device);
7044
- const modules = (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
7724
+ const modules = (
7725
+ // @ts-expect-error shaderInputs is assigned in setShaderInputs above.
7726
+ (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || []
7727
+ );
7045
7728
  const isWebGPU = this.device.type === "webgpu";
7046
7729
  if (isWebGPU && this.props.source) {
7047
7730
  this.props.shaderLayout ||= getShaderLayoutFromWGSL(this.props.source);
7048
- const { source, getUniforms } = this.props.shaderAssembler.assembleShader({
7731
+ const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
7049
7732
  platformInfo,
7050
7733
  ...this.props,
7051
7734
  modules
@@ -7053,7 +7736,7 @@ void main() {
7053
7736
  this.source = source;
7054
7737
  this._getModuleUniforms = getUniforms;
7055
7738
  } else {
7056
- const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleShaderPair({
7739
+ const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleGLSLShaderPair({
7057
7740
  platformInfo,
7058
7741
  ...this.props,
7059
7742
  modules
@@ -7147,8 +7830,11 @@ void main() {
7147
7830
  try {
7148
7831
  this._logDrawCallStart();
7149
7832
  this.pipeline = this._updatePipeline();
7150
- this.pipeline.setBindings(this.bindings, { disableWarnings: this.props.disableWarnings });
7151
- if (!(0, import_core11.isObjectEmpty)(this.uniforms)) {
7833
+ const syncBindings = this._getBindings();
7834
+ this.pipeline.setBindings(syncBindings, {
7835
+ disableWarnings: this.props.disableWarnings
7836
+ });
7837
+ if (!isObjectEmpty(this.uniforms)) {
7152
7838
  this.pipeline.setUniformsWebGL(this.uniforms);
7153
7839
  }
7154
7840
  const { indexBuffer } = this.vertexArray;
@@ -7228,7 +7914,7 @@ void main() {
7228
7914
  * @param parameters
7229
7915
  */
7230
7916
  setParameters(parameters) {
7231
- if (!(0, import_core11.deepEqual)(parameters, this.parameters, 2)) {
7917
+ if (!deepEqual(parameters, this.parameters, 2)) {
7232
7918
  this.parameters = parameters;
7233
7919
  this._setPipelineNeedsUpdate("parameters");
7234
7920
  }
@@ -7256,7 +7942,7 @@ void main() {
7256
7942
  /** Set the shader inputs */
7257
7943
  setShaderInputs(shaderInputs) {
7258
7944
  this.shaderInputs = shaderInputs;
7259
- this._uniformStore = new import_core10.UniformStore(this.shaderInputs.modules);
7945
+ this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
7260
7946
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
7261
7947
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
7262
7948
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -7296,7 +7982,7 @@ void main() {
7296
7982
  */
7297
7983
  setAttributes(buffers, options) {
7298
7984
  if (buffers.indices) {
7299
- import_core11.log.warn(
7985
+ import_core10.log.warn(
7300
7986
  `Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`
7301
7987
  )();
7302
7988
  }
@@ -7305,7 +7991,7 @@ void main() {
7305
7991
  (layout) => getAttributeNames(layout).includes(bufferName)
7306
7992
  );
7307
7993
  if (!bufferLayout) {
7308
- import_core11.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
7994
+ import_core10.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
7309
7995
  continue;
7310
7996
  }
7311
7997
  const attributeNames = getAttributeNames(bufferLayout);
@@ -7318,7 +8004,7 @@ void main() {
7318
8004
  }
7319
8005
  }
7320
8006
  if (!set && !(options?.disableWarnings ?? this.props.disableWarnings)) {
7321
- import_core11.log.warn(
8007
+ import_core10.log.warn(
7322
8008
  `Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`
7323
8009
  )();
7324
8010
  }
@@ -7339,7 +8025,7 @@ void main() {
7339
8025
  if (attributeInfo) {
7340
8026
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
7341
8027
  } else if (!(options?.disableWarnings ?? this.props.disableWarnings)) {
7342
- import_core11.log.warn(
8028
+ import_core10.log.warn(
7343
8029
  `Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`
7344
8030
  )();
7345
8031
  }
@@ -7353,7 +8039,7 @@ void main() {
7353
8039
  * @param uniforms
7354
8040
  */
7355
8041
  setUniforms(uniforms) {
7356
- if (!(0, import_core11.isObjectEmpty)(uniforms)) {
8042
+ if (!isObjectEmpty(uniforms)) {
7357
8043
  this.pipeline.setUniformsWebGL(uniforms);
7358
8044
  Object.assign(this.uniforms, uniforms);
7359
8045
  }
@@ -7363,21 +8049,39 @@ void main() {
7363
8049
  * @deprecated Updates shader module settings (which results in uniforms being set)
7364
8050
  */
7365
8051
  updateModuleSettings(props) {
7366
- const { bindings, uniforms } = (0, import_core11.splitUniformsAndBindings)(this._getModuleUniforms(props));
8052
+ const { bindings, uniforms } = splitUniformsAndBindings(this._getModuleUniforms(props));
7367
8053
  Object.assign(this.bindings, bindings);
7368
8054
  Object.assign(this.uniforms, uniforms);
7369
8055
  this.setNeedsRedraw("moduleSettings");
7370
8056
  }
7371
8057
  // Internal methods
8058
+ /** Get texture / texture view from any async textures */
8059
+ _getBindings() {
8060
+ return Object.entries(this.bindings).reduce((acc, [name, binding]) => {
8061
+ if (binding instanceof AsyncTexture) {
8062
+ if (binding.isReady) {
8063
+ acc[name] = binding.texture;
8064
+ }
8065
+ } else {
8066
+ acc[name] = binding;
8067
+ }
8068
+ return acc;
8069
+ }, {});
8070
+ }
7372
8071
  /** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
7373
8072
  _getBindingsUpdateTimestamp() {
7374
8073
  let timestamp = 0;
7375
8074
  for (const binding of Object.values(this.bindings)) {
7376
- if (binding instanceof import_core9.TextureView) {
8075
+ if (binding instanceof import_core8.TextureView) {
7377
8076
  timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
7378
- } else if (binding instanceof import_core9.Buffer || binding instanceof import_core9.Texture) {
8077
+ } else if (binding instanceof import_core8.Buffer || binding instanceof import_core8.Texture) {
7379
8078
  timestamp = Math.max(timestamp, binding.updateTimestamp);
7380
- } else if (!(binding instanceof import_core9.Sampler)) {
8079
+ } else if (binding instanceof AsyncTexture) {
8080
+ timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
8081
+ // The texture will become available in the future
8082
+ Infinity
8083
+ );
8084
+ } else if (!(binding instanceof import_core8.Sampler)) {
7381
8085
  timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
7382
8086
  }
7383
8087
  }
@@ -7412,7 +8116,7 @@ void main() {
7412
8116
  let prevShaderVs = null;
7413
8117
  let prevShaderFs = null;
7414
8118
  if (this.pipeline) {
7415
- import_core11.log.log(
8119
+ import_core10.log.log(
7416
8120
  1,
7417
8121
  `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
7418
8122
  )();
@@ -7442,10 +8146,13 @@ void main() {
7442
8146
  bufferLayout: this.bufferLayout,
7443
8147
  topology: this.topology,
7444
8148
  parameters: this.parameters,
8149
+ // TODO - why set bindings here when we reset them every frame?
8150
+ // Should we expose a BindGroup abstraction?
8151
+ bindings: this._getBindings(),
7445
8152
  vs,
7446
8153
  fs
7447
8154
  });
7448
- this._attributeInfos = (0, import_core12.getAttributeInfosFromLayouts)(
8155
+ this._attributeInfos = (0, import_core11.getAttributeInfosFromLayouts)(
7449
8156
  this.pipeline.shaderLayout,
7450
8157
  this.bufferLayout
7451
8158
  );
@@ -7460,33 +8167,33 @@ void main() {
7460
8167
  _lastLogTime = 0;
7461
8168
  _logOpen = false;
7462
8169
  _logDrawCallStart() {
7463
- const logDrawTimeout = import_core11.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
7464
- if (import_core11.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
8170
+ const logDrawTimeout = import_core10.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
8171
+ if (import_core10.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
7465
8172
  return;
7466
8173
  }
7467
8174
  this._lastLogTime = Date.now();
7468
8175
  this._logOpen = true;
7469
- import_core11.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core11.log.level <= 2 })();
8176
+ import_core10.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core10.log.level <= 2 })();
7470
8177
  }
7471
8178
  _logDrawCallEnd() {
7472
8179
  if (this._logOpen) {
7473
8180
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
7474
- import_core11.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
8181
+ import_core10.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
7475
8182
  const uniformTable = this.shaderInputs.getDebugTable();
7476
8183
  for (const [name, value] of Object.entries(this.uniforms)) {
7477
8184
  uniformTable[name] = { value };
7478
8185
  }
7479
- import_core11.log.table(LOG_DRAW_PRIORITY, uniformTable)();
8186
+ import_core10.log.table(LOG_DRAW_PRIORITY, uniformTable)();
7480
8187
  const attributeTable = this._getAttributeDebugTable();
7481
- import_core11.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
7482
- import_core11.log.table(LOG_DRAW_PRIORITY, attributeTable)();
7483
- import_core11.log.groupEnd(LOG_DRAW_PRIORITY)();
8188
+ import_core10.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
8189
+ import_core10.log.table(LOG_DRAW_PRIORITY, attributeTable)();
8190
+ import_core10.log.groupEnd(LOG_DRAW_PRIORITY)();
7484
8191
  this._logOpen = false;
7485
8192
  }
7486
8193
  }
7487
8194
  _drawCount = 0;
7488
8195
  _logFramebuffer(renderPass) {
7489
- const debugFramebuffers = import_core11.log.get("framebuffer");
8196
+ const debugFramebuffers = import_core10.log.get("framebuffer");
7490
8197
  this._drawCount++;
7491
8198
  if (!debugFramebuffers || this._drawCount++ > 3 && this._drawCount % 60) {
7492
8199
  return;
@@ -7499,13 +8206,11 @@ void main() {
7499
8206
  _getAttributeDebugTable() {
7500
8207
  const table = {};
7501
8208
  for (const [name, attributeInfo] of Object.entries(this._attributeInfos)) {
8209
+ const values = this.vertexArray.attributes[attributeInfo.location];
7502
8210
  table[attributeInfo.location] = {
7503
8211
  name,
7504
8212
  type: attributeInfo.shaderType,
7505
- values: this._getBufferOrConstantValues(
7506
- this.vertexArray.attributes[attributeInfo.location],
7507
- attributeInfo.bufferDataType
7508
- )
8213
+ values: values ? this._getBufferOrConstantValues(values, attributeInfo.bufferDataType) : "null"
7509
8214
  };
7510
8215
  }
7511
8216
  if (this.vertexArray.indexBuffer) {
@@ -7521,15 +8226,15 @@ void main() {
7521
8226
  }
7522
8227
  // TODO - fix typing of luma data types
7523
8228
  _getBufferOrConstantValues(attribute, dataType) {
7524
- const TypedArrayConstructor = (0, import_core12.getTypedArrayFromDataType)(dataType);
7525
- const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
8229
+ const TypedArrayConstructor = (0, import_core11.getTypedArrayFromDataType)(dataType);
8230
+ const typedArray = attribute instanceof import_core8.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
7526
8231
  return typedArray.toString();
7527
8232
  }
7528
8233
  };
7529
8234
  var Model = _Model;
7530
8235
  __publicField(Model, "defaultProps", {
7531
- ...import_core10.RenderPipeline.defaultProps,
7532
- source: null,
8236
+ ...import_core9.RenderPipeline.defaultProps,
8237
+ source: void 0,
7533
8238
  vs: null,
7534
8239
  fs: null,
7535
8240
  id: "unnamed",
@@ -7579,9 +8284,17 @@ void main() {
7579
8284
  function getAttributeNames(bufferLayout) {
7580
8285
  return bufferLayout.attributes ? bufferLayout.attributes?.map((layout) => layout.attribute) : [bufferLayout.name];
7581
8286
  }
8287
+ function isObjectEmpty(obj) {
8288
+ let isEmpty = true;
8289
+ for (const key in obj) {
8290
+ isEmpty = false;
8291
+ break;
8292
+ }
8293
+ return isEmpty;
8294
+ }
7582
8295
 
7583
8296
  // src/transform/buffer-transform.ts
7584
- var import_core13 = __toESM(require_core(), 1);
8297
+ var import_core12 = __toESM(require_core(), 1);
7585
8298
  var BufferTransform = class {
7586
8299
  device;
7587
8300
  model;
@@ -7591,7 +8304,9 @@ void main() {
7591
8304
  return device?.info?.type === "webgl";
7592
8305
  }
7593
8306
  constructor(device, props = Model.defaultProps) {
7594
- (0, import_core13.assert)(BufferTransform.isSupported(device), "BufferTransform not yet implemented on WebGPU");
8307
+ if (!BufferTransform.isSupported(device)) {
8308
+ throw new Error("BufferTransform not yet implemented on WebGPU");
8309
+ }
7595
8310
  this.device = device;
7596
8311
  this.model = new Model(this.device, {
7597
8312
  id: props.id || "buffer-transform-model",
@@ -7601,6 +8316,7 @@ void main() {
7601
8316
  });
7602
8317
  this.transformFeedback = this.device.createTransformFeedback({
7603
8318
  layout: this.model.pipeline.shaderLayout,
8319
+ // @ts-expect-error TODO
7604
8320
  buffers: props.feedbackBuffers
7605
8321
  });
7606
8322
  this.model.setTransformFeedback(this.transformFeedback);
@@ -7632,7 +8348,10 @@ void main() {
7632
8348
  }
7633
8349
  readAsync(varyingName) {
7634
8350
  const result = this.getBuffer(varyingName);
7635
- if (result instanceof import_core13.Buffer) {
8351
+ if (!result) {
8352
+ throw new Error("BufferTransform#getBuffer");
8353
+ }
8354
+ if (result instanceof import_core12.Buffer) {
7636
8355
  return result.readAsync();
7637
8356
  }
7638
8357
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
@@ -7715,6 +8434,7 @@ void main() {
7715
8434
  binding = {
7716
8435
  sourceBuffers: {},
7717
8436
  sourceTextures: {},
8437
+ // @ts-expect-error
7718
8438
  targetTexture: null
7719
8439
  };
7720
8440
  }
@@ -7747,10 +8467,9 @@ void main() {
7747
8467
  };
7748
8468
 
7749
8469
  // src/lib/clip-space.ts
7750
- var import_core15 = __toESM(require_core(), 1);
8470
+ var import_core13 = __toESM(require_core(), 1);
7751
8471
 
7752
8472
  // src/geometry/geometry.ts
7753
- var import_core14 = __toESM(require_core(), 1);
7754
8473
  var Geometry = class {
7755
8474
  id;
7756
8475
  /** Determines how vertices are read from the 'vertex' attributes */
@@ -7761,7 +8480,7 @@ void main() {
7761
8480
  userData = {};
7762
8481
  constructor(props) {
7763
8482
  const { attributes = {}, indices = null, vertexCount = null } = props;
7764
- this.id = props.id || (0, import_core14.uid)("geometry");
8483
+ this.id = props.id || uid("geometry");
7765
8484
  this.topology = props.topology;
7766
8485
  if (indices) {
7767
8486
  this.indices = ArrayBuffer.isView(indices) ? { value: indices, size: 1 } : indices;
@@ -7769,15 +8488,18 @@ void main() {
7769
8488
  this.attributes = {};
7770
8489
  for (const [attributeName, attributeValue] of Object.entries(attributes)) {
7771
8490
  const attribute = ArrayBuffer.isView(attributeValue) ? { value: attributeValue } : attributeValue;
7772
- (0, import_core14.assert)(
7773
- ArrayBuffer.isView(attribute.value),
7774
- `${this._print(attributeName)}: must be typed array or object with value as typed array`
7775
- );
8491
+ if (!ArrayBuffer.isView(attribute.value)) {
8492
+ throw new Error(
8493
+ `${this._print(attributeName)}: must be typed array or object with value as typed array`
8494
+ );
8495
+ }
7776
8496
  if ((attributeName === "POSITION" || attributeName === "positions") && !attribute.size) {
7777
8497
  attribute.size = 3;
7778
8498
  }
7779
8499
  if (attributeName === "indices") {
7780
- (0, import_core14.assert)(!this.indices);
8500
+ if (this.indices) {
8501
+ throw new Error("Multiple indices detected");
8502
+ }
7781
8503
  this.indices = attribute;
7782
8504
  } else {
7783
8505
  this.attributes[attributeName] = attribute;
@@ -7824,17 +8546,16 @@ void main() {
7824
8546
  let vertexCount = Infinity;
7825
8547
  for (const attribute of Object.values(attributes)) {
7826
8548
  const { value, size, constant } = attribute;
7827
- if (!constant && value && size >= 1) {
8549
+ if (!constant && value && size !== void 0 && size >= 1) {
7828
8550
  vertexCount = Math.min(vertexCount, value.length / size);
7829
8551
  }
7830
8552
  }
7831
- (0, import_core14.assert)(Number.isFinite(vertexCount));
7832
8553
  return vertexCount;
7833
8554
  }
7834
8555
  };
7835
8556
 
7836
8557
  // src/lib/clip-space.ts
7837
- var CLIPSPACE_VERTEX_SHADER = import_core15.glsl`\
8558
+ var CLIPSPACE_VERTEX_SHADER = import_core13.glsl`\
7838
8559
  #version 300 es
7839
8560
  in vec2 aClipSpacePosition;
7840
8561
  in vec2 aTexCoord;
@@ -7873,7 +8594,6 @@ void main(void) {
7873
8594
  };
7874
8595
 
7875
8596
  // src/scenegraph/scenegraph-node.ts
7876
- var import_core16 = __toESM(require_core(), 1);
7877
8597
  var ScenegraphNode = class {
7878
8598
  id;
7879
8599
  matrix = new Matrix4();
@@ -7885,7 +8605,7 @@ void main(void) {
7885
8605
  props = {};
7886
8606
  constructor(props = {}) {
7887
8607
  const { id } = props;
7888
- this.id = id || (0, import_core16.uid)(this.constructor.name);
8608
+ this.id = id || uid(this.constructor.name);
7889
8609
  this._setScenegraphNodeProps(props);
7890
8610
  }
7891
8611
  getBounds() {
@@ -7905,17 +8625,14 @@ void main(void) {
7905
8625
  return `{type: ScenegraphNode, id: ${this.id})}`;
7906
8626
  }
7907
8627
  setPosition(position) {
7908
- (0, import_core16.assert)(position.length === 3, "setPosition requires vector argument");
7909
8628
  this.position = position;
7910
8629
  return this;
7911
8630
  }
7912
8631
  setRotation(rotation) {
7913
- (0, import_core16.assert)(rotation.length === 3, "setRotation requires vector argument");
7914
8632
  this.rotation = rotation;
7915
8633
  return this;
7916
8634
  }
7917
8635
  setScale(scale2) {
7918
- (0, import_core16.assert)(scale2.length === 3, "setScale requires vector argument");
7919
8636
  this.scale = scale2;
7920
8637
  return this;
7921
8638
  }
@@ -7967,7 +8684,6 @@ void main(void) {
7967
8684
  return this;
7968
8685
  }
7969
8686
  getCoordinateUniforms(viewMatrix, modelMatrix) {
7970
- (0, import_core16.assert)(viewMatrix);
7971
8687
  modelMatrix = modelMatrix || this.matrix;
7972
8688
  const worldMatrix = new Matrix4(viewMatrix).multiplyRight(modelMatrix);
7973
8689
  const worldInverse = worldMatrix.invert();
@@ -8004,9 +8720,6 @@ void main(void) {
8004
8720
  }
8005
8721
  */
8006
8722
  _setScenegraphNodeProps(props) {
8007
- if ("display" in props) {
8008
- this.display = props.display;
8009
- }
8010
8723
  if ("position" in props) {
8011
8724
  this.setPosition(props.position);
8012
8725
  }
@@ -8024,13 +8737,13 @@ void main(void) {
8024
8737
  };
8025
8738
 
8026
8739
  // src/scenegraph/group-node.ts
8027
- var import_core19 = __toESM(require_core(), 1);
8740
+ var import_core16 = __toESM(require_core(), 1);
8028
8741
  var GroupNode = class extends ScenegraphNode {
8029
8742
  children;
8030
8743
  constructor(props = {}) {
8031
8744
  props = Array.isArray(props) ? { children: props } : props;
8032
8745
  const { children = [] } = props;
8033
- import_core19.log.assert(
8746
+ import_core16.log.assert(
8034
8747
  children.every((child) => child instanceof ScenegraphNode),
8035
8748
  "every child must an instance of ScenegraphNode"
8036
8749
  );
@@ -8121,9 +8834,6 @@ void main(void) {
8121
8834
  this.bounds = props.bounds || null;
8122
8835
  this.setProps(props);
8123
8836
  }
8124
- getBounds() {
8125
- return this.bounds;
8126
- }
8127
8837
  destroy() {
8128
8838
  if (this.model) {
8129
8839
  this.model.destroy();
@@ -8132,17 +8842,16 @@ void main(void) {
8132
8842
  this.managedResources.forEach((resource) => resource.destroy());
8133
8843
  this.managedResources = [];
8134
8844
  }
8845
+ getBounds() {
8846
+ return this.bounds;
8847
+ }
8135
8848
  // Expose model methods
8136
8849
  draw(renderPass) {
8137
8850
  return this.model.draw(renderPass);
8138
8851
  }
8139
8852
  };
8140
8853
 
8141
- // src/geometries/cone-geometry.ts
8142
- var import_core21 = __toESM(require_core(), 1);
8143
-
8144
8854
  // src/geometries/truncated-cone-geometry.ts
8145
- var import_core20 = __toESM(require_core(), 1);
8146
8855
  var INDEX_OFFSETS = {
8147
8856
  x: [2, 0, 1],
8148
8857
  y: [0, 1, 2],
@@ -8150,7 +8859,7 @@ void main(void) {
8150
8859
  };
8151
8860
  var TruncatedConeGeometry = class extends Geometry {
8152
8861
  constructor(props = {}) {
8153
- const { id = (0, import_core20.uid)("truncated-code-geometry") } = props;
8862
+ const { id = uid("truncated-code-geometry") } = props;
8154
8863
  const { indices, attributes } = tesselateTruncatedCone(props);
8155
8864
  super({
8156
8865
  ...props,
@@ -8254,7 +8963,7 @@ void main(void) {
8254
8963
  // src/geometries/cone-geometry.ts
8255
8964
  var ConeGeometry = class extends TruncatedConeGeometry {
8256
8965
  constructor(props = {}) {
8257
- const { id = (0, import_core21.uid)("cone-geometry"), radius = 1, cap = true } = props;
8966
+ const { id = uid("cone-geometry"), radius = 1, cap = true } = props;
8258
8967
  super({
8259
8968
  ...props,
8260
8969
  id,
@@ -8267,10 +8976,9 @@ void main(void) {
8267
8976
  };
8268
8977
 
8269
8978
  // src/geometries/cube-geometry.ts
8270
- var import_core22 = __toESM(require_core(), 1);
8271
8979
  var CubeGeometry = class extends Geometry {
8272
8980
  constructor(props = {}) {
8273
- const { id = (0, import_core22.uid)("cube-geometry"), indices = true } = props;
8981
+ const { id = uid("cube-geometry"), indices = true } = props;
8274
8982
  super(
8275
8983
  indices ? {
8276
8984
  ...props,
@@ -8879,10 +9587,9 @@ void main(void) {
8879
9587
  };
8880
9588
 
8881
9589
  // src/geometries/cylinder-geometry.ts
8882
- var import_core23 = __toESM(require_core(), 1);
8883
9590
  var CylinderGeometry = class extends TruncatedConeGeometry {
8884
9591
  constructor(props = {}) {
8885
- const { id = (0, import_core23.uid)("cylinder-geometry"), radius = 1 } = props;
9592
+ const { id = uid("cylinder-geometry"), radius = 1 } = props;
8886
9593
  super({
8887
9594
  ...props,
8888
9595
  id,
@@ -8893,12 +9600,11 @@ void main(void) {
8893
9600
  };
8894
9601
 
8895
9602
  // src/geometries/ico-sphere-geometry.ts
8896
- var import_core24 = __toESM(require_core(), 1);
8897
9603
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
8898
9604
  var ICO_INDICES = [3, 4, 5, 3, 5, 1, 3, 1, 0, 3, 0, 4, 4, 0, 2, 4, 2, 5, 2, 0, 1, 5, 2, 1];
8899
9605
  var IcoSphereGeometry = class extends Geometry {
8900
9606
  constructor(props = {}) {
8901
- const { id = (0, import_core24.uid)("ico-sphere-geometry") } = props;
9607
+ const { id = uid("ico-sphere-geometry") } = props;
8902
9608
  const { indices, attributes } = tesselateIcosaHedron(props);
8903
9609
  super({
8904
9610
  ...props,
@@ -9039,9 +9745,6 @@ void main(void) {
9039
9745
  };
9040
9746
  }
9041
9747
 
9042
- // src/geometries/plane-geometry.ts
9043
- var import_core26 = __toESM(require_core(), 1);
9044
-
9045
9748
  // src/geometry/geometry-utils.ts
9046
9749
  function unpackIndexedGeometry(geometry) {
9047
9750
  const { indices, attributes } = geometry;
@@ -9073,7 +9776,7 @@ void main(void) {
9073
9776
  // src/geometries/plane-geometry.ts
9074
9777
  var PlaneGeometry = class extends Geometry {
9075
9778
  constructor(props = {}) {
9076
- const { id = (0, import_core26.uid)("plane-geometry") } = props;
9779
+ const { id = uid("plane-geometry") } = props;
9077
9780
  const { indices, attributes } = tesselatePlane(props);
9078
9781
  super({
9079
9782
  ...props,
@@ -9163,10 +9866,9 @@ void main(void) {
9163
9866
  }
9164
9867
 
9165
9868
  // src/geometries/sphere-geometry.ts
9166
- var import_core27 = __toESM(require_core(), 1);
9167
9869
  var SphereGeometry = class extends Geometry {
9168
9870
  constructor(props = {}) {
9169
- const { id = (0, import_core27.uid)("sphere-geometry") } = props;
9871
+ const { id = uid("sphere-geometry") } = props;
9170
9872
  const { indices, attributes } = tesselateSphere(props);
9171
9873
  super({
9172
9874
  ...props,
@@ -9241,10 +9943,24 @@ void main(void) {
9241
9943
  };
9242
9944
  }
9243
9945
 
9946
+ // src/application-utils/random.ts
9947
+ function makeRandomGenerator() {
9948
+ let s = 1;
9949
+ let c = 1;
9950
+ return () => {
9951
+ s = Math.sin(c * 17.23);
9952
+ c = Math.cos(s * 27.92);
9953
+ return fract(Math.abs(s * c) * 1432.71);
9954
+ };
9955
+ }
9956
+ function fract(n) {
9957
+ return n - Math.floor(n);
9958
+ }
9959
+
9244
9960
  // src/computation.ts
9245
- var import_core28 = __toESM(require_core(), 1);
9246
- var import_core29 = __toESM(require_core(), 1);
9247
- var import_core30 = __toESM(require_core(), 1);
9961
+ var import_core18 = __toESM(require_core(), 1);
9962
+ var import_core19 = __toESM(require_core(), 1);
9963
+ var import_core20 = __toESM(require_core(), 1);
9248
9964
  var LOG_DRAW_PRIORITY2 = 2;
9249
9965
  var LOG_DRAW_TIMEOUT2 = 1e4;
9250
9966
  var _Computation = class {
@@ -9255,13 +9971,16 @@ void main(void) {
9255
9971
  userData = {};
9256
9972
  /** Bindings (textures, samplers, uniform buffers) */
9257
9973
  bindings = {};
9258
- /** The underlying GPU "program". @note May be recreated if parameters change */
9974
+ /** The underlying GPU pipeline. */
9259
9975
  pipeline;
9976
+ /** Assembled compute shader source */
9977
+ source;
9260
9978
  /** the underlying compiled compute shader */
9979
+ // @ts-ignore Set in function called from constructor
9261
9980
  shader;
9262
- source;
9263
9981
  /** ShaderInputs instance */
9264
9982
  shaderInputs;
9983
+ // @ts-ignore Set in function called from constructor
9265
9984
  _uniformStore;
9266
9985
  _pipelineNeedsUpdate = "newly created";
9267
9986
  _getModuleUniforms;
@@ -9273,19 +9992,20 @@ void main(void) {
9273
9992
  }
9274
9993
  this.props = { ..._Computation.defaultProps, ...props };
9275
9994
  props = this.props;
9276
- this.id = props.id || (0, import_core29.uid)("model");
9995
+ this.id = props.id || uid("model");
9277
9996
  this.device = device;
9278
9997
  Object.assign(this.userData, props.userData);
9279
9998
  const moduleMap = Object.fromEntries(
9280
9999
  this.props.modules?.map((module) => [module.name, module]) || []
9281
10000
  );
9282
- this.setShaderInputs(props.shaderInputs || new ShaderInputs(moduleMap));
10001
+ this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
10002
+ this.setShaderInputs(this.shaderInputs);
9283
10003
  this.props.shaderLayout ||= getShaderLayoutFromWGSL(this.props.source);
9284
10004
  const platformInfo = getPlatformInfo2(device);
9285
10005
  const modules = (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
9286
10006
  this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
9287
10007
  this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
9288
- const { source, getUniforms } = this.props.shaderAssembler.assembleShader({
10008
+ const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
9289
10009
  platformInfo,
9290
10010
  ...this.props,
9291
10011
  modules
@@ -9338,7 +10058,7 @@ void main(void) {
9338
10058
  }
9339
10059
  setShaderInputs(shaderInputs) {
9340
10060
  this.shaderInputs = shaderInputs;
9341
- this._uniformStore = new import_core28.UniformStore(this.shaderInputs.modules);
10061
+ this._uniformStore = new import_core18.UniformStore(this.shaderInputs.modules);
9342
10062
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
9343
10063
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
9344
10064
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -9351,7 +10071,7 @@ void main(void) {
9351
10071
  const uniforms = this._getModuleUniforms(props);
9352
10072
  const keys = Object.keys(uniforms).filter((k) => {
9353
10073
  const uniform = uniforms[k];
9354
- return !(0, import_core29.isNumberArray)(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
10074
+ return !isNumericArray(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
9355
10075
  });
9356
10076
  const bindings = {};
9357
10077
  for (const k of keys) {
@@ -9375,7 +10095,7 @@ void main(void) {
9375
10095
  if (this._pipelineNeedsUpdate) {
9376
10096
  let prevShader = null;
9377
10097
  if (this.pipeline) {
9378
- import_core29.log.log(
10098
+ import_core19.log.log(
9379
10099
  1,
9380
10100
  `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
9381
10101
  )();
@@ -9402,33 +10122,33 @@ void main(void) {
9402
10122
  _lastLogTime = 0;
9403
10123
  _logOpen = false;
9404
10124
  _logDrawCallStart() {
9405
- const logDrawTimeout = import_core29.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
9406
- if (import_core29.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
10125
+ const logDrawTimeout = import_core19.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
10126
+ if (import_core19.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
9407
10127
  return;
9408
10128
  }
9409
10129
  this._lastLogTime = Date.now();
9410
10130
  this._logOpen = true;
9411
- import_core29.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core29.log.level <= 2 })();
10131
+ import_core19.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core19.log.level <= 2 })();
9412
10132
  }
9413
10133
  _logDrawCallEnd() {
9414
10134
  if (this._logOpen) {
9415
10135
  const uniformTable = this.shaderInputs.getDebugTable();
9416
- import_core29.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
9417
- import_core29.log.groupEnd(LOG_DRAW_PRIORITY2)();
10136
+ import_core19.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
10137
+ import_core19.log.groupEnd(LOG_DRAW_PRIORITY2)();
9418
10138
  this._logOpen = false;
9419
10139
  }
9420
10140
  }
9421
10141
  _drawCount = 0;
9422
10142
  // TODO - fix typing of luma data types
9423
10143
  _getBufferOrConstantValues(attribute, dataType) {
9424
- const TypedArrayConstructor = (0, import_core30.getTypedArrayFromDataType)(dataType);
9425
- const typedArray = attribute instanceof import_core28.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
10144
+ const TypedArrayConstructor = (0, import_core20.getTypedArrayFromDataType)(dataType);
10145
+ const typedArray = attribute instanceof import_core18.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
9426
10146
  return typedArray.toString();
9427
10147
  }
9428
10148
  };
9429
10149
  var Computation = _Computation;
9430
10150
  __publicField(Computation, "defaultProps", {
9431
- ...import_core28.ComputePipeline.defaultProps,
10151
+ ...import_core18.ComputePipeline.defaultProps,
9432
10152
  id: "unnamed",
9433
10153
  handle: void 0,
9434
10154
  userData: {},