@luma.gl/webgl 9.2.6 → 9.3.0-alpha.11

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 (247) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts +1 -1
  2. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  3. package/dist/adapter/converters/device-parameters.js +4 -1
  4. package/dist/adapter/converters/device-parameters.js.map +1 -1
  5. package/dist/adapter/converters/sampler-parameters.d.ts +1 -1
  6. package/dist/adapter/converters/sampler-parameters.d.ts.map +1 -1
  7. package/dist/adapter/converters/sampler-parameters.js +1 -1
  8. package/dist/adapter/converters/sampler-parameters.js.map +1 -1
  9. package/dist/adapter/converters/shader-formats.d.ts +1 -64
  10. package/dist/adapter/converters/shader-formats.d.ts.map +1 -1
  11. package/dist/adapter/converters/shader-formats.js +1 -64
  12. package/dist/adapter/converters/shader-formats.js.map +1 -1
  13. package/dist/adapter/converters/webgl-shadertypes.d.ts +1 -3
  14. package/dist/adapter/converters/webgl-shadertypes.d.ts.map +1 -1
  15. package/dist/adapter/converters/webgl-shadertypes.js +2 -7
  16. package/dist/adapter/converters/webgl-shadertypes.js.map +1 -1
  17. package/dist/adapter/converters/webgl-texture-table.d.ts +8 -4
  18. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
  19. package/dist/adapter/converters/webgl-texture-table.js +125 -61
  20. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  21. package/dist/adapter/converters/webgl-vertex-formats.d.ts +1 -1
  22. package/dist/adapter/converters/webgl-vertex-formats.d.ts.map +1 -1
  23. package/dist/adapter/converters/webgl-vertex-formats.js +4 -4
  24. package/dist/adapter/converters/webgl-vertex-formats.js.map +1 -1
  25. package/dist/adapter/device-helpers/webgl-device-features.d.ts +1 -1
  26. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  27. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  28. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
  29. package/dist/adapter/device-helpers/webgl-device-info.d.ts +1 -1
  30. package/dist/adapter/device-helpers/webgl-device-info.d.ts.map +1 -1
  31. package/dist/adapter/device-helpers/webgl-device-info.js +6 -1
  32. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
  33. package/dist/adapter/device-helpers/webgl-device-limits.d.ts +1 -1
  34. package/dist/adapter/device-helpers/webgl-device-limits.d.ts.map +1 -1
  35. package/dist/adapter/device-helpers/webgl-device-limits.js +2 -2
  36. package/dist/adapter/device-helpers/webgl-device-limits.js.map +1 -1
  37. package/dist/adapter/helpers/format-utils.d.ts +1 -1
  38. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  39. package/dist/adapter/helpers/format-utils.js +1 -1
  40. package/dist/adapter/helpers/format-utils.js.map +1 -1
  41. package/dist/adapter/helpers/get-shader-layout-from-glsl.js +36 -22
  42. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  43. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts +1 -1
  44. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts.map +1 -1
  45. package/dist/adapter/helpers/parse-shader-compiler-log.js +22 -2
  46. package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -1
  47. package/dist/adapter/helpers/set-uniform.d.ts +1 -1
  48. package/dist/adapter/helpers/set-uniform.d.ts.map +1 -1
  49. package/dist/adapter/helpers/set-uniform.js +2 -2
  50. package/dist/adapter/helpers/set-uniform.js.map +1 -1
  51. package/dist/adapter/helpers/webgl-texture-utils.d.ts +1 -1
  52. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  53. package/dist/adapter/helpers/webgl-texture-utils.js +9 -9
  54. package/dist/adapter/helpers/webgl-texture-utils.js.map +1 -1
  55. package/dist/adapter/helpers/webgl-topology-utils.d.ts +1 -1
  56. package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
  57. package/dist/adapter/helpers/webgl-topology-utils.js +3 -3
  58. package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -1
  59. package/dist/adapter/resources/webgl-buffer.d.ts +1 -1
  60. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  61. package/dist/adapter/resources/webgl-buffer.js +20 -5
  62. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  63. package/dist/adapter/resources/webgl-command-buffer.d.ts +7 -8
  64. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  65. package/dist/adapter/resources/webgl-command-buffer.js +33 -43
  66. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  67. package/dist/adapter/resources/webgl-command-encoder.d.ts +6 -5
  68. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  69. package/dist/adapter/resources/webgl-command-encoder.js +23 -8
  70. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  71. package/dist/adapter/resources/webgl-fence.d.ts +14 -0
  72. package/dist/adapter/resources/webgl-fence.d.ts.map +1 -0
  73. package/dist/adapter/resources/webgl-fence.js +49 -0
  74. package/dist/adapter/resources/webgl-fence.js.map +1 -0
  75. package/dist/adapter/resources/webgl-framebuffer.d.ts +3 -1
  76. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  77. package/dist/adapter/resources/webgl-framebuffer.js +10 -1
  78. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -1
  79. package/dist/adapter/resources/webgl-query-set.d.ts +37 -31
  80. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  81. package/dist/adapter/resources/webgl-query-set.js +247 -96
  82. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  83. package/dist/adapter/resources/webgl-render-pass.d.ts +1 -1
  84. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  85. package/dist/adapter/resources/webgl-render-pass.js +28 -11
  86. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  87. package/dist/adapter/resources/webgl-render-pipeline.d.ts +17 -21
  88. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  89. package/dist/adapter/resources/webgl-render-pipeline.js +94 -192
  90. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  91. package/dist/adapter/resources/webgl-sampler.d.ts +1 -1
  92. package/dist/adapter/resources/webgl-sampler.d.ts.map +1 -1
  93. package/dist/adapter/resources/webgl-sampler.js +1 -1
  94. package/dist/adapter/resources/webgl-sampler.js.map +1 -1
  95. package/dist/adapter/resources/webgl-shader.d.ts +1 -1
  96. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  97. package/dist/adapter/resources/webgl-shader.js +15 -8
  98. package/dist/adapter/resources/webgl-shader.js.map +1 -1
  99. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  100. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  101. package/dist/adapter/resources/webgl-shared-render-pipeline.js +155 -0
  102. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  103. package/dist/adapter/resources/webgl-texture.d.ts +42 -4
  104. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  105. package/dist/adapter/resources/webgl-texture.js +289 -65
  106. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  107. package/dist/adapter/resources/webgl-transform-feedback.js +6 -6
  108. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  109. package/dist/adapter/resources/webgl-vertex-array.d.ts +2 -2
  110. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  111. package/dist/adapter/resources/webgl-vertex-array.js +1 -1
  112. package/dist/adapter/resources/webgl-vertex-array.js.map +1 -1
  113. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  114. package/dist/adapter/webgl-adapter.js +22 -23
  115. package/dist/adapter/webgl-adapter.js.map +1 -1
  116. package/dist/adapter/webgl-canvas-context.d.ts +2 -2
  117. package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
  118. package/dist/adapter/webgl-canvas-context.js +16 -6
  119. package/dist/adapter/webgl-canvas-context.js.map +1 -1
  120. package/dist/adapter/webgl-device.d.ts +10 -5
  121. package/dist/adapter/webgl-device.d.ts.map +1 -1
  122. package/dist/adapter/webgl-device.js +78 -28
  123. package/dist/adapter/webgl-device.js.map +1 -1
  124. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  125. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  126. package/dist/adapter/webgl-presentation-context.js +64 -0
  127. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  128. package/dist/constants/index.d.ts +3 -0
  129. package/dist/constants/index.d.ts.map +1 -0
  130. package/dist/constants/index.js +5 -0
  131. package/dist/constants/index.js.map +1 -0
  132. package/dist/constants/webgl-constants.d.ts +822 -0
  133. package/dist/constants/webgl-constants.d.ts.map +1 -0
  134. package/dist/constants/webgl-constants.js +928 -0
  135. package/dist/constants/webgl-constants.js.map +1 -0
  136. package/dist/constants/webgl-types.d.ts +480 -0
  137. package/dist/constants/webgl-types.d.ts.map +1 -0
  138. package/dist/constants/webgl-types.js +6 -0
  139. package/dist/constants/webgl-types.js.map +1 -0
  140. package/dist/context/debug/spector.d.ts.map +1 -1
  141. package/dist/context/debug/spector.js +4 -4
  142. package/dist/context/debug/spector.js.map +1 -1
  143. package/dist/context/debug/webgl-developer-tools.js +11 -9
  144. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  145. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  146. package/dist/context/helpers/create-browser-context.js +46 -36
  147. package/dist/context/helpers/create-browser-context.js.map +1 -1
  148. package/dist/context/helpers/webgl-context-data.d.ts +5 -1
  149. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  150. package/dist/context/helpers/webgl-context-data.js +9 -10
  151. package/dist/context/helpers/webgl-context-data.js.map +1 -1
  152. package/dist/context/helpers/webgl-extensions.d.ts +1 -1
  153. package/dist/context/helpers/webgl-extensions.d.ts.map +1 -1
  154. package/dist/context/parameters/unified-parameter-api.d.ts +2 -2
  155. package/dist/context/parameters/unified-parameter-api.d.ts.map +1 -1
  156. package/dist/context/parameters/unified-parameter-api.js +2 -2
  157. package/dist/context/parameters/unified-parameter-api.js.map +1 -1
  158. package/dist/context/parameters/webgl-parameter-tables.d.ts +1 -1
  159. package/dist/context/parameters/webgl-parameter-tables.d.ts.map +1 -1
  160. package/dist/context/parameters/webgl-parameter-tables.js +1 -1
  161. package/dist/context/parameters/webgl-parameter-tables.js.map +1 -1
  162. package/dist/context/polyfills/polyfill-webgl1-extensions.js +1 -1
  163. package/dist/context/polyfills/polyfill-webgl1-extensions.js.map +1 -1
  164. package/dist/context/state-tracker/webgl-state-tracker.js +2 -2
  165. package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -1
  166. package/dist/dist.dev.js +1898 -997
  167. package/dist/dist.min.js +2 -2
  168. package/dist/index.cjs +3 -5255
  169. package/dist/index.cjs.map +4 -4
  170. package/dist/index.d.ts +3 -0
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +2 -0
  173. package/dist/index.js.map +1 -1
  174. package/dist/utils/fill-array.js +1 -1
  175. package/dist/utils/fill-array.js.map +1 -1
  176. package/dist/webgl-constants.d.ts +2 -0
  177. package/dist/webgl-constants.d.ts.map +1 -0
  178. package/dist/webgl-constants.js +5 -0
  179. package/dist/webgl-constants.js.map +1 -0
  180. package/dist/webgl-types.d.ts +2 -0
  181. package/dist/webgl-types.d.ts.map +1 -0
  182. package/dist/{types.js → webgl-types.js} +1 -1
  183. package/dist/webgl-types.js.map +1 -0
  184. package/package.json +19 -5
  185. package/src/adapter/converters/device-parameters.ts +6 -2
  186. package/src/adapter/converters/sampler-parameters.ts +1 -1
  187. package/src/adapter/converters/shader-formats.ts +1 -66
  188. package/src/adapter/converters/webgl-shadertypes.ts +2 -10
  189. package/src/adapter/converters/webgl-texture-table.ts +160 -68
  190. package/src/adapter/converters/webgl-vertex-formats.ts +4 -4
  191. package/src/adapter/device-helpers/webgl-device-features.ts +2 -3
  192. package/src/adapter/device-helpers/webgl-device-info.ts +7 -1
  193. package/src/adapter/device-helpers/webgl-device-limits.ts +2 -2
  194. package/src/adapter/helpers/format-utils.ts +1 -1
  195. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +44 -24
  196. package/src/adapter/helpers/parse-shader-compiler-log.ts +25 -3
  197. package/src/adapter/helpers/set-uniform.ts +2 -2
  198. package/src/adapter/helpers/webgl-texture-utils.ts +9 -9
  199. package/src/adapter/helpers/webgl-topology-utils.ts +3 -3
  200. package/src/adapter/resources/webgl-buffer.ts +17 -5
  201. package/src/adapter/resources/webgl-command-buffer.ts +48 -52
  202. package/src/adapter/resources/webgl-command-encoder.ts +28 -11
  203. package/src/adapter/resources/webgl-fence.ts +55 -0
  204. package/src/adapter/resources/webgl-framebuffer.ts +12 -1
  205. package/src/adapter/resources/webgl-query-set.ts +295 -101
  206. package/src/adapter/resources/webgl-render-pass.ts +30 -13
  207. package/src/adapter/resources/webgl-render-pipeline.ts +131 -227
  208. package/src/adapter/resources/webgl-sampler.ts +1 -1
  209. package/src/adapter/resources/webgl-shader.ts +15 -8
  210. package/src/adapter/resources/webgl-shared-render-pipeline.ts +211 -0
  211. package/src/adapter/resources/webgl-texture.ts +458 -84
  212. package/src/adapter/resources/webgl-transform-feedback.ts +6 -6
  213. package/src/adapter/resources/webgl-vertex-array.ts +1 -1
  214. package/src/adapter/webgl-adapter.ts +26 -24
  215. package/src/adapter/webgl-canvas-context.ts +19 -8
  216. package/src/adapter/webgl-device.ts +94 -35
  217. package/src/adapter/webgl-presentation-context.ts +93 -0
  218. package/src/constants/index.d.ts.map +1 -0
  219. package/src/constants/index.js.map +1 -0
  220. package/src/constants/index.ts +31 -0
  221. package/src/constants/webgl-constants.d.ts.map +1 -0
  222. package/src/constants/webgl-constants.js.map +1 -0
  223. package/src/constants/webgl-constants.ts +1051 -0
  224. package/src/constants/webgl-types.d.ts.map +1 -0
  225. package/src/constants/webgl-types.js.map +1 -0
  226. package/src/constants/webgl-types.ts +813 -0
  227. package/src/context/debug/spector.ts +4 -4
  228. package/src/context/debug/webgl-developer-tools.ts +20 -9
  229. package/src/context/helpers/create-browser-context.ts +54 -43
  230. package/src/context/helpers/webgl-context-data.ts +17 -11
  231. package/src/context/helpers/webgl-extensions.ts +1 -1
  232. package/src/context/parameters/unified-parameter-api.ts +3 -3
  233. package/src/context/parameters/webgl-parameter-tables.ts +1 -1
  234. package/src/context/polyfills/polyfill-webgl1-extensions.ts +1 -1
  235. package/src/context/state-tracker/webgl-state-tracker.ts +2 -2
  236. package/src/index.ts +27 -0
  237. package/src/utils/fill-array.ts +1 -1
  238. package/src/webgl-constants.d.ts.map +1 -0
  239. package/src/webgl-constants.js.map +1 -0
  240. package/src/webgl-constants.ts +5 -0
  241. package/src/webgl-types.d.ts.map +1 -0
  242. package/src/webgl-types.js.map +1 -0
  243. package/src/webgl-types.ts +29 -0
  244. package/dist/types.d.ts +0 -11
  245. package/dist/types.d.ts.map +0 -1
  246. package/dist/types.js.map +0 -1
  247. package/src/types.ts +0 -14
package/dist/dist.dev.js CHANGED
@@ -48,10 +48,10 @@ var __exports__ = (() => {
48
48
  }
49
49
  });
50
50
 
51
- // ../constants/src/webgl-constants.ts
51
+ // src/constants/webgl-constants.ts
52
52
  var GLEnum;
53
53
  var init_webgl_constants = __esm({
54
- "../constants/src/webgl-constants.ts"() {
54
+ "src/constants/webgl-constants.ts"() {
55
55
  "use strict";
56
56
  GLEnum = /* @__PURE__ */ ((GLEnum2) => {
57
57
  GLEnum2[GLEnum2["DEPTH_BUFFER_BIT"] = 256] = "DEPTH_BUFFER_BIT";
@@ -705,9 +705,9 @@ var __exports__ = (() => {
705
705
  }
706
706
  });
707
707
 
708
- // ../constants/src/index.ts
709
- var init_src = __esm({
710
- "../constants/src/index.ts"() {
708
+ // src/constants/index.ts
709
+ var init_constants = __esm({
710
+ "src/constants/index.ts"() {
711
711
  "use strict";
712
712
  init_webgl_constants();
713
713
  }
@@ -847,6 +847,24 @@ var __exports__ = (() => {
847
847
  }
848
848
  });
849
849
 
850
+ // src/context/helpers/webgl-context-data.ts
851
+ function getWebGLContextData(gl) {
852
+ const contextData = gl.luma || {
853
+ _polyfilled: false,
854
+ extensions: {},
855
+ softwareRenderer: false
856
+ };
857
+ contextData._polyfilled ??= false;
858
+ contextData.extensions ||= {};
859
+ gl.luma = contextData;
860
+ return contextData;
861
+ }
862
+ var init_webgl_context_data = __esm({
863
+ "src/context/helpers/webgl-context-data.ts"() {
864
+ "use strict";
865
+ }
866
+ });
867
+
850
868
  // src/context/debug/spector.ts
851
869
  async function loadSpectorJS(props) {
852
870
  if (!globalThis.SPECTOR) {
@@ -888,9 +906,10 @@ var __exports__ = (() => {
888
906
  }
889
907
  if (props.gl) {
890
908
  const gl = props.gl;
891
- const device = gl.device;
909
+ const contextData = getWebGLContextData(gl);
910
+ const device = contextData.device;
892
911
  spector?.startCapture(props.gl, 500);
893
- gl.device = device;
912
+ contextData.device = device;
894
913
  new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
895
914
  import_core.log.info("Spector capture stopped after 2 seconds")();
896
915
  spector?.stopCapture();
@@ -904,6 +923,7 @@ var __exports__ = (() => {
904
923
  "use strict";
905
924
  import_core = __toESM(require_core(), 1);
906
925
  init_load_script();
926
+ init_webgl_context_data();
907
927
  LOG_LEVEL = 1;
908
928
  spector = null;
909
929
  initialized = false;
@@ -1000,7 +1020,7 @@ var __exports__ = (() => {
1000
1020
  });
1001
1021
 
1002
1022
  // src/context/debug/webgl-developer-tools.ts
1003
- function getWebGLContextData(gl) {
1023
+ function getWebGLContextData2(gl) {
1004
1024
  gl.luma = gl.luma || {};
1005
1025
  return gl.luma;
1006
1026
  }
@@ -1015,7 +1035,7 @@ var __exports__ = (() => {
1015
1035
  return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
1016
1036
  }
1017
1037
  function getRealContext(gl) {
1018
- const data = getWebGLContextData(gl);
1038
+ const data = getWebGLContextData2(gl);
1019
1039
  return data.realContext ? data.realContext : gl;
1020
1040
  }
1021
1041
  function getDebugContext(gl, props) {
@@ -1023,7 +1043,7 @@ var __exports__ = (() => {
1023
1043
  import_core2.log.warn("webgl-debug not loaded")();
1024
1044
  return gl;
1025
1045
  }
1026
- const data = getWebGLContextData(gl);
1046
+ const data = getWebGLContextData2(gl);
1027
1047
  if (data.debugContext) {
1028
1048
  return data.debugContext;
1029
1049
  }
@@ -1045,6 +1065,7 @@ var __exports__ = (() => {
1045
1065
  const debugContext = Object.create(WebGLDebugContext);
1046
1066
  data.realContext = gl;
1047
1067
  data.debugContext = debugContext;
1068
+ debugContext.luma = data;
1048
1069
  debugContext.debug = true;
1049
1070
  return debugContext;
1050
1071
  }
@@ -1059,16 +1080,24 @@ var __exports__ = (() => {
1059
1080
  const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
1060
1081
  const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
1061
1082
  const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
1062
- import_core2.log.error(message2)();
1083
+ import_core2.log.error(
1084
+ "%cWebGL",
1085
+ "color: white; background: red; padding: 2px 6px; border-radius: 3px;",
1086
+ message2
1087
+ )();
1063
1088
  debugger;
1089
+ throw new Error(message2);
1064
1090
  }
1065
1091
  function onValidateGLFunc(props, functionName, functionArgs) {
1066
1092
  let functionString = "";
1067
- if (import_core2.log.level >= 1) {
1093
+ if (props.traceWebGL && import_core2.log.level >= 1) {
1068
1094
  functionString = getFunctionString(functionName, functionArgs);
1069
- if (props.traceWebGL) {
1070
- import_core2.log.log(1, functionString)();
1071
- }
1095
+ import_core2.log.info(
1096
+ 1,
1097
+ "%cWebGL",
1098
+ "color: white; background: blue; padding: 2px 6px; border-radius: 3px;",
1099
+ functionString
1100
+ )();
1072
1101
  }
1073
1102
  for (const arg of functionArgs) {
1074
1103
  if (arg === void 0) {
@@ -1082,7 +1111,7 @@ var __exports__ = (() => {
1082
1111
  "src/context/debug/webgl-developer-tools.ts"() {
1083
1112
  "use strict";
1084
1113
  import_core2 = __toESM(require_core(), 1);
1085
- init_src();
1114
+ init_constants();
1086
1115
  init_dist();
1087
1116
  init_load_script();
1088
1117
  WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
@@ -1621,7 +1650,7 @@ var __exports__ = (() => {
1621
1650
  }
1622
1651
  }
1623
1652
  }
1624
- const cache = gl.state && gl.state.cache;
1653
+ const cache = gl.lumaState?.cache;
1625
1654
  if (cache) {
1626
1655
  for (const key in compositeSetters) {
1627
1656
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -1744,7 +1773,7 @@ var __exports__ = (() => {
1744
1773
  init_webgl_parameter_tables();
1745
1774
  WebGLStateTracker = class {
1746
1775
  static get(gl) {
1747
- return gl.state;
1776
+ return gl.lumaState;
1748
1777
  }
1749
1778
  gl;
1750
1779
  program = null;
@@ -1782,7 +1811,7 @@ var __exports__ = (() => {
1782
1811
  throw new Error("WebGLStateTracker");
1783
1812
  }
1784
1813
  this.initialized = true;
1785
- this.gl.state = this;
1814
+ this.gl.lumaState = this;
1786
1815
  installProgramSpy(gl);
1787
1816
  for (const key in GL_HOOKED_SETTERS) {
1788
1817
  const setter = GL_HOOKED_SETTERS[key];
@@ -1822,46 +1851,61 @@ var __exports__ = (() => {
1822
1851
  // src/context/helpers/create-browser-context.ts
1823
1852
  function createBrowserContext(canvas, props, webglContextAttributes) {
1824
1853
  let errorMessage = "";
1854
+ const onCreateError = (event) => {
1855
+ const statusMessage = event.statusMessage;
1856
+ if (statusMessage) {
1857
+ errorMessage ||= statusMessage;
1858
+ }
1859
+ };
1860
+ canvas.addEventListener("webglcontextcreationerror", onCreateError, false);
1861
+ const allowSoftwareRenderer = webglContextAttributes.failIfMajorPerformanceCaveat !== true;
1825
1862
  const webglProps = {
1826
1863
  preserveDrawingBuffer: true,
1827
- // failIfMajorPerformanceCaveat: true,
1828
- ...webglContextAttributes
1864
+ ...webglContextAttributes,
1865
+ // Always start by requesting a high-performance context.
1866
+ failIfMajorPerformanceCaveat: true
1829
1867
  };
1830
1868
  let gl = null;
1831
- gl ||= canvas.getContext("webgl2", webglProps);
1832
- if (webglProps.failIfMajorPerformanceCaveat) {
1833
- errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1834
- }
1835
- if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
1836
- webglProps.failIfMajorPerformanceCaveat = false;
1837
- gl = canvas.getContext("webgl2", webglProps);
1838
- gl.luma ||= {};
1839
- gl.luma.softwareRenderer = true;
1840
- }
1841
- if (!gl) {
1842
- gl = canvas.getContext("webgl", {});
1843
- if (gl) {
1844
- gl = null;
1845
- errorMessage ||= "Your browser only supports WebGL1";
1869
+ try {
1870
+ gl ||= canvas.getContext("webgl2", webglProps);
1871
+ if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1872
+ errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1846
1873
  }
1874
+ let softwareRenderer = false;
1875
+ if (!gl && allowSoftwareRenderer) {
1876
+ webglProps.failIfMajorPerformanceCaveat = false;
1877
+ gl = canvas.getContext("webgl2", webglProps);
1878
+ softwareRenderer = true;
1879
+ }
1880
+ if (!gl) {
1881
+ gl = canvas.getContext("webgl", {});
1882
+ if (gl) {
1883
+ gl = null;
1884
+ errorMessage ||= "Your browser only supports WebGL1";
1885
+ }
1886
+ }
1887
+ if (!gl) {
1888
+ errorMessage ||= "Your browser does not support WebGL";
1889
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1890
+ }
1891
+ const luma = getWebGLContextData(gl);
1892
+ luma.softwareRenderer = softwareRenderer;
1893
+ const { onContextLost, onContextRestored } = props;
1894
+ canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1895
+ canvas.addEventListener(
1896
+ "webglcontextrestored",
1897
+ (event) => onContextRestored(event),
1898
+ false
1899
+ );
1900
+ return gl;
1901
+ } finally {
1902
+ canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
1847
1903
  }
1848
- if (!gl) {
1849
- errorMessage ||= "Your browser does not support WebGL";
1850
- throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1851
- }
1852
- const { onContextLost, onContextRestored } = props;
1853
- canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1854
- canvas.addEventListener(
1855
- "webglcontextrestored",
1856
- (event) => onContextRestored(event),
1857
- false
1858
- );
1859
- gl.luma ||= {};
1860
- return gl;
1861
1904
  }
1862
1905
  var init_create_browser_context = __esm({
1863
1906
  "src/context/helpers/create-browser-context.ts"() {
1864
1907
  "use strict";
1908
+ init_webgl_context_data();
1865
1909
  }
1866
1910
  });
1867
1911
 
@@ -1939,6 +1983,8 @@ var __exports__ = (() => {
1939
1983
  }
1940
1984
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1941
1985
  switch (gpuVendor) {
1986
+ case "apple":
1987
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1942
1988
  case "intel":
1943
1989
  return "integrated";
1944
1990
  case "software":
@@ -1949,6 +1995,9 @@ var __exports__ = (() => {
1949
1995
  return "discrete";
1950
1996
  }
1951
1997
  }
1998
+ function isAppleSiliconGPU(vendor, renderer) {
1999
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
2000
+ }
1952
2001
  var init_webgl_device_info = __esm({
1953
2002
  "src/adapter/device-helpers/webgl-device-info.ts"() {
1954
2003
  "use strict";
@@ -1997,8 +2046,27 @@ var __exports__ = (() => {
1997
2046
  return feature in TEXTURE_FEATURES;
1998
2047
  }
1999
2048
  function checkTextureFeature(gl, feature, extensions) {
2000
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
2001
- return textureExtensions.every((extension) => getWebGLExtension(gl, extension, extensions));
2049
+ return hasTextureFeature(gl, feature, extensions, /* @__PURE__ */ new Set());
2050
+ }
2051
+ function hasTextureFeature(gl, feature, extensions, seenFeatures) {
2052
+ const definition = TEXTURE_FEATURES[feature];
2053
+ if (!definition) {
2054
+ return false;
2055
+ }
2056
+ if (seenFeatures.has(feature)) {
2057
+ return false;
2058
+ }
2059
+ seenFeatures.add(feature);
2060
+ const hasDependentFeatures = (definition.features || []).every(
2061
+ (dependentFeature) => hasTextureFeature(gl, dependentFeature, extensions, seenFeatures)
2062
+ );
2063
+ seenFeatures.delete(feature);
2064
+ if (!hasDependentFeatures) {
2065
+ return false;
2066
+ }
2067
+ return (definition.extensions || []).every(
2068
+ (extension) => Boolean(getWebGLExtension(gl, extension, extensions))
2069
+ );
2002
2070
  }
2003
2071
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
2004
2072
  let supported = formatSupport.create;
@@ -2009,12 +2077,17 @@ var __exports__ = (() => {
2009
2077
  if (webglFormatInfo?.x) {
2010
2078
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
2011
2079
  }
2080
+ if (formatSupport.format === "stencil8") {
2081
+ supported = false;
2082
+ }
2083
+ const renderFeatureSupported = webglFormatInfo?.r === false ? false : webglFormatInfo?.r === void 0 || checkTextureFeature(gl, webglFormatInfo.r, extensions);
2084
+ const renderable = supported && formatSupport.render && renderFeatureSupported && isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
2012
2085
  return {
2013
2086
  format: formatSupport.format,
2014
2087
  // @ts-ignore
2015
2088
  create: supported && formatSupport.create,
2016
2089
  // @ts-ignore
2017
- render: supported && formatSupport.render,
2090
+ render: renderable,
2018
2091
  // @ts-ignore
2019
2092
  filter: supported && formatSupport.filter,
2020
2093
  // @ts-ignore
@@ -2023,6 +2096,45 @@ var __exports__ = (() => {
2023
2096
  store: supported && formatSupport.store
2024
2097
  };
2025
2098
  }
2099
+ function isColorRenderableTextureFormat(gl, format, extensions) {
2100
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
2101
+ const internalFormat = webglFormatInfo?.gl;
2102
+ if (internalFormat === void 0) {
2103
+ return false;
2104
+ }
2105
+ if (webglFormatInfo?.x && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
2106
+ return false;
2107
+ }
2108
+ const previousTexture = gl.getParameter(32873 /* TEXTURE_BINDING_2D */);
2109
+ const previousFramebuffer = gl.getParameter(36006 /* FRAMEBUFFER_BINDING */);
2110
+ const texture = gl.createTexture();
2111
+ const framebuffer = gl.createFramebuffer();
2112
+ if (!texture || !framebuffer) {
2113
+ return false;
2114
+ }
2115
+ const noError = Number(0 /* NO_ERROR */);
2116
+ let error = Number(gl.getError());
2117
+ while (error !== noError) {
2118
+ error = gl.getError();
2119
+ }
2120
+ let renderable = false;
2121
+ try {
2122
+ gl.bindTexture(3553 /* TEXTURE_2D */, texture);
2123
+ gl.texStorage2D(3553 /* TEXTURE_2D */, 1, internalFormat, 1, 1);
2124
+ if (Number(gl.getError()) !== noError) {
2125
+ return false;
2126
+ }
2127
+ gl.bindFramebuffer(36160 /* FRAMEBUFFER */, framebuffer);
2128
+ gl.framebufferTexture2D(36160 /* FRAMEBUFFER */, 36064 /* COLOR_ATTACHMENT0 */, 3553 /* TEXTURE_2D */, texture, 0);
2129
+ renderable = Number(gl.checkFramebufferStatus(36160 /* FRAMEBUFFER */)) === Number(36053 /* FRAMEBUFFER_COMPLETE */) && Number(gl.getError()) === noError;
2130
+ } finally {
2131
+ gl.bindFramebuffer(36160 /* FRAMEBUFFER */, previousFramebuffer);
2132
+ gl.deleteFramebuffer(framebuffer);
2133
+ gl.bindTexture(3553 /* TEXTURE_2D */, previousTexture);
2134
+ gl.deleteTexture(texture);
2135
+ }
2136
+ return renderable;
2137
+ }
2026
2138
  function getTextureFormatWebGL(format) {
2027
2139
  const formatData = WEBGL_TEXTURE_FORMATS[format];
2028
2140
  const webglFormat = convertTextureFormatToGL(format);
@@ -2078,7 +2190,7 @@ var __exports__ = (() => {
2078
2190
  }
2079
2191
  return webglFormat;
2080
2192
  }
2081
- var import_core3, X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC, X_ETC2, X_ASTC, X_ETC1, X_PVRTC, X_ATC, EXT_texture_norm16, EXT_render_snorm, EXT_color_buffer_float, TEXTURE_FEATURES, WEBGL_TEXTURE_FORMATS;
2193
+ var import_core3, X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC, X_ETC2, X_ASTC, X_ETC1, X_PVRTC, X_ATC, EXT_texture_norm16, EXT_render_snorm, EXT_color_buffer_float, SNORM8_COLOR_RENDERABLE, NORM16_COLOR_RENDERABLE, SNORM16_COLOR_RENDERABLE, FLOAT16_COLOR_RENDERABLE, FLOAT32_COLOR_RENDERABLE, RGB9E5UFLOAT_COLOR_RENDERABLE, TEXTURE_FEATURES, WEBGL_TEXTURE_FORMATS;
2082
2194
  var init_webgl_texture_table = __esm({
2083
2195
  "src/adapter/converters/webgl-texture-table.ts"() {
2084
2196
  "use strict";
@@ -2097,44 +2209,51 @@ var __exports__ = (() => {
2097
2209
  EXT_texture_norm16 = "EXT_texture_norm16";
2098
2210
  EXT_render_snorm = "EXT_render_snorm";
2099
2211
  EXT_color_buffer_float = "EXT_color_buffer_float";
2212
+ SNORM8_COLOR_RENDERABLE = "snorm8-renderable-webgl";
2213
+ NORM16_COLOR_RENDERABLE = "norm16-renderable-webgl";
2214
+ SNORM16_COLOR_RENDERABLE = "snorm16-renderable-webgl";
2215
+ FLOAT16_COLOR_RENDERABLE = "float16-renderable-webgl";
2216
+ FLOAT32_COLOR_RENDERABLE = "float32-renderable-webgl";
2217
+ RGB9E5UFLOAT_COLOR_RENDERABLE = "rgb9e5ufloat-renderable-webgl";
2100
2218
  TEXTURE_FEATURES = {
2101
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
2102
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
2103
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
2104
- "snorm8-renderable-webgl": [EXT_render_snorm],
2105
- "norm16-renderable-webgl": [EXT_texture_norm16],
2106
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
2107
- "float32-filterable": ["OES_texture_float_linear"],
2108
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
2109
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
2110
- "texture-blend-float-webgl": ["EXT_float_blend"],
2111
- "texture-compression-bc": [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
2219
+ "float32-renderable-webgl": { extensions: [EXT_color_buffer_float] },
2220
+ "float16-renderable-webgl": { extensions: ["EXT_color_buffer_half_float"] },
2221
+ "rgb9e5ufloat-renderable-webgl": { extensions: ["WEBGL_render_shared_exponent"] },
2222
+ "snorm8-renderable-webgl": { extensions: [EXT_render_snorm] },
2223
+ "norm16-webgl": { extensions: [EXT_texture_norm16] },
2224
+ "norm16-renderable-webgl": { features: ["norm16-webgl"] },
2225
+ "snorm16-renderable-webgl": { features: ["norm16-webgl"], extensions: [EXT_render_snorm] },
2226
+ "float32-filterable": { extensions: ["OES_texture_float_linear"] },
2227
+ "float16-filterable-webgl": { extensions: ["OES_texture_half_float_linear"] },
2228
+ "texture-filterable-anisotropic-webgl": { extensions: ["EXT_texture_filter_anisotropic"] },
2229
+ "texture-blend-float-webgl": { extensions: ["EXT_float_blend"] },
2230
+ "texture-compression-bc": { extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC] },
2112
2231
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
2113
2232
  // 'texture-compression-bc3-webgl': [X_S3TC],
2114
- "texture-compression-bc5-webgl": [X_RGTC],
2115
- "texture-compression-bc7-webgl": [X_BPTC],
2116
- "texture-compression-etc2": [X_ETC2],
2117
- "texture-compression-astc": [X_ASTC],
2118
- "texture-compression-etc1-webgl": [X_ETC1],
2119
- "texture-compression-pvrtc-webgl": [X_PVRTC],
2120
- "texture-compression-atc-webgl": [X_ATC]
2233
+ "texture-compression-bc5-webgl": { extensions: [X_RGTC] },
2234
+ "texture-compression-bc7-webgl": { extensions: [X_BPTC] },
2235
+ "texture-compression-etc2": { extensions: [X_ETC2] },
2236
+ "texture-compression-astc": { extensions: [X_ASTC] },
2237
+ "texture-compression-etc1-webgl": { extensions: [X_ETC1] },
2238
+ "texture-compression-pvrtc-webgl": { extensions: [X_PVRTC] },
2239
+ "texture-compression-atc-webgl": { extensions: [X_ATC] }
2121
2240
  };
2122
2241
  WEBGL_TEXTURE_FORMATS = {
2123
2242
  // 8-bit formats
2124
2243
  "r8unorm": { gl: 33321 /* R8 */, rb: true },
2125
- "r8snorm": { gl: 36756 /* R8_SNORM */ },
2244
+ "r8snorm": { gl: 36756 /* R8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2126
2245
  "r8uint": { gl: 33330 /* R8UI */, rb: true },
2127
2246
  "r8sint": { gl: 33329 /* R8I */, rb: true },
2128
2247
  // 16-bit formats
2129
2248
  "rg8unorm": { gl: 33323 /* RG8 */, rb: true },
2130
- "rg8snorm": { gl: 36757 /* RG8_SNORM */ },
2249
+ "rg8snorm": { gl: 36757 /* RG8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2131
2250
  "rg8uint": { gl: 33336 /* RG8UI */, rb: true },
2132
2251
  "rg8sint": { gl: 33335 /* RG8I */, rb: true },
2133
2252
  "r16uint": { gl: 33332 /* R16UI */, rb: true },
2134
2253
  "r16sint": { gl: 33331 /* R16I */, rb: true },
2135
- "r16float": { gl: 33325 /* R16F */, rb: true },
2136
- "r16unorm": { gl: 33322 /* R16_EXT */, rb: true },
2137
- "r16snorm": { gl: 36760 /* R16_SNORM_EXT */ },
2254
+ "r16float": { gl: 33325 /* R16F */, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2255
+ "r16unorm": { gl: 33322 /* R16_EXT */, rb: true, r: NORM16_COLOR_RENDERABLE },
2256
+ "r16snorm": { gl: 36760 /* R16_SNORM_EXT */, r: SNORM16_COLOR_RENDERABLE },
2138
2257
  // Packed 16-bit formats
2139
2258
  "rgba4unorm-webgl": { gl: 32854 /* RGBA4 */, rb: true },
2140
2259
  "rgb565unorm-webgl": { gl: 36194 /* RGB565 */, rb: true },
@@ -2145,7 +2264,7 @@ var __exports__ = (() => {
2145
2264
  // 32-bit formats
2146
2265
  "rgba8unorm": { gl: 32856 /* RGBA8 */ },
2147
2266
  "rgba8unorm-srgb": { gl: 35907 /* SRGB8_ALPHA8 */ },
2148
- "rgba8snorm": { gl: 36759 /* RGBA8_SNORM */ },
2267
+ "rgba8snorm": { gl: 36759 /* RGBA8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2149
2268
  "rgba8uint": { gl: 36220 /* RGBA8UI */ },
2150
2269
  "rgba8sint": { gl: 36238 /* RGBA8I */ },
2151
2270
  // reverse colors, webgpu only
@@ -2153,38 +2272,38 @@ var __exports__ = (() => {
2153
2272
  "bgra8unorm-srgb": {},
2154
2273
  "rg16uint": { gl: 33338 /* RG16UI */ },
2155
2274
  "rg16sint": { gl: 33337 /* RG16I */ },
2156
- "rg16float": { gl: 33327 /* RG16F */, rb: true },
2157
- "rg16unorm": { gl: 33324 /* RG16_EXT */ },
2158
- "rg16snorm": { gl: 36761 /* RG16_SNORM_EXT */ },
2275
+ "rg16float": { gl: 33327 /* RG16F */, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2276
+ "rg16unorm": { gl: 33324 /* RG16_EXT */, r: NORM16_COLOR_RENDERABLE },
2277
+ "rg16snorm": { gl: 36761 /* RG16_SNORM_EXT */, r: SNORM16_COLOR_RENDERABLE },
2159
2278
  "r32uint": { gl: 33334 /* R32UI */, rb: true },
2160
2279
  "r32sint": { gl: 33333 /* R32I */, rb: true },
2161
- "r32float": { gl: 33326 /* R32F */ },
2280
+ "r32float": { gl: 33326 /* R32F */, r: FLOAT32_COLOR_RENDERABLE },
2162
2281
  // Packed 32-bit formats
2163
- "rgb9e5ufloat": { gl: 35901 /* RGB9_E5 */ },
2282
+ "rgb9e5ufloat": { gl: 35901 /* RGB9_E5 */, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
2164
2283
  // , filter: true},
2165
2284
  "rg11b10ufloat": { gl: 35898 /* R11F_G11F_B10F */, rb: true },
2166
2285
  "rgb10a2unorm": { gl: 32857 /* RGB10_A2 */, rb: true },
2167
2286
  "rgb10a2uint": { gl: 36975 /* RGB10_A2UI */, rb: true },
2168
2287
  // 48-bit formats
2169
- "rgb16unorm-webgl": { gl: 32852 /* RGB16_EXT */ },
2288
+ "rgb16unorm-webgl": { gl: 32852 /* RGB16_EXT */, r: false },
2170
2289
  // rgb not renderable
2171
- "rgb16snorm-webgl": { gl: 36762 /* RGB16_SNORM_EXT */ },
2290
+ "rgb16snorm-webgl": { gl: 36762 /* RGB16_SNORM_EXT */, r: false },
2172
2291
  // rgb not renderable
2173
2292
  // 64-bit formats
2174
2293
  "rg32uint": { gl: 33340 /* RG32UI */, rb: true },
2175
2294
  "rg32sint": { gl: 33339 /* RG32I */, rb: true },
2176
- "rg32float": { gl: 33328 /* RG32F */, rb: true },
2295
+ "rg32float": { gl: 33328 /* RG32F */, rb: true, r: FLOAT32_COLOR_RENDERABLE },
2177
2296
  "rgba16uint": { gl: 36214 /* RGBA16UI */, rb: true },
2178
2297
  "rgba16sint": { gl: 36232 /* RGBA16I */, rb: true },
2179
- "rgba16float": { gl: 34842 /* RGBA16F */ },
2180
- "rgba16unorm": { gl: 32859 /* RGBA16_EXT */, rb: true },
2181
- "rgba16snorm": { gl: 36763 /* RGBA16_SNORM_EXT */ },
2298
+ "rgba16float": { gl: 34842 /* RGBA16F */, r: FLOAT16_COLOR_RENDERABLE },
2299
+ "rgba16unorm": { gl: 32859 /* RGBA16_EXT */, rb: true, r: NORM16_COLOR_RENDERABLE },
2300
+ "rgba16snorm": { gl: 36763 /* RGBA16_SNORM_EXT */, r: SNORM16_COLOR_RENDERABLE },
2182
2301
  // 96-bit formats (deprecated!)
2183
- "rgb32float-webgl": { gl: 34837 /* RGB32F */, x: EXT_color_buffer_float, dataFormat: 6407 /* RGB */, types: [5126 /* FLOAT */] },
2302
+ "rgb32float-webgl": { gl: 34837 /* RGB32F */, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: 6407 /* RGB */, types: [5126 /* FLOAT */] },
2184
2303
  // 128-bit formats
2185
2304
  "rgba32uint": { gl: 36208 /* RGBA32UI */, rb: true },
2186
2305
  "rgba32sint": { gl: 36226 /* RGBA32I */, rb: true },
2187
- "rgba32float": { gl: 34836 /* RGBA32F */, rb: true },
2306
+ "rgba32float": { gl: 34836 /* RGBA32F */, rb: true, r: FLOAT32_COLOR_RENDERABLE },
2188
2307
  // Depth and stencil formats
2189
2308
  "stencil8": { gl: 36168 /* STENCIL_INDEX8 */, rb: true },
2190
2309
  // 8 stencil bits
@@ -2242,8 +2361,8 @@ var __exports__ = (() => {
2242
2361
  "astc-8x6-unorm-srgb": { gl: 37846 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR */ },
2243
2362
  "astc-8x8-unorm": { gl: 37815 /* COMPRESSED_RGBA_ASTC_8x8_KHR */ },
2244
2363
  "astc-8x8-unorm-srgb": { gl: 37847 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR */ },
2245
- "astc-10x5-unorm": { gl: 37819 /* COMPRESSED_RGBA_ASTC_10x10_KHR */ },
2246
- "astc-10x5-unorm-srgb": { gl: 37851 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR */ },
2364
+ "astc-10x5-unorm": { gl: 37816 /* COMPRESSED_RGBA_ASTC_10x5_KHR */ },
2365
+ "astc-10x5-unorm-srgb": { gl: 37848 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR */ },
2247
2366
  "astc-10x6-unorm": { gl: 37817 /* COMPRESSED_RGBA_ASTC_10x6_KHR */ },
2248
2367
  "astc-10x6-unorm-srgb": { gl: 37849 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR */ },
2249
2368
  "astc-10x8-unorm": { gl: 37818 /* COMPRESSED_RGBA_ASTC_10x8_KHR */ },
@@ -2257,7 +2376,7 @@ var __exports__ = (() => {
2257
2376
  // WEBGL_compressed_texture_pvrtc
2258
2377
  "pvrtc-rgb4unorm-webgl": { gl: 35840 /* COMPRESSED_RGB_PVRTC_4BPPV1_IMG */ },
2259
2378
  "pvrtc-rgba4unorm-webgl": { gl: 35842 /* COMPRESSED_RGBA_PVRTC_4BPPV1_IMG */ },
2260
- "pvrtc-rbg2unorm-webgl": { gl: 35841 /* COMPRESSED_RGB_PVRTC_2BPPV1_IMG */ },
2379
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 /* COMPRESSED_RGB_PVRTC_2BPPV1_IMG */ },
2261
2380
  "pvrtc-rgba2unorm-webgl": { gl: 35843 /* COMPRESSED_RGBA_PVRTC_2BPPV1_IMG */ },
2262
2381
  // WEBGL_compressed_texture_etc1
2263
2382
  "etc1-rbg-unorm-webgl": { gl: 36196 /* COMPRESSED_RGB_ETC1_WEBGL */ },
@@ -2281,12 +2400,11 @@ var __exports__ = (() => {
2281
2400
  // optional WebGPU features
2282
2401
  "depth-clip-control": "EXT_depth_clamp",
2283
2402
  // TODO these seem subtly different
2284
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2403
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2285
2404
  // "indirect-first-instance"
2286
2405
  // Textures are handled by getTextureFeatures()
2287
2406
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2288
2407
  // optional WebGL features
2289
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2290
2408
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2291
2409
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2292
2410
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2586,6 +2704,15 @@ var __exports__ = (() => {
2586
2704
  }
2587
2705
  gl.bindTexture(texture.glTarget, null);
2588
2706
  }
2707
+ /** Default framebuffer resize is managed by canvas size and should be a no-op. */
2708
+ resizeAttachments(width, height) {
2709
+ if (this.handle === null) {
2710
+ this.width = width;
2711
+ this.height = height;
2712
+ return;
2713
+ }
2714
+ super.resizeAttachments(width, height);
2715
+ }
2589
2716
  };
2590
2717
  }
2591
2718
  });
@@ -2608,14 +2735,83 @@ var __exports__ = (() => {
2608
2735
  super(props);
2609
2736
  this.device = device;
2610
2737
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
2611
- this._updateDevice();
2738
+ this._configureDevice();
2739
+ }
2740
+ // IMPLEMENTATION OF ABSTRACT METHODS
2741
+ _configureDevice() {
2742
+ const shouldResize = this.drawingBufferWidth !== this._framebuffer?.width || this.drawingBufferHeight !== this._framebuffer?.height;
2743
+ if (shouldResize) {
2744
+ this._framebuffer?.resize([this.drawingBufferWidth, this.drawingBufferHeight]);
2745
+ }
2612
2746
  }
2613
- getCurrentFramebuffer() {
2614
- this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
2747
+ _getCurrentFramebuffer() {
2748
+ this._framebuffer ||= new WEBGLFramebuffer(this.device, {
2749
+ id: "canvas-context-framebuffer",
2750
+ handle: null,
2751
+ // Setting handle to null returns a reference to the default WebGL framebuffer
2752
+ width: this.drawingBufferWidth,
2753
+ height: this.drawingBufferHeight
2754
+ });
2615
2755
  return this._framebuffer;
2616
2756
  }
2617
- // IMPLEMENTATION OF ABSTRACT METHODS
2618
- _updateDevice() {
2757
+ };
2758
+ }
2759
+ });
2760
+
2761
+ // src/adapter/webgl-presentation-context.ts
2762
+ var import_core8, WebGLPresentationContext;
2763
+ var init_webgl_presentation_context = __esm({
2764
+ "src/adapter/webgl-presentation-context.ts"() {
2765
+ "use strict";
2766
+ import_core8 = __toESM(require_core(), 1);
2767
+ WebGLPresentationContext = class extends import_core8.PresentationContext {
2768
+ device;
2769
+ handle = null;
2770
+ context2d;
2771
+ get [Symbol.toStringTag]() {
2772
+ return "WebGLPresentationContext";
2773
+ }
2774
+ constructor(device, props = {}) {
2775
+ super(props);
2776
+ this.device = device;
2777
+ const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
2778
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2779
+ if (!defaultCanvasContext.offscreenCanvas) {
2780
+ throw new Error(
2781
+ `${contextLabel}: WebGL PresentationContext requires the default CanvasContext canvas to be an OffscreenCanvas`
2782
+ );
2783
+ }
2784
+ const context2d = this.canvas.getContext("2d");
2785
+ if (!context2d) {
2786
+ throw new Error(`${contextLabel}: Failed to create 2d presentation context`);
2787
+ }
2788
+ this.context2d = context2d;
2789
+ this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
2790
+ this._configureDevice();
2791
+ this._startObservers();
2792
+ }
2793
+ present() {
2794
+ this._resizeDrawingBufferIfNeeded();
2795
+ this.device.submit();
2796
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2797
+ const [sourceWidth, sourceHeight] = defaultCanvasContext.getDrawingBufferSize();
2798
+ if (this.drawingBufferWidth === 0 || this.drawingBufferHeight === 0 || sourceWidth === 0 || sourceHeight === 0 || defaultCanvasContext.canvas.width === 0 || defaultCanvasContext.canvas.height === 0) {
2799
+ return;
2800
+ }
2801
+ if (sourceWidth !== this.drawingBufferWidth || sourceHeight !== this.drawingBufferHeight || defaultCanvasContext.canvas.width !== this.drawingBufferWidth || defaultCanvasContext.canvas.height !== this.drawingBufferHeight) {
2802
+ throw new Error(
2803
+ `${this[Symbol.toStringTag]}(${this.id}): Default canvas context size ${sourceWidth}x${sourceHeight} does not match presentation size ${this.drawingBufferWidth}x${this.drawingBufferHeight}`
2804
+ );
2805
+ }
2806
+ this.context2d.clearRect(0, 0, this.drawingBufferWidth, this.drawingBufferHeight);
2807
+ this.context2d.drawImage(defaultCanvasContext.canvas, 0, 0);
2808
+ }
2809
+ _configureDevice() {
2810
+ }
2811
+ _getCurrentFramebuffer(options) {
2812
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2813
+ defaultCanvasContext.setDrawingBufferSize(this.drawingBufferWidth, this.drawingBufferHeight);
2814
+ return defaultCanvasContext.getCurrentFramebuffer(options);
2619
2815
  }
2620
2816
  };
2621
2817
  }
@@ -2637,35 +2833,35 @@ var __exports__ = (() => {
2637
2833
 
2638
2834
  // src/adapter/resources/webgl-buffer.ts
2639
2835
  function getWebGLTarget(usage) {
2640
- if (usage & import_core8.Buffer.INDEX) {
2836
+ if (usage & import_core9.Buffer.INDEX) {
2641
2837
  return 34963 /* ELEMENT_ARRAY_BUFFER */;
2642
2838
  }
2643
- if (usage & import_core8.Buffer.VERTEX) {
2839
+ if (usage & import_core9.Buffer.VERTEX) {
2644
2840
  return 34962 /* ARRAY_BUFFER */;
2645
2841
  }
2646
- if (usage & import_core8.Buffer.UNIFORM) {
2842
+ if (usage & import_core9.Buffer.UNIFORM) {
2647
2843
  return 35345 /* UNIFORM_BUFFER */;
2648
2844
  }
2649
2845
  return 34962 /* ARRAY_BUFFER */;
2650
2846
  }
2651
2847
  function getWebGLUsage(usage) {
2652
- if (usage & import_core8.Buffer.INDEX) {
2848
+ if (usage & import_core9.Buffer.INDEX) {
2653
2849
  return 35044 /* STATIC_DRAW */;
2654
2850
  }
2655
- if (usage & import_core8.Buffer.VERTEX) {
2851
+ if (usage & import_core9.Buffer.VERTEX) {
2656
2852
  return 35044 /* STATIC_DRAW */;
2657
2853
  }
2658
- if (usage & import_core8.Buffer.UNIFORM) {
2854
+ if (usage & import_core9.Buffer.UNIFORM) {
2659
2855
  return 35048 /* DYNAMIC_DRAW */;
2660
2856
  }
2661
2857
  return 35044 /* STATIC_DRAW */;
2662
2858
  }
2663
- var import_core8, WEBGLBuffer;
2859
+ var import_core9, WEBGLBuffer;
2664
2860
  var init_webgl_buffer = __esm({
2665
2861
  "src/adapter/resources/webgl-buffer.ts"() {
2666
2862
  "use strict";
2667
- import_core8 = __toESM(require_core(), 1);
2668
- WEBGLBuffer = class extends import_core8.Buffer {
2863
+ import_core9 = __toESM(require_core(), 1);
2864
+ WEBGLBuffer = class extends import_core9.Buffer {
2669
2865
  device;
2670
2866
  gl;
2671
2867
  handle;
@@ -2700,8 +2896,12 @@ var __exports__ = (() => {
2700
2896
  destroy() {
2701
2897
  if (!this.destroyed && this.handle) {
2702
2898
  this.removeStats();
2703
- this.trackDeallocatedMemory();
2704
- this.gl.deleteBuffer(this.handle);
2899
+ if (!this.props.handle) {
2900
+ this.trackDeallocatedMemory();
2901
+ this.gl.deleteBuffer(this.handle);
2902
+ } else {
2903
+ this.trackDeallocatedReferencedMemory("Buffer");
2904
+ }
2705
2905
  this.destroyed = true;
2706
2906
  this.handle = null;
2707
2907
  }
@@ -2716,7 +2916,11 @@ var __exports__ = (() => {
2716
2916
  this.bytesUsed = byteLength;
2717
2917
  this.byteLength = byteLength;
2718
2918
  this._setDebugData(data, byteOffset, byteLength);
2719
- this.trackAllocatedMemory(byteLength);
2919
+ if (!this.props.handle) {
2920
+ this.trackAllocatedMemory(byteLength);
2921
+ } else {
2922
+ this.trackReferencedMemory(byteLength, "Buffer");
2923
+ }
2720
2924
  }
2721
2925
  // Allocate a GPU buffer of specified size.
2722
2926
  _initWithByteLength(byteLength) {
@@ -2731,7 +2935,11 @@ var __exports__ = (() => {
2731
2935
  this.bytesUsed = byteLength;
2732
2936
  this.byteLength = byteLength;
2733
2937
  this._setDebugData(null, 0, byteLength);
2734
- this.trackAllocatedMemory(byteLength);
2938
+ if (!this.props.handle) {
2939
+ this.trackAllocatedMemory(byteLength);
2940
+ } else {
2941
+ this.trackReferencedMemory(byteLength, "Buffer");
2942
+ }
2735
2943
  return this;
2736
2944
  }
2737
2945
  write(data, byteOffset = 0) {
@@ -2782,9 +2990,20 @@ var __exports__ = (() => {
2782
2990
  if (line.length <= 1) {
2783
2991
  continue;
2784
2992
  }
2993
+ const lineWithTrimmedWhitespace = line.trim();
2785
2994
  const segments = line.split(":");
2995
+ const trimmedMessageType = segments[0]?.trim();
2786
2996
  if (segments.length === 2) {
2787
2997
  const [messageType2, message2] = segments;
2998
+ if (!messageType2 || !message2) {
2999
+ messages.push({
3000
+ message: lineWithTrimmedWhitespace,
3001
+ type: getMessageType(trimmedMessageType || "info"),
3002
+ lineNum: 0,
3003
+ linePos: 0
3004
+ });
3005
+ continue;
3006
+ }
2788
3007
  messages.push({
2789
3008
  message: message2.trim(),
2790
3009
  type: getMessageType(messageType2),
@@ -2794,12 +3013,21 @@ var __exports__ = (() => {
2794
3013
  continue;
2795
3014
  }
2796
3015
  const [messageType, linePosition, lineNumber, ...rest] = segments;
3016
+ if (!messageType || !linePosition || !lineNumber) {
3017
+ messages.push({
3018
+ message: segments.slice(1).join(":").trim() || lineWithTrimmedWhitespace,
3019
+ type: getMessageType(trimmedMessageType || "info"),
3020
+ lineNum: 0,
3021
+ linePos: 0
3022
+ });
3023
+ continue;
3024
+ }
2797
3025
  let lineNum = parseInt(lineNumber, 10);
2798
- if (isNaN(lineNum)) {
3026
+ if (Number.isNaN(lineNum)) {
2799
3027
  lineNum = 0;
2800
3028
  }
2801
3029
  let linePos = parseInt(linePosition, 10);
2802
- if (isNaN(linePos)) {
3030
+ if (Number.isNaN(linePos)) {
2803
3031
  linePos = 0;
2804
3032
  }
2805
3033
  messages.push({
@@ -2824,13 +3052,13 @@ var __exports__ = (() => {
2824
3052
  });
2825
3053
 
2826
3054
  // src/adapter/resources/webgl-shader.ts
2827
- var import_core9, WEBGLShader;
3055
+ var import_core10, WEBGLShader;
2828
3056
  var init_webgl_shader = __esm({
2829
3057
  "src/adapter/resources/webgl-shader.ts"() {
2830
3058
  "use strict";
2831
- import_core9 = __toESM(require_core(), 1);
3059
+ import_core10 = __toESM(require_core(), 1);
2832
3060
  init_parse_shader_compiler_log();
2833
- WEBGLShader = class extends import_core9.Shader {
3061
+ WEBGLShader = class extends import_core10.Shader {
2834
3062
  device;
2835
3063
  handle;
2836
3064
  constructor(device, props) {
@@ -2847,7 +3075,12 @@ var __exports__ = (() => {
2847
3075
  throw new Error(this.props.stage);
2848
3076
  }
2849
3077
  device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
2850
- this._compile(this.source);
3078
+ const compilationStatus = this._compile(this.source);
3079
+ if (compilationStatus && typeof compilationStatus.catch === "function") {
3080
+ compilationStatus.catch(() => {
3081
+ this.compilationStatus = "error";
3082
+ });
3083
+ }
2851
3084
  }
2852
3085
  destroy() {
2853
3086
  if (this.handle) {
@@ -2878,7 +3111,7 @@ var __exports__ = (() => {
2878
3111
  }
2879
3112
  // PRIVATE METHODS
2880
3113
  /** Compile a shader and get compilation status */
2881
- async _compile(source) {
3114
+ _compile(source) {
2882
3115
  source = source.startsWith("#version ") ? source : `#version 300 es
2883
3116
  ${source}`;
2884
3117
  const { gl } = this.device;
@@ -2896,11 +3129,12 @@ ${source}`;
2896
3129
  }
2897
3130
  return;
2898
3131
  }
2899
- import_core9.log.once(1, "Shader compilation is asynchronous")();
2900
- await this._waitForCompilationComplete();
2901
- import_core9.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2902
- this._getCompilationStatus();
2903
- this.debugShader();
3132
+ import_core10.log.once(1, "Shader compilation is asynchronous")();
3133
+ return this._waitForCompilationComplete().then(() => {
3134
+ import_core10.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
3135
+ this._getCompilationStatus();
3136
+ this.debugShader();
3137
+ });
2904
3138
  }
2905
3139
  /** Use KHR_parallel_shader_compile extension if available */
2906
3140
  async _waitForCompilationComplete() {
@@ -3059,13 +3293,16 @@ ${source}`;
3059
3293
  parameters.depthCompare !== "always" ? gl.enable(2929 /* DEPTH_TEST */) : gl.disable(2929 /* DEPTH_TEST */);
3060
3294
  gl.depthFunc(convertCompareFunction("depthCompare", parameters.depthCompare));
3061
3295
  }
3296
+ if (parameters.clearDepth !== void 0) {
3297
+ gl.clearDepth(parameters.clearDepth);
3298
+ }
3062
3299
  if (parameters.stencilWriteMask) {
3063
3300
  const mask = parameters.stencilWriteMask;
3064
3301
  gl.stencilMaskSeparate(1028 /* FRONT */, mask);
3065
3302
  gl.stencilMaskSeparate(1029 /* BACK */, mask);
3066
3303
  }
3067
3304
  if (parameters.stencilReadMask) {
3068
- import_core10.log.warn("stencilReadMask not supported under WebGL");
3305
+ import_core11.log.warn("stencilReadMask not supported under WebGL");
3069
3306
  }
3070
3307
  if (parameters.stencilCompare) {
3071
3308
  const mask = parameters.stencilReadMask || 4294967295;
@@ -3199,11 +3436,11 @@ ${source}`;
3199
3436
  }
3200
3437
  return isEmpty;
3201
3438
  }
3202
- var import_core10;
3439
+ var import_core11;
3203
3440
  var init_device_parameters = __esm({
3204
3441
  "src/adapter/converters/device-parameters.ts"() {
3205
3442
  "use strict";
3206
- import_core10 = __toESM(require_core(), 1);
3443
+ import_core11 = __toESM(require_core(), 1);
3207
3444
  init_unified_parameter_api();
3208
3445
  }
3209
3446
  });
@@ -3296,13 +3533,13 @@ ${source}`;
3296
3533
  });
3297
3534
 
3298
3535
  // src/adapter/resources/webgl-sampler.ts
3299
- var import_core11, WEBGLSampler;
3536
+ var import_core12, WEBGLSampler;
3300
3537
  var init_webgl_sampler = __esm({
3301
3538
  "src/adapter/resources/webgl-sampler.ts"() {
3302
3539
  "use strict";
3303
- import_core11 = __toESM(require_core(), 1);
3540
+ import_core12 = __toESM(require_core(), 1);
3304
3541
  init_sampler_parameters();
3305
- WEBGLSampler = class extends import_core11.Sampler {
3542
+ WEBGLSampler = class extends import_core12.Sampler {
3306
3543
  device;
3307
3544
  handle;
3308
3545
  parameters;
@@ -3378,19 +3615,19 @@ ${source}`;
3378
3615
  });
3379
3616
 
3380
3617
  // src/adapter/resources/webgl-texture-view.ts
3381
- var import_core12, WEBGLTextureView;
3618
+ var import_core13, WEBGLTextureView;
3382
3619
  var init_webgl_texture_view = __esm({
3383
3620
  "src/adapter/resources/webgl-texture-view.ts"() {
3384
3621
  "use strict";
3385
- import_core12 = __toESM(require_core(), 1);
3386
- WEBGLTextureView = class extends import_core12.TextureView {
3622
+ import_core13 = __toESM(require_core(), 1);
3623
+ WEBGLTextureView = class extends import_core13.TextureView {
3387
3624
  device;
3388
3625
  gl;
3389
3626
  handle;
3390
3627
  // Does not have a WebGL representation
3391
3628
  texture;
3392
3629
  constructor(device, props) {
3393
- super(device, { ...import_core12.Texture.defaultProps, ...props });
3630
+ super(device, { ...import_core13.Texture.defaultProps, ...props });
3394
3631
  this.device = device;
3395
3632
  this.gl = this.device.gl;
3396
3633
  this.handle = null;
@@ -3400,7 +3637,54 @@ ${source}`;
3400
3637
  }
3401
3638
  });
3402
3639
 
3640
+ // src/adapter/converters/shader-formats.ts
3641
+ function convertGLDataTypeToDataType(type) {
3642
+ return GL_DATA_TYPE_MAP[type];
3643
+ }
3644
+ var GL_DATA_TYPE_MAP;
3645
+ var init_shader_formats = __esm({
3646
+ "src/adapter/converters/shader-formats.ts"() {
3647
+ "use strict";
3648
+ GL_DATA_TYPE_MAP = {
3649
+ [5124 /* INT */]: "sint32",
3650
+ [5125 /* UNSIGNED_INT */]: "uint32",
3651
+ [5122 /* SHORT */]: "sint16",
3652
+ [5123 /* UNSIGNED_SHORT */]: "uint16",
3653
+ [5120 /* BYTE */]: "sint8",
3654
+ [5121 /* UNSIGNED_BYTE */]: "uint8",
3655
+ [5126 /* FLOAT */]: "float32",
3656
+ [5131 /* HALF_FLOAT */]: "float16",
3657
+ [33635 /* UNSIGNED_SHORT_5_6_5 */]: "uint16",
3658
+ [32819 /* UNSIGNED_SHORT_4_4_4_4 */]: "uint16",
3659
+ [32820 /* UNSIGNED_SHORT_5_5_5_1 */]: "uint16",
3660
+ [33640 /* UNSIGNED_INT_2_10_10_10_REV */]: "uint32",
3661
+ [35899 /* UNSIGNED_INT_10F_11F_11F_REV */]: "uint32",
3662
+ [35902 /* UNSIGNED_INT_5_9_9_9_REV */]: "uint32",
3663
+ [34042 /* UNSIGNED_INT_24_8 */]: "uint32",
3664
+ [36269 /* FLOAT_32_UNSIGNED_INT_24_8_REV */]: "uint32"
3665
+ };
3666
+ }
3667
+ });
3668
+
3403
3669
  // src/adapter/resources/webgl-texture.ts
3670
+ function getArrayBufferView(typedArray, byteOffset = 0) {
3671
+ if (!byteOffset) {
3672
+ return typedArray;
3673
+ }
3674
+ return new typedArray.constructor(
3675
+ typedArray.buffer,
3676
+ typedArray.byteOffset + byteOffset,
3677
+ (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT
3678
+ );
3679
+ }
3680
+ function getWebGLTextureSourceElementOffset(typedArray, byteOffset) {
3681
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
3682
+ throw new Error(
3683
+ `Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`
3684
+ );
3685
+ }
3686
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
3687
+ }
3404
3688
  function getWebGLTextureTarget(dimension) {
3405
3689
  switch (dimension) {
3406
3690
  case "1d":
@@ -3421,16 +3705,17 @@ ${source}`;
3421
3705
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3422
3706
  return dimension === "cube" ? 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ + level : glTarget;
3423
3707
  }
3424
- var import_core13, WEBGLTexture;
3708
+ var import_core14, WEBGLTexture;
3425
3709
  var init_webgl_texture = __esm({
3426
3710
  "src/adapter/resources/webgl-texture.ts"() {
3427
3711
  "use strict";
3428
- import_core13 = __toESM(require_core(), 1);
3712
+ import_core14 = __toESM(require_core(), 1);
3429
3713
  init_webgl_texture_table();
3430
3714
  init_sampler_parameters();
3431
3715
  init_with_parameters();
3432
3716
  init_webgl_texture_view();
3433
- WEBGLTexture = class extends import_core13.Texture {
3717
+ init_shader_formats();
3718
+ WEBGLTexture = class extends import_core14.Texture {
3434
3719
  // readonly MAX_ATTRIBUTES: number;
3435
3720
  device;
3436
3721
  gl;
@@ -3459,8 +3744,12 @@ ${source}`;
3459
3744
  // state
3460
3745
  /** Texture binding slot - TODO - move to texture view? */
3461
3746
  _textureUnit = 0;
3747
+ /** Cached framebuffer reused for color texture readback. */
3748
+ _framebuffer = null;
3749
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3750
+ _framebufferAttachmentKey = null;
3462
3751
  constructor(device, props) {
3463
- super(device, props);
3752
+ super(device, props, { byteAlignment: 1 });
3464
3753
  this.device = device;
3465
3754
  this.gl = this.device.gl;
3466
3755
  const formatInfo = getTextureFormatWebGL(this.props.format);
@@ -3473,29 +3762,43 @@ ${source}`;
3473
3762
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3474
3763
  this.gl.bindTexture(this.glTarget, this.handle);
3475
3764
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3476
- switch (dimension) {
3477
- case "2d":
3478
- case "cube":
3479
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3480
- break;
3481
- case "2d-array":
3482
- case "3d":
3483
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3484
- break;
3485
- default:
3486
- throw new Error(dimension);
3765
+ if (!this.compressed) {
3766
+ switch (dimension) {
3767
+ case "2d":
3768
+ case "cube":
3769
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3770
+ break;
3771
+ case "2d-array":
3772
+ case "3d":
3773
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3774
+ break;
3775
+ default:
3776
+ throw new Error(dimension);
3777
+ }
3487
3778
  }
3488
3779
  this.gl.bindTexture(this.glTarget, null);
3489
3780
  this._initializeData(props.data);
3781
+ if (!this.props.handle) {
3782
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
3783
+ } else {
3784
+ this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
3785
+ }
3490
3786
  this.setSampler(this.props.sampler);
3491
3787
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3492
3788
  Object.seal(this);
3493
3789
  }
3494
3790
  destroy() {
3495
3791
  if (this.handle) {
3496
- this.gl.deleteTexture(this.handle);
3792
+ this._framebuffer?.destroy();
3793
+ this._framebuffer = null;
3794
+ this._framebufferAttachmentKey = null;
3497
3795
  this.removeStats();
3498
- this.trackDeallocatedMemory("Texture");
3796
+ if (!this.props.handle) {
3797
+ this.gl.deleteTexture(this.handle);
3798
+ this.trackDeallocatedMemory("Texture");
3799
+ } else {
3800
+ this.trackDeallocatedReferencedMemory("Texture");
3801
+ }
3499
3802
  this.destroyed = true;
3500
3803
  }
3501
3804
  }
@@ -3507,53 +3810,6 @@ ${source}`;
3507
3810
  const parameters = convertSamplerParametersToWebGL(this.sampler.props);
3508
3811
  this._setSamplerParameters(parameters);
3509
3812
  }
3510
- copyImageData(options_) {
3511
- const options = this._normalizeCopyImageDataOptions(options_);
3512
- const typedArray = options.data;
3513
- const { width, height, depth } = this;
3514
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0, z = 0 } = options;
3515
- const { glFormat, glType, compressed } = this;
3516
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3517
- let unpackRowLength;
3518
- if (!this.compressed) {
3519
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3520
- if (bytesPerPixel) {
3521
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3522
- throw new Error(
3523
- `bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`
3524
- );
3525
- }
3526
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
3527
- }
3528
- }
3529
- const glParameters = !this.compressed ? {
3530
- ...unpackRowLength !== void 0 ? { [3314 /* UNPACK_ROW_LENGTH */]: unpackRowLength } : {},
3531
- [32878 /* UNPACK_IMAGE_HEIGHT */]: options.rowsPerImage
3532
- } : {};
3533
- this.gl.bindTexture(glTarget, this.handle);
3534
- withGLParameters(this.gl, glParameters, () => {
3535
- switch (this.dimension) {
3536
- case "2d":
3537
- case "cube":
3538
- if (compressed) {
3539
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
3540
- } else {
3541
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3542
- }
3543
- break;
3544
- case "2d-array":
3545
- case "3d":
3546
- if (compressed) {
3547
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
3548
- } else {
3549
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
3550
- }
3551
- break;
3552
- default:
3553
- }
3554
- });
3555
- this.gl.bindTexture(glTarget, null);
3556
- }
3557
3813
  copyExternalImage(options_) {
3558
3814
  const options = this._normalizeCopyExternalImageOptions(options_);
3559
3815
  if (options.sourceX || options.sourceY) {
@@ -3561,7 +3817,7 @@ ${source}`;
3561
3817
  }
3562
3818
  const { glFormat, glType } = this;
3563
3819
  const { image, depth, mipLevel, x, y, z, width, height } = options;
3564
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3820
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3565
3821
  const glParameters = options.flipY ? { [37440 /* UNPACK_FLIP_Y_WEBGL */]: true } : {};
3566
3822
  this.gl.bindTexture(this.glTarget, this.handle);
3567
3823
  withGLParameters(this.gl, glParameters, () => {
@@ -3580,81 +3836,815 @@ ${source}`;
3580
3836
  this.gl.bindTexture(this.glTarget, null);
3581
3837
  return { width: options.width, height: options.height };
3582
3838
  }
3583
- // WEBGL SPECIFIC
3584
- generateMipmapsWebGL(options) {
3585
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3586
- if (!isFilterableAndRenderable) {
3587
- import_core13.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3588
- if (!options?.force) {
3589
- return;
3590
- }
3839
+ copyImageData(options_) {
3840
+ super.copyImageData(options_);
3841
+ }
3842
+ /**
3843
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
3844
+ *
3845
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
3846
+ * before any WebGL calls are issued.
3847
+ */
3848
+ readBuffer(options = {}, buffer) {
3849
+ if (!buffer) {
3850
+ throw new Error(`${this} readBuffer requires a destination buffer`);
3851
+ }
3852
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
3853
+ const byteOffset = options.byteOffset ?? 0;
3854
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
3855
+ if (buffer.byteLength < byteOffset + memoryLayout.byteLength) {
3856
+ throw new Error(
3857
+ `${this} readBuffer target is too small (${buffer.byteLength} < ${byteOffset + memoryLayout.byteLength})`
3858
+ );
3591
3859
  }
3860
+ const webglBuffer = buffer;
3861
+ this.gl.bindBuffer(35051 /* PIXEL_PACK_BUFFER */, webglBuffer.handle);
3592
3862
  try {
3593
- this.gl.bindTexture(this.glTarget, this.handle);
3594
- this.gl.generateMipmap(this.glTarget);
3595
- } catch (error) {
3596
- import_core13.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3863
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, (destinationByteOffset) => {
3864
+ this.gl.readPixels(
3865
+ normalizedOptions.x,
3866
+ normalizedOptions.y,
3867
+ normalizedOptions.width,
3868
+ normalizedOptions.height,
3869
+ this.glFormat,
3870
+ this.glType,
3871
+ byteOffset + destinationByteOffset
3872
+ );
3873
+ });
3597
3874
  } finally {
3598
- this.gl.bindTexture(this.glTarget, null);
3875
+ this.gl.bindBuffer(35051 /* PIXEL_PACK_BUFFER */, null);
3599
3876
  }
3877
+ return buffer;
3600
3878
  }
3601
- // INTERNAL
3602
- /**
3603
- * Sets sampler parameters on texture
3604
- */
3605
- _setSamplerParameters(parameters) {
3606
- import_core13.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3879
+ async readDataAsync(options = {}) {
3880
+ throw new Error(
3881
+ `${this} readDataAsync is deprecated; use readBuffer() with an explicit destination buffer or DynamicTexture.readAsync()`
3882
+ );
3883
+ }
3884
+ writeBuffer(buffer, options_ = {}) {
3885
+ const options = this._normalizeTextureWriteOptions(options_);
3886
+ const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
3887
+ const { glFormat, glType, compressed } = this;
3888
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3889
+ if (compressed) {
3890
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
3891
+ }
3892
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3893
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3894
+ const glParameters = {
3895
+ [3317 /* UNPACK_ALIGNMENT */]: this.byteAlignment,
3896
+ ...unpackRowLength !== void 0 ? { [3314 /* UNPACK_ROW_LENGTH */]: unpackRowLength } : {},
3897
+ [32878 /* UNPACK_IMAGE_HEIGHT */]: options.rowsPerImage
3898
+ };
3607
3899
  this.gl.bindTexture(this.glTarget, this.handle);
3608
- for (const [pname, pvalue] of Object.entries(parameters)) {
3609
- const param = Number(pname);
3610
- const value = pvalue;
3611
- switch (param) {
3612
- case 33082 /* TEXTURE_MIN_LOD */:
3613
- case 33083 /* TEXTURE_MAX_LOD */:
3614
- this.gl.texParameterf(this.glTarget, param, value);
3615
- break;
3616
- case 10240 /* TEXTURE_MAG_FILTER */:
3617
- case 10241 /* TEXTURE_MIN_FILTER */:
3618
- this.gl.texParameteri(this.glTarget, param, value);
3900
+ this.gl.bindBuffer(35052 /* PIXEL_UNPACK_BUFFER */, buffer.handle);
3901
+ withGLParameters(this.gl, glParameters, () => {
3902
+ switch (this.dimension) {
3903
+ case "2d":
3904
+ case "cube":
3905
+ this.gl.texSubImage2D(
3906
+ glTarget,
3907
+ mipLevel,
3908
+ x,
3909
+ y,
3910
+ width,
3911
+ height,
3912
+ glFormat,
3913
+ glType,
3914
+ byteOffset
3915
+ );
3916
+ break;
3917
+ case "2d-array":
3918
+ case "3d":
3919
+ this.gl.texSubImage3D(
3920
+ glTarget,
3921
+ mipLevel,
3922
+ x,
3923
+ y,
3924
+ z,
3925
+ width,
3926
+ height,
3927
+ depthOrArrayLayers,
3928
+ glFormat,
3929
+ glType,
3930
+ byteOffset
3931
+ );
3932
+ break;
3933
+ default:
3934
+ }
3935
+ });
3936
+ this.gl.bindBuffer(35052 /* PIXEL_UNPACK_BUFFER */, null);
3937
+ this.gl.bindTexture(this.glTarget, null);
3938
+ }
3939
+ writeData(data, options_ = {}) {
3940
+ const options = this._normalizeTextureWriteOptions(options_);
3941
+ const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3942
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
3943
+ const { glFormat, glType, compressed } = this;
3944
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3945
+ let unpackRowLength;
3946
+ if (!compressed) {
3947
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3948
+ if (bytesPerPixel) {
3949
+ unpackRowLength = options.bytesPerRow / bytesPerPixel;
3950
+ }
3951
+ }
3952
+ const glParameters = !this.compressed ? {
3953
+ [3317 /* UNPACK_ALIGNMENT */]: this.byteAlignment,
3954
+ ...unpackRowLength !== void 0 ? { [3314 /* UNPACK_ROW_LENGTH */]: unpackRowLength } : {},
3955
+ [32878 /* UNPACK_IMAGE_HEIGHT */]: options.rowsPerImage
3956
+ } : {};
3957
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
3958
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
3959
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
3960
+ const isFullMipUpload = x === 0 && y === 0 && z === 0 && width === mipLevelSize.width && height === mipLevelSize.height && depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
3961
+ this.gl.bindTexture(this.glTarget, this.handle);
3962
+ this.gl.bindBuffer(35052 /* PIXEL_UNPACK_BUFFER */, null);
3963
+ withGLParameters(this.gl, glParameters, () => {
3964
+ switch (this.dimension) {
3965
+ case "2d":
3966
+ case "cube":
3967
+ if (compressed) {
3968
+ if (isFullMipUpload) {
3969
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
3970
+ } else {
3971
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
3972
+ }
3973
+ } else {
3974
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3975
+ }
3976
+ break;
3977
+ case "2d-array":
3978
+ case "3d":
3979
+ if (compressed) {
3980
+ if (isFullMipUpload) {
3981
+ this.gl.compressedTexImage3D(
3982
+ glTarget,
3983
+ mipLevel,
3984
+ glFormat,
3985
+ width,
3986
+ height,
3987
+ depthOrArrayLayers,
3988
+ 0,
3989
+ compressedData
3990
+ );
3991
+ } else {
3992
+ this.gl.compressedTexSubImage3D(
3993
+ glTarget,
3994
+ mipLevel,
3995
+ x,
3996
+ y,
3997
+ z,
3998
+ width,
3999
+ height,
4000
+ depthOrArrayLayers,
4001
+ glFormat,
4002
+ compressedData
4003
+ );
4004
+ }
4005
+ } else {
4006
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
4007
+ }
4008
+ break;
4009
+ default:
4010
+ }
4011
+ });
4012
+ this.gl.bindTexture(this.glTarget, null);
4013
+ }
4014
+ // IMPLEMENTATION SPECIFIC
4015
+ /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
4016
+ _getRowByteAlignment(format, width) {
4017
+ return 1;
4018
+ }
4019
+ /**
4020
+ * Wraps a given texture into a framebuffer object, that can be further used
4021
+ * to read data from the texture object.
4022
+ */
4023
+ _getFramebuffer() {
4024
+ this._framebuffer ||= this.device.createFramebuffer({
4025
+ id: `framebuffer-for-${this.id}`,
4026
+ width: this.width,
4027
+ height: this.height,
4028
+ colorAttachments: [this]
4029
+ });
4030
+ return this._framebuffer;
4031
+ }
4032
+ // WEBGL SPECIFIC
4033
+ readDataSyncWebGL(options_ = {}) {
4034
+ const options = this._getSupportedColorReadOptions(options_);
4035
+ const memoryLayout = this.computeMemoryLayout(options);
4036
+ const shaderType = convertGLDataTypeToDataType(this.glType);
4037
+ const ArrayType = (0, import_core14.getTypedArrayConstructor)(shaderType);
4038
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT);
4039
+ this._readColorTextureLayers(options, memoryLayout, (destinationByteOffset) => {
4040
+ const layerView = new ArrayType(
4041
+ targetArray.buffer,
4042
+ targetArray.byteOffset + destinationByteOffset,
4043
+ memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT
4044
+ );
4045
+ this.gl.readPixels(
4046
+ options.x,
4047
+ options.y,
4048
+ options.width,
4049
+ options.height,
4050
+ this.glFormat,
4051
+ this.glType,
4052
+ layerView
4053
+ );
4054
+ });
4055
+ return targetArray.buffer;
4056
+ }
4057
+ /**
4058
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
4059
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
4060
+ */
4061
+ _readColorTextureLayers(options, memoryLayout, readLayer) {
4062
+ const framebuffer = this._getFramebuffer();
4063
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
4064
+ const glParameters = {
4065
+ [3333 /* PACK_ALIGNMENT */]: this.byteAlignment,
4066
+ ...packRowLength !== options.width ? { [3330 /* PACK_ROW_LENGTH */]: packRowLength } : {}
4067
+ };
4068
+ const prevReadBuffer = this.gl.getParameter(3074 /* READ_BUFFER */);
4069
+ const prevHandle = this.gl.bindFramebuffer(
4070
+ 36160 /* FRAMEBUFFER */,
4071
+ framebuffer.handle
4072
+ );
4073
+ try {
4074
+ this.gl.readBuffer(36064 /* COLOR_ATTACHMENT0 */);
4075
+ withGLParameters(this.gl, glParameters, () => {
4076
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
4077
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
4078
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
4079
+ }
4080
+ });
4081
+ } finally {
4082
+ this.gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle || null);
4083
+ this.gl.readBuffer(prevReadBuffer);
4084
+ }
4085
+ }
4086
+ /**
4087
+ * Attaches a single color subresource to the cached read framebuffer.
4088
+ *
4089
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
4090
+ */
4091
+ _attachReadSubresource(framebuffer, mipLevel, layer) {
4092
+ const attachmentKey = `${mipLevel}:${layer}`;
4093
+ if (this._framebufferAttachmentKey === attachmentKey) {
4094
+ return;
4095
+ }
4096
+ switch (this.dimension) {
4097
+ case "2d":
4098
+ this.gl.framebufferTexture2D(
4099
+ 36160 /* FRAMEBUFFER */,
4100
+ 36064 /* COLOR_ATTACHMENT0 */,
4101
+ 3553 /* TEXTURE_2D */,
4102
+ this.handle,
4103
+ mipLevel
4104
+ );
4105
+ break;
4106
+ case "cube":
4107
+ this.gl.framebufferTexture2D(
4108
+ 36160 /* FRAMEBUFFER */,
4109
+ 36064 /* COLOR_ATTACHMENT0 */,
4110
+ getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer),
4111
+ this.handle,
4112
+ mipLevel
4113
+ );
4114
+ break;
4115
+ case "2d-array":
4116
+ case "3d":
4117
+ this.gl.framebufferTextureLayer(
4118
+ 36160 /* FRAMEBUFFER */,
4119
+ 36064 /* COLOR_ATTACHMENT0 */,
4120
+ this.handle,
4121
+ mipLevel,
4122
+ layer
4123
+ );
4124
+ break;
4125
+ default:
4126
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
4127
+ }
4128
+ if (this.device.props.debug) {
4129
+ const status = Number(this.gl.checkFramebufferStatus(36160 /* FRAMEBUFFER */));
4130
+ if (status !== Number(36053 /* FRAMEBUFFER_COMPLETE */)) {
4131
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
4132
+ }
4133
+ }
4134
+ this._framebufferAttachmentKey = attachmentKey;
4135
+ }
4136
+ /**
4137
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
4138
+ */
4139
+ generateMipmapsWebGL(options) {
4140
+ const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
4141
+ if (!isFilterableAndRenderable) {
4142
+ import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
4143
+ if (!options?.force) {
4144
+ return;
4145
+ }
4146
+ }
4147
+ try {
4148
+ this.gl.bindTexture(this.glTarget, this.handle);
4149
+ this.gl.generateMipmap(this.glTarget);
4150
+ } catch (error) {
4151
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
4152
+ } finally {
4153
+ this.gl.bindTexture(this.glTarget, null);
4154
+ }
4155
+ }
4156
+ // INTERNAL
4157
+ /**
4158
+ * Sets sampler parameters on texture
4159
+ */
4160
+ _setSamplerParameters(parameters) {
4161
+ import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
4162
+ this.gl.bindTexture(this.glTarget, this.handle);
4163
+ for (const [pname, pvalue] of Object.entries(parameters)) {
4164
+ const param = Number(pname);
4165
+ const value = pvalue;
4166
+ switch (param) {
4167
+ case 33082 /* TEXTURE_MIN_LOD */:
4168
+ case 33083 /* TEXTURE_MAX_LOD */:
4169
+ this.gl.texParameterf(this.glTarget, param, value);
4170
+ break;
4171
+ case 10240 /* TEXTURE_MAG_FILTER */:
4172
+ case 10241 /* TEXTURE_MIN_FILTER */:
4173
+ this.gl.texParameteri(this.glTarget, param, value);
3619
4174
  break;
3620
4175
  case 10242 /* TEXTURE_WRAP_S */:
3621
4176
  case 10243 /* TEXTURE_WRAP_T */:
3622
4177
  case 32882 /* TEXTURE_WRAP_R */:
3623
4178
  this.gl.texParameteri(this.glTarget, param, value);
3624
4179
  break;
3625
- case 34046 /* TEXTURE_MAX_ANISOTROPY_EXT */:
3626
- if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
3627
- this.gl.texParameteri(this.glTarget, param, value);
4180
+ case 34046 /* TEXTURE_MAX_ANISOTROPY_EXT */:
4181
+ if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
4182
+ this.gl.texParameteri(this.glTarget, param, value);
4183
+ }
4184
+ break;
4185
+ case 34892 /* TEXTURE_COMPARE_MODE */:
4186
+ case 34893 /* TEXTURE_COMPARE_FUNC */:
4187
+ this.gl.texParameteri(this.glTarget, param, value);
4188
+ break;
4189
+ }
4190
+ }
4191
+ this.gl.bindTexture(this.glTarget, null);
4192
+ }
4193
+ _getActiveUnit() {
4194
+ return this.gl.getParameter(34016 /* ACTIVE_TEXTURE */) - 33984 /* TEXTURE0 */;
4195
+ }
4196
+ _bind(_textureUnit) {
4197
+ const { gl } = this;
4198
+ if (_textureUnit !== void 0) {
4199
+ this._textureUnit = _textureUnit;
4200
+ gl.activeTexture(gl.TEXTURE0 + _textureUnit);
4201
+ }
4202
+ gl.bindTexture(this.glTarget, this.handle);
4203
+ return _textureUnit;
4204
+ }
4205
+ _unbind(_textureUnit) {
4206
+ const { gl } = this;
4207
+ if (_textureUnit !== void 0) {
4208
+ this._textureUnit = _textureUnit;
4209
+ gl.activeTexture(gl.TEXTURE0 + _textureUnit);
4210
+ }
4211
+ gl.bindTexture(this.glTarget, null);
4212
+ return _textureUnit;
4213
+ }
4214
+ };
4215
+ }
4216
+ });
4217
+
4218
+ // src/adapter/helpers/set-uniform.ts
4219
+ function setUniform(gl, location, type, value) {
4220
+ const gl2 = gl;
4221
+ let uniformValue = value;
4222
+ if (uniformValue === true) {
4223
+ uniformValue = 1;
4224
+ }
4225
+ if (uniformValue === false) {
4226
+ uniformValue = 0;
4227
+ }
4228
+ const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
4229
+ switch (type) {
4230
+ case 35678 /* SAMPLER_2D */:
4231
+ case 35680 /* SAMPLER_CUBE */:
4232
+ case 35679 /* SAMPLER_3D */:
4233
+ case 35682 /* SAMPLER_2D_SHADOW */:
4234
+ case 36289 /* SAMPLER_2D_ARRAY */:
4235
+ case 36292 /* SAMPLER_2D_ARRAY_SHADOW */:
4236
+ case 36293 /* SAMPLER_CUBE_SHADOW */:
4237
+ case 36298 /* INT_SAMPLER_2D */:
4238
+ case 36299 /* INT_SAMPLER_3D */:
4239
+ case 36300 /* INT_SAMPLER_CUBE */:
4240
+ case 36303 /* INT_SAMPLER_2D_ARRAY */:
4241
+ case 36306 /* UNSIGNED_INT_SAMPLER_2D */:
4242
+ case 36307 /* UNSIGNED_INT_SAMPLER_3D */:
4243
+ case 36308 /* UNSIGNED_INT_SAMPLER_CUBE */:
4244
+ case 36311 /* UNSIGNED_INT_SAMPLER_2D_ARRAY */:
4245
+ if (typeof value !== "number") {
4246
+ throw new Error("samplers must be set to integers");
4247
+ }
4248
+ return gl.uniform1i(location, value);
4249
+ case 5126 /* FLOAT */:
4250
+ return gl.uniform1fv(location, arrayValue);
4251
+ case 35664 /* FLOAT_VEC2 */:
4252
+ return gl.uniform2fv(location, arrayValue);
4253
+ case 35665 /* FLOAT_VEC3 */:
4254
+ return gl.uniform3fv(location, arrayValue);
4255
+ case 35666 /* FLOAT_VEC4 */:
4256
+ return gl.uniform4fv(location, arrayValue);
4257
+ case 5124 /* INT */:
4258
+ return gl.uniform1iv(location, arrayValue);
4259
+ case 35667 /* INT_VEC2 */:
4260
+ return gl.uniform2iv(location, arrayValue);
4261
+ case 35668 /* INT_VEC3 */:
4262
+ return gl.uniform3iv(location, arrayValue);
4263
+ case 35669 /* INT_VEC4 */:
4264
+ return gl.uniform4iv(location, arrayValue);
4265
+ case 35670 /* BOOL */:
4266
+ return gl.uniform1iv(location, arrayValue);
4267
+ case 35671 /* BOOL_VEC2 */:
4268
+ return gl.uniform2iv(location, arrayValue);
4269
+ case 35672 /* BOOL_VEC3 */:
4270
+ return gl.uniform3iv(location, arrayValue);
4271
+ case 35673 /* BOOL_VEC4 */:
4272
+ return gl.uniform4iv(location, arrayValue);
4273
+ case 5125 /* UNSIGNED_INT */:
4274
+ return gl2.uniform1uiv(location, arrayValue, 1);
4275
+ case 36294 /* UNSIGNED_INT_VEC2 */:
4276
+ return gl2.uniform2uiv(location, arrayValue, 2);
4277
+ case 36295 /* UNSIGNED_INT_VEC3 */:
4278
+ return gl2.uniform3uiv(location, arrayValue, 3);
4279
+ case 36296 /* UNSIGNED_INT_VEC4 */:
4280
+ return gl2.uniform4uiv(location, arrayValue, 4);
4281
+ case 35674 /* FLOAT_MAT2 */:
4282
+ return gl.uniformMatrix2fv(location, false, arrayValue);
4283
+ case 35675 /* FLOAT_MAT3 */:
4284
+ return gl.uniformMatrix3fv(location, false, arrayValue);
4285
+ case 35676 /* FLOAT_MAT4 */:
4286
+ return gl.uniformMatrix4fv(location, false, arrayValue);
4287
+ case 35685 /* FLOAT_MAT2x3 */:
4288
+ return gl2.uniformMatrix2x3fv(location, false, arrayValue);
4289
+ case 35686 /* FLOAT_MAT2x4 */:
4290
+ return gl2.uniformMatrix2x4fv(location, false, arrayValue);
4291
+ case 35687 /* FLOAT_MAT3x2 */:
4292
+ return gl2.uniformMatrix3x2fv(location, false, arrayValue);
4293
+ case 35688 /* FLOAT_MAT3x4 */:
4294
+ return gl2.uniformMatrix3x4fv(location, false, arrayValue);
4295
+ case 35689 /* FLOAT_MAT4x2 */:
4296
+ return gl2.uniformMatrix4x2fv(location, false, arrayValue);
4297
+ case 35690 /* FLOAT_MAT4x3 */:
4298
+ return gl2.uniformMatrix4x3fv(location, false, arrayValue);
4299
+ }
4300
+ throw new Error("Illegal uniform");
4301
+ }
4302
+ var init_set_uniform = __esm({
4303
+ "src/adapter/helpers/set-uniform.ts"() {
4304
+ "use strict";
4305
+ }
4306
+ });
4307
+
4308
+ // src/adapter/helpers/webgl-topology-utils.ts
4309
+ function getGLDrawMode(topology) {
4310
+ switch (topology) {
4311
+ case "point-list":
4312
+ return 0 /* POINTS */;
4313
+ case "line-list":
4314
+ return 1 /* LINES */;
4315
+ case "line-strip":
4316
+ return 3 /* LINE_STRIP */;
4317
+ case "triangle-list":
4318
+ return 4 /* TRIANGLES */;
4319
+ case "triangle-strip":
4320
+ return 5 /* TRIANGLE_STRIP */;
4321
+ default:
4322
+ throw new Error(topology);
4323
+ }
4324
+ }
4325
+ function getGLPrimitive(topology) {
4326
+ switch (topology) {
4327
+ case "point-list":
4328
+ return 0 /* POINTS */;
4329
+ case "line-list":
4330
+ return 1 /* LINES */;
4331
+ case "line-strip":
4332
+ return 1 /* LINES */;
4333
+ case "triangle-list":
4334
+ return 4 /* TRIANGLES */;
4335
+ case "triangle-strip":
4336
+ return 4 /* TRIANGLES */;
4337
+ default:
4338
+ throw new Error(topology);
4339
+ }
4340
+ }
4341
+ var init_webgl_topology_utils = __esm({
4342
+ "src/adapter/helpers/webgl-topology-utils.ts"() {
4343
+ "use strict";
4344
+ }
4345
+ });
4346
+
4347
+ // src/adapter/resources/webgl-render-pipeline.ts
4348
+ function mergeShaderLayout(baseLayout, overrideLayout) {
4349
+ const mergedLayout = {
4350
+ ...baseLayout,
4351
+ attributes: baseLayout.attributes.map((attribute) => ({ ...attribute })),
4352
+ bindings: baseLayout.bindings.map((binding) => ({ ...binding }))
4353
+ };
4354
+ for (const attribute of overrideLayout?.attributes || []) {
4355
+ const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
4356
+ if (!baseAttribute) {
4357
+ import_core15.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
4358
+ } else {
4359
+ baseAttribute.type = attribute.type || baseAttribute.type;
4360
+ baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
4361
+ }
4362
+ }
4363
+ for (const binding of overrideLayout?.bindings || []) {
4364
+ const baseBinding = getShaderLayoutBindingByName(mergedLayout, binding.name);
4365
+ if (!baseBinding) {
4366
+ import_core15.log.warn(`shader layout binding ${binding.name} not present in shader`);
4367
+ continue;
4368
+ }
4369
+ Object.assign(baseBinding, binding);
4370
+ }
4371
+ return mergedLayout;
4372
+ }
4373
+ function getShaderLayoutBindingByName(shaderLayout, bindingName) {
4374
+ return shaderLayout.bindings.find(
4375
+ (binding) => binding.name === bindingName || binding.name === `${bindingName}Uniforms` || `${binding.name}Uniforms` === bindingName
4376
+ );
4377
+ }
4378
+ function getBindingValueForLayoutBinding(bindings, bindingName) {
4379
+ return bindings[bindingName] || bindings[`${bindingName}Uniforms`] || bindings[bindingName.replace(/Uniforms$/, "")];
4380
+ }
4381
+ var import_core15, WEBGLRenderPipeline;
4382
+ var init_webgl_render_pipeline = __esm({
4383
+ "src/adapter/resources/webgl-render-pipeline.ts"() {
4384
+ "use strict";
4385
+ import_core15 = __toESM(require_core(), 1);
4386
+ init_device_parameters();
4387
+ init_set_uniform();
4388
+ init_webgl_buffer();
4389
+ init_webgl_framebuffer();
4390
+ init_webgl_texture();
4391
+ init_webgl_texture_view();
4392
+ init_webgl_topology_utils();
4393
+ WEBGLRenderPipeline = class extends import_core15.RenderPipeline {
4394
+ /** The WebGL device that created this render pipeline */
4395
+ device;
4396
+ /** Handle to underlying WebGL program */
4397
+ handle;
4398
+ /** vertex shader */
4399
+ vs;
4400
+ /** fragment shader */
4401
+ fs;
4402
+ /** The layout extracted from shader by WebGL introspection APIs */
4403
+ introspectedLayout;
4404
+ /** Compatibility path for direct pipeline.setBindings() usage */
4405
+ bindings = {};
4406
+ /** Compatibility path for direct pipeline.uniforms usage */
4407
+ uniforms = {};
4408
+ /** WebGL varyings */
4409
+ varyings = null;
4410
+ _uniformCount = 0;
4411
+ _uniformSetters = {};
4412
+ // TODO are these used?
4413
+ get [Symbol.toStringTag]() {
4414
+ return "WEBGLRenderPipeline";
4415
+ }
4416
+ constructor(device, props) {
4417
+ super(device, props);
4418
+ this.device = device;
4419
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
4420
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
4421
+ this.handle = webglSharedRenderPipeline.handle;
4422
+ this.vs = webglSharedRenderPipeline.vs;
4423
+ this.fs = webglSharedRenderPipeline.fs;
4424
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
4425
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
4426
+ this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4427
+ this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4428
+ }
4429
+ destroy() {
4430
+ if (this.destroyed) {
4431
+ return;
4432
+ }
4433
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4434
+ this.sharedRenderPipeline.destroy();
4435
+ }
4436
+ this.destroyResource();
4437
+ }
4438
+ /**
4439
+ * Compatibility shim for code paths that still set bindings on the pipeline.
4440
+ * Shared-model draws pass bindings per draw and do not rely on this state.
4441
+ */
4442
+ setBindings(bindings, options) {
4443
+ const flatBindings = (0, import_core15.flattenBindingsByGroup)(
4444
+ (0, import_core15.normalizeBindingsByGroup)(this.shaderLayout, bindings)
4445
+ );
4446
+ for (const [name, value] of Object.entries(flatBindings)) {
4447
+ const binding = getShaderLayoutBindingByName(this.shaderLayout, name);
4448
+ if (!binding) {
4449
+ const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
4450
+ if (!options?.disableWarnings) {
4451
+ import_core15.log.warn(
4452
+ `No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`,
4453
+ value
4454
+ )();
4455
+ }
4456
+ } else {
4457
+ if (!value) {
4458
+ import_core15.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4459
+ }
4460
+ switch (binding.type) {
4461
+ case "uniform":
4462
+ if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
4463
+ throw new Error("buffer value");
4464
+ }
4465
+ break;
4466
+ case "texture":
4467
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4468
+ throw new Error(`${this} Bad texture binding for ${name}`);
4469
+ }
4470
+ break;
4471
+ case "sampler":
4472
+ import_core15.log.warn(`Ignoring sampler ${name}`)();
4473
+ break;
4474
+ default:
4475
+ throw new Error(binding.type);
4476
+ }
4477
+ this.bindings[name] = value;
4478
+ }
4479
+ }
4480
+ }
4481
+ /** @todo needed for portable model
4482
+ * @note The WebGL API is offers many ways to draw things
4483
+ * This function unifies those ways into a single call using common parameters with sane defaults
4484
+ */
4485
+ draw(options) {
4486
+ this._syncLinkStatus();
4487
+ const drawBindings = options.bindGroups ? (0, import_core15.flattenBindingsByGroup)(options.bindGroups) : options.bindings || this.bindings;
4488
+ const {
4489
+ renderPass,
4490
+ parameters = this.props.parameters,
4491
+ topology = this.props.topology,
4492
+ vertexArray,
4493
+ vertexCount,
4494
+ // indexCount,
4495
+ instanceCount,
4496
+ isInstanced = false,
4497
+ firstVertex = 0,
4498
+ // firstIndex,
4499
+ // firstInstance,
4500
+ // baseVertex,
4501
+ transformFeedback,
4502
+ uniforms = this.uniforms
4503
+ } = options;
4504
+ const glDrawMode = getGLDrawMode(topology);
4505
+ const isIndexed = Boolean(vertexArray.indexBuffer);
4506
+ const glIndexType = vertexArray.indexBuffer?.glIndexType;
4507
+ if (this.linkStatus !== "success") {
4508
+ import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4509
+ return false;
4510
+ }
4511
+ if (!this._areTexturesRenderable(drawBindings)) {
4512
+ import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4513
+ return false;
4514
+ }
4515
+ this.device.gl.useProgram(this.handle);
4516
+ vertexArray.bindBeforeRender(renderPass);
4517
+ if (transformFeedback) {
4518
+ transformFeedback.begin(this.props.topology);
4519
+ }
4520
+ this._applyBindings(drawBindings, { disableWarnings: this.props.disableWarnings });
4521
+ this._applyUniforms(uniforms);
4522
+ const webglRenderPass = renderPass;
4523
+ withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4524
+ if (isIndexed && isInstanced) {
4525
+ this.device.gl.drawElementsInstanced(
4526
+ glDrawMode,
4527
+ vertexCount || 0,
4528
+ // indexCount?
4529
+ glIndexType,
4530
+ firstVertex,
4531
+ instanceCount || 0
4532
+ );
4533
+ } else if (isIndexed) {
4534
+ this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4535
+ } else if (isInstanced) {
4536
+ this.device.gl.drawArraysInstanced(
4537
+ glDrawMode,
4538
+ firstVertex,
4539
+ vertexCount || 0,
4540
+ instanceCount || 0
4541
+ );
4542
+ } else {
4543
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4544
+ }
4545
+ if (transformFeedback) {
4546
+ transformFeedback.end();
4547
+ }
4548
+ });
4549
+ vertexArray.unbindAfterRender(renderPass);
4550
+ return true;
4551
+ }
4552
+ /**
4553
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
4554
+ * Update a texture if needed (e.g. from video)
4555
+ * Note: This is currently done before every draw call
4556
+ */
4557
+ _areTexturesRenderable(bindings) {
4558
+ let texturesRenderable = true;
4559
+ for (const bindingInfo of this.shaderLayout.bindings) {
4560
+ if (!getBindingValueForLayoutBinding(bindings, bindingInfo.name)) {
4561
+ import_core15.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4562
+ texturesRenderable = false;
4563
+ }
4564
+ }
4565
+ return texturesRenderable;
4566
+ }
4567
+ /** Apply any bindings (before each draw call) */
4568
+ _applyBindings(bindings, _options) {
4569
+ this._syncLinkStatus();
4570
+ if (this.linkStatus !== "success") {
4571
+ return;
4572
+ }
4573
+ const { gl } = this.device;
4574
+ gl.useProgram(this.handle);
4575
+ let textureUnit = 0;
4576
+ let uniformBufferIndex = 0;
4577
+ for (const binding of this.shaderLayout.bindings) {
4578
+ const value = getBindingValueForLayoutBinding(bindings, binding.name);
4579
+ if (!value) {
4580
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4581
+ }
4582
+ switch (binding.type) {
4583
+ case "uniform":
4584
+ const { name } = binding;
4585
+ const location = gl.getUniformBlockIndex(this.handle, name);
4586
+ if (location === 4294967295 /* INVALID_INDEX */) {
4587
+ throw new Error(`Invalid uniform block name ${name}`);
4588
+ }
4589
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
4590
+ if (value instanceof WEBGLBuffer) {
4591
+ gl.bindBufferBase(35345 /* UNIFORM_BUFFER */, uniformBufferIndex, value.handle);
4592
+ } else {
4593
+ const bufferBinding = value;
4594
+ gl.bindBufferRange(
4595
+ 35345 /* UNIFORM_BUFFER */,
4596
+ uniformBufferIndex,
4597
+ bufferBinding.buffer.handle,
4598
+ bufferBinding.offset || 0,
4599
+ bufferBinding.size || bufferBinding.buffer.byteLength - (bufferBinding.offset || 0)
4600
+ );
4601
+ }
4602
+ uniformBufferIndex += 1;
4603
+ break;
4604
+ case "texture":
4605
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4606
+ throw new Error("texture");
4607
+ }
4608
+ let texture;
4609
+ if (value instanceof WEBGLTextureView) {
4610
+ texture = value.texture;
4611
+ } else if (value instanceof WEBGLTexture) {
4612
+ texture = value;
4613
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4614
+ import_core15.log.warn(
4615
+ "Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead"
4616
+ )();
4617
+ texture = value.colorAttachments[0].texture;
4618
+ } else {
4619
+ throw new Error("No texture");
3628
4620
  }
4621
+ gl.activeTexture(33984 /* TEXTURE0 */ + textureUnit);
4622
+ gl.bindTexture(texture.glTarget, texture.handle);
4623
+ textureUnit += 1;
3629
4624
  break;
3630
- case 34892 /* TEXTURE_COMPARE_MODE */:
3631
- case 34893 /* TEXTURE_COMPARE_FUNC */:
3632
- this.gl.texParameteri(this.glTarget, param, value);
4625
+ case "sampler":
3633
4626
  break;
4627
+ case "storage":
4628
+ case "read-only-storage":
4629
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3634
4630
  }
3635
4631
  }
3636
- this.gl.bindTexture(this.glTarget, null);
3637
- }
3638
- _getActiveUnit() {
3639
- return this.gl.getParameter(34016 /* ACTIVE_TEXTURE */) - 33984 /* TEXTURE0 */;
3640
4632
  }
3641
- _bind(_textureUnit) {
3642
- const { gl } = this;
3643
- if (_textureUnit !== void 0) {
3644
- this._textureUnit = _textureUnit;
3645
- gl.activeTexture(gl.TEXTURE0 + _textureUnit);
4633
+ /**
4634
+ * Due to program sharing, uniforms need to be reset before every draw call
4635
+ * (though caching will avoid redundant WebGL calls)
4636
+ */
4637
+ _applyUniforms(uniforms) {
4638
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
4639
+ const { name, location, type, textureUnit } = uniformLayout;
4640
+ const value = uniforms[name] ?? textureUnit;
4641
+ if (value !== void 0) {
4642
+ setUniform(this.device.gl, location, type, value);
4643
+ }
3646
4644
  }
3647
- gl.bindTexture(this.glTarget, this.handle);
3648
- return _textureUnit;
3649
4645
  }
3650
- _unbind(_textureUnit) {
3651
- const { gl } = this;
3652
- if (_textureUnit !== void 0) {
3653
- this._textureUnit = _textureUnit;
3654
- gl.activeTexture(gl.TEXTURE0 + _textureUnit);
3655
- }
3656
- gl.bindTexture(this.glTarget, null);
3657
- return _textureUnit;
4646
+ _syncLinkStatus() {
4647
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
3658
4648
  }
3659
4649
  };
3660
4650
  }
@@ -3843,7 +4833,7 @@ ${source}`;
3843
4833
  }
3844
4834
  const { name, type: glUniformType, size } = activeInfo;
3845
4835
  const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3846
- const { type, components } = (0, import_core14.getVariableShaderTypeInfo)(uniformType);
4836
+ const { type, components } = (0, import_core16.getVariableShaderTypeInfo)(uniformType);
3847
4837
  varyings.push({ location, name, type, size: size * components });
3848
4838
  }
3849
4839
  varyings.sort((a, b) => a.location - b.location);
@@ -3904,21 +4894,34 @@ ${source}`;
3904
4894
  const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387 /* UNIFORM_OFFSET */);
3905
4895
  const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388 /* UNIFORM_ARRAY_STRIDE */);
3906
4896
  for (let i = 0; i < blockInfo.uniformCount; ++i) {
3907
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3908
- if (!activeInfo) {
3909
- throw new Error("activeInfo");
3910
- }
3911
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3912
- blockInfo.uniforms.push({
3913
- name: activeInfo.name,
3914
- format,
3915
- type: uniformType[i],
3916
- arrayLength: uniformArrayLength[i],
3917
- byteOffset: uniformOffset[i],
3918
- byteStride: uniformStride[i]
3919
- // matrixStride: uniformStride[i],
3920
- // rowMajor: uniformRowMajor[i]
3921
- });
4897
+ const uniformIndex = uniformIndices[i];
4898
+ if (uniformIndex !== void 0) {
4899
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
4900
+ if (!activeInfo) {
4901
+ throw new Error("activeInfo");
4902
+ }
4903
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
4904
+ blockInfo.uniforms.push({
4905
+ name: activeInfo.name,
4906
+ format,
4907
+ type: uniformType[i],
4908
+ arrayLength: uniformArrayLength[i],
4909
+ byteOffset: uniformOffset[i],
4910
+ byteStride: uniformStride[i]
4911
+ // matrixStride: uniformStride[i],
4912
+ // rowMajor: uniformRowMajor[i]
4913
+ });
4914
+ }
4915
+ }
4916
+ const uniformInstancePrefixes = new Set(
4917
+ blockInfo.uniforms.map((uniform) => uniform.name.split(".")[0]).filter((instanceName) => Boolean(instanceName))
4918
+ );
4919
+ const blockAlias = blockInfo.name.replace(/Uniforms$/, "");
4920
+ if (uniformInstancePrefixes.size === 1 && !uniformInstancePrefixes.has(blockInfo.name) && !uniformInstancePrefixes.has(blockAlias)) {
4921
+ const [instanceName] = uniformInstancePrefixes;
4922
+ import_core16.log.warn(
4923
+ `Uniform block "${blockInfo.name}" uses GLSL instance "${instanceName}". luma.gl binds uniform buffers by block name ("${blockInfo.name}") and alias ("${blockAlias}"). Prefer matching the instance name to one of those to avoid confusing silent mismatches.`
4924
+ )();
3922
4925
  }
3923
4926
  uniformBlocks.push(blockInfo);
3924
4927
  }
@@ -3935,366 +4938,84 @@ ${source}`;
3935
4938
  }
3936
4939
  const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3937
4940
  const matches = UNIFORM_NAME_REGEXP.exec(name);
3938
- if (!matches || matches.length < 2) {
3939
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3940
- }
4941
+ const uniformName = (0, import_core16.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
3941
4942
  return {
3942
- name: matches[1],
3943
- length: matches[2] ? 1 : 0,
3944
- isArray: Boolean(matches[2])
4943
+ name: uniformName,
4944
+ // TODO - is this a bug, shouldn't we return the value?
4945
+ length: matches?.[2] ? 1 : 0,
4946
+ isArray: Boolean(matches?.[2])
3945
4947
  };
3946
4948
  }
3947
- var import_core14;
4949
+ var import_core16;
3948
4950
  var init_get_shader_layout_from_glsl = __esm({
3949
4951
  "src/adapter/helpers/get-shader-layout-from-glsl.ts"() {
3950
4952
  "use strict";
3951
- import_core14 = __toESM(require_core(), 1);
4953
+ import_core16 = __toESM(require_core(), 1);
3952
4954
  init_webgl_shadertypes();
3953
4955
  }
3954
- });
3955
-
3956
- // src/adapter/helpers/set-uniform.ts
3957
- function setUniform(gl, location, type, value) {
3958
- const gl2 = gl;
3959
- let uniformValue = value;
3960
- if (uniformValue === true) {
3961
- uniformValue = 1;
3962
- }
3963
- if (uniformValue === false) {
3964
- uniformValue = 0;
3965
- }
3966
- const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
3967
- switch (type) {
3968
- case 35678 /* SAMPLER_2D */:
3969
- case 35680 /* SAMPLER_CUBE */:
3970
- case 35679 /* SAMPLER_3D */:
3971
- case 35682 /* SAMPLER_2D_SHADOW */:
3972
- case 36289 /* SAMPLER_2D_ARRAY */:
3973
- case 36292 /* SAMPLER_2D_ARRAY_SHADOW */:
3974
- case 36293 /* SAMPLER_CUBE_SHADOW */:
3975
- case 36298 /* INT_SAMPLER_2D */:
3976
- case 36299 /* INT_SAMPLER_3D */:
3977
- case 36300 /* INT_SAMPLER_CUBE */:
3978
- case 36303 /* INT_SAMPLER_2D_ARRAY */:
3979
- case 36306 /* UNSIGNED_INT_SAMPLER_2D */:
3980
- case 36307 /* UNSIGNED_INT_SAMPLER_3D */:
3981
- case 36308 /* UNSIGNED_INT_SAMPLER_CUBE */:
3982
- case 36311 /* UNSIGNED_INT_SAMPLER_2D_ARRAY */:
3983
- if (typeof value !== "number") {
3984
- throw new Error("samplers must be set to integers");
3985
- }
3986
- return gl.uniform1i(location, value);
3987
- case 5126 /* FLOAT */:
3988
- return gl.uniform1fv(location, arrayValue);
3989
- case 35664 /* FLOAT_VEC2 */:
3990
- return gl.uniform2fv(location, arrayValue);
3991
- case 35665 /* FLOAT_VEC3 */:
3992
- return gl.uniform3fv(location, arrayValue);
3993
- case 35666 /* FLOAT_VEC4 */:
3994
- return gl.uniform4fv(location, arrayValue);
3995
- case 5124 /* INT */:
3996
- return gl.uniform1iv(location, arrayValue);
3997
- case 35667 /* INT_VEC2 */:
3998
- return gl.uniform2iv(location, arrayValue);
3999
- case 35668 /* INT_VEC3 */:
4000
- return gl.uniform3iv(location, arrayValue);
4001
- case 35669 /* INT_VEC4 */:
4002
- return gl.uniform4iv(location, arrayValue);
4003
- case 35670 /* BOOL */:
4004
- return gl.uniform1iv(location, arrayValue);
4005
- case 35671 /* BOOL_VEC2 */:
4006
- return gl.uniform2iv(location, arrayValue);
4007
- case 35672 /* BOOL_VEC3 */:
4008
- return gl.uniform3iv(location, arrayValue);
4009
- case 35673 /* BOOL_VEC4 */:
4010
- return gl.uniform4iv(location, arrayValue);
4011
- case 5125 /* UNSIGNED_INT */:
4012
- return gl2.uniform1uiv(location, arrayValue, 1);
4013
- case 36294 /* UNSIGNED_INT_VEC2 */:
4014
- return gl2.uniform2uiv(location, arrayValue, 2);
4015
- case 36295 /* UNSIGNED_INT_VEC3 */:
4016
- return gl2.uniform3uiv(location, arrayValue, 3);
4017
- case 36296 /* UNSIGNED_INT_VEC4 */:
4018
- return gl2.uniform4uiv(location, arrayValue, 4);
4019
- case 35674 /* FLOAT_MAT2 */:
4020
- return gl.uniformMatrix2fv(location, false, arrayValue);
4021
- case 35675 /* FLOAT_MAT3 */:
4022
- return gl.uniformMatrix3fv(location, false, arrayValue);
4023
- case 35676 /* FLOAT_MAT4 */:
4024
- return gl.uniformMatrix4fv(location, false, arrayValue);
4025
- case 35685 /* FLOAT_MAT2x3 */:
4026
- return gl2.uniformMatrix2x3fv(location, false, arrayValue);
4027
- case 35686 /* FLOAT_MAT2x4 */:
4028
- return gl2.uniformMatrix2x4fv(location, false, arrayValue);
4029
- case 35687 /* FLOAT_MAT3x2 */:
4030
- return gl2.uniformMatrix3x2fv(location, false, arrayValue);
4031
- case 35688 /* FLOAT_MAT3x4 */:
4032
- return gl2.uniformMatrix3x4fv(location, false, arrayValue);
4033
- case 35689 /* FLOAT_MAT4x2 */:
4034
- return gl2.uniformMatrix4x2fv(location, false, arrayValue);
4035
- case 35690 /* FLOAT_MAT4x3 */:
4036
- return gl2.uniformMatrix4x3fv(location, false, arrayValue);
4037
- }
4038
- throw new Error("Illegal uniform");
4039
- }
4040
- var init_set_uniform = __esm({
4041
- "src/adapter/helpers/set-uniform.ts"() {
4042
- "use strict";
4043
- }
4044
- });
4045
-
4046
- // src/adapter/helpers/webgl-topology-utils.ts
4047
- function getGLDrawMode(topology) {
4048
- switch (topology) {
4049
- case "point-list":
4050
- return 0 /* POINTS */;
4051
- case "line-list":
4052
- return 1 /* LINES */;
4053
- case "line-strip":
4054
- return 3 /* LINE_STRIP */;
4055
- case "triangle-list":
4056
- return 4 /* TRIANGLES */;
4057
- case "triangle-strip":
4058
- return 5 /* TRIANGLE_STRIP */;
4059
- default:
4060
- throw new Error(topology);
4061
- }
4062
- }
4063
- function getGLPrimitive(topology) {
4064
- switch (topology) {
4065
- case "point-list":
4066
- return 0 /* POINTS */;
4067
- case "line-list":
4068
- return 1 /* LINES */;
4069
- case "line-strip":
4070
- return 1 /* LINES */;
4071
- case "triangle-list":
4072
- return 4 /* TRIANGLES */;
4073
- case "triangle-strip":
4074
- return 4 /* TRIANGLES */;
4075
- default:
4076
- throw new Error(topology);
4077
- }
4078
- }
4079
- var init_webgl_topology_utils = __esm({
4080
- "src/adapter/helpers/webgl-topology-utils.ts"() {
4081
- "use strict";
4082
- }
4083
- });
4084
-
4085
- // src/adapter/resources/webgl-render-pipeline.ts
4086
- function mergeShaderLayout(baseLayout, overrideLayout) {
4087
- const mergedLayout = {
4088
- ...baseLayout,
4089
- attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
4090
- };
4091
- for (const attribute of overrideLayout?.attributes || []) {
4092
- const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
4093
- if (!baseAttribute) {
4094
- import_core15.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
4095
- } else {
4096
- baseAttribute.type = attribute.type || baseAttribute.type;
4097
- baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
4098
- }
4099
- }
4100
- return mergedLayout;
4101
- }
4102
- var import_core15, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
4103
- var init_webgl_render_pipeline = __esm({
4104
- "src/adapter/resources/webgl-render-pipeline.ts"() {
4956
+ });
4957
+
4958
+ // src/adapter/resources/webgl-shared-render-pipeline.ts
4959
+ var import_core17, LOG_PROGRAM_PERF_PRIORITY, WEBGLSharedRenderPipeline;
4960
+ var init_webgl_shared_render_pipeline = __esm({
4961
+ "src/adapter/resources/webgl-shared-render-pipeline.ts"() {
4105
4962
  "use strict";
4106
- import_core15 = __toESM(require_core(), 1);
4963
+ import_core17 = __toESM(require_core(), 1);
4107
4964
  init_get_shader_layout_from_glsl();
4108
- init_device_parameters();
4109
- init_set_uniform();
4110
- init_webgl_buffer();
4111
- init_webgl_framebuffer();
4112
- init_webgl_texture();
4113
- init_webgl_texture_view();
4114
- init_webgl_topology_utils();
4965
+ init_webgl_shadertypes();
4115
4966
  LOG_PROGRAM_PERF_PRIORITY = 4;
4116
- WEBGLRenderPipeline = class extends import_core15.RenderPipeline {
4117
- /** The WebGL device that created this render pipeline */
4967
+ WEBGLSharedRenderPipeline = class extends import_core17.SharedRenderPipeline {
4118
4968
  device;
4119
- /** Handle to underlying WebGL program */
4120
4969
  handle;
4121
- /** vertex shader */
4122
4970
  vs;
4123
- /** fragment shader */
4124
4971
  fs;
4125
- /** The layout extracted from shader by WebGL introspection APIs */
4126
- introspectedLayout;
4127
- /** Uniforms set on this model */
4128
- uniforms = {};
4129
- /** Bindings set on this model */
4130
- bindings = {};
4131
- /** WebGL varyings */
4132
- varyings = null;
4133
- _uniformCount = 0;
4134
- _uniformSetters = {};
4135
- // TODO are these used?
4136
- get [Symbol.toStringTag]() {
4137
- return "WEBGLRenderPipeline";
4138
- }
4972
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4973
+ linkStatus = "pending";
4139
4974
  constructor(device, props) {
4140
4975
  super(device, props);
4141
4976
  this.device = device;
4142
- this.handle = this.props.handle || this.device.gl.createProgram();
4143
- this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4977
+ this.handle = props.handle || this.device.gl.createProgram();
4144
4978
  this.vs = props.vs;
4145
4979
  this.fs = props.fs;
4146
- const { varyings, bufferMode = 35981 /* SEPARATE_ATTRIBS */ } = props;
4147
- if (varyings && varyings.length > 0) {
4148
- this.varyings = varyings;
4149
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4980
+ if (props.varyings && props.varyings.length > 0) {
4981
+ this.device.gl.transformFeedbackVaryings(
4982
+ this.handle,
4983
+ props.varyings,
4984
+ props.bufferMode || 35981 /* SEPARATE_ATTRIBS */
4985
+ );
4150
4986
  }
4151
4987
  this._linkShaders();
4152
- import_core15.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4988
+ import_core17.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4153
4989
  this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4154
- import_core15.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4155
- this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4990
+ import_core17.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4156
4991
  }
4157
4992
  destroy() {
4158
- if (this.handle) {
4159
- this.device.gl.useProgram(null);
4160
- this.device.gl.deleteProgram(this.handle);
4161
- this.destroyed = true;
4162
- this.handle.destroyed = true;
4163
- this.handle = null;
4164
- }
4165
- }
4166
- /**
4167
- * Bindings include: textures, samplers and uniform buffers
4168
- * @todo needed for portable model
4169
- */
4170
- setBindings(bindings, options) {
4171
- for (const [name, value] of Object.entries(bindings)) {
4172
- const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
4173
- if (!binding) {
4174
- const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
4175
- if (!options?.disableWarnings) {
4176
- import_core15.log.warn(
4177
- `No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`,
4178
- value
4179
- )();
4180
- }
4181
- continue;
4182
- }
4183
- if (!value) {
4184
- import_core15.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4185
- }
4186
- switch (binding.type) {
4187
- case "uniform":
4188
- if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
4189
- throw new Error("buffer value");
4190
- }
4191
- break;
4192
- case "texture":
4193
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4194
- throw new Error(`${this} Bad texture binding for ${name}`);
4195
- }
4196
- break;
4197
- case "sampler":
4198
- import_core15.log.warn(`Ignoring sampler ${name}`)();
4199
- break;
4200
- default:
4201
- throw new Error(binding.type);
4202
- }
4203
- this.bindings[name] = value;
4204
- }
4205
- }
4206
- /** @todo needed for portable model
4207
- * @note The WebGL API is offers many ways to draw things
4208
- * This function unifies those ways into a single call using common parameters with sane defaults
4209
- */
4210
- draw(options) {
4211
- const {
4212
- renderPass,
4213
- parameters = this.props.parameters,
4214
- topology = this.props.topology,
4215
- vertexArray,
4216
- vertexCount,
4217
- // indexCount,
4218
- instanceCount,
4219
- isInstanced = false,
4220
- firstVertex = 0,
4221
- // firstIndex,
4222
- // firstInstance,
4223
- // baseVertex,
4224
- transformFeedback
4225
- } = options;
4226
- const glDrawMode = getGLDrawMode(topology);
4227
- const isIndexed = Boolean(vertexArray.indexBuffer);
4228
- const glIndexType = vertexArray.indexBuffer?.glIndexType;
4229
- if (this.linkStatus !== "success") {
4230
- import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4231
- return false;
4232
- }
4233
- if (!this._areTexturesRenderable()) {
4234
- import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4235
- return false;
4236
- }
4237
- this.device.gl.useProgram(this.handle);
4238
- vertexArray.bindBeforeRender(renderPass);
4239
- if (transformFeedback) {
4240
- transformFeedback.begin(this.props.topology);
4993
+ if (this.destroyed) {
4994
+ return;
4241
4995
  }
4242
- this._applyBindings();
4243
- this._applyUniforms();
4244
- const webglRenderPass = renderPass;
4245
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4246
- if (isIndexed && isInstanced) {
4247
- this.device.gl.drawElementsInstanced(
4248
- glDrawMode,
4249
- vertexCount || 0,
4250
- // indexCount?
4251
- glIndexType,
4252
- firstVertex,
4253
- instanceCount || 0
4254
- );
4255
- } else if (isIndexed) {
4256
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4257
- } else if (isInstanced) {
4258
- this.device.gl.drawArraysInstanced(
4259
- glDrawMode,
4260
- firstVertex,
4261
- vertexCount || 0,
4262
- instanceCount || 0
4263
- );
4264
- } else {
4265
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4266
- }
4267
- if (transformFeedback) {
4268
- transformFeedback.end();
4269
- }
4270
- });
4271
- vertexArray.unbindAfterRender(renderPass);
4272
- return true;
4996
+ this.device.gl.useProgram(null);
4997
+ this.device.gl.deleteProgram(this.handle);
4998
+ this.handle.destroyed = true;
4999
+ this.destroyResource();
4273
5000
  }
4274
- // PRIVATE METHODS
4275
- // setAttributes(attributes: Record<string, Buffer>): void {}
4276
- // setBindings(bindings: Record<string, Binding>): void {}
4277
5001
  async _linkShaders() {
4278
5002
  const { gl } = this.device;
4279
5003
  gl.attachShader(this.handle, this.vs.handle);
4280
5004
  gl.attachShader(this.handle, this.fs.handle);
4281
- import_core15.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
5005
+ import_core17.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4282
5006
  gl.linkProgram(this.handle);
4283
- import_core15.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4284
- if (import_core15.log.level === 0) {
4285
- }
5007
+ import_core17.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4286
5008
  if (!this.device.features.has("compilation-status-async-webgl")) {
4287
5009
  const status2 = this._getLinkStatus();
4288
5010
  this._reportLinkStatus(status2);
4289
5011
  return;
4290
5012
  }
4291
- import_core15.log.once(1, "RenderPipeline linking is asynchronous")();
5013
+ import_core17.log.once(1, "RenderPipeline linking is asynchronous")();
4292
5014
  await this._waitForLinkComplete();
4293
- import_core15.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
5015
+ import_core17.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4294
5016
  const status = this._getLinkStatus();
4295
5017
  this._reportLinkStatus(status);
4296
5018
  }
4297
- /** Report link status. First, check for shader compilation failures if linking fails */
4298
5019
  async _reportLinkStatus(status) {
4299
5020
  switch (status) {
4300
5021
  case "success":
@@ -4316,152 +5037,82 @@ ${source}`;
4316
5037
  case "error":
4317
5038
  this.fs.debugShader();
4318
5039
  throw new Error(`${this} ${errorType} during compilation of ${this.fs}`);
4319
- case "pending":
4320
- await this.fs.asyncCompilationStatus;
4321
- this.fs.debugShader();
4322
- break;
4323
- case "success":
4324
- break;
4325
- }
4326
- const linkErrorLog = this.device.gl.getProgramInfoLog(this.handle);
4327
- this.device.reportError(
4328
- new Error(`${errorType} during ${status}: ${linkErrorLog}`),
4329
- this
4330
- )();
4331
- this.device.debug();
4332
- }
4333
- }
4334
- /**
4335
- * Get the shader compilation status
4336
- * TODO - Load log even when no error reported, to catch warnings?
4337
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4338
- */
4339
- _getLinkStatus() {
4340
- const { gl } = this.device;
4341
- const linked = gl.getProgramParameter(this.handle, 35714 /* LINK_STATUS */);
4342
- if (!linked) {
4343
- this.linkStatus = "error";
4344
- return "link-error";
4345
- }
4346
- gl.validateProgram(this.handle);
4347
- const validated = gl.getProgramParameter(this.handle, 35715 /* VALIDATE_STATUS */);
4348
- if (!validated) {
4349
- this.linkStatus = "error";
4350
- return "validation-error";
4351
- }
4352
- this.linkStatus = "success";
4353
- return "success";
4354
- }
4355
- /** Use KHR_parallel_shader_compile extension if available */
4356
- async _waitForLinkComplete() {
4357
- const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4358
- const DELAY_MS = 10;
4359
- if (!this.device.features.has("compilation-status-async-webgl")) {
4360
- await waitMs(DELAY_MS);
4361
- return;
4362
- }
4363
- const { gl } = this.device;
4364
- for (; ; ) {
4365
- const complete = gl.getProgramParameter(this.handle, 37297 /* COMPLETION_STATUS_KHR */);
4366
- if (complete) {
4367
- return;
4368
- }
4369
- await waitMs(DELAY_MS);
4370
- }
4371
- }
4372
- /**
4373
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4374
- * Update a texture if needed (e.g. from video)
4375
- * Note: This is currently done before every draw call
4376
- */
4377
- _areTexturesRenderable() {
4378
- let texturesRenderable = true;
4379
- for (const bindingInfo of this.shaderLayout.bindings) {
4380
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4381
- import_core15.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4382
- texturesRenderable = false;
4383
- }
4384
- }
4385
- return texturesRenderable;
4386
- }
4387
- /** Apply any bindings (before each draw call) */
4388
- _applyBindings() {
4389
- if (this.linkStatus !== "success") {
4390
- return;
4391
- }
4392
- const { gl } = this.device;
4393
- gl.useProgram(this.handle);
4394
- let textureUnit = 0;
4395
- let uniformBufferIndex = 0;
4396
- for (const binding of this.shaderLayout.bindings) {
4397
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4398
- if (!value) {
4399
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4400
- }
4401
- switch (binding.type) {
4402
- case "uniform":
4403
- const { name } = binding;
4404
- const location = gl.getUniformBlockIndex(this.handle, name);
4405
- if (location === 4294967295 /* INVALID_INDEX */) {
4406
- throw new Error(`Invalid uniform block name ${name}`);
4407
- }
4408
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
4409
- if (value instanceof WEBGLBuffer) {
4410
- gl.bindBufferBase(35345 /* UNIFORM_BUFFER */, uniformBufferIndex, value.handle);
4411
- } else {
4412
- gl.bindBufferRange(
4413
- 35345 /* UNIFORM_BUFFER */,
4414
- uniformBufferIndex,
4415
- // @ts-expect-error
4416
- value.buffer.handle,
4417
- // @ts-expect-error
4418
- value.offset || 0,
4419
- // @ts-expect-error
4420
- value.size || value.buffer.byteLength - value.offset
4421
- );
4422
- }
4423
- uniformBufferIndex += 1;
4424
- break;
4425
- case "texture":
4426
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4427
- throw new Error("texture");
4428
- }
4429
- let texture;
4430
- if (value instanceof WEBGLTextureView) {
4431
- texture = value.texture;
4432
- } else if (value instanceof WEBGLTexture) {
4433
- texture = value;
4434
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4435
- import_core15.log.warn(
4436
- "Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead"
4437
- )();
4438
- texture = value.colorAttachments[0].texture;
4439
- } else {
4440
- throw new Error("No texture");
4441
- }
4442
- gl.activeTexture(33984 /* TEXTURE0 */ + textureUnit);
4443
- gl.bindTexture(texture.glTarget, texture.handle);
4444
- textureUnit += 1;
4445
- break;
4446
- case "sampler":
4447
- break;
4448
- case "storage":
4449
- case "read-only-storage":
4450
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
5040
+ case "pending":
5041
+ await this.fs.asyncCompilationStatus;
5042
+ this.fs.debugShader();
5043
+ break;
5044
+ case "success":
5045
+ break;
5046
+ }
5047
+ const linkErrorLog = this.device.gl.getProgramInfoLog(this.handle);
5048
+ this.device.reportError(
5049
+ new Error(`${errorType} during ${status}: ${linkErrorLog}`),
5050
+ this
5051
+ )();
5052
+ this.device.debug();
5053
+ }
5054
+ }
5055
+ _getLinkStatus() {
5056
+ const { gl } = this.device;
5057
+ const linked = gl.getProgramParameter(this.handle, 35714 /* LINK_STATUS */);
5058
+ if (!linked) {
5059
+ this.linkStatus = "error";
5060
+ return "link-error";
5061
+ }
5062
+ this._initializeSamplerUniforms();
5063
+ gl.validateProgram(this.handle);
5064
+ const validated = gl.getProgramParameter(this.handle, 35715 /* VALIDATE_STATUS */);
5065
+ if (!validated) {
5066
+ this.linkStatus = "error";
5067
+ return "validation-error";
5068
+ }
5069
+ this.linkStatus = "success";
5070
+ return "success";
5071
+ }
5072
+ _initializeSamplerUniforms() {
5073
+ const { gl } = this.device;
5074
+ gl.useProgram(this.handle);
5075
+ let textureUnit = 0;
5076
+ const uniformCount = gl.getProgramParameter(this.handle, 35718 /* ACTIVE_UNIFORMS */);
5077
+ for (let uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) {
5078
+ const activeInfo = gl.getActiveUniform(this.handle, uniformIndex);
5079
+ if (activeInfo && isGLSamplerType(activeInfo.type)) {
5080
+ const isArray3 = activeInfo.name.endsWith("[0]");
5081
+ const uniformName = isArray3 ? activeInfo.name.slice(0, -3) : activeInfo.name;
5082
+ const location = gl.getUniformLocation(this.handle, uniformName);
5083
+ if (location !== null) {
5084
+ textureUnit = this._assignSamplerUniform(location, activeInfo, isArray3, textureUnit);
5085
+ }
4451
5086
  }
4452
5087
  }
4453
5088
  }
4454
- /**
4455
- * Due to program sharing, uniforms need to be reset before every draw call
4456
- * (though caching will avoid redundant WebGL calls)
4457
- */
4458
- _applyUniforms() {
4459
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4460
- const { name, location, type, textureUnit } = uniformLayout;
4461
- const value = this.uniforms[name] ?? textureUnit;
4462
- if (value !== void 0) {
4463
- setUniform(this.device.gl, location, type, value);
5089
+ _assignSamplerUniform(location, activeInfo, isArray3, textureUnit) {
5090
+ const { gl } = this.device;
5091
+ if (isArray3 && activeInfo.size > 1) {
5092
+ const textureUnits = Int32Array.from(
5093
+ { length: activeInfo.size },
5094
+ (_, arrayIndex) => textureUnit + arrayIndex
5095
+ );
5096
+ gl.uniform1iv(location, textureUnits);
5097
+ return textureUnit + activeInfo.size;
5098
+ }
5099
+ gl.uniform1i(location, textureUnit);
5100
+ return textureUnit + 1;
5101
+ }
5102
+ async _waitForLinkComplete() {
5103
+ const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
5104
+ const DELAY_MS = 10;
5105
+ if (!this.device.features.has("compilation-status-async-webgl")) {
5106
+ await waitMs(DELAY_MS);
5107
+ return;
5108
+ }
5109
+ const { gl } = this.device;
5110
+ for (; ; ) {
5111
+ const complete = gl.getProgramParameter(this.handle, 37297 /* COMPLETION_STATUS_KHR */);
5112
+ if (complete) {
5113
+ return;
4464
5114
  }
5115
+ await waitMs(DELAY_MS);
4465
5116
  }
4466
5117
  }
4467
5118
  };
@@ -4484,44 +5135,44 @@ ${source}`;
4484
5135
  device.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, null);
4485
5136
  device.gl.bindBuffer(36663 /* COPY_WRITE_BUFFER */, null);
4486
5137
  }
4487
- function _copyBufferToTexture(device, options) {
4488
- throw new Error("Not implemented");
5138
+ function _copyBufferToTexture(_device, _options) {
5139
+ throw new Error("copyBufferToTexture is not supported in WebGL");
4489
5140
  }
4490
5141
  function _copyTextureToBuffer(device, options) {
4491
5142
  const {
4492
- /** Texture to copy to/from. */
4493
5143
  sourceTexture,
4494
- /** Mip-map level of the texture to copy to/from. (Default 0) */
4495
5144
  mipLevel = 0,
4496
- /** Defines which aspects of the texture to copy to/from. */
4497
5145
  aspect = "all",
4498
- /** Width to copy */
4499
5146
  width = options.sourceTexture.width,
4500
- /** Height to copy */
4501
5147
  height = options.sourceTexture.height,
4502
- depthOrArrayLayers = 0,
4503
- /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
4504
- origin = [0, 0],
4505
- /** Destination buffer */
5148
+ depthOrArrayLayers,
5149
+ origin = [0, 0, 0],
4506
5150
  destinationBuffer,
4507
- /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
4508
5151
  byteOffset = 0,
4509
- /**
4510
- * The stride, in bytes, between the beginning of each block row and the subsequent block row.
4511
- * Required if there are multiple block rows (i.e. the copy height or depth is more than one block).
4512
- */
4513
5152
  bytesPerRow,
4514
- /**
4515
- * Number of block rows per single image of the texture.
4516
- * rowsPerImage &times; bytesPerRow is the stride, in bytes, between the beginning of each image of data and the subsequent image.
4517
- * Required if there are multiple images (i.e. the copy depth is more than one).
4518
- */
4519
5153
  rowsPerImage
4520
5154
  } = options;
5155
+ if (sourceTexture instanceof import_core18.Texture) {
5156
+ sourceTexture.readBuffer(
5157
+ {
5158
+ x: origin[0] ?? 0,
5159
+ y: origin[1] ?? 0,
5160
+ z: origin[2] ?? 0,
5161
+ width,
5162
+ height,
5163
+ depthOrArrayLayers,
5164
+ mipLevel,
5165
+ aspect,
5166
+ byteOffset
5167
+ },
5168
+ destinationBuffer
5169
+ );
5170
+ return;
5171
+ }
4521
5172
  if (aspect !== "all") {
4522
5173
  throw new Error("aspect not supported in WebGL");
4523
5174
  }
4524
- if (mipLevel !== 0 || depthOrArrayLayers !== 0 || bytesPerRow || rowsPerImage) {
5175
+ if (mipLevel !== 0 || depthOrArrayLayers !== void 0 || bytesPerRow || rowsPerImage) {
4525
5176
  throw new Error("not implemented");
4526
5177
  }
4527
5178
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
@@ -4530,9 +5181,8 @@ ${source}`;
4530
5181
  const webglBuffer = destinationBuffer;
4531
5182
  const sourceWidth = width || framebuffer.width;
4532
5183
  const sourceHeight = height || framebuffer.height;
4533
- const sourceParams = getTextureFormatWebGL(
4534
- framebuffer.colorAttachments[0].texture.props.format
4535
- );
5184
+ const colorAttachment0 = (0, import_core18.assertDefined)(framebuffer.colorAttachments[0]);
5185
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
4536
5186
  const sourceFormat = sourceParams.format;
4537
5187
  const sourceType = sourceParams.type;
4538
5188
  device.gl.bindBuffer(35051 /* PIXEL_PACK_BUFFER */, webglBuffer.handle);
@@ -4567,7 +5217,7 @@ ${source}`;
4567
5217
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
4568
5218
  origin = [0, 0],
4569
5219
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
4570
- destinationOrigin = [0, 0],
5220
+ destinationOrigin = [0, 0, 0],
4571
5221
  /** Texture to copy to/from. */
4572
5222
  destinationTexture
4573
5223
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -4583,7 +5233,7 @@ ${source}`;
4583
5233
  // depthOrArrayLayers = 0
4584
5234
  } = options;
4585
5235
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
4586
- const [sourceX, sourceY] = origin;
5236
+ const [sourceX = 0, sourceY = 0] = origin;
4587
5237
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
4588
5238
  const prevHandle = device.gl.bindFramebuffer(
4589
5239
  36160 /* FRAMEBUFFER */,
@@ -4639,7 +5289,7 @@ ${source}`;
4639
5289
  }
4640
5290
  }
4641
5291
  function getFramebuffer(source) {
4642
- if (source instanceof import_core16.Texture) {
5292
+ if (source instanceof import_core18.Texture) {
4643
5293
  const { width, height, id } = source;
4644
5294
  const framebuffer = source.device.createFramebuffer({
4645
5295
  id: `framebuffer-for-${id}`,
@@ -4651,19 +5301,19 @@ ${source}`;
4651
5301
  }
4652
5302
  return { framebuffer: source, destroyFramebuffer: false };
4653
5303
  }
4654
- var import_core16, WEBGLCommandBuffer;
5304
+ var import_core18, WEBGLCommandBuffer;
4655
5305
  var init_webgl_command_buffer = __esm({
4656
5306
  "src/adapter/resources/webgl-command-buffer.ts"() {
4657
5307
  "use strict";
4658
- import_core16 = __toESM(require_core(), 1);
4659
- init_webgl_texture();
5308
+ import_core18 = __toESM(require_core(), 1);
4660
5309
  init_webgl_texture_table();
4661
- WEBGLCommandBuffer = class extends import_core16.CommandBuffer {
5310
+ init_webgl_texture();
5311
+ WEBGLCommandBuffer = class extends import_core18.CommandBuffer {
4662
5312
  device;
4663
5313
  handle = null;
4664
5314
  commands = [];
4665
- constructor(device) {
4666
- super(device, {});
5315
+ constructor(device, props = {}) {
5316
+ super(device, props);
4667
5317
  this.device = device;
4668
5318
  }
4669
5319
  _executeCommands(commands = this.commands) {
@@ -4691,15 +5341,15 @@ ${source}`;
4691
5341
  });
4692
5342
 
4693
5343
  // src/adapter/resources/webgl-render-pass.ts
4694
- var import_core17, COLOR_CHANNELS, WEBGLRenderPass;
5344
+ var import_core19, COLOR_CHANNELS, WEBGLRenderPass;
4695
5345
  var init_webgl_render_pass = __esm({
4696
5346
  "src/adapter/resources/webgl-render-pass.ts"() {
4697
5347
  "use strict";
4698
- import_core17 = __toESM(require_core(), 1);
5348
+ import_core19 = __toESM(require_core(), 1);
4699
5349
  init_with_parameters();
4700
5350
  init_unified_parameter_api();
4701
5351
  COLOR_CHANNELS = [1, 2, 4, 8];
4702
- WEBGLRenderPass = class extends import_core17.RenderPass {
5352
+ WEBGLRenderPass = class extends import_core19.RenderPass {
4703
5353
  device;
4704
5354
  handle = null;
4705
5355
  /** Parameters that should be applied before each draw call */
@@ -4707,10 +5357,15 @@ ${source}`;
4707
5357
  constructor(device, props) {
4708
5358
  super(device, props);
4709
5359
  this.device = device;
5360
+ const webglFramebuffer = this.props.framebuffer;
5361
+ const isDefaultFramebuffer = !webglFramebuffer || webglFramebuffer.handle === null;
5362
+ if (isDefaultFramebuffer) {
5363
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
5364
+ }
4710
5365
  let viewport;
4711
5366
  if (!props?.parameters?.viewport) {
4712
- if (props?.framebuffer) {
4713
- const { width, height } = props.framebuffer;
5367
+ if (!isDefaultFramebuffer) {
5368
+ const { width, height } = webglFramebuffer;
4714
5369
  viewport = [0, 0, width, height];
4715
5370
  } else {
4716
5371
  const [width, height] = device.getDefaultCanvasContext().getDrawingBufferSize();
@@ -4719,19 +5374,28 @@ ${source}`;
4719
5374
  }
4720
5375
  this.device.pushState();
4721
5376
  this.setParameters({ viewport, ...this.props.parameters });
4722
- const webglFramebuffer = this.props.framebuffer;
4723
- if (this.props.framebuffer && webglFramebuffer?.handle) {
4724
- const drawBuffers = this.props.framebuffer.colorAttachments.map(
4725
- (_, i) => 36064 /* COLOR_ATTACHMENT0 */ + i
4726
- );
5377
+ if (!isDefaultFramebuffer) {
5378
+ const drawBuffers = webglFramebuffer.colorAttachments.map((_, i) => 36064 /* COLOR_ATTACHMENT0 */ + i);
4727
5379
  this.device.gl.drawBuffers(drawBuffers);
4728
5380
  } else {
4729
5381
  this.device.gl.drawBuffers([1029 /* BACK */]);
4730
5382
  }
4731
5383
  this.clear();
5384
+ if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== void 0) {
5385
+ const webglQuerySet = this.props.timestampQuerySet;
5386
+ webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
5387
+ }
4732
5388
  }
4733
5389
  end() {
5390
+ if (this.destroyed) {
5391
+ return;
5392
+ }
5393
+ if (this.props.timestampQuerySet && this.props.endTimestampIndex !== void 0) {
5394
+ const webglQuerySet = this.props.timestampQuerySet;
5395
+ webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
5396
+ }
4734
5397
  this.device.popState();
5398
+ this.destroy();
4735
5399
  }
4736
5400
  pushDebugGroup(groupLabel) {
4737
5401
  }
@@ -4771,9 +5435,9 @@ ${source}`;
4771
5435
  if (parameters.blendConstant) {
4772
5436
  glParameters.blendColor = parameters.blendConstant;
4773
5437
  }
4774
- if (parameters.stencilReference) {
4775
- console.warn("RenderPassParameters.stencilReference not yet implemented in WebGL");
5438
+ if (parameters.stencilReference !== void 0) {
4776
5439
  glParameters[2967 /* STENCIL_REF */] = parameters.stencilReference;
5440
+ glParameters[36003 /* STENCIL_BACK_REF */] = parameters.stencilReference;
4777
5441
  }
4778
5442
  if ("colorMask" in parameters) {
4779
5443
  glParameters.colorMask = COLOR_CHANNELS.map(
@@ -4873,31 +5537,39 @@ ${source}`;
4873
5537
  });
4874
5538
 
4875
5539
  // src/adapter/resources/webgl-command-encoder.ts
4876
- var import_core18, WEBGLCommandEncoder;
5540
+ var import_core20, WEBGLCommandEncoder;
4877
5541
  var init_webgl_command_encoder = __esm({
4878
5542
  "src/adapter/resources/webgl-command-encoder.ts"() {
4879
5543
  "use strict";
4880
- import_core18 = __toESM(require_core(), 1);
5544
+ import_core20 = __toESM(require_core(), 1);
4881
5545
  init_webgl_command_buffer();
4882
5546
  init_webgl_render_pass();
4883
- WEBGLCommandEncoder = class extends import_core18.CommandEncoder {
5547
+ WEBGLCommandEncoder = class extends import_core20.CommandEncoder {
4884
5548
  device;
4885
5549
  handle = null;
4886
5550
  commandBuffer;
4887
5551
  constructor(device, props) {
4888
5552
  super(device, props);
4889
5553
  this.device = device;
4890
- this.commandBuffer = new WEBGLCommandBuffer(device);
5554
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5555
+ id: `${this.props.id}-command-buffer`
5556
+ });
4891
5557
  }
4892
5558
  destroy() {
5559
+ this.destroyResource();
4893
5560
  }
4894
- finish() {
5561
+ finish(props) {
5562
+ if (props?.id && this.commandBuffer.id !== props.id) {
5563
+ this.commandBuffer.id = props.id;
5564
+ this.commandBuffer.props.id = props.id;
5565
+ }
5566
+ this.destroy();
4895
5567
  return this.commandBuffer;
4896
5568
  }
4897
- beginRenderPass(props) {
4898
- return new WEBGLRenderPass(this.device, props);
5569
+ beginRenderPass(props = {}) {
5570
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4899
5571
  }
4900
- beginComputePass(props) {
5572
+ beginComputePass(props = {}) {
4901
5573
  throw new Error("ComputePass not supported in WebGL");
4902
5574
  }
4903
5575
  copyBufferToBuffer(options) {
@@ -4921,7 +5593,12 @@ ${source}`;
4921
5593
  }
4922
5594
  insertDebugMarker(markerLabel) {
4923
5595
  }
4924
- resolveQuerySet(querySet, destination, options) {
5596
+ resolveQuerySet(_querySet, _destination, _options) {
5597
+ throw new Error("resolveQuerySet is not supported in WebGL");
5598
+ }
5599
+ writeTimestamp(querySet, queryIndex) {
5600
+ const webglQuerySet = querySet;
5601
+ webglQuerySet.writeTimestamp(queryIndex);
4925
5602
  }
4926
5603
  };
4927
5604
  }
@@ -4934,7 +5611,7 @@ ${source}`;
4934
5611
  const total = count * length;
4935
5612
  let copied = 0;
4936
5613
  for (let i = start; copied < length; copied++) {
4937
- target2[i++] = source[copied];
5614
+ target2[i++] = source[copied] ?? 0;
4938
5615
  }
4939
5616
  while (copied < total) {
4940
5617
  if (copied < total - copied) {
@@ -4971,15 +5648,15 @@ ${source}`;
4971
5648
  }
4972
5649
  return true;
4973
5650
  }
4974
- var import_core19, WEBGLVertexArray;
5651
+ var import_core21, WEBGLVertexArray;
4975
5652
  var init_webgl_vertex_array = __esm({
4976
5653
  "src/adapter/resources/webgl-vertex-array.ts"() {
4977
5654
  "use strict";
4978
- import_core19 = __toESM(require_core(), 1);
5655
+ import_core21 = __toESM(require_core(), 1);
4979
5656
  init_dist();
4980
5657
  init_webgl_vertex_formats();
4981
5658
  init_fill_array();
4982
- WEBGLVertexArray = class extends import_core19.VertexArray {
5659
+ WEBGLVertexArray = class extends import_core21.VertexArray {
4983
5660
  get [Symbol.toStringTag]() {
4984
5661
  return "VertexArray";
4985
5662
  }
@@ -5147,7 +5824,7 @@ ${source}`;
5147
5824
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
5148
5825
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
5149
5826
  if (updateNeeded) {
5150
- const typedArray = (0, import_core19.getScratchArray)(value.constructor, length);
5827
+ const typedArray = (0, import_core21.getScratchArray)(value.constructor, length);
5151
5828
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
5152
5829
  this.buffer.write(typedArray);
5153
5830
  this.bufferValue = value;
@@ -5165,14 +5842,14 @@ ${source}`;
5165
5842
  }
5166
5843
  return /^\d+$/.test(value);
5167
5844
  }
5168
- var import_core20, WEBGLTransformFeedback;
5845
+ var import_core22, WEBGLTransformFeedback;
5169
5846
  var init_webgl_transform_feedback = __esm({
5170
5847
  "src/adapter/resources/webgl-transform-feedback.ts"() {
5171
5848
  "use strict";
5172
- import_core20 = __toESM(require_core(), 1);
5173
- init_src2();
5849
+ import_core22 = __toESM(require_core(), 1);
5850
+ init_src();
5174
5851
  init_webgl_topology_utils();
5175
- WEBGLTransformFeedback = class extends import_core20.TransformFeedback {
5852
+ WEBGLTransformFeedback = class extends import_core22.TransformFeedback {
5176
5853
  device;
5177
5854
  gl;
5178
5855
  handle;
@@ -5225,8 +5902,8 @@ ${source}`;
5225
5902
  this.buffers = {};
5226
5903
  this.unusedBuffers = {};
5227
5904
  this.bind(() => {
5228
- for (const bufferName in buffers) {
5229
- this.setBuffer(bufferName, buffers[bufferName]);
5905
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
5906
+ this.setBuffer(bufferName, buffer);
5230
5907
  }
5231
5908
  });
5232
5909
  }
@@ -5235,7 +5912,7 @@ ${source}`;
5235
5912
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
5236
5913
  if (location < 0) {
5237
5914
  this.unusedBuffers[locationOrName] = buffer;
5238
- import_core20.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5915
+ import_core22.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5239
5916
  return;
5240
5917
  }
5241
5918
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -5248,7 +5925,7 @@ ${source}`;
5248
5925
  return this.buffers[locationOrName] || null;
5249
5926
  }
5250
5927
  const location = this._getVaryingIndex(locationOrName);
5251
- return location >= 0 ? this.buffers[location] : null;
5928
+ return this.buffers[location] ?? null;
5252
5929
  }
5253
5930
  bind(funcOrHandle = this.handle) {
5254
5931
  if (typeof funcOrHandle !== "function") {
@@ -5295,8 +5972,8 @@ ${source}`;
5295
5972
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
5296
5973
  */
5297
5974
  _bindBuffers() {
5298
- for (const bufferIndex in this.buffers) {
5299
- const { buffer, byteLength, byteOffset } = this._getBufferRange(this.buffers[bufferIndex]);
5975
+ for (const [bufferIndex, bufferEntry] of Object.entries(this.buffers)) {
5976
+ const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferEntry);
5300
5977
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
5301
5978
  }
5302
5979
  }
@@ -5318,144 +5995,343 @@ ${source}`;
5318
5995
  });
5319
5996
 
5320
5997
  // src/adapter/resources/webgl-query-set.ts
5321
- var import_core21, WEBGLQuerySet;
5998
+ var import_core23, WEBGLQuerySet;
5322
5999
  var init_webgl_query_set = __esm({
5323
6000
  "src/adapter/resources/webgl-query-set.ts"() {
5324
6001
  "use strict";
5325
- import_core21 = __toESM(require_core(), 1);
5326
- WEBGLQuerySet = class extends import_core21.QuerySet {
6002
+ import_core23 = __toESM(require_core(), 1);
6003
+ WEBGLQuerySet = class extends import_core23.QuerySet {
5327
6004
  device;
5328
6005
  handle;
5329
- target = null;
5330
- _queryPending = false;
5331
- _pollingPromise = null;
6006
+ _timestampPairs = [];
6007
+ _pendingReads = /* @__PURE__ */ new Set();
6008
+ _occlusionQuery = null;
6009
+ _occlusionActive = false;
5332
6010
  get [Symbol.toStringTag]() {
5333
- return "Query";
6011
+ return "QuerySet";
5334
6012
  }
5335
- // Create a query class
5336
6013
  constructor(device, props) {
5337
6014
  super(device, props);
5338
6015
  this.device = device;
5339
- if (props.count > 1) {
5340
- throw new Error("WebGL QuerySet can only have one value");
5341
- }
5342
- const handle = this.device.gl.createQuery();
5343
- if (!handle) {
5344
- throw new Error("WebGL query not supported");
6016
+ if (props.type === "timestamp") {
6017
+ if (props.count < 2) {
6018
+ throw new Error("Timestamp QuerySet requires at least two query slots");
6019
+ }
6020
+ this._timestampPairs = new Array(Math.ceil(props.count / 2)).fill(null).map(() => ({ activeQuery: null, completedQueries: [] }));
6021
+ this.handle = null;
6022
+ } else {
6023
+ if (props.count > 1) {
6024
+ throw new Error("WebGL occlusion QuerySet can only have one value");
6025
+ }
6026
+ const handle = this.device.gl.createQuery();
6027
+ if (!handle) {
6028
+ throw new Error("WebGL query not supported");
6029
+ }
6030
+ this.handle = handle;
5345
6031
  }
5346
- this.handle = handle;
5347
6032
  Object.seal(this);
5348
6033
  }
5349
6034
  destroy() {
5350
- this.device.gl.deleteQuery(this.handle);
6035
+ if (this.destroyed) {
6036
+ return;
6037
+ }
6038
+ if (this.handle) {
6039
+ this.device.gl.deleteQuery(this.handle);
6040
+ }
6041
+ for (const pair of this._timestampPairs) {
6042
+ if (pair.activeQuery) {
6043
+ this._cancelPendingQuery(pair.activeQuery);
6044
+ this.device.gl.deleteQuery(pair.activeQuery.handle);
6045
+ }
6046
+ for (const query of pair.completedQueries) {
6047
+ this._cancelPendingQuery(query);
6048
+ this.device.gl.deleteQuery(query.handle);
6049
+ }
6050
+ }
6051
+ if (this._occlusionQuery) {
6052
+ this._cancelPendingQuery(this._occlusionQuery);
6053
+ this.device.gl.deleteQuery(this._occlusionQuery.handle);
6054
+ }
6055
+ for (const query of Array.from(this._pendingReads)) {
6056
+ this._cancelPendingQuery(query);
6057
+ }
6058
+ this.destroyResource();
5351
6059
  }
5352
- // FOR RENDER PASS AND COMMAND ENCODER
5353
- /**
5354
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
5355
- * Measures GPU time delta between this call and a matching `end` call in the
5356
- * GPU instruction stream.
5357
- */
5358
- beginTimestampQuery() {
5359
- return this._begin(35007 /* TIME_ELAPSED_EXT */);
6060
+ isResultAvailable(queryIndex) {
6061
+ if (this.props.type === "timestamp") {
6062
+ if (queryIndex === void 0) {
6063
+ return this._timestampPairs.some(
6064
+ (_, pairIndex) => this._isTimestampPairAvailable(pairIndex)
6065
+ );
6066
+ }
6067
+ return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
6068
+ }
6069
+ if (!this._occlusionQuery) {
6070
+ return false;
6071
+ }
6072
+ return this._pollQueryAvailability(this._occlusionQuery);
6073
+ }
6074
+ async readResults(options) {
6075
+ const firstQuery = options?.firstQuery || 0;
6076
+ const queryCount = options?.queryCount || this.props.count - firstQuery;
6077
+ this._validateRange(firstQuery, queryCount);
6078
+ if (this.props.type === "timestamp") {
6079
+ const results = new Array(queryCount).fill(0n);
6080
+ const startPairIndex = Math.floor(firstQuery / 2);
6081
+ const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
6082
+ for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
6083
+ const duration = await this._consumeTimestampPairResult(pairIndex);
6084
+ const beginSlot = pairIndex * 2;
6085
+ const endSlot = beginSlot + 1;
6086
+ if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
6087
+ results[beginSlot - firstQuery] = 0n;
6088
+ }
6089
+ if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
6090
+ results[endSlot - firstQuery] = duration;
6091
+ }
6092
+ }
6093
+ return results;
6094
+ }
6095
+ if (!this._occlusionQuery) {
6096
+ throw new Error("Occlusion query has not been started");
6097
+ }
6098
+ return [await this._consumeQueryResult(this._occlusionQuery)];
5360
6099
  }
5361
- endTimestampQuery() {
5362
- this._end();
6100
+ async readTimestampDuration(beginIndex, endIndex) {
6101
+ if (this.props.type !== "timestamp") {
6102
+ throw new Error("Timestamp durations require a timestamp QuerySet");
6103
+ }
6104
+ if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
6105
+ throw new Error("Timestamp duration range is out of bounds");
6106
+ }
6107
+ if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
6108
+ throw new Error("WebGL timestamp durations require adjacent even/odd query indices");
6109
+ }
6110
+ const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
6111
+ return Number(result) / 1e6;
5363
6112
  }
5364
- // Shortcut for occlusion queries
5365
- beginOcclusionQuery(options) {
5366
- return this._begin(
5367
- options?.conservative ? 36202 /* ANY_SAMPLES_PASSED_CONSERVATIVE */ : 35887 /* ANY_SAMPLES_PASSED */
5368
- );
6113
+ beginOcclusionQuery() {
6114
+ if (this.props.type !== "occlusion") {
6115
+ throw new Error("Occlusion queries require an occlusion QuerySet");
6116
+ }
6117
+ if (!this.handle) {
6118
+ throw new Error("WebGL occlusion query is not available");
6119
+ }
6120
+ if (this._occlusionActive) {
6121
+ throw new Error("Occlusion query is already active");
6122
+ }
6123
+ this.device.gl.beginQuery(35887 /* ANY_SAMPLES_PASSED */, this.handle);
6124
+ this._occlusionQuery = {
6125
+ handle: this.handle,
6126
+ promise: null,
6127
+ result: null,
6128
+ disjoint: false,
6129
+ cancelled: false,
6130
+ pollRequestId: null,
6131
+ resolve: null,
6132
+ reject: null
6133
+ };
6134
+ this._occlusionActive = true;
5369
6135
  }
5370
6136
  endOcclusionQuery() {
5371
- this._end();
5372
- }
5373
- // Shortcut for transformFeedbackQuery
5374
- beginTransformFeedbackQuery() {
5375
- return this._begin(35976 /* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN */);
5376
- }
5377
- endTransformFeedbackQuery() {
5378
- this._end();
5379
- }
5380
- async resolveQuery() {
5381
- const value = await this.pollQuery();
5382
- return [value];
6137
+ if (!this._occlusionActive) {
6138
+ throw new Error("Occlusion query is not active");
6139
+ }
6140
+ this.device.gl.endQuery(35887 /* ANY_SAMPLES_PASSED */);
6141
+ this._occlusionActive = false;
5383
6142
  }
5384
- // PRIVATE METHODS
5385
- /**
5386
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5387
- * instance, `end()` must be called on that same instance before
5388
- * calling `begin()` on another query. While there can be multiple
5389
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5390
- * It is not possible to interleave or overlap `begin` and `end` calls.
5391
- */
5392
- _begin(target2) {
5393
- if (this._queryPending) {
6143
+ writeTimestamp(queryIndex) {
6144
+ if (this.props.type !== "timestamp") {
6145
+ throw new Error("Timestamp writes require a timestamp QuerySet");
6146
+ }
6147
+ const pairIndex = this._getTimestampPairIndex(queryIndex);
6148
+ const pair = this._timestampPairs[pairIndex];
6149
+ if (queryIndex % 2 === 0) {
6150
+ if (pair.activeQuery) {
6151
+ throw new Error("Timestamp query pair is already active");
6152
+ }
6153
+ const handle = this.device.gl.createQuery();
6154
+ if (!handle) {
6155
+ throw new Error("WebGL query not supported");
6156
+ }
6157
+ const query = {
6158
+ handle,
6159
+ promise: null,
6160
+ result: null,
6161
+ disjoint: false,
6162
+ cancelled: false,
6163
+ pollRequestId: null,
6164
+ resolve: null,
6165
+ reject: null
6166
+ };
6167
+ this.device.gl.beginQuery(35007 /* TIME_ELAPSED_EXT */, handle);
6168
+ pair.activeQuery = query;
5394
6169
  return;
5395
6170
  }
5396
- this.target = target2;
5397
- this.device.gl.beginQuery(this.target, this.handle);
5398
- return;
6171
+ if (!pair.activeQuery) {
6172
+ throw new Error("Timestamp query pair was ended before it was started");
6173
+ }
6174
+ this.device.gl.endQuery(35007 /* TIME_ELAPSED_EXT */);
6175
+ pair.completedQueries.push(pair.activeQuery);
6176
+ pair.activeQuery = null;
5399
6177
  }
5400
- // ends the current query
5401
- _end() {
5402
- if (this._queryPending) {
5403
- return;
6178
+ _validateRange(firstQuery, queryCount) {
6179
+ if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
6180
+ throw new Error("Query read range is out of bounds");
5404
6181
  }
5405
- if (this.target) {
5406
- this.device.gl.endQuery(this.target);
5407
- this.target = null;
5408
- this._queryPending = true;
6182
+ }
6183
+ _getTimestampPairIndex(queryIndex) {
6184
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
6185
+ throw new Error("Query index is out of bounds");
5409
6186
  }
5410
- return;
6187
+ return Math.floor(queryIndex / 2);
5411
6188
  }
5412
- // Returns true if the query result is available
5413
- isResultAvailable() {
5414
- if (!this._queryPending) {
6189
+ _isTimestampPairAvailable(pairIndex) {
6190
+ const pair = this._timestampPairs[pairIndex];
6191
+ if (!pair || pair.completedQueries.length === 0) {
5415
6192
  return false;
5416
6193
  }
6194
+ return this._pollQueryAvailability(pair.completedQueries[0]);
6195
+ }
6196
+ _pollQueryAvailability(query) {
6197
+ if (query.cancelled || this.destroyed) {
6198
+ query.result = 0n;
6199
+ return true;
6200
+ }
6201
+ if (query.result !== null || query.disjoint) {
6202
+ return true;
6203
+ }
5417
6204
  const resultAvailable = this.device.gl.getQueryParameter(
5418
- this.handle,
6205
+ query.handle,
5419
6206
  34919 /* QUERY_RESULT_AVAILABLE */
5420
6207
  );
5421
- if (resultAvailable) {
5422
- this._queryPending = false;
6208
+ if (!resultAvailable) {
6209
+ return false;
6210
+ }
6211
+ const isDisjoint = Boolean(this.device.gl.getParameter(36795 /* GPU_DISJOINT_EXT */));
6212
+ query.disjoint = isDisjoint;
6213
+ query.result = isDisjoint ? 0n : BigInt(this.device.gl.getQueryParameter(query.handle, 34918 /* QUERY_RESULT */));
6214
+ return true;
6215
+ }
6216
+ async _consumeTimestampPairResult(pairIndex) {
6217
+ const pair = this._timestampPairs[pairIndex];
6218
+ if (!pair || pair.completedQueries.length === 0) {
6219
+ throw new Error("Timestamp query pair has no completed result");
6220
+ }
6221
+ const query = pair.completedQueries.shift();
6222
+ try {
6223
+ return await this._consumeQueryResult(query);
6224
+ } finally {
6225
+ this.device.gl.deleteQuery(query.handle);
5423
6226
  }
5424
- return resultAvailable;
5425
6227
  }
5426
- // Timing query is disjoint, i.e. results are invalid
5427
- isTimerDisjoint() {
5428
- return this.device.gl.getParameter(36795 /* GPU_DISJOINT_EXT */);
6228
+ _consumeQueryResult(query) {
6229
+ if (query.promise) {
6230
+ return query.promise;
6231
+ }
6232
+ this._pendingReads.add(query);
6233
+ query.promise = new Promise((resolve, reject) => {
6234
+ query.resolve = resolve;
6235
+ query.reject = reject;
6236
+ const poll = () => {
6237
+ query.pollRequestId = null;
6238
+ if (query.cancelled || this.destroyed) {
6239
+ this._pendingReads.delete(query);
6240
+ query.promise = null;
6241
+ query.resolve = null;
6242
+ query.reject = null;
6243
+ resolve(0n);
6244
+ return;
6245
+ }
6246
+ if (!this._pollQueryAvailability(query)) {
6247
+ query.pollRequestId = this._requestAnimationFrame(poll);
6248
+ return;
6249
+ }
6250
+ this._pendingReads.delete(query);
6251
+ query.promise = null;
6252
+ query.resolve = null;
6253
+ query.reject = null;
6254
+ if (query.disjoint) {
6255
+ reject(new Error("GPU timestamp query was invalidated by a disjoint event"));
6256
+ } else {
6257
+ resolve(query.result || 0n);
6258
+ }
6259
+ };
6260
+ poll();
6261
+ });
6262
+ return query.promise;
6263
+ }
6264
+ _cancelPendingQuery(query) {
6265
+ this._pendingReads.delete(query);
6266
+ query.cancelled = true;
6267
+ if (query.pollRequestId !== null) {
6268
+ this._cancelAnimationFrame(query.pollRequestId);
6269
+ query.pollRequestId = null;
6270
+ }
6271
+ if (query.resolve) {
6272
+ const resolve = query.resolve;
6273
+ query.promise = null;
6274
+ query.resolve = null;
6275
+ query.reject = null;
6276
+ resolve(0n);
6277
+ }
5429
6278
  }
5430
- // Returns query result.
5431
- getResult() {
5432
- return this.device.gl.getQueryParameter(this.handle, 34918 /* QUERY_RESULT */);
6279
+ _requestAnimationFrame(callback) {
6280
+ return requestAnimationFrame(callback);
5433
6281
  }
5434
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5435
- getTimerMilliseconds() {
5436
- return this.getResult() / 1e6;
6282
+ _cancelAnimationFrame(requestId) {
6283
+ cancelAnimationFrame(requestId);
5437
6284
  }
5438
- // Polls the query
5439
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5440
- if (this._pollingPromise) {
5441
- return this._pollingPromise;
6285
+ };
6286
+ }
6287
+ });
6288
+
6289
+ // src/adapter/resources/webgl-fence.ts
6290
+ var import_core24, WEBGLFence;
6291
+ var init_webgl_fence = __esm({
6292
+ "src/adapter/resources/webgl-fence.ts"() {
6293
+ "use strict";
6294
+ import_core24 = __toESM(require_core(), 1);
6295
+ WEBGLFence = class extends import_core24.Fence {
6296
+ device;
6297
+ gl;
6298
+ handle;
6299
+ signaled;
6300
+ _signaled = false;
6301
+ constructor(device, props = {}) {
6302
+ super(device, {});
6303
+ this.device = device;
6304
+ this.gl = device.gl;
6305
+ const sync = this.props.handle || this.gl.fenceSync(this.gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
6306
+ if (!sync) {
6307
+ throw new Error("Failed to create WebGL fence");
5442
6308
  }
5443
- let counter = 0;
5444
- this._pollingPromise = new Promise((resolve, reject) => {
6309
+ this.handle = sync;
6310
+ this.signaled = new Promise((resolve) => {
5445
6311
  const poll = () => {
5446
- if (this.isResultAvailable()) {
5447
- resolve(this.getResult());
5448
- this._pollingPromise = null;
5449
- } else if (counter++ > limit) {
5450
- reject("Timed out");
5451
- this._pollingPromise = null;
6312
+ const status = this.gl.clientWaitSync(this.handle, 0, 0);
6313
+ if (status === this.gl.ALREADY_SIGNALED || status === this.gl.CONDITION_SATISFIED) {
6314
+ this._signaled = true;
6315
+ resolve();
5452
6316
  } else {
5453
- requestAnimationFrame(poll);
6317
+ setTimeout(poll, 1);
5454
6318
  }
5455
6319
  };
5456
- requestAnimationFrame(poll);
6320
+ poll();
5457
6321
  });
5458
- return this._pollingPromise;
6322
+ }
6323
+ isSignaled() {
6324
+ if (this._signaled) {
6325
+ return true;
6326
+ }
6327
+ const status = this.gl.getSyncParameter(this.handle, this.gl.SYNC_STATUS);
6328
+ this._signaled = status === this.gl.SIGNALED;
6329
+ return this._signaled;
6330
+ }
6331
+ destroy() {
6332
+ if (!this.destroyed) {
6333
+ this.gl.deleteSync(this.handle);
6334
+ }
5459
6335
  }
5460
6336
  };
5461
6337
  }
@@ -5507,35 +6383,6 @@ ${source}`;
5507
6383
  }
5508
6384
  });
5509
6385
 
5510
- // src/adapter/converters/shader-formats.ts
5511
- function convertGLDataTypeToDataType(type) {
5512
- return GL_DATA_TYPE_MAP[type];
5513
- }
5514
- var GL_DATA_TYPE_MAP;
5515
- var init_shader_formats = __esm({
5516
- "src/adapter/converters/shader-formats.ts"() {
5517
- "use strict";
5518
- GL_DATA_TYPE_MAP = {
5519
- [5124 /* INT */]: "sint32",
5520
- [5125 /* UNSIGNED_INT */]: "uint32",
5521
- [5122 /* SHORT */]: "sint16",
5522
- [5123 /* UNSIGNED_SHORT */]: "uint16",
5523
- [5120 /* BYTE */]: "sint8",
5524
- [5121 /* UNSIGNED_BYTE */]: "uint8",
5525
- [5126 /* FLOAT */]: "float32",
5526
- [5131 /* HALF_FLOAT */]: "float16",
5527
- [33635 /* UNSIGNED_SHORT_5_6_5 */]: "uint16",
5528
- [32819 /* UNSIGNED_SHORT_4_4_4_4 */]: "uint16",
5529
- [32820 /* UNSIGNED_SHORT_5_5_5_1 */]: "uint16",
5530
- [33640 /* UNSIGNED_INT_2_10_10_10_REV */]: "uint32",
5531
- [35899 /* UNSIGNED_INT_10F_11F_11F_REV */]: "uint32",
5532
- [35902 /* UNSIGNED_INT_5_9_9_9_REV */]: "uint32",
5533
- [34042 /* UNSIGNED_INT_24_8 */]: "uint32",
5534
- [36269 /* FLOAT_32_UNSIGNED_INT_24_8_REV */]: "uint32"
5535
- };
5536
- }
5537
- });
5538
-
5539
6386
  // src/adapter/helpers/webgl-texture-utils.ts
5540
6387
  function readPixelsToArray(source, options) {
5541
6388
  const {
@@ -5565,7 +6412,7 @@ ${source}`;
5565
6412
  sourceFormat ||= texture?.glFormat || 6408 /* RGBA */;
5566
6413
  sourceType ||= texture?.glType || 5121 /* UNSIGNED_BYTE */;
5567
6414
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5568
- const signedType = (0, import_core22.getDataType)(target2);
6415
+ const signedType = import_core25.dataTypeDecoder.getDataType(target2);
5569
6416
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5570
6417
  const prevHandle = gl.bindFramebuffer(
5571
6418
  36160 /* FRAMEBUFFER */,
@@ -5617,7 +6464,7 @@ ${source}`;
5617
6464
  return webglBufferTarget;
5618
6465
  }
5619
6466
  function getFramebuffer2(source) {
5620
- if (!(source instanceof import_core22.Framebuffer)) {
6467
+ if (!(source instanceof import_core25.Framebuffer)) {
5621
6468
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5622
6469
  }
5623
6470
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5639,15 +6486,15 @@ ${source}`;
5639
6486
  }
5640
6487
  glType ||= 5121 /* UNSIGNED_BYTE */;
5641
6488
  const shaderType = convertGLDataTypeToDataType(glType);
5642
- const ArrayType = (0, import_core22.getTypedArrayConstructor)(shaderType);
6489
+ const ArrayType = import_core25.dataTypeDecoder.getTypedArrayConstructor(shaderType);
5643
6490
  const components = glFormatToComponents(glFormat);
5644
6491
  return new ArrayType(width * height * components);
5645
6492
  }
5646
- var import_core22;
6493
+ var import_core25;
5647
6494
  var init_webgl_texture_utils = __esm({
5648
6495
  "src/adapter/helpers/webgl-texture-utils.ts"() {
5649
6496
  "use strict";
5650
- import_core22 = __toESM(require_core(), 1);
6497
+ import_core25 = __toESM(require_core(), 1);
5651
6498
  init_webgl_shadertypes();
5652
6499
  init_format_utils();
5653
6500
  init_shader_formats();
@@ -5693,17 +6540,19 @@ ${source}`;
5693
6540
  }
5694
6541
  return true;
5695
6542
  }
5696
- var import_core23, WebGLDevice;
6543
+ var import_core26, WebGLDevice;
5697
6544
  var init_webgl_device = __esm({
5698
6545
  "src/adapter/webgl-device.ts"() {
5699
6546
  "use strict";
5700
- import_core23 = __toESM(require_core(), 1);
6547
+ import_core26 = __toESM(require_core(), 1);
5701
6548
  init_webgl_state_tracker();
5702
6549
  init_create_browser_context();
6550
+ init_webgl_context_data();
5703
6551
  init_webgl_device_info();
5704
6552
  init_webgl_device_features();
5705
6553
  init_webgl_device_limits();
5706
6554
  init_webgl_canvas_context();
6555
+ init_webgl_presentation_context();
5707
6556
  init_spector();
5708
6557
  init_webgl_developer_tools();
5709
6558
  init_webgl_texture_table();
@@ -5714,15 +6563,23 @@ ${source}`;
5714
6563
  init_webgl_texture();
5715
6564
  init_webgl_framebuffer();
5716
6565
  init_webgl_render_pipeline();
6566
+ init_webgl_shared_render_pipeline();
5717
6567
  init_webgl_command_encoder();
5718
6568
  init_webgl_vertex_array();
5719
6569
  init_webgl_transform_feedback();
5720
6570
  init_webgl_query_set();
6571
+ init_webgl_fence();
5721
6572
  init_webgl_texture_utils();
5722
6573
  init_unified_parameter_api();
5723
6574
  init_with_parameters();
5724
6575
  init_webgl_extensions();
5725
- WebGLDevice = class extends import_core23.Device {
6576
+ WebGLDevice = class extends import_core26.Device {
6577
+ static getDeviceFromContext(gl) {
6578
+ if (!gl) {
6579
+ return null;
6580
+ }
6581
+ return gl.luma?.device ?? null;
6582
+ }
5726
6583
  // Public `Device` API
5727
6584
  /** type of this device */
5728
6585
  type = "webgl";
@@ -5744,7 +6601,7 @@ ${source}`;
5744
6601
  // @ts-ignore TODO fix
5745
6602
  _constants;
5746
6603
  /** State used by luma.gl classes - TODO - not used? */
5747
- _extensions = {};
6604
+ extensions;
5748
6605
  _polyfilled = false;
5749
6606
  /** Instance of Spector.js (if initialized) */
5750
6607
  spectorJS;
@@ -5767,11 +6624,12 @@ ${source}`;
5767
6624
  }
5768
6625
  constructor(props) {
5769
6626
  super({ ...props, id: props.id || uid("webgl-device") });
5770
- const canvasContextProps = import_core23.Device._getCanvasContextProps(props);
6627
+ const canvasContextProps = import_core26.Device._getCanvasContextProps(props);
5771
6628
  if (!canvasContextProps) {
5772
6629
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5773
6630
  }
5774
- let device = canvasContextProps.canvas?.gl?.device;
6631
+ const existingContext = canvasContextProps.canvas?.gl ?? null;
6632
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5775
6633
  if (device) {
5776
6634
  throw new Error(`WebGL context already attached to device ${device.id}`);
5777
6635
  }
@@ -5786,6 +6644,9 @@ ${source}`;
5786
6644
  if (props.powerPreference !== void 0) {
5787
6645
  webglContextAttributes.powerPreference = props.powerPreference;
5788
6646
  }
6647
+ if (props.failIfMajorPerformanceCaveat !== void 0) {
6648
+ webglContextAttributes.failIfMajorPerformanceCaveat = props.failIfMajorPerformanceCaveat;
6649
+ }
5789
6650
  const externalGLContext = this.props._handle;
5790
6651
  const gl = externalGLContext || createBrowserContext(
5791
6652
  this.canvasContext.canvas,
@@ -5802,14 +6663,15 @@ ${source}`;
5802
6663
  if (!gl) {
5803
6664
  throw new Error("WebGL context creation failed");
5804
6665
  }
5805
- device = gl.device;
6666
+ device = WebGLDevice.getDeviceFromContext(gl);
5806
6667
  if (device) {
5807
6668
  if (props._reuseDevices) {
5808
- import_core23.log.log(
6669
+ import_core26.log.log(
5809
6670
  1,
5810
6671
  `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`,
5811
6672
  device
5812
6673
  )();
6674
+ this.canvasContext.destroy();
5813
6675
  device._reused = true;
5814
6676
  return device;
5815
6677
  }
@@ -5818,32 +6680,31 @@ ${source}`;
5818
6680
  this.handle = gl;
5819
6681
  this.gl = gl;
5820
6682
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5821
- this.gl.device = this;
5822
- this.gl._version = 2;
5823
- this.info = getDeviceInfo(this.gl, this._extensions);
6683
+ const contextData = getWebGLContextData(this.handle);
6684
+ contextData.device = this;
6685
+ if (!contextData.extensions) {
6686
+ contextData.extensions = {};
6687
+ }
6688
+ this.extensions = contextData.extensions;
6689
+ this.info = getDeviceInfo(this.gl, this.extensions);
5824
6690
  this.limits = new WebGLDeviceLimits(this.gl);
5825
- this.features = new WebGLDeviceFeatures(
5826
- this.gl,
5827
- this._extensions,
5828
- this.props._disabledFeatures
5829
- );
6691
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5830
6692
  if (this.props._initializeFeatures) {
5831
6693
  this.features.initializeFeatures();
5832
6694
  }
5833
6695
  const glState = new WebGLStateTracker(this.gl, {
5834
- log: (...args) => import_core23.log.log(1, ...args)()
6696
+ log: (...args) => import_core26.log.log(1, ...args)()
5835
6697
  });
5836
6698
  glState.trackState(this.gl, { copyState: false });
5837
- const debugWebGL = props.debugWebGL || props.debug;
5838
- const traceWebGL = props.debugWebGL;
5839
- if (debugWebGL) {
5840
- this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
5841
- import_core23.log.warn("WebGL debug mode activated. Performance reduced.")();
5842
- if (props.debugWebGL) {
5843
- import_core23.log.level = Math.max(import_core23.log.level, 1);
5844
- }
6699
+ if (props.debug || props.debugWebGL) {
6700
+ this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
6701
+ import_core26.log.warn("WebGL debug mode activated. Performance reduced.")();
6702
+ }
6703
+ if (props.debugWebGL) {
6704
+ import_core26.log.level = Math.max(import_core26.log.level, 1);
5845
6705
  }
5846
6706
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6707
+ this.canvasContext._startObservers();
5847
6708
  }
5848
6709
  /**
5849
6710
  * Destroys the device
@@ -5856,20 +6717,22 @@ ${source}`;
5856
6717
  * browser API for destroying WebGL contexts.
5857
6718
  */
5858
6719
  destroy() {
6720
+ this.commandEncoder?.destroy();
5859
6721
  if (!this.props._reuseDevices && !this._reused) {
5860
- delete this.gl.device;
6722
+ const contextData = getWebGLContextData(this.handle);
6723
+ contextData.device = null;
5861
6724
  }
5862
6725
  }
5863
6726
  get isLost() {
5864
6727
  return this.gl.isContextLost();
5865
6728
  }
5866
6729
  // IMPLEMENTATION OF ABSTRACT DEVICE
5867
- getTextureByteAlignment() {
5868
- return 4;
5869
- }
5870
6730
  createCanvasContext(props) {
5871
6731
  throw new Error("WebGL only supports a single canvas");
5872
6732
  }
6733
+ createPresentationContext(props) {
6734
+ return new WebGLPresentationContext(this, props || {});
6735
+ }
5873
6736
  createBuffer(props) {
5874
6737
  const newProps = this._normalizeBufferProps(props);
5875
6738
  return new WEBGLBuffer(this, newProps);
@@ -5898,9 +6761,18 @@ ${source}`;
5898
6761
  createQuerySet(props) {
5899
6762
  return new WEBGLQuerySet(this, props);
5900
6763
  }
6764
+ createFence() {
6765
+ return new WEBGLFence(this);
6766
+ }
5901
6767
  createRenderPipeline(props) {
5902
6768
  return new WEBGLRenderPipeline(this, props);
5903
6769
  }
6770
+ _createSharedRenderPipelineWebGL(props) {
6771
+ return new WEBGLSharedRenderPipeline(
6772
+ this,
6773
+ props
6774
+ );
6775
+ }
5904
6776
  createComputePipeline(props) {
5905
6777
  throw new Error("ComputePipeline not supported in WebGL");
5906
6778
  }
@@ -5913,12 +6785,31 @@ ${source}`;
5913
6785
  * Chrome's offscreen canvas does not require gl.commit
5914
6786
  */
5915
6787
  submit(commandBuffer) {
6788
+ let submittedCommandEncoder = null;
5916
6789
  if (!commandBuffer) {
5917
- commandBuffer = this.commandEncoder.finish();
5918
- this.commandEncoder.destroy();
5919
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
6790
+ ({ submittedCommandEncoder, commandBuffer } = this._finalizeDefaultCommandEncoderForSubmit());
6791
+ }
6792
+ try {
6793
+ commandBuffer._executeCommands();
6794
+ if (submittedCommandEncoder) {
6795
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
6796
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
6797
+ }).catch(() => {
6798
+ });
6799
+ }
6800
+ } finally {
6801
+ commandBuffer.destroy();
5920
6802
  }
5921
- commandBuffer._executeCommands();
6803
+ }
6804
+ _finalizeDefaultCommandEncoderForSubmit() {
6805
+ const submittedCommandEncoder = this.commandEncoder;
6806
+ const commandBuffer = submittedCommandEncoder.finish();
6807
+ this.commandEncoder.destroy();
6808
+ this.commandEncoder = this.createCommandEncoder({
6809
+ id: submittedCommandEncoder.props.id,
6810
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
6811
+ });
6812
+ return { submittedCommandEncoder, commandBuffer };
5922
6813
  }
5923
6814
  //
5924
6815
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5941,11 +6832,11 @@ ${source}`;
5941
6832
  return withGLParameters(this.gl, parameters, func);
5942
6833
  }
5943
6834
  resetWebGL() {
5944
- import_core23.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6835
+ import_core26.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5945
6836
  resetGLParameters(this.gl);
5946
6837
  }
5947
6838
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5948
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
6839
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5949
6840
  }
5950
6841
  //
5951
6842
  // WebGL-only API (not part of `Device` API)
@@ -6013,7 +6904,7 @@ ${source}`;
6013
6904
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
6014
6905
  const currentConstant = this._constants[location];
6015
6906
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
6016
- import_core23.log.info(
6907
+ import_core26.log.info(
6017
6908
  1,
6018
6909
  `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`
6019
6910
  )();
@@ -6035,8 +6926,8 @@ ${source}`;
6035
6926
  }
6036
6927
  /** Ensure extensions are only requested once */
6037
6928
  getExtension(name) {
6038
- getWebGLExtension(this.gl, name, this._extensions);
6039
- return this._extensions;
6929
+ getWebGLExtension(this.gl, name, this.extensions);
6930
+ return this.extensions;
6040
6931
  }
6041
6932
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
6042
6933
  /**
@@ -6057,23 +6948,23 @@ ${source}`;
6057
6948
  if (typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext) {
6058
6949
  return true;
6059
6950
  }
6060
- return Boolean(gl && Number.isFinite(gl._version));
6951
+ return Boolean(gl && typeof gl.createVertexArray === "function");
6061
6952
  }
6062
- var import_core24, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
6953
+ var import_core27, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
6063
6954
  var init_webgl_adapter = __esm({
6064
6955
  "src/adapter/webgl-adapter.ts"() {
6065
6956
  "use strict";
6066
- import_core24 = __toESM(require_core(), 1);
6957
+ import_core27 = __toESM(require_core(), 1);
6067
6958
  init_polyfill_webgl1_extensions();
6068
6959
  init_spector();
6069
6960
  init_webgl_developer_tools();
6070
6961
  LOG_LEVEL2 = 1;
6071
- WebGLAdapter = class extends import_core24.Adapter {
6962
+ WebGLAdapter = class extends import_core27.Adapter {
6072
6963
  /** type of device's created by this adapter */
6073
6964
  type = "webgl";
6074
6965
  constructor() {
6075
6966
  super();
6076
- import_core24.Device.defaultProps = { ...import_core24.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
6967
+ import_core27.Device.defaultProps = { ...import_core27.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
6077
6968
  }
6078
6969
  /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
6079
6970
  enforceWebGL2(enable2) {
@@ -6088,7 +6979,7 @@ ${source}`;
6088
6979
  return true;
6089
6980
  }
6090
6981
  if (typeof WebGLRenderingContext !== "undefined" && handle instanceof WebGLRenderingContext) {
6091
- import_core24.log.warn("WebGL1 is not supported", handle)();
6982
+ import_core27.log.warn("WebGL1 is not supported", handle)();
6092
6983
  }
6093
6984
  return false;
6094
6985
  }
@@ -6104,8 +6995,9 @@ ${source}`;
6104
6995
  if (gl instanceof WebGLDevice2) {
6105
6996
  return gl;
6106
6997
  }
6107
- if (gl?.device instanceof WebGLDevice2) {
6108
- return gl.device;
6998
+ const existingDevice = WebGLDevice2.getDeviceFromContext(gl);
6999
+ if (existingDevice) {
7000
+ return existingDevice;
6109
7001
  }
6110
7002
  if (!isWebGL(gl)) {
6111
7003
  throw new Error("Invalid WebGL2RenderingContext");
@@ -6119,28 +7011,33 @@ ${source}`;
6119
7011
  }
6120
7012
  async create(props = {}) {
6121
7013
  const { WebGLDevice: WebGLDevice2 } = await Promise.resolve().then(() => (init_webgl_device(), webgl_device_exports));
6122
- import_core24.log.groupCollapsed(LOG_LEVEL2, "WebGLDevice created")();
6123
- try {
6124
- const promises = [];
6125
- if (props.debugWebGL || props.debug) {
6126
- promises.push(loadWebGLDeveloperTools());
6127
- }
6128
- if (props.debugSpectorJS) {
6129
- promises.push(loadSpectorJS(props));
6130
- }
6131
- const results = await Promise.allSettled(promises);
6132
- for (const result of results) {
6133
- if (result.status === "rejected") {
6134
- import_core24.log.error(`Failed to initialize debug libraries ${result.reason}`)();
6135
- }
7014
+ const promises = [];
7015
+ if (props.debugWebGL || props.debug) {
7016
+ promises.push(loadWebGLDeveloperTools());
7017
+ }
7018
+ if (props.debugSpectorJS) {
7019
+ promises.push(loadSpectorJS(props));
7020
+ }
7021
+ const results = await Promise.allSettled(promises);
7022
+ for (const result of results) {
7023
+ if (result.status === "rejected") {
7024
+ import_core27.log.error(`Failed to initialize debug libraries ${result.reason}`)();
6136
7025
  }
7026
+ }
7027
+ try {
6137
7028
  const device = new WebGLDevice2(props);
7029
+ import_core27.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
6138
7030
  const message2 = `${device._reused ? "Reusing" : "Created"} device with WebGL2 ${device.props.debug ? "debug " : ""}context: ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
6139
- import_core24.log.probe(LOG_LEVEL2, message2)();
6140
- import_core24.log.table(LOG_LEVEL2, device.info)();
7031
+ import_core27.log.probe(LOG_LEVEL2, message2)();
7032
+ import_core27.log.table(LOG_LEVEL2, device.info)();
6141
7033
  return device;
6142
7034
  } finally {
6143
- import_core24.log.groupEnd(LOG_LEVEL2)();
7035
+ import_core27.log.groupEnd(LOG_LEVEL2)();
7036
+ import_core27.log.info(
7037
+ LOG_LEVEL2,
7038
+ `%cWebGL call tracing: luma.log.set('debug-webgl') `,
7039
+ "color: white; background: blue; padding: 2px 6px; border-radius: 3px;"
7040
+ )();
6144
7041
  }
6145
7042
  }
6146
7043
  };
@@ -6149,9 +7046,10 @@ ${source}`;
6149
7046
  });
6150
7047
 
6151
7048
  // src/index.ts
6152
- var init_src2 = __esm({
7049
+ var init_src = __esm({
6153
7050
  "src/index.ts"() {
6154
7051
  "use strict";
7052
+ init_webgl_constants();
6155
7053
  init_webgl_adapter();
6156
7054
  init_webgl_device();
6157
7055
  init_webgl_canvas_context();
@@ -6160,6 +7058,7 @@ ${source}`;
6160
7058
  init_webgl_shader();
6161
7059
  init_webgl_sampler();
6162
7060
  init_webgl_framebuffer();
7061
+ init_webgl_fence();
6163
7062
  init_webgl_render_pipeline();
6164
7063
  init_webgl_command_encoder();
6165
7064
  init_webgl_render_pass();
@@ -6176,8 +7075,10 @@ ${source}`;
6176
7075
  // bundle.ts
6177
7076
  var bundle_exports = {};
6178
7077
  __export(bundle_exports, {
7078
+ GL: () => GLEnum,
6179
7079
  WEBGLBuffer: () => WEBGLBuffer,
6180
7080
  WEBGLCommandEncoder: () => WEBGLCommandEncoder,
7081
+ WEBGLFence: () => WEBGLFence,
6181
7082
  WEBGLFramebuffer: () => WEBGLFramebuffer,
6182
7083
  WEBGLRenderPass: () => WEBGLRenderPass,
6183
7084
  WEBGLRenderPipeline: () => WEBGLRenderPipeline,
@@ -6199,7 +7100,7 @@ ${source}`;
6199
7100
  withGLParameters: () => withGLParameters
6200
7101
  });
6201
7102
  __reExport(bundle_exports, __toESM(require_core(), 1));
6202
- init_src2();
7103
+ init_src();
6203
7104
  return __toCommonJS(bundle_exports);
6204
7105
  })();
6205
7106
  return __exports__;