@luma.gl/engine 9.1.9 → 9.2.0-alpha.2

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 (102) hide show
  1. package/README.md +5 -0
  2. package/dist/animation-loop/animation-loop.d.ts +12 -12
  3. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  4. package/dist/animation-loop/animation-loop.js +26 -62
  5. package/dist/animation-loop/animation-loop.js.map +1 -1
  6. package/dist/animation-loop/animation-props.d.ts +3 -4
  7. package/dist/animation-loop/animation-props.d.ts.map +1 -1
  8. package/dist/animation-loop/make-animation-loop.d.ts +4 -1
  9. package/dist/animation-loop/make-animation-loop.d.ts.map +1 -1
  10. package/dist/animation-loop/make-animation-loop.js +39 -7
  11. package/dist/animation-loop/make-animation-loop.js.map +1 -1
  12. package/dist/async-texture/async-texture.d.ts +106 -2
  13. package/dist/async-texture/async-texture.d.ts.map +1 -1
  14. package/dist/async-texture/async-texture.js +281 -13
  15. package/dist/async-texture/async-texture.js.map +1 -1
  16. package/dist/compute/computation.d.ts +1 -1
  17. package/dist/compute/computation.d.ts.map +1 -1
  18. package/dist/compute/computation.js +2 -2
  19. package/dist/compute/computation.js.map +1 -1
  20. package/dist/compute/swap.d.ts.map +1 -1
  21. package/dist/compute/swap.js +6 -2
  22. package/dist/compute/swap.js.map +1 -1
  23. package/dist/compute/texture-transform.d.ts.map +1 -1
  24. package/dist/compute/texture-transform.js +4 -2
  25. package/dist/compute/texture-transform.js.map +1 -1
  26. package/dist/debug/copy-texture-to-image.d.ts +23 -1
  27. package/dist/debug/copy-texture-to-image.d.ts.map +1 -1
  28. package/dist/debug/copy-texture-to-image.js +37 -1
  29. package/dist/debug/copy-texture-to-image.js.map +1 -1
  30. package/dist/dist.dev.js +566 -232
  31. package/dist/dist.min.js +26 -26
  32. package/dist/factories/pipeline-factory.d.ts +11 -1
  33. package/dist/factories/pipeline-factory.d.ts.map +1 -1
  34. package/dist/factories/pipeline-factory.js +107 -25
  35. package/dist/factories/pipeline-factory.js.map +1 -1
  36. package/dist/factories/shader-factory.d.ts +5 -1
  37. package/dist/factories/shader-factory.d.ts.map +1 -1
  38. package/dist/factories/shader-factory.js +40 -6
  39. package/dist/factories/shader-factory.js.map +1 -1
  40. package/dist/geometries/cube-geometry.d.ts +3 -3
  41. package/dist/geometries/cube-geometry.d.ts.map +1 -1
  42. package/dist/geometry/geometry.d.ts.map +1 -1
  43. package/dist/geometry/geometry.js +3 -2
  44. package/dist/geometry/geometry.js.map +1 -1
  45. package/dist/index.cjs +581 -251
  46. package/dist/index.cjs.map +4 -4
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/model/model.d.ts +4 -25
  51. package/dist/model/model.d.ts.map +1 -1
  52. package/dist/model/model.js +26 -71
  53. package/dist/model/model.js.map +1 -1
  54. package/dist/models/billboard-texture-model.d.ts.map +1 -1
  55. package/dist/models/billboard-texture-model.js +6 -4
  56. package/dist/models/billboard-texture-model.js.map +1 -1
  57. package/dist/modules/picking/legacy-picking-manager.d.ts +1 -1
  58. package/dist/modules/picking/legacy-picking-manager.d.ts.map +1 -1
  59. package/dist/modules/picking/legacy-picking-manager.js +1 -1
  60. package/dist/modules/picking/legacy-picking-manager.js.map +1 -1
  61. package/dist/modules/picking/picking-manager.d.ts +2 -2
  62. package/dist/modules/picking/picking-manager.d.ts.map +1 -1
  63. package/dist/modules/picking/picking-manager.js +2 -2
  64. package/dist/modules/picking/picking-manager.js.map +1 -1
  65. package/dist/passes/get-fragment-shader.js +2 -2
  66. package/dist/passes/shader-pass-renderer.d.ts +4 -4
  67. package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
  68. package/dist/passes/shader-pass-renderer.js +15 -5
  69. package/dist/passes/shader-pass-renderer.js.map +1 -1
  70. package/dist/shader-inputs.js +1 -1
  71. package/dist/shader-inputs.js.map +1 -1
  72. package/dist/utils/buffer-layout-helper.d.ts +12 -0
  73. package/dist/utils/buffer-layout-helper.d.ts.map +1 -0
  74. package/dist/utils/buffer-layout-helper.js +41 -0
  75. package/dist/utils/buffer-layout-helper.js.map +1 -0
  76. package/dist/utils/buffer-layout-order.d.ts +3 -0
  77. package/dist/utils/buffer-layout-order.d.ts.map +1 -0
  78. package/dist/utils/buffer-layout-order.js +16 -0
  79. package/dist/utils/buffer-layout-order.js.map +1 -0
  80. package/package.json +4 -4
  81. package/src/animation-loop/animation-loop.ts +31 -71
  82. package/src/animation-loop/animation-props.ts +3 -5
  83. package/src/animation-loop/make-animation-loop.ts +41 -9
  84. package/src/async-texture/async-texture.ts +386 -23
  85. package/src/async-texture/texture-setters.ts.disabled +296 -0
  86. package/src/compute/computation.ts +3 -3
  87. package/src/compute/swap.ts +7 -2
  88. package/src/compute/texture-transform.ts +4 -2
  89. package/src/debug/copy-texture-to-image.ts +52 -2
  90. package/src/factories/pipeline-factory.ts +122 -26
  91. package/src/factories/shader-factory.ts +43 -7
  92. package/src/geometry/geometry.ts +3 -2
  93. package/src/index.ts +12 -0
  94. package/src/model/model.ts +31 -86
  95. package/src/models/billboard-texture-model.ts +6 -4
  96. package/src/modules/picking/legacy-picking-manager.ts +2 -2
  97. package/src/modules/picking/picking-manager.ts +3 -3
  98. package/src/passes/get-fragment-shader.ts +2 -2
  99. package/src/passes/shader-pass-renderer.ts +18 -8
  100. package/src/shader-inputs.ts +1 -1
  101. package/src/utils/buffer-layout-helper.ts +51 -0
  102. package/src/utils/buffer-layout-order.ts +26 -0
package/dist/dist.dev.js CHANGED
@@ -481,25 +481,7 @@ var __exports__ = (() => {
481
481
 
482
482
  // src/animation-loop/animation-loop.ts
483
483
  var statIdCounter = 0;
484
- var DEFAULT_ANIMATION_LOOP_PROPS = {
485
- device: null,
486
- onAddHTML: () => "",
487
- onInitialize: async () => {
488
- return null;
489
- },
490
- onRender: () => {
491
- },
492
- onFinalize: () => {
493
- },
494
- onError: (error) => console.error(error),
495
- // eslint-disable-line no-console
496
- stats: import_core.luma.stats.get(`animation-loop-${statIdCounter++}`),
497
- // view parameters
498
- useDevicePixels: true,
499
- autoResizeViewport: false,
500
- autoResizeDrawingBuffer: false
501
- };
502
- var AnimationLoop = class {
484
+ var _AnimationLoop = class {
503
485
  device = null;
504
486
  canvas = null;
505
487
  props;
@@ -523,21 +505,16 @@ var __exports__ = (() => {
523
505
  * @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
524
506
  */
525
507
  constructor(props) {
526
- this.props = { ...DEFAULT_ANIMATION_LOOP_PROPS, ...props };
508
+ this.props = { ..._AnimationLoop.defaultAnimationLoopProps, ...props };
527
509
  props = this.props;
528
510
  if (!props.device) {
529
511
  throw new Error("No device provided");
530
512
  }
531
- const { useDevicePixels = true } = this.props;
532
513
  this.stats = props.stats || new Stats({ id: "animation-loop-stats" });
533
514
  this.cpuTime = this.stats.get("CPU Time");
534
515
  this.gpuTime = this.stats.get("GPU Time");
535
516
  this.frameRate = this.stats.get("Frame Rate");
536
- this.setProps({
537
- autoResizeViewport: props.autoResizeViewport,
538
- autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
539
- useDevicePixels
540
- });
517
+ this.setProps({ autoResizeViewport: props.autoResizeViewport });
541
518
  this.start = this.start.bind(this);
542
519
  this.stop = this.stop.bind(this);
543
520
  this._onMousemove = this._onMousemove.bind(this);
@@ -551,37 +528,19 @@ var __exports__ = (() => {
551
528
  delete() {
552
529
  this.destroy();
553
530
  }
554
- setError(error) {
531
+ reportError(error) {
555
532
  this.props.onError(error);
556
- this._error = Error();
557
- const canvas2 = this.device?.canvasContext?.canvas;
558
- if (canvas2 instanceof HTMLCanvasElement) {
559
- const errorDiv = document.createElement("h1");
560
- errorDiv.innerHTML = error.message;
561
- errorDiv.style.position = "absolute";
562
- errorDiv.style.top = "20%";
563
- errorDiv.style.left = "10px";
564
- errorDiv.style.color = "black";
565
- errorDiv.style.backgroundColor = "red";
566
- document.body.appendChild(errorDiv);
567
- }
533
+ this._error = error;
568
534
  }
569
535
  /** Flags this animation loop as needing redraw */
570
536
  setNeedsRedraw(reason) {
571
537
  this.needsRedraw = this.needsRedraw || reason;
572
538
  return this;
573
539
  }
574
- /** TODO - move these props to CanvasContext? */
575
540
  setProps(props) {
576
541
  if ("autoResizeViewport" in props) {
577
542
  this.props.autoResizeViewport = props.autoResizeViewport || false;
578
543
  }
579
- if ("autoResizeDrawingBuffer" in props) {
580
- this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer || false;
581
- }
582
- if ("useDevicePixels" in props) {
583
- this.props.useDevicePixels = props.useDevicePixels || false;
584
- }
585
544
  return this;
586
545
  }
587
546
  /** Starts a render loop if not already running */
@@ -676,7 +635,6 @@ var __exports__ = (() => {
676
635
  this._startEventHandling();
677
636
  this._initializeAnimationProps();
678
637
  this._updateAnimationProps();
679
- this._resizeCanvasDrawingBuffer();
680
638
  this._resizeViewport();
681
639
  }
682
640
  _setDisplay(display) {
@@ -723,22 +681,24 @@ var __exports__ = (() => {
723
681
  this.needsRedraw = false;
724
682
  }
725
683
  _setupFrame() {
726
- this._resizeCanvasDrawingBuffer();
727
684
  this._resizeViewport();
728
685
  }
729
686
  // Initialize the object that will be passed to app callbacks
730
687
  _initializeAnimationProps() {
731
- const canvas2 = this.device?.canvasContext?.canvas;
732
- if (!this.device || !canvas2) {
688
+ const canvasContext = this.device?.getDefaultCanvasContext();
689
+ if (!this.device || !canvasContext) {
733
690
  throw new Error("loop");
734
691
  }
692
+ const canvas2 = canvasContext?.canvas;
693
+ const useDevicePixels = canvasContext.props.useDevicePixels;
735
694
  this.animationProps = {
736
695
  animationLoop: this,
737
696
  device: this.device,
697
+ canvasContext,
738
698
  canvas: canvas2,
699
+ // @ts-expect-error Deprecated
700
+ useDevicePixels,
739
701
  timeline: this.timeline,
740
- // Initial values
741
- useDevicePixels: this.props.useDevicePixels,
742
702
  needsRedraw: false,
743
703
  // Placeholders
744
704
  width: 1,
@@ -791,7 +751,7 @@ var __exports__ = (() => {
791
751
  if (!this.device) {
792
752
  throw new Error("No device provided");
793
753
  }
794
- this.canvas = this.device.canvasContext?.canvas || null;
754
+ this.canvas = this.device.getDefaultCanvasContext().canvas || null;
795
755
  }
796
756
  _createInfoDiv() {
797
757
  if (this.canvas && this.props.onAddHTML) {
@@ -818,9 +778,9 @@ var __exports__ = (() => {
818
778
  if (!this.device) {
819
779
  return { width: 1, height: 1, aspect: 1 };
820
780
  }
821
- const [width, height] = this.device?.canvasContext?.getPixelSize() || [1, 1];
781
+ const [width, height] = this.device?.getDefaultCanvasContext().getDevicePixelSize() || [1, 1];
822
782
  let aspect = 1;
823
- const canvas2 = this.device?.canvasContext?.canvas;
783
+ const canvas2 = this.device?.getDefaultCanvasContext().canvas;
824
784
  if (canvas2 && canvas2.clientHeight) {
825
785
  aspect = canvas2.clientWidth / canvas2.clientHeight;
826
786
  } else if (width > 0 && height > 0) {
@@ -828,7 +788,7 @@ var __exports__ = (() => {
828
788
  }
829
789
  return { width, height, aspect };
830
790
  }
831
- /** Default viewport setup */
791
+ /** @deprecated Default viewport setup */
832
792
  _resizeViewport() {
833
793
  if (this.props.autoResizeViewport && this.device.gl) {
834
794
  this.device.gl.viewport(
@@ -841,15 +801,6 @@ var __exports__ = (() => {
841
801
  );
842
802
  }
843
803
  }
844
- /**
845
- * Resize the render buffer of the canvas to match canvas client size
846
- * Optionally multiplying with devicePixel ratio
847
- */
848
- _resizeCanvasDrawingBuffer() {
849
- if (this.props.autoResizeDrawingBuffer) {
850
- this.device?.canvasContext?.resize({ useDevicePixels: this.props.useDevicePixels });
851
- }
852
- }
853
804
  _beginFrameTimers() {
854
805
  this.frameRate.timeEnd();
855
806
  this.frameRate.timeStart();
@@ -874,6 +825,21 @@ var __exports__ = (() => {
874
825
  this._getAnimationProps()._mousePosition = null;
875
826
  }
876
827
  };
828
+ var AnimationLoop = _AnimationLoop;
829
+ __publicField(AnimationLoop, "defaultAnimationLoopProps", {
830
+ device: null,
831
+ onAddHTML: () => "",
832
+ onInitialize: async () => null,
833
+ onRender: () => {
834
+ },
835
+ onFinalize: () => {
836
+ },
837
+ onError: (error) => console.error(error),
838
+ // eslint-disable-line no-console
839
+ stats: import_core.luma.stats.get(`animation-loop-${statIdCounter++}`),
840
+ // view parameters
841
+ autoResizeViewport: false
842
+ });
877
843
 
878
844
  // src/animation-loop/make-animation-loop.ts
879
845
  var import_core2 = __toESM(require_core(), 1);
@@ -884,8 +850,14 @@ var __exports__ = (() => {
884
850
  ...props,
885
851
  device,
886
852
  async onInitialize(animationProps) {
887
- renderLoop = new AnimationLoopTemplateCtor(animationProps);
888
- return await renderLoop?.onInitialize(animationProps);
853
+ clearError(animationProps.animationLoop.device);
854
+ try {
855
+ renderLoop = new AnimationLoopTemplateCtor(animationProps);
856
+ return await renderLoop?.onInitialize(animationProps);
857
+ } catch (error) {
858
+ setError(animationProps.animationLoop.device, error);
859
+ return null;
860
+ }
889
861
  },
890
862
  onRender: (animationProps) => renderLoop?.onRender(animationProps),
891
863
  onFinalize: (animationProps) => renderLoop?.onFinalize(animationProps)
@@ -895,9 +867,32 @@ var __exports__ = (() => {
895
867
  };
896
868
  return animationLoop;
897
869
  }
870
+ function setError(device, error) {
871
+ const canvas2 = device?.getDefaultCanvasContext().canvas;
872
+ if (canvas2 instanceof HTMLCanvasElement) {
873
+ canvas2.style.overflow = "visible";
874
+ let errorDiv = document.getElementById("animation-loop-error");
875
+ errorDiv?.remove();
876
+ errorDiv = document.createElement("h1");
877
+ errorDiv.id = "animation-loop-error";
878
+ errorDiv.innerHTML = error.message;
879
+ errorDiv.style.position = "absolute";
880
+ errorDiv.style.top = "10px";
881
+ errorDiv.style.left = "10px";
882
+ errorDiv.style.color = "black";
883
+ errorDiv.style.backgroundColor = "red";
884
+ canvas2.parentElement?.appendChild(errorDiv);
885
+ }
886
+ }
887
+ function clearError(device) {
888
+ const errorDiv = document.getElementById("animation-loop-error");
889
+ if (errorDiv) {
890
+ errorDiv.remove();
891
+ }
892
+ }
898
893
 
899
894
  // src/model/model.ts
900
- var import_core7 = __toESM(require_core(), 1);
895
+ var import_core9 = __toESM(require_core(), 1);
901
896
  var import_shadertools2 = __toESM(require_shadertools(), 1);
902
897
 
903
898
  // src/geometry/gpu-geometry.ts
@@ -1012,63 +1007,142 @@ var __exports__ = (() => {
1012
1007
  var _PipelineFactory = class {
1013
1008
  /** Get the singleton default pipeline factory for the specified device */
1014
1009
  static getDefaultPipelineFactory(device) {
1015
- device._lumaData.defaultPipelineFactory = device._lumaData.defaultPipelineFactory || new _PipelineFactory(device);
1016
- return device._lumaData.defaultPipelineFactory;
1010
+ device._lumaData["defaultPipelineFactory"] = device._lumaData["defaultPipelineFactory"] || new _PipelineFactory(device);
1011
+ return device._lumaData["defaultPipelineFactory"];
1017
1012
  }
1018
1013
  device;
1014
+ cachingEnabled;
1019
1015
  destroyPolicy;
1016
+ debug;
1020
1017
  _hashCounter = 0;
1021
1018
  _hashes = {};
1022
1019
  _renderPipelineCache = {};
1023
1020
  _computePipelineCache = {};
1021
+ get [Symbol.toStringTag]() {
1022
+ return "PipelineFactory";
1023
+ }
1024
+ toString() {
1025
+ return `PipelineFactory(${this.device.id})`;
1026
+ }
1024
1027
  constructor(device) {
1025
1028
  this.device = device;
1026
- this.destroyPolicy = device.props._factoryDestroyPolicy;
1029
+ this.cachingEnabled = device.props._cachePipelines;
1030
+ this.destroyPolicy = device.props._cacheDestroyPolicy;
1031
+ this.debug = device.props.debugFactories;
1027
1032
  }
1028
- /** Return a RenderPipeline matching props. Reuses a similar pipeline if already created. */
1033
+ /** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
1029
1034
  createRenderPipeline(props) {
1035
+ if (!this.cachingEnabled) {
1036
+ return this.device.createRenderPipeline(props);
1037
+ }
1030
1038
  const allProps = { ...import_core4.RenderPipeline.defaultProps, ...props };
1039
+ const cache = this._renderPipelineCache;
1031
1040
  const hash = this._hashRenderPipeline(allProps);
1032
- if (!this._renderPipelineCache[hash]) {
1033
- const pipeline = this.device.createRenderPipeline({
1041
+ let pipeline = cache[hash]?.pipeline;
1042
+ if (!pipeline) {
1043
+ pipeline = this.device.createRenderPipeline({
1034
1044
  ...allProps,
1035
- id: allProps.id ? `${allProps.id}-cached` : void 0
1045
+ id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached")
1036
1046
  });
1037
1047
  pipeline.hash = hash;
1038
- this._renderPipelineCache[hash] = { pipeline, useCount: 0 };
1048
+ cache[hash] = { pipeline, useCount: 1 };
1049
+ if (this.debug) {
1050
+ import_core4.log.warn(`${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
1051
+ }
1052
+ } else {
1053
+ cache[hash].useCount++;
1054
+ if (this.debug) {
1055
+ import_core4.log.warn(
1056
+ `${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`
1057
+ )();
1058
+ }
1039
1059
  }
1040
- this._renderPipelineCache[hash].useCount++;
1041
- return this._renderPipelineCache[hash].pipeline;
1060
+ return pipeline;
1042
1061
  }
1062
+ /** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
1043
1063
  createComputePipeline(props) {
1064
+ if (!this.cachingEnabled) {
1065
+ return this.device.createComputePipeline(props);
1066
+ }
1044
1067
  const allProps = { ...import_core4.ComputePipeline.defaultProps, ...props };
1068
+ const cache = this._computePipelineCache;
1045
1069
  const hash = this._hashComputePipeline(allProps);
1046
- if (!this._computePipelineCache[hash]) {
1047
- const pipeline = this.device.createComputePipeline({
1070
+ let pipeline = cache[hash]?.pipeline;
1071
+ if (!pipeline) {
1072
+ pipeline = this.device.createComputePipeline({
1048
1073
  ...allProps,
1049
1074
  id: allProps.id ? `${allProps.id}-cached` : void 0
1050
1075
  });
1051
1076
  pipeline.hash = hash;
1052
- this._computePipelineCache[hash] = { pipeline, useCount: 0 };
1077
+ cache[hash] = { pipeline, useCount: 1 };
1078
+ if (this.debug) {
1079
+ import_core4.log.warn(`${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
1080
+ }
1081
+ } else {
1082
+ cache[hash].useCount++;
1083
+ if (this.debug) {
1084
+ import_core4.log.warn(
1085
+ `${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`
1086
+ )();
1087
+ }
1053
1088
  }
1054
- this._computePipelineCache[hash].useCount++;
1055
- return this._computePipelineCache[hash].pipeline;
1089
+ return pipeline;
1056
1090
  }
1057
1091
  release(pipeline) {
1092
+ if (!this.cachingEnabled) {
1093
+ pipeline.destroy();
1094
+ return;
1095
+ }
1096
+ const cache = this._getCache(pipeline);
1058
1097
  const hash = pipeline.hash;
1059
- const cache = pipeline instanceof import_core4.ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
1060
1098
  cache[hash].useCount--;
1061
1099
  if (cache[hash].useCount === 0) {
1062
- if (this.destroyPolicy === "unused") {
1063
- cache[hash].pipeline.destroy();
1064
- delete cache[hash];
1100
+ this._destroyPipeline(pipeline);
1101
+ if (this.debug) {
1102
+ import_core4.log.warn(`${this}: ${pipeline} released and destroyed`)();
1065
1103
  }
1104
+ } else if (cache[hash].useCount < 0) {
1105
+ import_core4.log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
1106
+ cache[hash].useCount = 0;
1107
+ } else if (this.debug) {
1108
+ import_core4.log.warn(`${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
1066
1109
  }
1067
1110
  }
1068
1111
  // PRIVATE
1112
+ /** Destroy a cached pipeline, removing it from the cache (depending on destroy policy) */
1113
+ _destroyPipeline(pipeline) {
1114
+ const cache = this._getCache(pipeline);
1115
+ switch (this.destroyPolicy) {
1116
+ case "never":
1117
+ return false;
1118
+ case "unused":
1119
+ delete cache[pipeline.hash];
1120
+ pipeline.destroy();
1121
+ return true;
1122
+ }
1123
+ }
1124
+ /** Get the appropriate cache for the type of pipeline */
1125
+ _getCache(pipeline) {
1126
+ let cache;
1127
+ if (pipeline instanceof import_core4.ComputePipeline) {
1128
+ cache = this._computePipelineCache;
1129
+ }
1130
+ if (pipeline instanceof import_core4.RenderPipeline) {
1131
+ cache = this._renderPipelineCache;
1132
+ }
1133
+ if (!cache) {
1134
+ throw new Error(`${this}`);
1135
+ }
1136
+ if (!cache[pipeline.hash]) {
1137
+ throw new Error(`${this}: ${pipeline} matched incorrect entry`);
1138
+ }
1139
+ return cache;
1140
+ }
1141
+ /** Calculate a hash based on all the inputs for a compute pipeline */
1069
1142
  _hashComputePipeline(props) {
1143
+ const { type } = this.device;
1070
1144
  const shaderHash = this._getHash(props.shader.source);
1071
- return `${shaderHash}`;
1145
+ return `${type}/C/${shaderHash}`;
1072
1146
  }
1073
1147
  /** Calculate a hash based on all the inputs for a render pipeline */
1074
1148
  _hashRenderPipeline(props) {
@@ -1076,12 +1150,14 @@ var __exports__ = (() => {
1076
1150
  const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
1077
1151
  const varyingHash = "-";
1078
1152
  const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
1079
- switch (this.device.type) {
1153
+ const { type } = this.device;
1154
+ switch (type) {
1080
1155
  case "webgl":
1081
- return `${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
1156
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
1157
+ case "webgpu":
1082
1158
  default:
1083
1159
  const parameterHash = this._getHash(JSON.stringify(props.parameters));
1084
- return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
1160
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
1085
1161
  }
1086
1162
  }
1087
1163
  _getHash(key) {
@@ -1099,19 +1175,32 @@ var __exports__ = (() => {
1099
1175
  var _ShaderFactory = class {
1100
1176
  /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
1101
1177
  static getDefaultShaderFactory(device) {
1102
- device._lumaData.defaultShaderFactory ||= new _ShaderFactory(device);
1103
- return device._lumaData.defaultShaderFactory;
1178
+ device._lumaData["defaultShaderFactory"] ||= new _ShaderFactory(device);
1179
+ return device._lumaData["defaultShaderFactory"];
1104
1180
  }
1105
1181
  device;
1182
+ cachingEnabled;
1106
1183
  destroyPolicy;
1184
+ debug;
1107
1185
  _cache = {};
1186
+ get [Symbol.toStringTag]() {
1187
+ return "ShaderFactory";
1188
+ }
1189
+ toString() {
1190
+ return `${this[Symbol.toStringTag]}(${this.device.id})`;
1191
+ }
1108
1192
  /** @internal */
1109
1193
  constructor(device) {
1110
1194
  this.device = device;
1111
- this.destroyPolicy = device.props._factoryDestroyPolicy;
1195
+ this.cachingEnabled = device.props._cacheShaders;
1196
+ this.destroyPolicy = device.props._cacheDestroyPolicy;
1197
+ this.debug = true;
1112
1198
  }
1113
1199
  /** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
1114
1200
  createShader(props) {
1201
+ if (!this.cachingEnabled) {
1202
+ return this.device.createShader(props);
1203
+ }
1115
1204
  const key = this._hashShader(props);
1116
1205
  let cacheEntry = this._cache[key];
1117
1206
  if (!cacheEntry) {
@@ -1119,13 +1208,24 @@ var __exports__ = (() => {
1119
1208
  ...props,
1120
1209
  id: props.id ? `${props.id}-cached` : void 0
1121
1210
  });
1122
- this._cache[key] = cacheEntry = { shader, useCount: 0 };
1211
+ this._cache[key] = cacheEntry = { shader, useCount: 1 };
1212
+ if (this.debug) {
1213
+ import_core5.log.warn(`${this}: Created new shader ${shader.id}`)();
1214
+ }
1215
+ } else {
1216
+ cacheEntry.useCount++;
1217
+ if (this.debug) {
1218
+ import_core5.log.warn(`${this}: Reusing shader ${cacheEntry.shader.id} count=${cacheEntry.useCount}`)();
1219
+ }
1123
1220
  }
1124
- cacheEntry.useCount++;
1125
1221
  return cacheEntry.shader;
1126
1222
  }
1127
1223
  /** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
1128
1224
  release(shader) {
1225
+ if (!this.cachingEnabled) {
1226
+ shader.destroy();
1227
+ return;
1228
+ }
1129
1229
  const key = this._hashShader(shader);
1130
1230
  const cacheEntry = this._cache[key];
1131
1231
  if (cacheEntry) {
@@ -1134,7 +1234,14 @@ var __exports__ = (() => {
1134
1234
  if (this.destroyPolicy === "unused") {
1135
1235
  delete this._cache[key];
1136
1236
  cacheEntry.shader.destroy();
1237
+ if (this.debug) {
1238
+ import_core5.log.warn(`${this}: Releasing shader ${shader.id}, destroyed`)();
1239
+ }
1137
1240
  }
1241
+ } else if (cacheEntry.useCount < 0) {
1242
+ throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
1243
+ } else if (this.debug) {
1244
+ import_core5.log.warn(`${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
1138
1245
  }
1139
1246
  }
1140
1247
  }
@@ -1251,8 +1358,59 @@ var __exports__ = (() => {
1251
1358
  return false;
1252
1359
  }
1253
1360
 
1254
- // src/shader-inputs.ts
1361
+ // src/utils/buffer-layout-helper.ts
1255
1362
  var import_core6 = __toESM(require_core(), 1);
1363
+ var BufferLayoutHelper = class {
1364
+ bufferLayouts;
1365
+ constructor(bufferLayouts) {
1366
+ this.bufferLayouts = bufferLayouts;
1367
+ }
1368
+ getBufferLayout(name) {
1369
+ return this.bufferLayouts.find((layout) => layout.name === name) || null;
1370
+ }
1371
+ /** Get attribute names from a BufferLayout */
1372
+ getAttributeNamesForBuffer(bufferLayout) {
1373
+ return bufferLayout.attributes ? bufferLayout.attributes?.map((layout) => layout.attribute) : [bufferLayout.name];
1374
+ }
1375
+ mergeBufferLayouts(bufferLayouts1, bufferLayouts2) {
1376
+ const mergedLayouts = [...bufferLayouts1];
1377
+ for (const attribute of bufferLayouts2) {
1378
+ const index = mergedLayouts.findIndex((attribute2) => attribute2.name === attribute.name);
1379
+ if (index < 0) {
1380
+ mergedLayouts.push(attribute);
1381
+ } else {
1382
+ mergedLayouts[index] = attribute;
1383
+ }
1384
+ }
1385
+ return mergedLayouts;
1386
+ }
1387
+ getBufferIndex(bufferName) {
1388
+ const bufferIndex = this.bufferLayouts.findIndex((layout) => layout.name === bufferName);
1389
+ if (bufferIndex === -1) {
1390
+ import_core6.log.warn(`BufferLayout: Missing buffer for "${bufferName}".`)();
1391
+ }
1392
+ return bufferIndex;
1393
+ }
1394
+ };
1395
+
1396
+ // src/utils/buffer-layout-order.ts
1397
+ function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
1398
+ const shaderLayoutMap = Object.fromEntries(
1399
+ shaderLayout.attributes.map((attr) => [attr.name, attr.location])
1400
+ );
1401
+ const sortedLayout = bufferLayout.slice();
1402
+ sortedLayout.sort((a, b) => {
1403
+ const attributeNamesA = a.attributes ? a.attributes.map((attr) => attr.attribute) : [a.name];
1404
+ const attributeNamesB = b.attributes ? b.attributes.map((attr) => attr.attribute) : [b.name];
1405
+ const minLocationA = Math.min(...attributeNamesA.map((name) => shaderLayoutMap[name]));
1406
+ const minLocationB = Math.min(...attributeNamesB.map((name) => shaderLayoutMap[name]));
1407
+ return minLocationA - minLocationB;
1408
+ });
1409
+ return sortedLayout;
1410
+ }
1411
+
1412
+ // src/shader-inputs.ts
1413
+ var import_core7 = __toESM(require_core(), 1);
1256
1414
  var import_shadertools = __toESM(require_shadertools(), 1);
1257
1415
 
1258
1416
  // ../../node_modules/@math.gl/types/dist/is-array.js
@@ -1315,14 +1473,14 @@ var __exports__ = (() => {
1315
1473
  for (const resolvedModule of resolvedModules) {
1316
1474
  modules[resolvedModule.name] = resolvedModule;
1317
1475
  }
1318
- import_core6.log.log(1, "Creating ShaderInputs with modules", Object.keys(modules))();
1476
+ import_core7.log.log(1, "Creating ShaderInputs with modules", Object.keys(modules))();
1319
1477
  this.modules = modules;
1320
1478
  this.moduleUniforms = {};
1321
1479
  this.moduleBindings = {};
1322
1480
  for (const [name, module] of Object.entries(modules)) {
1323
1481
  this._addModule(module);
1324
1482
  if (module.name && name !== module.name && !this.options.disableWarnings) {
1325
- import_core6.log.warn(`Module name: ${name} vs ${module.name}`)();
1483
+ import_core7.log.warn(`Module name: ${name} vs ${module.name}`)();
1326
1484
  }
1327
1485
  }
1328
1486
  }
@@ -1339,7 +1497,7 @@ var __exports__ = (() => {
1339
1497
  const module = this.modules[moduleName];
1340
1498
  if (!module) {
1341
1499
  if (!this.options.disableWarnings) {
1342
- import_core6.log.warn(`Module ${name} not found`)();
1500
+ import_core7.log.warn(`Module ${name} not found`)();
1343
1501
  }
1344
1502
  continue;
1345
1503
  }
@@ -1391,6 +1549,9 @@ var __exports__ = (() => {
1391
1549
  }
1392
1550
  };
1393
1551
 
1552
+ // src/async-texture/async-texture.ts
1553
+ var import_core8 = __toESM(require_core(), 1);
1554
+
1394
1555
  // src/application-utils/load-file.ts
1395
1556
  var pathPrefix = "";
1396
1557
  function setPathPrefix(prefix) {
@@ -1418,9 +1579,12 @@ var __exports__ = (() => {
1418
1579
  }
1419
1580
 
1420
1581
  // src/async-texture/async-texture.ts
1421
- var AsyncTexture = class {
1582
+ var TextureCubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
1583
+ var CubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
1584
+ var _AsyncTexture = class {
1422
1585
  device;
1423
1586
  id;
1587
+ props;
1424
1588
  // TODO - should we type these as possibly `null`? It will make usage harder?
1425
1589
  // @ts-expect-error
1426
1590
  texture;
@@ -1443,9 +1607,15 @@ var __exports__ = (() => {
1443
1607
  }
1444
1608
  constructor(device, props) {
1445
1609
  this.device = device;
1446
- this.id = props.id || uid("async-texture");
1610
+ const id = uid("async-texture");
1611
+ this.props = { ..._AsyncTexture.defaultProps, id, ...props };
1612
+ this.id = this.props.id;
1613
+ props = { ...props };
1447
1614
  if (typeof props?.data === "string" && props.dimension === "2d") {
1448
- props = { ...props, data: loadImageBitmap(props.data) };
1615
+ props.data = loadImageBitmap(props.data);
1616
+ }
1617
+ if (props.mipmaps) {
1618
+ props.mipLevels = "auto";
1449
1619
  }
1450
1620
  this.ready = new Promise((resolve, reject) => {
1451
1621
  this.resolveReady = () => {
@@ -1457,22 +1627,50 @@ var __exports__ = (() => {
1457
1627
  this.initAsync(props);
1458
1628
  }
1459
1629
  async initAsync(props) {
1630
+ let resolveReady;
1631
+ let rejectReady;
1460
1632
  const asyncData = props.data;
1461
- let data;
1462
- try {
1463
- data = await awaitAllPromises(asyncData);
1464
- } catch (error) {
1465
- this.rejectReady(error);
1466
- }
1633
+ const data = await awaitAllPromises(asyncData).then(resolveReady, rejectReady);
1467
1634
  if (this.destroyed) {
1468
1635
  return;
1469
1636
  }
1470
- const syncProps = { ...props, data };
1637
+ const size = this.props.width && this.props.height ? { width: this.props.width, height: this.props.height } : this.getTextureDataSize(data);
1638
+ if (!size) {
1639
+ throw new Error("Texture size could not be determined");
1640
+ }
1641
+ const syncProps = { ...size, ...props, data: void 0, mipLevels: 1 };
1642
+ const maxMips = this.device.getMipLevelCount(syncProps.width, syncProps.height);
1643
+ syncProps.mipLevels = this.props.mipLevels === "auto" ? maxMips : Math.min(maxMips, this.props.mipLevels);
1471
1644
  this.texture = this.device.createTexture(syncProps);
1472
1645
  this.sampler = this.texture.sampler;
1473
1646
  this.view = this.texture.view;
1474
1647
  this.isReady = true;
1475
- this.resolveReady();
1648
+ if (props.data) {
1649
+ switch (this.props.dimension) {
1650
+ case "1d":
1651
+ this._setTexture1DData(this.texture, data);
1652
+ break;
1653
+ case "2d":
1654
+ this._setTexture2DData(data);
1655
+ break;
1656
+ case "3d":
1657
+ this._setTexture3DData(this.texture, data);
1658
+ break;
1659
+ case "2d-array":
1660
+ this._setTextureArrayData(this.texture, data);
1661
+ break;
1662
+ case "cube":
1663
+ this._setTextureCubeData(this.texture, data);
1664
+ break;
1665
+ case "cube-array":
1666
+ this._setTextureCubeArrayData(this.texture, data);
1667
+ break;
1668
+ }
1669
+ }
1670
+ if (this.props.mipmaps) {
1671
+ this.generateMipmaps();
1672
+ }
1673
+ import_core8.log.info(1, `${this} loaded`);
1476
1674
  }
1477
1675
  destroy() {
1478
1676
  if (this.texture) {
@@ -1481,10 +1679,20 @@ var __exports__ = (() => {
1481
1679
  }
1482
1680
  this.destroyed = true;
1483
1681
  }
1682
+ generateMipmaps() {
1683
+ this.texture.generateMipmapsWebGL();
1684
+ }
1685
+ /** Set sampler or create and set new Sampler from SamplerProps */
1686
+ setSampler(sampler = {}) {
1687
+ this.texture.setSampler(
1688
+ sampler instanceof import_core8.Sampler ? sampler : this.device.createSampler(sampler)
1689
+ );
1690
+ }
1484
1691
  /**
1485
1692
  * Textures are immutable and cannot be resized after creation,
1486
1693
  * but we can create a similar texture with the same parameters but a new size.
1487
1694
  * @note Does not copy contents of the texture
1695
+ * @note Mipmaps may need to be regenerated after resizing / setting new data
1488
1696
  * @todo Abort pending promise and create a texture with the new size?
1489
1697
  */
1490
1698
  resize(size) {
@@ -1501,7 +1709,163 @@ var __exports__ = (() => {
1501
1709
  }
1502
1710
  return true;
1503
1711
  }
1712
+ /** Check if texture data is a typed array */
1713
+ isTextureLevelData(data) {
1714
+ const typedArray = data?.data;
1715
+ return ArrayBuffer.isView(typedArray);
1716
+ }
1717
+ /** Get the size of the texture described by the provided TextureData */
1718
+ getTextureDataSize(data) {
1719
+ if (!data) {
1720
+ return null;
1721
+ }
1722
+ if (ArrayBuffer.isView(data)) {
1723
+ return null;
1724
+ }
1725
+ if (Array.isArray(data)) {
1726
+ return this.getTextureDataSize(data[0]);
1727
+ }
1728
+ if (this.device.isExternalImage(data)) {
1729
+ return this.device.getExternalImageSize(data);
1730
+ }
1731
+ if (data && typeof data === "object" && data.constructor === Object) {
1732
+ const textureDataArray = Object.values(data);
1733
+ const untypedData = textureDataArray[0];
1734
+ return { width: untypedData.width, height: untypedData.height };
1735
+ }
1736
+ throw new Error("texture size deduction failed");
1737
+ }
1738
+ /** Convert luma.gl cubemap face constants to depth index */
1739
+ getCubeFaceDepth(face) {
1740
+ switch (face) {
1741
+ case "+X":
1742
+ return 0;
1743
+ case "-X":
1744
+ return 1;
1745
+ case "+Y":
1746
+ return 2;
1747
+ case "-Y":
1748
+ return 3;
1749
+ case "+Z":
1750
+ return 4;
1751
+ case "-Z":
1752
+ return 5;
1753
+ default:
1754
+ throw new Error(face);
1755
+ }
1756
+ }
1757
+ // EXPERIMENTAL
1758
+ setTextureData(data) {
1759
+ }
1760
+ /** Experimental: Set multiple mip levels */
1761
+ _setTexture1DData(texture, data) {
1762
+ throw new Error("setTexture1DData not supported in WebGL.");
1763
+ }
1764
+ /** Experimental: Set multiple mip levels */
1765
+ _setTexture2DData(lodData, depth = 0) {
1766
+ if (!this.texture) {
1767
+ throw new Error("Texture not initialized");
1768
+ }
1769
+ const lodArray = this._normalizeTextureData(lodData);
1770
+ if (lodArray.length > 1 && this.props.mipmaps !== false) {
1771
+ import_core8.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
1772
+ }
1773
+ for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
1774
+ const imageData = lodArray[mipLevel];
1775
+ if (this.device.isExternalImage(imageData)) {
1776
+ this.texture.copyExternalImage({ image: imageData, depth, mipLevel, flipY: true });
1777
+ } else {
1778
+ this.texture.copyImageData({ data: imageData.data, mipLevel });
1779
+ }
1780
+ }
1781
+ }
1782
+ /**
1783
+ * Experimental: Sets 3D texture data: multiple depth slices, multiple mip levels
1784
+ * @param data
1785
+ */
1786
+ _setTexture3DData(texture, data) {
1787
+ if (this.texture?.props.dimension !== "3d") {
1788
+ throw new Error(this.id);
1789
+ }
1790
+ for (let depth = 0; depth < data.length; depth++) {
1791
+ this._setTexture2DData(data[depth], depth);
1792
+ }
1793
+ }
1794
+ /**
1795
+ * Experimental: Set Cube texture data, multiple faces, multiple mip levels
1796
+ * @todo - could support TextureCubeArray with depth
1797
+ * @param data
1798
+ * @param index
1799
+ */
1800
+ _setTextureCubeData(texture, data) {
1801
+ if (this.texture?.props.dimension !== "cube") {
1802
+ throw new Error(this.id);
1803
+ }
1804
+ for (const [face, faceData] of Object.entries(data)) {
1805
+ const faceDepth = CubeFaces.indexOf(face);
1806
+ this._setTexture2DData(faceData, faceDepth);
1807
+ }
1808
+ }
1809
+ /**
1810
+ * Experimental: Sets texture array data, multiple levels, multiple depth slices
1811
+ * @param data
1812
+ */
1813
+ _setTextureArrayData(texture, data) {
1814
+ if (this.texture?.props.dimension !== "2d-array") {
1815
+ throw new Error(this.id);
1816
+ }
1817
+ for (let depth = 0; depth < data.length; depth++) {
1818
+ this._setTexture2DData(data[depth], depth);
1819
+ }
1820
+ }
1821
+ /**
1822
+ * Experimental: Sets texture cube array, multiple faces, multiple levels, multiple mip levels
1823
+ * @param data
1824
+ */
1825
+ _setTextureCubeArrayData(texture, data) {
1826
+ throw new Error("setTextureCubeArrayData not supported in WebGL2.");
1827
+ }
1828
+ /** Experimental */
1829
+ _setTextureCubeFaceData(texture, lodData, face, depth = 0) {
1830
+ if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
1831
+ import_core8.log.warn(`${this.id} has mipmap and multiple LODs.`)();
1832
+ }
1833
+ const faceDepth = TextureCubeFaces.indexOf(face);
1834
+ this._setTexture2DData(lodData, faceDepth);
1835
+ }
1836
+ /**
1837
+ * Normalize TextureData to an array of TextureImageData / ExternalImages
1838
+ * @param data
1839
+ * @param options
1840
+ * @returns array of TextureImageData / ExternalImages
1841
+ */
1842
+ _normalizeTextureData(data) {
1843
+ const options = this.texture;
1844
+ let mipLevelArray;
1845
+ if (ArrayBuffer.isView(data)) {
1846
+ mipLevelArray = [
1847
+ {
1848
+ // ts-expect-error does data really need to be Uint8ClampedArray?
1849
+ data,
1850
+ width: options.width,
1851
+ height: options.height
1852
+ // depth: options.depth
1853
+ }
1854
+ ];
1855
+ } else if (!Array.isArray(data)) {
1856
+ mipLevelArray = [data];
1857
+ } else {
1858
+ mipLevelArray = data;
1859
+ }
1860
+ return mipLevelArray;
1861
+ }
1504
1862
  };
1863
+ var AsyncTexture = _AsyncTexture;
1864
+ __publicField(AsyncTexture, "defaultProps", {
1865
+ ...import_core8.Texture.defaultProps,
1866
+ data: null,
1867
+ mipmaps: false
1868
+ });
1505
1869
  async function awaitAllPromises(x) {
1506
1870
  x = await x;
1507
1871
  if (Array.isArray(x)) {
@@ -1557,8 +1921,6 @@ var __exports__ = (() => {
1557
1921
  constantAttributes = {};
1558
1922
  /** Bindings (textures, samplers, uniform buffers) */
1559
1923
  bindings = {};
1560
- /** Sets uniforms @deprecated Use uniform buffers and setBindings() for portability*/
1561
- uniforms = {};
1562
1924
  /**
1563
1925
  * VertexArray
1564
1926
  * @note not implemented: if bufferLayout is updated, vertex array has to be rebuilt!
@@ -1576,7 +1938,6 @@ var __exports__ = (() => {
1576
1938
  _uniformStore;
1577
1939
  _attributeInfos = {};
1578
1940
  _gpuGeometry = null;
1579
- _getModuleUniforms;
1580
1941
  props;
1581
1942
  _pipelineNeedsUpdate = "newly created";
1582
1943
  _needsRedraw = "initializing";
@@ -1637,7 +1998,8 @@ var __exports__ = (() => {
1637
1998
  this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
1638
1999
  this.pipeline = this._updatePipeline();
1639
2000
  this.vertexArray = device.createVertexArray({
1640
- renderPipeline: this.pipeline
2001
+ shaderLayout: this.pipeline.shaderLayout,
2002
+ bufferLayout: this.pipeline.bufferLayout
1641
2003
  });
1642
2004
  if (this._gpuGeometry) {
1643
2005
  this._setGeometryAttributes(this._gpuGeometry);
@@ -1663,28 +2025,22 @@ var __exports__ = (() => {
1663
2025
  if (props.bindings) {
1664
2026
  this.setBindings(props.bindings);
1665
2027
  }
1666
- if (props.uniforms) {
1667
- this.setUniformsWebGL(props.uniforms);
1668
- }
1669
- if (props.moduleSettings) {
1670
- this.updateModuleSettingsWebGL(props.moduleSettings);
1671
- }
1672
2028
  if (props.transformFeedback) {
1673
2029
  this.transformFeedback = props.transformFeedback;
1674
2030
  }
1675
2031
  Object.seal(this);
1676
2032
  }
1677
2033
  destroy() {
1678
- if (this._destroyed)
1679
- return;
1680
- this.pipelineFactory.release(this.pipeline);
1681
- this.shaderFactory.release(this.pipeline.vs);
1682
- if (this.pipeline.fs) {
1683
- this.shaderFactory.release(this.pipeline.fs);
2034
+ if (!this._destroyed) {
2035
+ this.pipelineFactory.release(this.pipeline);
2036
+ this.shaderFactory.release(this.pipeline.vs);
2037
+ if (this.pipeline.fs) {
2038
+ this.shaderFactory.release(this.pipeline.fs);
2039
+ }
2040
+ this._uniformStore.destroy();
2041
+ this._gpuGeometry?.destroy();
2042
+ this._destroyed = true;
1684
2043
  }
1685
- this._uniformStore.destroy();
1686
- this._gpuGeometry?.destroy();
1687
- this._destroyed = true;
1688
2044
  }
1689
2045
  // Draw call
1690
2046
  /** Query redraw status. Clears the status. */
@@ -1707,7 +2063,7 @@ var __exports__ = (() => {
1707
2063
  draw(renderPass) {
1708
2064
  const loadingBinding = this._areBindingsLoading();
1709
2065
  if (loadingBinding) {
1710
- import_core7.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
2066
+ import_core9.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1711
2067
  return false;
1712
2068
  }
1713
2069
  try {
@@ -1725,9 +2081,6 @@ var __exports__ = (() => {
1725
2081
  this.pipeline.setBindings(syncBindings, {
1726
2082
  disableWarnings: this.props.disableWarnings
1727
2083
  });
1728
- if (!isObjectEmpty(this.uniforms)) {
1729
- this.pipeline.setUniformsWebGL(this.uniforms);
1730
- }
1731
2084
  const { indexBuffer } = this.vertexArray;
1732
2085
  const indexCount = indexBuffer ? indexBuffer.byteLength / (indexBuffer.indexType === "uint32" ? 4 : 2) : void 0;
1733
2086
  drawSuccess = this.pipeline.draw({
@@ -1768,7 +2121,7 @@ var __exports__ = (() => {
1768
2121
  const gpuGeometry = geometry && makeGPUGeometry(this.device, geometry);
1769
2122
  if (gpuGeometry) {
1770
2123
  this.setTopology(gpuGeometry.topology || "triangle-list");
1771
- const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
2124
+ const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
1772
2125
  this.bufferLayout = bufferLayoutHelper.mergeBufferLayouts(
1773
2126
  gpuGeometry.bufferLayout,
1774
2127
  this.bufferLayout
@@ -1794,12 +2147,13 @@ var __exports__ = (() => {
1794
2147
  * @note Triggers a pipeline rebuild / pipeline cache fetch
1795
2148
  */
1796
2149
  setBufferLayout(bufferLayout) {
1797
- const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
2150
+ const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
1798
2151
  this.bufferLayout = this._gpuGeometry ? bufferLayoutHelper.mergeBufferLayouts(bufferLayout, this._gpuGeometry.bufferLayout) : bufferLayout;
1799
2152
  this._setPipelineNeedsUpdate("bufferLayout");
1800
2153
  this.pipeline = this._updatePipeline();
1801
2154
  this.vertexArray = this.device.createVertexArray({
1802
- renderPipeline: this.pipeline
2155
+ shaderLayout: this.pipeline.shaderLayout,
2156
+ bufferLayout: this.pipeline.bufferLayout
1803
2157
  });
1804
2158
  if (this._gpuGeometry) {
1805
2159
  this._setGeometryAttributes(this._gpuGeometry);
@@ -1839,7 +2193,7 @@ var __exports__ = (() => {
1839
2193
  /** Set the shader inputs */
1840
2194
  setShaderInputs(shaderInputs) {
1841
2195
  this.shaderInputs = shaderInputs;
1842
- this._uniformStore = new import_core7.UniformStore(this.shaderInputs.modules);
2196
+ this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
1843
2197
  for (const [moduleName, module] of Object.entries(this.shaderInputs.modules)) {
1844
2198
  if (shaderModuleHasUniforms(module)) {
1845
2199
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
@@ -1882,21 +2236,21 @@ var __exports__ = (() => {
1882
2236
  */
1883
2237
  setAttributes(buffers, options) {
1884
2238
  const disableWarnings = options?.disableWarnings ?? this.props.disableWarnings;
1885
- if (buffers.indices) {
1886
- import_core7.log.warn(
2239
+ if (buffers["indices"]) {
2240
+ import_core9.log.warn(
1887
2241
  `Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`
1888
2242
  )();
1889
2243
  }
1890
- this.bufferLayout = (0, import_core7.sortedBufferLayoutByShaderSourceLocations)(
2244
+ this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(
1891
2245
  this.pipeline.shaderLayout,
1892
2246
  this.bufferLayout
1893
2247
  );
1894
- const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
2248
+ const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
1895
2249
  for (const [bufferName, buffer] of Object.entries(buffers)) {
1896
2250
  const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
1897
2251
  if (!bufferLayout) {
1898
2252
  if (!disableWarnings) {
1899
- import_core7.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2253
+ import_core9.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
1900
2254
  }
1901
2255
  continue;
1902
2256
  }
@@ -1911,7 +2265,7 @@ var __exports__ = (() => {
1911
2265
  }
1912
2266
  }
1913
2267
  if (!set && !disableWarnings) {
1914
- import_core7.log.warn(
2268
+ import_core9.log.warn(
1915
2269
  `Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`
1916
2270
  )();
1917
2271
  }
@@ -1932,44 +2286,14 @@ var __exports__ = (() => {
1932
2286
  if (attributeInfo) {
1933
2287
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
1934
2288
  } else if (!(options?.disableWarnings ?? this.props.disableWarnings)) {
1935
- import_core7.log.warn(
2289
+ import_core9.log.warn(
1936
2290
  `Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`
1937
2291
  )();
1938
2292
  }
1939
2293
  }
1940
2294
  this.setNeedsRedraw("constants");
1941
2295
  }
1942
- // DEPRECATED METHODS
1943
- /**
1944
- * Sets individual uniforms
1945
- * @deprecated WebGL only, use uniform buffers for portability
1946
- * @param uniforms
1947
- */
1948
- setUniforms(uniforms) {
1949
- this.setUniformsWebGL(uniforms);
1950
- }
1951
- /**
1952
- * Sets individual uniforms
1953
- * @deprecated WebGL only, use uniform buffers for portability
1954
- * @param uniforms
1955
- */
1956
- setUniformsWebGL(uniforms) {
1957
- if (!isObjectEmpty(uniforms)) {
1958
- this.pipeline.setUniformsWebGL(uniforms);
1959
- Object.assign(this.uniforms, uniforms);
1960
- }
1961
- this.setNeedsRedraw("uniforms");
1962
- }
1963
- /**
1964
- * @deprecated Updates shader module settings (which results in uniforms being set)
1965
- */
1966
- updateModuleSettingsWebGL(props) {
1967
- const { bindings, uniforms } = splitUniformsAndBindings(this._getModuleUniforms(props));
1968
- Object.assign(this.bindings, bindings);
1969
- Object.assign(this.uniforms, uniforms);
1970
- this.setNeedsRedraw("moduleSettings");
1971
- }
1972
- // Internal methods
2296
+ // INTERNAL METHODS
1973
2297
  /** Check that bindings are loaded. Returns id of first binding that is still loading. */
1974
2298
  _areBindingsLoading() {
1975
2299
  for (const binding of Object.values(this.bindings)) {
@@ -1997,16 +2321,16 @@ var __exports__ = (() => {
1997
2321
  _getBindingsUpdateTimestamp() {
1998
2322
  let timestamp = 0;
1999
2323
  for (const binding of Object.values(this.bindings)) {
2000
- if (binding instanceof import_core7.TextureView) {
2324
+ if (binding instanceof import_core9.TextureView) {
2001
2325
  timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
2002
- } else if (binding instanceof import_core7.Buffer || binding instanceof import_core7.Texture) {
2326
+ } else if (binding instanceof import_core9.Buffer || binding instanceof import_core9.Texture) {
2003
2327
  timestamp = Math.max(timestamp, binding.updateTimestamp);
2004
2328
  } else if (binding instanceof AsyncTexture) {
2005
2329
  timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
2006
2330
  // The texture will become available in the future
2007
2331
  Infinity
2008
2332
  );
2009
- } else if (!(binding instanceof import_core7.Sampler)) {
2333
+ } else if (!(binding instanceof import_core9.Sampler)) {
2010
2334
  timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
2011
2335
  }
2012
2336
  }
@@ -2041,7 +2365,7 @@ var __exports__ = (() => {
2041
2365
  let prevShaderVs = null;
2042
2366
  let prevShaderFs = null;
2043
2367
  if (this.pipeline) {
2044
- import_core7.log.log(
2368
+ import_core9.log.log(
2045
2369
  1,
2046
2370
  `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
2047
2371
  )();
@@ -2077,7 +2401,7 @@ var __exports__ = (() => {
2077
2401
  vs: vs3,
2078
2402
  fs: fs3
2079
2403
  });
2080
- this._attributeInfos = (0, import_core7.getAttributeInfosFromLayouts)(
2404
+ this._attributeInfos = (0, import_core9.getAttributeInfosFromLayouts)(
2081
2405
  this.pipeline.shaderLayout,
2082
2406
  this.bufferLayout
2083
2407
  );
@@ -2092,27 +2416,24 @@ var __exports__ = (() => {
2092
2416
  _lastLogTime = 0;
2093
2417
  _logOpen = false;
2094
2418
  _logDrawCallStart() {
2095
- const logDrawTimeout = import_core7.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2096
- if (import_core7.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2419
+ const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2420
+ if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2097
2421
  return;
2098
2422
  }
2099
2423
  this._lastLogTime = Date.now();
2100
2424
  this._logOpen = true;
2101
- import_core7.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core7.log.level <= 2 })();
2425
+ import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
2102
2426
  }
2103
2427
  _logDrawCallEnd() {
2104
2428
  if (this._logOpen) {
2105
2429
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
2106
- import_core7.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
2430
+ import_core9.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
2107
2431
  const uniformTable = this.shaderInputs.getDebugTable();
2108
- for (const [name, value] of Object.entries(this.uniforms)) {
2109
- uniformTable[name] = { value };
2110
- }
2111
- import_core7.log.table(LOG_DRAW_PRIORITY, uniformTable)();
2432
+ import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
2112
2433
  const attributeTable = this._getAttributeDebugTable();
2113
- import_core7.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2114
- import_core7.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2115
- import_core7.log.groupEnd(LOG_DRAW_PRIORITY)();
2434
+ import_core9.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2435
+ import_core9.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2436
+ import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
2116
2437
  this._logOpen = false;
2117
2438
  }
2118
2439
  }
@@ -2141,7 +2462,7 @@ var __exports__ = (() => {
2141
2462
  if (this.vertexArray.indexBuffer) {
2142
2463
  const { indexBuffer } = this.vertexArray;
2143
2464
  const values = indexBuffer.indexType === "uint32" ? new Uint32Array(indexBuffer.debugData) : new Uint16Array(indexBuffer.debugData);
2144
- table.indices = {
2465
+ table["indices"] = {
2145
2466
  name: "indices",
2146
2467
  type: indexBuffer.indexType,
2147
2468
  values: values.toString()
@@ -2151,14 +2472,14 @@ var __exports__ = (() => {
2151
2472
  }
2152
2473
  // TODO - fix typing of luma data types
2153
2474
  _getBufferOrConstantValues(attribute, dataType) {
2154
- const TypedArrayConstructor = (0, import_core7.getTypedArrayFromDataType)(dataType);
2155
- const typedArray = attribute instanceof import_core7.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2475
+ const TypedArrayConstructor = (0, import_core9.getTypedArrayConstructor)(dataType);
2476
+ const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2156
2477
  return typedArray.toString();
2157
2478
  }
2158
2479
  };
2159
2480
  var Model = _Model;
2160
2481
  __publicField(Model, "defaultProps", {
2161
- ...import_core7.RenderPipeline.defaultProps,
2482
+ ...import_core9.RenderPipeline.defaultProps,
2162
2483
  source: void 0,
2163
2484
  vs: null,
2164
2485
  fs: null,
@@ -2167,7 +2488,6 @@ var __exports__ = (() => {
2167
2488
  userData: {},
2168
2489
  defines: {},
2169
2490
  modules: [],
2170
- moduleSettings: void 0,
2171
2491
  geometry: null,
2172
2492
  indexBuffer: null,
2173
2493
  attributes: {},
@@ -2205,7 +2525,7 @@ var __exports__ = (() => {
2205
2525
  }
2206
2526
 
2207
2527
  // src/compute/buffer-transform.ts
2208
- var import_core8 = __toESM(require_core(), 1);
2528
+ var import_core10 = __toESM(require_core(), 1);
2209
2529
  var import_shadertools3 = __toESM(require_shadertools(), 1);
2210
2530
  var _BufferTransform = class {
2211
2531
  device;
@@ -2267,7 +2587,7 @@ var __exports__ = (() => {
2267
2587
  if (!result) {
2268
2588
  throw new Error("BufferTransform#getBuffer");
2269
2589
  }
2270
- if (result instanceof import_core8.Buffer) {
2590
+ if (result instanceof import_core10.Buffer) {
2271
2591
  return result.readAsync();
2272
2592
  }
2273
2593
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
@@ -2304,7 +2624,7 @@ var __exports__ = (() => {
2304
2624
  mipmapFilter: "nearest"
2305
2625
  });
2306
2626
  this.model = new Model(this.device, {
2307
- id: props.id || "texture-transform-model",
2627
+ id: props.id || uid("texture-transform-model"),
2308
2628
  fs: props.fs || (0, import_shadertools4.getPassthroughFS)({
2309
2629
  input: props.targetTextureVarying,
2310
2630
  inputChannels: props.targetTextureChannels,
@@ -2333,6 +2653,7 @@ var __exports__ = (() => {
2333
2653
  const renderPass = this.device.beginRenderPass({ framebuffer, ...options });
2334
2654
  this.model.draw(renderPass);
2335
2655
  renderPass.end();
2656
+ this.device.submit();
2336
2657
  }
2337
2658
  getTargetTexture() {
2338
2659
  const { targetTexture } = this.bindings[this.currentIndex];
@@ -2422,9 +2743,9 @@ var __exports__ = (() => {
2422
2743
  this.attributes[attributeName] = attribute;
2423
2744
  }
2424
2745
  }
2425
- if (this.indices && this.indices.isIndexed !== void 0) {
2746
+ if (this.indices && this.indices["isIndexed"] !== void 0) {
2426
2747
  this.indices = Object.assign({}, this.indices);
2427
- delete this.indices.isIndexed;
2748
+ delete this.indices["isIndexed"];
2428
2749
  }
2429
2750
  this.vertexCount = vertexCount || this._calculateVertexCount(this.attributes, this.indices);
2430
2751
  }
@@ -2550,7 +2871,7 @@ ${props.source}` };
2550
2871
  @group(0) @binding(1) var backgroundTextureSampler: sampler;
2551
2872
 
2552
2873
  fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
2553
- let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0) * 2;
2874
+ let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0);
2554
2875
  let texSize: vec2<f32> = vec2<f32>(f32(iTexSize.x), f32(iTexSize.y));
2555
2876
  var position: vec2<f32> = coordinates.xy / texSize;
2556
2877
  return position;
@@ -2572,7 +2893,7 @@ uniform sampler2D backgroundTexture;
2572
2893
  out vec4 fragColor;
2573
2894
 
2574
2895
  vec2 billboardTexture_getTextureUV() {
2575
- ivec2 iTexSize = textureDimensions(backgroundTexture, 0) * 2;
2896
+ ivec2 iTexSize = textureSize(backgroundTexture, 0);
2576
2897
  vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
2577
2898
  vec2 position = gl_FragCoord.xy / texSize;
2578
2899
  return position;
@@ -2592,18 +2913,20 @@ void main(void) {
2592
2913
  fs: BACKGROUND_FS,
2593
2914
  parameters: {
2594
2915
  depthWriteEnabled: false,
2595
- depthCompare: "always",
2596
2916
  ...props.blend ? {
2597
2917
  blend: true,
2598
2918
  blendColorOperation: "add",
2599
2919
  blendAlphaOperation: "add",
2600
2920
  blendColorSrcFactor: "one",
2601
- blendColorDstFactor: "one-minus-src-color",
2921
+ blendColorDstFactor: "one-minus-src",
2602
2922
  blendAlphaSrcFactor: "one",
2603
2923
  blendAlphaDstFactor: "one-minus-src-alpha"
2604
2924
  } : {}
2605
2925
  }
2606
2926
  });
2927
+ if (!props.backgroundTexture) {
2928
+ throw new Error("BackgroundTextureModel requires a backgroundTexture prop");
2929
+ }
2607
2930
  this.setTexture(props.backgroundTexture);
2608
2931
  }
2609
2932
  setTexture(backgroundTexture) {
@@ -4796,13 +5119,13 @@ void main(void) {
4796
5119
  };
4797
5120
 
4798
5121
  // src/scenegraph/group-node.ts
4799
- var import_core11 = __toESM(require_core(), 1);
5122
+ var import_core13 = __toESM(require_core(), 1);
4800
5123
  var GroupNode = class extends ScenegraphNode {
4801
5124
  children;
4802
5125
  constructor(props = {}) {
4803
5126
  props = Array.isArray(props) ? { children: props } : props;
4804
5127
  const { children = [] } = props;
4805
- import_core11.log.assert(
5128
+ import_core13.log.assert(
4806
5129
  children.every((child) => child instanceof ScenegraphNode),
4807
5130
  "every child must an instance of ScenegraphNode"
4808
5131
  );
@@ -6020,7 +6343,7 @@ void main(void) {
6020
6343
  var import_shadertools5 = __toESM(require_shadertools(), 1);
6021
6344
 
6022
6345
  // src/compute/swap.ts
6023
- var import_core13 = __toESM(require_core(), 1);
6346
+ var import_core15 = __toESM(require_core(), 1);
6024
6347
  var Swap = class {
6025
6348
  /** The current resource - usually the source for renders or computations */
6026
6349
  current;
@@ -6048,14 +6371,18 @@ void main(void) {
6048
6371
  let colorAttachments = props.colorAttachments?.map(
6049
6372
  (colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
6050
6373
  format: colorAttachment,
6051
- usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
6374
+ usage: import_core15.Texture.SAMPLE | import_core15.Texture.RENDER | import_core15.Texture.COPY_SRC | import_core15.Texture.COPY_DST,
6375
+ width: 1,
6376
+ height: 1
6052
6377
  })
6053
6378
  );
6054
6379
  const current = device.createFramebuffer({ ...props, colorAttachments });
6055
6380
  colorAttachments = props.colorAttachments?.map(
6056
6381
  (colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
6057
6382
  format: colorAttachment,
6058
- usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
6383
+ usage: import_core15.Texture.TEXTURE | import_core15.Texture.COPY_SRC | import_core15.Texture.COPY_DST | import_core15.Texture.RENDER_ATTACHMENT,
6384
+ width: 1,
6385
+ height: 1
6059
6386
  })
6060
6387
  );
6061
6388
  const next = device.createFramebuffer({ ...props, colorAttachments });
@@ -6118,11 +6445,11 @@ void main(void) {
6118
6445
  return (
6119
6446
  /* wgsl */
6120
6447
  `// Binding 0:1 is reserved for shader passes
6121
- @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
6448
+ // @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
6122
6449
  @group(0) @binding(1) var texture: texture_2d<f32>;
6123
6450
  @group(0) @binding(2) var sampler: sampler;
6124
6451
 
6125
- struct FragmentInputs = {
6452
+ struct FragmentInputs {
6126
6453
  @location(0) fragUV: vec2f,
6127
6454
  @location(1) fragPosition: vec4f,
6128
6455
  @location(2) fragCoordinate: vec4f
@@ -6227,9 +6554,9 @@ void main() {
6227
6554
  {}
6228
6555
  );
6229
6556
  this.shaderInputs = props.shaderInputs || new ShaderInputs(modules);
6230
- const size = device.getCanvasContext().getPixelSize();
6557
+ const size = device.getCanvasContext().getDrawingBufferSize();
6231
6558
  this.swapFramebuffers = new SwapFramebuffers(device, {
6232
- colorAttachments: ["rgba8unorm"],
6559
+ colorAttachments: [device.preferredColorFormat],
6233
6560
  width: size[0],
6234
6561
  height: size[1]
6235
6562
  });
@@ -6283,7 +6610,13 @@ void main() {
6283
6610
  if (!outputTexture) {
6284
6611
  return false;
6285
6612
  }
6286
- const renderPass = this.device.beginRenderPass({ clearColor: [0, 0, 0, 1], clearDepth: 1 });
6613
+ const framebuffer = this.device.getDefaultCanvasContext().getCurrentFramebuffer({ depthStencilAttachment: false });
6614
+ const renderPass = this.device.beginRenderPass({
6615
+ id: "shader-pass-renderer-to-screen",
6616
+ framebuffer,
6617
+ clearColor: [0, 0, 0, 1],
6618
+ clearDepth: 1
6619
+ });
6287
6620
  this.clipSpace.setBindings({ sourceTexture: outputTexture });
6288
6621
  this.clipSpace.draw(renderPass);
6289
6622
  renderPass.end();
@@ -6302,6 +6635,7 @@ void main() {
6302
6635
  backgroundTexture: sourceTexture
6303
6636
  });
6304
6637
  const clearTexturePass = this.device.beginRenderPass({
6638
+ id: "shader-pass-renderer-clear-texture",
6305
6639
  framebuffer: this.swapFramebuffers.current,
6306
6640
  clearColor: [0, 0, 0, 1]
6307
6641
  });
@@ -6320,6 +6654,7 @@ void main() {
6320
6654
  // texSize: [sourceTextures.width, sourceTextures.height]
6321
6655
  };
6322
6656
  const renderPass = this.device.beginRenderPass({
6657
+ id: "shader-pass-renderer-run-pass",
6323
6658
  framebuffer: this.swapFramebuffers.next,
6324
6659
  clearColor: [0, 0, 0, 1],
6325
6660
  clearDepth: 1
@@ -6368,8 +6703,7 @@ void main() {
6368
6703
  fs: fs3,
6369
6704
  modules: [shaderPass],
6370
6705
  parameters: {
6371
- depthWriteEnabled: false,
6372
- depthCompare: "always"
6706
+ depthWriteEnabled: false
6373
6707
  }
6374
6708
  });
6375
6709
  }
@@ -6390,7 +6724,7 @@ void main() {
6390
6724
  };
6391
6725
 
6392
6726
  // src/compute/computation.ts
6393
- var import_core14 = __toESM(require_core(), 1);
6727
+ var import_core16 = __toESM(require_core(), 1);
6394
6728
  var import_shadertools6 = __toESM(require_shadertools(), 1);
6395
6729
  var LOG_DRAW_PRIORITY2 = 2;
6396
6730
  var LOG_DRAW_TIMEOUT2 = 1e4;
@@ -6489,7 +6823,7 @@ void main() {
6489
6823
  }
6490
6824
  setShaderInputs(shaderInputs) {
6491
6825
  this.shaderInputs = shaderInputs;
6492
- this._uniformStore = new import_core14.UniformStore(this.shaderInputs.modules);
6826
+ this._uniformStore = new import_core16.UniformStore(this.shaderInputs.modules);
6493
6827
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
6494
6828
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
6495
6829
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -6526,7 +6860,7 @@ void main() {
6526
6860
  if (this._pipelineNeedsUpdate) {
6527
6861
  let prevShader = null;
6528
6862
  if (this.pipeline) {
6529
- import_core14.log.log(
6863
+ import_core16.log.log(
6530
6864
  1,
6531
6865
  `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
6532
6866
  )();
@@ -6553,33 +6887,33 @@ void main() {
6553
6887
  _lastLogTime = 0;
6554
6888
  _logOpen = false;
6555
6889
  _logDrawCallStart() {
6556
- const logDrawTimeout = import_core14.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
6557
- if (import_core14.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
6890
+ const logDrawTimeout = import_core16.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
6891
+ if (import_core16.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
6558
6892
  return;
6559
6893
  }
6560
6894
  this._lastLogTime = Date.now();
6561
6895
  this._logOpen = true;
6562
- import_core14.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core14.log.level <= 2 })();
6896
+ import_core16.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core16.log.level <= 2 })();
6563
6897
  }
6564
6898
  _logDrawCallEnd() {
6565
6899
  if (this._logOpen) {
6566
6900
  const uniformTable = this.shaderInputs.getDebugTable();
6567
- import_core14.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
6568
- import_core14.log.groupEnd(LOG_DRAW_PRIORITY2)();
6901
+ import_core16.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
6902
+ import_core16.log.groupEnd(LOG_DRAW_PRIORITY2)();
6569
6903
  this._logOpen = false;
6570
6904
  }
6571
6905
  }
6572
6906
  _drawCount = 0;
6573
6907
  // TODO - fix typing of luma data types
6574
6908
  _getBufferOrConstantValues(attribute, dataType) {
6575
- const TypedArrayConstructor = (0, import_core14.getTypedArrayFromDataType)(dataType);
6576
- const typedArray = attribute instanceof import_core14.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
6909
+ const TypedArrayConstructor = (0, import_core16.getTypedArrayConstructor)(dataType);
6910
+ const typedArray = attribute instanceof import_core16.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
6577
6911
  return typedArray.toString();
6578
6912
  }
6579
6913
  };
6580
6914
  var Computation = _Computation;
6581
6915
  __publicField(Computation, "defaultProps", {
6582
- ...import_core14.ComputePipeline.defaultProps,
6916
+ ...import_core16.ComputePipeline.defaultProps,
6583
6917
  id: "unnamed",
6584
6918
  handle: void 0,
6585
6919
  userData: {},
@@ -6730,7 +7064,7 @@ uniform pickingUniforms {
6730
7064
  /** Prepare for rendering picking colors */
6731
7065
  beginRenderPass() {
6732
7066
  const framebuffer = this.getFramebuffer();
6733
- framebuffer.resize(this.device.getDefaultCanvasContext().getPixelSize());
7067
+ framebuffer.resize(this.device.getDefaultCanvasContext().getDevicePixelSize());
6734
7068
  this.props.shaderInputs?.setProps({ picking: { isActive: true } });
6735
7069
  const pickingPass = this.device.beginRenderPass({
6736
7070
  framebuffer,
@@ -6739,7 +7073,7 @@ uniform pickingUniforms {
6739
7073
  });
6740
7074
  return pickingPass;
6741
7075
  }
6742
- getPickInfo(mousePosition) {
7076
+ async updatePickInfo(mousePosition) {
6743
7077
  const framebuffer = this.getFramebuffer();
6744
7078
  const [pickX, pickY] = this.getPickPosition(mousePosition);
6745
7079
  const pixelData = this.device.readPixelsToArrayWebGL(framebuffer, {
@@ -7100,7 +7434,7 @@ vec4 picking_filterColor(vec4 color) {
7100
7434
  /** Prepare for rendering picking colors */
7101
7435
  beginRenderPass() {
7102
7436
  const framebuffer = this.getFramebuffer();
7103
- framebuffer.resize(this.device.getCanvasContext().getPixelSize());
7437
+ framebuffer.resize(this.device.getCanvasContext().getDevicePixelSize());
7104
7438
  this.shaderInputs.setProps({ picking: { isActive: true } });
7105
7439
  const pickingPass = this.device.beginRenderPass({
7106
7440
  framebuffer,