@luma.gl/core 9.3.0-alpha.4 → 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 (252) hide show
  1. package/dist/adapter/canvas-context.d.ts +6 -182
  2. package/dist/adapter/canvas-context.d.ts.map +1 -1
  3. package/dist/adapter/canvas-context.js +5 -481
  4. package/dist/adapter/canvas-context.js.map +1 -1
  5. package/dist/adapter/canvas-observer.d.ts +32 -0
  6. package/dist/adapter/canvas-observer.d.ts.map +1 -0
  7. package/dist/adapter/canvas-observer.js +90 -0
  8. package/dist/adapter/canvas-observer.js.map +1 -0
  9. package/dist/adapter/canvas-surface.d.ts +150 -0
  10. package/dist/adapter/canvas-surface.d.ts.map +1 -0
  11. package/dist/adapter/canvas-surface.js +392 -0
  12. package/dist/adapter/canvas-surface.js.map +1 -0
  13. package/dist/adapter/device.d.ts +76 -11
  14. package/dist/adapter/device.d.ts.map +1 -1
  15. package/dist/adapter/device.js +180 -9
  16. package/dist/adapter/device.js.map +1 -1
  17. package/dist/adapter/luma.js +1 -1
  18. package/dist/adapter/presentation-context.d.ts +11 -0
  19. package/dist/adapter/presentation-context.d.ts.map +1 -0
  20. package/dist/adapter/presentation-context.js +12 -0
  21. package/dist/adapter/presentation-context.js.map +1 -0
  22. package/dist/adapter/resources/buffer.d.ts +1 -1
  23. package/dist/adapter/resources/buffer.d.ts.map +1 -1
  24. package/dist/adapter/resources/buffer.js +14 -6
  25. package/dist/adapter/resources/buffer.js.map +1 -1
  26. package/dist/adapter/resources/command-buffer.d.ts +3 -1
  27. package/dist/adapter/resources/command-buffer.d.ts.map +1 -1
  28. package/dist/adapter/resources/command-buffer.js +3 -1
  29. package/dist/adapter/resources/command-buffer.js.map +1 -1
  30. package/dist/adapter/resources/command-encoder.d.ts +25 -2
  31. package/dist/adapter/resources/command-encoder.d.ts.map +1 -1
  32. package/dist/adapter/resources/command-encoder.js +68 -2
  33. package/dist/adapter/resources/command-encoder.js.map +1 -1
  34. package/dist/adapter/resources/compute-pipeline.d.ts +2 -2
  35. package/dist/adapter/resources/compute-pipeline.d.ts.map +1 -1
  36. package/dist/adapter/resources/fence.d.ts +1 -1
  37. package/dist/adapter/resources/fence.d.ts.map +1 -1
  38. package/dist/adapter/resources/fence.js +3 -1
  39. package/dist/adapter/resources/fence.js.map +1 -1
  40. package/dist/adapter/resources/framebuffer.d.ts +1 -1
  41. package/dist/adapter/resources/framebuffer.d.ts.map +1 -1
  42. package/dist/adapter/resources/query-set.d.ts +17 -1
  43. package/dist/adapter/resources/query-set.d.ts.map +1 -1
  44. package/dist/adapter/resources/query-set.js.map +1 -1
  45. package/dist/adapter/resources/render-pipeline.d.ts +28 -10
  46. package/dist/adapter/resources/render-pipeline.d.ts.map +1 -1
  47. package/dist/adapter/resources/render-pipeline.js +21 -2
  48. package/dist/adapter/resources/render-pipeline.js.map +1 -1
  49. package/dist/adapter/resources/resource.d.ts +8 -0
  50. package/dist/adapter/resources/resource.d.ts.map +1 -1
  51. package/dist/adapter/resources/resource.js +240 -14
  52. package/dist/adapter/resources/resource.js.map +1 -1
  53. package/dist/adapter/resources/shared-render-pipeline.d.ts +22 -0
  54. package/dist/adapter/resources/shared-render-pipeline.d.ts.map +1 -0
  55. package/dist/adapter/resources/shared-render-pipeline.js +25 -0
  56. package/dist/adapter/resources/shared-render-pipeline.js.map +1 -0
  57. package/dist/adapter/resources/texture-view.d.ts +1 -1
  58. package/dist/adapter/resources/texture-view.d.ts.map +1 -1
  59. package/dist/adapter/resources/texture.d.ts +82 -15
  60. package/dist/adapter/resources/texture.d.ts.map +1 -1
  61. package/dist/adapter/resources/texture.js +186 -33
  62. package/dist/adapter/resources/texture.js.map +1 -1
  63. package/dist/adapter/types/attachments.d.ts +1 -1
  64. package/dist/adapter/types/attachments.d.ts.map +1 -1
  65. package/dist/adapter/types/buffer-layout.d.ts +1 -1
  66. package/dist/adapter/types/buffer-layout.d.ts.map +1 -1
  67. package/dist/adapter/types/parameters.d.ts +3 -1
  68. package/dist/adapter/types/parameters.d.ts.map +1 -1
  69. package/dist/adapter/types/parameters.js +1 -0
  70. package/dist/adapter/types/parameters.js.map +1 -1
  71. package/dist/adapter/types/shader-layout.d.ts +10 -6
  72. package/dist/adapter/types/shader-layout.d.ts.map +1 -1
  73. package/dist/adapter/types/uniforms.d.ts +6 -0
  74. package/dist/adapter/types/uniforms.d.ts.map +1 -1
  75. package/dist/adapter-utils/bind-groups.d.ts +9 -0
  76. package/dist/adapter-utils/bind-groups.d.ts.map +1 -0
  77. package/dist/adapter-utils/bind-groups.js +41 -0
  78. package/dist/adapter-utils/bind-groups.js.map +1 -0
  79. package/dist/adapter-utils/get-attribute-from-layouts.d.ts +2 -2
  80. package/dist/adapter-utils/get-attribute-from-layouts.d.ts.map +1 -1
  81. package/dist/adapter-utils/get-attribute-from-layouts.js +6 -6
  82. package/dist/adapter-utils/get-attribute-from-layouts.js.map +1 -1
  83. package/dist/dist.dev.js +1934 -415
  84. package/dist/dist.min.js +6 -6
  85. package/dist/factories/bind-group-factory.d.ts +20 -0
  86. package/dist/factories/bind-group-factory.d.ts.map +1 -0
  87. package/dist/factories/bind-group-factory.js +79 -0
  88. package/dist/factories/bind-group-factory.js.map +1 -0
  89. package/dist/factories/core-module-state.d.ts +7 -0
  90. package/dist/factories/core-module-state.d.ts.map +1 -0
  91. package/dist/{shadertypes/data-types/shader-types.js → factories/core-module-state.js} +1 -1
  92. package/dist/factories/core-module-state.js.map +1 -0
  93. package/dist/factories/pipeline-factory.d.ts +54 -0
  94. package/dist/factories/pipeline-factory.d.ts.map +1 -0
  95. package/dist/factories/pipeline-factory.js +270 -0
  96. package/dist/factories/pipeline-factory.js.map +1 -0
  97. package/dist/factories/shader-factory.d.ts +20 -0
  98. package/dist/factories/shader-factory.d.ts.map +1 -0
  99. package/dist/factories/shader-factory.js +84 -0
  100. package/dist/factories/shader-factory.js.map +1 -0
  101. package/dist/index.cjs +1858 -409
  102. package/dist/index.cjs.map +4 -4
  103. package/dist/index.d.ts +25 -14
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +15 -9
  106. package/dist/index.js.map +1 -1
  107. package/dist/portable/uniform-block.d.ts +1 -1
  108. package/dist/portable/uniform-block.d.ts.map +1 -1
  109. package/dist/portable/uniform-buffer-layout.d.ts +20 -15
  110. package/dist/portable/uniform-buffer-layout.d.ts.map +1 -1
  111. package/dist/portable/uniform-buffer-layout.js +188 -43
  112. package/dist/portable/uniform-buffer-layout.js.map +1 -1
  113. package/dist/portable/uniform-store.d.ts +5 -6
  114. package/dist/portable/uniform-store.d.ts.map +1 -1
  115. package/dist/portable/uniform-store.js +6 -3
  116. package/dist/portable/uniform-store.js.map +1 -1
  117. package/dist/shadertypes/data-types/data-type-decoder.d.ts +20 -0
  118. package/dist/shadertypes/data-types/data-type-decoder.d.ts.map +1 -0
  119. package/dist/shadertypes/data-types/data-type-decoder.js +79 -0
  120. package/dist/shadertypes/data-types/data-type-decoder.js.map +1 -0
  121. package/dist/shadertypes/data-types/data-types.d.ts +31 -12
  122. package/dist/shadertypes/data-types/data-types.d.ts.map +1 -1
  123. package/dist/{image-utils → shadertypes/image-types}/image-types.d.ts +0 -6
  124. package/dist/shadertypes/image-types/image-types.d.ts.map +1 -0
  125. package/dist/shadertypes/image-types/image-types.js.map +1 -0
  126. package/dist/shadertypes/shader-types/shader-type-decoder.d.ts +41 -0
  127. package/dist/shadertypes/shader-types/shader-type-decoder.d.ts.map +1 -0
  128. package/dist/shadertypes/{data-types/decode-shader-types.js → shader-types/shader-type-decoder.js} +43 -4
  129. package/dist/shadertypes/shader-types/shader-type-decoder.js.map +1 -0
  130. package/dist/shadertypes/shader-types/shader-types.d.ts +101 -0
  131. package/dist/shadertypes/shader-types/shader-types.d.ts.map +1 -0
  132. package/dist/shadertypes/shader-types/shader-types.js +30 -0
  133. package/dist/shadertypes/shader-types/shader-types.js.map +1 -0
  134. package/dist/shadertypes/texture-types/pixel-utils.d.ts.map +1 -0
  135. package/dist/shadertypes/texture-types/pixel-utils.js.map +1 -0
  136. package/dist/shadertypes/{textures → texture-types}/texture-format-decoder.d.ts +1 -0
  137. package/dist/shadertypes/texture-types/texture-format-decoder.d.ts.map +1 -0
  138. package/dist/shadertypes/{textures → texture-types}/texture-format-decoder.js +55 -9
  139. package/dist/shadertypes/texture-types/texture-format-decoder.js.map +1 -0
  140. package/dist/shadertypes/texture-types/texture-format-generics.d.ts +34 -0
  141. package/dist/shadertypes/texture-types/texture-format-generics.d.ts.map +1 -0
  142. package/dist/shadertypes/texture-types/texture-format-generics.js.map +1 -0
  143. package/dist/shadertypes/texture-types/texture-format-table.d.ts.map +1 -0
  144. package/dist/shadertypes/{textures → texture-types}/texture-format-table.js +10 -9
  145. package/dist/shadertypes/texture-types/texture-format-table.js.map +1 -0
  146. package/dist/shadertypes/{textures → texture-types}/texture-formats.d.ts +10 -3
  147. package/dist/shadertypes/texture-types/texture-formats.d.ts.map +1 -0
  148. package/dist/shadertypes/{textures → texture-types}/texture-formats.js +1 -0
  149. package/dist/shadertypes/texture-types/texture-formats.js.map +1 -0
  150. package/dist/shadertypes/{textures → texture-types}/texture-layout.d.ts +1 -1
  151. package/dist/shadertypes/texture-types/texture-layout.d.ts.map +1 -0
  152. package/dist/shadertypes/texture-types/texture-layout.js.map +1 -0
  153. package/dist/shadertypes/vertex-types/vertex-format-decoder.d.ts +24 -0
  154. package/dist/shadertypes/vertex-types/vertex-format-decoder.d.ts.map +1 -0
  155. package/dist/shadertypes/vertex-types/vertex-format-decoder.js +106 -0
  156. package/dist/shadertypes/vertex-types/vertex-format-decoder.js.map +1 -0
  157. package/dist/shadertypes/vertex-types/vertex-formats.d.ts +50 -0
  158. package/dist/shadertypes/vertex-types/vertex-formats.d.ts.map +1 -0
  159. package/dist/shadertypes/vertex-types/vertex-formats.js.map +1 -0
  160. package/dist/utils/array-equal.d.ts +1 -1
  161. package/dist/utils/array-equal.d.ts.map +1 -1
  162. package/dist/utils/array-equal.js +15 -9
  163. package/dist/utils/array-equal.js.map +1 -1
  164. package/dist/utils/stats-manager.d.ts.map +1 -1
  165. package/dist/utils/stats-manager.js +61 -1
  166. package/dist/utils/stats-manager.js.map +1 -1
  167. package/package.json +3 -3
  168. package/src/adapter/canvas-context.ts +7 -623
  169. package/src/adapter/canvas-observer.ts +130 -0
  170. package/src/adapter/canvas-surface.ts +521 -0
  171. package/src/adapter/device.ts +287 -21
  172. package/src/adapter/presentation-context.ts +16 -0
  173. package/src/adapter/resources/buffer.ts +13 -5
  174. package/src/adapter/resources/command-buffer.ts +3 -1
  175. package/src/adapter/resources/command-encoder.ts +94 -3
  176. package/src/adapter/resources/compute-pipeline.ts +2 -2
  177. package/src/adapter/resources/fence.ts +3 -1
  178. package/src/adapter/resources/framebuffer.ts +1 -1
  179. package/src/adapter/resources/query-set.ts +17 -1
  180. package/src/adapter/resources/render-pipeline.ts +52 -16
  181. package/src/adapter/resources/resource.ts +284 -14
  182. package/src/adapter/resources/shared-render-pipeline.ts +40 -0
  183. package/src/adapter/resources/texture-view.ts +1 -1
  184. package/src/adapter/resources/texture.ts +273 -43
  185. package/src/adapter/types/attachments.ts +1 -1
  186. package/src/adapter/types/buffer-layout.ts +1 -1
  187. package/src/adapter/types/parameters.ts +4 -1
  188. package/src/adapter/types/shader-layout.ts +15 -9
  189. package/src/adapter/types/uniforms.ts +12 -0
  190. package/src/adapter-utils/bind-groups.ts +71 -0
  191. package/src/adapter-utils/get-attribute-from-layouts.ts +8 -11
  192. package/src/factories/bind-group-factory.ts +139 -0
  193. package/src/factories/core-module-state.ts +11 -0
  194. package/src/factories/pipeline-factory.ts +328 -0
  195. package/src/factories/shader-factory.ts +103 -0
  196. package/src/index.ts +54 -26
  197. package/src/portable/uniform-block.ts +1 -1
  198. package/src/portable/uniform-buffer-layout.ts +269 -62
  199. package/src/portable/uniform-store.ts +14 -11
  200. package/src/shadertypes/data-types/data-type-decoder.ts +105 -0
  201. package/src/shadertypes/data-types/data-types.ts +100 -48
  202. package/src/{image-utils → shadertypes/image-types}/image-types.ts +0 -7
  203. package/src/shadertypes/{data-types/decode-shader-types.ts → shader-types/shader-type-decoder.ts} +88 -14
  204. package/src/shadertypes/shader-types/shader-types.ts +207 -0
  205. package/src/shadertypes/{textures → texture-types}/texture-format-decoder.ts +75 -9
  206. package/src/shadertypes/{textures → texture-types}/texture-format-generics.ts +42 -48
  207. package/src/shadertypes/{textures → texture-types}/texture-format-table.ts +10 -9
  208. package/src/shadertypes/{textures → texture-types}/texture-formats.ts +20 -3
  209. package/src/shadertypes/vertex-types/vertex-format-decoder.ts +131 -0
  210. package/src/shadertypes/vertex-types/vertex-formats.ts +183 -0
  211. package/src/utils/array-equal.ts +21 -9
  212. package/src/utils/stats-manager.ts +76 -2
  213. package/dist/image-utils/image-types.d.ts.map +0 -1
  214. package/dist/image-utils/image-types.js.map +0 -1
  215. package/dist/shadertypes/data-types/decode-shader-types.d.ts +0 -17
  216. package/dist/shadertypes/data-types/decode-shader-types.d.ts.map +0 -1
  217. package/dist/shadertypes/data-types/decode-shader-types.js.map +0 -1
  218. package/dist/shadertypes/data-types/shader-types.d.ts +0 -43
  219. package/dist/shadertypes/data-types/shader-types.d.ts.map +0 -1
  220. package/dist/shadertypes/data-types/shader-types.js.map +0 -1
  221. package/dist/shadertypes/textures/pixel-utils.d.ts.map +0 -1
  222. package/dist/shadertypes/textures/pixel-utils.js.map +0 -1
  223. package/dist/shadertypes/textures/texture-format-decoder.d.ts.map +0 -1
  224. package/dist/shadertypes/textures/texture-format-decoder.js.map +0 -1
  225. package/dist/shadertypes/textures/texture-format-generics.d.ts +0 -33
  226. package/dist/shadertypes/textures/texture-format-generics.d.ts.map +0 -1
  227. package/dist/shadertypes/textures/texture-format-generics.js.map +0 -1
  228. package/dist/shadertypes/textures/texture-format-table.d.ts.map +0 -1
  229. package/dist/shadertypes/textures/texture-format-table.js.map +0 -1
  230. package/dist/shadertypes/textures/texture-formats.d.ts.map +0 -1
  231. package/dist/shadertypes/textures/texture-formats.js.map +0 -1
  232. package/dist/shadertypes/textures/texture-layout.d.ts.map +0 -1
  233. package/dist/shadertypes/textures/texture-layout.js.map +0 -1
  234. package/dist/shadertypes/vertex-arrays/decode-vertex-format.d.ts +0 -18
  235. package/dist/shadertypes/vertex-arrays/decode-vertex-format.d.ts.map +0 -1
  236. package/dist/shadertypes/vertex-arrays/decode-vertex-format.js +0 -100
  237. package/dist/shadertypes/vertex-arrays/decode-vertex-format.js.map +0 -1
  238. package/dist/shadertypes/vertex-arrays/vertex-formats.d.ts +0 -27
  239. package/dist/shadertypes/vertex-arrays/vertex-formats.d.ts.map +0 -1
  240. package/dist/shadertypes/vertex-arrays/vertex-formats.js.map +0 -1
  241. package/src/shadertypes/data-types/shader-types.ts +0 -94
  242. package/src/shadertypes/vertex-arrays/decode-vertex-format.ts +0 -124
  243. package/src/shadertypes/vertex-arrays/vertex-formats.ts +0 -91
  244. /package/dist/{image-utils → shadertypes/image-types}/image-types.js +0 -0
  245. /package/dist/shadertypes/{textures → texture-types}/pixel-utils.d.ts +0 -0
  246. /package/dist/shadertypes/{textures → texture-types}/pixel-utils.js +0 -0
  247. /package/dist/shadertypes/{textures → texture-types}/texture-format-generics.js +0 -0
  248. /package/dist/shadertypes/{textures → texture-types}/texture-format-table.d.ts +0 -0
  249. /package/dist/shadertypes/{textures → texture-types}/texture-layout.js +0 -0
  250. /package/dist/shadertypes/{vertex-arrays → vertex-types}/vertex-formats.js +0 -0
  251. /package/src/shadertypes/{textures → texture-types}/pixel-utils.ts +0 -0
  252. /package/src/shadertypes/{textures → texture-types}/texture-layout.ts +0 -0
package/dist/index.cjs CHANGED
@@ -38,50 +38,72 @@ __export(dist_exports, {
38
38
  ExternalTexture: () => ExternalTexture,
39
39
  Fence: () => Fence,
40
40
  Framebuffer: () => Framebuffer,
41
+ PipelineFactory: () => PipelineFactory,
41
42
  PipelineLayout: () => PipelineLayout,
43
+ PresentationContext: () => PresentationContext,
42
44
  QuerySet: () => QuerySet,
43
45
  RenderPass: () => RenderPass,
44
46
  RenderPipeline: () => RenderPipeline,
45
47
  Resource: () => Resource,
46
48
  Sampler: () => Sampler,
47
49
  Shader: () => Shader,
50
+ ShaderFactory: () => ShaderFactory,
51
+ SharedRenderPipeline: () => SharedRenderPipeline,
48
52
  Texture: () => Texture,
49
- TextureFormatDecoder: () => TextureFormatDecoder,
50
53
  TextureView: () => TextureView,
51
54
  TransformFeedback: () => TransformFeedback,
52
55
  UniformBlock: () => UniformBlock,
53
56
  UniformBufferLayout: () => UniformBufferLayout,
54
57
  UniformStore: () => UniformStore,
55
58
  VertexArray: () => VertexArray,
59
+ _getDefaultBindGroupFactory: () => _getDefaultBindGroupFactory,
56
60
  _getTextureFormatDefinition: () => getTextureFormatDefinition,
57
61
  _getTextureFormatTable: () => getTextureFormatTable,
58
62
  assert: () => assert,
59
63
  assertDefined: () => assertDefined,
64
+ dataTypeDecoder: () => dataTypeDecoder,
65
+ flattenBindingsByGroup: () => flattenBindingsByGroup,
60
66
  getAttributeInfosFromLayouts: () => getAttributeInfosFromLayouts,
61
67
  getAttributeShaderTypeInfo: () => getAttributeShaderTypeInfo,
62
- getDataType: () => getDataType,
63
- getDataTypeInfo: () => getDataTypeInfo,
64
68
  getExternalImageSize: () => getExternalImageSize,
65
- getNormalizedDataType: () => getNormalizedDataType,
66
69
  getScratchArray: () => getScratchArray,
70
+ getShaderLayoutBinding: () => getShaderLayoutBinding,
67
71
  getTextureImageView: () => getTextureImageView,
68
72
  getTypedArrayConstructor: () => getTypedArrayConstructor,
69
73
  getVariableShaderTypeInfo: () => getVariableShaderTypeInfo,
70
- getVertexFormatFromAttribute: () => getVertexFormatFromAttribute,
71
- getVertexFormatInfo: () => getVertexFormatInfo,
72
74
  isExternalImage: () => isExternalImage,
73
75
  log: () => log,
74
76
  luma: () => luma,
75
- makeVertexFormat: () => makeVertexFormat,
77
+ normalizeBindingsByGroup: () => normalizeBindingsByGroup,
76
78
  readPixel: () => readPixel,
77
79
  setTextureImageData: () => setTextureImageData,
80
+ shaderTypeDecoder: () => shaderTypeDecoder,
78
81
  textureFormatDecoder: () => textureFormatDecoder,
82
+ vertexFormatDecoder: () => vertexFormatDecoder,
79
83
  writePixel: () => writePixel
80
84
  });
81
85
  module.exports = __toCommonJS(dist_exports);
82
86
 
83
87
  // dist/utils/stats-manager.js
84
88
  var import_stats = require("@probe.gl/stats");
89
+ var GPU_TIME_AND_MEMORY_STATS = "GPU Time and Memory";
90
+ var GPU_TIME_AND_MEMORY_STAT_ORDER = [
91
+ "Adapter",
92
+ "GPU",
93
+ "GPU Type",
94
+ "GPU Backend",
95
+ "Frame Rate",
96
+ "CPU Time",
97
+ "GPU Time",
98
+ "GPU Memory",
99
+ "Buffer Memory",
100
+ "Texture Memory",
101
+ "Referenced Buffer Memory",
102
+ "Referenced Texture Memory",
103
+ "Swap Chain Texture"
104
+ ];
105
+ var ORDERED_STATS_CACHE = /* @__PURE__ */ new WeakMap();
106
+ var ORDERED_STAT_NAME_SET_CACHE = /* @__PURE__ */ new WeakMap();
85
107
  var StatsManager = class {
86
108
  stats = /* @__PURE__ */ new Map();
87
109
  getStats(name2) {
@@ -91,10 +113,50 @@ var StatsManager = class {
91
113
  if (!this.stats.has(name2)) {
92
114
  this.stats.set(name2, new import_stats.Stats({ id: name2 }));
93
115
  }
94
- return this.stats.get(name2);
116
+ const stats = this.stats.get(name2);
117
+ if (name2 === GPU_TIME_AND_MEMORY_STATS) {
118
+ initializeStats(stats, GPU_TIME_AND_MEMORY_STAT_ORDER);
119
+ }
120
+ return stats;
95
121
  }
96
122
  };
97
123
  var lumaStats = new StatsManager();
124
+ function initializeStats(stats, orderedStatNames) {
125
+ const statsMap = stats.stats;
126
+ let addedOrderedStat = false;
127
+ for (const statName of orderedStatNames) {
128
+ if (!statsMap[statName]) {
129
+ stats.get(statName);
130
+ addedOrderedStat = true;
131
+ }
132
+ }
133
+ const statCount = Object.keys(statsMap).length;
134
+ const cachedStats = ORDERED_STATS_CACHE.get(stats);
135
+ if (!addedOrderedStat && (cachedStats == null ? void 0 : cachedStats.orderedStatNames) === orderedStatNames && cachedStats.statCount === statCount) {
136
+ return;
137
+ }
138
+ const reorderedStats = {};
139
+ let orderedStatNamesSet = ORDERED_STAT_NAME_SET_CACHE.get(orderedStatNames);
140
+ if (!orderedStatNamesSet) {
141
+ orderedStatNamesSet = new Set(orderedStatNames);
142
+ ORDERED_STAT_NAME_SET_CACHE.set(orderedStatNames, orderedStatNamesSet);
143
+ }
144
+ for (const statName of orderedStatNames) {
145
+ if (statsMap[statName]) {
146
+ reorderedStats[statName] = statsMap[statName];
147
+ }
148
+ }
149
+ for (const [statName, stat] of Object.entries(statsMap)) {
150
+ if (!orderedStatNamesSet.has(statName)) {
151
+ reorderedStats[statName] = stat;
152
+ }
153
+ }
154
+ for (const statName of Object.keys(statsMap)) {
155
+ delete statsMap[statName];
156
+ }
157
+ Object.assign(statsMap, reorderedStats);
158
+ ORDERED_STATS_CACHE.set(stats, { orderedStatNames, statCount });
159
+ }
98
160
 
99
161
  // dist/utils/log.js
100
162
  var import_log = require("@probe.gl/log");
@@ -109,6 +171,57 @@ function uid(id = "id") {
109
171
  }
110
172
 
111
173
  // dist/adapter/resources/resource.js
174
+ var CPU_HOTSPOT_PROFILER_MODULE = "cpu-hotspot-profiler";
175
+ var RESOURCE_COUNTS_STATS = "GPU Resource Counts";
176
+ var LEGACY_RESOURCE_COUNTS_STATS = "Resource Counts";
177
+ var GPU_TIME_AND_MEMORY_STATS2 = "GPU Time and Memory";
178
+ var BASE_RESOURCE_COUNT_ORDER = [
179
+ "Resources",
180
+ "Buffers",
181
+ "Textures",
182
+ "Samplers",
183
+ "TextureViews",
184
+ "Framebuffers",
185
+ "QuerySets",
186
+ "Shaders",
187
+ "RenderPipelines",
188
+ "ComputePipelines",
189
+ "PipelineLayouts",
190
+ "VertexArrays",
191
+ "RenderPasss",
192
+ "ComputePasss",
193
+ "CommandEncoders",
194
+ "CommandBuffers"
195
+ ];
196
+ var WEBGL_RESOURCE_COUNT_ORDER = [
197
+ "Resources",
198
+ "Buffers",
199
+ "Textures",
200
+ "Samplers",
201
+ "TextureViews",
202
+ "Framebuffers",
203
+ "QuerySets",
204
+ "Shaders",
205
+ "RenderPipelines",
206
+ "SharedRenderPipelines",
207
+ "ComputePipelines",
208
+ "PipelineLayouts",
209
+ "VertexArrays",
210
+ "RenderPasss",
211
+ "ComputePasss",
212
+ "CommandEncoders",
213
+ "CommandBuffers"
214
+ ];
215
+ var BASE_RESOURCE_COUNT_STAT_ORDER = BASE_RESOURCE_COUNT_ORDER.flatMap((resourceType) => [
216
+ `${resourceType} Created`,
217
+ `${resourceType} Active`
218
+ ]);
219
+ var WEBGL_RESOURCE_COUNT_STAT_ORDER = WEBGL_RESOURCE_COUNT_ORDER.flatMap((resourceType) => [
220
+ `${resourceType} Created`,
221
+ `${resourceType} Active`
222
+ ]);
223
+ var ORDERED_STATS_CACHE2 = /* @__PURE__ */ new WeakMap();
224
+ var ORDERED_STAT_NAME_SET_CACHE2 = /* @__PURE__ */ new WeakMap();
112
225
  var Resource = class {
113
226
  toString() {
114
227
  return `${this[Symbol.toStringTag] || this.constructor.name}:"${this.id}"`;
@@ -125,6 +238,8 @@ var Resource = class {
125
238
  destroyed = false;
126
239
  /** For resources that allocate GPU memory */
127
240
  allocatedBytes = 0;
241
+ /** Stats bucket currently holding the tracked allocation */
242
+ allocatedBytesName = null;
128
243
  /** Attached resources will be destroyed when this resource is destroyed. Tracks auto-created "sub" resources. */
129
244
  _attachedResources = /* @__PURE__ */ new Set();
130
245
  /**
@@ -146,6 +261,9 @@ var Resource = class {
146
261
  * destroy can be called on any resource to release it before it is garbage collected.
147
262
  */
148
263
  destroy() {
264
+ if (this.destroyed) {
265
+ return;
266
+ }
149
267
  this.destroyResource();
150
268
  }
151
269
  /** @deprecated Use destroy() */
@@ -184,7 +302,7 @@ var Resource = class {
184
302
  }
185
303
  /** Destroy all owned resources. Make sure the resources are no longer needed before calling. */
186
304
  destroyAttachedResources() {
187
- for (const resource of Object.values(this._attachedResources)) {
305
+ for (const resource of this._attachedResources) {
188
306
  resource.destroy();
189
307
  }
190
308
  this._attachedResources = /* @__PURE__ */ new Set();
@@ -192,37 +310,107 @@ var Resource = class {
192
310
  // PROTECTED METHODS
193
311
  /** Perform all destroy steps. Can be called by derived resources when overriding destroy() */
194
312
  destroyResource() {
313
+ if (this.destroyed) {
314
+ return;
315
+ }
195
316
  this.destroyAttachedResources();
196
317
  this.removeStats();
197
318
  this.destroyed = true;
198
319
  }
199
320
  /** Called by .destroy() to track object destruction. Subclass must call if overriding destroy() */
200
321
  removeStats() {
201
- const stats = this._device.statsManager.getStats("Resource Counts");
202
- const name2 = this[Symbol.toStringTag];
203
- stats.get(`${name2}s Active`).decrementCount();
322
+ const profiler = getCpuHotspotProfiler(this._device);
323
+ const startTime = profiler ? getTimestamp() : 0;
324
+ const statsObjects = [
325
+ this._device.statsManager.getStats(RESOURCE_COUNTS_STATS),
326
+ this._device.statsManager.getStats(LEGACY_RESOURCE_COUNTS_STATS)
327
+ ];
328
+ const orderedStatNames = getResourceCountStatOrder(this._device);
329
+ for (const stats of statsObjects) {
330
+ initializeStats2(stats, orderedStatNames);
331
+ }
332
+ const name2 = this.getStatsName();
333
+ for (const stats of statsObjects) {
334
+ stats.get("Resources Active").decrementCount();
335
+ stats.get(`${name2}s Active`).decrementCount();
336
+ }
337
+ if (profiler) {
338
+ profiler.statsBookkeepingCalls = (profiler.statsBookkeepingCalls || 0) + 1;
339
+ profiler.statsBookkeepingTimeMs = (profiler.statsBookkeepingTimeMs || 0) + (getTimestamp() - startTime);
340
+ }
204
341
  }
205
342
  /** Called by subclass to track memory allocations */
206
- trackAllocatedMemory(bytes, name2 = this[Symbol.toStringTag]) {
207
- const stats = this._device.statsManager.getStats("Resource Counts");
343
+ trackAllocatedMemory(bytes, name2 = this.getStatsName()) {
344
+ const profiler = getCpuHotspotProfiler(this._device);
345
+ const startTime = profiler ? getTimestamp() : 0;
346
+ const stats = this._device.statsManager.getStats(GPU_TIME_AND_MEMORY_STATS2);
347
+ if (this.allocatedBytes > 0 && this.allocatedBytesName) {
348
+ stats.get("GPU Memory").subtractCount(this.allocatedBytes);
349
+ stats.get(`${this.allocatedBytesName} Memory`).subtractCount(this.allocatedBytes);
350
+ }
208
351
  stats.get("GPU Memory").addCount(bytes);
209
352
  stats.get(`${name2} Memory`).addCount(bytes);
353
+ if (profiler) {
354
+ profiler.statsBookkeepingCalls = (profiler.statsBookkeepingCalls || 0) + 1;
355
+ profiler.statsBookkeepingTimeMs = (profiler.statsBookkeepingTimeMs || 0) + (getTimestamp() - startTime);
356
+ }
210
357
  this.allocatedBytes = bytes;
358
+ this.allocatedBytesName = name2;
359
+ }
360
+ /** Called by subclass to track handle-backed memory allocations separately from owned allocations */
361
+ trackReferencedMemory(bytes, name2 = this.getStatsName()) {
362
+ this.trackAllocatedMemory(bytes, `Referenced ${name2}`);
211
363
  }
212
364
  /** Called by subclass to track memory deallocations */
213
- trackDeallocatedMemory(name2 = this[Symbol.toStringTag]) {
214
- const stats = this._device.statsManager.getStats("Resource Counts");
365
+ trackDeallocatedMemory(name2 = this.getStatsName()) {
366
+ if (this.allocatedBytes === 0) {
367
+ this.allocatedBytesName = null;
368
+ return;
369
+ }
370
+ const profiler = getCpuHotspotProfiler(this._device);
371
+ const startTime = profiler ? getTimestamp() : 0;
372
+ const stats = this._device.statsManager.getStats(GPU_TIME_AND_MEMORY_STATS2);
215
373
  stats.get("GPU Memory").subtractCount(this.allocatedBytes);
216
- stats.get(`${name2} Memory`).subtractCount(this.allocatedBytes);
374
+ stats.get(`${this.allocatedBytesName || name2} Memory`).subtractCount(this.allocatedBytes);
375
+ if (profiler) {
376
+ profiler.statsBookkeepingCalls = (profiler.statsBookkeepingCalls || 0) + 1;
377
+ profiler.statsBookkeepingTimeMs = (profiler.statsBookkeepingTimeMs || 0) + (getTimestamp() - startTime);
378
+ }
217
379
  this.allocatedBytes = 0;
380
+ this.allocatedBytesName = null;
381
+ }
382
+ /** Called by subclass to deallocate handle-backed memory tracked via trackReferencedMemory() */
383
+ trackDeallocatedReferencedMemory(name2 = this.getStatsName()) {
384
+ this.trackDeallocatedMemory(`Referenced ${name2}`);
218
385
  }
219
386
  /** Called by resource constructor to track object creation */
220
387
  addStats() {
221
- const stats = this._device.statsManager.getStats("Resource Counts");
222
- const name2 = this[Symbol.toStringTag];
223
- stats.get("Resources Created").incrementCount();
224
- stats.get(`${name2}s Created`).incrementCount();
225
- stats.get(`${name2}s Active`).incrementCount();
388
+ const name2 = this.getStatsName();
389
+ const profiler = getCpuHotspotProfiler(this._device);
390
+ const startTime = profiler ? getTimestamp() : 0;
391
+ const statsObjects = [
392
+ this._device.statsManager.getStats(RESOURCE_COUNTS_STATS),
393
+ this._device.statsManager.getStats(LEGACY_RESOURCE_COUNTS_STATS)
394
+ ];
395
+ const orderedStatNames = getResourceCountStatOrder(this._device);
396
+ for (const stats of statsObjects) {
397
+ initializeStats2(stats, orderedStatNames);
398
+ }
399
+ for (const stats of statsObjects) {
400
+ stats.get("Resources Created").incrementCount();
401
+ stats.get("Resources Active").incrementCount();
402
+ stats.get(`${name2}s Created`).incrementCount();
403
+ stats.get(`${name2}s Active`).incrementCount();
404
+ }
405
+ if (profiler) {
406
+ profiler.statsBookkeepingCalls = (profiler.statsBookkeepingCalls || 0) + 1;
407
+ profiler.statsBookkeepingTimeMs = (profiler.statsBookkeepingTimeMs || 0) + (getTimestamp() - startTime);
408
+ }
409
+ recordTransientCanvasResourceCreate(this._device, name2);
410
+ }
411
+ /** Canonical resource name used for stats buckets. */
412
+ getStatsName() {
413
+ return getCanonicalResourceName(this);
226
414
  }
227
415
  };
228
416
  /** Default properties for resource */
@@ -240,6 +428,97 @@ function selectivelyMerge(props, defaultProps) {
240
428
  }
241
429
  return mergedProps;
242
430
  }
431
+ function initializeStats2(stats, orderedStatNames) {
432
+ const statsMap = stats.stats;
433
+ let addedOrderedStat = false;
434
+ for (const statName of orderedStatNames) {
435
+ if (!statsMap[statName]) {
436
+ stats.get(statName);
437
+ addedOrderedStat = true;
438
+ }
439
+ }
440
+ const statCount = Object.keys(statsMap).length;
441
+ const cachedStats = ORDERED_STATS_CACHE2.get(stats);
442
+ if (!addedOrderedStat && (cachedStats == null ? void 0 : cachedStats.orderedStatNames) === orderedStatNames && cachedStats.statCount === statCount) {
443
+ return;
444
+ }
445
+ const reorderedStats = {};
446
+ let orderedStatNamesSet = ORDERED_STAT_NAME_SET_CACHE2.get(orderedStatNames);
447
+ if (!orderedStatNamesSet) {
448
+ orderedStatNamesSet = new Set(orderedStatNames);
449
+ ORDERED_STAT_NAME_SET_CACHE2.set(orderedStatNames, orderedStatNamesSet);
450
+ }
451
+ for (const statName of orderedStatNames) {
452
+ if (statsMap[statName]) {
453
+ reorderedStats[statName] = statsMap[statName];
454
+ }
455
+ }
456
+ for (const [statName, stat] of Object.entries(statsMap)) {
457
+ if (!orderedStatNamesSet.has(statName)) {
458
+ reorderedStats[statName] = stat;
459
+ }
460
+ }
461
+ for (const statName of Object.keys(statsMap)) {
462
+ delete statsMap[statName];
463
+ }
464
+ Object.assign(statsMap, reorderedStats);
465
+ ORDERED_STATS_CACHE2.set(stats, { orderedStatNames, statCount });
466
+ }
467
+ function getResourceCountStatOrder(device) {
468
+ return device.type === "webgl" ? WEBGL_RESOURCE_COUNT_STAT_ORDER : BASE_RESOURCE_COUNT_STAT_ORDER;
469
+ }
470
+ function getCpuHotspotProfiler(device) {
471
+ const profiler = device.userData[CPU_HOTSPOT_PROFILER_MODULE];
472
+ return (profiler == null ? void 0 : profiler.enabled) ? profiler : null;
473
+ }
474
+ function getTimestamp() {
475
+ var _a, _b;
476
+ return ((_b = (_a = globalThis.performance) == null ? void 0 : _a.now) == null ? void 0 : _b.call(_a)) ?? Date.now();
477
+ }
478
+ function recordTransientCanvasResourceCreate(device, name2) {
479
+ const profiler = getCpuHotspotProfiler(device);
480
+ if (!profiler || !profiler.activeDefaultFramebufferAcquireDepth) {
481
+ return;
482
+ }
483
+ profiler.transientCanvasResourceCreates = (profiler.transientCanvasResourceCreates || 0) + 1;
484
+ switch (name2) {
485
+ case "Texture":
486
+ profiler.transientCanvasTextureCreates = (profiler.transientCanvasTextureCreates || 0) + 1;
487
+ break;
488
+ case "TextureView":
489
+ profiler.transientCanvasTextureViewCreates = (profiler.transientCanvasTextureViewCreates || 0) + 1;
490
+ break;
491
+ case "Sampler":
492
+ profiler.transientCanvasSamplerCreates = (profiler.transientCanvasSamplerCreates || 0) + 1;
493
+ break;
494
+ case "Framebuffer":
495
+ profiler.transientCanvasFramebufferCreates = (profiler.transientCanvasFramebufferCreates || 0) + 1;
496
+ break;
497
+ default:
498
+ break;
499
+ }
500
+ }
501
+ function getCanonicalResourceName(resource) {
502
+ let prototype = Object.getPrototypeOf(resource);
503
+ while (prototype) {
504
+ const parentPrototype = Object.getPrototypeOf(prototype);
505
+ if (!parentPrototype || parentPrototype === Resource.prototype) {
506
+ return getPrototypeToStringTag(prototype) || resource[Symbol.toStringTag] || resource.constructor.name;
507
+ }
508
+ prototype = parentPrototype;
509
+ }
510
+ return resource[Symbol.toStringTag] || resource.constructor.name;
511
+ }
512
+ function getPrototypeToStringTag(prototype) {
513
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, Symbol.toStringTag);
514
+ if (typeof (descriptor == null ? void 0 : descriptor.get) === "function") {
515
+ return descriptor.get.call(prototype);
516
+ }
517
+ if (typeof (descriptor == null ? void 0 : descriptor.value) === "string") {
518
+ return descriptor.value;
519
+ }
520
+ return null;
521
+ }
243
522
 
244
523
  // dist/adapter/resources/buffer.js
245
524
  var _Buffer = class extends Resource {
@@ -279,15 +558,23 @@ var _Buffer = class extends Resource {
279
558
  /** A partial CPU-side copy of the data in this buffer, for debugging purposes */
280
559
  debugData = new ArrayBuffer(0);
281
560
  /** This doesn't handle partial non-zero offset updates correctly */
282
- _setDebugData(data, byteOffset, byteLength) {
283
- const arrayBuffer2 = ArrayBuffer.isView(data) ? data.buffer : data;
561
+ _setDebugData(data, _byteOffset, byteLength) {
562
+ let arrayBufferView = null;
563
+ let arrayBuffer2;
564
+ if (ArrayBuffer.isView(data)) {
565
+ arrayBufferView = data;
566
+ arrayBuffer2 = data.buffer;
567
+ } else {
568
+ arrayBuffer2 = data;
569
+ }
284
570
  const debugDataLength = Math.min(data ? data.byteLength : byteLength, _Buffer.DEBUG_DATA_MAX_LENGTH);
285
571
  if (arrayBuffer2 === null) {
286
572
  this.debugData = new ArrayBuffer(debugDataLength);
287
- } else if (byteOffset === 0 && byteLength === arrayBuffer2.byteLength) {
288
- this.debugData = arrayBuffer2.slice(0, debugDataLength);
289
573
  } else {
290
- this.debugData = arrayBuffer2.slice(byteOffset, byteOffset + debugDataLength);
574
+ const sourceByteOffset = Math.min((arrayBufferView == null ? void 0 : arrayBufferView.byteOffset) || 0, arrayBuffer2.byteLength);
575
+ const availableByteLength = Math.max(0, arrayBuffer2.byteLength - sourceByteOffset);
576
+ const copyByteLength = Math.min(debugDataLength, availableByteLength);
577
+ this.debugData = new Uint8Array(arrayBuffer2, sourceByteOffset, copyByteLength).slice().buffer;
291
578
  }
292
579
  }
293
580
  };
@@ -321,62 +608,73 @@ __publicField(Buffer2, "defaultProps", {
321
608
  onMapped: void 0
322
609
  });
323
610
 
324
- // dist/shadertypes/data-types/decode-data-types.js
325
- function getDataTypeInfo(type) {
326
- const normalized = type.includes("norm");
327
- const integer = !normalized && !type.startsWith("float");
328
- const signed = type.startsWith("s");
329
- const typeInfo = NORMALIZED_TYPE_MAP[type];
330
- const [signedType, primitiveType, byteLength] = typeInfo || ["uint8 ", "i32", 1];
331
- return {
332
- signedType,
333
- primitiveType,
334
- byteLength,
335
- normalized,
336
- integer,
337
- signed
338
- };
339
- }
340
- function getNormalizedDataType(signedDataType) {
341
- const dataType = signedDataType;
342
- switch (dataType) {
343
- case "uint8":
344
- return "unorm8";
345
- case "sint8":
346
- return "snorm8";
347
- case "uint16":
348
- return "unorm16";
349
- case "sint16":
350
- return "snorm16";
351
- default:
352
- 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
+ };
353
631
  }
354
- }
355
- function alignTo(size, count) {
356
- switch (count) {
357
- case 1:
358
- return size;
359
- case 2:
360
- return size + size % 2;
361
- default:
362
- 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
+ }
363
647
  }
364
- }
365
- function getDataType(arrayOrType) {
366
- const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
367
- if (Constructor === Uint8ClampedArray) {
368
- 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
+ }
369
658
  }
370
- const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
371
- if (!info) {
372
- 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];
373
670
  }
374
- return info[0];
375
- }
376
- function getTypedArrayConstructor(type) {
377
- const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
378
- return Constructor;
379
- }
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();
380
678
  var NORMALIZED_TYPE_MAP = {
381
679
  uint8: ["uint8", "u32", 1, false, Uint8Array],
382
680
  sint8: ["sint8", "i32", 1, false, Int8Array],
@@ -392,87 +690,99 @@ var NORMALIZED_TYPE_MAP = {
392
690
  sint32: ["sint32", "i32", 4, false, Int32Array]
393
691
  };
394
692
 
395
- // dist/shadertypes/vertex-arrays/decode-vertex-format.js
396
- function getVertexFormatInfo(format) {
397
- let webglOnly;
398
- if (format.endsWith("-webgl")) {
399
- format.replace("-webgl", "");
400
- webglOnly = true;
401
- }
402
- const [type_, count] = format.split("x");
403
- const type = type_;
404
- const components = count ? parseInt(count) : 1;
405
- const decodedType = getDataTypeInfo(type);
406
- const result = {
407
- type,
408
- components,
409
- byteLength: decodedType.byteLength * components,
410
- integer: decodedType.integer,
411
- signed: decodedType.signed,
412
- normalized: decodedType.normalized
413
- };
414
- if (webglOnly) {
415
- result.webglOnly = true;
416
- }
417
- return result;
418
- }
419
- function makeVertexFormat(signedDataType, components, normalized) {
420
- const dataType = normalized ? getNormalizedDataType(signedDataType) : signedDataType;
421
- switch (dataType) {
422
- case "unorm8":
423
- if (components === 1) {
424
- return "unorm8";
425
- }
426
- if (components === 3) {
427
- return "unorm8x3-webgl";
428
- }
429
- return `${dataType}x${components}`;
430
- case "snorm8":
431
- case "uint8":
432
- case "sint8":
433
- case "uint16":
434
- case "sint16":
435
- case "unorm16":
436
- case "snorm16":
437
- case "float16":
438
- if (components === 1 || components === 3) {
439
- throw new Error(`size: ${components}`);
440
- }
441
- return `${dataType}x${components}`;
442
- default:
443
- return components === 1 ? dataType : `${dataType}x${components}`;
444
- }
445
- }
446
- function getVertexFormatFromAttribute(typedArray, size, normalized) {
447
- if (!size || size > 4) {
448
- 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
+ }
449
748
  }
450
- const components = size;
451
- const signedDataType = getDataType(typedArray);
452
- return makeVertexFormat(signedDataType, components, normalized);
453
- }
454
- function getCompatibleVertexFormat(opts) {
455
- let vertexType;
456
- switch (opts.primitiveType) {
457
- case "f32":
458
- vertexType = "float32";
459
- break;
460
- case "i32":
461
- vertexType = "sint32";
462
- break;
463
- case "u32":
464
- vertexType = "uint32";
465
- break;
466
- case "f16":
467
- 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);
468
757
  }
469
- if (opts.components === 1) {
470
- 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}`;
471
781
  }
472
- return `${vertexType}x${opts.components}`;
473
- }
782
+ };
783
+ var vertexFormatDecoder = new VertexFormatDecoder();
474
784
 
475
- // dist/shadertypes/textures/texture-format-table.js
785
+ // dist/shadertypes/texture-types/texture-format-table.js
476
786
  var texture_compression_bc = "texture-compression-bc";
477
787
  var texture_compression_astc = "texture-compression-astc";
478
788
  var texture_compression_etc2 = "texture-compression-etc2";
@@ -483,6 +793,7 @@ var float32_renderable = "float32-renderable-webgl";
483
793
  var float16_renderable = "float16-renderable-webgl";
484
794
  var rgb9e5ufloat_renderable = "rgb9e5ufloat-renderable-webgl";
485
795
  var snorm8_renderable = "snorm8-renderable-webgl";
796
+ var norm16_webgl = "norm16-webgl";
486
797
  var norm16_renderable = "norm16-renderable-webgl";
487
798
  var snorm16_renderable = "snorm16-renderable-webgl";
488
799
  var float32_filterable = "float32-filterable";
@@ -516,16 +827,16 @@ var TEXTURE_FORMAT_COLOR_DEPTH_TABLE = {
516
827
  "rgba8sint": {},
517
828
  "bgra8unorm": {},
518
829
  "bgra8unorm-srgb": {},
519
- "r16unorm": { f: norm16_renderable },
520
- "rg16unorm": { render: norm16_renderable },
521
- "rgb16unorm-webgl": { f: norm16_renderable },
830
+ "r16unorm": { f: norm16_webgl, render: norm16_renderable },
831
+ "rg16unorm": { f: norm16_webgl, render: norm16_renderable },
832
+ "rgb16unorm-webgl": { f: norm16_webgl, render: false },
522
833
  // rgb not renderable
523
- "rgba16unorm": { render: norm16_renderable },
524
- "r16snorm": { f: snorm16_renderable },
525
- "rg16snorm": { render: snorm16_renderable },
526
- "rgb16snorm-webgl": { f: norm16_renderable },
834
+ "rgba16unorm": { f: norm16_webgl, render: norm16_renderable },
835
+ "r16snorm": { f: norm16_webgl, render: snorm16_renderable },
836
+ "rg16snorm": { f: norm16_webgl, render: snorm16_renderable },
837
+ "rgb16snorm-webgl": { f: norm16_webgl, render: false },
527
838
  // rgb not renderable
528
- "rgba16snorm": { render: snorm16_renderable },
839
+ "rgba16snorm": { f: norm16_webgl, render: snorm16_renderable },
529
840
  "r16uint": {},
530
841
  "rg16uint": {},
531
842
  "rgba16uint": {},
@@ -628,7 +939,7 @@ var TEXTURE_FORMAT_COMPRESSED_TABLE = {
628
939
  // WEBGL_compressed_texture_pvrtc
629
940
  "pvrtc-rgb4unorm-webgl": { f: texture_compression_pvrtc_webgl },
630
941
  "pvrtc-rgba4unorm-webgl": { f: texture_compression_pvrtc_webgl },
631
- "pvrtc-rbg2unorm-webgl": { f: texture_compression_pvrtc_webgl },
942
+ "pvrtc-rgb2unorm-webgl": { f: texture_compression_pvrtc_webgl },
632
943
  "pvrtc-rgba2unorm-webgl": { f: texture_compression_pvrtc_webgl },
633
944
  // WEBGL_compressed_texture_etc1
634
945
  "etc1-rbg-unorm-webgl": { f: texture_compression_etc1_webgl },
@@ -642,7 +953,7 @@ var TEXTURE_FORMAT_TABLE = {
642
953
  ...TEXTURE_FORMAT_COMPRESSED_TABLE
643
954
  };
644
955
 
645
- // dist/shadertypes/textures/texture-format-decoder.js
956
+ // dist/shadertypes/texture-types/texture-format-decoder.js
646
957
  var RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
647
958
  var COLOR_FORMAT_PREFIXES = ["rgb", "rgba", "bgra"];
648
959
  var DEPTH_FORMAT_PREFIXES = ["depth", "stencil"];
@@ -689,10 +1000,13 @@ var TextureFormatDecoder = class {
689
1000
  };
690
1001
  var textureFormatDecoder = new TextureFormatDecoder();
691
1002
  function computeTextureMemoryLayout({ format, width, height, depth, byteAlignment }) {
692
- const { bytesPerPixel } = textureFormatDecoder.getInfo(format);
693
- const unpaddedBytesPerRow = width * bytesPerPixel;
1003
+ const formatInfo = textureFormatDecoder.getInfo(format);
1004
+ const { bytesPerPixel, bytesPerBlock = bytesPerPixel, blockWidth = 1, blockHeight = 1, compressed = false } = formatInfo;
1005
+ const blockColumns = compressed ? Math.ceil(width / blockWidth) : width;
1006
+ const blockRows = compressed ? Math.ceil(height / blockHeight) : height;
1007
+ const unpaddedBytesPerRow = blockColumns * bytesPerBlock;
694
1008
  const bytesPerRow = Math.ceil(unpaddedBytesPerRow / byteAlignment) * byteAlignment;
695
- const rowsPerImage = height;
1009
+ const rowsPerImage = blockRows;
696
1010
  const byteLength = bytesPerRow * rowsPerImage * depth;
697
1011
  return {
698
1012
  bytesPerPixel,
@@ -718,7 +1032,8 @@ function getTextureFormatCapabilities(format) {
718
1032
  const isSigned = formatInfo == null ? void 0 : formatInfo.signed;
719
1033
  const isInteger = formatInfo == null ? void 0 : formatInfo.integer;
720
1034
  const isWebGLSpecific = formatInfo == null ? void 0 : formatInfo.webgl;
721
- formatCapabilities.render &&= !isSigned;
1035
+ const isCompressed = Boolean(formatInfo == null ? void 0 : formatInfo.compressed);
1036
+ formatCapabilities.render &&= !isDepthStencil && !isCompressed;
722
1037
  formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
723
1038
  return formatCapabilities;
724
1039
  }
@@ -730,17 +1045,18 @@ function getTextureFormatInfo(format) {
730
1045
  formatInfo.bytesPerPixel = 1;
731
1046
  formatInfo.srgb = false;
732
1047
  formatInfo.compressed = true;
1048
+ formatInfo.bytesPerBlock = getCompressedTextureBlockByteLength(format);
733
1049
  const blockSize = getCompressedTextureBlockSize(format);
734
1050
  if (blockSize) {
735
1051
  formatInfo.blockWidth = blockSize.blockWidth;
736
1052
  formatInfo.blockHeight = blockSize.blockHeight;
737
1053
  }
738
1054
  }
739
- const matches = RGB_FORMAT_REGEX.exec(format);
1055
+ const matches = !formatInfo.packed ? RGB_FORMAT_REGEX.exec(format) : null;
740
1056
  if (matches) {
741
1057
  const [, channels, length, type, srgb, suffix] = matches;
742
1058
  const dataType = `${type}${length}`;
743
- const decodedType = getDataTypeInfo(dataType);
1059
+ const decodedType = dataTypeDecoder.getDataTypeInfo(dataType);
744
1060
  const bits = decodedType.byteLength * 8;
745
1061
  const components = (channels == null ? void 0 : channels.length) ?? 1;
746
1062
  const bitsPerChannel = [
@@ -816,10 +1132,31 @@ function getCompressedTextureBlockSize(format) {
816
1132
  const [, blockWidth, blockHeight] = matches;
817
1133
  return { blockWidth: Number(blockWidth), blockHeight: Number(blockHeight) };
818
1134
  }
1135
+ if (format.startsWith("bc") || format.startsWith("etc1") || format.startsWith("etc2") || format.startsWith("eac") || format.startsWith("atc")) {
1136
+ return { blockWidth: 4, blockHeight: 4 };
1137
+ }
1138
+ if (format.startsWith("pvrtc-rgb4") || format.startsWith("pvrtc-rgba4")) {
1139
+ return { blockWidth: 4, blockHeight: 4 };
1140
+ }
1141
+ if (format.startsWith("pvrtc-rgb2") || format.startsWith("pvrtc-rgba2")) {
1142
+ return { blockWidth: 8, blockHeight: 4 };
1143
+ }
819
1144
  return null;
820
1145
  }
1146
+ function getCompressedTextureBlockByteLength(format) {
1147
+ if (format.startsWith("bc1") || format.startsWith("bc4") || format.startsWith("etc1") || format.startsWith("etc2-rgb8") || format.startsWith("etc2-rgb8a1") || format.startsWith("eac-r11") || format === "atc-rgb-unorm-webgl") {
1148
+ return 8;
1149
+ }
1150
+ if (format.startsWith("bc2") || format.startsWith("bc3") || format.startsWith("bc5") || format.startsWith("bc6h") || format.startsWith("bc7") || format.startsWith("etc2-rgba8") || format.startsWith("eac-rg11") || format.startsWith("astc") || format === "atc-rgba-unorm-webgl" || format === "atc-rgbai-unorm-webgl") {
1151
+ return 16;
1152
+ }
1153
+ if (format.startsWith("pvrtc")) {
1154
+ return 8;
1155
+ }
1156
+ return 16;
1157
+ }
821
1158
 
822
- // dist/image-utils/image-types.js
1159
+ // dist/shadertypes/image-types/image-types.js
823
1160
  function isExternalImage(data) {
824
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;
825
1162
  }
@@ -842,6 +1179,53 @@ function getExternalImageSize(data) {
842
1179
  // dist/adapter/device.js
843
1180
  var DeviceLimits = class {
844
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
+ }
845
1229
  var DeviceFeatures = class {
846
1230
  features;
847
1231
  disabledFeatures;
@@ -872,6 +1256,8 @@ var _Device = class {
872
1256
  userData = {};
873
1257
  /** stats */
874
1258
  statsManager = lumaStats;
1259
+ /** Internal per-device factory storage */
1260
+ _factories = {};
875
1261
  /** An abstract timestamp used for change tracking */
876
1262
  timestamp = 0;
877
1263
  /** True if this device has been reused during device creation (app has multiple references) */
@@ -879,12 +1265,15 @@ var _Device = class {
879
1265
  /** Used by other luma.gl modules to store data on the device */
880
1266
  _moduleData = {};
881
1267
  _textureCaps = {};
1268
+ /** Internal timestamp query set used when GPU timing collection is enabled for this device. */
1269
+ _debugGPUTimeQuery = null;
882
1270
  constructor(props) {
883
1271
  this.props = { ..._Device.defaultProps, ...props };
884
1272
  this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
885
1273
  }
1274
+ // TODO - just expose the shadertypes decoders?
886
1275
  getVertexFormatInfo(format) {
887
- return getVertexFormatInfo(format);
1276
+ return vertexFormatDecoder.getVertexFormatInfo(format);
888
1277
  }
889
1278
  isVertexFormatSupported(format) {
890
1279
  return true;
@@ -932,6 +1321,16 @@ var _Device = class {
932
1321
  isTextureFormatCompressed(format) {
933
1322
  return textureFormatDecoder.isCompressed(format);
934
1323
  }
1324
+ /** Returns the compressed texture formats that can be created and sampled on this device */
1325
+ getSupportedCompressedTextureFormats() {
1326
+ const supportedFormats = [];
1327
+ for (const format of Object.keys(getTextureFormatTable())) {
1328
+ if (this.isTextureFormatCompressed(format) && this.isTextureFormatSupported(format)) {
1329
+ supportedFormats.push(format);
1330
+ }
1331
+ }
1332
+ return supportedFormats;
1333
+ }
935
1334
  // DEBUG METHODS
936
1335
  pushDebugGroup(groupLabel) {
937
1336
  this.commandEncoder.pushDebugGroup(groupLabel);
@@ -976,7 +1375,8 @@ var _Device = class {
976
1375
  reportError(error, context, ...args) {
977
1376
  const isHandled = this.props.onError(error, context);
978
1377
  if (!isHandled) {
979
- 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);
980
1380
  }
981
1381
  return () => {
982
1382
  };
@@ -1010,6 +1410,78 @@ or create a device with the 'debug: true' prop.`;
1010
1410
  beginComputePass(props) {
1011
1411
  return this.commandEncoder.beginComputePass(props);
1012
1412
  }
1413
+ /**
1414
+ * Generate mipmaps for a WebGPU texture.
1415
+ * WebGPU textures must be created up front with the required mip count, usage flags, and a format that supports the chosen generation path.
1416
+ * WebGL uses `Texture.generateMipmapsWebGL()` directly because the backend manages mip generation on the texture object itself.
1417
+ */
1418
+ generateMipmapsWebGPU(_texture) {
1419
+ throw new Error("not implemented");
1420
+ }
1421
+ /** Internal helper for creating a shareable WebGL render-pipeline implementation. */
1422
+ _createSharedRenderPipelineWebGL(_props) {
1423
+ throw new Error("_createSharedRenderPipelineWebGL() not implemented");
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
+ }
1433
+ /**
1434
+ * Internal helper that returns `true` when timestamp-query GPU timing should be
1435
+ * collected for this device.
1436
+ */
1437
+ _supportsDebugGPUTime() {
1438
+ return this.features.has("timestamp-query") && Boolean(this.props.debug || this.props.debugGPUTime);
1439
+ }
1440
+ /**
1441
+ * Internal helper that enables device-managed GPU timing collection on the
1442
+ * default command encoder. Reuses the existing query set if timing is already enabled.
1443
+ *
1444
+ * @param queryCount - Number of timestamp slots reserved for profiled passes.
1445
+ * @returns The device-managed timestamp QuerySet, or `null` when timing is not supported or could not be enabled.
1446
+ */
1447
+ _enableDebugGPUTime(queryCount = 256) {
1448
+ if (!this._supportsDebugGPUTime()) {
1449
+ return null;
1450
+ }
1451
+ if (this._debugGPUTimeQuery) {
1452
+ return this._debugGPUTimeQuery;
1453
+ }
1454
+ try {
1455
+ this._debugGPUTimeQuery = this.createQuerySet({ type: "timestamp", count: queryCount });
1456
+ this.commandEncoder = this.createCommandEncoder({
1457
+ id: this.commandEncoder.props.id,
1458
+ timeProfilingQuerySet: this._debugGPUTimeQuery
1459
+ });
1460
+ } catch {
1461
+ this._debugGPUTimeQuery = null;
1462
+ }
1463
+ return this._debugGPUTimeQuery;
1464
+ }
1465
+ /**
1466
+ * Internal helper that disables device-managed GPU timing collection and restores
1467
+ * the default command encoder to an unprofiled state.
1468
+ */
1469
+ _disableDebugGPUTime() {
1470
+ if (!this._debugGPUTimeQuery) {
1471
+ return;
1472
+ }
1473
+ if (this.commandEncoder.getTimeProfilingQuerySet() === this._debugGPUTimeQuery) {
1474
+ this.commandEncoder = this.createCommandEncoder({
1475
+ id: this.commandEncoder.props.id
1476
+ });
1477
+ }
1478
+ this._debugGPUTimeQuery.destroy();
1479
+ this._debugGPUTimeQuery = null;
1480
+ }
1481
+ /** Internal helper that returns `true` when device-managed GPU timing is currently active. */
1482
+ _isDebugGPUTimeEnabled() {
1483
+ return this._debugGPUTimeQuery !== null;
1484
+ }
1013
1485
  // DEPRECATED METHODS
1014
1486
  /** @deprecated Use getDefaultCanvasContext() */
1015
1487
  getCanvasContext() {
@@ -1117,7 +1589,8 @@ __publicField(Device, "defaultProps", {
1117
1589
  onVisibilityChange: (context) => log.log(1, `${context} Visibility changed ${context.isVisible}`)(),
1118
1590
  onDevicePixelRatioChange: (context, info) => log.log(1, `${context} DPR changed ${info.oldRatio} => ${context.devicePixelRatio}`)(),
1119
1591
  // Debug flags
1120
- debug: log.get("debug") || void 0,
1592
+ debug: getDefaultDebugValue(),
1593
+ debugGPUTime: false,
1121
1594
  debugShaders: log.get("debug-shaders") || void 0,
1122
1595
  debugFramebuffers: Boolean(log.get("debug-framebuffers")),
1123
1596
  debugFactories: Boolean(log.get("debug-factories")),
@@ -1128,9 +1601,11 @@ __publicField(Device, "defaultProps", {
1128
1601
  // Experimental
1129
1602
  _reuseDevices: false,
1130
1603
  _requestMaxLimits: true,
1131
- _cacheShaders: false,
1132
- _cachePipelines: false,
1133
- _cacheDestroyPolicy: "unused",
1604
+ _cacheShaders: true,
1605
+ _destroyShaders: false,
1606
+ _cachePipelines: true,
1607
+ _sharePipelines: true,
1608
+ _destroyPipelines: false,
1134
1609
  // TODO - Change these after confirming things work as expected
1135
1610
  _initializeFeatures: true,
1136
1611
  _disabledFeatures: {
@@ -1139,6 +1614,25 @@ __publicField(Device, "defaultProps", {
1139
1614
  // INTERNAL
1140
1615
  _handle: void 0
1141
1616
  });
1617
+ function _getDefaultDebugValue(logDebugValue, nodeEnv) {
1618
+ if (logDebugValue !== void 0 && logDebugValue !== null) {
1619
+ return Boolean(logDebugValue);
1620
+ }
1621
+ if (nodeEnv !== void 0) {
1622
+ return nodeEnv !== "production";
1623
+ }
1624
+ return false;
1625
+ }
1626
+ function getDefaultDebugValue() {
1627
+ return _getDefaultDebugValue(log.get("debug"), getNodeEnv());
1628
+ }
1629
+ function getNodeEnv() {
1630
+ const processObject = globalThis.process;
1631
+ if (!(processObject == null ? void 0 : processObject.env)) {
1632
+ return void 0;
1633
+ }
1634
+ return processObject.env["NODE_ENV"];
1635
+ }
1142
1636
 
1143
1637
  // dist/adapter/luma.js
1144
1638
  var STARTUP_MESSAGE = "set luma.log.level=1 (or higher) to trace rendering";
@@ -1158,7 +1652,7 @@ var _Luma = class {
1158
1652
  VERSION = (
1159
1653
  // Version detection using build plugin
1160
1654
  // @ts-expect-error no-undef
1161
- true ? "9.3.0-alpha.4" : "running from source"
1655
+ true ? "9.3.0-alpha.8" : "running from source"
1162
1656
  );
1163
1657
  spector;
1164
1658
  preregisteredAdapters = /* @__PURE__ */ new Map();
@@ -1323,9 +1817,91 @@ function getPageLoadPromise() {
1323
1817
  return pageLoadPromise;
1324
1818
  }
1325
1819
 
1326
- // dist/adapter/canvas-context.js
1820
+ // dist/adapter/canvas-surface.js
1327
1821
  var import_env2 = require("@probe.gl/env");
1328
1822
 
1823
+ // dist/adapter/canvas-observer.js
1824
+ var CanvasObserver = class {
1825
+ props;
1826
+ _resizeObserver;
1827
+ _intersectionObserver;
1828
+ _observeDevicePixelRatioTimeout = null;
1829
+ _observeDevicePixelRatioMediaQuery = null;
1830
+ _handleDevicePixelRatioChange = () => this._refreshDevicePixelRatio();
1831
+ _trackPositionInterval = null;
1832
+ _started = false;
1833
+ get started() {
1834
+ return this._started;
1835
+ }
1836
+ constructor(props) {
1837
+ this.props = props;
1838
+ }
1839
+ start() {
1840
+ if (this._started || !this.props.canvas) {
1841
+ return;
1842
+ }
1843
+ this._started = true;
1844
+ this._intersectionObserver ||= new IntersectionObserver((entries) => this.props.onIntersection(entries));
1845
+ this._resizeObserver ||= new ResizeObserver((entries) => this.props.onResize(entries));
1846
+ this._intersectionObserver.observe(this.props.canvas);
1847
+ try {
1848
+ this._resizeObserver.observe(this.props.canvas, { box: "device-pixel-content-box" });
1849
+ } catch {
1850
+ this._resizeObserver.observe(this.props.canvas, { box: "content-box" });
1851
+ }
1852
+ this._observeDevicePixelRatioTimeout = setTimeout(() => this._refreshDevicePixelRatio(), 0);
1853
+ if (this.props.trackPosition) {
1854
+ this._trackPosition();
1855
+ }
1856
+ }
1857
+ stop() {
1858
+ var _a, _b;
1859
+ if (!this._started) {
1860
+ return;
1861
+ }
1862
+ this._started = false;
1863
+ if (this._observeDevicePixelRatioTimeout) {
1864
+ clearTimeout(this._observeDevicePixelRatioTimeout);
1865
+ this._observeDevicePixelRatioTimeout = null;
1866
+ }
1867
+ if (this._observeDevicePixelRatioMediaQuery) {
1868
+ this._observeDevicePixelRatioMediaQuery.removeEventListener("change", this._handleDevicePixelRatioChange);
1869
+ this._observeDevicePixelRatioMediaQuery = null;
1870
+ }
1871
+ if (this._trackPositionInterval) {
1872
+ clearInterval(this._trackPositionInterval);
1873
+ this._trackPositionInterval = null;
1874
+ }
1875
+ (_a = this._resizeObserver) == null ? void 0 : _a.disconnect();
1876
+ (_b = this._intersectionObserver) == null ? void 0 : _b.disconnect();
1877
+ }
1878
+ _refreshDevicePixelRatio() {
1879
+ var _a;
1880
+ if (!this._started) {
1881
+ return;
1882
+ }
1883
+ this.props.onDevicePixelRatioChange();
1884
+ (_a = this._observeDevicePixelRatioMediaQuery) == null ? void 0 : _a.removeEventListener("change", this._handleDevicePixelRatioChange);
1885
+ this._observeDevicePixelRatioMediaQuery = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
1886
+ this._observeDevicePixelRatioMediaQuery.addEventListener("change", this._handleDevicePixelRatioChange, { once: true });
1887
+ }
1888
+ _trackPosition(intervalMs = 100) {
1889
+ if (this._trackPositionInterval) {
1890
+ return;
1891
+ }
1892
+ this._trackPositionInterval = setInterval(() => {
1893
+ if (!this._started) {
1894
+ if (this._trackPositionInterval) {
1895
+ clearInterval(this._trackPositionInterval);
1896
+ this._trackPositionInterval = null;
1897
+ }
1898
+ } else {
1899
+ this.props.onPositionChange();
1900
+ }
1901
+ }, intervalMs);
1902
+ }
1903
+ };
1904
+
1329
1905
  // dist/utils/promise-utils.js
1330
1906
  function withResolvers() {
1331
1907
  let resolve;
@@ -1351,8 +1927,8 @@ function assertDefined(value, message) {
1351
1927
  return value;
1352
1928
  }
1353
1929
 
1354
- // dist/adapter/canvas-context.js
1355
- var _CanvasContext = class {
1930
+ // dist/adapter/canvas-surface.js
1931
+ var _CanvasSurface = class {
1356
1932
  static isHTMLCanvas(canvas) {
1357
1933
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
1358
1934
  }
@@ -1388,11 +1964,7 @@ var _CanvasContext = class {
1388
1964
  drawingBufferHeight;
1389
1965
  /** Resolves when the canvas is initialized, i.e. when the ResizeObserver has updated the pixel size */
1390
1966
  _initializedResolvers = withResolvers();
1391
- /** ResizeObserver to track canvas size changes */
1392
- _resizeObserver;
1393
- /** IntersectionObserver to track canvas visibility changes */
1394
- _intersectionObserver;
1395
- _observeDevicePixelRatioTimeout = null;
1967
+ _canvasObserver;
1396
1968
  /** Position of the canvas in the document, updated by a timer */
1397
1969
  _position = [0, 0];
1398
1970
  /** Whether this canvas context has been destroyed */
@@ -1404,7 +1976,7 @@ var _CanvasContext = class {
1404
1976
  }
1405
1977
  constructor(props) {
1406
1978
  var _a, _b;
1407
- this.props = { ..._CanvasContext.defaultProps, ...props };
1979
+ this.props = { ..._CanvasSurface.defaultProps, ...props };
1408
1980
  props = this.props;
1409
1981
  this.initialized = this._initializedResolvers.promise;
1410
1982
  if (!(0, import_env2.isBrowser)()) {
@@ -1416,11 +1988,11 @@ var _CanvasContext = class {
1416
1988
  } else {
1417
1989
  this.canvas = props.canvas;
1418
1990
  }
1419
- if (_CanvasContext.isHTMLCanvas(this.canvas)) {
1991
+ if (_CanvasSurface.isHTMLCanvas(this.canvas)) {
1420
1992
  this.id = props.id || this.canvas.id;
1421
1993
  this.type = "html-canvas";
1422
1994
  this.htmlCanvas = this.canvas;
1423
- } else if (_CanvasContext.isOffscreenCanvas(this.canvas)) {
1995
+ } else if (_CanvasSurface.isOffscreenCanvas(this.canvas)) {
1424
1996
  this.id = props.id || "offscreen-canvas";
1425
1997
  this.type = "offscreen-canvas";
1426
1998
  this.offscreenCanvas = this.canvas;
@@ -1436,32 +2008,20 @@ var _CanvasContext = class {
1436
2008
  this.drawingBufferHeight = this.canvas.height;
1437
2009
  this.devicePixelRatio = globalThis.devicePixelRatio || 1;
1438
2010
  this._position = [0, 0];
1439
- if (_CanvasContext.isHTMLCanvas(this.canvas)) {
1440
- this._intersectionObserver = new IntersectionObserver((entries) => this._handleIntersection(entries));
1441
- this._intersectionObserver.observe(this.canvas);
1442
- this._resizeObserver = new ResizeObserver((entries) => this._handleResize(entries));
1443
- try {
1444
- this._resizeObserver.observe(this.canvas, { box: "device-pixel-content-box" });
1445
- } catch {
1446
- this._resizeObserver.observe(this.canvas, { box: "content-box" });
1447
- }
1448
- this._observeDevicePixelRatioTimeout = setTimeout(() => this._observeDevicePixelRatio(), 0);
1449
- if (this.props.trackPosition) {
1450
- this._trackPosition();
1451
- }
1452
- }
2011
+ this._canvasObserver = new CanvasObserver({
2012
+ canvas: this.htmlCanvas,
2013
+ trackPosition: this.props.trackPosition,
2014
+ onResize: (entries) => this._handleResize(entries),
2015
+ onIntersection: (entries) => this._handleIntersection(entries),
2016
+ onDevicePixelRatioChange: () => this._observeDevicePixelRatio(),
2017
+ onPositionChange: () => this.updatePosition()
2018
+ });
1453
2019
  }
1454
2020
  destroy() {
1455
- var _a, _b;
1456
2021
  if (!this.destroyed) {
1457
2022
  this.destroyed = true;
1458
- if (this._observeDevicePixelRatioTimeout) {
1459
- clearTimeout(this._observeDevicePixelRatioTimeout);
1460
- this._observeDevicePixelRatioTimeout = null;
1461
- }
2023
+ this._stopObservers();
1462
2024
  this.device = null;
1463
- (_a = this._resizeObserver) == null ? void 0 : _a.disconnect();
1464
- (_b = this._intersectionObserver) == null ? void 0 : _b.disconnect();
1465
2025
  }
1466
2026
  }
1467
2027
  setProps(props) {
@@ -1476,41 +2036,22 @@ var _CanvasContext = class {
1476
2036
  this._resizeDrawingBufferIfNeeded();
1477
2037
  return this._getCurrentFramebuffer(options);
1478
2038
  }
1479
- // SIZE METHODS
1480
- /**
1481
- * Returns the size covered by the canvas in CSS pixels
1482
- * @note This can be different from the actual device pixel size of a canvas due to DPR scaling, and rounding to integer pixels
1483
- * @note This is independent of the canvas' internal drawing buffer size (.width, .height).
1484
- */
1485
2039
  getCSSSize() {
1486
2040
  return [this.cssWidth, this.cssHeight];
1487
2041
  }
1488
2042
  getPosition() {
1489
2043
  return this._position;
1490
2044
  }
1491
- /**
1492
- * Returns the size covered by the canvas in actual device pixels.
1493
- * @note This can be different from the 'CSS' size of a canvas due to DPR scaling, and rounding to integer pixels
1494
- * @note This is independent of the canvas' internal drawing buffer size (.width, .height).
1495
- */
1496
2045
  getDevicePixelSize() {
1497
2046
  return [this.devicePixelWidth, this.devicePixelHeight];
1498
2047
  }
1499
- /** Get the drawing buffer size (number of pixels GPU is rendering into, can be different from CSS size) */
1500
2048
  getDrawingBufferSize() {
1501
2049
  return [this.drawingBufferWidth, this.drawingBufferHeight];
1502
2050
  }
1503
- /** Returns the biggest allowed framebuffer size. @todo Allow the application to limit this? */
1504
2051
  getMaxDrawingBufferSize() {
1505
2052
  const maxTextureDimension = this.device.limits.maxTextureDimension2D;
1506
2053
  return [maxTextureDimension, maxTextureDimension];
1507
2054
  }
1508
- /**
1509
- * Update the canvas drawing buffer size.
1510
- * @note - Called automatically if props.autoResize is true.
1511
- * @note - Defers update of drawing buffer size until framebuffer is requested to avoid flicker
1512
- * (resizing clears the drawing buffer)!
1513
- */
1514
2055
  setDrawingBufferSize(width, height) {
1515
2056
  width = Math.floor(width);
1516
2057
  height = Math.floor(height);
@@ -1521,19 +2062,10 @@ var _CanvasContext = class {
1521
2062
  this.drawingBufferHeight = height;
1522
2063
  this._needsDrawingBufferResize = true;
1523
2064
  }
1524
- /**
1525
- * Returns the current DPR (number of physical pixels per CSS pixel), if props.useDevicePixels is true
1526
- * @note This can be a fractional (non-integer) number, e.g. when the user zooms in the browser.
1527
- * @note This function handles the non-HTML canvas cases
1528
- */
1529
2065
  getDevicePixelRatio() {
1530
- const dpr = typeof window !== "undefined" && window.devicePixelRatio;
1531
- return dpr || 1;
2066
+ const devicePixelRatio2 = typeof window !== "undefined" && window.devicePixelRatio;
2067
+ return devicePixelRatio2 || 1;
1532
2068
  }
1533
- // DEPRECATED METHODS
1534
- /**
1535
- * Maps CSS pixel position to device pixel position
1536
- */
1537
2069
  cssToDevicePixels(cssPixel, yInvert = true) {
1538
2070
  const ratio = this.cssToDeviceRatio();
1539
2071
  const [width, height] = this.getDrawingBufferSize();
@@ -1543,10 +2075,10 @@ var _CanvasContext = class {
1543
2075
  getPixelSize() {
1544
2076
  return this.getDevicePixelSize();
1545
2077
  }
1546
- /** @deprecated - TODO which values should we use for aspect */
2078
+ /** @deprecated Use the current drawing buffer size for projection setup. */
1547
2079
  getAspect() {
1548
- const [width, height] = this.getDevicePixelSize();
1549
- return width / height;
2080
+ const [width, height] = this.getDrawingBufferSize();
2081
+ return width > 0 && height > 0 ? width / height : 1;
1550
2082
  }
1551
2083
  /** @deprecated Returns multiplier need to convert CSS size to Device size */
1552
2084
  cssToDeviceRatio() {
@@ -1562,18 +2094,37 @@ var _CanvasContext = class {
1562
2094
  resize(size) {
1563
2095
  this.setDrawingBufferSize(size.width, size.height);
1564
2096
  }
1565
- // IMPLEMENTATION
1566
- /**
1567
- * Allows subclass constructor to override the canvas id for auto created canvases.
1568
- * This can really help when debugging DOM in apps that create multiple devices
1569
- */
1570
2097
  _setAutoCreatedCanvasId(id) {
1571
2098
  var _a;
1572
2099
  if (((_a = this.htmlCanvas) == null ? void 0 : _a.id) === "lumagl-auto-created-canvas") {
1573
2100
  this.htmlCanvas.id = id;
1574
2101
  }
1575
2102
  }
1576
- /** reacts to an observed intersection */
2103
+ /**
2104
+ * Starts DOM observation after the derived context and its device are fully initialized.
2105
+ *
2106
+ * `CanvasSurface` construction runs before subclasses can assign `this.device`, and the
2107
+ * default WebGL canvas context is created before `WebGLDevice` has initialized `limits`,
2108
+ * `features`, and the rest of its runtime state. Deferring observer startup avoids early
2109
+ * `ResizeObserver` and DPR callbacks running against a partially initialized device.
2110
+ */
2111
+ _startObservers() {
2112
+ if (this.destroyed) {
2113
+ return;
2114
+ }
2115
+ this._canvasObserver.start();
2116
+ }
2117
+ /**
2118
+ * Stops all DOM observation and timers associated with a canvas surface.
2119
+ *
2120
+ * This pairs with `_startObservers()` so teardown uses the same lifecycle whether a context is
2121
+ * explicitly destroyed, abandoned during device reuse, or temporarily has not started observing
2122
+ * yet. Centralizing shutdown here keeps resize/DPR/position watchers from surviving past the
2123
+ * lifetime of the owning device.
2124
+ */
2125
+ _stopObservers() {
2126
+ this._canvasObserver.stop();
2127
+ }
1577
2128
  _handleIntersection(entries) {
1578
2129
  if (this.destroyed) {
1579
2130
  return;
@@ -1588,11 +2139,6 @@ var _CanvasContext = class {
1588
2139
  this.device.props.onVisibilityChange(this);
1589
2140
  }
1590
2141
  }
1591
- /**
1592
- * Reacts to an observed resize by using the most accurate pixel size information the browser can provide
1593
- * @see https://web.dev/articles/device-pixel-content-box
1594
- * @see https://webgpufundamentals.org/webgpu/lessons/webgpu-resizing-the-canvas.html
1595
- */
1596
2142
  _handleResize(entries) {
1597
2143
  var _a, _b, _c, _d, _e;
1598
2144
  if (this.destroyed) {
@@ -1614,12 +2160,11 @@ var _CanvasContext = class {
1614
2160
  this._updateDrawingBufferSize();
1615
2161
  this.device.props.onResize(this, { oldPixelSize });
1616
2162
  }
1617
- /** Initiate a deferred update for the canvas drawing buffer size */
1618
2163
  _updateDrawingBufferSize() {
1619
2164
  if (this.props.autoResize) {
1620
2165
  if (typeof this.props.useDevicePixels === "number") {
1621
- const dpr = this.props.useDevicePixels;
1622
- this.setDrawingBufferSize(this.cssWidth * dpr, this.cssHeight * dpr);
2166
+ const devicePixelRatio2 = this.props.useDevicePixels;
2167
+ this.setDrawingBufferSize(this.cssWidth * devicePixelRatio2, this.cssHeight * devicePixelRatio2);
1623
2168
  } else if (this.props.useDevicePixels) {
1624
2169
  this.setDrawingBufferSize(this.devicePixelWidth, this.devicePixelHeight);
1625
2170
  } else {
@@ -1630,7 +2175,6 @@ var _CanvasContext = class {
1630
2175
  this.isInitialized = true;
1631
2176
  this.updatePosition();
1632
2177
  }
1633
- /** Perform a deferred resize of the drawing buffer if needed */
1634
2178
  _resizeDrawingBufferIfNeeded() {
1635
2179
  if (this._needsDrawingBufferResize) {
1636
2180
  this._needsDrawingBufferResize = false;
@@ -1642,33 +2186,18 @@ var _CanvasContext = class {
1642
2186
  }
1643
2187
  }
1644
2188
  }
1645
- /** Monitor DPR changes */
1646
2189
  _observeDevicePixelRatio() {
1647
2190
  var _a, _b;
1648
- if (this.destroyed) {
2191
+ if (this.destroyed || !this._canvasObserver.started) {
1649
2192
  return;
1650
2193
  }
1651
2194
  const oldRatio = this.devicePixelRatio;
1652
2195
  this.devicePixelRatio = window.devicePixelRatio;
1653
2196
  this.updatePosition();
1654
- (_b = (_a = this.device.props).onDevicePixelRatioChange) == null ? void 0 : _b.call(_a, this, { oldRatio });
1655
- matchMedia(`(resolution: ${this.devicePixelRatio}dppx)`).addEventListener("change", () => this._observeDevicePixelRatio(), { once: true });
1656
- }
1657
- /** Start tracking positions with a timer */
1658
- _trackPosition(intervalMs = 100) {
1659
- const intervalId = setInterval(() => {
1660
- if (this.destroyed) {
1661
- clearInterval(intervalId);
1662
- } else {
1663
- this.updatePosition();
1664
- }
1665
- }, intervalMs);
2197
+ (_b = (_a = this.device.props).onDevicePixelRatioChange) == null ? void 0 : _b.call(_a, this, {
2198
+ oldRatio
2199
+ });
1666
2200
  }
1667
- /**
1668
- * Calculated the absolute position of the canvas
1669
- * @note - getBoundingClientRect() is normally cheap but can be expensive
1670
- * if called before browser has finished a reflow. Should not be the case here.
1671
- */
1672
2201
  updatePosition() {
1673
2202
  var _a, _b, _c;
1674
2203
  if (this.destroyed) {
@@ -1682,13 +2211,15 @@ var _CanvasContext = class {
1682
2211
  if (positionChanged) {
1683
2212
  const oldPosition = this._position;
1684
2213
  this._position = position;
1685
- (_c = (_b = this.device.props).onPositionChange) == null ? void 0 : _c.call(_b, this, { oldPosition });
2214
+ (_c = (_b = this.device.props).onPositionChange) == null ? void 0 : _c.call(_b, this, {
2215
+ oldPosition
2216
+ });
1686
2217
  }
1687
2218
  }
1688
2219
  }
1689
2220
  };
1690
- var CanvasContext = _CanvasContext;
1691
- __publicField(CanvasContext, "defaultProps", {
2221
+ var CanvasSurface = _CanvasSurface;
2222
+ __publicField(CanvasSurface, "defaultProps", {
1692
2223
  id: void 0,
1693
2224
  canvas: null,
1694
2225
  width: 800,
@@ -1716,7 +2247,7 @@ function getContainer(container) {
1716
2247
  }
1717
2248
  function getCanvasFromDOM(canvasId) {
1718
2249
  const canvas = document.getElementById(canvasId);
1719
- if (!CanvasContext.isHTMLCanvas(canvas)) {
2250
+ if (!CanvasSurface.isHTMLCanvas(canvas)) {
1720
2251
  throw new Error("Object is not a canvas element");
1721
2252
  }
1722
2253
  return canvas;
@@ -1740,33 +2271,40 @@ function scalePixels(pixel, ratio, width, height, yInvert) {
1740
2271
  const point = pixel;
1741
2272
  const x = scaleX(point[0], ratio, width);
1742
2273
  let y = scaleY(point[1], ratio, height, yInvert);
1743
- let t = scaleX(point[0] + 1, ratio, width);
1744
- const xHigh = t === width - 1 ? t : t - 1;
1745
- t = scaleY(point[1] + 1, ratio, height, yInvert);
2274
+ let temporary = scaleX(point[0] + 1, ratio, width);
2275
+ const xHigh = temporary === width - 1 ? temporary : temporary - 1;
2276
+ temporary = scaleY(point[1] + 1, ratio, height, yInvert);
1746
2277
  let yHigh;
1747
2278
  if (yInvert) {
1748
- t = t === 0 ? t : t + 1;
2279
+ temporary = temporary === 0 ? temporary : temporary + 1;
1749
2280
  yHigh = y;
1750
- y = t;
2281
+ y = temporary;
1751
2282
  } else {
1752
- yHigh = t === height - 1 ? t : t - 1;
2283
+ yHigh = temporary === height - 1 ? temporary : temporary - 1;
1753
2284
  }
1754
2285
  return {
1755
2286
  x,
1756
2287
  y,
1757
- // when ratio < 1, current css pixel and next css pixel may point to same device pixel, set width/height to 1 in those cases.
1758
2288
  width: Math.max(xHigh - x + 1, 1),
1759
2289
  height: Math.max(yHigh - y + 1, 1)
1760
2290
  };
1761
2291
  }
1762
2292
  function scaleX(x, ratio, width) {
1763
- const r = Math.min(Math.round(x * ratio), width - 1);
1764
- return r;
2293
+ return Math.min(Math.round(x * ratio), width - 1);
1765
2294
  }
1766
2295
  function scaleY(y, ratio, height, yInvert) {
1767
2296
  return yInvert ? Math.max(0, height - 1 - Math.round(y * ratio)) : Math.min(Math.round(y * ratio), height - 1);
1768
2297
  }
1769
2298
 
2299
+ // dist/adapter/canvas-context.js
2300
+ var CanvasContext = class extends CanvasSurface {
2301
+ };
2302
+ __publicField(CanvasContext, "defaultProps", CanvasSurface.defaultProps);
2303
+
2304
+ // dist/adapter/presentation-context.js
2305
+ var PresentationContext = class extends CanvasSurface {
2306
+ };
2307
+
1770
2308
  // dist/adapter/resources/sampler.js
1771
2309
  var _Sampler = class extends Resource {
1772
2310
  get [Symbol.toStringTag]() {
@@ -1821,6 +2359,8 @@ var _Texture = class extends Resource {
1821
2359
  depth;
1822
2360
  /** mip levels in this texture */
1823
2361
  mipLevels;
2362
+ /** sample count */
2363
+ samples;
1824
2364
  /** Rows are multiples of this length, padded with extra bytes if needed */
1825
2365
  byteAlignment;
1826
2366
  /** The ready promise is always resolved. It is provided for type compatibility with DynamicTexture. */
@@ -1846,6 +2386,7 @@ var _Texture = class extends Resource {
1846
2386
  this.height = this.props.height;
1847
2387
  this.depth = this.props.depth;
1848
2388
  this.mipLevels = this.props.mipLevels;
2389
+ this.samples = this.props.samples || 1;
1849
2390
  if (this.dimension === "cube") {
1850
2391
  this.depth = 6;
1851
2392
  }
@@ -1877,9 +2418,25 @@ var _Texture = class extends Resource {
1877
2418
  setSampler(sampler) {
1878
2419
  this.sampler = sampler instanceof Sampler ? sampler : this.device.createSampler(sampler);
1879
2420
  }
2421
+ /**
2422
+ * Copy raw image data (bytes) into the texture.
2423
+ *
2424
+ * @note Deprecated compatibility wrapper over {@link writeData}.
2425
+ * @note Uses the same layout defaults and alignment rules as {@link writeData}.
2426
+ * @note Tightly packed CPU uploads can omit `bytesPerRow` and `rowsPerImage`.
2427
+ * @note If the CPU source rows are padded, pass explicit `bytesPerRow` and `rowsPerImage`.
2428
+ * @deprecated Use writeData()
2429
+ */
2430
+ copyImageData(options) {
2431
+ const { data, depth, ...writeOptions } = options;
2432
+ this.writeData(data, {
2433
+ ...writeOptions,
2434
+ depthOrArrayLayers: writeOptions.depthOrArrayLayers ?? depth
2435
+ });
2436
+ }
1880
2437
  /**
1881
2438
  * Calculates the memory layout of the texture, required when reading and writing data.
1882
- * @return the memory layout of the texture, in particular bytesPerRow which includes required padding
2439
+ * @return the backend-aligned linear layout, in particular bytesPerRow which includes any required padding for buffer copy/read paths
1883
2440
  */
1884
2441
  computeMemoryLayout(options_ = {}) {
1885
2442
  const options = this._normalizeTextureReadOptions(options_);
@@ -1898,9 +2455,11 @@ var _Texture = class extends Resource {
1898
2455
  * @returns A Buffer containing the texture data.
1899
2456
  *
1900
2457
  * @note The memory layout of the texture data is determined by the texture format and dimensions.
1901
- * @note The application can call Texture.computeMemoryLayout() to compute the layout.
1902
- * @note The application can call Buffer.readAsync()
1903
- * @note If not supplied a buffer will be created and the application needs to call Buffer.destroy
2458
+ * @note The application can call Texture.computeMemoryLayout() to compute the backend-aligned layout.
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.
2461
+ * @note On WebGPU this corresponds to a texture-to-buffer copy and uses buffer-copy alignment rules.
2462
+ * @note On WebGL, luma.gl emulates the same logical readback behavior.
1904
2463
  */
1905
2464
  readBuffer(options, buffer) {
1906
2465
  throw new Error("readBuffer not implemented");
@@ -1911,15 +2470,20 @@ var _Texture = class extends Resource {
1911
2470
  *
1912
2471
  * @note The memory layout of the texture data is determined by the texture format and dimensions.
1913
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.
1914
2474
  */
1915
2475
  readDataAsync(options) {
1916
2476
  throw new Error("readBuffer not implemented");
1917
2477
  }
1918
2478
  /**
1919
- * Writes an GPU Buffer into a texture.
2479
+ * Writes a GPU Buffer into a texture.
1920
2480
  *
2481
+ * @param buffer - Source GPU buffer.
2482
+ * @param options - Destination subresource, extent, and source layout options.
1921
2483
  * @note The memory layout of the texture data is determined by the texture format and dimensions.
1922
- * @note The application can call Texture.computeMemoryLayout() to compute the layout.
2484
+ * @note The application can call Texture.computeMemoryLayout() to compute the backend-aligned layout.
2485
+ * @note On WebGPU this corresponds to a buffer-to-texture copy and uses buffer-copy alignment rules.
2486
+ * @note On WebGL, luma.gl emulates the same destination and layout semantics.
1923
2487
  */
1924
2488
  writeBuffer(buffer, options) {
1925
2489
  throw new Error("readBuffer not implemented");
@@ -1927,8 +2491,11 @@ var _Texture = class extends Resource {
1927
2491
  /**
1928
2492
  * Writes an array buffer into a texture.
1929
2493
  *
1930
- * @note The memory layout of the texture data is determined by the texture format and dimensions.
1931
- * @note The application can call Texture.computeMemoryLayout() to compute the layout.
2494
+ * @param data - Source texel data.
2495
+ * @param options - Destination subresource, extent, and source layout options.
2496
+ * @note If `bytesPerRow` and `rowsPerImage` are omitted, luma.gl computes a tightly packed CPU-memory layout for the requested region.
2497
+ * @note On WebGPU this corresponds to `GPUQueue.writeTexture()` and does not implicitly pad rows to 256 bytes.
2498
+ * @note On WebGL, padded CPU data is supported via the same `bytesPerRow` and `rowsPerImage` options.
1932
2499
  */
1933
2500
  writeData(data, options) {
1934
2501
  throw new Error("readBuffer not implemented");
@@ -1991,37 +2558,148 @@ var _Texture = class extends Resource {
1991
2558
  }
1992
2559
  }
1993
2560
  _normalizeCopyImageDataOptions(options_) {
1994
- const { width, height, depth } = this;
1995
- const options = { ..._Texture.defaultCopyDataOptions, width, height, depth, ...options_ };
1996
- const info = this.device.getTextureFormatInfo(this.format);
1997
- if (!options_.bytesPerRow && !info.bytesPerPixel) {
1998
- throw new Error(`bytesPerRow must be provided for texture format ${this.format}`);
1999
- }
2000
- options.bytesPerRow = options_.bytesPerRow || width * (info.bytesPerPixel || 4);
2001
- options.rowsPerImage = options_.rowsPerImage || height;
2002
- return options;
2561
+ const { data, depth, ...writeOptions } = options_;
2562
+ const options = this._normalizeTextureWriteOptions({
2563
+ ...writeOptions,
2564
+ depthOrArrayLayers: writeOptions.depthOrArrayLayers ?? depth
2565
+ });
2566
+ return { data, depth: options.depthOrArrayLayers, ...options };
2003
2567
  }
2004
2568
  _normalizeCopyExternalImageOptions(options_) {
2569
+ const optionsWithoutUndefined = _Texture._omitUndefined(options_);
2570
+ const mipLevel = optionsWithoutUndefined.mipLevel ?? 0;
2571
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
2005
2572
  const size = this.device.getExternalImageSize(options_.image);
2006
- const options = { ..._Texture.defaultCopyExternalImageOptions, ...size, ...options_ };
2007
- options.width = Math.min(options.width, this.width - options.x);
2008
- options.height = Math.min(options.height, this.height - options.y);
2573
+ const options = {
2574
+ ..._Texture.defaultCopyExternalImageOptions,
2575
+ ...mipLevelSize,
2576
+ ...size,
2577
+ ...optionsWithoutUndefined
2578
+ };
2579
+ options.width = Math.min(options.width, mipLevelSize.width - options.x);
2580
+ options.height = Math.min(options.height, mipLevelSize.height - options.y);
2581
+ options.depth = Math.min(options.depth, mipLevelSize.depthOrArrayLayers - options.z);
2009
2582
  return options;
2010
2583
  }
2011
2584
  _normalizeTextureReadOptions(options_) {
2012
- const { width, height } = this;
2013
- const options = { ..._Texture.defaultTextureReadOptions, width, height, ...options_ };
2014
- options.width = Math.min(options.width, this.width - options.x);
2015
- options.height = Math.min(options.height, this.height - options.y);
2585
+ const optionsWithoutUndefined = _Texture._omitUndefined(options_);
2586
+ const mipLevel = optionsWithoutUndefined.mipLevel ?? 0;
2587
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
2588
+ const options = {
2589
+ ..._Texture.defaultTextureReadOptions,
2590
+ ...mipLevelSize,
2591
+ ...optionsWithoutUndefined
2592
+ };
2593
+ options.width = Math.min(options.width, mipLevelSize.width - options.x);
2594
+ options.height = Math.min(options.height, mipLevelSize.height - options.y);
2595
+ options.depthOrArrayLayers = Math.min(options.depthOrArrayLayers, mipLevelSize.depthOrArrayLayers - options.z);
2016
2596
  return options;
2017
2597
  }
2598
+ /**
2599
+ * Normalizes a texture read request and validates the color-only readback contract used by the
2600
+ * current texture read APIs. Supported dimensions are `2d`, `cube`, `cube-array`,
2601
+ * `2d-array`, and `3d`.
2602
+ *
2603
+ * @throws if the texture format, aspect, or dimension is not supported by the first-pass
2604
+ * color-read implementation.
2605
+ */
2606
+ _getSupportedColorReadOptions(options_) {
2607
+ const options = this._normalizeTextureReadOptions(options_);
2608
+ const formatInfo = textureFormatDecoder.getInfo(this.format);
2609
+ this._validateColorReadAspect(options);
2610
+ this._validateColorReadFormat(formatInfo);
2611
+ switch (this.dimension) {
2612
+ case "2d":
2613
+ case "cube":
2614
+ case "cube-array":
2615
+ case "2d-array":
2616
+ case "3d":
2617
+ return options;
2618
+ default:
2619
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
2620
+ }
2621
+ }
2622
+ /** Validates that a read request targets the full color aspect of the texture. */
2623
+ _validateColorReadAspect(options) {
2624
+ if (options.aspect !== "all") {
2625
+ throw new Error(`${this} color readback only supports aspect 'all'`);
2626
+ }
2627
+ }
2628
+ /** Validates that a read request targets an uncompressed color-renderable texture format. */
2629
+ _validateColorReadFormat(formatInfo) {
2630
+ if (formatInfo.compressed) {
2631
+ throw new Error(`${this} color readback does not support compressed formats (${this.format})`);
2632
+ }
2633
+ switch (formatInfo.attachment) {
2634
+ case "color":
2635
+ return;
2636
+ case "depth":
2637
+ throw new Error(`${this} color readback does not support depth formats (${this.format})`);
2638
+ case "stencil":
2639
+ throw new Error(`${this} color readback does not support stencil formats (${this.format})`);
2640
+ case "depth-stencil":
2641
+ throw new Error(`${this} color readback does not support depth-stencil formats (${this.format})`);
2642
+ default:
2643
+ throw new Error(`${this} color readback does not support format ${this.format}`);
2644
+ }
2645
+ }
2018
2646
  _normalizeTextureWriteOptions(options_) {
2019
- const { width, height } = this;
2020
- const options = { ..._Texture.defaultTextureReadOptions, width, height, ...options_ };
2021
- options.width = Math.min(options.width, this.width - options.x);
2022
- options.height = Math.min(options.height, this.height - options.y);
2647
+ const optionsWithoutUndefined = _Texture._omitUndefined(options_);
2648
+ const mipLevel = optionsWithoutUndefined.mipLevel ?? 0;
2649
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
2650
+ const options = {
2651
+ ..._Texture.defaultTextureWriteOptions,
2652
+ ...mipLevelSize,
2653
+ ...optionsWithoutUndefined
2654
+ };
2655
+ options.width = Math.min(options.width, mipLevelSize.width - options.x);
2656
+ options.height = Math.min(options.height, mipLevelSize.height - options.y);
2657
+ options.depthOrArrayLayers = Math.min(options.depthOrArrayLayers, mipLevelSize.depthOrArrayLayers - options.z);
2658
+ const layout = textureFormatDecoder.computeMemoryLayout({
2659
+ format: this.format,
2660
+ width: options.width,
2661
+ height: options.height,
2662
+ depth: options.depthOrArrayLayers,
2663
+ byteAlignment: this.byteAlignment
2664
+ });
2665
+ const minimumBytesPerRow = layout.bytesPerPixel * options.width;
2666
+ options.bytesPerRow = optionsWithoutUndefined.bytesPerRow ?? layout.bytesPerRow;
2667
+ options.rowsPerImage = optionsWithoutUndefined.rowsPerImage ?? options.height;
2668
+ if (options.bytesPerRow < minimumBytesPerRow) {
2669
+ throw new Error(`bytesPerRow (${options.bytesPerRow}) must be at least ${minimumBytesPerRow} for ${this.format}`);
2670
+ }
2671
+ if (options.rowsPerImage < options.height) {
2672
+ throw new Error(`rowsPerImage (${options.rowsPerImage}) must be at least ${options.height} for ${this.format}`);
2673
+ }
2674
+ const bytesPerPixel = this.device.getTextureFormatInfo(this.format).bytesPerPixel;
2675
+ if (bytesPerPixel && options.bytesPerRow % bytesPerPixel !== 0) {
2676
+ throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
2677
+ }
2023
2678
  return options;
2024
2679
  }
2680
+ _getMipLevelSize(mipLevel) {
2681
+ const width = Math.max(1, this.width >> mipLevel);
2682
+ const height = this.baseDimension === "1d" ? 1 : Math.max(1, this.height >> mipLevel);
2683
+ const depthOrArrayLayers = this.dimension === "3d" ? Math.max(1, this.depth >> mipLevel) : this.depth;
2684
+ return { width, height, depthOrArrayLayers };
2685
+ }
2686
+ getAllocatedByteLength() {
2687
+ let allocatedByteLength = 0;
2688
+ for (let mipLevel = 0; mipLevel < this.mipLevels; mipLevel++) {
2689
+ const { width, height, depthOrArrayLayers } = this._getMipLevelSize(mipLevel);
2690
+ allocatedByteLength += textureFormatDecoder.computeMemoryLayout({
2691
+ format: this.format,
2692
+ width,
2693
+ height,
2694
+ depth: depthOrArrayLayers,
2695
+ byteAlignment: 1
2696
+ }).byteLength;
2697
+ }
2698
+ return allocatedByteLength * this.samples;
2699
+ }
2700
+ static _omitUndefined(options) {
2701
+ return Object.fromEntries(Object.entries(options).filter(([, value]) => value !== void 0));
2702
+ }
2025
2703
  };
2026
2704
  var Texture = _Texture;
2027
2705
  /** The texture can be bound for use as a sampled texture in a shader */
@@ -2057,6 +2735,10 @@ __publicField(Texture, "defaultCopyDataOptions", {
2057
2735
  byteOffset: 0,
2058
2736
  bytesPerRow: void 0,
2059
2737
  rowsPerImage: void 0,
2738
+ width: void 0,
2739
+ height: void 0,
2740
+ depthOrArrayLayers: void 0,
2741
+ depth: 1,
2060
2742
  mipLevel: 0,
2061
2743
  x: 0,
2062
2744
  y: 0,
@@ -2090,6 +2772,19 @@ __publicField(Texture, "defaultTextureReadOptions", {
2090
2772
  mipLevel: 0,
2091
2773
  aspect: "all"
2092
2774
  });
2775
+ __publicField(Texture, "defaultTextureWriteOptions", {
2776
+ byteOffset: 0,
2777
+ bytesPerRow: void 0,
2778
+ rowsPerImage: void 0,
2779
+ x: 0,
2780
+ y: 0,
2781
+ z: 0,
2782
+ width: void 0,
2783
+ height: void 0,
2784
+ depthOrArrayLayers: 1,
2785
+ mipLevel: 0,
2786
+ aspect: "all"
2787
+ });
2093
2788
 
2094
2789
  // dist/adapter/resources/texture-view.js
2095
2790
  var _TextureView = class extends Resource {
@@ -2466,10 +3161,23 @@ var _RenderPipeline = class extends Resource {
2466
3161
  linkStatus = "pending";
2467
3162
  /** The hash of the pipeline */
2468
3163
  hash = "";
3164
+ /** Optional shared backend implementation */
3165
+ sharedRenderPipeline = null;
3166
+ /** Whether shader or pipeline compilation/linking is still in progress */
3167
+ get isPending() {
3168
+ var _a;
3169
+ return this.linkStatus === "pending" || this.vs.compilationStatus === "pending" || ((_a = this.fs) == null ? void 0 : _a.compilationStatus) === "pending";
3170
+ }
3171
+ /** Whether shader or pipeline compilation/linking has failed */
3172
+ get isErrored() {
3173
+ var _a;
3174
+ return this.linkStatus === "error" || this.vs.compilationStatus === "error" || ((_a = this.fs) == null ? void 0 : _a.compilationStatus) === "error";
3175
+ }
2469
3176
  constructor(device, props) {
2470
3177
  super(device, props, _RenderPipeline.defaultProps);
2471
3178
  this.shaderLayout = this.props.shaderLayout;
2472
3179
  this.bufferLayout = this.props.bufferLayout || [];
3180
+ this.sharedRenderPipeline = this.props._sharedRenderPipeline || null;
2473
3181
  }
2474
3182
  };
2475
3183
  var RenderPipeline = _RenderPipeline;
@@ -2487,10 +3195,476 @@ __publicField(RenderPipeline, "defaultProps", {
2487
3195
  colorAttachmentFormats: void 0,
2488
3196
  depthStencilAttachmentFormat: void 0,
2489
3197
  parameters: {},
2490
- bindings: {},
2491
- uniforms: {}
3198
+ varyings: void 0,
3199
+ bufferMode: void 0,
3200
+ disableWarnings: false,
3201
+ _sharedRenderPipeline: void 0,
3202
+ bindings: void 0,
3203
+ bindGroups: void 0
2492
3204
  });
2493
3205
 
3206
+ // dist/adapter/resources/shared-render-pipeline.js
3207
+ var SharedRenderPipeline = class extends Resource {
3208
+ get [Symbol.toStringTag]() {
3209
+ return "SharedRenderPipeline";
3210
+ }
3211
+ constructor(device, props) {
3212
+ super(device, props, {
3213
+ ...Resource.defaultProps,
3214
+ handle: void 0,
3215
+ vs: void 0,
3216
+ fs: void 0,
3217
+ varyings: void 0,
3218
+ bufferMode: void 0
3219
+ });
3220
+ }
3221
+ };
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
+
2494
3668
  // dist/adapter/resources/render-pass.js
2495
3669
  var _RenderPass = class extends Resource {
2496
3670
  get [Symbol.toStringTag]() {
@@ -2529,28 +3703,6 @@ __publicField(RenderPass, "defaultProps", {
2529
3703
  endTimestampIndex: void 0
2530
3704
  });
2531
3705
 
2532
- // dist/adapter/resources/compute-pipeline.js
2533
- var _ComputePipeline = class extends Resource {
2534
- get [Symbol.toStringTag]() {
2535
- return "ComputePipeline";
2536
- }
2537
- hash = "";
2538
- /** The merged shader layout */
2539
- shaderLayout;
2540
- constructor(device, props) {
2541
- super(device, props, _ComputePipeline.defaultProps);
2542
- this.shaderLayout = props.shaderLayout;
2543
- }
2544
- };
2545
- var ComputePipeline = _ComputePipeline;
2546
- __publicField(ComputePipeline, "defaultProps", {
2547
- ...Resource.defaultProps,
2548
- shader: void 0,
2549
- entryPoint: void 0,
2550
- constants: {},
2551
- shaderLayout: void 0
2552
- });
2553
-
2554
3706
  // dist/adapter/resources/compute-pass.js
2555
3707
  var _ComputePass = class extends Resource {
2556
3708
  constructor(device, props) {
@@ -2573,8 +3725,69 @@ var _CommandEncoder = class extends Resource {
2573
3725
  get [Symbol.toStringTag]() {
2574
3726
  return "CommandEncoder";
2575
3727
  }
3728
+ _timeProfilingQuerySet = null;
3729
+ _timeProfilingSlotCount = 0;
3730
+ _gpuTimeMs;
2576
3731
  constructor(device, props) {
2577
3732
  super(device, props, _CommandEncoder.defaultProps);
3733
+ this._timeProfilingQuerySet = props.timeProfilingQuerySet ?? null;
3734
+ this._timeProfilingSlotCount = 0;
3735
+ this._gpuTimeMs = void 0;
3736
+ }
3737
+ /**
3738
+ * Reads all resolved timestamp pairs on the current profiler query set and caches the sum
3739
+ * as milliseconds on this encoder.
3740
+ */
3741
+ async resolveTimeProfilingQuerySet() {
3742
+ this._gpuTimeMs = void 0;
3743
+ if (!this._timeProfilingQuerySet) {
3744
+ return;
3745
+ }
3746
+ const pairCount = Math.floor(this._timeProfilingSlotCount / 2);
3747
+ if (pairCount <= 0) {
3748
+ return;
3749
+ }
3750
+ const queryCount = pairCount * 2;
3751
+ const results = await this._timeProfilingQuerySet.readResults({
3752
+ firstQuery: 0,
3753
+ queryCount
3754
+ });
3755
+ let totalDurationNanoseconds = 0n;
3756
+ for (let queryIndex = 0; queryIndex < queryCount; queryIndex += 2) {
3757
+ totalDurationNanoseconds += results[queryIndex + 1] - results[queryIndex];
3758
+ }
3759
+ this._gpuTimeMs = Number(totalDurationNanoseconds) / 1e6;
3760
+ }
3761
+ /** Returns the number of query slots consumed by automatic pass profiling on this encoder. */
3762
+ getTimeProfilingSlotCount() {
3763
+ return this._timeProfilingSlotCount;
3764
+ }
3765
+ getTimeProfilingQuerySet() {
3766
+ return this._timeProfilingQuerySet;
3767
+ }
3768
+ /** Internal helper for auto-assigning timestamp slots to render/compute passes on this encoder. */
3769
+ _applyTimeProfilingToPassProps(props) {
3770
+ const passProps = props || {};
3771
+ if (!this._supportsTimestampQueries() || !this._timeProfilingQuerySet) {
3772
+ return passProps;
3773
+ }
3774
+ if (passProps.timestampQuerySet !== void 0 || passProps.beginTimestampIndex !== void 0 || passProps.endTimestampIndex !== void 0) {
3775
+ return passProps;
3776
+ }
3777
+ const beginTimestampIndex = this._timeProfilingSlotCount;
3778
+ if (beginTimestampIndex + 1 >= this._timeProfilingQuerySet.props.count) {
3779
+ return passProps;
3780
+ }
3781
+ this._timeProfilingSlotCount += 2;
3782
+ return {
3783
+ ...passProps,
3784
+ timestampQuerySet: this._timeProfilingQuerySet,
3785
+ beginTimestampIndex,
3786
+ endTimestampIndex: beginTimestampIndex + 1
3787
+ };
3788
+ }
3789
+ _supportsTimestampQueries() {
3790
+ return this.device.features.has("timestamp-query");
2578
3791
  }
2579
3792
  };
2580
3793
  var CommandEncoder = _CommandEncoder;
@@ -2583,7 +3796,8 @@ var CommandEncoder = _CommandEncoder;
2583
3796
  // beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
2584
3797
  __publicField(CommandEncoder, "defaultProps", {
2585
3798
  ...Resource.defaultProps,
2586
- measureExecutionTime: void 0
3799
+ measureExecutionTime: void 0,
3800
+ timeProfilingQuerySet: void 0
2587
3801
  });
2588
3802
 
2589
3803
  // dist/adapter/resources/command-buffer.js
@@ -2600,13 +3814,22 @@ __publicField(CommandBuffer, "defaultProps", {
2600
3814
  ...Resource.defaultProps
2601
3815
  });
2602
3816
 
2603
- // dist/shadertypes/data-types/decode-shader-types.js
3817
+ // dist/shadertypes/shader-types/shader-type-decoder.js
2604
3818
  function getVariableShaderTypeInfo(format) {
2605
- const decoded = UNIFORM_FORMATS[format];
3819
+ const resolvedFormat = resolveVariableShaderTypeAlias(format);
3820
+ const decoded = UNIFORM_FORMATS[resolvedFormat];
3821
+ if (!decoded) {
3822
+ throw new Error(`Unsupported variable shader type: ${format}`);
3823
+ }
2606
3824
  return decoded;
2607
3825
  }
2608
3826
  function getAttributeShaderTypeInfo(attributeType) {
2609
- const [primitiveType, components] = TYPE_INFO[attributeType];
3827
+ const resolvedAttributeType = resolveAttributeShaderTypeAlias(attributeType);
3828
+ const decoded = TYPE_INFO[resolvedAttributeType];
3829
+ if (!decoded) {
3830
+ throw new Error(`Unsupported attribute shader type: ${attributeType}`);
3831
+ }
3832
+ const [primitiveType, components] = decoded;
2610
3833
  const integer = primitiveType === "i32" || primitiveType === "u32";
2611
3834
  const signed = primitiveType !== "u32";
2612
3835
  const byteLength = PRIMITIVE_TYPE_SIZES[primitiveType] * components;
@@ -2618,6 +3841,33 @@ function getAttributeShaderTypeInfo(attributeType) {
2618
3841
  signed
2619
3842
  };
2620
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
+ }
3864
+ function resolveAttributeShaderTypeAlias(alias) {
3865
+ return WGSL_ATTRIBUTE_TYPE_ALIAS_MAP[alias] || alias;
3866
+ }
3867
+ function resolveVariableShaderTypeAlias(alias) {
3868
+ return WGSL_VARIABLE_TYPE_ALIAS_MAP[alias] || alias;
3869
+ }
3870
+ var shaderTypeDecoder = new ShaderTypeDecoder();
2621
3871
  var PRIMITIVE_TYPE_SIZES = {
2622
3872
  f32: 4,
2623
3873
  f16: 2,
@@ -2714,7 +3964,18 @@ var WGSL_ATTRIBUTE_TYPE_ALIAS_MAP = {
2714
3964
  vec4h: "vec4<f16>"
2715
3965
  };
2716
3966
  var WGSL_VARIABLE_TYPE_ALIAS_MAP = {
2717
- ...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>",
2718
3979
  mat2x2f: "mat2x2<f32>",
2719
3980
  mat2x3f: "mat2x3<f32>",
2720
3981
  mat2x4f: "mat2x4<f32>",
@@ -2778,10 +4039,10 @@ function getAttributeInfoFromLayouts(shaderLayout, bufferLayout, name2) {
2778
4039
  if (!shaderDeclaration) {
2779
4040
  return null;
2780
4041
  }
2781
- const attributeTypeInfo = getAttributeShaderTypeInfo(shaderDeclaration.type);
2782
- const defaultVertexFormat = getCompatibleVertexFormat(attributeTypeInfo);
4042
+ const attributeTypeInfo = shaderTypeDecoder.getAttributeShaderTypeInfo(shaderDeclaration.type);
4043
+ const defaultVertexFormat = vertexFormatDecoder.getCompatibleVertexFormat(attributeTypeInfo);
2783
4044
  const vertexFormat = (bufferMapping == null ? void 0 : bufferMapping.vertexFormat) || defaultVertexFormat;
2784
- const vertexFormatInfo = getVertexFormatInfo(vertexFormat);
4045
+ const vertexFormatInfo = vertexFormatDecoder.getVertexFormatInfo(vertexFormat);
2785
4046
  return {
2786
4047
  attributeName: (bufferMapping == null ? void 0 : bufferMapping.attributeName) || shaderDeclaration.name,
2787
4048
  bufferName: (bufferMapping == null ? void 0 : bufferMapping.bufferName) || shaderDeclaration.name,
@@ -2850,7 +4111,7 @@ function getAttributeFromAttributesList(bufferLayouts, name2) {
2850
4111
  let byteStride = bufferLayout.byteStride;
2851
4112
  if (typeof bufferLayout.byteStride !== "number") {
2852
4113
  for (const attributeMapping2 of bufferLayout.attributes || []) {
2853
- const info = getVertexFormatInfo(attributeMapping2.format);
4114
+ const info = vertexFormatDecoder.getVertexFormatInfo(attributeMapping2.format);
2854
4115
  byteStride += info.byteLength;
2855
4116
  }
2856
4117
  }
@@ -2936,7 +4197,9 @@ __publicField(QuerySet, "defaultProps", {
2936
4197
 
2937
4198
  // dist/adapter/resources/fence.js
2938
4199
  var _Fence = class extends Resource {
2939
- [Symbol.toStringTag] = "WEBGLFence";
4200
+ get [Symbol.toStringTag]() {
4201
+ return "Fence";
4202
+ }
2940
4203
  constructor(device, props = {}) {
2941
4204
  super(device, props, _Fence.defaultProps);
2942
4205
  }
@@ -2964,6 +4227,36 @@ __publicField(PipelineLayout, "defaultProps", {
2964
4227
  }
2965
4228
  });
2966
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
+
2967
4260
  // dist/utils/array-utils-flat.js
2968
4261
  var arrayBuffer;
2969
4262
  function getScratchArrayBuffer(byteLength) {
@@ -2977,19 +4270,32 @@ function getScratchArray(Type, length) {
2977
4270
  return new Type(scratchArrayBuffer, 0, length);
2978
4271
  }
2979
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
+
2980
4284
  // dist/portable/uniform-buffer-layout.js
2981
4285
  var minBufferSize = 1024;
2982
4286
  var UniformBufferLayout = class {
2983
4287
  layout = {};
4288
+ uniformTypes;
2984
4289
  /** number of bytes needed for buffer allocation */
2985
4290
  byteLength;
2986
4291
  /** Create a new UniformBufferLayout given a map of attributes. */
2987
- constructor(uniformTypes, uniformSizes = {}) {
4292
+ constructor(uniformTypes) {
4293
+ this.uniformTypes = { ...uniformTypes };
2988
4294
  let size = 0;
2989
- for (const [key, uniformType] of Object.entries(uniformTypes)) {
2990
- 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);
2991
4297
  }
2992
- size += (4 - size % 4) % 4;
4298
+ size = alignTo(size, 4);
2993
4299
  this.byteLength = Math.max(size * 4, minBufferSize);
2994
4300
  }
2995
4301
  /** Does this layout have a field with specified name */
@@ -3001,115 +4307,255 @@ var UniformBufferLayout = class {
3001
4307
  const layout = this.layout[name2];
3002
4308
  return layout;
3003
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
+ }
3004
4323
  /** Get the data for the complete buffer */
3005
4324
  getData(uniformValues) {
3006
4325
  const buffer = getScratchArrayBuffer(this.byteLength);
4326
+ new Uint8Array(buffer, 0, this.byteLength).fill(0);
3007
4327
  const typedArrays = {
3008
4328
  i32: new Int32Array(buffer),
3009
4329
  u32: new Uint32Array(buffer),
3010
4330
  f32: new Float32Array(buffer),
3011
4331
  f16: new Uint16Array(buffer)
3012
4332
  };
3013
- for (const [name2, value] of Object.entries(uniformValues)) {
3014
- 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);
3015
4336
  }
3016
4337
  return new Uint8Array(buffer, 0, this.byteLength);
3017
4338
  }
3018
4339
  // Recursively add a uniform to the layout
3019
- _addToLayout(name2, type, offset, count = 1) {
4340
+ _addToLayout(name2, type, offset) {
3020
4341
  if (typeof type === "string") {
3021
- const info = getVariableShaderTypeInfo(type);
3022
- const sizeInSlots = info.components * count;
3023
- const alignedOffset = alignTo(offset, info.components);
4342
+ const info = getLeafLayoutInfo(type);
4343
+ const alignedOffset = alignTo(offset, info.alignment);
3024
4344
  this.layout[name2] = {
3025
4345
  offset: alignedOffset,
3026
- size: sizeInSlots,
3027
- type: info.type
4346
+ ...info
3028
4347
  };
3029
- return alignedOffset + sizeInSlots;
4348
+ return alignedOffset + info.size;
3030
4349
  }
3031
4350
  if (Array.isArray(type)) {
4351
+ if (Array.isArray(type[0])) {
4352
+ throw new Error(`Nested arrays are not supported for ${name2}`);
4353
+ }
3032
4354
  const elementType = type[0];
3033
- const length = count > 1 ? count : type.length > 1 ? type[1] : 1;
3034
- let arrayOffset = alignTo(offset, 4);
4355
+ const length = type[1];
4356
+ const stride = alignTo(getTypeSize(elementType), 4);
4357
+ const arrayOffset = alignTo(offset, 4);
3035
4358
  for (let i = 0; i < length; i++) {
3036
- arrayOffset = this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset);
4359
+ this._addToLayout(`${name2}[${i}]`, elementType, arrayOffset + i * stride);
3037
4360
  }
3038
- return arrayOffset;
4361
+ return arrayOffset + stride * length;
3039
4362
  }
3040
- if (typeof type === "object") {
4363
+ if (isCompositeShaderTypeStruct(type)) {
3041
4364
  let structOffset = alignTo(offset, 4);
3042
4365
  for (const [memberName, memberType] of Object.entries(type)) {
3043
4366
  structOffset = this._addToLayout(`${name2}.${memberName}`, memberType, structOffset);
3044
4367
  }
3045
- return structOffset;
4368
+ return alignTo(structOffset, 4);
3046
4369
  }
3047
4370
  throw new Error(`Unsupported CompositeShaderType for ${name2}`);
3048
4371
  }
3049
- _writeCompositeValue(typedArrays, baseName, value) {
3050
- if (this.layout[baseName]) {
3051
- 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;
3052
4378
  return;
3053
4379
  }
3054
- if (Array.isArray(value)) {
3055
- for (let i = 0; i < value.length; i++) {
3056
- const element = value[i];
3057
- const indexedName = `${baseName}[${i}]`;
3058
- 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);
3059
4400
  }
3060
4401
  return;
3061
4402
  }
3062
- if (typeof value === "object" && value !== null) {
4403
+ if (isCompositeShaderTypeStruct(uniformType) && isCompositeUniformObject(value)) {
3063
4404
  for (const [key, subValue] of Object.entries(value)) {
4405
+ if (subValue === void 0) {
4406
+ continue;
4407
+ }
3064
4408
  const nestedName = `${baseName}.${key}`;
3065
- this._writeCompositeValue(typedArrays, nestedName, subValue);
4409
+ this._flattenCompositeValue(flattenedUniformValues, nestedName, uniformType[key], subValue);
3066
4410
  }
3067
4411
  return;
3068
4412
  }
3069
4413
  log.warn(`Unsupported uniform value for ${baseName}:`, value)();
3070
4414
  }
3071
- _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) {
3072
4432
  const layout = this.layout[name2];
3073
4433
  if (!layout) {
3074
4434
  log.warn(`Uniform ${name2} not found in layout`)();
3075
4435
  return;
3076
4436
  }
3077
- const { type, size, offset } = layout;
4437
+ const { type, components, columns, rows, offset } = layout;
3078
4438
  const array = typedArrays[type];
3079
- if (size === 1) {
4439
+ if (components === 1) {
3080
4440
  array[offset] = Number(value);
3081
- } else {
3082
- 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
+ }
3083
4456
  }
3084
4457
  }
3085
4458
  };
3086
-
3087
- // dist/utils/is-array.js
3088
- function isTypedArray(value) {
3089
- 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);
3090
4478
  }
3091
- function isNumberArray(value) {
3092
- if (Array.isArray(value)) {
3093
- return value.length === 0 || typeof value[0] === "number";
4479
+ function getTypeAlignment(type) {
4480
+ if (typeof type === "string") {
4481
+ return getLeafLayoutInfo(type).alignment;
3094
4482
  }
3095
- 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);
3096
4536
  }
3097
4537
 
3098
4538
  // dist/utils/array-equal.js
4539
+ var MAX_ELEMENTWISE_ARRAY_COMPARE_LENGTH = 128;
3099
4540
  function arrayEqual(a, b, limit = 16) {
3100
- if (a !== b) {
3101
- return false;
4541
+ if (a === b) {
4542
+ return true;
3102
4543
  }
3103
4544
  const arrayA = a;
3104
4545
  const arrayB = b;
3105
- if (!isNumberArray(arrayA)) {
4546
+ if (!isNumberArray(arrayA) || !isNumberArray(arrayB)) {
3106
4547
  return false;
3107
4548
  }
3108
- if (isNumberArray(arrayB) && arrayA.length === arrayB.length) {
3109
- for (let i = 0; i < arrayA.length; ++i) {
3110
- if (arrayB[i] !== arrayA[i]) {
3111
- return false;
3112
- }
4549
+ if (arrayA.length !== arrayB.length) {
4550
+ return false;
4551
+ }
4552
+ const maxCompareLength = Math.min(limit, MAX_ELEMENTWISE_ARRAY_COMPARE_LENGTH);
4553
+ if (arrayA.length > maxCompareLength) {
4554
+ return false;
4555
+ }
4556
+ for (let i = 0; i < arrayA.length; ++i) {
4557
+ if (arrayB[i] !== arrayA[i]) {
4558
+ return false;
3113
4559
  }
3114
4560
  }
3115
4561
  return true;
@@ -3187,10 +4633,10 @@ var UniformStore = class {
3187
4633
  constructor(blocks) {
3188
4634
  for (const [bufferName, block] of Object.entries(blocks)) {
3189
4635
  const uniformBufferName = bufferName;
3190
- const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes ?? {}, block.uniformSizes ?? {});
4636
+ const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes ?? {});
3191
4637
  this.uniformBufferLayouts.set(uniformBufferName, uniformBufferLayout);
3192
4638
  const uniformBlock = new UniformBlock({ name: bufferName });
3193
- uniformBlock.setUniforms(block.defaultUniforms || {});
4639
+ uniformBlock.setUniforms(uniformBufferLayout.getFlatUniformValues(block.defaultUniforms || {}));
3194
4640
  this.uniformBlocks.set(uniformBufferName, uniformBlock);
3195
4641
  }
3196
4642
  }
@@ -3207,7 +4653,10 @@ var UniformStore = class {
3207
4653
  setUniforms(uniforms) {
3208
4654
  var _a;
3209
4655
  for (const [blockName, uniformValues] of Object.entries(uniforms)) {
3210
- (_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 || {});
3211
4660
  }
3212
4661
  this.updateUniformBuffers();
3213
4662
  }
@@ -3281,7 +4730,7 @@ var UniformStore = class {
3281
4730
  }
3282
4731
  };
3283
4732
 
3284
- // dist/shadertypes/textures/texture-layout.js
4733
+ // dist/shadertypes/texture-types/texture-layout.js
3285
4734
  function getTextureImageView(arrayBuffer2, memoryLayout, format, image = 0) {
3286
4735
  const formatInfo = textureFormatDecoder.getInfo(format);
3287
4736
  const bytesPerComponent = formatInfo.bytesPerPixel / formatInfo.components;
@@ -3319,7 +4768,7 @@ function setTextureImageData(arrayBuffer2, memoryLayout, format, data, image = 0
3319
4768
  typedArray.set(subArray, offset);
3320
4769
  }
3321
4770
 
3322
- // dist/shadertypes/textures/pixel-utils.js
4771
+ // dist/shadertypes/texture-types/pixel-utils.js
3323
4772
  function readPixel(pixelData, x, y, bitsPerChannel) {
3324
4773
  if (x < 0 || x >= pixelData.width || y < 0 || y >= pixelData.height) {
3325
4774
  throw new Error("Coordinates out of bounds.");