@luma.gl/core 9.3.0-alpha.6 → 9.3.0-alpha.8

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 (202) hide show
  1. package/dist/adapter/canvas-surface.d.ts +1 -1
  2. package/dist/adapter/canvas-surface.d.ts.map +1 -1
  3. package/dist/adapter/device.d.ts +13 -3
  4. package/dist/adapter/device.d.ts.map +1 -1
  5. package/dist/adapter/device.js +73 -6
  6. package/dist/adapter/device.js.map +1 -1
  7. package/dist/adapter/luma.js +1 -1
  8. package/dist/adapter/resources/command-buffer.d.ts +3 -1
  9. package/dist/adapter/resources/command-buffer.d.ts.map +1 -1
  10. package/dist/adapter/resources/command-buffer.js +3 -1
  11. package/dist/adapter/resources/command-buffer.js.map +1 -1
  12. package/dist/adapter/resources/command-encoder.d.ts +3 -1
  13. package/dist/adapter/resources/command-encoder.d.ts.map +1 -1
  14. package/dist/adapter/resources/command-encoder.js +3 -1
  15. package/dist/adapter/resources/command-encoder.js.map +1 -1
  16. package/dist/adapter/resources/compute-pipeline.d.ts +2 -2
  17. package/dist/adapter/resources/compute-pipeline.d.ts.map +1 -1
  18. package/dist/adapter/resources/framebuffer.d.ts +1 -1
  19. package/dist/adapter/resources/framebuffer.d.ts.map +1 -1
  20. package/dist/adapter/resources/render-pipeline.d.ts +10 -4
  21. package/dist/adapter/resources/render-pipeline.d.ts.map +1 -1
  22. package/dist/adapter/resources/render-pipeline.js +2 -1
  23. package/dist/adapter/resources/render-pipeline.js.map +1 -1
  24. package/dist/adapter/resources/texture-view.d.ts +1 -1
  25. package/dist/adapter/resources/texture-view.d.ts.map +1 -1
  26. package/dist/adapter/resources/texture.d.ts +5 -4
  27. package/dist/adapter/resources/texture.d.ts.map +1 -1
  28. package/dist/adapter/resources/texture.js +4 -3
  29. package/dist/adapter/resources/texture.js.map +1 -1
  30. package/dist/adapter/types/attachments.d.ts +1 -1
  31. package/dist/adapter/types/attachments.d.ts.map +1 -1
  32. package/dist/adapter/types/buffer-layout.d.ts +1 -1
  33. package/dist/adapter/types/buffer-layout.d.ts.map +1 -1
  34. package/dist/adapter/types/parameters.d.ts +3 -1
  35. package/dist/adapter/types/parameters.d.ts.map +1 -1
  36. package/dist/adapter/types/parameters.js +1 -0
  37. package/dist/adapter/types/parameters.js.map +1 -1
  38. package/dist/adapter/types/shader-layout.d.ts +10 -6
  39. package/dist/adapter/types/shader-layout.d.ts.map +1 -1
  40. package/dist/adapter/types/uniforms.d.ts +6 -0
  41. package/dist/adapter/types/uniforms.d.ts.map +1 -1
  42. package/dist/adapter-utils/bind-groups.d.ts +9 -0
  43. package/dist/adapter-utils/bind-groups.d.ts.map +1 -0
  44. package/dist/adapter-utils/bind-groups.js +41 -0
  45. package/dist/adapter-utils/bind-groups.js.map +1 -0
  46. package/dist/adapter-utils/get-attribute-from-layouts.d.ts +2 -2
  47. package/dist/adapter-utils/get-attribute-from-layouts.d.ts.map +1 -1
  48. package/dist/adapter-utils/get-attribute-from-layouts.js +6 -6
  49. package/dist/adapter-utils/get-attribute-from-layouts.js.map +1 -1
  50. package/dist/dist.dev.js +983 -223
  51. package/dist/dist.min.js +5 -5
  52. package/dist/factories/bind-group-factory.d.ts +20 -0
  53. package/dist/factories/bind-group-factory.d.ts.map +1 -0
  54. package/dist/factories/bind-group-factory.js +79 -0
  55. package/dist/factories/bind-group-factory.js.map +1 -0
  56. package/dist/factories/core-module-state.d.ts +7 -0
  57. package/dist/factories/core-module-state.d.ts.map +1 -0
  58. package/dist/{shadertypes/data-types/shader-types.js → factories/core-module-state.js} +1 -1
  59. package/dist/factories/core-module-state.js.map +1 -0
  60. package/dist/factories/pipeline-factory.d.ts +54 -0
  61. package/dist/factories/pipeline-factory.d.ts.map +1 -0
  62. package/dist/factories/pipeline-factory.js +270 -0
  63. package/dist/factories/pipeline-factory.js.map +1 -0
  64. package/dist/factories/shader-factory.d.ts +20 -0
  65. package/dist/factories/shader-factory.d.ts.map +1 -0
  66. package/dist/factories/shader-factory.js +84 -0
  67. package/dist/factories/shader-factory.js.map +1 -0
  68. package/dist/index.cjs +942 -221
  69. package/dist/index.cjs.map +4 -4
  70. package/dist/index.d.ts +22 -14
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +13 -9
  73. package/dist/index.js.map +1 -1
  74. package/dist/portable/uniform-block.d.ts +1 -1
  75. package/dist/portable/uniform-block.d.ts.map +1 -1
  76. package/dist/portable/uniform-buffer-layout.d.ts +20 -15
  77. package/dist/portable/uniform-buffer-layout.d.ts.map +1 -1
  78. package/dist/portable/uniform-buffer-layout.js +188 -43
  79. package/dist/portable/uniform-buffer-layout.js.map +1 -1
  80. package/dist/portable/uniform-store.d.ts +5 -6
  81. package/dist/portable/uniform-store.d.ts.map +1 -1
  82. package/dist/portable/uniform-store.js +6 -3
  83. package/dist/portable/uniform-store.js.map +1 -1
  84. package/dist/shadertypes/data-types/data-type-decoder.d.ts +20 -0
  85. package/dist/shadertypes/data-types/data-type-decoder.d.ts.map +1 -0
  86. package/dist/shadertypes/data-types/data-type-decoder.js +79 -0
  87. package/dist/shadertypes/data-types/data-type-decoder.js.map +1 -0
  88. package/dist/shadertypes/data-types/data-types.d.ts +31 -12
  89. package/dist/shadertypes/data-types/data-types.d.ts.map +1 -1
  90. package/dist/{image-utils → shadertypes/image-types}/image-types.d.ts +0 -6
  91. package/dist/shadertypes/image-types/image-types.d.ts.map +1 -0
  92. package/dist/shadertypes/image-types/image-types.js.map +1 -0
  93. package/dist/shadertypes/shader-types/shader-type-decoder.d.ts +41 -0
  94. package/dist/shadertypes/shader-types/shader-type-decoder.d.ts.map +1 -0
  95. package/dist/shadertypes/{data-types/decode-shader-types.js → shader-types/shader-type-decoder.js} +32 -2
  96. package/dist/shadertypes/shader-types/shader-type-decoder.js.map +1 -0
  97. package/dist/shadertypes/shader-types/shader-types.d.ts +101 -0
  98. package/dist/shadertypes/shader-types/shader-types.d.ts.map +1 -0
  99. package/dist/shadertypes/shader-types/shader-types.js +30 -0
  100. package/dist/shadertypes/shader-types/shader-types.js.map +1 -0
  101. package/dist/shadertypes/texture-types/pixel-utils.d.ts.map +1 -0
  102. package/dist/shadertypes/texture-types/pixel-utils.js.map +1 -0
  103. package/dist/shadertypes/{textures → texture-types}/texture-format-decoder.d.ts +1 -0
  104. package/dist/shadertypes/texture-types/texture-format-decoder.d.ts.map +1 -0
  105. package/dist/shadertypes/{textures → texture-types}/texture-format-decoder.js +4 -3
  106. package/dist/shadertypes/texture-types/texture-format-decoder.js.map +1 -0
  107. package/dist/shadertypes/texture-types/texture-format-generics.d.ts +34 -0
  108. package/dist/shadertypes/texture-types/texture-format-generics.d.ts.map +1 -0
  109. package/dist/shadertypes/texture-types/texture-format-generics.js.map +1 -0
  110. package/dist/shadertypes/texture-types/texture-format-table.d.ts.map +1 -0
  111. package/dist/shadertypes/texture-types/texture-format-table.js.map +1 -0
  112. package/dist/shadertypes/{textures → texture-types}/texture-formats.d.ts +5 -1
  113. package/dist/shadertypes/texture-types/texture-formats.d.ts.map +1 -0
  114. package/dist/shadertypes/{textures → texture-types}/texture-formats.js +1 -0
  115. package/dist/shadertypes/texture-types/texture-formats.js.map +1 -0
  116. package/dist/shadertypes/{textures → texture-types}/texture-layout.d.ts +1 -1
  117. package/dist/shadertypes/texture-types/texture-layout.d.ts.map +1 -0
  118. package/dist/shadertypes/texture-types/texture-layout.js.map +1 -0
  119. package/dist/shadertypes/vertex-types/vertex-format-decoder.d.ts +24 -0
  120. package/dist/shadertypes/vertex-types/vertex-format-decoder.d.ts.map +1 -0
  121. package/dist/shadertypes/vertex-types/vertex-format-decoder.js +106 -0
  122. package/dist/shadertypes/vertex-types/vertex-format-decoder.js.map +1 -0
  123. package/dist/shadertypes/vertex-types/vertex-formats.d.ts +50 -0
  124. package/dist/shadertypes/vertex-types/vertex-formats.d.ts.map +1 -0
  125. package/dist/shadertypes/vertex-types/vertex-formats.js.map +1 -0
  126. package/package.json +2 -2
  127. package/src/adapter/canvas-surface.ts +1 -1
  128. package/src/adapter/device.ts +115 -10
  129. package/src/adapter/resources/command-buffer.ts +3 -1
  130. package/src/adapter/resources/command-encoder.ts +3 -1
  131. package/src/adapter/resources/compute-pipeline.ts +2 -2
  132. package/src/adapter/resources/framebuffer.ts +1 -1
  133. package/src/adapter/resources/render-pipeline.ts +12 -5
  134. package/src/adapter/resources/texture-view.ts +1 -1
  135. package/src/adapter/resources/texture.ts +6 -5
  136. package/src/adapter/types/attachments.ts +1 -1
  137. package/src/adapter/types/buffer-layout.ts +1 -1
  138. package/src/adapter/types/parameters.ts +4 -1
  139. package/src/adapter/types/shader-layout.ts +15 -9
  140. package/src/adapter/types/uniforms.ts +12 -0
  141. package/src/adapter-utils/bind-groups.ts +71 -0
  142. package/src/adapter-utils/get-attribute-from-layouts.ts +8 -11
  143. package/src/factories/bind-group-factory.ts +139 -0
  144. package/src/factories/core-module-state.ts +11 -0
  145. package/src/factories/pipeline-factory.ts +328 -0
  146. package/src/factories/shader-factory.ts +103 -0
  147. package/src/index.ts +47 -26
  148. package/src/portable/uniform-block.ts +1 -1
  149. package/src/portable/uniform-buffer-layout.ts +269 -62
  150. package/src/portable/uniform-store.ts +14 -11
  151. package/src/shadertypes/data-types/data-type-decoder.ts +105 -0
  152. package/src/shadertypes/data-types/data-types.ts +100 -48
  153. package/src/{image-utils → shadertypes/image-types}/image-types.ts +0 -7
  154. package/src/shadertypes/{data-types/decode-shader-types.ts → shader-types/shader-type-decoder.ts} +76 -11
  155. package/src/shadertypes/shader-types/shader-types.ts +207 -0
  156. package/src/shadertypes/{textures → texture-types}/texture-format-decoder.ts +4 -3
  157. package/src/shadertypes/{textures → texture-types}/texture-format-generics.ts +42 -48
  158. package/src/shadertypes/{textures → texture-types}/texture-formats.ts +14 -2
  159. package/src/shadertypes/vertex-types/vertex-format-decoder.ts +131 -0
  160. package/src/shadertypes/vertex-types/vertex-formats.ts +183 -0
  161. package/dist/image-utils/image-types.d.ts.map +0 -1
  162. package/dist/image-utils/image-types.js.map +0 -1
  163. package/dist/shadertypes/data-types/decode-shader-types.d.ts +0 -17
  164. package/dist/shadertypes/data-types/decode-shader-types.d.ts.map +0 -1
  165. package/dist/shadertypes/data-types/decode-shader-types.js.map +0 -1
  166. package/dist/shadertypes/data-types/shader-types.d.ts +0 -43
  167. package/dist/shadertypes/data-types/shader-types.d.ts.map +0 -1
  168. package/dist/shadertypes/data-types/shader-types.js.map +0 -1
  169. package/dist/shadertypes/textures/pixel-utils.d.ts.map +0 -1
  170. package/dist/shadertypes/textures/pixel-utils.js.map +0 -1
  171. package/dist/shadertypes/textures/texture-format-decoder.d.ts.map +0 -1
  172. package/dist/shadertypes/textures/texture-format-decoder.js.map +0 -1
  173. package/dist/shadertypes/textures/texture-format-generics.d.ts +0 -33
  174. package/dist/shadertypes/textures/texture-format-generics.d.ts.map +0 -1
  175. package/dist/shadertypes/textures/texture-format-generics.js.map +0 -1
  176. package/dist/shadertypes/textures/texture-format-table.d.ts.map +0 -1
  177. package/dist/shadertypes/textures/texture-format-table.js.map +0 -1
  178. package/dist/shadertypes/textures/texture-formats.d.ts.map +0 -1
  179. package/dist/shadertypes/textures/texture-formats.js.map +0 -1
  180. package/dist/shadertypes/textures/texture-layout.d.ts.map +0 -1
  181. package/dist/shadertypes/textures/texture-layout.js.map +0 -1
  182. package/dist/shadertypes/vertex-arrays/decode-vertex-format.d.ts +0 -18
  183. package/dist/shadertypes/vertex-arrays/decode-vertex-format.d.ts.map +0 -1
  184. package/dist/shadertypes/vertex-arrays/decode-vertex-format.js +0 -100
  185. package/dist/shadertypes/vertex-arrays/decode-vertex-format.js.map +0 -1
  186. package/dist/shadertypes/vertex-arrays/vertex-formats.d.ts +0 -27
  187. package/dist/shadertypes/vertex-arrays/vertex-formats.d.ts.map +0 -1
  188. package/dist/shadertypes/vertex-arrays/vertex-formats.js.map +0 -1
  189. package/src/shadertypes/data-types/shader-types.ts +0 -94
  190. package/src/shadertypes/vertex-arrays/decode-vertex-format.ts +0 -124
  191. package/src/shadertypes/vertex-arrays/vertex-formats.ts +0 -91
  192. /package/dist/{image-utils → shadertypes/image-types}/image-types.js +0 -0
  193. /package/dist/shadertypes/{textures → texture-types}/pixel-utils.d.ts +0 -0
  194. /package/dist/shadertypes/{textures → texture-types}/pixel-utils.js +0 -0
  195. /package/dist/shadertypes/{textures → texture-types}/texture-format-generics.js +0 -0
  196. /package/dist/shadertypes/{textures → texture-types}/texture-format-table.d.ts +0 -0
  197. /package/dist/shadertypes/{textures → texture-types}/texture-format-table.js +0 -0
  198. /package/dist/shadertypes/{textures → texture-types}/texture-layout.js +0 -0
  199. /package/dist/shadertypes/{vertex-arrays → vertex-types}/vertex-formats.js +0 -0
  200. /package/src/shadertypes/{textures → texture-types}/pixel-utils.ts +0 -0
  201. /package/src/shadertypes/{textures → texture-types}/texture-format-table.ts +0 -0
  202. /package/src/shadertypes/{textures → texture-types}/texture-layout.ts +0 -0
package/dist/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(dist_exports, {
38
38
  ExternalTexture: () => ExternalTexture,
39
39
  Fence: () => Fence,
40
40
  Framebuffer: () => Framebuffer,
41
+ PipelineFactory: () => PipelineFactory,
41
42
  PipelineLayout: () => PipelineLayout,
42
43
  PresentationContext: () => PresentationContext,
43
44
  QuerySet: () => QuerySet,
@@ -46,38 +47,39 @@ __export(dist_exports, {
46
47
  Resource: () => Resource,
47
48
  Sampler: () => Sampler,
48
49
  Shader: () => Shader,
50
+ ShaderFactory: () => ShaderFactory,
49
51
  SharedRenderPipeline: () => SharedRenderPipeline,
50
52
  Texture: () => Texture,
51
- TextureFormatDecoder: () => TextureFormatDecoder,
52
53
  TextureView: () => TextureView,
53
54
  TransformFeedback: () => TransformFeedback,
54
55
  UniformBlock: () => UniformBlock,
55
56
  UniformBufferLayout: () => UniformBufferLayout,
56
57
  UniformStore: () => UniformStore,
57
58
  VertexArray: () => VertexArray,
59
+ _getDefaultBindGroupFactory: () => _getDefaultBindGroupFactory,
58
60
  _getTextureFormatDefinition: () => getTextureFormatDefinition,
59
61
  _getTextureFormatTable: () => getTextureFormatTable,
60
62
  assert: () => assert,
61
63
  assertDefined: () => assertDefined,
64
+ dataTypeDecoder: () => dataTypeDecoder,
65
+ flattenBindingsByGroup: () => flattenBindingsByGroup,
62
66
  getAttributeInfosFromLayouts: () => getAttributeInfosFromLayouts,
63
67
  getAttributeShaderTypeInfo: () => getAttributeShaderTypeInfo,
64
- getDataType: () => getDataType,
65
- getDataTypeInfo: () => getDataTypeInfo,
66
68
  getExternalImageSize: () => getExternalImageSize,
67
- getNormalizedDataType: () => getNormalizedDataType,
68
69
  getScratchArray: () => getScratchArray,
70
+ getShaderLayoutBinding: () => getShaderLayoutBinding,
69
71
  getTextureImageView: () => getTextureImageView,
70
72
  getTypedArrayConstructor: () => getTypedArrayConstructor,
71
73
  getVariableShaderTypeInfo: () => getVariableShaderTypeInfo,
72
- getVertexFormatFromAttribute: () => getVertexFormatFromAttribute,
73
- getVertexFormatInfo: () => getVertexFormatInfo,
74
74
  isExternalImage: () => isExternalImage,
75
75
  log: () => log,
76
76
  luma: () => luma,
77
- makeVertexFormat: () => makeVertexFormat,
77
+ normalizeBindingsByGroup: () => normalizeBindingsByGroup,
78
78
  readPixel: () => readPixel,
79
79
  setTextureImageData: () => setTextureImageData,
80
+ shaderTypeDecoder: () => shaderTypeDecoder,
80
81
  textureFormatDecoder: () => textureFormatDecoder,
82
+ vertexFormatDecoder: () => vertexFormatDecoder,
81
83
  writePixel: () => writePixel
82
84
  });
83
85
  module.exports = __toCommonJS(dist_exports);
@@ -606,62 +608,73 @@ __publicField(Buffer2, "defaultProps", {
606
608
  onMapped: void 0
607
609
  });
608
610
 
609
- // dist/shadertypes/data-types/decode-data-types.js
610
- function getDataTypeInfo(type) {
611
- const normalized = type.includes("norm");
612
- const integer = !normalized && !type.startsWith("float");
613
- const signed = type.startsWith("s");
614
- const typeInfo = NORMALIZED_TYPE_MAP[type];
615
- const [signedType, primitiveType, byteLength] = typeInfo || ["uint8 ", "i32", 1];
616
- return {
617
- signedType,
618
- primitiveType,
619
- byteLength,
620
- normalized,
621
- integer,
622
- signed
623
- };
624
- }
625
- function getNormalizedDataType(signedDataType) {
626
- const dataType = signedDataType;
627
- switch (dataType) {
628
- case "uint8":
629
- return "unorm8";
630
- case "sint8":
631
- return "snorm8";
632
- case "uint16":
633
- return "unorm16";
634
- case "sint16":
635
- return "snorm16";
636
- default:
637
- return dataType;
611
+ // dist/shadertypes/data-types/data-type-decoder.js
612
+ var DataTypeDecoder = class {
613
+ /**
614
+ * Gets info about a data type constant (signed or normalized)
615
+ * @returns underlying primitive / signed types, byte length, normalization, integer, signed flags
616
+ */
617
+ getDataTypeInfo(type) {
618
+ const [signedType, primitiveType, byteLength] = NORMALIZED_TYPE_MAP[type];
619
+ const normalized = type.includes("norm");
620
+ const integer = !normalized && !type.startsWith("float");
621
+ const signed = type.startsWith("s");
622
+ return {
623
+ signedType,
624
+ primitiveType,
625
+ byteLength,
626
+ normalized,
627
+ integer,
628
+ signed
629
+ // TODO - add webglOnly flag
630
+ };
638
631
  }
639
- }
640
- function alignTo(size, count) {
641
- switch (count) {
642
- case 1:
643
- return size;
644
- case 2:
645
- return size + size % 2;
646
- default:
647
- return size + (4 - size % 4) % 4;
632
+ /** Build a vertex format from a signed data type and a component */
633
+ getNormalizedDataType(signedDataType) {
634
+ const dataType = signedDataType;
635
+ switch (dataType) {
636
+ case "uint8":
637
+ return "unorm8";
638
+ case "sint8":
639
+ return "snorm8";
640
+ case "uint16":
641
+ return "unorm16";
642
+ case "sint16":
643
+ return "snorm16";
644
+ default:
645
+ return dataType;
646
+ }
648
647
  }
649
- }
650
- function getDataType(arrayOrType) {
651
- const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
652
- if (Constructor === Uint8ClampedArray) {
653
- return "uint8";
648
+ /** Align offset to 1, 2 or 4 elements (4, 8 or 16 bytes) */
649
+ alignTo(size, count) {
650
+ switch (count) {
651
+ case 1:
652
+ return size;
653
+ case 2:
654
+ return size + size % 2;
655
+ default:
656
+ return size + (4 - size % 4) % 4;
657
+ }
654
658
  }
655
- const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
656
- if (!info) {
657
- throw new Error(Constructor.name);
659
+ /** Returns the VariableShaderType that corresponds to a typed array */
660
+ getDataType(arrayOrType) {
661
+ const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
662
+ if (Constructor === Uint8ClampedArray) {
663
+ return "uint8";
664
+ }
665
+ const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
666
+ if (!info) {
667
+ throw new Error(Constructor.name);
668
+ }
669
+ return info[0];
658
670
  }
659
- return info[0];
660
- }
661
- function getTypedArrayConstructor(type) {
662
- const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
663
- return Constructor;
664
- }
671
+ /** Returns the TypedArray that corresponds to a shader data type */
672
+ getTypedArrayConstructor(type) {
673
+ const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
674
+ return Constructor;
675
+ }
676
+ };
677
+ var dataTypeDecoder = new DataTypeDecoder();
665
678
  var NORMALIZED_TYPE_MAP = {
666
679
  uint8: ["uint8", "u32", 1, false, Uint8Array],
667
680
  sint8: ["sint8", "i32", 1, false, Int8Array],
@@ -677,87 +690,99 @@ var NORMALIZED_TYPE_MAP = {
677
690
  sint32: ["sint32", "i32", 4, false, Int32Array]
678
691
  };
679
692
 
680
- // dist/shadertypes/vertex-arrays/decode-vertex-format.js
681
- function getVertexFormatInfo(format) {
682
- let webglOnly;
683
- if (format.endsWith("-webgl")) {
684
- format.replace("-webgl", "");
685
- webglOnly = true;
686
- }
687
- const [type_, count] = format.split("x");
688
- const type = type_;
689
- const components = count ? parseInt(count) : 1;
690
- const decodedType = getDataTypeInfo(type);
691
- const result = {
692
- type,
693
- components,
694
- byteLength: decodedType.byteLength * components,
695
- integer: decodedType.integer,
696
- signed: decodedType.signed,
697
- normalized: decodedType.normalized
698
- };
699
- if (webglOnly) {
700
- result.webglOnly = true;
701
- }
702
- return result;
703
- }
704
- function makeVertexFormat(signedDataType, components, normalized) {
705
- const dataType = normalized ? getNormalizedDataType(signedDataType) : signedDataType;
706
- switch (dataType) {
707
- case "unorm8":
708
- if (components === 1) {
709
- return "unorm8";
710
- }
711
- if (components === 3) {
712
- return "unorm8x3-webgl";
713
- }
714
- return `${dataType}x${components}`;
715
- case "snorm8":
716
- case "uint8":
717
- case "sint8":
718
- case "uint16":
719
- case "sint16":
720
- case "unorm16":
721
- case "snorm16":
722
- case "float16":
723
- if (components === 1 || components === 3) {
724
- throw new Error(`size: ${components}`);
725
- }
726
- return `${dataType}x${components}`;
727
- default:
728
- return components === 1 ? dataType : `${dataType}x${components}`;
729
- }
730
- }
731
- function getVertexFormatFromAttribute(typedArray, size, normalized) {
732
- if (!size || size > 4) {
733
- throw new Error(`size ${size}`);
693
+ // dist/shadertypes/vertex-types/vertex-format-decoder.js
694
+ var VertexFormatDecoder = class {
695
+ /**
696
+ * Decodes a vertex format, returning type, components, byte length and flags (integer, signed, normalized)
697
+ */
698
+ getVertexFormatInfo(format) {
699
+ let webglOnly;
700
+ if (format.endsWith("-webgl")) {
701
+ format.replace("-webgl", "");
702
+ webglOnly = true;
703
+ }
704
+ const [type_, count] = format.split("x");
705
+ const type = type_;
706
+ const components = count ? parseInt(count) : 1;
707
+ const decodedType = dataTypeDecoder.getDataTypeInfo(type);
708
+ const result = {
709
+ type,
710
+ components,
711
+ byteLength: decodedType.byteLength * components,
712
+ integer: decodedType.integer,
713
+ signed: decodedType.signed,
714
+ normalized: decodedType.normalized
715
+ };
716
+ if (webglOnly) {
717
+ result.webglOnly = true;
718
+ }
719
+ return result;
720
+ }
721
+ /** Build a vertex format from a signed data type and a component */
722
+ makeVertexFormat(signedDataType, components, normalized) {
723
+ const dataType = normalized ? dataTypeDecoder.getNormalizedDataType(signedDataType) : signedDataType;
724
+ switch (dataType) {
725
+ case "unorm8":
726
+ if (components === 1) {
727
+ return "unorm8";
728
+ }
729
+ if (components === 3) {
730
+ return "unorm8x3-webgl";
731
+ }
732
+ return `${dataType}x${components}`;
733
+ case "snorm8":
734
+ case "uint8":
735
+ case "sint8":
736
+ case "uint16":
737
+ case "sint16":
738
+ case "unorm16":
739
+ case "snorm16":
740
+ case "float16":
741
+ if (components === 1 || components === 3) {
742
+ throw new Error(`size: ${components}`);
743
+ }
744
+ return `${dataType}x${components}`;
745
+ default:
746
+ return components === 1 ? dataType : `${dataType}x${components}`;
747
+ }
734
748
  }
735
- const components = size;
736
- const signedDataType = getDataType(typedArray);
737
- return makeVertexFormat(signedDataType, components, normalized);
738
- }
739
- function getCompatibleVertexFormat(opts) {
740
- let vertexType;
741
- switch (opts.primitiveType) {
742
- case "f32":
743
- vertexType = "float32";
744
- break;
745
- case "i32":
746
- vertexType = "sint32";
747
- break;
748
- case "u32":
749
- vertexType = "uint32";
750
- break;
751
- case "f16":
752
- return opts.components <= 2 ? "float16x2" : "float16x4";
749
+ /** Get the vertex format for an attribute with TypedArray and size */
750
+ getVertexFormatFromAttribute(typedArray, size, normalized) {
751
+ if (!size || size > 4) {
752
+ throw new Error(`size ${size}`);
753
+ }
754
+ const components = size;
755
+ const signedDataType = dataTypeDecoder.getDataType(typedArray);
756
+ return this.makeVertexFormat(signedDataType, components, normalized);
753
757
  }
754
- if (opts.components === 1) {
755
- return vertexType;
758
+ /**
759
+ * Return a "default" vertex format for a certain shader data type
760
+ * The simplest vertex format that matches the shader attribute's data type
761
+ */
762
+ getCompatibleVertexFormat(opts) {
763
+ let vertexType;
764
+ switch (opts.primitiveType) {
765
+ case "f32":
766
+ vertexType = "float32";
767
+ break;
768
+ case "i32":
769
+ vertexType = "sint32";
770
+ break;
771
+ case "u32":
772
+ vertexType = "uint32";
773
+ break;
774
+ case "f16":
775
+ return opts.components <= 2 ? "float16x2" : "float16x4";
776
+ }
777
+ if (opts.components === 1) {
778
+ return vertexType;
779
+ }
780
+ return `${vertexType}x${opts.components}`;
756
781
  }
757
- return `${vertexType}x${opts.components}`;
758
- }
782
+ };
783
+ var vertexFormatDecoder = new VertexFormatDecoder();
759
784
 
760
- // dist/shadertypes/textures/texture-format-table.js
785
+ // dist/shadertypes/texture-types/texture-format-table.js
761
786
  var texture_compression_bc = "texture-compression-bc";
762
787
  var texture_compression_astc = "texture-compression-astc";
763
788
  var texture_compression_etc2 = "texture-compression-etc2";
@@ -928,7 +953,7 @@ var TEXTURE_FORMAT_TABLE = {
928
953
  ...TEXTURE_FORMAT_COMPRESSED_TABLE
929
954
  };
930
955
 
931
- // dist/shadertypes/textures/texture-format-decoder.js
956
+ // dist/shadertypes/texture-types/texture-format-decoder.js
932
957
  var RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
933
958
  var COLOR_FORMAT_PREFIXES = ["rgb", "rgba", "bgra"];
934
959
  var DEPTH_FORMAT_PREFIXES = ["depth", "stencil"];
@@ -1027,11 +1052,11 @@ function getTextureFormatInfo(format) {
1027
1052
  formatInfo.blockHeight = blockSize.blockHeight;
1028
1053
  }
1029
1054
  }
1030
- const matches = RGB_FORMAT_REGEX.exec(format);
1055
+ const matches = !formatInfo.packed ? RGB_FORMAT_REGEX.exec(format) : null;
1031
1056
  if (matches) {
1032
1057
  const [, channels, length, type, srgb, suffix] = matches;
1033
1058
  const dataType = `${type}${length}`;
1034
- const decodedType = getDataTypeInfo(dataType);
1059
+ const decodedType = dataTypeDecoder.getDataTypeInfo(dataType);
1035
1060
  const bits = decodedType.byteLength * 8;
1036
1061
  const components = (channels == null ? void 0 : channels.length) ?? 1;
1037
1062
  const bitsPerChannel = [
@@ -1131,7 +1156,7 @@ function getCompressedTextureBlockByteLength(format) {
1131
1156
  return 16;
1132
1157
  }
1133
1158
 
1134
- // dist/image-utils/image-types.js
1159
+ // dist/shadertypes/image-types/image-types.js
1135
1160
  function isExternalImage(data) {
1136
1161
  return typeof ImageData !== "undefined" && data instanceof ImageData || typeof ImageBitmap !== "undefined" && data instanceof ImageBitmap || typeof HTMLImageElement !== "undefined" && data instanceof HTMLImageElement || typeof HTMLVideoElement !== "undefined" && data instanceof HTMLVideoElement || typeof VideoFrame !== "undefined" && data instanceof VideoFrame || typeof HTMLCanvasElement !== "undefined" && data instanceof HTMLCanvasElement || typeof OffscreenCanvas !== "undefined" && data instanceof OffscreenCanvas;
1137
1162
  }
@@ -1154,6 +1179,53 @@ function getExternalImageSize(data) {
1154
1179
  // dist/adapter/device.js
1155
1180
  var DeviceLimits = class {
1156
1181
  };
1182
+ function formatErrorLogArguments(context, args) {
1183
+ const formattedContext = formatErrorLogValue(context);
1184
+ const formattedArgs = args.map(formatErrorLogValue).filter((arg) => arg !== void 0);
1185
+ return [formattedContext, ...formattedArgs].filter((arg) => arg !== void 0);
1186
+ }
1187
+ function formatErrorLogValue(value) {
1188
+ var _a;
1189
+ if (value === void 0) {
1190
+ return void 0;
1191
+ }
1192
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1193
+ return value;
1194
+ }
1195
+ if (value instanceof Error) {
1196
+ return value.message;
1197
+ }
1198
+ if (Array.isArray(value)) {
1199
+ return value.map(formatErrorLogValue);
1200
+ }
1201
+ if (typeof value === "object") {
1202
+ if (hasCustomToString(value)) {
1203
+ const stringValue = String(value);
1204
+ if (stringValue !== "[object Object]") {
1205
+ return stringValue;
1206
+ }
1207
+ }
1208
+ if (looksLikeGPUCompilationMessage(value)) {
1209
+ return formatGPUCompilationMessage(value);
1210
+ }
1211
+ return ((_a = value.constructor) == null ? void 0 : _a.name) || "Object";
1212
+ }
1213
+ return String(value);
1214
+ }
1215
+ function hasCustomToString(value) {
1216
+ return "toString" in value && typeof value.toString === "function" && value.toString !== Object.prototype.toString;
1217
+ }
1218
+ function looksLikeGPUCompilationMessage(value) {
1219
+ return "message" in value && "type" in value;
1220
+ }
1221
+ function formatGPUCompilationMessage(value) {
1222
+ const type = typeof value.type === "string" ? value.type : "message";
1223
+ const message = typeof value.message === "string" ? value.message : "";
1224
+ const lineNum = typeof value.lineNum === "number" ? value.lineNum : null;
1225
+ const linePos = typeof value.linePos === "number" ? value.linePos : null;
1226
+ const location = lineNum !== null && linePos !== null ? ` @ ${lineNum}:${linePos}` : lineNum !== null ? ` @ ${lineNum}` : "";
1227
+ return `${type}${location}: ${message}`.trim();
1228
+ }
1157
1229
  var DeviceFeatures = class {
1158
1230
  features;
1159
1231
  disabledFeatures;
@@ -1184,6 +1256,8 @@ var _Device = class {
1184
1256
  userData = {};
1185
1257
  /** stats */
1186
1258
  statsManager = lumaStats;
1259
+ /** Internal per-device factory storage */
1260
+ _factories = {};
1187
1261
  /** An abstract timestamp used for change tracking */
1188
1262
  timestamp = 0;
1189
1263
  /** True if this device has been reused during device creation (app has multiple references) */
@@ -1197,8 +1271,9 @@ var _Device = class {
1197
1271
  this.props = { ..._Device.defaultProps, ...props };
1198
1272
  this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
1199
1273
  }
1274
+ // TODO - just expose the shadertypes decoders?
1200
1275
  getVertexFormatInfo(format) {
1201
- return getVertexFormatInfo(format);
1276
+ return vertexFormatDecoder.getVertexFormatInfo(format);
1202
1277
  }
1203
1278
  isVertexFormatSupported(format) {
1204
1279
  return true;
@@ -1300,7 +1375,8 @@ var _Device = class {
1300
1375
  reportError(error, context, ...args) {
1301
1376
  const isHandled = this.props.onError(error, context);
1302
1377
  if (!isHandled) {
1303
- return log.error(this.type === "webgl" ? "%cWebGL" : "%cWebGPU", "color: white; background: red; padding: 2px 6px; border-radius: 3px;", error.message, context, ...args);
1378
+ const logArguments = formatErrorLogArguments(context, args);
1379
+ return log.error(this.type === "webgl" ? "%cWebGL" : "%cWebGPU", "color: white; background: red; padding: 2px 6px; border-radius: 3px;", error.message, ...logArguments);
1304
1380
  }
1305
1381
  return () => {
1306
1382
  };
@@ -1346,6 +1422,14 @@ or create a device with the 'debug: true' prop.`;
1346
1422
  _createSharedRenderPipelineWebGL(_props) {
1347
1423
  throw new Error("_createSharedRenderPipelineWebGL() not implemented");
1348
1424
  }
1425
+ /** Internal WebGPU-only helper for retrieving the native bind-group layout for a pipeline group. */
1426
+ _createBindGroupLayoutWebGPU(_pipeline, _group) {
1427
+ throw new Error("_createBindGroupLayoutWebGPU() not implemented");
1428
+ }
1429
+ /** Internal WebGPU-only helper for creating a native bind group. */
1430
+ _createBindGroupWebGPU(_bindGroupLayout, _shaderLayout, _bindings, _group) {
1431
+ throw new Error("_createBindGroupWebGPU() not implemented");
1432
+ }
1349
1433
  /**
1350
1434
  * Internal helper that returns `true` when timestamp-query GPU timing should be
1351
1435
  * collected for this device.
@@ -1568,7 +1652,7 @@ var _Luma = class {
1568
1652
  VERSION = (
1569
1653
  // Version detection using build plugin
1570
1654
  // @ts-expect-error no-undef
1571
- true ? "9.3.0-alpha.6" : "running from source"
1655
+ true ? "9.3.0-alpha.8" : "running from source"
1572
1656
  );
1573
1657
  spector;
1574
1658
  preregisteredAdapters = /* @__PURE__ */ new Map();
@@ -2372,8 +2456,8 @@ var _Texture = class extends Resource {
2372
2456
  *
2373
2457
  * @note The memory layout of the texture data is determined by the texture format and dimensions.
2374
2458
  * @note The application can call Texture.computeMemoryLayout() to compute the backend-aligned layout.
2375
- * @note The application can call Buffer.readAsync()
2376
- * @note If not supplied a buffer will be created and the application needs to call Buffer.destroy
2459
+ * @note The application can call Buffer.readAsync() to read the returned buffer on the CPU.
2460
+ * @note The destination buffer must be supplied by the caller and must be large enough for the requested region.
2377
2461
  * @note On WebGPU this corresponds to a texture-to-buffer copy and uses buffer-copy alignment rules.
2378
2462
  * @note On WebGL, luma.gl emulates the same logical readback behavior.
2379
2463
  */
@@ -2386,6 +2470,7 @@ var _Texture = class extends Resource {
2386
2470
  *
2387
2471
  * @note The memory layout of the texture data is determined by the texture format and dimensions.
2388
2472
  * @note The application can call Texture.computeMemoryLayout() to compute the layout.
2473
+ * @deprecated Use Texture.readBuffer() with an explicit destination buffer, or DynamicTexture.readAsync() for convenience readback.
2389
2474
  */
2390
2475
  readDataAsync(options) {
2391
2476
  throw new Error("readBuffer not implemented");
@@ -3114,7 +3199,8 @@ __publicField(RenderPipeline, "defaultProps", {
3114
3199
  bufferMode: void 0,
3115
3200
  disableWarnings: false,
3116
3201
  _sharedRenderPipeline: void 0,
3117
- bindings: void 0
3202
+ bindings: void 0,
3203
+ bindGroups: void 0
3118
3204
  });
3119
3205
 
3120
3206
  // dist/adapter/resources/shared-render-pipeline.js
@@ -3134,6 +3220,451 @@ var SharedRenderPipeline = class extends Resource {
3134
3220
  }
3135
3221
  };
3136
3222
 
3223
+ // dist/adapter/resources/compute-pipeline.js
3224
+ var _ComputePipeline = class extends Resource {
3225
+ get [Symbol.toStringTag]() {
3226
+ return "ComputePipeline";
3227
+ }
3228
+ hash = "";
3229
+ /** The merged shader layout */
3230
+ shaderLayout;
3231
+ constructor(device, props) {
3232
+ super(device, props, _ComputePipeline.defaultProps);
3233
+ this.shaderLayout = props.shaderLayout;
3234
+ }
3235
+ };
3236
+ var ComputePipeline = _ComputePipeline;
3237
+ __publicField(ComputePipeline, "defaultProps", {
3238
+ ...Resource.defaultProps,
3239
+ shader: void 0,
3240
+ entryPoint: void 0,
3241
+ constants: {},
3242
+ shaderLayout: void 0
3243
+ });
3244
+
3245
+ // dist/factories/pipeline-factory.js
3246
+ var _PipelineFactory = class {
3247
+ /** Get the singleton default pipeline factory for the specified device */
3248
+ static getDefaultPipelineFactory(device) {
3249
+ const moduleData = device.getModuleData("@luma.gl/core");
3250
+ moduleData.defaultPipelineFactory ||= new _PipelineFactory(device);
3251
+ return moduleData.defaultPipelineFactory;
3252
+ }
3253
+ device;
3254
+ _hashCounter = 0;
3255
+ _hashes = {};
3256
+ _renderPipelineCache = {};
3257
+ _computePipelineCache = {};
3258
+ _sharedRenderPipelineCache = {};
3259
+ get [Symbol.toStringTag]() {
3260
+ return "PipelineFactory";
3261
+ }
3262
+ toString() {
3263
+ return `PipelineFactory(${this.device.id})`;
3264
+ }
3265
+ constructor(device) {
3266
+ this.device = device;
3267
+ }
3268
+ /**
3269
+ * WebGL has two cache layers with different priorities:
3270
+ * - `_sharedRenderPipelineCache` owns `WEBGLSharedRenderPipeline` / `WebGLProgram` reuse.
3271
+ * - `_renderPipelineCache` owns `RenderPipeline` wrapper reuse.
3272
+ *
3273
+ * Shared WebGL program reuse is the hard requirement. Wrapper reuse is beneficial,
3274
+ * but wrapper cache misses are acceptable if that keeps the cache logic simple and
3275
+ * prevents incorrect cache hits.
3276
+ *
3277
+ * In particular, wrapper hash logic must never force program creation or linked-program
3278
+ * introspection just to decide whether a shared WebGL program can be reused.
3279
+ */
3280
+ /** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
3281
+ createRenderPipeline(props) {
3282
+ var _a;
3283
+ if (!this.device.props._cachePipelines) {
3284
+ return this.device.createRenderPipeline(props);
3285
+ }
3286
+ const allProps = { ...RenderPipeline.defaultProps, ...props };
3287
+ const cache = this._renderPipelineCache;
3288
+ const hash = this._hashRenderPipeline(allProps);
3289
+ let pipeline = (_a = cache[hash]) == null ? void 0 : _a.resource;
3290
+ if (!pipeline) {
3291
+ const sharedRenderPipeline = this.device.type === "webgl" && this.device.props._sharePipelines ? this.createSharedRenderPipeline(allProps) : void 0;
3292
+ pipeline = this.device.createRenderPipeline({
3293
+ ...allProps,
3294
+ id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached"),
3295
+ _sharedRenderPipeline: sharedRenderPipeline
3296
+ });
3297
+ pipeline.hash = hash;
3298
+ cache[hash] = { resource: pipeline, useCount: 1 };
3299
+ if (this.device.props.debugFactories) {
3300
+ log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
3301
+ }
3302
+ } else {
3303
+ cache[hash].useCount++;
3304
+ if (this.device.props.debugFactories) {
3305
+ log.log(3, `${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
3306
+ }
3307
+ }
3308
+ return pipeline;
3309
+ }
3310
+ /** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
3311
+ createComputePipeline(props) {
3312
+ var _a;
3313
+ if (!this.device.props._cachePipelines) {
3314
+ return this.device.createComputePipeline(props);
3315
+ }
3316
+ const allProps = { ...ComputePipeline.defaultProps, ...props };
3317
+ const cache = this._computePipelineCache;
3318
+ const hash = this._hashComputePipeline(allProps);
3319
+ let pipeline = (_a = cache[hash]) == null ? void 0 : _a.resource;
3320
+ if (!pipeline) {
3321
+ pipeline = this.device.createComputePipeline({
3322
+ ...allProps,
3323
+ id: allProps.id ? `${allProps.id}-cached` : void 0
3324
+ });
3325
+ pipeline.hash = hash;
3326
+ cache[hash] = { resource: pipeline, useCount: 1 };
3327
+ if (this.device.props.debugFactories) {
3328
+ log.log(3, `${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
3329
+ }
3330
+ } else {
3331
+ cache[hash].useCount++;
3332
+ if (this.device.props.debugFactories) {
3333
+ log.log(3, `${this}: ${cache[hash].resource} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
3334
+ }
3335
+ }
3336
+ return pipeline;
3337
+ }
3338
+ release(pipeline) {
3339
+ if (!this.device.props._cachePipelines) {
3340
+ pipeline.destroy();
3341
+ return;
3342
+ }
3343
+ const cache = this._getCache(pipeline);
3344
+ const hash = pipeline.hash;
3345
+ cache[hash].useCount--;
3346
+ if (cache[hash].useCount === 0) {
3347
+ this._destroyPipeline(pipeline);
3348
+ if (this.device.props.debugFactories) {
3349
+ log.log(3, `${this}: ${pipeline} released and destroyed`)();
3350
+ }
3351
+ } else if (cache[hash].useCount < 0) {
3352
+ log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
3353
+ cache[hash].useCount = 0;
3354
+ } else if (this.device.props.debugFactories) {
3355
+ log.log(3, `${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
3356
+ }
3357
+ }
3358
+ createSharedRenderPipeline(props) {
3359
+ const sharedPipelineHash = this._hashSharedRenderPipeline(props);
3360
+ let sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
3361
+ if (!sharedCacheItem) {
3362
+ const sharedRenderPipeline = this.device._createSharedRenderPipelineWebGL(props);
3363
+ sharedCacheItem = { resource: sharedRenderPipeline, useCount: 0 };
3364
+ this._sharedRenderPipelineCache[sharedPipelineHash] = sharedCacheItem;
3365
+ }
3366
+ sharedCacheItem.useCount++;
3367
+ return sharedCacheItem.resource;
3368
+ }
3369
+ releaseSharedRenderPipeline(pipeline) {
3370
+ if (!pipeline.sharedRenderPipeline) {
3371
+ return;
3372
+ }
3373
+ const sharedPipelineHash = this._hashSharedRenderPipeline(pipeline.sharedRenderPipeline.props);
3374
+ const sharedCacheItem = this._sharedRenderPipelineCache[sharedPipelineHash];
3375
+ if (!sharedCacheItem) {
3376
+ return;
3377
+ }
3378
+ sharedCacheItem.useCount--;
3379
+ if (sharedCacheItem.useCount === 0) {
3380
+ sharedCacheItem.resource.destroy();
3381
+ delete this._sharedRenderPipelineCache[sharedPipelineHash];
3382
+ }
3383
+ }
3384
+ // PRIVATE
3385
+ /** Destroy a cached pipeline, removing it from the cache if configured to do so. */
3386
+ _destroyPipeline(pipeline) {
3387
+ const cache = this._getCache(pipeline);
3388
+ if (!this.device.props._destroyPipelines) {
3389
+ return false;
3390
+ }
3391
+ delete cache[pipeline.hash];
3392
+ pipeline.destroy();
3393
+ if (pipeline instanceof RenderPipeline) {
3394
+ this.releaseSharedRenderPipeline(pipeline);
3395
+ }
3396
+ return true;
3397
+ }
3398
+ /** Get the appropriate cache for the type of pipeline */
3399
+ _getCache(pipeline) {
3400
+ let cache;
3401
+ if (pipeline instanceof ComputePipeline) {
3402
+ cache = this._computePipelineCache;
3403
+ }
3404
+ if (pipeline instanceof RenderPipeline) {
3405
+ cache = this._renderPipelineCache;
3406
+ }
3407
+ if (!cache) {
3408
+ throw new Error(`${this}`);
3409
+ }
3410
+ if (!cache[pipeline.hash]) {
3411
+ throw new Error(`${this}: ${pipeline} matched incorrect entry`);
3412
+ }
3413
+ return cache;
3414
+ }
3415
+ /** Calculate a hash based on all the inputs for a compute pipeline */
3416
+ _hashComputePipeline(props) {
3417
+ const { type } = this.device;
3418
+ const shaderHash = this._getHash(props.shader.source);
3419
+ const shaderLayoutHash = this._getHash(JSON.stringify(props.shaderLayout));
3420
+ return `${type}/C/${shaderHash}SL${shaderLayoutHash}`;
3421
+ }
3422
+ /** Calculate a hash based on all the inputs for a render pipeline */
3423
+ _hashRenderPipeline(props) {
3424
+ const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
3425
+ const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
3426
+ const varyingHash = this._getWebGLVaryingHash(props);
3427
+ const shaderLayoutHash = this._getHash(JSON.stringify(props.shaderLayout));
3428
+ const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
3429
+ const { type } = this.device;
3430
+ switch (type) {
3431
+ case "webgl":
3432
+ const webglParameterHash = this._getHash(JSON.stringify(props.parameters));
3433
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${webglParameterHash}SL${shaderLayoutHash}BL${bufferLayoutHash}`;
3434
+ case "webgpu":
3435
+ default:
3436
+ const entryPointHash = this._getHash(JSON.stringify({
3437
+ vertexEntryPoint: props.vertexEntryPoint,
3438
+ fragmentEntryPoint: props.fragmentEntryPoint
3439
+ }));
3440
+ const parameterHash = this._getHash(JSON.stringify(props.parameters));
3441
+ const attachmentHash = this._getWebGPUAttachmentHash(props);
3442
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}EP${entryPointHash}P${parameterHash}SL${shaderLayoutHash}BL${bufferLayoutHash}A${attachmentHash}`;
3443
+ }
3444
+ }
3445
+ // This is the only gate for shared `WebGLProgram` reuse.
3446
+ // Only include inputs that affect program linking or transform-feedback linkage.
3447
+ // Wrapper-only concerns such as topology, parameters, attachment formats and layout
3448
+ // overrides must not be added here.
3449
+ _hashSharedRenderPipeline(props) {
3450
+ const vsHash = props.vs ? this._getHash(props.vs.source) : 0;
3451
+ const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
3452
+ const varyingHash = this._getWebGLVaryingHash(props);
3453
+ return `webgl/S/${vsHash}/${fsHash}V${varyingHash}`;
3454
+ }
3455
+ _getHash(key) {
3456
+ if (this._hashes[key] === void 0) {
3457
+ this._hashes[key] = this._hashCounter++;
3458
+ }
3459
+ return this._hashes[key];
3460
+ }
3461
+ _getWebGLVaryingHash(props) {
3462
+ const { varyings = [], bufferMode = null } = props;
3463
+ return this._getHash(JSON.stringify({ varyings, bufferMode }));
3464
+ }
3465
+ _getWebGPUAttachmentHash(props) {
3466
+ var _a;
3467
+ const colorAttachmentFormats = props.colorAttachmentFormats ?? [
3468
+ this.device.preferredColorFormat
3469
+ ];
3470
+ const depthStencilAttachmentFormat = ((_a = props.parameters) == null ? void 0 : _a.depthWriteEnabled) ? props.depthStencilAttachmentFormat || this.device.preferredDepthFormat : null;
3471
+ return this._getHash(JSON.stringify({
3472
+ colorAttachmentFormats,
3473
+ depthStencilAttachmentFormat
3474
+ }));
3475
+ }
3476
+ };
3477
+ var PipelineFactory = _PipelineFactory;
3478
+ __publicField(PipelineFactory, "defaultProps", { ...RenderPipeline.defaultProps });
3479
+
3480
+ // dist/factories/shader-factory.js
3481
+ var _ShaderFactory = class {
3482
+ /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
3483
+ static getDefaultShaderFactory(device) {
3484
+ const moduleData = device.getModuleData("@luma.gl/core");
3485
+ moduleData.defaultShaderFactory ||= new _ShaderFactory(device);
3486
+ return moduleData.defaultShaderFactory;
3487
+ }
3488
+ device;
3489
+ _cache = {};
3490
+ get [Symbol.toStringTag]() {
3491
+ return "ShaderFactory";
3492
+ }
3493
+ toString() {
3494
+ return `${this[Symbol.toStringTag]}(${this.device.id})`;
3495
+ }
3496
+ /** @internal */
3497
+ constructor(device) {
3498
+ this.device = device;
3499
+ }
3500
+ /** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
3501
+ createShader(props) {
3502
+ if (!this.device.props._cacheShaders) {
3503
+ return this.device.createShader(props);
3504
+ }
3505
+ const key = this._hashShader(props);
3506
+ let cacheEntry = this._cache[key];
3507
+ if (!cacheEntry) {
3508
+ const resource = this.device.createShader({
3509
+ ...props,
3510
+ id: props.id ? `${props.id}-cached` : void 0
3511
+ });
3512
+ this._cache[key] = cacheEntry = { resource, useCount: 1 };
3513
+ if (this.device.props.debugFactories) {
3514
+ log.log(3, `${this}: Created new shader ${resource.id}`)();
3515
+ }
3516
+ } else {
3517
+ cacheEntry.useCount++;
3518
+ if (this.device.props.debugFactories) {
3519
+ log.log(3, `${this}: Reusing shader ${cacheEntry.resource.id} count=${cacheEntry.useCount}`)();
3520
+ }
3521
+ }
3522
+ return cacheEntry.resource;
3523
+ }
3524
+ /** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
3525
+ release(shader) {
3526
+ if (!this.device.props._cacheShaders) {
3527
+ shader.destroy();
3528
+ return;
3529
+ }
3530
+ const key = this._hashShader(shader);
3531
+ const cacheEntry = this._cache[key];
3532
+ if (cacheEntry) {
3533
+ cacheEntry.useCount--;
3534
+ if (cacheEntry.useCount === 0) {
3535
+ if (this.device.props._destroyShaders) {
3536
+ delete this._cache[key];
3537
+ cacheEntry.resource.destroy();
3538
+ if (this.device.props.debugFactories) {
3539
+ log.log(3, `${this}: Releasing shader ${shader.id}, destroyed`)();
3540
+ }
3541
+ }
3542
+ } else if (cacheEntry.useCount < 0) {
3543
+ throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
3544
+ } else if (this.device.props.debugFactories) {
3545
+ log.log(3, `${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
3546
+ }
3547
+ }
3548
+ }
3549
+ // PRIVATE
3550
+ _hashShader(value) {
3551
+ return `${value.stage}:${value.source}`;
3552
+ }
3553
+ };
3554
+ var ShaderFactory = _ShaderFactory;
3555
+ __publicField(ShaderFactory, "defaultProps", { ...Shader.defaultProps });
3556
+
3557
+ // dist/adapter-utils/bind-groups.js
3558
+ function getShaderLayoutBinding(shaderLayout, bindingName, options) {
3559
+ const bindingLayout = shaderLayout.bindings.find((binding) => binding.name === bindingName || `${binding.name.toLocaleLowerCase()}uniforms` === bindingName.toLocaleLowerCase());
3560
+ if (!bindingLayout && !(options == null ? void 0 : options.ignoreWarnings)) {
3561
+ log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
3562
+ }
3563
+ return bindingLayout || null;
3564
+ }
3565
+ function normalizeBindingsByGroup(shaderLayout, bindingsOrBindGroups) {
3566
+ if (!bindingsOrBindGroups) {
3567
+ return {};
3568
+ }
3569
+ if (areBindingsGrouped(bindingsOrBindGroups)) {
3570
+ const bindGroups2 = bindingsOrBindGroups;
3571
+ return Object.fromEntries(Object.entries(bindGroups2).map(([group, bindings]) => [Number(group), { ...bindings }]));
3572
+ }
3573
+ const bindGroups = {};
3574
+ for (const [bindingName, binding] of Object.entries(bindingsOrBindGroups)) {
3575
+ const bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
3576
+ const group = (bindingLayout == null ? void 0 : bindingLayout.group) ?? 0;
3577
+ bindGroups[group] ||= {};
3578
+ bindGroups[group][bindingName] = binding;
3579
+ }
3580
+ return bindGroups;
3581
+ }
3582
+ function flattenBindingsByGroup(bindGroups) {
3583
+ const bindings = {};
3584
+ for (const groupBindings of Object.values(bindGroups)) {
3585
+ Object.assign(bindings, groupBindings);
3586
+ }
3587
+ return bindings;
3588
+ }
3589
+ function areBindingsGrouped(bindingsOrBindGroups) {
3590
+ const keys = Object.keys(bindingsOrBindGroups);
3591
+ return keys.length > 0 && keys.every((key) => /^\d+$/.test(key));
3592
+ }
3593
+
3594
+ // dist/factories/bind-group-factory.js
3595
+ var BindGroupFactory = class {
3596
+ device;
3597
+ _layoutCacheByPipeline = /* @__PURE__ */ new WeakMap();
3598
+ _bindGroupCacheByLayout = /* @__PURE__ */ new WeakMap();
3599
+ constructor(device) {
3600
+ this.device = device;
3601
+ }
3602
+ getBindGroups(pipeline, bindings, bindGroupCacheKeys) {
3603
+ if (this.device.type !== "webgpu" || pipeline.shaderLayout.bindings.length === 0) {
3604
+ return {};
3605
+ }
3606
+ const bindingsByGroup = normalizeBindingsByGroup(pipeline.shaderLayout, bindings);
3607
+ const resolvedBindGroups = {};
3608
+ for (const group of getBindGroupIndicesUpToMax(pipeline.shaderLayout.bindings)) {
3609
+ const groupBindings = bindingsByGroup[group];
3610
+ const bindGroupLayout = this._getBindGroupLayout(pipeline, group);
3611
+ if (!groupBindings || Object.keys(groupBindings).length === 0) {
3612
+ if (!hasBindingsInGroup(pipeline.shaderLayout.bindings, group)) {
3613
+ resolvedBindGroups[group] = this._getEmptyBindGroup(bindGroupLayout, pipeline.shaderLayout, group);
3614
+ }
3615
+ continue;
3616
+ }
3617
+ const bindGroupCacheKey = bindGroupCacheKeys == null ? void 0 : bindGroupCacheKeys[group];
3618
+ if (bindGroupCacheKey) {
3619
+ const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout);
3620
+ if (layoutCache.bindGroupsBySource.has(bindGroupCacheKey)) {
3621
+ resolvedBindGroups[group] = layoutCache.bindGroupsBySource.get(bindGroupCacheKey) || null;
3622
+ continue;
3623
+ }
3624
+ const bindGroup = this.device._createBindGroupWebGPU(bindGroupLayout, pipeline.shaderLayout, groupBindings, group);
3625
+ layoutCache.bindGroupsBySource.set(bindGroupCacheKey, bindGroup);
3626
+ resolvedBindGroups[group] = bindGroup;
3627
+ } else {
3628
+ resolvedBindGroups[group] = this.device._createBindGroupWebGPU(bindGroupLayout, pipeline.shaderLayout, groupBindings, group);
3629
+ }
3630
+ }
3631
+ return resolvedBindGroups;
3632
+ }
3633
+ _getBindGroupLayout(pipeline, group) {
3634
+ let layoutCache = this._layoutCacheByPipeline.get(pipeline);
3635
+ if (!layoutCache) {
3636
+ layoutCache = {};
3637
+ this._layoutCacheByPipeline.set(pipeline, layoutCache);
3638
+ }
3639
+ layoutCache[group] ||= this.device._createBindGroupLayoutWebGPU(pipeline, group);
3640
+ return layoutCache[group];
3641
+ }
3642
+ _getEmptyBindGroup(bindGroupLayout, shaderLayout, group) {
3643
+ const layoutCache = this._getLayoutBindGroupCache(bindGroupLayout);
3644
+ layoutCache.emptyBindGroup ||= this.device._createBindGroupWebGPU(bindGroupLayout, shaderLayout, {}, group) || null;
3645
+ return layoutCache.emptyBindGroup;
3646
+ }
3647
+ _getLayoutBindGroupCache(bindGroupLayout) {
3648
+ let layoutCache = this._bindGroupCacheByLayout.get(bindGroupLayout);
3649
+ if (!layoutCache) {
3650
+ layoutCache = { bindGroupsBySource: /* @__PURE__ */ new WeakMap() };
3651
+ this._bindGroupCacheByLayout.set(bindGroupLayout, layoutCache);
3652
+ }
3653
+ return layoutCache;
3654
+ }
3655
+ };
3656
+ function _getDefaultBindGroupFactory(device) {
3657
+ device._factories.bindGroupFactory ||= new BindGroupFactory(device);
3658
+ return device._factories.bindGroupFactory;
3659
+ }
3660
+ function getBindGroupIndicesUpToMax(bindings) {
3661
+ const maxGroup = bindings.reduce((highestGroup, binding) => Math.max(highestGroup, binding.group), -1);
3662
+ return Array.from({ length: maxGroup + 1 }, (_, group) => group);
3663
+ }
3664
+ function hasBindingsInGroup(bindings, group) {
3665
+ return bindings.some((binding) => binding.group === group);
3666
+ }
3667
+
3137
3668
  // dist/adapter/resources/render-pass.js
3138
3669
  var _RenderPass = class extends Resource {
3139
3670
  get [Symbol.toStringTag]() {
@@ -3172,28 +3703,6 @@ __publicField(RenderPass, "defaultProps", {
3172
3703
  endTimestampIndex: void 0
3173
3704
  });
3174
3705
 
3175
- // dist/adapter/resources/compute-pipeline.js
3176
- var _ComputePipeline = class extends Resource {
3177
- get [Symbol.toStringTag]() {
3178
- return "ComputePipeline";
3179
- }
3180
- hash = "";
3181
- /** The merged shader layout */
3182
- shaderLayout;
3183
- constructor(device, props) {
3184
- super(device, props, _ComputePipeline.defaultProps);
3185
- this.shaderLayout = props.shaderLayout;
3186
- }
3187
- };
3188
- var ComputePipeline = _ComputePipeline;
3189
- __publicField(ComputePipeline, "defaultProps", {
3190
- ...Resource.defaultProps,
3191
- shader: void 0,
3192
- entryPoint: void 0,
3193
- constants: {},
3194
- shaderLayout: void 0
3195
- });
3196
-
3197
3706
  // dist/adapter/resources/compute-pass.js
3198
3707
  var _ComputePass = class extends Resource {
3199
3708
  constructor(device, props) {
@@ -3305,7 +3814,7 @@ __publicField(CommandBuffer, "defaultProps", {
3305
3814
  ...Resource.defaultProps
3306
3815
  });
3307
3816
 
3308
- // dist/shadertypes/data-types/decode-shader-types.js
3817
+ // dist/shadertypes/shader-types/shader-type-decoder.js
3309
3818
  function getVariableShaderTypeInfo(format) {
3310
3819
  const resolvedFormat = resolveVariableShaderTypeAlias(format);
3311
3820
  const decoded = UNIFORM_FORMATS[resolvedFormat];
@@ -3332,12 +3841,33 @@ function getAttributeShaderTypeInfo(attributeType) {
3332
3841
  signed
3333
3842
  };
3334
3843
  }
3844
+ var ShaderTypeDecoder = class {
3845
+ getVariableShaderTypeInfo(format) {
3846
+ return getVariableShaderTypeInfo(format);
3847
+ }
3848
+ getAttributeShaderTypeInfo(attributeType) {
3849
+ return getAttributeShaderTypeInfo(attributeType);
3850
+ }
3851
+ makeShaderAttributeType(primitiveType, components) {
3852
+ return makeShaderAttributeType(primitiveType, components);
3853
+ }
3854
+ resolveAttributeShaderTypeAlias(alias) {
3855
+ return resolveAttributeShaderTypeAlias(alias);
3856
+ }
3857
+ resolveVariableShaderTypeAlias(alias) {
3858
+ return resolveVariableShaderTypeAlias(alias);
3859
+ }
3860
+ };
3861
+ function makeShaderAttributeType(primitiveType, components) {
3862
+ return components === 1 ? primitiveType : `vec${components}<${primitiveType}>`;
3863
+ }
3335
3864
  function resolveAttributeShaderTypeAlias(alias) {
3336
3865
  return WGSL_ATTRIBUTE_TYPE_ALIAS_MAP[alias] || alias;
3337
3866
  }
3338
3867
  function resolveVariableShaderTypeAlias(alias) {
3339
3868
  return WGSL_VARIABLE_TYPE_ALIAS_MAP[alias] || alias;
3340
3869
  }
3870
+ var shaderTypeDecoder = new ShaderTypeDecoder();
3341
3871
  var PRIMITIVE_TYPE_SIZES = {
3342
3872
  f32: 4,
3343
3873
  f16: 2,
@@ -3434,7 +3964,18 @@ var WGSL_ATTRIBUTE_TYPE_ALIAS_MAP = {
3434
3964
  vec4h: "vec4<f16>"
3435
3965
  };
3436
3966
  var WGSL_VARIABLE_TYPE_ALIAS_MAP = {
3437
- ...WGSL_ATTRIBUTE_TYPE_ALIAS_MAP,
3967
+ vec2i: "vec2<i32>",
3968
+ vec3i: "vec3<i32>",
3969
+ vec4i: "vec4<i32>",
3970
+ vec2u: "vec2<u32>",
3971
+ vec3u: "vec3<u32>",
3972
+ vec4u: "vec4<u32>",
3973
+ vec2f: "vec2<f32>",
3974
+ vec3f: "vec3<f32>",
3975
+ vec4f: "vec4<f32>",
3976
+ vec2h: "vec2<f16>",
3977
+ vec3h: "vec3<f16>",
3978
+ vec4h: "vec4<f16>",
3438
3979
  mat2x2f: "mat2x2<f32>",
3439
3980
  mat2x3f: "mat2x3<f32>",
3440
3981
  mat2x4f: "mat2x4<f32>",
@@ -3498,10 +4039,10 @@ function getAttributeInfoFromLayouts(shaderLayout, bufferLayout, name2) {
3498
4039
  if (!shaderDeclaration) {
3499
4040
  return null;
3500
4041
  }
3501
- const attributeTypeInfo = getAttributeShaderTypeInfo(shaderDeclaration.type);
3502
- const defaultVertexFormat = getCompatibleVertexFormat(attributeTypeInfo);
4042
+ const attributeTypeInfo = shaderTypeDecoder.getAttributeShaderTypeInfo(shaderDeclaration.type);
4043
+ const defaultVertexFormat = vertexFormatDecoder.getCompatibleVertexFormat(attributeTypeInfo);
3503
4044
  const vertexFormat = (bufferMapping == null ? void 0 : bufferMapping.vertexFormat) || defaultVertexFormat;
3504
- const vertexFormatInfo = getVertexFormatInfo(vertexFormat);
4045
+ const vertexFormatInfo = vertexFormatDecoder.getVertexFormatInfo(vertexFormat);
3505
4046
  return {
3506
4047
  attributeName: (bufferMapping == null ? void 0 : bufferMapping.attributeName) || shaderDeclaration.name,
3507
4048
  bufferName: (bufferMapping == null ? void 0 : bufferMapping.bufferName) || shaderDeclaration.name,
@@ -3570,7 +4111,7 @@ function getAttributeFromAttributesList(bufferLayouts, name2) {
3570
4111
  let byteStride = bufferLayout.byteStride;
3571
4112
  if (typeof bufferLayout.byteStride !== "number") {
3572
4113
  for (const attributeMapping2 of bufferLayout.attributes || []) {
3573
- const info = getVertexFormatInfo(attributeMapping2.format);
4114
+ const info = vertexFormatDecoder.getVertexFormatInfo(attributeMapping2.format);
3574
4115
  byteStride += info.byteLength;
3575
4116
  }
3576
4117
  }
@@ -3686,6 +4227,36 @@ __publicField(PipelineLayout, "defaultProps", {
3686
4227
  }
3687
4228
  });
3688
4229
 
4230
+ // dist/shadertypes/data-types/decode-data-types.js
4231
+ function alignTo(size, count) {
4232
+ switch (count) {
4233
+ case 1:
4234
+ return size;
4235
+ case 2:
4236
+ return size + size % 2;
4237
+ default:
4238
+ return size + (4 - size % 4) % 4;
4239
+ }
4240
+ }
4241
+ function getTypedArrayConstructor(type) {
4242
+ const [, , , , Constructor] = NORMALIZED_TYPE_MAP2[type];
4243
+ return Constructor;
4244
+ }
4245
+ var NORMALIZED_TYPE_MAP2 = {
4246
+ uint8: ["uint8", "u32", 1, false, Uint8Array],
4247
+ sint8: ["sint8", "i32", 1, false, Int8Array],
4248
+ unorm8: ["uint8", "f32", 1, true, Uint8Array],
4249
+ snorm8: ["sint8", "f32", 1, true, Int8Array],
4250
+ uint16: ["uint16", "u32", 2, false, Uint16Array],
4251
+ sint16: ["sint16", "i32", 2, false, Int16Array],
4252
+ unorm16: ["uint16", "u32", 2, true, Uint16Array],
4253
+ snorm16: ["sint16", "i32", 2, true, Int16Array],
4254
+ float16: ["float16", "f16", 2, false, Uint16Array],
4255
+ float32: ["float32", "f32", 4, false, Float32Array],
4256
+ uint32: ["uint32", "u32", 4, false, Uint32Array],
4257
+ sint32: ["sint32", "i32", 4, false, Int32Array]
4258
+ };
4259
+
3689
4260
  // dist/utils/array-utils-flat.js
3690
4261
  var arrayBuffer;
3691
4262
  function getScratchArrayBuffer(byteLength) {
@@ -3699,19 +4270,32 @@ function getScratchArray(Type, length) {
3699
4270
  return new Type(scratchArrayBuffer, 0, length);
3700
4271
  }
3701
4272
 
4273
+ // dist/utils/is-array.js
4274
+ function isTypedArray(value) {
4275
+ return ArrayBuffer.isView(value) && !(value instanceof DataView);
4276
+ }
4277
+ function isNumberArray(value) {
4278
+ if (Array.isArray(value)) {
4279
+ return value.length === 0 || typeof value[0] === "number";
4280
+ }
4281
+ return isTypedArray(value);
4282
+ }
4283
+
3702
4284
  // dist/portable/uniform-buffer-layout.js
3703
4285
  var minBufferSize = 1024;
3704
4286
  var UniformBufferLayout = class {
3705
4287
  layout = {};
4288
+ uniformTypes;
3706
4289
  /** number of bytes needed for buffer allocation */
3707
4290
  byteLength;
3708
4291
  /** Create a new UniformBufferLayout given a map of attributes. */
3709
- constructor(uniformTypes, uniformSizes = {}) {
4292
+ constructor(uniformTypes) {
4293
+ this.uniformTypes = { ...uniformTypes };
3710
4294
  let size = 0;
3711
- for (const [key, uniformType] of Object.entries(uniformTypes)) {
3712
- size = this._addToLayout(key, uniformType, size, uniformSizes == null ? void 0 : uniformSizes[key]);
4295
+ for (const [key, uniformType] of Object.entries(this.uniformTypes)) {
4296
+ size = this._addToLayout(key, uniformType, size);
3713
4297
  }
3714
- size += (4 - size % 4) % 4;
4298
+ size = alignTo(size, 4);
3715
4299
  this.byteLength = Math.max(size * 4, minBufferSize);
3716
4300
  }
3717
4301
  /** Does this layout have a field with specified name */
@@ -3723,98 +4307,232 @@ var UniformBufferLayout = class {
3723
4307
  const layout = this.layout[name2];
3724
4308
  return layout;
3725
4309
  }
4310
+ /** Flatten nested uniform values into leaf-path values understood by UniformBlock. */
4311
+ getFlatUniformValues(uniformValues) {
4312
+ const flattenedUniformValues = {};
4313
+ for (const [name2, value] of Object.entries(uniformValues)) {
4314
+ const uniformType = this.uniformTypes[name2];
4315
+ if (uniformType) {
4316
+ this._flattenCompositeValue(flattenedUniformValues, name2, uniformType, value);
4317
+ } else if (this.layout[name2]) {
4318
+ flattenedUniformValues[name2] = value;
4319
+ }
4320
+ }
4321
+ return flattenedUniformValues;
4322
+ }
3726
4323
  /** Get the data for the complete buffer */
3727
4324
  getData(uniformValues) {
3728
4325
  const buffer = getScratchArrayBuffer(this.byteLength);
4326
+ new Uint8Array(buffer, 0, this.byteLength).fill(0);
3729
4327
  const typedArrays = {
3730
4328
  i32: new Int32Array(buffer),
3731
4329
  u32: new Uint32Array(buffer),
3732
4330
  f32: new Float32Array(buffer),
3733
4331
  f16: new Uint16Array(buffer)
3734
4332
  };
3735
- for (const [name2, value] of Object.entries(uniformValues)) {
3736
- this._writeCompositeValue(typedArrays, name2, value);
4333
+ const flattenedUniformValues = this.getFlatUniformValues(uniformValues);
4334
+ for (const [name2, value] of Object.entries(flattenedUniformValues)) {
4335
+ this._writeLeafValue(typedArrays, name2, value);
3737
4336
  }
3738
4337
  return new Uint8Array(buffer, 0, this.byteLength);
3739
4338
  }
3740
4339
  // Recursively add a uniform to the layout
3741
- _addToLayout(name2, type, offset, count = 1) {
4340
+ _addToLayout(name2, type, offset) {
3742
4341
  if (typeof type === "string") {
3743
- const info = getVariableShaderTypeInfo(type);
3744
- const sizeInSlots = info.components * count;
3745
- const alignedOffset = alignTo(offset, info.components);
4342
+ const info = getLeafLayoutInfo(type);
4343
+ const alignedOffset = alignTo(offset, info.alignment);
3746
4344
  this.layout[name2] = {
3747
4345
  offset: alignedOffset,
3748
- size: sizeInSlots,
3749
- type: info.type
4346
+ ...info
3750
4347
  };
3751
- return alignedOffset + sizeInSlots;
4348
+ return alignedOffset + info.size;
3752
4349
  }
3753
4350
  if (Array.isArray(type)) {
4351
+ if (Array.isArray(type[0])) {
4352
+ throw new Error(`Nested arrays are not supported for ${name2}`);
4353
+ }
3754
4354
  const elementType = type[0];
3755
- const length = count > 1 ? count : type.length > 1 ? type[1] : 1;
3756
- let arrayOffset = alignTo(offset, 4);
4355
+ const length = type[1];
4356
+ const stride = alignTo(getTypeSize(elementType), 4);
4357
+ const arrayOffset = alignTo(offset, 4);
3757
4358
  for (let i = 0; i < length; i++) {
3758
- arrayOffset = this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset);
4359
+ this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset + i * stride);
3759
4360
  }
3760
- return arrayOffset;
4361
+ return arrayOffset + stride * length;
3761
4362
  }
3762
- if (typeof type === "object") {
4363
+ if (isCompositeShaderTypeStruct(type)) {
3763
4364
  let structOffset = alignTo(offset, 4);
3764
4365
  for (const [memberName, memberType] of Object.entries(type)) {
3765
4366
  structOffset = this._addToLayout(`${name2}.${memberName}`, memberType, structOffset);
3766
4367
  }
3767
- return structOffset;
4368
+ return alignTo(structOffset, 4);
3768
4369
  }
3769
4370
  throw new Error(`Unsupported CompositeShaderType for ${name2}`);
3770
4371
  }
3771
- _writeCompositeValue(typedArrays, baseName, value) {
3772
- if (this.layout[baseName]) {
3773
- this._writeToBuffer(typedArrays, baseName, value);
4372
+ _flattenCompositeValue(flattenedUniformValues, baseName, uniformType, value) {
4373
+ if (value === void 0) {
4374
+ return;
4375
+ }
4376
+ if (typeof uniformType === "string" || this.layout[baseName]) {
4377
+ flattenedUniformValues[baseName] = value;
3774
4378
  return;
3775
4379
  }
3776
- if (Array.isArray(value)) {
3777
- for (let i = 0; i < value.length; i++) {
3778
- const element = value[i];
3779
- const indexedName = `${baseName}[${i}]`;
3780
- this._writeCompositeValue(typedArrays, indexedName, element);
4380
+ if (Array.isArray(uniformType)) {
4381
+ const elementType = uniformType[0];
4382
+ const length = uniformType[1];
4383
+ if (Array.isArray(elementType)) {
4384
+ throw new Error(`Nested arrays are not supported for ${baseName}`);
4385
+ }
4386
+ if (typeof elementType === "string" && isNumberArray(value)) {
4387
+ this._flattenPackedArray(flattenedUniformValues, baseName, elementType, length, value);
4388
+ return;
4389
+ }
4390
+ if (!Array.isArray(value)) {
4391
+ log.warn(`Unsupported uniform array value for ${baseName}:`, value)();
4392
+ return;
4393
+ }
4394
+ for (let index = 0; index < Math.min(value.length, length); index++) {
4395
+ const elementValue = value[index];
4396
+ if (elementValue === void 0) {
4397
+ continue;
4398
+ }
4399
+ this._flattenCompositeValue(flattenedUniformValues, `${baseName}[${index}]`, elementType, elementValue);
3781
4400
  }
3782
4401
  return;
3783
4402
  }
3784
- if (typeof value === "object" && value !== null) {
4403
+ if (isCompositeShaderTypeStruct(uniformType) && isCompositeUniformObject(value)) {
3785
4404
  for (const [key, subValue] of Object.entries(value)) {
4405
+ if (subValue === void 0) {
4406
+ continue;
4407
+ }
3786
4408
  const nestedName = `${baseName}.${key}`;
3787
- this._writeCompositeValue(typedArrays, nestedName, subValue);
4409
+ this._flattenCompositeValue(flattenedUniformValues, nestedName, uniformType[key], subValue);
3788
4410
  }
3789
4411
  return;
3790
4412
  }
3791
4413
  log.warn(`Unsupported uniform value for ${baseName}:`, value)();
3792
4414
  }
3793
- _writeToBuffer(typedArrays, name2, value) {
4415
+ _flattenPackedArray(flattenedUniformValues, baseName, elementType, length, value) {
4416
+ const numericValue = value;
4417
+ const elementLayout = getLeafLayoutInfo(elementType);
4418
+ const packedElementLength = elementLayout.components;
4419
+ for (let index = 0; index < length; index++) {
4420
+ const start = index * packedElementLength;
4421
+ if (start >= numericValue.length) {
4422
+ break;
4423
+ }
4424
+ if (packedElementLength === 1) {
4425
+ flattenedUniformValues[`${baseName}[${index}]`] = Number(numericValue[start]);
4426
+ } else {
4427
+ flattenedUniformValues[`${baseName}[${index}]`] = sliceNumericArray(value, start, start + packedElementLength);
4428
+ }
4429
+ }
4430
+ }
4431
+ _writeLeafValue(typedArrays, name2, value) {
3794
4432
  const layout = this.layout[name2];
3795
4433
  if (!layout) {
3796
4434
  log.warn(`Uniform ${name2} not found in layout`)();
3797
4435
  return;
3798
4436
  }
3799
- const { type, size, offset } = layout;
4437
+ const { type, components, columns, rows, offset } = layout;
3800
4438
  const array = typedArrays[type];
3801
- if (size === 1) {
4439
+ if (components === 1) {
3802
4440
  array[offset] = Number(value);
3803
- } else {
3804
- array.set(value, offset);
4441
+ return;
4442
+ }
4443
+ const sourceValue = value;
4444
+ if (columns === 1) {
4445
+ for (let componentIndex = 0; componentIndex < components; componentIndex++) {
4446
+ array[offset + componentIndex] = Number(sourceValue[componentIndex] ?? 0);
4447
+ }
4448
+ return;
4449
+ }
4450
+ let sourceIndex = 0;
4451
+ for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
4452
+ const columnOffset = offset + columnIndex * 4;
4453
+ for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
4454
+ array[columnOffset + rowIndex] = Number(sourceValue[sourceIndex++] ?? 0);
4455
+ }
3805
4456
  }
3806
4457
  }
3807
4458
  };
3808
-
3809
- // dist/utils/is-array.js
3810
- function isTypedArray(value) {
3811
- return ArrayBuffer.isView(value) && !(value instanceof DataView);
4459
+ function getTypeSize(type) {
4460
+ if (typeof type === "string") {
4461
+ return getLeafLayoutInfo(type).size;
4462
+ }
4463
+ if (Array.isArray(type)) {
4464
+ const elementType = type[0];
4465
+ const length = type[1];
4466
+ if (Array.isArray(elementType)) {
4467
+ throw new Error("Nested arrays are not supported");
4468
+ }
4469
+ return alignTo(getTypeSize(elementType), 4) * length;
4470
+ }
4471
+ let size = 0;
4472
+ for (const memberType of Object.values(type)) {
4473
+ const compositeMemberType = memberType;
4474
+ size = alignTo(size, getTypeAlignment(compositeMemberType));
4475
+ size += getTypeSize(compositeMemberType);
4476
+ }
4477
+ return alignTo(size, 4);
3812
4478
  }
3813
- function isNumberArray(value) {
3814
- if (Array.isArray(value)) {
3815
- return value.length === 0 || typeof value[0] === "number";
4479
+ function getTypeAlignment(type) {
4480
+ if (typeof type === "string") {
4481
+ return getLeafLayoutInfo(type).alignment;
3816
4482
  }
3817
- return isTypedArray(value);
4483
+ if (Array.isArray(type)) {
4484
+ return 4;
4485
+ }
4486
+ return 4;
4487
+ }
4488
+ function getLeafLayoutInfo(type) {
4489
+ const resolvedType = resolveVariableShaderTypeAlias(type);
4490
+ const decodedType = getVariableShaderTypeInfo(resolvedType);
4491
+ const matrixMatch = /^mat(\d)x(\d)<.+>$/.exec(resolvedType);
4492
+ if (matrixMatch) {
4493
+ const columns = Number(matrixMatch[1]);
4494
+ const rows = Number(matrixMatch[2]);
4495
+ return {
4496
+ alignment: 4,
4497
+ size: columns * 4,
4498
+ components: columns * rows,
4499
+ columns,
4500
+ rows,
4501
+ shaderType: resolvedType,
4502
+ type: decodedType.type
4503
+ };
4504
+ }
4505
+ const vectorMatch = /^vec(\d)<.+>$/.exec(resolvedType);
4506
+ if (vectorMatch) {
4507
+ const components = Number(vectorMatch[1]);
4508
+ return {
4509
+ alignment: components === 2 ? 2 : 4,
4510
+ size: components === 3 ? 4 : components,
4511
+ components,
4512
+ columns: 1,
4513
+ rows: components,
4514
+ shaderType: resolvedType,
4515
+ type: decodedType.type
4516
+ };
4517
+ }
4518
+ return {
4519
+ alignment: 1,
4520
+ size: 1,
4521
+ components: 1,
4522
+ columns: 1,
4523
+ rows: 1,
4524
+ shaderType: resolvedType,
4525
+ type: decodedType.type
4526
+ };
4527
+ }
4528
+ function isCompositeShaderTypeStruct(value) {
4529
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4530
+ }
4531
+ function isCompositeUniformObject(value) {
4532
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value) && !ArrayBuffer.isView(value);
4533
+ }
4534
+ function sliceNumericArray(value, start, end) {
4535
+ return Array.prototype.slice.call(value, start, end);
3818
4536
  }
3819
4537
 
3820
4538
  // dist/utils/array-equal.js
@@ -3915,10 +4633,10 @@ var UniformStore = class {
3915
4633
  constructor(blocks) {
3916
4634
  for (const [bufferName, block] of Object.entries(blocks)) {
3917
4635
  const uniformBufferName = bufferName;
3918
- const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes ?? {}, block.uniformSizes ?? {});
4636
+ const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes ?? {});
3919
4637
  this.uniformBufferLayouts.set(uniformBufferName, uniformBufferLayout);
3920
4638
  const uniformBlock = new UniformBlock({ name: bufferName });
3921
- uniformBlock.setUniforms(block.defaultUniforms || {});
4639
+ uniformBlock.setUniforms(uniformBufferLayout.getFlatUniformValues(block.defaultUniforms || {}));
3922
4640
  this.uniformBlocks.set(uniformBufferName, uniformBlock);
3923
4641
  }
3924
4642
  }
@@ -3935,7 +4653,10 @@ var UniformStore = class {
3935
4653
  setUniforms(uniforms) {
3936
4654
  var _a;
3937
4655
  for (const [blockName, uniformValues] of Object.entries(uniforms)) {
3938
- (_a = this.uniformBlocks.get(blockName)) == null ? void 0 : _a.setUniforms(uniformValues);
4656
+ const uniformBufferName = blockName;
4657
+ const uniformBufferLayout = this.uniformBufferLayouts.get(uniformBufferName);
4658
+ const flattenedUniforms = uniformBufferLayout == null ? void 0 : uniformBufferLayout.getFlatUniformValues(uniformValues || {});
4659
+ (_a = this.uniformBlocks.get(uniformBufferName)) == null ? void 0 : _a.setUniforms(flattenedUniforms || {});
3939
4660
  }
3940
4661
  this.updateUniformBuffers();
3941
4662
  }
@@ -4009,7 +4730,7 @@ var UniformStore = class {
4009
4730
  }
4010
4731
  };
4011
4732
 
4012
- // dist/shadertypes/textures/texture-layout.js
4733
+ // dist/shadertypes/texture-types/texture-layout.js
4013
4734
  function getTextureImageView(arrayBuffer2, memoryLayout, format, image = 0) {
4014
4735
  const formatInfo = textureFormatDecoder.getInfo(format);
4015
4736
  const bytesPerComponent = formatInfo.bytesPerPixel / formatInfo.components;
@@ -4047,7 +4768,7 @@ function setTextureImageData(arrayBuffer2, memoryLayout, format, data, image = 0
4047
4768
  typedArray.set(subArray, offset);
4048
4769
  }
4049
4770
 
4050
- // dist/shadertypes/textures/pixel-utils.js
4771
+ // dist/shadertypes/texture-types/pixel-utils.js
4051
4772
  function readPixel(pixelData, x, y, bitsPerChannel) {
4052
4773
  if (x < 0 || x >= pixelData.width || y < 0 || y >= pixelData.height) {
4053
4774
  throw new Error("Coordinates out of bounds.");