@luma.gl/webgl 9.3.0-alpha.4 → 9.3.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) 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 +1 -6
  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 +122 -58
  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 +1 -1
  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 +1 -1
  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 +30 -19
  42. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  43. package/dist/adapter/helpers/set-uniform.d.ts +1 -1
  44. package/dist/adapter/helpers/set-uniform.d.ts.map +1 -1
  45. package/dist/adapter/helpers/set-uniform.js +1 -1
  46. package/dist/adapter/helpers/set-uniform.js.map +1 -1
  47. package/dist/adapter/helpers/webgl-texture-utils.d.ts +1 -1
  48. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  49. package/dist/adapter/helpers/webgl-texture-utils.js +4 -4
  50. package/dist/adapter/helpers/webgl-texture-utils.js.map +1 -1
  51. package/dist/adapter/helpers/webgl-topology-utils.d.ts +1 -1
  52. package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
  53. package/dist/adapter/helpers/webgl-topology-utils.js +1 -1
  54. package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -1
  55. package/dist/adapter/resources/webgl-buffer.d.ts +1 -1
  56. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  57. package/dist/adapter/resources/webgl-buffer.js +20 -5
  58. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  59. package/dist/adapter/resources/webgl-command-buffer.d.ts +3 -3
  60. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  61. package/dist/adapter/resources/webgl-command-buffer.js +22 -36
  62. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  63. package/dist/adapter/resources/webgl-command-encoder.d.ts +6 -5
  64. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  65. package/dist/adapter/resources/webgl-command-encoder.js +23 -8
  66. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  67. package/dist/adapter/resources/webgl-framebuffer.d.ts +3 -1
  68. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  69. package/dist/adapter/resources/webgl-framebuffer.js +10 -1
  70. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -1
  71. package/dist/adapter/resources/webgl-query-set.d.ts +37 -31
  72. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  73. package/dist/adapter/resources/webgl-query-set.js +247 -96
  74. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  75. package/dist/adapter/resources/webgl-render-pass.d.ts +1 -1
  76. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  77. package/dist/adapter/resources/webgl-render-pass.js +25 -11
  78. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  79. package/dist/adapter/resources/webgl-render-pipeline.d.ts +17 -21
  80. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  81. package/dist/adapter/resources/webgl-render-pipeline.js +69 -167
  82. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  83. package/dist/adapter/resources/webgl-sampler.d.ts +1 -1
  84. package/dist/adapter/resources/webgl-sampler.d.ts.map +1 -1
  85. package/dist/adapter/resources/webgl-sampler.js +1 -1
  86. package/dist/adapter/resources/webgl-sampler.js.map +1 -1
  87. package/dist/adapter/resources/webgl-shader.d.ts +1 -1
  88. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  89. package/dist/adapter/resources/webgl-shader.js +15 -8
  90. package/dist/adapter/resources/webgl-shader.js.map +1 -1
  91. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  92. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  93. package/dist/adapter/resources/webgl-shared-render-pipeline.js +155 -0
  94. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  95. package/dist/adapter/resources/webgl-texture.d.ts +27 -6
  96. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  97. package/dist/adapter/resources/webgl-texture.js +199 -101
  98. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  99. package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
  100. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  101. package/dist/adapter/resources/webgl-vertex-array.d.ts +2 -2
  102. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  103. package/dist/adapter/resources/webgl-vertex-array.js +1 -1
  104. package/dist/adapter/resources/webgl-vertex-array.js.map +1 -1
  105. package/dist/adapter/webgl-device.d.ts +6 -3
  106. package/dist/adapter/webgl-device.d.ts.map +1 -1
  107. package/dist/adapter/webgl-device.js +36 -4
  108. package/dist/adapter/webgl-device.js.map +1 -1
  109. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  110. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  111. package/dist/adapter/webgl-presentation-context.js +64 -0
  112. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  113. package/dist/constants/index.d.ts +3 -0
  114. package/dist/constants/index.d.ts.map +1 -0
  115. package/dist/constants/index.js +5 -0
  116. package/dist/constants/index.js.map +1 -0
  117. package/dist/constants/webgl-constants.d.ts +822 -0
  118. package/dist/constants/webgl-constants.d.ts.map +1 -0
  119. package/dist/constants/webgl-constants.js +928 -0
  120. package/dist/constants/webgl-constants.js.map +1 -0
  121. package/dist/constants/webgl-types.d.ts +480 -0
  122. package/dist/constants/webgl-types.d.ts.map +1 -0
  123. package/dist/constants/webgl-types.js +6 -0
  124. package/dist/constants/webgl-types.js.map +1 -0
  125. package/dist/context/debug/webgl-developer-tools.js +1 -1
  126. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  127. package/dist/context/helpers/webgl-context-data.d.ts +1 -1
  128. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  129. package/dist/context/helpers/webgl-extensions.d.ts +1 -1
  130. package/dist/context/helpers/webgl-extensions.d.ts.map +1 -1
  131. package/dist/context/parameters/unified-parameter-api.d.ts +1 -1
  132. package/dist/context/parameters/unified-parameter-api.d.ts.map +1 -1
  133. package/dist/context/parameters/webgl-parameter-tables.d.ts +1 -1
  134. package/dist/context/parameters/webgl-parameter-tables.d.ts.map +1 -1
  135. package/dist/context/parameters/webgl-parameter-tables.js +1 -1
  136. package/dist/context/parameters/webgl-parameter-tables.js.map +1 -1
  137. package/dist/context/polyfills/polyfill-webgl1-extensions.js +1 -1
  138. package/dist/context/polyfills/polyfill-webgl1-extensions.js.map +1 -1
  139. package/dist/dist.dev.js +1473 -824
  140. package/dist/dist.min.js +2 -2
  141. package/dist/index.cjs +3 -5491
  142. package/dist/index.cjs.map +4 -4
  143. package/dist/index.d.ts +2 -0
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +1 -0
  146. package/dist/index.js.map +1 -1
  147. package/dist/webgl-constants.d.ts +2 -0
  148. package/dist/webgl-constants.d.ts.map +1 -0
  149. package/dist/webgl-constants.js +5 -0
  150. package/dist/webgl-constants.js.map +1 -0
  151. package/dist/webgl-types.d.ts +2 -0
  152. package/dist/webgl-types.d.ts.map +1 -0
  153. package/dist/{types.js → webgl-types.js} +1 -1
  154. package/dist/webgl-types.js.map +1 -0
  155. package/package.json +18 -4
  156. package/src/adapter/converters/device-parameters.ts +6 -2
  157. package/src/adapter/converters/sampler-parameters.ts +1 -1
  158. package/src/adapter/converters/shader-formats.ts +1 -66
  159. package/src/adapter/converters/webgl-shadertypes.ts +1 -9
  160. package/src/adapter/converters/webgl-texture-table.ts +160 -68
  161. package/src/adapter/converters/webgl-vertex-formats.ts +1 -1
  162. package/src/adapter/device-helpers/webgl-device-features.ts +2 -3
  163. package/src/adapter/device-helpers/webgl-device-info.ts +7 -1
  164. package/src/adapter/device-helpers/webgl-device-limits.ts +1 -1
  165. package/src/adapter/helpers/format-utils.ts +1 -1
  166. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +38 -20
  167. package/src/adapter/helpers/set-uniform.ts +1 -1
  168. package/src/adapter/helpers/webgl-texture-utils.ts +4 -4
  169. package/src/adapter/helpers/webgl-topology-utils.ts +1 -1
  170. package/src/adapter/resources/webgl-buffer.ts +17 -5
  171. package/src/adapter/resources/webgl-command-buffer.ts +28 -28
  172. package/src/adapter/resources/webgl-command-encoder.ts +28 -11
  173. package/src/adapter/resources/webgl-framebuffer.ts +12 -1
  174. package/src/adapter/resources/webgl-query-set.ts +295 -101
  175. package/src/adapter/resources/webgl-render-pass.ts +26 -13
  176. package/src/adapter/resources/webgl-render-pipeline.ts +101 -196
  177. package/src/adapter/resources/webgl-sampler.ts +1 -1
  178. package/src/adapter/resources/webgl-shader.ts +15 -8
  179. package/src/adapter/resources/webgl-shared-render-pipeline.ts +211 -0
  180. package/src/adapter/resources/webgl-texture.ts +324 -122
  181. package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
  182. package/src/adapter/resources/webgl-vertex-array.ts +1 -1
  183. package/src/adapter/webgl-device.ts +50 -6
  184. package/src/adapter/webgl-presentation-context.ts +93 -0
  185. package/src/constants/index.d.ts.map +1 -0
  186. package/src/constants/index.js.map +1 -0
  187. package/src/constants/index.ts +31 -0
  188. package/src/constants/webgl-constants.d.ts.map +1 -0
  189. package/src/constants/webgl-constants.js.map +1 -0
  190. package/src/constants/webgl-constants.ts +1051 -0
  191. package/src/constants/webgl-types.d.ts.map +1 -0
  192. package/src/constants/webgl-types.js.map +1 -0
  193. package/src/constants/webgl-types.ts +813 -0
  194. package/src/context/debug/webgl-developer-tools.ts +1 -1
  195. package/src/context/helpers/webgl-context-data.ts +1 -1
  196. package/src/context/helpers/webgl-extensions.ts +1 -1
  197. package/src/context/parameters/unified-parameter-api.ts +1 -1
  198. package/src/context/parameters/webgl-parameter-tables.ts +1 -1
  199. package/src/context/polyfills/polyfill-webgl1-extensions.ts +1 -1
  200. package/src/index.ts +26 -0
  201. package/src/webgl-constants.d.ts.map +1 -0
  202. package/src/webgl-constants.js.map +1 -0
  203. package/src/webgl-constants.ts +5 -0
  204. package/src/webgl-types.d.ts.map +1 -0
  205. package/src/webgl-types.js.map +1 -0
  206. package/src/webgl-types.ts +29 -0
  207. package/dist/types.d.ts +0 -11
  208. package/dist/types.d.ts.map +0 -1
  209. package/dist/types.js.map +0 -1
  210. 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
  }
@@ -1111,7 +1111,7 @@ var __exports__ = (() => {
1111
1111
  "src/context/debug/webgl-developer-tools.ts"() {
1112
1112
  "use strict";
1113
1113
  import_core2 = __toESM(require_core(), 1);
1114
- init_src();
1114
+ init_constants();
1115
1115
  init_dist();
1116
1116
  init_load_script();
1117
1117
  WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
@@ -1983,6 +1983,8 @@ var __exports__ = (() => {
1983
1983
  }
1984
1984
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1985
1985
  switch (gpuVendor) {
1986
+ case "apple":
1987
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1986
1988
  case "intel":
1987
1989
  return "integrated";
1988
1990
  case "software":
@@ -1993,6 +1995,9 @@ var __exports__ = (() => {
1993
1995
  return "discrete";
1994
1996
  }
1995
1997
  }
1998
+ function isAppleSiliconGPU(vendor, renderer) {
1999
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
2000
+ }
1996
2001
  var init_webgl_device_info = __esm({
1997
2002
  "src/adapter/device-helpers/webgl-device-info.ts"() {
1998
2003
  "use strict";
@@ -2041,8 +2046,27 @@ var __exports__ = (() => {
2041
2046
  return feature in TEXTURE_FEATURES;
2042
2047
  }
2043
2048
  function checkTextureFeature(gl, feature, extensions) {
2044
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
2045
- 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
+ );
2046
2070
  }
2047
2071
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
2048
2072
  let supported = formatSupport.create;
@@ -2053,12 +2077,17 @@ var __exports__ = (() => {
2053
2077
  if (webglFormatInfo?.x) {
2054
2078
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
2055
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);
2056
2085
  return {
2057
2086
  format: formatSupport.format,
2058
2087
  // @ts-ignore
2059
2088
  create: supported && formatSupport.create,
2060
2089
  // @ts-ignore
2061
- render: supported && formatSupport.render,
2090
+ render: renderable,
2062
2091
  // @ts-ignore
2063
2092
  filter: supported && formatSupport.filter,
2064
2093
  // @ts-ignore
@@ -2067,6 +2096,45 @@ var __exports__ = (() => {
2067
2096
  store: supported && formatSupport.store
2068
2097
  };
2069
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
+ }
2070
2138
  function getTextureFormatWebGL(format) {
2071
2139
  const formatData = WEBGL_TEXTURE_FORMATS[format];
2072
2140
  const webglFormat = convertTextureFormatToGL(format);
@@ -2122,7 +2190,7 @@ var __exports__ = (() => {
2122
2190
  }
2123
2191
  return webglFormat;
2124
2192
  }
2125
- 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;
2126
2194
  var init_webgl_texture_table = __esm({
2127
2195
  "src/adapter/converters/webgl-texture-table.ts"() {
2128
2196
  "use strict";
@@ -2141,44 +2209,51 @@ var __exports__ = (() => {
2141
2209
  EXT_texture_norm16 = "EXT_texture_norm16";
2142
2210
  EXT_render_snorm = "EXT_render_snorm";
2143
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";
2144
2218
  TEXTURE_FEATURES = {
2145
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
2146
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
2147
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
2148
- "snorm8-renderable-webgl": [EXT_render_snorm],
2149
- "norm16-renderable-webgl": [EXT_texture_norm16],
2150
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
2151
- "float32-filterable": ["OES_texture_float_linear"],
2152
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
2153
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
2154
- "texture-blend-float-webgl": ["EXT_float_blend"],
2155
- "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] },
2156
2231
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
2157
2232
  // 'texture-compression-bc3-webgl': [X_S3TC],
2158
- "texture-compression-bc5-webgl": [X_RGTC],
2159
- "texture-compression-bc7-webgl": [X_BPTC],
2160
- "texture-compression-etc2": [X_ETC2],
2161
- "texture-compression-astc": [X_ASTC],
2162
- "texture-compression-etc1-webgl": [X_ETC1],
2163
- "texture-compression-pvrtc-webgl": [X_PVRTC],
2164
- "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] }
2165
2240
  };
2166
2241
  WEBGL_TEXTURE_FORMATS = {
2167
2242
  // 8-bit formats
2168
2243
  "r8unorm": { gl: 33321 /* R8 */, rb: true },
2169
- "r8snorm": { gl: 36756 /* R8_SNORM */ },
2244
+ "r8snorm": { gl: 36756 /* R8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2170
2245
  "r8uint": { gl: 33330 /* R8UI */, rb: true },
2171
2246
  "r8sint": { gl: 33329 /* R8I */, rb: true },
2172
2247
  // 16-bit formats
2173
2248
  "rg8unorm": { gl: 33323 /* RG8 */, rb: true },
2174
- "rg8snorm": { gl: 36757 /* RG8_SNORM */ },
2249
+ "rg8snorm": { gl: 36757 /* RG8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2175
2250
  "rg8uint": { gl: 33336 /* RG8UI */, rb: true },
2176
2251
  "rg8sint": { gl: 33335 /* RG8I */, rb: true },
2177
2252
  "r16uint": { gl: 33332 /* R16UI */, rb: true },
2178
2253
  "r16sint": { gl: 33331 /* R16I */, rb: true },
2179
- "r16float": { gl: 33325 /* R16F */, rb: true },
2180
- "r16unorm": { gl: 33322 /* R16_EXT */, rb: true },
2181
- "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 },
2182
2257
  // Packed 16-bit formats
2183
2258
  "rgba4unorm-webgl": { gl: 32854 /* RGBA4 */, rb: true },
2184
2259
  "rgb565unorm-webgl": { gl: 36194 /* RGB565 */, rb: true },
@@ -2189,7 +2264,7 @@ var __exports__ = (() => {
2189
2264
  // 32-bit formats
2190
2265
  "rgba8unorm": { gl: 32856 /* RGBA8 */ },
2191
2266
  "rgba8unorm-srgb": { gl: 35907 /* SRGB8_ALPHA8 */ },
2192
- "rgba8snorm": { gl: 36759 /* RGBA8_SNORM */ },
2267
+ "rgba8snorm": { gl: 36759 /* RGBA8_SNORM */, r: SNORM8_COLOR_RENDERABLE },
2193
2268
  "rgba8uint": { gl: 36220 /* RGBA8UI */ },
2194
2269
  "rgba8sint": { gl: 36238 /* RGBA8I */ },
2195
2270
  // reverse colors, webgpu only
@@ -2197,38 +2272,38 @@ var __exports__ = (() => {
2197
2272
  "bgra8unorm-srgb": {},
2198
2273
  "rg16uint": { gl: 33338 /* RG16UI */ },
2199
2274
  "rg16sint": { gl: 33337 /* RG16I */ },
2200
- "rg16float": { gl: 33327 /* RG16F */, rb: true },
2201
- "rg16unorm": { gl: 33324 /* RG16_EXT */ },
2202
- "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 },
2203
2278
  "r32uint": { gl: 33334 /* R32UI */, rb: true },
2204
2279
  "r32sint": { gl: 33333 /* R32I */, rb: true },
2205
- "r32float": { gl: 33326 /* R32F */ },
2280
+ "r32float": { gl: 33326 /* R32F */, r: FLOAT32_COLOR_RENDERABLE },
2206
2281
  // Packed 32-bit formats
2207
- "rgb9e5ufloat": { gl: 35901 /* RGB9_E5 */ },
2282
+ "rgb9e5ufloat": { gl: 35901 /* RGB9_E5 */, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
2208
2283
  // , filter: true},
2209
2284
  "rg11b10ufloat": { gl: 35898 /* R11F_G11F_B10F */, rb: true },
2210
2285
  "rgb10a2unorm": { gl: 32857 /* RGB10_A2 */, rb: true },
2211
2286
  "rgb10a2uint": { gl: 36975 /* RGB10_A2UI */, rb: true },
2212
2287
  // 48-bit formats
2213
- "rgb16unorm-webgl": { gl: 32852 /* RGB16_EXT */ },
2288
+ "rgb16unorm-webgl": { gl: 32852 /* RGB16_EXT */, r: false },
2214
2289
  // rgb not renderable
2215
- "rgb16snorm-webgl": { gl: 36762 /* RGB16_SNORM_EXT */ },
2290
+ "rgb16snorm-webgl": { gl: 36762 /* RGB16_SNORM_EXT */, r: false },
2216
2291
  // rgb not renderable
2217
2292
  // 64-bit formats
2218
2293
  "rg32uint": { gl: 33340 /* RG32UI */, rb: true },
2219
2294
  "rg32sint": { gl: 33339 /* RG32I */, rb: true },
2220
- "rg32float": { gl: 33328 /* RG32F */, rb: true },
2295
+ "rg32float": { gl: 33328 /* RG32F */, rb: true, r: FLOAT32_COLOR_RENDERABLE },
2221
2296
  "rgba16uint": { gl: 36214 /* RGBA16UI */, rb: true },
2222
2297
  "rgba16sint": { gl: 36232 /* RGBA16I */, rb: true },
2223
- "rgba16float": { gl: 34842 /* RGBA16F */ },
2224
- "rgba16unorm": { gl: 32859 /* RGBA16_EXT */, rb: true },
2225
- "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 },
2226
2301
  // 96-bit formats (deprecated!)
2227
- "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 */] },
2228
2303
  // 128-bit formats
2229
2304
  "rgba32uint": { gl: 36208 /* RGBA32UI */, rb: true },
2230
2305
  "rgba32sint": { gl: 36226 /* RGBA32I */, rb: true },
2231
- "rgba32float": { gl: 34836 /* RGBA32F */, rb: true },
2306
+ "rgba32float": { gl: 34836 /* RGBA32F */, rb: true, r: FLOAT32_COLOR_RENDERABLE },
2232
2307
  // Depth and stencil formats
2233
2308
  "stencil8": { gl: 36168 /* STENCIL_INDEX8 */, rb: true },
2234
2309
  // 8 stencil bits
@@ -2286,8 +2361,8 @@ var __exports__ = (() => {
2286
2361
  "astc-8x6-unorm-srgb": { gl: 37846 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR */ },
2287
2362
  "astc-8x8-unorm": { gl: 37815 /* COMPRESSED_RGBA_ASTC_8x8_KHR */ },
2288
2363
  "astc-8x8-unorm-srgb": { gl: 37847 /* COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR */ },
2289
- "astc-10x5-unorm": { gl: 37819 /* COMPRESSED_RGBA_ASTC_10x10_KHR */ },
2290
- "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 */ },
2291
2366
  "astc-10x6-unorm": { gl: 37817 /* COMPRESSED_RGBA_ASTC_10x6_KHR */ },
2292
2367
  "astc-10x6-unorm-srgb": { gl: 37849 /* COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR */ },
2293
2368
  "astc-10x8-unorm": { gl: 37818 /* COMPRESSED_RGBA_ASTC_10x8_KHR */ },
@@ -2301,7 +2376,7 @@ var __exports__ = (() => {
2301
2376
  // WEBGL_compressed_texture_pvrtc
2302
2377
  "pvrtc-rgb4unorm-webgl": { gl: 35840 /* COMPRESSED_RGB_PVRTC_4BPPV1_IMG */ },
2303
2378
  "pvrtc-rgba4unorm-webgl": { gl: 35842 /* COMPRESSED_RGBA_PVRTC_4BPPV1_IMG */ },
2304
- "pvrtc-rbg2unorm-webgl": { gl: 35841 /* COMPRESSED_RGB_PVRTC_2BPPV1_IMG */ },
2379
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 /* COMPRESSED_RGB_PVRTC_2BPPV1_IMG */ },
2305
2380
  "pvrtc-rgba2unorm-webgl": { gl: 35843 /* COMPRESSED_RGBA_PVRTC_2BPPV1_IMG */ },
2306
2381
  // WEBGL_compressed_texture_etc1
2307
2382
  "etc1-rbg-unorm-webgl": { gl: 36196 /* COMPRESSED_RGB_ETC1_WEBGL */ },
@@ -2325,12 +2400,11 @@ var __exports__ = (() => {
2325
2400
  // optional WebGPU features
2326
2401
  "depth-clip-control": "EXT_depth_clamp",
2327
2402
  // TODO these seem subtly different
2328
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2403
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2329
2404
  // "indirect-first-instance"
2330
2405
  // Textures are handled by getTextureFeatures()
2331
2406
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2332
2407
  // optional WebGL features
2333
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2334
2408
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2335
2409
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2336
2410
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2630,6 +2704,15 @@ var __exports__ = (() => {
2630
2704
  }
2631
2705
  gl.bindTexture(texture.glTarget, null);
2632
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
+ }
2633
2716
  };
2634
2717
  }
2635
2718
  });
@@ -2675,6 +2758,65 @@ var __exports__ = (() => {
2675
2758
  }
2676
2759
  });
2677
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);
2815
+ }
2816
+ };
2817
+ }
2818
+ });
2819
+
2678
2820
  // src/utils/uid.ts
2679
2821
  function uid(id = "id") {
2680
2822
  uidCounters[id] = uidCounters[id] || 1;
@@ -2691,35 +2833,35 @@ var __exports__ = (() => {
2691
2833
 
2692
2834
  // src/adapter/resources/webgl-buffer.ts
2693
2835
  function getWebGLTarget(usage) {
2694
- if (usage & import_core8.Buffer.INDEX) {
2836
+ if (usage & import_core9.Buffer.INDEX) {
2695
2837
  return 34963 /* ELEMENT_ARRAY_BUFFER */;
2696
2838
  }
2697
- if (usage & import_core8.Buffer.VERTEX) {
2839
+ if (usage & import_core9.Buffer.VERTEX) {
2698
2840
  return 34962 /* ARRAY_BUFFER */;
2699
2841
  }
2700
- if (usage & import_core8.Buffer.UNIFORM) {
2842
+ if (usage & import_core9.Buffer.UNIFORM) {
2701
2843
  return 35345 /* UNIFORM_BUFFER */;
2702
2844
  }
2703
2845
  return 34962 /* ARRAY_BUFFER */;
2704
2846
  }
2705
2847
  function getWebGLUsage(usage) {
2706
- if (usage & import_core8.Buffer.INDEX) {
2848
+ if (usage & import_core9.Buffer.INDEX) {
2707
2849
  return 35044 /* STATIC_DRAW */;
2708
2850
  }
2709
- if (usage & import_core8.Buffer.VERTEX) {
2851
+ if (usage & import_core9.Buffer.VERTEX) {
2710
2852
  return 35044 /* STATIC_DRAW */;
2711
2853
  }
2712
- if (usage & import_core8.Buffer.UNIFORM) {
2854
+ if (usage & import_core9.Buffer.UNIFORM) {
2713
2855
  return 35048 /* DYNAMIC_DRAW */;
2714
2856
  }
2715
2857
  return 35044 /* STATIC_DRAW */;
2716
2858
  }
2717
- var import_core8, WEBGLBuffer;
2859
+ var import_core9, WEBGLBuffer;
2718
2860
  var init_webgl_buffer = __esm({
2719
2861
  "src/adapter/resources/webgl-buffer.ts"() {
2720
2862
  "use strict";
2721
- import_core8 = __toESM(require_core(), 1);
2722
- WEBGLBuffer = class extends import_core8.Buffer {
2863
+ import_core9 = __toESM(require_core(), 1);
2864
+ WEBGLBuffer = class extends import_core9.Buffer {
2723
2865
  device;
2724
2866
  gl;
2725
2867
  handle;
@@ -2754,8 +2896,12 @@ var __exports__ = (() => {
2754
2896
  destroy() {
2755
2897
  if (!this.destroyed && this.handle) {
2756
2898
  this.removeStats();
2757
- this.trackDeallocatedMemory();
2758
- 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
+ }
2759
2905
  this.destroyed = true;
2760
2906
  this.handle = null;
2761
2907
  }
@@ -2770,7 +2916,11 @@ var __exports__ = (() => {
2770
2916
  this.bytesUsed = byteLength;
2771
2917
  this.byteLength = byteLength;
2772
2918
  this._setDebugData(data, byteOffset, byteLength);
2773
- this.trackAllocatedMemory(byteLength);
2919
+ if (!this.props.handle) {
2920
+ this.trackAllocatedMemory(byteLength);
2921
+ } else {
2922
+ this.trackReferencedMemory(byteLength, "Buffer");
2923
+ }
2774
2924
  }
2775
2925
  // Allocate a GPU buffer of specified size.
2776
2926
  _initWithByteLength(byteLength) {
@@ -2785,7 +2935,11 @@ var __exports__ = (() => {
2785
2935
  this.bytesUsed = byteLength;
2786
2936
  this.byteLength = byteLength;
2787
2937
  this._setDebugData(null, 0, byteLength);
2788
- this.trackAllocatedMemory(byteLength);
2938
+ if (!this.props.handle) {
2939
+ this.trackAllocatedMemory(byteLength);
2940
+ } else {
2941
+ this.trackReferencedMemory(byteLength, "Buffer");
2942
+ }
2789
2943
  return this;
2790
2944
  }
2791
2945
  write(data, byteOffset = 0) {
@@ -2898,13 +3052,13 @@ var __exports__ = (() => {
2898
3052
  });
2899
3053
 
2900
3054
  // src/adapter/resources/webgl-shader.ts
2901
- var import_core9, WEBGLShader;
3055
+ var import_core10, WEBGLShader;
2902
3056
  var init_webgl_shader = __esm({
2903
3057
  "src/adapter/resources/webgl-shader.ts"() {
2904
3058
  "use strict";
2905
- import_core9 = __toESM(require_core(), 1);
3059
+ import_core10 = __toESM(require_core(), 1);
2906
3060
  init_parse_shader_compiler_log();
2907
- WEBGLShader = class extends import_core9.Shader {
3061
+ WEBGLShader = class extends import_core10.Shader {
2908
3062
  device;
2909
3063
  handle;
2910
3064
  constructor(device, props) {
@@ -2921,7 +3075,12 @@ var __exports__ = (() => {
2921
3075
  throw new Error(this.props.stage);
2922
3076
  }
2923
3077
  device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
2924
- 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
+ }
2925
3084
  }
2926
3085
  destroy() {
2927
3086
  if (this.handle) {
@@ -2952,7 +3111,7 @@ var __exports__ = (() => {
2952
3111
  }
2953
3112
  // PRIVATE METHODS
2954
3113
  /** Compile a shader and get compilation status */
2955
- async _compile(source) {
3114
+ _compile(source) {
2956
3115
  source = source.startsWith("#version ") ? source : `#version 300 es
2957
3116
  ${source}`;
2958
3117
  const { gl } = this.device;
@@ -2970,11 +3129,12 @@ ${source}`;
2970
3129
  }
2971
3130
  return;
2972
3131
  }
2973
- import_core9.log.once(1, "Shader compilation is asynchronous")();
2974
- await this._waitForCompilationComplete();
2975
- import_core9.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2976
- this._getCompilationStatus();
2977
- 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
+ });
2978
3138
  }
2979
3139
  /** Use KHR_parallel_shader_compile extension if available */
2980
3140
  async _waitForCompilationComplete() {
@@ -3133,13 +3293,16 @@ ${source}`;
3133
3293
  parameters.depthCompare !== "always" ? gl.enable(2929 /* DEPTH_TEST */) : gl.disable(2929 /* DEPTH_TEST */);
3134
3294
  gl.depthFunc(convertCompareFunction("depthCompare", parameters.depthCompare));
3135
3295
  }
3296
+ if (parameters.clearDepth !== void 0) {
3297
+ gl.clearDepth(parameters.clearDepth);
3298
+ }
3136
3299
  if (parameters.stencilWriteMask) {
3137
3300
  const mask = parameters.stencilWriteMask;
3138
3301
  gl.stencilMaskSeparate(1028 /* FRONT */, mask);
3139
3302
  gl.stencilMaskSeparate(1029 /* BACK */, mask);
3140
3303
  }
3141
3304
  if (parameters.stencilReadMask) {
3142
- import_core10.log.warn("stencilReadMask not supported under WebGL");
3305
+ import_core11.log.warn("stencilReadMask not supported under WebGL");
3143
3306
  }
3144
3307
  if (parameters.stencilCompare) {
3145
3308
  const mask = parameters.stencilReadMask || 4294967295;
@@ -3273,11 +3436,11 @@ ${source}`;
3273
3436
  }
3274
3437
  return isEmpty;
3275
3438
  }
3276
- var import_core10;
3439
+ var import_core11;
3277
3440
  var init_device_parameters = __esm({
3278
3441
  "src/adapter/converters/device-parameters.ts"() {
3279
3442
  "use strict";
3280
- import_core10 = __toESM(require_core(), 1);
3443
+ import_core11 = __toESM(require_core(), 1);
3281
3444
  init_unified_parameter_api();
3282
3445
  }
3283
3446
  });
@@ -3370,13 +3533,13 @@ ${source}`;
3370
3533
  });
3371
3534
 
3372
3535
  // src/adapter/resources/webgl-sampler.ts
3373
- var import_core11, WEBGLSampler;
3536
+ var import_core12, WEBGLSampler;
3374
3537
  var init_webgl_sampler = __esm({
3375
3538
  "src/adapter/resources/webgl-sampler.ts"() {
3376
3539
  "use strict";
3377
- import_core11 = __toESM(require_core(), 1);
3540
+ import_core12 = __toESM(require_core(), 1);
3378
3541
  init_sampler_parameters();
3379
- WEBGLSampler = class extends import_core11.Sampler {
3542
+ WEBGLSampler = class extends import_core12.Sampler {
3380
3543
  device;
3381
3544
  handle;
3382
3545
  parameters;
@@ -3452,19 +3615,19 @@ ${source}`;
3452
3615
  });
3453
3616
 
3454
3617
  // src/adapter/resources/webgl-texture-view.ts
3455
- var import_core12, WEBGLTextureView;
3618
+ var import_core13, WEBGLTextureView;
3456
3619
  var init_webgl_texture_view = __esm({
3457
3620
  "src/adapter/resources/webgl-texture-view.ts"() {
3458
3621
  "use strict";
3459
- import_core12 = __toESM(require_core(), 1);
3460
- WEBGLTextureView = class extends import_core12.TextureView {
3622
+ import_core13 = __toESM(require_core(), 1);
3623
+ WEBGLTextureView = class extends import_core13.TextureView {
3461
3624
  device;
3462
3625
  gl;
3463
3626
  handle;
3464
3627
  // Does not have a WebGL representation
3465
3628
  texture;
3466
3629
  constructor(device, props) {
3467
- super(device, { ...import_core12.Texture.defaultProps, ...props });
3630
+ super(device, { ...import_core13.Texture.defaultProps, ...props });
3468
3631
  this.device = device;
3469
3632
  this.gl = this.device.gl;
3470
3633
  this.handle = null;
@@ -3474,98 +3637,6 @@ ${source}`;
3474
3637
  }
3475
3638
  });
3476
3639
 
3477
- // src/adapter/converters/webgl-shadertypes.ts
3478
- function convertDataTypeToGLDataType(normalizedType) {
3479
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3480
- }
3481
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
3482
- return WEBGL_SHADER_TYPES[glUniformType];
3483
- }
3484
- function isGLSamplerType(type) {
3485
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3486
- }
3487
- function getTextureBindingFromGLSamplerType(glSamplerType) {
3488
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3489
- }
3490
- var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL, WEBGL_TO_NORMALIZED_DATA_TYPE;
3491
- var init_webgl_shadertypes = __esm({
3492
- "src/adapter/converters/webgl-shadertypes.ts"() {
3493
- "use strict";
3494
- WEBGL_SHADER_TYPES = {
3495
- [5126 /* FLOAT */]: "f32",
3496
- [35664 /* FLOAT_VEC2 */]: "vec2<f32>",
3497
- [35665 /* FLOAT_VEC3 */]: "vec3<f32>",
3498
- [35666 /* FLOAT_VEC4 */]: "vec4<f32>",
3499
- [5124 /* INT */]: "i32",
3500
- [35667 /* INT_VEC2 */]: "vec2<i32>",
3501
- [35668 /* INT_VEC3 */]: "vec3<i32>",
3502
- [35669 /* INT_VEC4 */]: "vec4<i32>",
3503
- [5125 /* UNSIGNED_INT */]: "u32",
3504
- [36294 /* UNSIGNED_INT_VEC2 */]: "vec2<u32>",
3505
- [36295 /* UNSIGNED_INT_VEC3 */]: "vec3<u32>",
3506
- [36296 /* UNSIGNED_INT_VEC4 */]: "vec4<u32>",
3507
- [35670 /* BOOL */]: "f32",
3508
- [35671 /* BOOL_VEC2 */]: "vec2<f32>",
3509
- [35672 /* BOOL_VEC3 */]: "vec3<f32>",
3510
- [35673 /* BOOL_VEC4 */]: "vec4<f32>",
3511
- // TODO - are sizes/components below correct?
3512
- [35674 /* FLOAT_MAT2 */]: "mat2x2<f32>",
3513
- [35685 /* FLOAT_MAT2x3 */]: "mat2x3<f32>",
3514
- [35686 /* FLOAT_MAT2x4 */]: "mat2x4<f32>",
3515
- [35687 /* FLOAT_MAT3x2 */]: "mat3x2<f32>",
3516
- [35675 /* FLOAT_MAT3 */]: "mat3x3<f32>",
3517
- [35688 /* FLOAT_MAT3x4 */]: "mat3x4<f32>",
3518
- [35689 /* FLOAT_MAT4x2 */]: "mat4x2<f32>",
3519
- [35690 /* FLOAT_MAT4x3 */]: "mat4x3<f32>",
3520
- [35676 /* FLOAT_MAT4 */]: "mat4x4<f32>"
3521
- };
3522
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3523
- [35678 /* SAMPLER_2D */]: { viewDimension: "2d", sampleType: "float" },
3524
- [35680 /* SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "float" },
3525
- [35679 /* SAMPLER_3D */]: { viewDimension: "3d", sampleType: "float" },
3526
- [35682 /* SAMPLER_2D_SHADOW */]: { viewDimension: "3d", sampleType: "depth" },
3527
- [36289 /* SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "float" },
3528
- [36292 /* SAMPLER_2D_ARRAY_SHADOW */]: { viewDimension: "2d-array", sampleType: "depth" },
3529
- [36293 /* SAMPLER_CUBE_SHADOW */]: { viewDimension: "cube", sampleType: "float" },
3530
- [36298 /* INT_SAMPLER_2D */]: { viewDimension: "2d", sampleType: "sint" },
3531
- [36299 /* INT_SAMPLER_3D */]: { viewDimension: "3d", sampleType: "sint" },
3532
- [36300 /* INT_SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "sint" },
3533
- [36303 /* INT_SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "uint" },
3534
- [36306 /* UNSIGNED_INT_SAMPLER_2D */]: { viewDimension: "2d", sampleType: "uint" },
3535
- [36307 /* UNSIGNED_INT_SAMPLER_3D */]: { viewDimension: "3d", sampleType: "uint" },
3536
- [36308 /* UNSIGNED_INT_SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "uint" },
3537
- [36311 /* UNSIGNED_INT_SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "uint" }
3538
- };
3539
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3540
- uint8: 5121 /* UNSIGNED_BYTE */,
3541
- sint8: 5120 /* BYTE */,
3542
- unorm8: 5121 /* UNSIGNED_BYTE */,
3543
- snorm8: 5120 /* BYTE */,
3544
- uint16: 5123 /* UNSIGNED_SHORT */,
3545
- sint16: 5122 /* SHORT */,
3546
- unorm16: 5123 /* UNSIGNED_SHORT */,
3547
- snorm16: 5122 /* SHORT */,
3548
- uint32: 5125 /* UNSIGNED_INT */,
3549
- sint32: 5124 /* INT */,
3550
- // WebGPU does not support normalized 32 bit integer attributes
3551
- // 'unorm32': GL.UNSIGNED_INT,
3552
- // 'snorm32': GL.INT,
3553
- float16: 5131 /* HALF_FLOAT */,
3554
- float32: 5126 /* FLOAT */
3555
- };
3556
- WEBGL_TO_NORMALIZED_DATA_TYPE = {
3557
- [5120 /* BYTE */]: ["sint8", "snorm16"],
3558
- [5121 /* UNSIGNED_BYTE */]: ["uint8", "unorm8"],
3559
- [5122 /* SHORT */]: ["sint16", "unorm16"],
3560
- [5123 /* UNSIGNED_SHORT */]: ["uint16", "unorm16"],
3561
- [5124 /* INT */]: ["sint32", "sint32"],
3562
- [5125 /* UNSIGNED_INT */]: ["uint32", "uint32"],
3563
- [5126 /* FLOAT */]: ["float32", "float32"],
3564
- [5131 /* HALF_FLOAT */]: ["float16", "float16"]
3565
- };
3566
- }
3567
- });
3568
-
3569
3640
  // src/adapter/converters/shader-formats.ts
3570
3641
  function convertGLDataTypeToDataType(type) {
3571
3642
  return GL_DATA_TYPE_MAP[type];
@@ -3596,6 +3667,24 @@ ${source}`;
3596
3667
  });
3597
3668
 
3598
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
+ }
3599
3688
  function getWebGLTextureTarget(dimension) {
3600
3689
  switch (dimension) {
3601
3690
  case "1d":
@@ -3616,19 +3705,17 @@ ${source}`;
3616
3705
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3617
3706
  return dimension === "cube" ? 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ + level : glTarget;
3618
3707
  }
3619
- var import_core13, import_core14, WEBGLTexture;
3708
+ var import_core14, WEBGLTexture;
3620
3709
  var init_webgl_texture = __esm({
3621
3710
  "src/adapter/resources/webgl-texture.ts"() {
3622
3711
  "use strict";
3623
- import_core13 = __toESM(require_core(), 1);
3712
+ import_core14 = __toESM(require_core(), 1);
3624
3713
  init_webgl_texture_table();
3625
3714
  init_sampler_parameters();
3626
3715
  init_with_parameters();
3627
3716
  init_webgl_texture_view();
3628
- init_webgl_shadertypes();
3629
3717
  init_shader_formats();
3630
- import_core14 = __toESM(require_core(), 1);
3631
- WEBGLTexture = class extends import_core13.Texture {
3718
+ WEBGLTexture = class extends import_core14.Texture {
3632
3719
  // readonly MAX_ATTRIBUTES: number;
3633
3720
  device;
3634
3721
  gl;
@@ -3657,8 +3744,10 @@ ${source}`;
3657
3744
  // state
3658
3745
  /** Texture binding slot - TODO - move to texture view? */
3659
3746
  _textureUnit = 0;
3660
- /** Chached framebuffer */
3747
+ /** Cached framebuffer reused for color texture readback. */
3661
3748
  _framebuffer = null;
3749
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3750
+ _framebufferAttachmentKey = null;
3662
3751
  constructor(device, props) {
3663
3752
  super(device, props, { byteAlignment: 1 });
3664
3753
  this.device = device;
@@ -3673,20 +3762,27 @@ ${source}`;
3673
3762
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3674
3763
  this.gl.bindTexture(this.glTarget, this.handle);
3675
3764
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3676
- switch (dimension) {
3677
- case "2d":
3678
- case "cube":
3679
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3680
- break;
3681
- case "2d-array":
3682
- case "3d":
3683
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3684
- break;
3685
- default:
3686
- 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
+ }
3687
3778
  }
3688
3779
  this.gl.bindTexture(this.glTarget, null);
3689
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
+ }
3690
3786
  this.setSampler(this.props.sampler);
3691
3787
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3692
3788
  Object.seal(this);
@@ -3695,9 +3791,14 @@ ${source}`;
3695
3791
  if (this.handle) {
3696
3792
  this._framebuffer?.destroy();
3697
3793
  this._framebuffer = null;
3698
- this.gl.deleteTexture(this.handle);
3794
+ this._framebufferAttachmentKey = null;
3699
3795
  this.removeStats();
3700
- 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
+ }
3701
3802
  this.destroyed = true;
3702
3803
  }
3703
3804
  }
@@ -3736,21 +3837,115 @@ ${source}`;
3736
3837
  return { width: options.width, height: options.height };
3737
3838
  }
3738
3839
  copyImageData(options_) {
3739
- const options = this._normalizeCopyImageDataOptions(options_);
3740
- const typedArray = options.data;
3741
- const { width, height, depth, z = 0 } = options;
3742
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0 } = 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
+ );
3859
+ }
3860
+ const webglBuffer = buffer;
3861
+ this.gl.bindBuffer(35051 /* PIXEL_PACK_BUFFER */, webglBuffer.handle);
3862
+ try {
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
+ });
3874
+ } finally {
3875
+ this.gl.bindBuffer(35051 /* PIXEL_PACK_BUFFER */, null);
3876
+ }
3877
+ return buffer;
3878
+ }
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
+ };
3899
+ this.gl.bindTexture(this.glTarget, this.handle);
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;
3743
3943
  const { glFormat, glType, compressed } = this;
3744
3944
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3745
3945
  let unpackRowLength;
3746
- if (!this.compressed) {
3946
+ if (!compressed) {
3747
3947
  const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3748
3948
  if (bytesPerPixel) {
3749
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3750
- throw new Error(
3751
- `bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`
3752
- );
3753
- }
3754
3949
  unpackRowLength = options.bytesPerRow / bytesPerPixel;
3755
3950
  }
3756
3951
  }
@@ -3759,23 +3954,56 @@ ${source}`;
3759
3954
  ...unpackRowLength !== void 0 ? { [3314 /* UNPACK_ROW_LENGTH */]: unpackRowLength } : {},
3760
3955
  [32878 /* UNPACK_IMAGE_HEIGHT */]: options.rowsPerImage
3761
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;
3762
3961
  this.gl.bindTexture(this.glTarget, this.handle);
3962
+ this.gl.bindBuffer(35052 /* PIXEL_UNPACK_BUFFER */, null);
3763
3963
  withGLParameters(this.gl, glParameters, () => {
3764
3964
  switch (this.dimension) {
3765
3965
  case "2d":
3766
3966
  case "cube":
3767
3967
  if (compressed) {
3768
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
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
+ }
3769
3973
  } else {
3770
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3974
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3771
3975
  }
3772
3976
  break;
3773
3977
  case "2d-array":
3774
3978
  case "3d":
3775
3979
  if (compressed) {
3776
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
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
+ }
3777
4005
  } else {
3778
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
4006
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
3779
4007
  }
3780
4008
  break;
3781
4009
  default:
@@ -3783,53 +4011,6 @@ ${source}`;
3783
4011
  });
3784
4012
  this.gl.bindTexture(this.glTarget, null);
3785
4013
  }
3786
- readBuffer(options = {}, buffer) {
3787
- throw new Error("readBuffer not implemented");
3788
- }
3789
- async readDataAsync(options = {}) {
3790
- return this.readDataSyncWebGL(options);
3791
- }
3792
- writeBuffer(buffer, options_ = {}) {
3793
- }
3794
- writeData(data, options_ = {}) {
3795
- const options = this._normalizeTextureWriteOptions(options_);
3796
- const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3797
- const {} = this;
3798
- const { width, height, mipLevel, x, y, z } = options;
3799
- const { glFormat, glType, compressed } = this;
3800
- const depth = 0;
3801
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3802
- const glParameters = !this.compressed ? {
3803
- // WebGL does not require byte alignment, but allows it to be specified
3804
- [3317 /* UNPACK_ALIGNMENT */]: this.byteAlignment
3805
- // [GL.UNPACK_ROW_LENGTH]: bytesPerRow,
3806
- // [GL.UNPACK_IMAGE_HEIGHT]: rowsPerImage
3807
- } : {};
3808
- this.gl.bindTexture(glTarget, this.handle);
3809
- this.gl.bindBuffer(35052 /* PIXEL_UNPACK_BUFFER */, null);
3810
- withGLParameters(this.gl, glParameters, () => {
3811
- switch (this.dimension) {
3812
- case "2d":
3813
- case "cube":
3814
- if (compressed) {
3815
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray);
3816
- } else {
3817
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray);
3818
- }
3819
- break;
3820
- case "2d-array":
3821
- case "3d":
3822
- if (compressed) {
3823
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray);
3824
- } else {
3825
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray);
3826
- }
3827
- break;
3828
- default:
3829
- }
3830
- });
3831
- this.gl.bindTexture(glTarget, null);
3832
- }
3833
4014
  // IMPLEMENTATION SPECIFIC
3834
4015
  /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
3835
4016
  _getRowByteAlignment(format, width) {
@@ -3850,30 +4031,107 @@ ${source}`;
3850
4031
  }
3851
4032
  // WEBGL SPECIFIC
3852
4033
  readDataSyncWebGL(options_ = {}) {
3853
- const options = this._normalizeTextureReadOptions(options_);
4034
+ const options = this._getSupportedColorReadOptions(options_);
3854
4035
  const memoryLayout = this.computeMemoryLayout(options);
3855
4036
  const shaderType = convertGLDataTypeToDataType(this.glType);
3856
4037
  const ArrayType = (0, import_core14.getTypedArrayConstructor)(shaderType);
3857
- const targetArray = new ArrayType(memoryLayout.byteLength);
3858
- const signedType = (0, import_core14.getDataType)(targetArray);
3859
- const sourceType = convertDataTypeToGLDataType(signedType);
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) {
3860
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 */);
3861
4069
  const prevHandle = this.gl.bindFramebuffer(
3862
4070
  36160 /* FRAMEBUFFER */,
3863
4071
  framebuffer.handle
3864
4072
  );
3865
- this.gl.readBuffer(36064 /* COLOR_ATTACHMENT0 */);
3866
- this.gl.readPixels(
3867
- options.x,
3868
- options.y,
3869
- options.width,
3870
- options.height,
3871
- this.glFormat,
3872
- sourceType,
3873
- targetArray
3874
- );
3875
- this.gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle || null);
3876
- return targetArray.buffer;
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;
3877
4135
  }
3878
4136
  /**
3879
4137
  * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
@@ -3881,7 +4139,7 @@ ${source}`;
3881
4139
  generateMipmapsWebGL(options) {
3882
4140
  const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3883
4141
  if (!isFilterableAndRenderable) {
3884
- import_core13.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
4142
+ import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3885
4143
  if (!options?.force) {
3886
4144
  return;
3887
4145
  }
@@ -3890,7 +4148,7 @@ ${source}`;
3890
4148
  this.gl.bindTexture(this.glTarget, this.handle);
3891
4149
  this.gl.generateMipmap(this.glTarget);
3892
4150
  } catch (error) {
3893
- import_core13.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
4151
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3894
4152
  } finally {
3895
4153
  this.gl.bindTexture(this.glTarget, null);
3896
4154
  }
@@ -3900,7 +4158,7 @@ ${source}`;
3900
4158
  * Sets sampler parameters on texture
3901
4159
  */
3902
4160
  _setSamplerParameters(parameters) {
3903
- import_core13.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
4161
+ import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3904
4162
  this.gl.bindTexture(this.glTarget, this.handle);
3905
4163
  for (const [pname, pvalue] of Object.entries(parameters)) {
3906
4164
  const param = Number(pname);
@@ -3957,210 +4215,6 @@ ${source}`;
3957
4215
  }
3958
4216
  });
3959
4217
 
3960
- // src/adapter/helpers/get-shader-layout-from-glsl.ts
3961
- function getShaderLayoutFromGLSL(gl, program) {
3962
- const shaderLayout = {
3963
- attributes: [],
3964
- bindings: []
3965
- };
3966
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3967
- const uniformBlocks = readUniformBlocks(gl, program);
3968
- for (const uniformBlock of uniformBlocks) {
3969
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3970
- name: uniform.name,
3971
- format: uniform.format,
3972
- byteOffset: uniform.byteOffset,
3973
- byteStride: uniform.byteStride,
3974
- arrayLength: uniform.arrayLength
3975
- }));
3976
- shaderLayout.bindings.push({
3977
- type: "uniform",
3978
- name: uniformBlock.name,
3979
- group: 0,
3980
- location: uniformBlock.location,
3981
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3982
- minBindingSize: uniformBlock.byteLength,
3983
- uniforms: uniforms2
3984
- });
3985
- }
3986
- const uniforms = readUniformBindings(gl, program);
3987
- let textureUnit = 0;
3988
- for (const uniform of uniforms) {
3989
- if (isGLSamplerType(uniform.type)) {
3990
- const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3991
- shaderLayout.bindings.push({
3992
- type: "texture",
3993
- name: uniform.name,
3994
- group: 0,
3995
- location: textureUnit,
3996
- viewDimension,
3997
- sampleType
3998
- });
3999
- uniform.textureUnit = textureUnit;
4000
- textureUnit += 1;
4001
- }
4002
- }
4003
- if (uniforms.length) {
4004
- shaderLayout.uniforms = uniforms;
4005
- }
4006
- const varyings = readVaryings(gl, program);
4007
- if (varyings?.length) {
4008
- shaderLayout.varyings = varyings;
4009
- }
4010
- return shaderLayout;
4011
- }
4012
- function readAttributeDeclarations(gl, program) {
4013
- const attributes = [];
4014
- const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
4015
- for (let index = 0; index < count; index++) {
4016
- const activeInfo = gl.getActiveAttrib(program, index);
4017
- if (!activeInfo) {
4018
- throw new Error("activeInfo");
4019
- }
4020
- const {
4021
- name,
4022
- type: compositeType
4023
- /* , size*/
4024
- } = activeInfo;
4025
- const location = gl.getAttribLocation(program, name);
4026
- if (location >= 0) {
4027
- const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
4028
- const stepMode = /instance/i.test(name) ? "instance" : "vertex";
4029
- attributes.push({
4030
- name,
4031
- location,
4032
- stepMode,
4033
- type: attributeType
4034
- // size - for arrays, size is the number of elements in the array
4035
- });
4036
- }
4037
- }
4038
- attributes.sort((a, b) => a.location - b.location);
4039
- return attributes;
4040
- }
4041
- function readVaryings(gl, program) {
4042
- const varyings = [];
4043
- const count = gl.getProgramParameter(program, 35971 /* TRANSFORM_FEEDBACK_VARYINGS */);
4044
- for (let location = 0; location < count; location++) {
4045
- const activeInfo = gl.getTransformFeedbackVarying(program, location);
4046
- if (!activeInfo) {
4047
- throw new Error("activeInfo");
4048
- }
4049
- const { name, type: glUniformType, size } = activeInfo;
4050
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
4051
- const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
4052
- varyings.push({ location, name, type, size: size * components });
4053
- }
4054
- varyings.sort((a, b) => a.location - b.location);
4055
- return varyings;
4056
- }
4057
- function readUniformBindings(gl, program) {
4058
- const uniforms = [];
4059
- const uniformCount = gl.getProgramParameter(program, 35718 /* ACTIVE_UNIFORMS */);
4060
- for (let i = 0; i < uniformCount; i++) {
4061
- const activeInfo = gl.getActiveUniform(program, i);
4062
- if (!activeInfo) {
4063
- throw new Error("activeInfo");
4064
- }
4065
- const { name: rawName, size, type } = activeInfo;
4066
- const { name, isArray: isArray3 } = parseUniformName(rawName);
4067
- let webglLocation = gl.getUniformLocation(program, name);
4068
- const uniformInfo = {
4069
- // WebGL locations are uniquely typed but just numbers
4070
- location: webglLocation,
4071
- name,
4072
- size,
4073
- type,
4074
- isArray: isArray3
4075
- };
4076
- uniforms.push(uniformInfo);
4077
- if (uniformInfo.size > 1) {
4078
- for (let j = 0; j < uniformInfo.size; j++) {
4079
- const elementName = `${name}[${j}]`;
4080
- webglLocation = gl.getUniformLocation(program, elementName);
4081
- const arrayElementUniformInfo = {
4082
- ...uniformInfo,
4083
- name: elementName,
4084
- location: webglLocation
4085
- };
4086
- uniforms.push(arrayElementUniformInfo);
4087
- }
4088
- }
4089
- }
4090
- return uniforms;
4091
- }
4092
- function readUniformBlocks(gl, program) {
4093
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
4094
- const uniformBlocks = [];
4095
- const blockCount = gl.getProgramParameter(program, 35382 /* ACTIVE_UNIFORM_BLOCKS */);
4096
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
4097
- const blockInfo = {
4098
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
4099
- location: getBlockParameter(blockIndex, 35391 /* UNIFORM_BLOCK_BINDING */),
4100
- byteLength: getBlockParameter(blockIndex, 35392 /* UNIFORM_BLOCK_DATA_SIZE */),
4101
- vertex: getBlockParameter(blockIndex, 35396 /* UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER */),
4102
- fragment: getBlockParameter(blockIndex, 35398 /* UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER */),
4103
- uniformCount: getBlockParameter(blockIndex, 35394 /* UNIFORM_BLOCK_ACTIVE_UNIFORMS */),
4104
- uniforms: []
4105
- };
4106
- const uniformIndices = getBlockParameter(blockIndex, 35395 /* UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES */) || [];
4107
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383 /* UNIFORM_TYPE */);
4108
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384 /* UNIFORM_SIZE */);
4109
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387 /* UNIFORM_OFFSET */);
4110
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388 /* UNIFORM_ARRAY_STRIDE */);
4111
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
4112
- const uniformIndex = uniformIndices[i];
4113
- if (uniformIndex === void 0) {
4114
- continue;
4115
- }
4116
- const activeInfo = gl.getActiveUniform(program, uniformIndex);
4117
- if (!activeInfo) {
4118
- throw new Error("activeInfo");
4119
- }
4120
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
4121
- blockInfo.uniforms.push({
4122
- name: activeInfo.name,
4123
- format,
4124
- type: uniformType[i],
4125
- arrayLength: uniformArrayLength[i],
4126
- byteOffset: uniformOffset[i],
4127
- byteStride: uniformStride[i]
4128
- // matrixStride: uniformStride[i],
4129
- // rowMajor: uniformRowMajor[i]
4130
- });
4131
- }
4132
- uniformBlocks.push(blockInfo);
4133
- }
4134
- uniformBlocks.sort((a, b) => a.location - b.location);
4135
- return uniformBlocks;
4136
- }
4137
- function parseUniformName(name) {
4138
- if (name[name.length - 1] !== "]") {
4139
- return {
4140
- name,
4141
- length: 1,
4142
- isArray: false
4143
- };
4144
- }
4145
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
4146
- const matches = UNIFORM_NAME_REGEXP.exec(name);
4147
- const uniformName = (0, import_core15.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
4148
- return {
4149
- name: uniformName,
4150
- // TODO - is this a bug, shouldn't we return the value?
4151
- length: matches?.[2] ? 1 : 0,
4152
- isArray: Boolean(matches?.[2])
4153
- };
4154
- }
4155
- var import_core15;
4156
- var init_get_shader_layout_from_glsl = __esm({
4157
- "src/adapter/helpers/get-shader-layout-from-glsl.ts"() {
4158
- "use strict";
4159
- import_core15 = __toESM(require_core(), 1);
4160
- init_webgl_shadertypes();
4161
- }
4162
- });
4163
-
4164
4218
  // src/adapter/helpers/set-uniform.ts
4165
4219
  function setUniform(gl, location, type, value) {
4166
4220
  const gl2 = gl;
@@ -4294,25 +4348,41 @@ ${source}`;
4294
4348
  function mergeShaderLayout(baseLayout, overrideLayout) {
4295
4349
  const mergedLayout = {
4296
4350
  ...baseLayout,
4297
- attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
4351
+ attributes: baseLayout.attributes.map((attribute) => ({ ...attribute })),
4352
+ bindings: baseLayout.bindings.map((binding) => ({ ...binding }))
4298
4353
  };
4299
4354
  for (const attribute of overrideLayout?.attributes || []) {
4300
4355
  const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
4301
4356
  if (!baseAttribute) {
4302
- import_core16.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
4357
+ import_core15.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
4303
4358
  } else {
4304
4359
  baseAttribute.type = attribute.type || baseAttribute.type;
4305
4360
  baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
4306
4361
  }
4307
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
+ }
4308
4371
  return mergedLayout;
4309
4372
  }
4310
- var import_core16, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
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;
4311
4382
  var init_webgl_render_pipeline = __esm({
4312
4383
  "src/adapter/resources/webgl-render-pipeline.ts"() {
4313
4384
  "use strict";
4314
- import_core16 = __toESM(require_core(), 1);
4315
- init_get_shader_layout_from_glsl();
4385
+ import_core15 = __toESM(require_core(), 1);
4316
4386
  init_device_parameters();
4317
4387
  init_set_uniform();
4318
4388
  init_webgl_buffer();
@@ -4320,8 +4390,7 @@ ${source}`;
4320
4390
  init_webgl_texture();
4321
4391
  init_webgl_texture_view();
4322
4392
  init_webgl_topology_utils();
4323
- LOG_PROGRAM_PERF_PRIORITY = 4;
4324
- WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
4393
+ WEBGLRenderPipeline = class extends import_core15.RenderPipeline {
4325
4394
  /** The WebGL device that created this render pipeline */
4326
4395
  device;
4327
4396
  /** Handle to underlying WebGL program */
@@ -4332,10 +4401,10 @@ ${source}`;
4332
4401
  fs;
4333
4402
  /** The layout extracted from shader by WebGL introspection APIs */
4334
4403
  introspectedLayout;
4335
- /** Uniforms set on this model */
4336
- uniforms = {};
4337
- /** Bindings set on this model */
4404
+ /** Compatibility path for direct pipeline.setBindings() usage */
4338
4405
  bindings = {};
4406
+ /** Compatibility path for direct pipeline.uniforms usage */
4407
+ uniforms = {};
4339
4408
  /** WebGL varyings */
4340
4409
  varyings = null;
4341
4410
  _uniformCount = 0;
@@ -4347,41 +4416,39 @@ ${source}`;
4347
4416
  constructor(device, props) {
4348
4417
  super(device, props);
4349
4418
  this.device = device;
4350
- this.handle = this.props.handle || this.device.gl.createProgram();
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;
4351
4426
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4352
- this.vs = props.vs;
4353
- this.fs = props.fs;
4354
- const { varyings, bufferMode = 35981 /* SEPARATE_ATTRIBS */ } = props;
4355
- if (varyings && varyings.length > 0) {
4356
- this.varyings = varyings;
4357
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4358
- }
4359
- this._linkShaders();
4360
- import_core16.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4361
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4362
- import_core16.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4363
4427
  this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4364
4428
  }
4365
4429
  destroy() {
4366
- if (this.handle) {
4367
- this.device.gl.useProgram(null);
4368
- this.device.gl.deleteProgram(this.handle);
4369
- this.destroyed = true;
4370
- this.handle.destroyed = true;
4371
- this.handle = null;
4430
+ if (this.destroyed) {
4431
+ return;
4432
+ }
4433
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4434
+ this.sharedRenderPipeline.destroy();
4372
4435
  }
4436
+ this.destroyResource();
4373
4437
  }
4374
4438
  /**
4375
- * Bindings include: textures, samplers and uniform buffers
4376
- * @todo needed for portable model
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.
4377
4441
  */
4378
4442
  setBindings(bindings, options) {
4379
- for (const [name, value] of Object.entries(bindings)) {
4380
- const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
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);
4381
4448
  if (!binding) {
4382
4449
  const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
4383
4450
  if (!options?.disableWarnings) {
4384
- import_core16.log.warn(
4451
+ import_core15.log.warn(
4385
4452
  `No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`,
4386
4453
  value
4387
4454
  )();
@@ -4389,7 +4456,7 @@ ${source}`;
4389
4456
  continue;
4390
4457
  }
4391
4458
  if (!value) {
4392
- import_core16.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4459
+ import_core15.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4393
4460
  }
4394
4461
  switch (binding.type) {
4395
4462
  case "uniform":
@@ -4403,7 +4470,7 @@ ${source}`;
4403
4470
  }
4404
4471
  break;
4405
4472
  case "sampler":
4406
- import_core16.log.warn(`Ignoring sampler ${name}`)();
4473
+ import_core15.log.warn(`Ignoring sampler ${name}`)();
4407
4474
  break;
4408
4475
  default:
4409
4476
  throw new Error(binding.type);
@@ -4416,6 +4483,8 @@ ${source}`;
4416
4483
  * This function unifies those ways into a single call using common parameters with sane defaults
4417
4484
  */
4418
4485
  draw(options) {
4486
+ this._syncLinkStatus();
4487
+ const drawBindings = options.bindGroups ? (0, import_core15.flattenBindingsByGroup)(options.bindGroups) : options.bindings || this.bindings;
4419
4488
  const {
4420
4489
  renderPass,
4421
4490
  parameters = this.props.parameters,
@@ -4429,17 +4498,18 @@ ${source}`;
4429
4498
  // firstIndex,
4430
4499
  // firstInstance,
4431
4500
  // baseVertex,
4432
- transformFeedback
4501
+ transformFeedback,
4502
+ uniforms = this.uniforms
4433
4503
  } = options;
4434
4504
  const glDrawMode = getGLDrawMode(topology);
4435
4505
  const isIndexed = Boolean(vertexArray.indexBuffer);
4436
4506
  const glIndexType = vertexArray.indexBuffer?.glIndexType;
4437
4507
  if (this.linkStatus !== "success") {
4438
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4508
+ import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4439
4509
  return false;
4440
4510
  }
4441
- if (!this._areTexturesRenderable()) {
4442
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4511
+ if (!this._areTexturesRenderable(drawBindings)) {
4512
+ import_core15.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4443
4513
  return false;
4444
4514
  }
4445
4515
  this.device.gl.useProgram(this.handle);
@@ -4447,8 +4517,8 @@ ${source}`;
4447
4517
  if (transformFeedback) {
4448
4518
  transformFeedback.begin(this.props.topology);
4449
4519
  }
4450
- this._applyBindings();
4451
- this._applyUniforms();
4520
+ this._applyBindings(drawBindings, { disableWarnings: this.props.disableWarnings });
4521
+ this._applyUniforms(uniforms);
4452
4522
  const webglRenderPass = renderPass;
4453
4523
  withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4454
4524
  if (isIndexed && isInstanced) {
@@ -4479,30 +4549,473 @@ ${source}`;
4479
4549
  vertexArray.unbindAfterRender(renderPass);
4480
4550
  return true;
4481
4551
  }
4482
- // PRIVATE METHODS
4483
- // setAttributes(attributes: Record<string, Buffer>): void {}
4484
- // setBindings(bindings: Record<string, Binding>): void {}
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");
4620
+ }
4621
+ gl.activeTexture(33984 /* TEXTURE0 */ + textureUnit);
4622
+ gl.bindTexture(texture.glTarget, texture.handle);
4623
+ textureUnit += 1;
4624
+ break;
4625
+ case "sampler":
4626
+ break;
4627
+ case "storage":
4628
+ case "read-only-storage":
4629
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4630
+ }
4631
+ }
4632
+ }
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
+ }
4644
+ }
4645
+ }
4646
+ _syncLinkStatus() {
4647
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
4648
+ }
4649
+ };
4650
+ }
4651
+ });
4652
+
4653
+ // src/adapter/converters/webgl-shadertypes.ts
4654
+ function convertDataTypeToGLDataType(normalizedType) {
4655
+ return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
4656
+ }
4657
+ function convertGLUniformTypeToShaderVariableType(glUniformType) {
4658
+ return WEBGL_SHADER_TYPES[glUniformType];
4659
+ }
4660
+ function isGLSamplerType(type) {
4661
+ return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
4662
+ }
4663
+ function getTextureBindingFromGLSamplerType(glSamplerType) {
4664
+ return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
4665
+ }
4666
+ var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL, WEBGL_TO_NORMALIZED_DATA_TYPE;
4667
+ var init_webgl_shadertypes = __esm({
4668
+ "src/adapter/converters/webgl-shadertypes.ts"() {
4669
+ "use strict";
4670
+ WEBGL_SHADER_TYPES = {
4671
+ [5126 /* FLOAT */]: "f32",
4672
+ [35664 /* FLOAT_VEC2 */]: "vec2<f32>",
4673
+ [35665 /* FLOAT_VEC3 */]: "vec3<f32>",
4674
+ [35666 /* FLOAT_VEC4 */]: "vec4<f32>",
4675
+ [5124 /* INT */]: "i32",
4676
+ [35667 /* INT_VEC2 */]: "vec2<i32>",
4677
+ [35668 /* INT_VEC3 */]: "vec3<i32>",
4678
+ [35669 /* INT_VEC4 */]: "vec4<i32>",
4679
+ [5125 /* UNSIGNED_INT */]: "u32",
4680
+ [36294 /* UNSIGNED_INT_VEC2 */]: "vec2<u32>",
4681
+ [36295 /* UNSIGNED_INT_VEC3 */]: "vec3<u32>",
4682
+ [36296 /* UNSIGNED_INT_VEC4 */]: "vec4<u32>",
4683
+ [35670 /* BOOL */]: "f32",
4684
+ [35671 /* BOOL_VEC2 */]: "vec2<f32>",
4685
+ [35672 /* BOOL_VEC3 */]: "vec3<f32>",
4686
+ [35673 /* BOOL_VEC4 */]: "vec4<f32>",
4687
+ // TODO - are sizes/components below correct?
4688
+ [35674 /* FLOAT_MAT2 */]: "mat2x2<f32>",
4689
+ [35685 /* FLOAT_MAT2x3 */]: "mat2x3<f32>",
4690
+ [35686 /* FLOAT_MAT2x4 */]: "mat2x4<f32>",
4691
+ [35687 /* FLOAT_MAT3x2 */]: "mat3x2<f32>",
4692
+ [35675 /* FLOAT_MAT3 */]: "mat3x3<f32>",
4693
+ [35688 /* FLOAT_MAT3x4 */]: "mat3x4<f32>",
4694
+ [35689 /* FLOAT_MAT4x2 */]: "mat4x2<f32>",
4695
+ [35690 /* FLOAT_MAT4x3 */]: "mat4x3<f32>",
4696
+ [35676 /* FLOAT_MAT4 */]: "mat4x4<f32>"
4697
+ };
4698
+ WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
4699
+ [35678 /* SAMPLER_2D */]: { viewDimension: "2d", sampleType: "float" },
4700
+ [35680 /* SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "float" },
4701
+ [35679 /* SAMPLER_3D */]: { viewDimension: "3d", sampleType: "float" },
4702
+ [35682 /* SAMPLER_2D_SHADOW */]: { viewDimension: "3d", sampleType: "depth" },
4703
+ [36289 /* SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "float" },
4704
+ [36292 /* SAMPLER_2D_ARRAY_SHADOW */]: { viewDimension: "2d-array", sampleType: "depth" },
4705
+ [36293 /* SAMPLER_CUBE_SHADOW */]: { viewDimension: "cube", sampleType: "float" },
4706
+ [36298 /* INT_SAMPLER_2D */]: { viewDimension: "2d", sampleType: "sint" },
4707
+ [36299 /* INT_SAMPLER_3D */]: { viewDimension: "3d", sampleType: "sint" },
4708
+ [36300 /* INT_SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "sint" },
4709
+ [36303 /* INT_SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "uint" },
4710
+ [36306 /* UNSIGNED_INT_SAMPLER_2D */]: { viewDimension: "2d", sampleType: "uint" },
4711
+ [36307 /* UNSIGNED_INT_SAMPLER_3D */]: { viewDimension: "3d", sampleType: "uint" },
4712
+ [36308 /* UNSIGNED_INT_SAMPLER_CUBE */]: { viewDimension: "cube", sampleType: "uint" },
4713
+ [36311 /* UNSIGNED_INT_SAMPLER_2D_ARRAY */]: { viewDimension: "2d-array", sampleType: "uint" }
4714
+ };
4715
+ NORMALIZED_SHADER_TYPE_TO_WEBGL = {
4716
+ uint8: 5121 /* UNSIGNED_BYTE */,
4717
+ sint8: 5120 /* BYTE */,
4718
+ unorm8: 5121 /* UNSIGNED_BYTE */,
4719
+ snorm8: 5120 /* BYTE */,
4720
+ uint16: 5123 /* UNSIGNED_SHORT */,
4721
+ sint16: 5122 /* SHORT */,
4722
+ unorm16: 5123 /* UNSIGNED_SHORT */,
4723
+ snorm16: 5122 /* SHORT */,
4724
+ uint32: 5125 /* UNSIGNED_INT */,
4725
+ sint32: 5124 /* INT */,
4726
+ // WebGPU does not support normalized 32 bit integer attributes
4727
+ // 'unorm32': GL.UNSIGNED_INT,
4728
+ // 'snorm32': GL.INT,
4729
+ float16: 5131 /* HALF_FLOAT */,
4730
+ float32: 5126 /* FLOAT */
4731
+ };
4732
+ WEBGL_TO_NORMALIZED_DATA_TYPE = {
4733
+ [5120 /* BYTE */]: ["sint8", "snorm16"],
4734
+ [5121 /* UNSIGNED_BYTE */]: ["uint8", "unorm8"],
4735
+ [5122 /* SHORT */]: ["sint16", "unorm16"],
4736
+ [5123 /* UNSIGNED_SHORT */]: ["uint16", "unorm16"],
4737
+ [5124 /* INT */]: ["sint32", "sint32"],
4738
+ [5125 /* UNSIGNED_INT */]: ["uint32", "uint32"],
4739
+ [5126 /* FLOAT */]: ["float32", "float32"],
4740
+ [5131 /* HALF_FLOAT */]: ["float16", "float16"]
4741
+ };
4742
+ }
4743
+ });
4744
+
4745
+ // src/adapter/helpers/get-shader-layout-from-glsl.ts
4746
+ function getShaderLayoutFromGLSL(gl, program) {
4747
+ const shaderLayout = {
4748
+ attributes: [],
4749
+ bindings: []
4750
+ };
4751
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
4752
+ const uniformBlocks = readUniformBlocks(gl, program);
4753
+ for (const uniformBlock of uniformBlocks) {
4754
+ const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
4755
+ name: uniform.name,
4756
+ format: uniform.format,
4757
+ byteOffset: uniform.byteOffset,
4758
+ byteStride: uniform.byteStride,
4759
+ arrayLength: uniform.arrayLength
4760
+ }));
4761
+ shaderLayout.bindings.push({
4762
+ type: "uniform",
4763
+ name: uniformBlock.name,
4764
+ group: 0,
4765
+ location: uniformBlock.location,
4766
+ visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
4767
+ minBindingSize: uniformBlock.byteLength,
4768
+ uniforms: uniforms2
4769
+ });
4770
+ }
4771
+ const uniforms = readUniformBindings(gl, program);
4772
+ let textureUnit = 0;
4773
+ for (const uniform of uniforms) {
4774
+ if (isGLSamplerType(uniform.type)) {
4775
+ const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
4776
+ shaderLayout.bindings.push({
4777
+ type: "texture",
4778
+ name: uniform.name,
4779
+ group: 0,
4780
+ location: textureUnit,
4781
+ viewDimension,
4782
+ sampleType
4783
+ });
4784
+ uniform.textureUnit = textureUnit;
4785
+ textureUnit += 1;
4786
+ }
4787
+ }
4788
+ if (uniforms.length) {
4789
+ shaderLayout.uniforms = uniforms;
4790
+ }
4791
+ const varyings = readVaryings(gl, program);
4792
+ if (varyings?.length) {
4793
+ shaderLayout.varyings = varyings;
4794
+ }
4795
+ return shaderLayout;
4796
+ }
4797
+ function readAttributeDeclarations(gl, program) {
4798
+ const attributes = [];
4799
+ const count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
4800
+ for (let index = 0; index < count; index++) {
4801
+ const activeInfo = gl.getActiveAttrib(program, index);
4802
+ if (!activeInfo) {
4803
+ throw new Error("activeInfo");
4804
+ }
4805
+ const {
4806
+ name,
4807
+ type: compositeType
4808
+ /* , size*/
4809
+ } = activeInfo;
4810
+ const location = gl.getAttribLocation(program, name);
4811
+ if (location >= 0) {
4812
+ const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
4813
+ const stepMode = /instance/i.test(name) ? "instance" : "vertex";
4814
+ attributes.push({
4815
+ name,
4816
+ location,
4817
+ stepMode,
4818
+ type: attributeType
4819
+ // size - for arrays, size is the number of elements in the array
4820
+ });
4821
+ }
4822
+ }
4823
+ attributes.sort((a, b) => a.location - b.location);
4824
+ return attributes;
4825
+ }
4826
+ function readVaryings(gl, program) {
4827
+ const varyings = [];
4828
+ const count = gl.getProgramParameter(program, 35971 /* TRANSFORM_FEEDBACK_VARYINGS */);
4829
+ for (let location = 0; location < count; location++) {
4830
+ const activeInfo = gl.getTransformFeedbackVarying(program, location);
4831
+ if (!activeInfo) {
4832
+ throw new Error("activeInfo");
4833
+ }
4834
+ const { name, type: glUniformType, size } = activeInfo;
4835
+ const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
4836
+ const { type, components } = (0, import_core16.getVariableShaderTypeInfo)(uniformType);
4837
+ varyings.push({ location, name, type, size: size * components });
4838
+ }
4839
+ varyings.sort((a, b) => a.location - b.location);
4840
+ return varyings;
4841
+ }
4842
+ function readUniformBindings(gl, program) {
4843
+ const uniforms = [];
4844
+ const uniformCount = gl.getProgramParameter(program, 35718 /* ACTIVE_UNIFORMS */);
4845
+ for (let i = 0; i < uniformCount; i++) {
4846
+ const activeInfo = gl.getActiveUniform(program, i);
4847
+ if (!activeInfo) {
4848
+ throw new Error("activeInfo");
4849
+ }
4850
+ const { name: rawName, size, type } = activeInfo;
4851
+ const { name, isArray: isArray3 } = parseUniformName(rawName);
4852
+ let webglLocation = gl.getUniformLocation(program, name);
4853
+ const uniformInfo = {
4854
+ // WebGL locations are uniquely typed but just numbers
4855
+ location: webglLocation,
4856
+ name,
4857
+ size,
4858
+ type,
4859
+ isArray: isArray3
4860
+ };
4861
+ uniforms.push(uniformInfo);
4862
+ if (uniformInfo.size > 1) {
4863
+ for (let j = 0; j < uniformInfo.size; j++) {
4864
+ const elementName = `${name}[${j}]`;
4865
+ webglLocation = gl.getUniformLocation(program, elementName);
4866
+ const arrayElementUniformInfo = {
4867
+ ...uniformInfo,
4868
+ name: elementName,
4869
+ location: webglLocation
4870
+ };
4871
+ uniforms.push(arrayElementUniformInfo);
4872
+ }
4873
+ }
4874
+ }
4875
+ return uniforms;
4876
+ }
4877
+ function readUniformBlocks(gl, program) {
4878
+ const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
4879
+ const uniformBlocks = [];
4880
+ const blockCount = gl.getProgramParameter(program, 35382 /* ACTIVE_UNIFORM_BLOCKS */);
4881
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
4882
+ const blockInfo = {
4883
+ name: gl.getActiveUniformBlockName(program, blockIndex) || "",
4884
+ location: getBlockParameter(blockIndex, 35391 /* UNIFORM_BLOCK_BINDING */),
4885
+ byteLength: getBlockParameter(blockIndex, 35392 /* UNIFORM_BLOCK_DATA_SIZE */),
4886
+ vertex: getBlockParameter(blockIndex, 35396 /* UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER */),
4887
+ fragment: getBlockParameter(blockIndex, 35398 /* UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER */),
4888
+ uniformCount: getBlockParameter(blockIndex, 35394 /* UNIFORM_BLOCK_ACTIVE_UNIFORMS */),
4889
+ uniforms: []
4890
+ };
4891
+ const uniformIndices = getBlockParameter(blockIndex, 35395 /* UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES */) || [];
4892
+ const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383 /* UNIFORM_TYPE */);
4893
+ const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384 /* UNIFORM_SIZE */);
4894
+ const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387 /* UNIFORM_OFFSET */);
4895
+ const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388 /* UNIFORM_ARRAY_STRIDE */);
4896
+ for (let i = 0; i < blockInfo.uniformCount; ++i) {
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
+ )();
4925
+ }
4926
+ uniformBlocks.push(blockInfo);
4927
+ }
4928
+ uniformBlocks.sort((a, b) => a.location - b.location);
4929
+ return uniformBlocks;
4930
+ }
4931
+ function parseUniformName(name) {
4932
+ if (name[name.length - 1] !== "]") {
4933
+ return {
4934
+ name,
4935
+ length: 1,
4936
+ isArray: false
4937
+ };
4938
+ }
4939
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
4940
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
4941
+ const uniformName = (0, import_core16.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
4942
+ return {
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])
4947
+ };
4948
+ }
4949
+ var import_core16;
4950
+ var init_get_shader_layout_from_glsl = __esm({
4951
+ "src/adapter/helpers/get-shader-layout-from-glsl.ts"() {
4952
+ "use strict";
4953
+ import_core16 = __toESM(require_core(), 1);
4954
+ init_webgl_shadertypes();
4955
+ }
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"() {
4962
+ "use strict";
4963
+ import_core17 = __toESM(require_core(), 1);
4964
+ init_get_shader_layout_from_glsl();
4965
+ init_webgl_shadertypes();
4966
+ LOG_PROGRAM_PERF_PRIORITY = 4;
4967
+ WEBGLSharedRenderPipeline = class extends import_core17.SharedRenderPipeline {
4968
+ device;
4969
+ handle;
4970
+ vs;
4971
+ fs;
4972
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4973
+ linkStatus = "pending";
4974
+ constructor(device, props) {
4975
+ super(device, props);
4976
+ this.device = device;
4977
+ this.handle = props.handle || this.device.gl.createProgram();
4978
+ this.vs = props.vs;
4979
+ this.fs = props.fs;
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
+ );
4986
+ }
4987
+ this._linkShaders();
4988
+ import_core17.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4989
+ this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4990
+ import_core17.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4991
+ }
4992
+ destroy() {
4993
+ if (this.destroyed) {
4994
+ return;
4995
+ }
4996
+ this.device.gl.useProgram(null);
4997
+ this.device.gl.deleteProgram(this.handle);
4998
+ this.handle.destroyed = true;
4999
+ this.destroyResource();
5000
+ }
4485
5001
  async _linkShaders() {
4486
5002
  const { gl } = this.device;
4487
5003
  gl.attachShader(this.handle, this.vs.handle);
4488
5004
  gl.attachShader(this.handle, this.fs.handle);
4489
- import_core16.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
5005
+ import_core17.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4490
5006
  gl.linkProgram(this.handle);
4491
- import_core16.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4492
- if (import_core16.log.level === 0) {
4493
- }
5007
+ import_core17.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4494
5008
  if (!this.device.features.has("compilation-status-async-webgl")) {
4495
5009
  const status2 = this._getLinkStatus();
4496
5010
  this._reportLinkStatus(status2);
4497
5011
  return;
4498
5012
  }
4499
- import_core16.log.once(1, "RenderPipeline linking is asynchronous")();
5013
+ import_core17.log.once(1, "RenderPipeline linking is asynchronous")();
4500
5014
  await this._waitForLinkComplete();
4501
- import_core16.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}`)();
4502
5016
  const status = this._getLinkStatus();
4503
5017
  this._reportLinkStatus(status);
4504
5018
  }
4505
- /** Report link status. First, check for shader compilation failures if linking fails */
4506
5019
  async _reportLinkStatus(status) {
4507
5020
  switch (status) {
4508
5021
  case "success":
@@ -4539,11 +5052,6 @@ ${source}`;
4539
5052
  this.device.debug();
4540
5053
  }
4541
5054
  }
4542
- /**
4543
- * Get the shader compilation status
4544
- * TODO - Load log even when no error reported, to catch warnings?
4545
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4546
- */
4547
5055
  _getLinkStatus() {
4548
5056
  const { gl } = this.device;
4549
5057
  const linked = gl.getProgramParameter(this.handle, 35714 /* LINK_STATUS */);
@@ -4551,6 +5059,7 @@ ${source}`;
4551
5059
  this.linkStatus = "error";
4552
5060
  return "link-error";
4553
5061
  }
5062
+ this._initializeSamplerUniforms();
4554
5063
  gl.validateProgram(this.handle);
4555
5064
  const validated = gl.getProgramParameter(this.handle, 35715 /* VALIDATE_STATUS */);
4556
5065
  if (!validated) {
@@ -4560,7 +5069,36 @@ ${source}`;
4560
5069
  this.linkStatus = "success";
4561
5070
  return "success";
4562
5071
  }
4563
- /** Use KHR_parallel_shader_compile extension if available */
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
+ }
5086
+ }
5087
+ }
5088
+ }
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
+ }
4564
5102
  async _waitForLinkComplete() {
4565
5103
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4566
5104
  const DELAY_MS = 10;
@@ -4577,101 +5115,6 @@ ${source}`;
4577
5115
  await waitMs(DELAY_MS);
4578
5116
  }
4579
5117
  }
4580
- /**
4581
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4582
- * Update a texture if needed (e.g. from video)
4583
- * Note: This is currently done before every draw call
4584
- */
4585
- _areTexturesRenderable() {
4586
- let texturesRenderable = true;
4587
- for (const bindingInfo of this.shaderLayout.bindings) {
4588
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4589
- import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4590
- texturesRenderable = false;
4591
- }
4592
- }
4593
- return texturesRenderable;
4594
- }
4595
- /** Apply any bindings (before each draw call) */
4596
- _applyBindings() {
4597
- if (this.linkStatus !== "success") {
4598
- return;
4599
- }
4600
- const { gl } = this.device;
4601
- gl.useProgram(this.handle);
4602
- let textureUnit = 0;
4603
- let uniformBufferIndex = 0;
4604
- for (const binding of this.shaderLayout.bindings) {
4605
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4606
- if (!value) {
4607
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4608
- }
4609
- switch (binding.type) {
4610
- case "uniform":
4611
- const { name } = binding;
4612
- const location = gl.getUniformBlockIndex(this.handle, name);
4613
- if (location === 4294967295 /* INVALID_INDEX */) {
4614
- throw new Error(`Invalid uniform block name ${name}`);
4615
- }
4616
- gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
4617
- if (value instanceof WEBGLBuffer) {
4618
- gl.bindBufferBase(35345 /* UNIFORM_BUFFER */, uniformBufferIndex, value.handle);
4619
- } else {
4620
- gl.bindBufferRange(
4621
- 35345 /* UNIFORM_BUFFER */,
4622
- uniformBufferIndex,
4623
- // @ts-expect-error
4624
- value.buffer.handle,
4625
- // @ts-expect-error
4626
- value.offset || 0,
4627
- // @ts-expect-error
4628
- value.size || value.buffer.byteLength - value.offset
4629
- );
4630
- }
4631
- uniformBufferIndex += 1;
4632
- break;
4633
- case "texture":
4634
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4635
- throw new Error("texture");
4636
- }
4637
- let texture;
4638
- if (value instanceof WEBGLTextureView) {
4639
- texture = value.texture;
4640
- } else if (value instanceof WEBGLTexture) {
4641
- texture = value;
4642
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4643
- import_core16.log.warn(
4644
- "Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead"
4645
- )();
4646
- texture = value.colorAttachments[0].texture;
4647
- } else {
4648
- throw new Error("No texture");
4649
- }
4650
- gl.activeTexture(33984 /* TEXTURE0 */ + textureUnit);
4651
- gl.bindTexture(texture.glTarget, texture.handle);
4652
- textureUnit += 1;
4653
- break;
4654
- case "sampler":
4655
- break;
4656
- case "storage":
4657
- case "read-only-storage":
4658
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4659
- }
4660
- }
4661
- }
4662
- /**
4663
- * Due to program sharing, uniforms need to be reset before every draw call
4664
- * (though caching will avoid redundant WebGL calls)
4665
- */
4666
- _applyUniforms() {
4667
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4668
- const { name, location, type, textureUnit } = uniformLayout;
4669
- const value = this.uniforms[name] ?? textureUnit;
4670
- if (value !== void 0) {
4671
- setUniform(this.device.gl, location, type, value);
4672
- }
4673
- }
4674
- }
4675
5118
  };
4676
5119
  }
4677
5120
  });
@@ -4692,44 +5135,44 @@ ${source}`;
4692
5135
  device.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, null);
4693
5136
  device.gl.bindBuffer(36663 /* COPY_WRITE_BUFFER */, null);
4694
5137
  }
4695
- function _copyBufferToTexture(device, options) {
4696
- throw new Error("Not implemented");
5138
+ function _copyBufferToTexture(_device, _options) {
5139
+ throw new Error("copyBufferToTexture is not supported in WebGL");
4697
5140
  }
4698
5141
  function _copyTextureToBuffer(device, options) {
4699
5142
  const {
4700
- /** Texture to copy to/from. */
4701
5143
  sourceTexture,
4702
- /** Mip-map level of the texture to copy to/from. (Default 0) */
4703
5144
  mipLevel = 0,
4704
- /** Defines which aspects of the texture to copy to/from. */
4705
5145
  aspect = "all",
4706
- /** Width to copy */
4707
5146
  width = options.sourceTexture.width,
4708
- /** Height to copy */
4709
5147
  height = options.sourceTexture.height,
4710
- depthOrArrayLayers = 0,
4711
- /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
5148
+ depthOrArrayLayers,
4712
5149
  origin = [0, 0, 0],
4713
- /** Destination buffer */
4714
5150
  destinationBuffer,
4715
- /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
4716
5151
  byteOffset = 0,
4717
- /**
4718
- * The stride, in bytes, between the beginning of each block row and the subsequent block row.
4719
- * Required if there are multiple block rows (i.e. the copy height or depth is more than one block).
4720
- */
4721
5152
  bytesPerRow,
4722
- /**
4723
- * Number of block rows per single image of the texture.
4724
- * rowsPerImage &times; bytesPerRow is the stride, in bytes, between the beginning of each image of data and the subsequent image.
4725
- * Required if there are multiple images (i.e. the copy depth is more than one).
4726
- */
4727
5153
  rowsPerImage
4728
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
+ }
4729
5172
  if (aspect !== "all") {
4730
5173
  throw new Error("aspect not supported in WebGL");
4731
5174
  }
4732
- if (mipLevel !== 0 || depthOrArrayLayers !== 0 || bytesPerRow || rowsPerImage) {
5175
+ if (mipLevel !== 0 || depthOrArrayLayers !== void 0 || bytesPerRow || rowsPerImage) {
4733
5176
  throw new Error("not implemented");
4734
5177
  }
4735
5178
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
@@ -4738,7 +5181,7 @@ ${source}`;
4738
5181
  const webglBuffer = destinationBuffer;
4739
5182
  const sourceWidth = width || framebuffer.width;
4740
5183
  const sourceHeight = height || framebuffer.height;
4741
- const colorAttachment0 = (0, import_core17.assertDefined)(framebuffer.colorAttachments[0]);
5184
+ const colorAttachment0 = (0, import_core18.assertDefined)(framebuffer.colorAttachments[0]);
4742
5185
  const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
4743
5186
  const sourceFormat = sourceParams.format;
4744
5187
  const sourceType = sourceParams.type;
@@ -4846,7 +5289,7 @@ ${source}`;
4846
5289
  }
4847
5290
  }
4848
5291
  function getFramebuffer(source) {
4849
- if (source instanceof import_core17.Texture) {
5292
+ if (source instanceof import_core18.Texture) {
4850
5293
  const { width, height, id } = source;
4851
5294
  const framebuffer = source.device.createFramebuffer({
4852
5295
  id: `framebuffer-for-${id}`,
@@ -4858,19 +5301,19 @@ ${source}`;
4858
5301
  }
4859
5302
  return { framebuffer: source, destroyFramebuffer: false };
4860
5303
  }
4861
- var import_core17, WEBGLCommandBuffer;
5304
+ var import_core18, WEBGLCommandBuffer;
4862
5305
  var init_webgl_command_buffer = __esm({
4863
5306
  "src/adapter/resources/webgl-command-buffer.ts"() {
4864
5307
  "use strict";
4865
- import_core17 = __toESM(require_core(), 1);
4866
- init_webgl_texture();
5308
+ import_core18 = __toESM(require_core(), 1);
4867
5309
  init_webgl_texture_table();
4868
- WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
5310
+ init_webgl_texture();
5311
+ WEBGLCommandBuffer = class extends import_core18.CommandBuffer {
4869
5312
  device;
4870
5313
  handle = null;
4871
5314
  commands = [];
4872
- constructor(device) {
4873
- super(device, {});
5315
+ constructor(device, props = {}) {
5316
+ super(device, props);
4874
5317
  this.device = device;
4875
5318
  }
4876
5319
  _executeCommands(commands = this.commands) {
@@ -4898,15 +5341,15 @@ ${source}`;
4898
5341
  });
4899
5342
 
4900
5343
  // src/adapter/resources/webgl-render-pass.ts
4901
- var import_core18, COLOR_CHANNELS, WEBGLRenderPass;
5344
+ var import_core19, COLOR_CHANNELS, WEBGLRenderPass;
4902
5345
  var init_webgl_render_pass = __esm({
4903
5346
  "src/adapter/resources/webgl-render-pass.ts"() {
4904
5347
  "use strict";
4905
- import_core18 = __toESM(require_core(), 1);
5348
+ import_core19 = __toESM(require_core(), 1);
4906
5349
  init_with_parameters();
4907
5350
  init_unified_parameter_api();
4908
5351
  COLOR_CHANNELS = [1, 2, 4, 8];
4909
- WEBGLRenderPass = class extends import_core18.RenderPass {
5352
+ WEBGLRenderPass = class extends import_core19.RenderPass {
4910
5353
  device;
4911
5354
  handle = null;
4912
5355
  /** Parameters that should be applied before each draw call */
@@ -4914,13 +5357,15 @@ ${source}`;
4914
5357
  constructor(device, props) {
4915
5358
  super(device, props);
4916
5359
  this.device = device;
4917
- if (!props?.framebuffer) {
5360
+ const webglFramebuffer = this.props.framebuffer;
5361
+ const isDefaultFramebuffer = !webglFramebuffer || webglFramebuffer.handle === null;
5362
+ if (isDefaultFramebuffer) {
4918
5363
  device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4919
5364
  }
4920
5365
  let viewport;
4921
5366
  if (!props?.parameters?.viewport) {
4922
- if (props?.framebuffer) {
4923
- const { width, height } = props.framebuffer;
5367
+ if (!isDefaultFramebuffer) {
5368
+ const { width, height } = webglFramebuffer;
4924
5369
  viewport = [0, 0, width, height];
4925
5370
  } else {
4926
5371
  const [width, height] = device.getDefaultCanvasContext().getDrawingBufferSize();
@@ -4929,19 +5374,28 @@ ${source}`;
4929
5374
  }
4930
5375
  this.device.pushState();
4931
5376
  this.setParameters({ viewport, ...this.props.parameters });
4932
- const webglFramebuffer = this.props.framebuffer;
4933
- if (this.props.framebuffer && webglFramebuffer?.handle) {
4934
- const drawBuffers = this.props.framebuffer.colorAttachments.map(
4935
- (_, i) => 36064 /* COLOR_ATTACHMENT0 */ + i
4936
- );
5377
+ if (!isDefaultFramebuffer) {
5378
+ const drawBuffers = webglFramebuffer.colorAttachments.map((_, i) => 36064 /* COLOR_ATTACHMENT0 */ + i);
4937
5379
  this.device.gl.drawBuffers(drawBuffers);
4938
- } else if (!this.props.framebuffer) {
5380
+ } else {
4939
5381
  this.device.gl.drawBuffers([1029 /* BACK */]);
4940
5382
  }
4941
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
+ }
4942
5388
  }
4943
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
+ }
4944
5397
  this.device.popState();
5398
+ this.destroy();
4945
5399
  }
4946
5400
  pushDebugGroup(groupLabel) {
4947
5401
  }
@@ -5083,31 +5537,39 @@ ${source}`;
5083
5537
  });
5084
5538
 
5085
5539
  // src/adapter/resources/webgl-command-encoder.ts
5086
- var import_core19, WEBGLCommandEncoder;
5540
+ var import_core20, WEBGLCommandEncoder;
5087
5541
  var init_webgl_command_encoder = __esm({
5088
5542
  "src/adapter/resources/webgl-command-encoder.ts"() {
5089
5543
  "use strict";
5090
- import_core19 = __toESM(require_core(), 1);
5544
+ import_core20 = __toESM(require_core(), 1);
5091
5545
  init_webgl_command_buffer();
5092
5546
  init_webgl_render_pass();
5093
- WEBGLCommandEncoder = class extends import_core19.CommandEncoder {
5547
+ WEBGLCommandEncoder = class extends import_core20.CommandEncoder {
5094
5548
  device;
5095
5549
  handle = null;
5096
5550
  commandBuffer;
5097
5551
  constructor(device, props) {
5098
5552
  super(device, props);
5099
5553
  this.device = device;
5100
- this.commandBuffer = new WEBGLCommandBuffer(device);
5554
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5555
+ id: `${this.props.id}-command-buffer`
5556
+ });
5101
5557
  }
5102
5558
  destroy() {
5559
+ this.destroyResource();
5103
5560
  }
5104
- 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();
5105
5567
  return this.commandBuffer;
5106
5568
  }
5107
- beginRenderPass(props) {
5108
- return new WEBGLRenderPass(this.device, props);
5569
+ beginRenderPass(props = {}) {
5570
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
5109
5571
  }
5110
- beginComputePass(props) {
5572
+ beginComputePass(props = {}) {
5111
5573
  throw new Error("ComputePass not supported in WebGL");
5112
5574
  }
5113
5575
  copyBufferToBuffer(options) {
@@ -5131,7 +5593,12 @@ ${source}`;
5131
5593
  }
5132
5594
  insertDebugMarker(markerLabel) {
5133
5595
  }
5134
- 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);
5135
5602
  }
5136
5603
  };
5137
5604
  }
@@ -5181,15 +5648,15 @@ ${source}`;
5181
5648
  }
5182
5649
  return true;
5183
5650
  }
5184
- var import_core20, WEBGLVertexArray;
5651
+ var import_core21, WEBGLVertexArray;
5185
5652
  var init_webgl_vertex_array = __esm({
5186
5653
  "src/adapter/resources/webgl-vertex-array.ts"() {
5187
5654
  "use strict";
5188
- import_core20 = __toESM(require_core(), 1);
5655
+ import_core21 = __toESM(require_core(), 1);
5189
5656
  init_dist();
5190
5657
  init_webgl_vertex_formats();
5191
5658
  init_fill_array();
5192
- WEBGLVertexArray = class extends import_core20.VertexArray {
5659
+ WEBGLVertexArray = class extends import_core21.VertexArray {
5193
5660
  get [Symbol.toStringTag]() {
5194
5661
  return "VertexArray";
5195
5662
  }
@@ -5357,7 +5824,7 @@ ${source}`;
5357
5824
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
5358
5825
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
5359
5826
  if (updateNeeded) {
5360
- const typedArray = (0, import_core20.getScratchArray)(value.constructor, length);
5827
+ const typedArray = (0, import_core21.getScratchArray)(value.constructor, length);
5361
5828
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
5362
5829
  this.buffer.write(typedArray);
5363
5830
  this.bufferValue = value;
@@ -5375,14 +5842,14 @@ ${source}`;
5375
5842
  }
5376
5843
  return /^\d+$/.test(value);
5377
5844
  }
5378
- var import_core21, WEBGLTransformFeedback;
5845
+ var import_core22, WEBGLTransformFeedback;
5379
5846
  var init_webgl_transform_feedback = __esm({
5380
5847
  "src/adapter/resources/webgl-transform-feedback.ts"() {
5381
5848
  "use strict";
5382
- import_core21 = __toESM(require_core(), 1);
5383
- init_src2();
5849
+ import_core22 = __toESM(require_core(), 1);
5850
+ init_src();
5384
5851
  init_webgl_topology_utils();
5385
- WEBGLTransformFeedback = class extends import_core21.TransformFeedback {
5852
+ WEBGLTransformFeedback = class extends import_core22.TransformFeedback {
5386
5853
  device;
5387
5854
  gl;
5388
5855
  handle;
@@ -5445,7 +5912,7 @@ ${source}`;
5445
5912
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
5446
5913
  if (location < 0) {
5447
5914
  this.unusedBuffers[locationOrName] = buffer;
5448
- import_core21.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5915
+ import_core22.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5449
5916
  return;
5450
5917
  }
5451
5918
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -5528,156 +5995,304 @@ ${source}`;
5528
5995
  });
5529
5996
 
5530
5997
  // src/adapter/resources/webgl-query-set.ts
5531
- var import_core22, WEBGLQuerySet;
5998
+ var import_core23, WEBGLQuerySet;
5532
5999
  var init_webgl_query_set = __esm({
5533
6000
  "src/adapter/resources/webgl-query-set.ts"() {
5534
6001
  "use strict";
5535
- import_core22 = __toESM(require_core(), 1);
5536
- WEBGLQuerySet = class extends import_core22.QuerySet {
6002
+ import_core23 = __toESM(require_core(), 1);
6003
+ WEBGLQuerySet = class extends import_core23.QuerySet {
5537
6004
  device;
5538
6005
  handle;
5539
- target = null;
5540
- _queryPending = false;
5541
- _pollingPromise = null;
6006
+ _timestampPairs = [];
6007
+ _pendingReads = /* @__PURE__ */ new Set();
6008
+ _occlusionQuery = null;
6009
+ _occlusionActive = false;
5542
6010
  get [Symbol.toStringTag]() {
5543
- return "Query";
6011
+ return "QuerySet";
5544
6012
  }
5545
- // Create a query class
5546
6013
  constructor(device, props) {
5547
6014
  super(device, props);
5548
6015
  this.device = device;
5549
- if (props.count > 1) {
5550
- throw new Error("WebGL QuerySet can only have one value");
5551
- }
5552
- const handle = this.device.gl.createQuery();
5553
- if (!handle) {
5554
- 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;
5555
6031
  }
5556
- this.handle = handle;
5557
6032
  Object.seal(this);
5558
6033
  }
5559
6034
  destroy() {
5560
- 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();
5561
6059
  }
5562
- // FOR RENDER PASS AND COMMAND ENCODER
5563
- /**
5564
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
5565
- * Measures GPU time delta between this call and a matching `end` call in the
5566
- * GPU instruction stream.
5567
- */
5568
- beginTimestampQuery() {
5569
- 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)];
5570
6099
  }
5571
- endTimestampQuery() {
5572
- 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;
5573
6112
  }
5574
- // Shortcut for occlusion queries
5575
- beginOcclusionQuery(options) {
5576
- return this._begin(
5577
- options?.conservative ? 36202 /* ANY_SAMPLES_PASSED_CONSERVATIVE */ : 35887 /* ANY_SAMPLES_PASSED */
5578
- );
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;
5579
6135
  }
5580
6136
  endOcclusionQuery() {
5581
- this._end();
5582
- }
5583
- // Shortcut for transformFeedbackQuery
5584
- beginTransformFeedbackQuery() {
5585
- return this._begin(35976 /* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN */);
5586
- }
5587
- endTransformFeedbackQuery() {
5588
- this._end();
5589
- }
5590
- async resolveQuery() {
5591
- const value = await this.pollQuery();
5592
- 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;
5593
6142
  }
5594
- // PRIVATE METHODS
5595
- /**
5596
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5597
- * instance, `end()` must be called on that same instance before
5598
- * calling `begin()` on another query. While there can be multiple
5599
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5600
- * It is not possible to interleave or overlap `begin` and `end` calls.
5601
- */
5602
- _begin(target2) {
5603
- 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;
5604
6169
  return;
5605
6170
  }
5606
- this.target = target2;
5607
- this.device.gl.beginQuery(this.target, this.handle);
5608
- 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;
5609
6177
  }
5610
- // ends the current query
5611
- _end() {
5612
- if (this._queryPending) {
5613
- 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");
5614
6181
  }
5615
- if (this.target) {
5616
- this.device.gl.endQuery(this.target);
5617
- this.target = null;
5618
- 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");
5619
6186
  }
5620
- return;
6187
+ return Math.floor(queryIndex / 2);
5621
6188
  }
5622
- // Returns true if the query result is available
5623
- isResultAvailable() {
5624
- if (!this._queryPending) {
6189
+ _isTimestampPairAvailable(pairIndex) {
6190
+ const pair = this._timestampPairs[pairIndex];
6191
+ if (!pair || pair.completedQueries.length === 0) {
5625
6192
  return false;
5626
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
+ }
5627
6204
  const resultAvailable = this.device.gl.getQueryParameter(
5628
- this.handle,
6205
+ query.handle,
5629
6206
  34919 /* QUERY_RESULT_AVAILABLE */
5630
6207
  );
5631
- if (resultAvailable) {
5632
- this._queryPending = false;
6208
+ if (!resultAvailable) {
6209
+ return false;
5633
6210
  }
5634
- return resultAvailable;
5635
- }
5636
- // Timing query is disjoint, i.e. results are invalid
5637
- isTimerDisjoint() {
5638
- return this.device.gl.getParameter(36795 /* GPU_DISJOINT_EXT */);
5639
- }
5640
- // Returns query result.
5641
- getResult() {
5642
- return this.device.gl.getQueryParameter(this.handle, 34918 /* QUERY_RESULT */);
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;
5643
6215
  }
5644
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5645
- getTimerMilliseconds() {
5646
- return this.getResult() / 1e6;
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);
6226
+ }
5647
6227
  }
5648
- // Polls the query
5649
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5650
- if (this._pollingPromise) {
5651
- return this._pollingPromise;
6228
+ _consumeQueryResult(query) {
6229
+ if (query.promise) {
6230
+ return query.promise;
5652
6231
  }
5653
- let counter = 0;
5654
- this._pollingPromise = new Promise((resolve, reject) => {
6232
+ this._pendingReads.add(query);
6233
+ query.promise = new Promise((resolve, reject) => {
6234
+ query.resolve = resolve;
6235
+ query.reject = reject;
5655
6236
  const poll = () => {
5656
- if (this.isResultAvailable()) {
5657
- resolve(this.getResult());
5658
- this._pollingPromise = null;
5659
- } else if (counter++ > limit) {
5660
- reject("Timed out");
5661
- this._pollingPromise = null;
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"));
5662
6256
  } else {
5663
- requestAnimationFrame(poll);
6257
+ resolve(query.result || 0n);
5664
6258
  }
5665
6259
  };
5666
- requestAnimationFrame(poll);
6260
+ poll();
5667
6261
  });
5668
- return this._pollingPromise;
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
+ }
6278
+ }
6279
+ _requestAnimationFrame(callback) {
6280
+ return requestAnimationFrame(callback);
6281
+ }
6282
+ _cancelAnimationFrame(requestId) {
6283
+ cancelAnimationFrame(requestId);
5669
6284
  }
5670
6285
  };
5671
6286
  }
5672
6287
  });
5673
6288
 
5674
6289
  // src/adapter/resources/webgl-fence.ts
5675
- var import_core23, WEBGLFence;
6290
+ var import_core24, WEBGLFence;
5676
6291
  var init_webgl_fence = __esm({
5677
6292
  "src/adapter/resources/webgl-fence.ts"() {
5678
6293
  "use strict";
5679
- import_core23 = __toESM(require_core(), 1);
5680
- WEBGLFence = class extends import_core23.Fence {
6294
+ import_core24 = __toESM(require_core(), 1);
6295
+ WEBGLFence = class extends import_core24.Fence {
5681
6296
  device;
5682
6297
  gl;
5683
6298
  handle;
@@ -5797,7 +6412,7 @@ ${source}`;
5797
6412
  sourceFormat ||= texture?.glFormat || 6408 /* RGBA */;
5798
6413
  sourceType ||= texture?.glType || 5121 /* UNSIGNED_BYTE */;
5799
6414
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5800
- const signedType = (0, import_core24.getDataType)(target2);
6415
+ const signedType = import_core25.dataTypeDecoder.getDataType(target2);
5801
6416
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5802
6417
  const prevHandle = gl.bindFramebuffer(
5803
6418
  36160 /* FRAMEBUFFER */,
@@ -5849,7 +6464,7 @@ ${source}`;
5849
6464
  return webglBufferTarget;
5850
6465
  }
5851
6466
  function getFramebuffer2(source) {
5852
- if (!(source instanceof import_core24.Framebuffer)) {
6467
+ if (!(source instanceof import_core25.Framebuffer)) {
5853
6468
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5854
6469
  }
5855
6470
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5871,15 +6486,15 @@ ${source}`;
5871
6486
  }
5872
6487
  glType ||= 5121 /* UNSIGNED_BYTE */;
5873
6488
  const shaderType = convertGLDataTypeToDataType(glType);
5874
- const ArrayType = (0, import_core24.getTypedArrayConstructor)(shaderType);
6489
+ const ArrayType = import_core25.dataTypeDecoder.getTypedArrayConstructor(shaderType);
5875
6490
  const components = glFormatToComponents(glFormat);
5876
6491
  return new ArrayType(width * height * components);
5877
6492
  }
5878
- var import_core24;
6493
+ var import_core25;
5879
6494
  var init_webgl_texture_utils = __esm({
5880
6495
  "src/adapter/helpers/webgl-texture-utils.ts"() {
5881
6496
  "use strict";
5882
- import_core24 = __toESM(require_core(), 1);
6497
+ import_core25 = __toESM(require_core(), 1);
5883
6498
  init_webgl_shadertypes();
5884
6499
  init_format_utils();
5885
6500
  init_shader_formats();
@@ -5925,11 +6540,11 @@ ${source}`;
5925
6540
  }
5926
6541
  return true;
5927
6542
  }
5928
- var import_core25, WebGLDevice;
6543
+ var import_core26, WebGLDevice;
5929
6544
  var init_webgl_device = __esm({
5930
6545
  "src/adapter/webgl-device.ts"() {
5931
6546
  "use strict";
5932
- import_core25 = __toESM(require_core(), 1);
6547
+ import_core26 = __toESM(require_core(), 1);
5933
6548
  init_webgl_state_tracker();
5934
6549
  init_create_browser_context();
5935
6550
  init_webgl_context_data();
@@ -5937,6 +6552,7 @@ ${source}`;
5937
6552
  init_webgl_device_features();
5938
6553
  init_webgl_device_limits();
5939
6554
  init_webgl_canvas_context();
6555
+ init_webgl_presentation_context();
5940
6556
  init_spector();
5941
6557
  init_webgl_developer_tools();
5942
6558
  init_webgl_texture_table();
@@ -5947,6 +6563,7 @@ ${source}`;
5947
6563
  init_webgl_texture();
5948
6564
  init_webgl_framebuffer();
5949
6565
  init_webgl_render_pipeline();
6566
+ init_webgl_shared_render_pipeline();
5950
6567
  init_webgl_command_encoder();
5951
6568
  init_webgl_vertex_array();
5952
6569
  init_webgl_transform_feedback();
@@ -5956,7 +6573,7 @@ ${source}`;
5956
6573
  init_unified_parameter_api();
5957
6574
  init_with_parameters();
5958
6575
  init_webgl_extensions();
5959
- WebGLDevice = class extends import_core25.Device {
6576
+ WebGLDevice = class extends import_core26.Device {
5960
6577
  static getDeviceFromContext(gl) {
5961
6578
  if (!gl) {
5962
6579
  return null;
@@ -6007,7 +6624,7 @@ ${source}`;
6007
6624
  }
6008
6625
  constructor(props) {
6009
6626
  super({ ...props, id: props.id || uid("webgl-device") });
6010
- const canvasContextProps = import_core25.Device._getCanvasContextProps(props);
6627
+ const canvasContextProps = import_core26.Device._getCanvasContextProps(props);
6011
6628
  if (!canvasContextProps) {
6012
6629
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
6013
6630
  }
@@ -6049,7 +6666,7 @@ ${source}`;
6049
6666
  device = WebGLDevice.getDeviceFromContext(gl);
6050
6667
  if (device) {
6051
6668
  if (props._reuseDevices) {
6052
- import_core25.log.log(
6669
+ import_core26.log.log(
6053
6670
  1,
6054
6671
  `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`,
6055
6672
  device
@@ -6073,17 +6690,18 @@ ${source}`;
6073
6690
  this.features.initializeFeatures();
6074
6691
  }
6075
6692
  const glState = new WebGLStateTracker(this.gl, {
6076
- log: (...args) => import_core25.log.log(1, ...args)()
6693
+ log: (...args) => import_core26.log.log(1, ...args)()
6077
6694
  });
6078
6695
  glState.trackState(this.gl, { copyState: false });
6079
6696
  if (props.debug || props.debugWebGL) {
6080
6697
  this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
6081
- import_core25.log.warn("WebGL debug mode activated. Performance reduced.")();
6698
+ import_core26.log.warn("WebGL debug mode activated. Performance reduced.")();
6082
6699
  }
6083
6700
  if (props.debugWebGL) {
6084
- import_core25.log.level = Math.max(import_core25.log.level, 1);
6701
+ import_core26.log.level = Math.max(import_core26.log.level, 1);
6085
6702
  }
6086
6703
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6704
+ this.canvasContext._startObservers();
6087
6705
  }
6088
6706
  /**
6089
6707
  * Destroys the device
@@ -6096,6 +6714,7 @@ ${source}`;
6096
6714
  * browser API for destroying WebGL contexts.
6097
6715
  */
6098
6716
  destroy() {
6717
+ this.commandEncoder?.destroy();
6099
6718
  if (!this.props._reuseDevices && !this._reused) {
6100
6719
  const contextData = getWebGLContextData(this.handle);
6101
6720
  contextData.device = null;
@@ -6108,6 +6727,9 @@ ${source}`;
6108
6727
  createCanvasContext(props) {
6109
6728
  throw new Error("WebGL only supports a single canvas");
6110
6729
  }
6730
+ createPresentationContext(props) {
6731
+ return new WebGLPresentationContext(this, props || {});
6732
+ }
6111
6733
  createBuffer(props) {
6112
6734
  const newProps = this._normalizeBufferProps(props);
6113
6735
  return new WEBGLBuffer(this, newProps);
@@ -6142,6 +6764,12 @@ ${source}`;
6142
6764
  createRenderPipeline(props) {
6143
6765
  return new WEBGLRenderPipeline(this, props);
6144
6766
  }
6767
+ _createSharedRenderPipelineWebGL(props) {
6768
+ return new WEBGLSharedRenderPipeline(
6769
+ this,
6770
+ props
6771
+ );
6772
+ }
6145
6773
  createComputePipeline(props) {
6146
6774
  throw new Error("ComputePipeline not supported in WebGL");
6147
6775
  }
@@ -6154,12 +6782,31 @@ ${source}`;
6154
6782
  * Chrome's offscreen canvas does not require gl.commit
6155
6783
  */
6156
6784
  submit(commandBuffer) {
6785
+ let submittedCommandEncoder = null;
6157
6786
  if (!commandBuffer) {
6158
- commandBuffer = this.commandEncoder.finish();
6159
- this.commandEncoder.destroy();
6160
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
6787
+ ({ submittedCommandEncoder, commandBuffer } = this._finalizeDefaultCommandEncoderForSubmit());
6788
+ }
6789
+ try {
6790
+ commandBuffer._executeCommands();
6791
+ if (submittedCommandEncoder) {
6792
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
6793
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
6794
+ }).catch(() => {
6795
+ });
6796
+ }
6797
+ } finally {
6798
+ commandBuffer.destroy();
6161
6799
  }
6162
- commandBuffer._executeCommands();
6800
+ }
6801
+ _finalizeDefaultCommandEncoderForSubmit() {
6802
+ const submittedCommandEncoder = this.commandEncoder;
6803
+ const commandBuffer = submittedCommandEncoder.finish();
6804
+ this.commandEncoder.destroy();
6805
+ this.commandEncoder = this.createCommandEncoder({
6806
+ id: submittedCommandEncoder.props.id,
6807
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
6808
+ });
6809
+ return { submittedCommandEncoder, commandBuffer };
6163
6810
  }
6164
6811
  //
6165
6812
  // TEMPORARY HACKS - will be removed in v9.1
@@ -6182,7 +6829,7 @@ ${source}`;
6182
6829
  return withGLParameters(this.gl, parameters, func);
6183
6830
  }
6184
6831
  resetWebGL() {
6185
- import_core25.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6832
+ import_core26.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6186
6833
  resetGLParameters(this.gl);
6187
6834
  }
6188
6835
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
@@ -6254,7 +6901,7 @@ ${source}`;
6254
6901
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
6255
6902
  const currentConstant = this._constants[location];
6256
6903
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
6257
- import_core25.log.info(
6904
+ import_core26.log.info(
6258
6905
  1,
6259
6906
  `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`
6260
6907
  )();
@@ -6300,21 +6947,21 @@ ${source}`;
6300
6947
  }
6301
6948
  return Boolean(gl && typeof gl.createVertexArray === "function");
6302
6949
  }
6303
- var import_core26, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
6950
+ var import_core27, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
6304
6951
  var init_webgl_adapter = __esm({
6305
6952
  "src/adapter/webgl-adapter.ts"() {
6306
6953
  "use strict";
6307
- import_core26 = __toESM(require_core(), 1);
6954
+ import_core27 = __toESM(require_core(), 1);
6308
6955
  init_polyfill_webgl1_extensions();
6309
6956
  init_spector();
6310
6957
  init_webgl_developer_tools();
6311
6958
  LOG_LEVEL2 = 1;
6312
- WebGLAdapter = class extends import_core26.Adapter {
6959
+ WebGLAdapter = class extends import_core27.Adapter {
6313
6960
  /** type of device's created by this adapter */
6314
6961
  type = "webgl";
6315
6962
  constructor() {
6316
6963
  super();
6317
- import_core26.Device.defaultProps = { ...import_core26.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
6964
+ import_core27.Device.defaultProps = { ...import_core27.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
6318
6965
  }
6319
6966
  /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
6320
6967
  enforceWebGL2(enable2) {
@@ -6329,7 +6976,7 @@ ${source}`;
6329
6976
  return true;
6330
6977
  }
6331
6978
  if (typeof WebGLRenderingContext !== "undefined" && handle instanceof WebGLRenderingContext) {
6332
- import_core26.log.warn("WebGL1 is not supported", handle)();
6979
+ import_core27.log.warn("WebGL1 is not supported", handle)();
6333
6980
  }
6334
6981
  return false;
6335
6982
  }
@@ -6371,19 +7018,19 @@ ${source}`;
6371
7018
  const results = await Promise.allSettled(promises);
6372
7019
  for (const result of results) {
6373
7020
  if (result.status === "rejected") {
6374
- import_core26.log.error(`Failed to initialize debug libraries ${result.reason}`)();
7021
+ import_core27.log.error(`Failed to initialize debug libraries ${result.reason}`)();
6375
7022
  }
6376
7023
  }
6377
7024
  try {
6378
7025
  const device = new WebGLDevice2(props);
6379
- import_core26.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
7026
+ import_core27.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
6380
7027
  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}`;
6381
- import_core26.log.probe(LOG_LEVEL2, message2)();
6382
- import_core26.log.table(LOG_LEVEL2, device.info)();
7028
+ import_core27.log.probe(LOG_LEVEL2, message2)();
7029
+ import_core27.log.table(LOG_LEVEL2, device.info)();
6383
7030
  return device;
6384
7031
  } finally {
6385
- import_core26.log.groupEnd(LOG_LEVEL2)();
6386
- import_core26.log.info(
7032
+ import_core27.log.groupEnd(LOG_LEVEL2)();
7033
+ import_core27.log.info(
6387
7034
  LOG_LEVEL2,
6388
7035
  `%cWebGL call tracing: luma.log.set('debug-webgl') `,
6389
7036
  "color: white; background: blue; padding: 2px 6px; border-radius: 3px;"
@@ -6396,9 +7043,10 @@ ${source}`;
6396
7043
  });
6397
7044
 
6398
7045
  // src/index.ts
6399
- var init_src2 = __esm({
7046
+ var init_src = __esm({
6400
7047
  "src/index.ts"() {
6401
7048
  "use strict";
7049
+ init_webgl_constants();
6402
7050
  init_webgl_adapter();
6403
7051
  init_webgl_device();
6404
7052
  init_webgl_canvas_context();
@@ -6424,6 +7072,7 @@ ${source}`;
6424
7072
  // bundle.ts
6425
7073
  var bundle_exports = {};
6426
7074
  __export(bundle_exports, {
7075
+ GL: () => GLEnum,
6427
7076
  WEBGLBuffer: () => WEBGLBuffer,
6428
7077
  WEBGLCommandEncoder: () => WEBGLCommandEncoder,
6429
7078
  WEBGLFence: () => WEBGLFence,
@@ -6448,7 +7097,7 @@ ${source}`;
6448
7097
  withGLParameters: () => withGLParameters
6449
7098
  });
6450
7099
  __reExport(bundle_exports, __toESM(require_core(), 1));
6451
- init_src2();
7100
+ init_src();
6452
7101
  return __toCommonJS(bundle_exports);
6453
7102
  })();
6454
7103
  return __exports__;