@luma.gl/webgl 9.3.0-alpha.2 → 9.3.0-alpha.6

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 (106) hide show
  1. package/dist/adapter/converters/webgl-texture-table.d.ts +7 -1
  2. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
  3. package/dist/adapter/converters/webgl-texture-table.js +121 -43
  4. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  5. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  6. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  7. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
  8. package/dist/adapter/device-helpers/webgl-device-info.js +5 -0
  9. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
  10. package/dist/adapter/helpers/get-shader-layout-from-glsl.js +23 -21
  11. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  12. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts +1 -1
  13. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts.map +1 -1
  14. package/dist/adapter/helpers/parse-shader-compiler-log.js +20 -0
  15. package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -1
  16. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-buffer.js +19 -4
  18. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  19. package/dist/adapter/resources/webgl-command-buffer.d.ts +3 -4
  20. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-command-buffer.js +11 -7
  22. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  23. package/dist/adapter/resources/webgl-command-encoder.d.ts +5 -4
  24. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-command-encoder.js +20 -7
  26. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  27. package/dist/adapter/resources/webgl-query-set.d.ts +29 -31
  28. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  29. package/dist/adapter/resources/webgl-query-set.js +193 -97
  30. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  31. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  32. package/dist/adapter/resources/webgl-render-pass.js +17 -0
  33. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  34. package/dist/adapter/resources/webgl-render-pipeline.d.ts +13 -19
  35. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  36. package/dist/adapter/resources/webgl-render-pipeline.js +36 -154
  37. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  38. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  39. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  40. package/dist/adapter/resources/webgl-shared-render-pipeline.js +152 -0
  41. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  42. package/dist/adapter/resources/webgl-texture.d.ts +23 -4
  43. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  44. package/dist/adapter/resources/webgl-texture.js +203 -100
  45. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  46. package/dist/adapter/resources/webgl-transform-feedback.js +5 -5
  47. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  48. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  49. package/dist/adapter/webgl-adapter.js +3 -4
  50. package/dist/adapter/webgl-adapter.js.map +1 -1
  51. package/dist/adapter/webgl-device.d.ts +6 -3
  52. package/dist/adapter/webgl-device.d.ts.map +1 -1
  53. package/dist/adapter/webgl-device.js +56 -14
  54. package/dist/adapter/webgl-device.js.map +1 -1
  55. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  56. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  57. package/dist/adapter/webgl-presentation-context.js +64 -0
  58. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  59. package/dist/context/debug/spector.d.ts.map +1 -1
  60. package/dist/context/debug/spector.js +4 -4
  61. package/dist/context/debug/spector.js.map +1 -1
  62. package/dist/context/debug/webgl-developer-tools.js +2 -0
  63. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  64. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  65. package/dist/context/helpers/create-browser-context.js +6 -8
  66. package/dist/context/helpers/create-browser-context.js.map +1 -1
  67. package/dist/context/helpers/webgl-context-data.d.ts +5 -1
  68. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  69. package/dist/context/helpers/webgl-context-data.js +9 -10
  70. package/dist/context/helpers/webgl-context-data.js.map +1 -1
  71. package/dist/context/parameters/unified-parameter-api.d.ts +1 -1
  72. package/dist/context/parameters/unified-parameter-api.js +2 -2
  73. package/dist/context/parameters/unified-parameter-api.js.map +1 -1
  74. package/dist/context/state-tracker/webgl-state-tracker.js +2 -2
  75. package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -1
  76. package/dist/dist.dev.js +1427 -828
  77. package/dist/dist.min.js +2 -2
  78. package/dist/index.cjs +1325 -811
  79. package/dist/index.cjs.map +4 -4
  80. package/dist/utils/fill-array.js +1 -1
  81. package/dist/utils/fill-array.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/adapter/converters/webgl-texture-table.ts +159 -47
  84. package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
  85. package/src/adapter/device-helpers/webgl-device-info.ts +6 -0
  86. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +25 -24
  87. package/src/adapter/helpers/parse-shader-compiler-log.ts +23 -1
  88. package/src/adapter/resources/webgl-buffer.ts +16 -4
  89. package/src/adapter/resources/webgl-command-buffer.ts +21 -24
  90. package/src/adapter/resources/webgl-command-encoder.ts +22 -7
  91. package/src/adapter/resources/webgl-query-set.ts +229 -102
  92. package/src/adapter/resources/webgl-render-pass.ts +19 -0
  93. package/src/adapter/resources/webgl-render-pipeline.ts +46 -181
  94. package/src/adapter/resources/webgl-shared-render-pipeline.ts +208 -0
  95. package/src/adapter/resources/webgl-texture.ts +326 -121
  96. package/src/adapter/resources/webgl-transform-feedback.ts +5 -5
  97. package/src/adapter/webgl-adapter.ts +3 -4
  98. package/src/adapter/webgl-device.ts +66 -19
  99. package/src/adapter/webgl-presentation-context.ts +93 -0
  100. package/src/context/debug/spector.ts +4 -4
  101. package/src/context/debug/webgl-developer-tools.ts +2 -0
  102. package/src/context/helpers/create-browser-context.ts +8 -8
  103. package/src/context/helpers/webgl-context-data.ts +17 -11
  104. package/src/context/parameters/unified-parameter-api.ts +2 -2
  105. package/src/context/state-tracker/webgl-state-tracker.ts +2 -2
  106. package/src/utils/fill-array.ts +1 -1
package/dist/index.cjs CHANGED
@@ -155,6 +155,24 @@ var init_load_script = __esm({
155
155
  }
156
156
  });
157
157
 
158
+ // dist/context/helpers/webgl-context-data.js
159
+ function getWebGLContextData(gl) {
160
+ const contextData = gl.luma || {
161
+ _polyfilled: false,
162
+ extensions: {},
163
+ softwareRenderer: false
164
+ };
165
+ contextData._polyfilled ??= false;
166
+ contextData.extensions ||= {};
167
+ gl.luma = contextData;
168
+ return contextData;
169
+ }
170
+ var init_webgl_context_data = __esm({
171
+ "dist/context/helpers/webgl-context-data.js"() {
172
+ "use strict";
173
+ }
174
+ });
175
+
158
176
  // dist/context/debug/spector.js
159
177
  async function loadSpectorJS(props) {
160
178
  if (!globalThis.SPECTOR) {
@@ -195,9 +213,10 @@ function initializeSpectorJS(props) {
195
213
  }
196
214
  if (props.gl) {
197
215
  const gl = props.gl;
198
- const device = gl.device;
216
+ const contextData = getWebGLContextData(gl);
217
+ const device = contextData.device;
199
218
  spector == null ? void 0 : spector.startCapture(props.gl, 500);
200
- gl.device = device;
219
+ contextData.device = device;
201
220
  new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
202
221
  import_core.log.info("Spector capture stopped after 2 seconds")();
203
222
  spector == null ? void 0 : spector.stopCapture();
@@ -211,6 +230,7 @@ var init_spector = __esm({
211
230
  "use strict";
212
231
  import_core = require("@luma.gl/core");
213
232
  init_load_script();
233
+ init_webgl_context_data();
214
234
  LOG_LEVEL = 1;
215
235
  spector = null;
216
236
  initialized = false;
@@ -226,7 +246,7 @@ var init_spector = __esm({
226
246
  });
227
247
 
228
248
  // dist/context/debug/webgl-developer-tools.js
229
- function getWebGLContextData(gl) {
249
+ function getWebGLContextData2(gl) {
230
250
  gl.luma = gl.luma || {};
231
251
  return gl.luma;
232
252
  }
@@ -241,7 +261,7 @@ function makeDebugContext(gl, props = {}) {
241
261
  return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
242
262
  }
243
263
  function getRealContext(gl) {
244
- const data = getWebGLContextData(gl);
264
+ const data = getWebGLContextData2(gl);
245
265
  return data.realContext ? data.realContext : gl;
246
266
  }
247
267
  function getDebugContext(gl, props) {
@@ -249,7 +269,7 @@ function getDebugContext(gl, props) {
249
269
  import_core2.log.warn("webgl-debug not loaded")();
250
270
  return gl;
251
271
  }
252
- const data = getWebGLContextData(gl);
272
+ const data = getWebGLContextData2(gl);
253
273
  if (data.debugContext) {
254
274
  return data.debugContext;
255
275
  }
@@ -267,6 +287,7 @@ function getDebugContext(gl, props) {
267
287
  const debugContext = Object.create(WebGLDebugContext);
268
288
  data.realContext = gl;
269
289
  data.debugContext = debugContext;
290
+ debugContext.luma = data;
270
291
  debugContext.debug = true;
271
292
  return debugContext;
272
293
  }
@@ -791,6 +812,7 @@ var init_webgl_parameter_tables = __esm({
791
812
 
792
813
  // dist/context/parameters/unified-parameter-api.js
793
814
  function setGLParameters(gl, parameters) {
815
+ var _a;
794
816
  if (isObjectEmpty(parameters)) {
795
817
  return;
796
818
  }
@@ -806,7 +828,7 @@ function setGLParameters(gl, parameters) {
806
828
  }
807
829
  }
808
830
  }
809
- const cache = gl.state && gl.state.cache;
831
+ const cache = (_a = gl.lumaState) == null ? void 0 : _a.cache;
810
832
  if (cache) {
811
833
  for (const key in compositeSetters) {
812
834
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -929,7 +951,7 @@ var init_webgl_state_tracker = __esm({
929
951
  init_webgl_parameter_tables();
930
952
  WebGLStateTracker = class {
931
953
  static get(gl) {
932
- return gl.state;
954
+ return gl.lumaState;
933
955
  }
934
956
  gl;
935
957
  program = null;
@@ -967,7 +989,7 @@ var init_webgl_state_tracker = __esm({
967
989
  throw new Error("WebGLStateTracker");
968
990
  }
969
991
  this.initialized = true;
970
- this.gl.state = this;
992
+ this.gl.lumaState = this;
971
993
  installProgramSpy(gl);
972
994
  for (const key in GL_HOOKED_SETTERS) {
973
995
  const setter = GL_HOOKED_SETTERS[key];
@@ -1027,13 +1049,11 @@ function createBrowserContext(canvas, props, webglContextAttributes) {
1027
1049
  if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1028
1050
  errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1029
1051
  }
1052
+ let softwareRenderer = false;
1030
1053
  if (!gl && allowSoftwareRenderer) {
1031
1054
  webglProps.failIfMajorPerformanceCaveat = false;
1032
1055
  gl = canvas.getContext("webgl2", webglProps);
1033
- if (gl) {
1034
- gl.luma ||= {};
1035
- gl.luma.softwareRenderer = true;
1036
- }
1056
+ softwareRenderer = true;
1037
1057
  }
1038
1058
  if (!gl) {
1039
1059
  gl = canvas.getContext("webgl", {});
@@ -1046,10 +1066,11 @@ function createBrowserContext(canvas, props, webglContextAttributes) {
1046
1066
  errorMessage ||= "Your browser does not support WebGL";
1047
1067
  throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1048
1068
  }
1069
+ const luma = getWebGLContextData(gl);
1070
+ luma.softwareRenderer = softwareRenderer;
1049
1071
  const { onContextLost, onContextRestored } = props;
1050
1072
  canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1051
1073
  canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1052
- gl.luma ||= {};
1053
1074
  return gl;
1054
1075
  } finally {
1055
1076
  canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
@@ -1058,6 +1079,7 @@ function createBrowserContext(canvas, props, webglContextAttributes) {
1058
1079
  var init_create_browser_context = __esm({
1059
1080
  "dist/context/helpers/create-browser-context.js"() {
1060
1081
  "use strict";
1082
+ init_webgl_context_data();
1061
1083
  }
1062
1084
  });
1063
1085
 
@@ -1135,6 +1157,8 @@ function identifyGPUType(vendor, renderer) {
1135
1157
  }
1136
1158
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1137
1159
  switch (gpuVendor) {
1160
+ case "apple":
1161
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1138
1162
  case "intel":
1139
1163
  return "integrated";
1140
1164
  case "software":
@@ -1145,6 +1169,9 @@ function identifyGPUType(vendor, renderer) {
1145
1169
  return "discrete";
1146
1170
  }
1147
1171
  }
1172
+ function isAppleSiliconGPU(vendor, renderer) {
1173
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1174
+ }
1148
1175
  var import_constants4;
1149
1176
  var init_webgl_device_info = __esm({
1150
1177
  "dist/adapter/device-helpers/webgl-device-info.js"() {
@@ -1197,8 +1224,23 @@ function isTextureFeature(feature) {
1197
1224
  return feature in TEXTURE_FEATURES;
1198
1225
  }
1199
1226
  function checkTextureFeature(gl, feature, extensions) {
1200
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1201
- return textureExtensions.every((extension) => getWebGLExtension(gl, extension, extensions));
1227
+ return hasTextureFeature(gl, feature, extensions, /* @__PURE__ */ new Set());
1228
+ }
1229
+ function hasTextureFeature(gl, feature, extensions, seenFeatures) {
1230
+ const definition = TEXTURE_FEATURES[feature];
1231
+ if (!definition) {
1232
+ return false;
1233
+ }
1234
+ if (seenFeatures.has(feature)) {
1235
+ return false;
1236
+ }
1237
+ seenFeatures.add(feature);
1238
+ const hasDependentFeatures = (definition.features || []).every((dependentFeature) => hasTextureFeature(gl, dependentFeature, extensions, seenFeatures));
1239
+ seenFeatures.delete(feature);
1240
+ if (!hasDependentFeatures) {
1241
+ return false;
1242
+ }
1243
+ return (definition.extensions || []).every((extension) => Boolean(getWebGLExtension(gl, extension, extensions)));
1202
1244
  }
1203
1245
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1204
1246
  let supported = formatSupport.create;
@@ -1209,12 +1251,17 @@ function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1209
1251
  if (webglFormatInfo == null ? void 0 : webglFormatInfo.x) {
1210
1252
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1211
1253
  }
1254
+ if (formatSupport.format === "stencil8") {
1255
+ supported = false;
1256
+ }
1257
+ const renderFeatureSupported = (webglFormatInfo == null ? void 0 : webglFormatInfo.r) === false ? false : (webglFormatInfo == null ? void 0 : webglFormatInfo.r) === void 0 || checkTextureFeature(gl, webglFormatInfo.r, extensions);
1258
+ const renderable = supported && formatSupport.render && renderFeatureSupported && isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
1212
1259
  return {
1213
1260
  format: formatSupport.format,
1214
1261
  // @ts-ignore
1215
1262
  create: supported && formatSupport.create,
1216
1263
  // @ts-ignore
1217
- render: supported && formatSupport.render,
1264
+ render: renderable,
1218
1265
  // @ts-ignore
1219
1266
  filter: supported && formatSupport.filter,
1220
1267
  // @ts-ignore
@@ -1223,6 +1270,45 @@ function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1223
1270
  store: supported && formatSupport.store
1224
1271
  };
1225
1272
  }
1273
+ function isColorRenderableTextureFormat(gl, format, extensions) {
1274
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
1275
+ const internalFormat = webglFormatInfo == null ? void 0 : webglFormatInfo.gl;
1276
+ if (internalFormat === void 0) {
1277
+ return false;
1278
+ }
1279
+ if ((webglFormatInfo == null ? void 0 : webglFormatInfo.x) && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
1280
+ return false;
1281
+ }
1282
+ const previousTexture = gl.getParameter(32873);
1283
+ const previousFramebuffer = gl.getParameter(36006);
1284
+ const texture = gl.createTexture();
1285
+ const framebuffer = gl.createFramebuffer();
1286
+ if (!texture || !framebuffer) {
1287
+ return false;
1288
+ }
1289
+ const noError = Number(0);
1290
+ let error = Number(gl.getError());
1291
+ while (error !== noError) {
1292
+ error = gl.getError();
1293
+ }
1294
+ let renderable = false;
1295
+ try {
1296
+ gl.bindTexture(3553, texture);
1297
+ gl.texStorage2D(3553, 1, internalFormat, 1, 1);
1298
+ if (Number(gl.getError()) !== noError) {
1299
+ return false;
1300
+ }
1301
+ gl.bindFramebuffer(36160, framebuffer);
1302
+ gl.framebufferTexture2D(36160, 36064, 3553, texture, 0);
1303
+ renderable = Number(gl.checkFramebufferStatus(36160)) === Number(36053) && Number(gl.getError()) === noError;
1304
+ } finally {
1305
+ gl.bindFramebuffer(36160, previousFramebuffer);
1306
+ gl.deleteFramebuffer(framebuffer);
1307
+ gl.bindTexture(3553, previousTexture);
1308
+ gl.deleteTexture(texture);
1309
+ }
1310
+ return renderable;
1311
+ }
1226
1312
  function getTextureFormatWebGL(format) {
1227
1313
  var _a;
1228
1314
  const formatData = WEBGL_TEXTURE_FORMATS[format];
@@ -1279,7 +1365,7 @@ function convertTextureFormatToGL(format) {
1279
1365
  }
1280
1366
  return webglFormat;
1281
1367
  }
1282
- var import_core3, import_constants6, 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;
1368
+ var import_core3, import_constants6, 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;
1283
1369
  var init_webgl_texture_table = __esm({
1284
1370
  "dist/adapter/converters/webgl-texture-table.js"() {
1285
1371
  "use strict";
@@ -1299,44 +1385,51 @@ var init_webgl_texture_table = __esm({
1299
1385
  EXT_texture_norm16 = "EXT_texture_norm16";
1300
1386
  EXT_render_snorm = "EXT_render_snorm";
1301
1387
  EXT_color_buffer_float = "EXT_color_buffer_float";
1388
+ SNORM8_COLOR_RENDERABLE = "snorm8-renderable-webgl";
1389
+ NORM16_COLOR_RENDERABLE = "norm16-renderable-webgl";
1390
+ SNORM16_COLOR_RENDERABLE = "snorm16-renderable-webgl";
1391
+ FLOAT16_COLOR_RENDERABLE = "float16-renderable-webgl";
1392
+ FLOAT32_COLOR_RENDERABLE = "float32-renderable-webgl";
1393
+ RGB9E5UFLOAT_COLOR_RENDERABLE = "rgb9e5ufloat-renderable-webgl";
1302
1394
  TEXTURE_FEATURES = {
1303
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1304
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1305
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1306
- "snorm8-renderable-webgl": [EXT_render_snorm],
1307
- "norm16-renderable-webgl": [EXT_texture_norm16],
1308
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1309
- "float32-filterable": ["OES_texture_float_linear"],
1310
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1311
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1312
- "texture-blend-float-webgl": ["EXT_float_blend"],
1313
- "texture-compression-bc": [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
1395
+ "float32-renderable-webgl": { extensions: [EXT_color_buffer_float] },
1396
+ "float16-renderable-webgl": { extensions: ["EXT_color_buffer_half_float"] },
1397
+ "rgb9e5ufloat-renderable-webgl": { extensions: ["WEBGL_render_shared_exponent"] },
1398
+ "snorm8-renderable-webgl": { extensions: [EXT_render_snorm] },
1399
+ "norm16-webgl": { extensions: [EXT_texture_norm16] },
1400
+ "norm16-renderable-webgl": { features: ["norm16-webgl"] },
1401
+ "snorm16-renderable-webgl": { features: ["norm16-webgl"], extensions: [EXT_render_snorm] },
1402
+ "float32-filterable": { extensions: ["OES_texture_float_linear"] },
1403
+ "float16-filterable-webgl": { extensions: ["OES_texture_half_float_linear"] },
1404
+ "texture-filterable-anisotropic-webgl": { extensions: ["EXT_texture_filter_anisotropic"] },
1405
+ "texture-blend-float-webgl": { extensions: ["EXT_float_blend"] },
1406
+ "texture-compression-bc": { extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC] },
1314
1407
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1315
1408
  // 'texture-compression-bc3-webgl': [X_S3TC],
1316
- "texture-compression-bc5-webgl": [X_RGTC],
1317
- "texture-compression-bc7-webgl": [X_BPTC],
1318
- "texture-compression-etc2": [X_ETC2],
1319
- "texture-compression-astc": [X_ASTC],
1320
- "texture-compression-etc1-webgl": [X_ETC1],
1321
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1322
- "texture-compression-atc-webgl": [X_ATC]
1409
+ "texture-compression-bc5-webgl": { extensions: [X_RGTC] },
1410
+ "texture-compression-bc7-webgl": { extensions: [X_BPTC] },
1411
+ "texture-compression-etc2": { extensions: [X_ETC2] },
1412
+ "texture-compression-astc": { extensions: [X_ASTC] },
1413
+ "texture-compression-etc1-webgl": { extensions: [X_ETC1] },
1414
+ "texture-compression-pvrtc-webgl": { extensions: [X_PVRTC] },
1415
+ "texture-compression-atc-webgl": { extensions: [X_ATC] }
1323
1416
  };
1324
1417
  WEBGL_TEXTURE_FORMATS = {
1325
1418
  // 8-bit formats
1326
1419
  "r8unorm": { gl: 33321, rb: true },
1327
- "r8snorm": { gl: 36756 },
1420
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1328
1421
  "r8uint": { gl: 33330, rb: true },
1329
1422
  "r8sint": { gl: 33329, rb: true },
1330
1423
  // 16-bit formats
1331
1424
  "rg8unorm": { gl: 33323, rb: true },
1332
- "rg8snorm": { gl: 36757 },
1425
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1333
1426
  "rg8uint": { gl: 33336, rb: true },
1334
1427
  "rg8sint": { gl: 33335, rb: true },
1335
1428
  "r16uint": { gl: 33332, rb: true },
1336
1429
  "r16sint": { gl: 33331, rb: true },
1337
- "r16float": { gl: 33325, rb: true },
1338
- "r16unorm": { gl: 33322, rb: true },
1339
- "r16snorm": { gl: 36760 },
1430
+ "r16float": { gl: 33325, rb: true, r: FLOAT16_COLOR_RENDERABLE },
1431
+ "r16unorm": { gl: 33322, rb: true, r: NORM16_COLOR_RENDERABLE },
1432
+ "r16snorm": { gl: 36760, r: SNORM16_COLOR_RENDERABLE },
1340
1433
  // Packed 16-bit formats
1341
1434
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1342
1435
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1347,7 +1440,7 @@ var init_webgl_texture_table = __esm({
1347
1440
  // 32-bit formats
1348
1441
  "rgba8unorm": { gl: 32856 },
1349
1442
  "rgba8unorm-srgb": { gl: 35907 },
1350
- "rgba8snorm": { gl: 36759 },
1443
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1351
1444
  "rgba8uint": { gl: 36220 },
1352
1445
  "rgba8sint": { gl: 36238 },
1353
1446
  // reverse colors, webgpu only
@@ -1355,38 +1448,38 @@ var init_webgl_texture_table = __esm({
1355
1448
  "bgra8unorm-srgb": {},
1356
1449
  "rg16uint": { gl: 33338 },
1357
1450
  "rg16sint": { gl: 33337 },
1358
- "rg16float": { gl: 33327, rb: true },
1359
- "rg16unorm": { gl: 33324 },
1360
- "rg16snorm": { gl: 36761 },
1451
+ "rg16float": { gl: 33327, rb: true, r: FLOAT16_COLOR_RENDERABLE },
1452
+ "rg16unorm": { gl: 33324, r: NORM16_COLOR_RENDERABLE },
1453
+ "rg16snorm": { gl: 36761, r: SNORM16_COLOR_RENDERABLE },
1361
1454
  "r32uint": { gl: 33334, rb: true },
1362
1455
  "r32sint": { gl: 33333, rb: true },
1363
- "r32float": { gl: 33326 },
1456
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1364
1457
  // Packed 32-bit formats
1365
- "rgb9e5ufloat": { gl: 35901 },
1458
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1366
1459
  // , filter: true},
1367
1460
  "rg11b10ufloat": { gl: 35898, rb: true },
1368
1461
  "rgb10a2unorm": { gl: 32857, rb: true },
1369
1462
  "rgb10a2uint": { gl: 36975, rb: true },
1370
1463
  // 48-bit formats
1371
- "rgb16unorm-webgl": { gl: 32852 },
1464
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1372
1465
  // rgb not renderable
1373
- "rgb16snorm-webgl": { gl: 36762 },
1466
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1374
1467
  // rgb not renderable
1375
1468
  // 64-bit formats
1376
1469
  "rg32uint": { gl: 33340, rb: true },
1377
1470
  "rg32sint": { gl: 33339, rb: true },
1378
- "rg32float": { gl: 33328, rb: true },
1471
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1379
1472
  "rgba16uint": { gl: 36214, rb: true },
1380
1473
  "rgba16sint": { gl: 36232, rb: true },
1381
- "rgba16float": { gl: 34842 },
1382
- "rgba16unorm": { gl: 32859, rb: true },
1383
- "rgba16snorm": { gl: 36763 },
1474
+ "rgba16float": { gl: 34842, r: FLOAT16_COLOR_RENDERABLE },
1475
+ "rgba16unorm": { gl: 32859, rb: true, r: NORM16_COLOR_RENDERABLE },
1476
+ "rgba16snorm": { gl: 36763, r: SNORM16_COLOR_RENDERABLE },
1384
1477
  // 96-bit formats (deprecated!)
1385
- "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, dataFormat: 6407, types: [5126] },
1478
+ "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: 6407, types: [5126] },
1386
1479
  // 128-bit formats
1387
1480
  "rgba32uint": { gl: 36208, rb: true },
1388
1481
  "rgba32sint": { gl: 36226, rb: true },
1389
- "rgba32float": { gl: 34836, rb: true },
1482
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1390
1483
  // Depth and stencil formats
1391
1484
  "stencil8": { gl: 36168, rb: true },
1392
1485
  // 8 stencil bits
@@ -1444,8 +1537,8 @@ var init_webgl_texture_table = __esm({
1444
1537
  "astc-8x6-unorm-srgb": { gl: 37846 },
1445
1538
  "astc-8x8-unorm": { gl: 37815 },
1446
1539
  "astc-8x8-unorm-srgb": { gl: 37847 },
1447
- "astc-10x5-unorm": { gl: 37819 },
1448
- "astc-10x5-unorm-srgb": { gl: 37851 },
1540
+ "astc-10x5-unorm": { gl: 37816 },
1541
+ "astc-10x5-unorm-srgb": { gl: 37848 },
1449
1542
  "astc-10x6-unorm": { gl: 37817 },
1450
1543
  "astc-10x6-unorm-srgb": { gl: 37849 },
1451
1544
  "astc-10x8-unorm": { gl: 37818 },
@@ -1459,7 +1552,7 @@ var init_webgl_texture_table = __esm({
1459
1552
  // WEBGL_compressed_texture_pvrtc
1460
1553
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
1461
1554
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
1462
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
1555
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
1463
1556
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
1464
1557
  // WEBGL_compressed_texture_etc1
1465
1558
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -1483,12 +1576,11 @@ var init_webgl_device_features = __esm({
1483
1576
  // optional WebGPU features
1484
1577
  "depth-clip-control": "EXT_depth_clamp",
1485
1578
  // TODO these seem subtly different
1486
- // 'timestamp-query' // GPUQueryType "timestamp-query"
1579
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
1487
1580
  // "indirect-first-instance"
1488
1581
  // Textures are handled by getTextureFeatures()
1489
1582
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
1490
1583
  // optional WebGL features
1491
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
1492
1584
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
1493
1585
  "polygon-mode-webgl": "WEBGL_polygon_mode",
1494
1586
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -1832,6 +1924,61 @@ var init_webgl_canvas_context = __esm({
1832
1924
  }
1833
1925
  });
1834
1926
 
1927
+ // dist/adapter/webgl-presentation-context.js
1928
+ var import_core8, WebGLPresentationContext;
1929
+ var init_webgl_presentation_context = __esm({
1930
+ "dist/adapter/webgl-presentation-context.js"() {
1931
+ "use strict";
1932
+ import_core8 = require("@luma.gl/core");
1933
+ WebGLPresentationContext = class extends import_core8.PresentationContext {
1934
+ device;
1935
+ handle = null;
1936
+ context2d;
1937
+ get [Symbol.toStringTag]() {
1938
+ return "WebGLPresentationContext";
1939
+ }
1940
+ constructor(device, props = {}) {
1941
+ super(props);
1942
+ this.device = device;
1943
+ const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
1944
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
1945
+ if (!defaultCanvasContext.offscreenCanvas) {
1946
+ throw new Error(`${contextLabel}: WebGL PresentationContext requires the default CanvasContext canvas to be an OffscreenCanvas`);
1947
+ }
1948
+ const context2d = this.canvas.getContext("2d");
1949
+ if (!context2d) {
1950
+ throw new Error(`${contextLabel}: Failed to create 2d presentation context`);
1951
+ }
1952
+ this.context2d = context2d;
1953
+ this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
1954
+ this._configureDevice();
1955
+ this._startObservers();
1956
+ }
1957
+ present() {
1958
+ this._resizeDrawingBufferIfNeeded();
1959
+ this.device.submit();
1960
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
1961
+ const [sourceWidth, sourceHeight] = defaultCanvasContext.getDrawingBufferSize();
1962
+ if (this.drawingBufferWidth === 0 || this.drawingBufferHeight === 0 || sourceWidth === 0 || sourceHeight === 0 || defaultCanvasContext.canvas.width === 0 || defaultCanvasContext.canvas.height === 0) {
1963
+ return;
1964
+ }
1965
+ if (sourceWidth !== this.drawingBufferWidth || sourceHeight !== this.drawingBufferHeight || defaultCanvasContext.canvas.width !== this.drawingBufferWidth || defaultCanvasContext.canvas.height !== this.drawingBufferHeight) {
1966
+ throw new Error(`${this[Symbol.toStringTag]}(${this.id}): Default canvas context size ${sourceWidth}x${sourceHeight} does not match presentation size ${this.drawingBufferWidth}x${this.drawingBufferHeight}`);
1967
+ }
1968
+ this.context2d.clearRect(0, 0, this.drawingBufferWidth, this.drawingBufferHeight);
1969
+ this.context2d.drawImage(defaultCanvasContext.canvas, 0, 0);
1970
+ }
1971
+ _configureDevice() {
1972
+ }
1973
+ _getCurrentFramebuffer(options) {
1974
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
1975
+ defaultCanvasContext.setDrawingBufferSize(this.drawingBufferWidth, this.drawingBufferHeight);
1976
+ return defaultCanvasContext.getCurrentFramebuffer(options);
1977
+ }
1978
+ };
1979
+ }
1980
+ });
1981
+
1835
1982
  // dist/utils/uid.js
1836
1983
  function uid(id = "id") {
1837
1984
  uidCounters[id] = uidCounters[id] || 1;
@@ -1848,36 +1995,36 @@ var init_uid = __esm({
1848
1995
 
1849
1996
  // dist/adapter/resources/webgl-buffer.js
1850
1997
  function getWebGLTarget(usage) {
1851
- if (usage & import_core8.Buffer.INDEX) {
1998
+ if (usage & import_core9.Buffer.INDEX) {
1852
1999
  return 34963;
1853
2000
  }
1854
- if (usage & import_core8.Buffer.VERTEX) {
2001
+ if (usage & import_core9.Buffer.VERTEX) {
1855
2002
  return 34962;
1856
2003
  }
1857
- if (usage & import_core8.Buffer.UNIFORM) {
2004
+ if (usage & import_core9.Buffer.UNIFORM) {
1858
2005
  return 35345;
1859
2006
  }
1860
2007
  return 34962;
1861
2008
  }
1862
2009
  function getWebGLUsage(usage) {
1863
- if (usage & import_core8.Buffer.INDEX) {
2010
+ if (usage & import_core9.Buffer.INDEX) {
1864
2011
  return 35044;
1865
2012
  }
1866
- if (usage & import_core8.Buffer.VERTEX) {
2013
+ if (usage & import_core9.Buffer.VERTEX) {
1867
2014
  return 35044;
1868
2015
  }
1869
- if (usage & import_core8.Buffer.UNIFORM) {
2016
+ if (usage & import_core9.Buffer.UNIFORM) {
1870
2017
  return 35048;
1871
2018
  }
1872
2019
  return 35044;
1873
2020
  }
1874
- var import_core8, import_constants9, WEBGLBuffer;
2021
+ var import_core9, import_constants9, WEBGLBuffer;
1875
2022
  var init_webgl_buffer = __esm({
1876
2023
  "dist/adapter/resources/webgl-buffer.js"() {
1877
2024
  "use strict";
1878
- import_core8 = require("@luma.gl/core");
2025
+ import_core9 = require("@luma.gl/core");
1879
2026
  import_constants9 = require("@luma.gl/constants");
1880
- WEBGLBuffer = class extends import_core8.Buffer {
2027
+ WEBGLBuffer = class extends import_core9.Buffer {
1881
2028
  device;
1882
2029
  gl;
1883
2030
  handle;
@@ -1912,8 +2059,12 @@ var init_webgl_buffer = __esm({
1912
2059
  destroy() {
1913
2060
  if (!this.destroyed && this.handle) {
1914
2061
  this.removeStats();
1915
- this.trackDeallocatedMemory();
1916
- this.gl.deleteBuffer(this.handle);
2062
+ if (!this.props.handle) {
2063
+ this.trackDeallocatedMemory();
2064
+ this.gl.deleteBuffer(this.handle);
2065
+ } else {
2066
+ this.trackDeallocatedReferencedMemory("Buffer");
2067
+ }
1917
2068
  this.destroyed = true;
1918
2069
  this.handle = null;
1919
2070
  }
@@ -1928,7 +2079,11 @@ var init_webgl_buffer = __esm({
1928
2079
  this.bytesUsed = byteLength;
1929
2080
  this.byteLength = byteLength;
1930
2081
  this._setDebugData(data, byteOffset, byteLength);
1931
- this.trackAllocatedMemory(byteLength);
2082
+ if (!this.props.handle) {
2083
+ this.trackAllocatedMemory(byteLength);
2084
+ } else {
2085
+ this.trackReferencedMemory(byteLength, "Buffer");
2086
+ }
1932
2087
  }
1933
2088
  // Allocate a GPU buffer of specified size.
1934
2089
  _initWithByteLength(byteLength) {
@@ -1943,7 +2098,11 @@ var init_webgl_buffer = __esm({
1943
2098
  this.bytesUsed = byteLength;
1944
2099
  this.byteLength = byteLength;
1945
2100
  this._setDebugData(null, 0, byteLength);
1946
- this.trackAllocatedMemory(byteLength);
2101
+ if (!this.props.handle) {
2102
+ this.trackAllocatedMemory(byteLength);
2103
+ } else {
2104
+ this.trackReferencedMemory(byteLength, "Buffer");
2105
+ }
1947
2106
  return this;
1948
2107
  }
1949
2108
  write(data, byteOffset = 0) {
@@ -1988,15 +2147,27 @@ var init_webgl_buffer = __esm({
1988
2147
 
1989
2148
  // dist/adapter/helpers/parse-shader-compiler-log.js
1990
2149
  function parseShaderCompilerLog(errLog) {
2150
+ var _a;
1991
2151
  const lines = errLog.split(/\r?\n/);
1992
2152
  const messages = [];
1993
2153
  for (const line of lines) {
1994
2154
  if (line.length <= 1) {
1995
2155
  continue;
1996
2156
  }
2157
+ const lineWithTrimmedWhitespace = line.trim();
1997
2158
  const segments = line.split(":");
2159
+ const trimmedMessageType = (_a = segments[0]) == null ? void 0 : _a.trim();
1998
2160
  if (segments.length === 2) {
1999
2161
  const [messageType2, message2] = segments;
2162
+ if (!messageType2 || !message2) {
2163
+ messages.push({
2164
+ message: lineWithTrimmedWhitespace,
2165
+ type: getMessageType(trimmedMessageType || "info"),
2166
+ lineNum: 0,
2167
+ linePos: 0
2168
+ });
2169
+ continue;
2170
+ }
2000
2171
  messages.push({
2001
2172
  message: message2.trim(),
2002
2173
  type: getMessageType(messageType2),
@@ -2006,6 +2177,15 @@ function parseShaderCompilerLog(errLog) {
2006
2177
  continue;
2007
2178
  }
2008
2179
  const [messageType, linePosition, lineNumber, ...rest] = segments;
2180
+ if (!messageType || !linePosition || !lineNumber) {
2181
+ messages.push({
2182
+ message: segments.slice(1).join(":").trim() || lineWithTrimmedWhitespace,
2183
+ type: getMessageType(trimmedMessageType || "info"),
2184
+ lineNum: 0,
2185
+ linePos: 0
2186
+ });
2187
+ continue;
2188
+ }
2009
2189
  let lineNum = parseInt(lineNumber, 10);
2010
2190
  if (isNaN(lineNum)) {
2011
2191
  lineNum = 0;
@@ -2036,14 +2216,14 @@ var init_parse_shader_compiler_log = __esm({
2036
2216
  });
2037
2217
 
2038
2218
  // dist/adapter/resources/webgl-shader.js
2039
- var import_core9, import_constants10, WEBGLShader;
2219
+ var import_core10, import_constants10, WEBGLShader;
2040
2220
  var init_webgl_shader = __esm({
2041
2221
  "dist/adapter/resources/webgl-shader.js"() {
2042
2222
  "use strict";
2043
- import_core9 = require("@luma.gl/core");
2223
+ import_core10 = require("@luma.gl/core");
2044
2224
  import_constants10 = require("@luma.gl/constants");
2045
2225
  init_parse_shader_compiler_log();
2046
- WEBGLShader = class extends import_core9.Shader {
2226
+ WEBGLShader = class extends import_core10.Shader {
2047
2227
  device;
2048
2228
  handle;
2049
2229
  constructor(device, props) {
@@ -2109,9 +2289,9 @@ ${source}`;
2109
2289
  }
2110
2290
  return;
2111
2291
  }
2112
- import_core9.log.once(1, "Shader compilation is asynchronous")();
2292
+ import_core10.log.once(1, "Shader compilation is asynchronous")();
2113
2293
  await this._waitForCompilationComplete();
2114
- import_core9.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2294
+ import_core10.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2115
2295
  this._getCompilationStatus();
2116
2296
  this.debugShader();
2117
2297
  }
@@ -2272,7 +2452,7 @@ function setDeviceParameters(device, parameters) {
2272
2452
  gl.stencilMaskSeparate(1029, mask);
2273
2453
  }
2274
2454
  if (parameters.stencilReadMask) {
2275
- import_core10.log.warn("stencilReadMask not supported under WebGL");
2455
+ import_core11.log.warn("stencilReadMask not supported under WebGL");
2276
2456
  }
2277
2457
  if (parameters.stencilCompare) {
2278
2458
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2385,11 +2565,11 @@ function isObjectEmpty2(obj) {
2385
2565
  }
2386
2566
  return isEmpty;
2387
2567
  }
2388
- var import_core10, import_constants11;
2568
+ var import_core11, import_constants11;
2389
2569
  var init_device_parameters = __esm({
2390
2570
  "dist/adapter/converters/device-parameters.js"() {
2391
2571
  "use strict";
2392
- import_core10 = require("@luma.gl/core");
2572
+ import_core11 = require("@luma.gl/core");
2393
2573
  import_constants11 = require("@luma.gl/constants");
2394
2574
  init_unified_parameter_api();
2395
2575
  }
@@ -2482,14 +2662,14 @@ var init_sampler_parameters = __esm({
2482
2662
  });
2483
2663
 
2484
2664
  // dist/adapter/resources/webgl-sampler.js
2485
- var import_core11, import_constants13, WEBGLSampler;
2665
+ var import_core12, import_constants13, WEBGLSampler;
2486
2666
  var init_webgl_sampler = __esm({
2487
2667
  "dist/adapter/resources/webgl-sampler.js"() {
2488
2668
  "use strict";
2489
- import_core11 = require("@luma.gl/core");
2669
+ import_core12 = require("@luma.gl/core");
2490
2670
  import_constants13 = require("@luma.gl/constants");
2491
2671
  init_sampler_parameters();
2492
- WEBGLSampler = class extends import_core11.Sampler {
2672
+ WEBGLSampler = class extends import_core12.Sampler {
2493
2673
  device;
2494
2674
  handle;
2495
2675
  parameters;
@@ -2565,19 +2745,19 @@ var init_with_parameters = __esm({
2565
2745
  });
2566
2746
 
2567
2747
  // dist/adapter/resources/webgl-texture-view.js
2568
- var import_core12, WEBGLTextureView;
2748
+ var import_core13, WEBGLTextureView;
2569
2749
  var init_webgl_texture_view = __esm({
2570
2750
  "dist/adapter/resources/webgl-texture-view.js"() {
2571
2751
  "use strict";
2572
- import_core12 = require("@luma.gl/core");
2573
- WEBGLTextureView = class extends import_core12.TextureView {
2752
+ import_core13 = require("@luma.gl/core");
2753
+ WEBGLTextureView = class extends import_core13.TextureView {
2574
2754
  device;
2575
2755
  gl;
2576
2756
  handle;
2577
2757
  // Does not have a WebGL representation
2578
2758
  texture;
2579
2759
  constructor(device, props) {
2580
- super(device, { ...import_core12.Texture.defaultProps, ...props });
2760
+ super(device, { ...import_core13.Texture.defaultProps, ...props });
2581
2761
  this.device = device;
2582
2762
  this.gl = this.device.gl;
2583
2763
  this.handle = null;
@@ -2587,98 +2767,15 @@ var init_webgl_texture_view = __esm({
2587
2767
  }
2588
2768
  });
2589
2769
 
2590
- // dist/adapter/converters/webgl-shadertypes.js
2591
- function convertDataTypeToGLDataType(normalizedType) {
2592
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
2593
- }
2594
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
2595
- return WEBGL_SHADER_TYPES[glUniformType];
2596
- }
2597
- function isGLSamplerType(type) {
2598
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
2599
- }
2600
- function getTextureBindingFromGLSamplerType(glSamplerType) {
2601
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
2602
- }
2603
- var import_constants14, WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
2604
- var init_webgl_shadertypes = __esm({
2605
- "dist/adapter/converters/webgl-shadertypes.js"() {
2606
- "use strict";
2607
- import_constants14 = require("@luma.gl/constants");
2608
- WEBGL_SHADER_TYPES = {
2609
- [5126]: "f32",
2610
- [35664]: "vec2<f32>",
2611
- [35665]: "vec3<f32>",
2612
- [35666]: "vec4<f32>",
2613
- [5124]: "i32",
2614
- [35667]: "vec2<i32>",
2615
- [35668]: "vec3<i32>",
2616
- [35669]: "vec4<i32>",
2617
- [5125]: "u32",
2618
- [36294]: "vec2<u32>",
2619
- [36295]: "vec3<u32>",
2620
- [36296]: "vec4<u32>",
2621
- [35670]: "f32",
2622
- [35671]: "vec2<f32>",
2623
- [35672]: "vec3<f32>",
2624
- [35673]: "vec4<f32>",
2625
- // TODO - are sizes/components below correct?
2626
- [35674]: "mat2x2<f32>",
2627
- [35685]: "mat2x3<f32>",
2628
- [35686]: "mat2x4<f32>",
2629
- [35687]: "mat3x2<f32>",
2630
- [35675]: "mat3x3<f32>",
2631
- [35688]: "mat3x4<f32>",
2632
- [35689]: "mat4x2<f32>",
2633
- [35690]: "mat4x3<f32>",
2634
- [35676]: "mat4x4<f32>"
2635
- };
2636
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
2637
- [35678]: { viewDimension: "2d", sampleType: "float" },
2638
- [35680]: { viewDimension: "cube", sampleType: "float" },
2639
- [35679]: { viewDimension: "3d", sampleType: "float" },
2640
- [35682]: { viewDimension: "3d", sampleType: "depth" },
2641
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
2642
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
2643
- [36293]: { viewDimension: "cube", sampleType: "float" },
2644
- [36298]: { viewDimension: "2d", sampleType: "sint" },
2645
- [36299]: { viewDimension: "3d", sampleType: "sint" },
2646
- [36300]: { viewDimension: "cube", sampleType: "sint" },
2647
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
2648
- [36306]: { viewDimension: "2d", sampleType: "uint" },
2649
- [36307]: { viewDimension: "3d", sampleType: "uint" },
2650
- [36308]: { viewDimension: "cube", sampleType: "uint" },
2651
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
2652
- };
2653
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
2654
- uint8: 5121,
2655
- sint8: 5120,
2656
- unorm8: 5121,
2657
- snorm8: 5120,
2658
- uint16: 5123,
2659
- sint16: 5122,
2660
- unorm16: 5123,
2661
- snorm16: 5122,
2662
- uint32: 5125,
2663
- sint32: 5124,
2664
- // WebGPU does not support normalized 32 bit integer attributes
2665
- // 'unorm32': GL.UNSIGNED_INT,
2666
- // 'snorm32': GL.INT,
2667
- float16: 5131,
2668
- float32: 5126
2669
- };
2670
- }
2671
- });
2672
-
2673
2770
  // dist/adapter/converters/shader-formats.js
2674
2771
  function convertGLDataTypeToDataType(type) {
2675
2772
  return GL_DATA_TYPE_MAP[type];
2676
2773
  }
2677
- var import_constants15, GL_DATA_TYPE_MAP;
2774
+ var import_constants14, GL_DATA_TYPE_MAP;
2678
2775
  var init_shader_formats = __esm({
2679
2776
  "dist/adapter/converters/shader-formats.js"() {
2680
2777
  "use strict";
2681
- import_constants15 = require("@luma.gl/constants");
2778
+ import_constants14 = require("@luma.gl/constants");
2682
2779
  GL_DATA_TYPE_MAP = {
2683
2780
  [5124]: "sint32",
2684
2781
  [5125]: "uint32",
@@ -2701,6 +2798,18 @@ var init_shader_formats = __esm({
2701
2798
  });
2702
2799
 
2703
2800
  // dist/adapter/resources/webgl-texture.js
2801
+ function getArrayBufferView(typedArray, byteOffset = 0) {
2802
+ if (!byteOffset) {
2803
+ return typedArray;
2804
+ }
2805
+ return new typedArray.constructor(typedArray.buffer, typedArray.byteOffset + byteOffset, (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT);
2806
+ }
2807
+ function getWebGLTextureSourceElementOffset(typedArray, byteOffset) {
2808
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
2809
+ throw new Error(`Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`);
2810
+ }
2811
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
2812
+ }
2704
2813
  function getWebGLTextureTarget(dimension) {
2705
2814
  switch (dimension) {
2706
2815
  case "1d":
@@ -2721,20 +2830,19 @@ function getWebGLTextureTarget(dimension) {
2721
2830
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
2722
2831
  return dimension === "cube" ? 34069 + level : glTarget;
2723
2832
  }
2724
- var import_core13, import_constants16, import_core14, WEBGLTexture;
2833
+ var import_core14, import_constants15, import_core15, WEBGLTexture;
2725
2834
  var init_webgl_texture = __esm({
2726
2835
  "dist/adapter/resources/webgl-texture.js"() {
2727
2836
  "use strict";
2728
- import_core13 = require("@luma.gl/core");
2729
- import_constants16 = require("@luma.gl/constants");
2837
+ import_core14 = require("@luma.gl/core");
2838
+ import_constants15 = require("@luma.gl/constants");
2730
2839
  init_webgl_texture_table();
2731
2840
  init_sampler_parameters();
2732
2841
  init_with_parameters();
2733
2842
  init_webgl_texture_view();
2734
- init_webgl_shadertypes();
2735
2843
  init_shader_formats();
2736
- import_core14 = require("@luma.gl/core");
2737
- WEBGLTexture = class extends import_core13.Texture {
2844
+ import_core15 = require("@luma.gl/core");
2845
+ WEBGLTexture = class extends import_core14.Texture {
2738
2846
  // readonly MAX_ATTRIBUTES: number;
2739
2847
  device;
2740
2848
  gl;
@@ -2763,8 +2871,10 @@ var init_webgl_texture = __esm({
2763
2871
  // state
2764
2872
  /** Texture binding slot - TODO - move to texture view? */
2765
2873
  _textureUnit = 0;
2766
- /** Chached framebuffer */
2874
+ /** Cached framebuffer reused for color texture readback. */
2767
2875
  _framebuffer = null;
2876
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
2877
+ _framebufferAttachmentKey = null;
2768
2878
  constructor(device, props) {
2769
2879
  super(device, props, { byteAlignment: 1 });
2770
2880
  this.device = device;
@@ -2779,20 +2889,27 @@ var init_webgl_texture = __esm({
2779
2889
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
2780
2890
  this.gl.bindTexture(this.glTarget, this.handle);
2781
2891
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
2782
- switch (dimension) {
2783
- case "2d":
2784
- case "cube":
2785
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
2786
- break;
2787
- case "2d-array":
2788
- case "3d":
2789
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
2790
- break;
2791
- default:
2792
- throw new Error(dimension);
2892
+ if (!this.compressed) {
2893
+ switch (dimension) {
2894
+ case "2d":
2895
+ case "cube":
2896
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
2897
+ break;
2898
+ case "2d-array":
2899
+ case "3d":
2900
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
2901
+ break;
2902
+ default:
2903
+ throw new Error(dimension);
2904
+ }
2793
2905
  }
2794
2906
  this.gl.bindTexture(this.glTarget, null);
2795
2907
  this._initializeData(props.data);
2908
+ if (!this.props.handle) {
2909
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
2910
+ } else {
2911
+ this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
2912
+ }
2796
2913
  this.setSampler(this.props.sampler);
2797
2914
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
2798
2915
  Object.seal(this);
@@ -2802,9 +2919,14 @@ var init_webgl_texture = __esm({
2802
2919
  if (this.handle) {
2803
2920
  (_a = this._framebuffer) == null ? void 0 : _a.destroy();
2804
2921
  this._framebuffer = null;
2805
- this.gl.deleteTexture(this.handle);
2922
+ this._framebufferAttachmentKey = null;
2806
2923
  this.removeStats();
2807
- this.trackDeallocatedMemory("Texture");
2924
+ if (!this.props.handle) {
2925
+ this.gl.deleteTexture(this.handle);
2926
+ this.trackDeallocatedMemory("Texture");
2927
+ } else {
2928
+ this.trackDeallocatedReferencedMemory("Texture");
2929
+ }
2808
2930
  this.destroyed = true;
2809
2931
  }
2810
2932
  }
@@ -2843,97 +2965,128 @@ var init_webgl_texture = __esm({
2843
2965
  return { width: options.width, height: options.height };
2844
2966
  }
2845
2967
  copyImageData(options_) {
2846
- const options = this._normalizeCopyImageDataOptions(options_);
2847
- const typedArray = options.data;
2848
- const { width, height, depth, z = 0 } = options;
2849
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0 } = options;
2968
+ super.copyImageData(options_);
2969
+ }
2970
+ /**
2971
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
2972
+ *
2973
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
2974
+ * before any WebGL calls are issued.
2975
+ */
2976
+ readBuffer(options = {}, buffer) {
2977
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
2978
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
2979
+ const readBuffer = buffer || this.device.createBuffer({
2980
+ byteLength: memoryLayout.byteLength,
2981
+ usage: import_core14.Buffer.COPY_DST | import_core14.Buffer.MAP_READ
2982
+ });
2983
+ if (readBuffer.byteLength < memoryLayout.byteLength) {
2984
+ throw new Error(`${this} readBuffer target is too small (${readBuffer.byteLength} < ${memoryLayout.byteLength})`);
2985
+ }
2986
+ const webglBuffer = readBuffer;
2987
+ this.gl.bindBuffer(35051, webglBuffer.handle);
2988
+ try {
2989
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, (destinationByteOffset) => {
2990
+ this.gl.readPixels(normalizedOptions.x, normalizedOptions.y, normalizedOptions.width, normalizedOptions.height, this.glFormat, this.glType, destinationByteOffset);
2991
+ });
2992
+ } finally {
2993
+ this.gl.bindBuffer(35051, null);
2994
+ }
2995
+ return readBuffer;
2996
+ }
2997
+ async readDataAsync(options = {}) {
2998
+ const buffer = this.readBuffer(options);
2999
+ const data = await buffer.readAsync();
3000
+ buffer.destroy();
3001
+ return data.buffer;
3002
+ }
3003
+ writeBuffer(buffer, options_ = {}) {
3004
+ const options = this._normalizeTextureWriteOptions(options_);
3005
+ const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
2850
3006
  const { glFormat, glType, compressed } = this;
2851
3007
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
2852
- let unpackRowLength;
2853
- if (!this.compressed) {
2854
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
2855
- if (bytesPerPixel) {
2856
- if (options.bytesPerRow % bytesPerPixel !== 0) {
2857
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
2858
- }
2859
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
2860
- }
3008
+ if (compressed) {
3009
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
2861
3010
  }
2862
- const glParameters = !this.compressed ? {
3011
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3012
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3013
+ const glParameters = {
2863
3014
  [3317]: this.byteAlignment,
2864
3015
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
2865
3016
  [32878]: options.rowsPerImage
2866
- } : {};
3017
+ };
2867
3018
  this.gl.bindTexture(this.glTarget, this.handle);
3019
+ this.gl.bindBuffer(35052, buffer.handle);
2868
3020
  withGLParameters(this.gl, glParameters, () => {
2869
3021
  switch (this.dimension) {
2870
3022
  case "2d":
2871
3023
  case "cube":
2872
- if (compressed) {
2873
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
2874
- } else {
2875
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
2876
- }
3024
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
2877
3025
  break;
2878
3026
  case "2d-array":
2879
3027
  case "3d":
2880
- if (compressed) {
2881
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
2882
- } else {
2883
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
2884
- }
3028
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
2885
3029
  break;
2886
3030
  default:
2887
3031
  }
2888
3032
  });
3033
+ this.gl.bindBuffer(35052, null);
2889
3034
  this.gl.bindTexture(this.glTarget, null);
2890
3035
  }
2891
- readBuffer(options = {}, buffer) {
2892
- throw new Error("readBuffer not implemented");
2893
- }
2894
- async readDataAsync(options = {}) {
2895
- return this.readDataSyncWebGL(options);
2896
- }
2897
- writeBuffer(buffer, options_ = {}) {
2898
- }
2899
3036
  writeData(data, options_ = {}) {
2900
3037
  const options = this._normalizeTextureWriteOptions(options_);
2901
3038
  const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
2902
- const {} = this;
2903
- const { width, height, mipLevel, x, y, z } = options;
3039
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
2904
3040
  const { glFormat, glType, compressed } = this;
2905
- const depth = 0;
2906
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3041
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3042
+ let unpackRowLength;
3043
+ if (!compressed) {
3044
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3045
+ if (bytesPerPixel) {
3046
+ unpackRowLength = options.bytesPerRow / bytesPerPixel;
3047
+ }
3048
+ }
2907
3049
  const glParameters = !this.compressed ? {
2908
- // WebGL does not require byte alignment, but allows it to be specified
2909
- [3317]: this.byteAlignment
2910
- // [GL.UNPACK_ROW_LENGTH]: bytesPerRow,
2911
- // [GL.UNPACK_IMAGE_HEIGHT]: rowsPerImage
3050
+ [3317]: this.byteAlignment,
3051
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3052
+ [32878]: options.rowsPerImage
2912
3053
  } : {};
2913
- this.gl.bindTexture(glTarget, this.handle);
3054
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
3055
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
3056
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
3057
+ const isFullMipUpload = x === 0 && y === 0 && z === 0 && width === mipLevelSize.width && height === mipLevelSize.height && depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
3058
+ this.gl.bindTexture(this.glTarget, this.handle);
2914
3059
  this.gl.bindBuffer(35052, null);
2915
3060
  withGLParameters(this.gl, glParameters, () => {
2916
3061
  switch (this.dimension) {
2917
3062
  case "2d":
2918
3063
  case "cube":
2919
3064
  if (compressed) {
2920
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray);
3065
+ if (isFullMipUpload) {
3066
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
3067
+ } else {
3068
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
3069
+ }
2921
3070
  } else {
2922
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray);
3071
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
2923
3072
  }
2924
3073
  break;
2925
3074
  case "2d-array":
2926
3075
  case "3d":
2927
3076
  if (compressed) {
2928
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray);
3077
+ if (isFullMipUpload) {
3078
+ this.gl.compressedTexImage3D(glTarget, mipLevel, glFormat, width, height, depthOrArrayLayers, 0, compressedData);
3079
+ } else {
3080
+ this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, compressedData);
3081
+ }
2929
3082
  } else {
2930
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray);
3083
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
2931
3084
  }
2932
3085
  break;
2933
3086
  default:
2934
3087
  }
2935
3088
  });
2936
- this.gl.bindTexture(glTarget, null);
3089
+ this.gl.bindTexture(this.glTarget, null);
2937
3090
  }
2938
3091
  // IMPLEMENTATION SPECIFIC
2939
3092
  /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
@@ -2955,28 +3108,83 @@ var init_webgl_texture = __esm({
2955
3108
  }
2956
3109
  // WEBGL SPECIFIC
2957
3110
  readDataSyncWebGL(options_ = {}) {
2958
- const options = this._normalizeTextureReadOptions(options_);
3111
+ const options = this._getSupportedColorReadOptions(options_);
2959
3112
  const memoryLayout = this.computeMemoryLayout(options);
2960
3113
  const shaderType = convertGLDataTypeToDataType(this.glType);
2961
- const ArrayType = (0, import_core14.getTypedArrayConstructor)(shaderType);
2962
- const targetArray = new ArrayType(memoryLayout.byteLength);
2963
- const signedType = (0, import_core14.getDataType)(targetArray);
2964
- const sourceType = convertDataTypeToGLDataType(signedType);
2965
- const framebuffer = this._getFramebuffer();
2966
- const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
2967
- this.gl.readBuffer(36064);
2968
- this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, sourceType, targetArray);
2969
- this.gl.bindFramebuffer(36160, prevHandle || null);
3114
+ const ArrayType = (0, import_core15.getTypedArrayConstructor)(shaderType);
3115
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT);
3116
+ this._readColorTextureLayers(options, memoryLayout, (destinationByteOffset) => {
3117
+ const layerView = new ArrayType(targetArray.buffer, targetArray.byteOffset + destinationByteOffset, memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT);
3118
+ this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, this.glType, layerView);
3119
+ });
2970
3120
  return targetArray.buffer;
2971
3121
  }
2972
3122
  /**
2973
- * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3123
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
3124
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
2974
3125
  */
2975
- generateMipmapsWebGL(options) {
2976
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
2977
- if (!isFilterableAndRenderable) {
2978
- import_core13.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
2979
- if (!(options == null ? void 0 : options.force)) {
3126
+ _readColorTextureLayers(options, memoryLayout, readLayer) {
3127
+ const framebuffer = this._getFramebuffer();
3128
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
3129
+ const glParameters = {
3130
+ [3333]: this.byteAlignment,
3131
+ ...packRowLength !== options.width ? { [3330]: packRowLength } : {}
3132
+ };
3133
+ const prevReadBuffer = this.gl.getParameter(3074);
3134
+ const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3135
+ try {
3136
+ this.gl.readBuffer(36064);
3137
+ withGLParameters(this.gl, glParameters, () => {
3138
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
3139
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
3140
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
3141
+ }
3142
+ });
3143
+ } finally {
3144
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3145
+ this.gl.readBuffer(prevReadBuffer);
3146
+ }
3147
+ }
3148
+ /**
3149
+ * Attaches a single color subresource to the cached read framebuffer.
3150
+ *
3151
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3152
+ */
3153
+ _attachReadSubresource(framebuffer, mipLevel, layer) {
3154
+ const attachmentKey = `${mipLevel}:${layer}`;
3155
+ if (this._framebufferAttachmentKey === attachmentKey) {
3156
+ return;
3157
+ }
3158
+ switch (this.dimension) {
3159
+ case "2d":
3160
+ this.gl.framebufferTexture2D(36160, 36064, 3553, this.handle, mipLevel);
3161
+ break;
3162
+ case "cube":
3163
+ this.gl.framebufferTexture2D(36160, 36064, getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer), this.handle, mipLevel);
3164
+ break;
3165
+ case "2d-array":
3166
+ case "3d":
3167
+ this.gl.framebufferTextureLayer(36160, 36064, this.handle, mipLevel, layer);
3168
+ break;
3169
+ default:
3170
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
3171
+ }
3172
+ if (this.device.props.debug) {
3173
+ const status = Number(this.gl.checkFramebufferStatus(36160));
3174
+ if (status !== Number(36053)) {
3175
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
3176
+ }
3177
+ }
3178
+ this._framebufferAttachmentKey = attachmentKey;
3179
+ }
3180
+ /**
3181
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3182
+ */
3183
+ generateMipmapsWebGL(options) {
3184
+ const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3185
+ if (!isFilterableAndRenderable) {
3186
+ import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3187
+ if (!(options == null ? void 0 : options.force)) {
2980
3188
  return;
2981
3189
  }
2982
3190
  }
@@ -2984,7 +3192,7 @@ var init_webgl_texture = __esm({
2984
3192
  this.gl.bindTexture(this.glTarget, this.handle);
2985
3193
  this.gl.generateMipmap(this.glTarget);
2986
3194
  } catch (error) {
2987
- import_core13.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3195
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
2988
3196
  } finally {
2989
3197
  this.gl.bindTexture(this.glTarget, null);
2990
3198
  }
@@ -2994,7 +3202,7 @@ var init_webgl_texture = __esm({
2994
3202
  * Sets sampler parameters on texture
2995
3203
  */
2996
3204
  _setSamplerParameters(parameters) {
2997
- import_core13.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3205
+ import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
2998
3206
  this.gl.bindTexture(this.glTarget, this.handle);
2999
3207
  for (const [pname, pvalue] of Object.entries(parameters)) {
3000
3208
  const param = Number(pname);
@@ -3051,208 +3259,6 @@ var init_webgl_texture = __esm({
3051
3259
  }
3052
3260
  });
3053
3261
 
3054
- // dist/adapter/helpers/get-shader-layout-from-glsl.js
3055
- function getShaderLayoutFromGLSL(gl, program) {
3056
- const shaderLayout = {
3057
- attributes: [],
3058
- bindings: []
3059
- };
3060
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3061
- const uniformBlocks = readUniformBlocks(gl, program);
3062
- for (const uniformBlock of uniformBlocks) {
3063
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3064
- name: uniform.name,
3065
- format: uniform.format,
3066
- byteOffset: uniform.byteOffset,
3067
- byteStride: uniform.byteStride,
3068
- arrayLength: uniform.arrayLength
3069
- }));
3070
- shaderLayout.bindings.push({
3071
- type: "uniform",
3072
- name: uniformBlock.name,
3073
- group: 0,
3074
- location: uniformBlock.location,
3075
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3076
- minBindingSize: uniformBlock.byteLength,
3077
- uniforms: uniforms2
3078
- });
3079
- }
3080
- const uniforms = readUniformBindings(gl, program);
3081
- let textureUnit = 0;
3082
- for (const uniform of uniforms) {
3083
- if (isGLSamplerType(uniform.type)) {
3084
- const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3085
- shaderLayout.bindings.push({
3086
- type: "texture",
3087
- name: uniform.name,
3088
- group: 0,
3089
- location: textureUnit,
3090
- viewDimension,
3091
- sampleType
3092
- });
3093
- uniform.textureUnit = textureUnit;
3094
- textureUnit += 1;
3095
- }
3096
- }
3097
- if (uniforms.length) {
3098
- shaderLayout.uniforms = uniforms;
3099
- }
3100
- const varyings = readVaryings(gl, program);
3101
- if (varyings == null ? void 0 : varyings.length) {
3102
- shaderLayout.varyings = varyings;
3103
- }
3104
- return shaderLayout;
3105
- }
3106
- function readAttributeDeclarations(gl, program) {
3107
- const attributes = [];
3108
- const count = gl.getProgramParameter(program, 35721);
3109
- for (let index = 0; index < count; index++) {
3110
- const activeInfo = gl.getActiveAttrib(program, index);
3111
- if (!activeInfo) {
3112
- throw new Error("activeInfo");
3113
- }
3114
- const {
3115
- name,
3116
- type: compositeType
3117
- /* , size*/
3118
- } = activeInfo;
3119
- const location = gl.getAttribLocation(program, name);
3120
- if (location >= 0) {
3121
- const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
3122
- const stepMode = /instance/i.test(name) ? "instance" : "vertex";
3123
- attributes.push({
3124
- name,
3125
- location,
3126
- stepMode,
3127
- type: attributeType
3128
- // size - for arrays, size is the number of elements in the array
3129
- });
3130
- }
3131
- }
3132
- attributes.sort((a, b) => a.location - b.location);
3133
- return attributes;
3134
- }
3135
- function readVaryings(gl, program) {
3136
- const varyings = [];
3137
- const count = gl.getProgramParameter(program, 35971);
3138
- for (let location = 0; location < count; location++) {
3139
- const activeInfo = gl.getTransformFeedbackVarying(program, location);
3140
- if (!activeInfo) {
3141
- throw new Error("activeInfo");
3142
- }
3143
- const { name, type: glUniformType, size } = activeInfo;
3144
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3145
- const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
3146
- varyings.push({ location, name, type, size: size * components });
3147
- }
3148
- varyings.sort((a, b) => a.location - b.location);
3149
- return varyings;
3150
- }
3151
- function readUniformBindings(gl, program) {
3152
- const uniforms = [];
3153
- const uniformCount = gl.getProgramParameter(program, 35718);
3154
- for (let i = 0; i < uniformCount; i++) {
3155
- const activeInfo = gl.getActiveUniform(program, i);
3156
- if (!activeInfo) {
3157
- throw new Error("activeInfo");
3158
- }
3159
- const { name: rawName, size, type } = activeInfo;
3160
- const { name, isArray: isArray3 } = parseUniformName(rawName);
3161
- let webglLocation = gl.getUniformLocation(program, name);
3162
- const uniformInfo = {
3163
- // WebGL locations are uniquely typed but just numbers
3164
- location: webglLocation,
3165
- name,
3166
- size,
3167
- type,
3168
- isArray: isArray3
3169
- };
3170
- uniforms.push(uniformInfo);
3171
- if (uniformInfo.size > 1) {
3172
- for (let j = 0; j < uniformInfo.size; j++) {
3173
- const elementName = `${name}[${j}]`;
3174
- webglLocation = gl.getUniformLocation(program, elementName);
3175
- const arrayElementUniformInfo = {
3176
- ...uniformInfo,
3177
- name: elementName,
3178
- location: webglLocation
3179
- };
3180
- uniforms.push(arrayElementUniformInfo);
3181
- }
3182
- }
3183
- }
3184
- return uniforms;
3185
- }
3186
- function readUniformBlocks(gl, program) {
3187
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3188
- const uniformBlocks = [];
3189
- const blockCount = gl.getProgramParameter(program, 35382);
3190
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3191
- const blockInfo = {
3192
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3193
- location: getBlockParameter(blockIndex, 35391),
3194
- byteLength: getBlockParameter(blockIndex, 35392),
3195
- vertex: getBlockParameter(blockIndex, 35396),
3196
- fragment: getBlockParameter(blockIndex, 35398),
3197
- uniformCount: getBlockParameter(blockIndex, 35394),
3198
- uniforms: []
3199
- };
3200
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3201
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3202
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3203
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3204
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3205
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3206
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3207
- if (!activeInfo) {
3208
- throw new Error("activeInfo");
3209
- }
3210
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3211
- blockInfo.uniforms.push({
3212
- name: activeInfo.name,
3213
- format,
3214
- type: uniformType[i],
3215
- arrayLength: uniformArrayLength[i],
3216
- byteOffset: uniformOffset[i],
3217
- byteStride: uniformStride[i]
3218
- // matrixStride: uniformStride[i],
3219
- // rowMajor: uniformRowMajor[i]
3220
- });
3221
- }
3222
- uniformBlocks.push(blockInfo);
3223
- }
3224
- uniformBlocks.sort((a, b) => a.location - b.location);
3225
- return uniformBlocks;
3226
- }
3227
- function parseUniformName(name) {
3228
- if (name[name.length - 1] !== "]") {
3229
- return {
3230
- name,
3231
- length: 1,
3232
- isArray: false
3233
- };
3234
- }
3235
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3236
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3237
- if (!matches || matches.length < 2) {
3238
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3239
- }
3240
- return {
3241
- name: matches[1],
3242
- length: matches[2] ? 1 : 0,
3243
- isArray: Boolean(matches[2])
3244
- };
3245
- }
3246
- var import_core15, import_constants17;
3247
- var init_get_shader_layout_from_glsl = __esm({
3248
- "dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3249
- "use strict";
3250
- import_core15 = require("@luma.gl/core");
3251
- import_constants17 = require("@luma.gl/constants");
3252
- init_webgl_shadertypes();
3253
- }
3254
- });
3255
-
3256
3262
  // dist/adapter/helpers/set-uniform.js
3257
3263
  function setUniform(gl, location, type, value) {
3258
3264
  const gl2 = gl;
@@ -3337,11 +3343,11 @@ function setUniform(gl, location, type, value) {
3337
3343
  }
3338
3344
  throw new Error("Illegal uniform");
3339
3345
  }
3340
- var import_constants18;
3346
+ var import_constants16;
3341
3347
  var init_set_uniform = __esm({
3342
3348
  "dist/adapter/helpers/set-uniform.js"() {
3343
3349
  "use strict";
3344
- import_constants18 = require("@luma.gl/constants");
3350
+ import_constants16 = require("@luma.gl/constants");
3345
3351
  }
3346
3352
  });
3347
3353
 
@@ -3378,11 +3384,11 @@ function getGLPrimitive(topology) {
3378
3384
  throw new Error(topology);
3379
3385
  }
3380
3386
  }
3381
- var import_constants19;
3387
+ var import_constants17;
3382
3388
  var init_webgl_topology_utils = __esm({
3383
3389
  "dist/adapter/helpers/webgl-topology-utils.js"() {
3384
3390
  "use strict";
3385
- import_constants19 = require("@luma.gl/constants");
3391
+ import_constants17 = require("@luma.gl/constants");
3386
3392
  }
3387
3393
  });
3388
3394
 
@@ -3403,13 +3409,12 @@ function mergeShaderLayout(baseLayout, overrideLayout) {
3403
3409
  }
3404
3410
  return mergedLayout;
3405
3411
  }
3406
- var import_core16, import_constants20, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3412
+ var import_core16, import_constants18, WEBGLRenderPipeline;
3407
3413
  var init_webgl_render_pipeline = __esm({
3408
3414
  "dist/adapter/resources/webgl-render-pipeline.js"() {
3409
3415
  "use strict";
3410
3416
  import_core16 = require("@luma.gl/core");
3411
- import_constants20 = require("@luma.gl/constants");
3412
- init_get_shader_layout_from_glsl();
3417
+ import_constants18 = require("@luma.gl/constants");
3413
3418
  init_device_parameters();
3414
3419
  init_set_uniform();
3415
3420
  init_webgl_buffer();
@@ -3417,7 +3422,6 @@ var init_webgl_render_pipeline = __esm({
3417
3422
  init_webgl_texture();
3418
3423
  init_webgl_texture_view();
3419
3424
  init_webgl_topology_utils();
3420
- LOG_PROGRAM_PERF_PRIORITY = 4;
3421
3425
  WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3422
3426
  /** The WebGL device that created this render pipeline */
3423
3427
  device;
@@ -3429,10 +3433,10 @@ var init_webgl_render_pipeline = __esm({
3429
3433
  fs;
3430
3434
  /** The layout extracted from shader by WebGL introspection APIs */
3431
3435
  introspectedLayout;
3432
- /** Uniforms set on this model */
3433
- uniforms = {};
3434
- /** Bindings set on this model */
3436
+ /** Compatibility path for direct pipeline.setBindings() usage */
3435
3437
  bindings = {};
3438
+ /** Compatibility path for direct pipeline.uniforms usage */
3439
+ uniforms = {};
3436
3440
  /** WebGL varyings */
3437
3441
  varyings = null;
3438
3442
  _uniformCount = 0;
@@ -3444,33 +3448,28 @@ var init_webgl_render_pipeline = __esm({
3444
3448
  constructor(device, props) {
3445
3449
  super(device, props);
3446
3450
  this.device = device;
3447
- this.handle = this.props.handle || this.device.gl.createProgram();
3451
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
3452
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
3453
+ this.handle = webglSharedRenderPipeline.handle;
3454
+ this.vs = webglSharedRenderPipeline.vs;
3455
+ this.fs = webglSharedRenderPipeline.fs;
3456
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
3457
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
3448
3458
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
3449
- this.vs = props.vs;
3450
- this.fs = props.fs;
3451
- const { varyings, bufferMode = 35981 } = props;
3452
- if (varyings && varyings.length > 0) {
3453
- this.varyings = varyings;
3454
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
3455
- }
3456
- this._linkShaders();
3457
- import_core16.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3458
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3459
- import_core16.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3460
3459
  this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
3461
3460
  }
3462
3461
  destroy() {
3463
- if (this.handle) {
3464
- this.device.gl.useProgram(null);
3465
- this.device.gl.deleteProgram(this.handle);
3466
- this.destroyed = true;
3467
- this.handle.destroyed = true;
3468
- this.handle = null;
3462
+ if (this.destroyed) {
3463
+ return;
3464
+ }
3465
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
3466
+ this.sharedRenderPipeline.destroy();
3469
3467
  }
3468
+ this.destroyResource();
3470
3469
  }
3471
3470
  /**
3472
- * Bindings include: textures, samplers and uniform buffers
3473
- * @todo needed for portable model
3471
+ * Compatibility shim for code paths that still set bindings on the pipeline.
3472
+ * Shared-model draws pass bindings per draw and do not rely on this state.
3474
3473
  */
3475
3474
  setBindings(bindings, options) {
3476
3475
  for (const [name, value] of Object.entries(bindings)) {
@@ -3511,6 +3510,7 @@ var init_webgl_render_pipeline = __esm({
3511
3510
  */
3512
3511
  draw(options) {
3513
3512
  var _a;
3513
+ this._syncLinkStatus();
3514
3514
  const {
3515
3515
  renderPass,
3516
3516
  parameters = this.props.parameters,
@@ -3524,7 +3524,9 @@ var init_webgl_render_pipeline = __esm({
3524
3524
  // firstIndex,
3525
3525
  // firstInstance,
3526
3526
  // baseVertex,
3527
- transformFeedback
3527
+ transformFeedback,
3528
+ bindings = this.bindings,
3529
+ uniforms = this.uniforms
3528
3530
  } = options;
3529
3531
  const glDrawMode = getGLDrawMode(topology);
3530
3532
  const isIndexed = Boolean(vertexArray.indexBuffer);
@@ -3533,7 +3535,7 @@ var init_webgl_render_pipeline = __esm({
3533
3535
  import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
3534
3536
  return false;
3535
3537
  }
3536
- if (!this._areTexturesRenderable()) {
3538
+ if (!this._areTexturesRenderable(bindings)) {
3537
3539
  import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
3538
3540
  return false;
3539
3541
  }
@@ -3542,57 +3544,479 @@ var init_webgl_render_pipeline = __esm({
3542
3544
  if (transformFeedback) {
3543
3545
  transformFeedback.begin(this.props.topology);
3544
3546
  }
3545
- this._applyBindings();
3546
- this._applyUniforms();
3547
- const webglRenderPass = renderPass;
3548
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
3549
- if (isIndexed && isInstanced) {
3550
- this.device.gl.drawElementsInstanced(
3551
- glDrawMode,
3552
- vertexCount || 0,
3553
- // indexCount?
3554
- glIndexType,
3555
- firstVertex,
3556
- instanceCount || 0
3557
- );
3558
- } else if (isIndexed) {
3559
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
3560
- } else if (isInstanced) {
3561
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
3562
- } else {
3563
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
3564
- }
3565
- if (transformFeedback) {
3566
- transformFeedback.end();
3567
- }
3568
- });
3569
- vertexArray.unbindAfterRender(renderPass);
3570
- return true;
3547
+ this._applyBindings(bindings, { disableWarnings: this.props.disableWarnings });
3548
+ this._applyUniforms(uniforms);
3549
+ const webglRenderPass = renderPass;
3550
+ withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
3551
+ if (isIndexed && isInstanced) {
3552
+ this.device.gl.drawElementsInstanced(
3553
+ glDrawMode,
3554
+ vertexCount || 0,
3555
+ // indexCount?
3556
+ glIndexType,
3557
+ firstVertex,
3558
+ instanceCount || 0
3559
+ );
3560
+ } else if (isIndexed) {
3561
+ this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
3562
+ } else if (isInstanced) {
3563
+ this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
3564
+ } else {
3565
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
3566
+ }
3567
+ if (transformFeedback) {
3568
+ transformFeedback.end();
3569
+ }
3570
+ });
3571
+ vertexArray.unbindAfterRender(renderPass);
3572
+ return true;
3573
+ }
3574
+ /**
3575
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
3576
+ * Update a texture if needed (e.g. from video)
3577
+ * Note: This is currently done before every draw call
3578
+ */
3579
+ _areTexturesRenderable(bindings) {
3580
+ let texturesRenderable = true;
3581
+ for (const bindingInfo of this.shaderLayout.bindings) {
3582
+ if (!bindings[bindingInfo.name] && !bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
3583
+ import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
3584
+ texturesRenderable = false;
3585
+ }
3586
+ }
3587
+ return texturesRenderable;
3588
+ }
3589
+ /** Apply any bindings (before each draw call) */
3590
+ _applyBindings(bindings, _options) {
3591
+ this._syncLinkStatus();
3592
+ if (this.linkStatus !== "success") {
3593
+ return;
3594
+ }
3595
+ const { gl } = this.device;
3596
+ gl.useProgram(this.handle);
3597
+ let textureUnit = 0;
3598
+ let uniformBufferIndex = 0;
3599
+ for (const binding of this.shaderLayout.bindings) {
3600
+ const value = bindings[binding.name] || bindings[binding.name.replace(/Uniforms$/, "")];
3601
+ if (!value) {
3602
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
3603
+ }
3604
+ switch (binding.type) {
3605
+ case "uniform":
3606
+ const { name } = binding;
3607
+ const location = gl.getUniformBlockIndex(this.handle, name);
3608
+ if (location === 4294967295) {
3609
+ throw new Error(`Invalid uniform block name ${name}`);
3610
+ }
3611
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
3612
+ if (value instanceof WEBGLBuffer) {
3613
+ gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
3614
+ } else {
3615
+ gl.bindBufferRange(
3616
+ 35345,
3617
+ uniformBufferIndex,
3618
+ // @ts-expect-error
3619
+ value.buffer.handle,
3620
+ // @ts-expect-error
3621
+ value.offset || 0,
3622
+ // @ts-expect-error
3623
+ value.size || value.buffer.byteLength - value.offset
3624
+ );
3625
+ }
3626
+ uniformBufferIndex += 1;
3627
+ break;
3628
+ case "texture":
3629
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3630
+ throw new Error("texture");
3631
+ }
3632
+ let texture;
3633
+ if (value instanceof WEBGLTextureView) {
3634
+ texture = value.texture;
3635
+ } else if (value instanceof WEBGLTexture) {
3636
+ texture = value;
3637
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
3638
+ import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
3639
+ texture = value.colorAttachments[0].texture;
3640
+ } else {
3641
+ throw new Error("No texture");
3642
+ }
3643
+ gl.activeTexture(33984 + textureUnit);
3644
+ gl.bindTexture(texture.glTarget, texture.handle);
3645
+ textureUnit += 1;
3646
+ break;
3647
+ case "sampler":
3648
+ break;
3649
+ case "storage":
3650
+ case "read-only-storage":
3651
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3652
+ }
3653
+ }
3654
+ }
3655
+ /**
3656
+ * Due to program sharing, uniforms need to be reset before every draw call
3657
+ * (though caching will avoid redundant WebGL calls)
3658
+ */
3659
+ _applyUniforms(uniforms) {
3660
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
3661
+ const { name, location, type, textureUnit } = uniformLayout;
3662
+ const value = uniforms[name] ?? textureUnit;
3663
+ if (value !== void 0) {
3664
+ setUniform(this.device.gl, location, type, value);
3665
+ }
3666
+ }
3667
+ }
3668
+ _syncLinkStatus() {
3669
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
3670
+ }
3671
+ };
3672
+ }
3673
+ });
3674
+
3675
+ // dist/adapter/converters/webgl-shadertypes.js
3676
+ function convertDataTypeToGLDataType(normalizedType) {
3677
+ return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3678
+ }
3679
+ function convertGLUniformTypeToShaderVariableType(glUniformType) {
3680
+ return WEBGL_SHADER_TYPES[glUniformType];
3681
+ }
3682
+ function isGLSamplerType(type) {
3683
+ return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3684
+ }
3685
+ function getTextureBindingFromGLSamplerType(glSamplerType) {
3686
+ return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3687
+ }
3688
+ var import_constants19, WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
3689
+ var init_webgl_shadertypes = __esm({
3690
+ "dist/adapter/converters/webgl-shadertypes.js"() {
3691
+ "use strict";
3692
+ import_constants19 = require("@luma.gl/constants");
3693
+ WEBGL_SHADER_TYPES = {
3694
+ [5126]: "f32",
3695
+ [35664]: "vec2<f32>",
3696
+ [35665]: "vec3<f32>",
3697
+ [35666]: "vec4<f32>",
3698
+ [5124]: "i32",
3699
+ [35667]: "vec2<i32>",
3700
+ [35668]: "vec3<i32>",
3701
+ [35669]: "vec4<i32>",
3702
+ [5125]: "u32",
3703
+ [36294]: "vec2<u32>",
3704
+ [36295]: "vec3<u32>",
3705
+ [36296]: "vec4<u32>",
3706
+ [35670]: "f32",
3707
+ [35671]: "vec2<f32>",
3708
+ [35672]: "vec3<f32>",
3709
+ [35673]: "vec4<f32>",
3710
+ // TODO - are sizes/components below correct?
3711
+ [35674]: "mat2x2<f32>",
3712
+ [35685]: "mat2x3<f32>",
3713
+ [35686]: "mat2x4<f32>",
3714
+ [35687]: "mat3x2<f32>",
3715
+ [35675]: "mat3x3<f32>",
3716
+ [35688]: "mat3x4<f32>",
3717
+ [35689]: "mat4x2<f32>",
3718
+ [35690]: "mat4x3<f32>",
3719
+ [35676]: "mat4x4<f32>"
3720
+ };
3721
+ WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3722
+ [35678]: { viewDimension: "2d", sampleType: "float" },
3723
+ [35680]: { viewDimension: "cube", sampleType: "float" },
3724
+ [35679]: { viewDimension: "3d", sampleType: "float" },
3725
+ [35682]: { viewDimension: "3d", sampleType: "depth" },
3726
+ [36289]: { viewDimension: "2d-array", sampleType: "float" },
3727
+ [36292]: { viewDimension: "2d-array", sampleType: "depth" },
3728
+ [36293]: { viewDimension: "cube", sampleType: "float" },
3729
+ [36298]: { viewDimension: "2d", sampleType: "sint" },
3730
+ [36299]: { viewDimension: "3d", sampleType: "sint" },
3731
+ [36300]: { viewDimension: "cube", sampleType: "sint" },
3732
+ [36303]: { viewDimension: "2d-array", sampleType: "uint" },
3733
+ [36306]: { viewDimension: "2d", sampleType: "uint" },
3734
+ [36307]: { viewDimension: "3d", sampleType: "uint" },
3735
+ [36308]: { viewDimension: "cube", sampleType: "uint" },
3736
+ [36311]: { viewDimension: "2d-array", sampleType: "uint" }
3737
+ };
3738
+ NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3739
+ uint8: 5121,
3740
+ sint8: 5120,
3741
+ unorm8: 5121,
3742
+ snorm8: 5120,
3743
+ uint16: 5123,
3744
+ sint16: 5122,
3745
+ unorm16: 5123,
3746
+ snorm16: 5122,
3747
+ uint32: 5125,
3748
+ sint32: 5124,
3749
+ // WebGPU does not support normalized 32 bit integer attributes
3750
+ // 'unorm32': GL.UNSIGNED_INT,
3751
+ // 'snorm32': GL.INT,
3752
+ float16: 5131,
3753
+ float32: 5126
3754
+ };
3755
+ }
3756
+ });
3757
+
3758
+ // dist/adapter/helpers/get-shader-layout-from-glsl.js
3759
+ function getShaderLayoutFromGLSL(gl, program) {
3760
+ const shaderLayout = {
3761
+ attributes: [],
3762
+ bindings: []
3763
+ };
3764
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
3765
+ const uniformBlocks = readUniformBlocks(gl, program);
3766
+ for (const uniformBlock of uniformBlocks) {
3767
+ const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3768
+ name: uniform.name,
3769
+ format: uniform.format,
3770
+ byteOffset: uniform.byteOffset,
3771
+ byteStride: uniform.byteStride,
3772
+ arrayLength: uniform.arrayLength
3773
+ }));
3774
+ shaderLayout.bindings.push({
3775
+ type: "uniform",
3776
+ name: uniformBlock.name,
3777
+ group: 0,
3778
+ location: uniformBlock.location,
3779
+ visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3780
+ minBindingSize: uniformBlock.byteLength,
3781
+ uniforms: uniforms2
3782
+ });
3783
+ }
3784
+ const uniforms = readUniformBindings(gl, program);
3785
+ let textureUnit = 0;
3786
+ for (const uniform of uniforms) {
3787
+ if (isGLSamplerType(uniform.type)) {
3788
+ const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3789
+ shaderLayout.bindings.push({
3790
+ type: "texture",
3791
+ name: uniform.name,
3792
+ group: 0,
3793
+ location: textureUnit,
3794
+ viewDimension,
3795
+ sampleType
3796
+ });
3797
+ uniform.textureUnit = textureUnit;
3798
+ textureUnit += 1;
3799
+ }
3800
+ }
3801
+ if (uniforms.length) {
3802
+ shaderLayout.uniforms = uniforms;
3803
+ }
3804
+ const varyings = readVaryings(gl, program);
3805
+ if (varyings == null ? void 0 : varyings.length) {
3806
+ shaderLayout.varyings = varyings;
3807
+ }
3808
+ return shaderLayout;
3809
+ }
3810
+ function readAttributeDeclarations(gl, program) {
3811
+ const attributes = [];
3812
+ const count = gl.getProgramParameter(program, 35721);
3813
+ for (let index = 0; index < count; index++) {
3814
+ const activeInfo = gl.getActiveAttrib(program, index);
3815
+ if (!activeInfo) {
3816
+ throw new Error("activeInfo");
3817
+ }
3818
+ const {
3819
+ name,
3820
+ type: compositeType
3821
+ /* , size*/
3822
+ } = activeInfo;
3823
+ const location = gl.getAttribLocation(program, name);
3824
+ if (location >= 0) {
3825
+ const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
3826
+ const stepMode = /instance/i.test(name) ? "instance" : "vertex";
3827
+ attributes.push({
3828
+ name,
3829
+ location,
3830
+ stepMode,
3831
+ type: attributeType
3832
+ // size - for arrays, size is the number of elements in the array
3833
+ });
3834
+ }
3835
+ }
3836
+ attributes.sort((a, b) => a.location - b.location);
3837
+ return attributes;
3838
+ }
3839
+ function readVaryings(gl, program) {
3840
+ const varyings = [];
3841
+ const count = gl.getProgramParameter(program, 35971);
3842
+ for (let location = 0; location < count; location++) {
3843
+ const activeInfo = gl.getTransformFeedbackVarying(program, location);
3844
+ if (!activeInfo) {
3845
+ throw new Error("activeInfo");
3846
+ }
3847
+ const { name, type: glUniformType, size } = activeInfo;
3848
+ const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3849
+ const { type, components } = (0, import_core17.getVariableShaderTypeInfo)(uniformType);
3850
+ varyings.push({ location, name, type, size: size * components });
3851
+ }
3852
+ varyings.sort((a, b) => a.location - b.location);
3853
+ return varyings;
3854
+ }
3855
+ function readUniformBindings(gl, program) {
3856
+ const uniforms = [];
3857
+ const uniformCount = gl.getProgramParameter(program, 35718);
3858
+ for (let i = 0; i < uniformCount; i++) {
3859
+ const activeInfo = gl.getActiveUniform(program, i);
3860
+ if (!activeInfo) {
3861
+ throw new Error("activeInfo");
3862
+ }
3863
+ const { name: rawName, size, type } = activeInfo;
3864
+ const { name, isArray: isArray3 } = parseUniformName(rawName);
3865
+ let webglLocation = gl.getUniformLocation(program, name);
3866
+ const uniformInfo = {
3867
+ // WebGL locations are uniquely typed but just numbers
3868
+ location: webglLocation,
3869
+ name,
3870
+ size,
3871
+ type,
3872
+ isArray: isArray3
3873
+ };
3874
+ uniforms.push(uniformInfo);
3875
+ if (uniformInfo.size > 1) {
3876
+ for (let j = 0; j < uniformInfo.size; j++) {
3877
+ const elementName = `${name}[${j}]`;
3878
+ webglLocation = gl.getUniformLocation(program, elementName);
3879
+ const arrayElementUniformInfo = {
3880
+ ...uniformInfo,
3881
+ name: elementName,
3882
+ location: webglLocation
3883
+ };
3884
+ uniforms.push(arrayElementUniformInfo);
3885
+ }
3886
+ }
3887
+ }
3888
+ return uniforms;
3889
+ }
3890
+ function readUniformBlocks(gl, program) {
3891
+ const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3892
+ const uniformBlocks = [];
3893
+ const blockCount = gl.getProgramParameter(program, 35382);
3894
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3895
+ const blockInfo = {
3896
+ name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3897
+ location: getBlockParameter(blockIndex, 35391),
3898
+ byteLength: getBlockParameter(blockIndex, 35392),
3899
+ vertex: getBlockParameter(blockIndex, 35396),
3900
+ fragment: getBlockParameter(blockIndex, 35398),
3901
+ uniformCount: getBlockParameter(blockIndex, 35394),
3902
+ uniforms: []
3903
+ };
3904
+ const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3905
+ const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3906
+ const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3907
+ const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3908
+ const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3909
+ for (let i = 0; i < blockInfo.uniformCount; ++i) {
3910
+ const uniformIndex = uniformIndices[i];
3911
+ if (uniformIndex !== void 0) {
3912
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
3913
+ if (!activeInfo) {
3914
+ throw new Error("activeInfo");
3915
+ }
3916
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3917
+ blockInfo.uniforms.push({
3918
+ name: activeInfo.name,
3919
+ format,
3920
+ type: uniformType[i],
3921
+ arrayLength: uniformArrayLength[i],
3922
+ byteOffset: uniformOffset[i],
3923
+ byteStride: uniformStride[i]
3924
+ // matrixStride: uniformStride[i],
3925
+ // rowMajor: uniformRowMajor[i]
3926
+ });
3927
+ }
3928
+ }
3929
+ uniformBlocks.push(blockInfo);
3930
+ }
3931
+ uniformBlocks.sort((a, b) => a.location - b.location);
3932
+ return uniformBlocks;
3933
+ }
3934
+ function parseUniformName(name) {
3935
+ if (name[name.length - 1] !== "]") {
3936
+ return {
3937
+ name,
3938
+ length: 1,
3939
+ isArray: false
3940
+ };
3941
+ }
3942
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3943
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
3944
+ const uniformName = (0, import_core17.assertDefined)(matches == null ? void 0 : matches[1], `Failed to parse GLSL uniform name ${name}`);
3945
+ return {
3946
+ name: uniformName,
3947
+ // TODO - is this a bug, shouldn't we return the value?
3948
+ length: (matches == null ? void 0 : matches[2]) ? 1 : 0,
3949
+ isArray: Boolean(matches == null ? void 0 : matches[2])
3950
+ };
3951
+ }
3952
+ var import_core17, import_constants20;
3953
+ var init_get_shader_layout_from_glsl = __esm({
3954
+ "dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3955
+ "use strict";
3956
+ import_core17 = require("@luma.gl/core");
3957
+ import_constants20 = require("@luma.gl/constants");
3958
+ init_webgl_shadertypes();
3959
+ }
3960
+ });
3961
+
3962
+ // dist/adapter/resources/webgl-shared-render-pipeline.js
3963
+ var import_constants21, import_core18, LOG_PROGRAM_PERF_PRIORITY, WEBGLSharedRenderPipeline;
3964
+ var init_webgl_shared_render_pipeline = __esm({
3965
+ "dist/adapter/resources/webgl-shared-render-pipeline.js"() {
3966
+ "use strict";
3967
+ import_constants21 = require("@luma.gl/constants");
3968
+ import_core18 = require("@luma.gl/core");
3969
+ init_get_shader_layout_from_glsl();
3970
+ init_webgl_shadertypes();
3971
+ LOG_PROGRAM_PERF_PRIORITY = 4;
3972
+ WEBGLSharedRenderPipeline = class extends import_core18.SharedRenderPipeline {
3973
+ device;
3974
+ handle;
3975
+ vs;
3976
+ fs;
3977
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
3978
+ linkStatus = "pending";
3979
+ constructor(device, props) {
3980
+ super(device, props);
3981
+ this.device = device;
3982
+ this.handle = props.handle || this.device.gl.createProgram();
3983
+ this.vs = props.vs;
3984
+ this.fs = props.fs;
3985
+ if (props.varyings && props.varyings.length > 0) {
3986
+ this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
3987
+ }
3988
+ this._linkShaders();
3989
+ import_core18.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3990
+ this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3991
+ import_core18.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3992
+ }
3993
+ destroy() {
3994
+ if (this.destroyed) {
3995
+ return;
3996
+ }
3997
+ this.device.gl.useProgram(null);
3998
+ this.device.gl.deleteProgram(this.handle);
3999
+ this.handle.destroyed = true;
4000
+ this.destroyResource();
3571
4001
  }
3572
- // PRIVATE METHODS
3573
- // setAttributes(attributes: Record<string, Buffer>): void {}
3574
- // setBindings(bindings: Record<string, Binding>): void {}
3575
4002
  async _linkShaders() {
3576
4003
  const { gl } = this.device;
3577
4004
  gl.attachShader(this.handle, this.vs.handle);
3578
4005
  gl.attachShader(this.handle, this.fs.handle);
3579
- import_core16.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4006
+ import_core18.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3580
4007
  gl.linkProgram(this.handle);
3581
- import_core16.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3582
- if (import_core16.log.level === 0) {
3583
- }
4008
+ import_core18.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3584
4009
  if (!this.device.features.has("compilation-status-async-webgl")) {
3585
4010
  const status2 = this._getLinkStatus();
3586
4011
  this._reportLinkStatus(status2);
3587
4012
  return;
3588
4013
  }
3589
- import_core16.log.once(1, "RenderPipeline linking is asynchronous")();
4014
+ import_core18.log.once(1, "RenderPipeline linking is asynchronous")();
3590
4015
  await this._waitForLinkComplete();
3591
- import_core16.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4016
+ import_core18.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
3592
4017
  const status = this._getLinkStatus();
3593
4018
  this._reportLinkStatus(status);
3594
4019
  }
3595
- /** Report link status. First, check for shader compilation failures if linking fails */
3596
4020
  async _reportLinkStatus(status) {
3597
4021
  var _a;
3598
4022
  switch (status) {
@@ -3627,11 +4051,6 @@ var init_webgl_render_pipeline = __esm({
3627
4051
  this.device.debug();
3628
4052
  }
3629
4053
  }
3630
- /**
3631
- * Get the shader compilation status
3632
- * TODO - Load log even when no error reported, to catch warnings?
3633
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
3634
- */
3635
4054
  _getLinkStatus() {
3636
4055
  const { gl } = this.device;
3637
4056
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -3639,6 +4058,7 @@ var init_webgl_render_pipeline = __esm({
3639
4058
  this.linkStatus = "error";
3640
4059
  return "link-error";
3641
4060
  }
4061
+ this._initializeSamplerUniforms();
3642
4062
  gl.validateProgram(this.handle);
3643
4063
  const validated = gl.getProgramParameter(this.handle, 35715);
3644
4064
  if (!validated) {
@@ -3648,7 +4068,33 @@ var init_webgl_render_pipeline = __esm({
3648
4068
  this.linkStatus = "success";
3649
4069
  return "success";
3650
4070
  }
3651
- /** Use KHR_parallel_shader_compile extension if available */
4071
+ _initializeSamplerUniforms() {
4072
+ const { gl } = this.device;
4073
+ gl.useProgram(this.handle);
4074
+ let textureUnit = 0;
4075
+ const uniformCount = gl.getProgramParameter(this.handle, 35718);
4076
+ for (let uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) {
4077
+ const activeInfo = gl.getActiveUniform(this.handle, uniformIndex);
4078
+ if (activeInfo && isGLSamplerType(activeInfo.type)) {
4079
+ const isArray3 = activeInfo.name.endsWith("[0]");
4080
+ const uniformName = isArray3 ? activeInfo.name.slice(0, -3) : activeInfo.name;
4081
+ const location = gl.getUniformLocation(this.handle, uniformName);
4082
+ if (location !== null) {
4083
+ textureUnit = this._assignSamplerUniform(location, activeInfo, isArray3, textureUnit);
4084
+ }
4085
+ }
4086
+ }
4087
+ }
4088
+ _assignSamplerUniform(location, activeInfo, isArray3, textureUnit) {
4089
+ const { gl } = this.device;
4090
+ if (isArray3 && activeInfo.size > 1) {
4091
+ const textureUnits = Int32Array.from({ length: activeInfo.size }, (_, arrayIndex) => textureUnit + arrayIndex);
4092
+ gl.uniform1iv(location, textureUnits);
4093
+ return textureUnit + activeInfo.size;
4094
+ }
4095
+ gl.uniform1i(location, textureUnit);
4096
+ return textureUnit + 1;
4097
+ }
3652
4098
  async _waitForLinkComplete() {
3653
4099
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
3654
4100
  const DELAY_MS = 10;
@@ -3665,99 +4111,6 @@ var init_webgl_render_pipeline = __esm({
3665
4111
  await waitMs(DELAY_MS);
3666
4112
  }
3667
4113
  }
3668
- /**
3669
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
3670
- * Update a texture if needed (e.g. from video)
3671
- * Note: This is currently done before every draw call
3672
- */
3673
- _areTexturesRenderable() {
3674
- let texturesRenderable = true;
3675
- for (const bindingInfo of this.shaderLayout.bindings) {
3676
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
3677
- import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
3678
- texturesRenderable = false;
3679
- }
3680
- }
3681
- return texturesRenderable;
3682
- }
3683
- /** Apply any bindings (before each draw call) */
3684
- _applyBindings() {
3685
- if (this.linkStatus !== "success") {
3686
- return;
3687
- }
3688
- const { gl } = this.device;
3689
- gl.useProgram(this.handle);
3690
- let textureUnit = 0;
3691
- let uniformBufferIndex = 0;
3692
- for (const binding of this.shaderLayout.bindings) {
3693
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
3694
- if (!value) {
3695
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
3696
- }
3697
- switch (binding.type) {
3698
- case "uniform":
3699
- const { name } = binding;
3700
- const location = gl.getUniformBlockIndex(this.handle, name);
3701
- if (location === 4294967295) {
3702
- throw new Error(`Invalid uniform block name ${name}`);
3703
- }
3704
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
3705
- if (value instanceof WEBGLBuffer) {
3706
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
3707
- } else {
3708
- gl.bindBufferRange(
3709
- 35345,
3710
- uniformBufferIndex,
3711
- // @ts-expect-error
3712
- value.buffer.handle,
3713
- // @ts-expect-error
3714
- value.offset || 0,
3715
- // @ts-expect-error
3716
- value.size || value.buffer.byteLength - value.offset
3717
- );
3718
- }
3719
- uniformBufferIndex += 1;
3720
- break;
3721
- case "texture":
3722
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3723
- throw new Error("texture");
3724
- }
3725
- let texture;
3726
- if (value instanceof WEBGLTextureView) {
3727
- texture = value.texture;
3728
- } else if (value instanceof WEBGLTexture) {
3729
- texture = value;
3730
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
3731
- import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
3732
- texture = value.colorAttachments[0].texture;
3733
- } else {
3734
- throw new Error("No texture");
3735
- }
3736
- gl.activeTexture(33984 + textureUnit);
3737
- gl.bindTexture(texture.glTarget, texture.handle);
3738
- textureUnit += 1;
3739
- break;
3740
- case "sampler":
3741
- break;
3742
- case "storage":
3743
- case "read-only-storage":
3744
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3745
- }
3746
- }
3747
- }
3748
- /**
3749
- * Due to program sharing, uniforms need to be reset before every draw call
3750
- * (though caching will avoid redundant WebGL calls)
3751
- */
3752
- _applyUniforms() {
3753
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
3754
- const { name, location, type, textureUnit } = uniformLayout;
3755
- const value = this.uniforms[name] ?? textureUnit;
3756
- if (value !== void 0) {
3757
- setUniform(this.device.gl, location, type, value);
3758
- }
3759
- }
3760
- }
3761
4114
  };
3762
4115
  }
3763
4116
  });
@@ -3789,7 +4142,7 @@ function _copyTextureToBuffer(device, options) {
3789
4142
  height = options.sourceTexture.height,
3790
4143
  depthOrArrayLayers = 0,
3791
4144
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
3792
- origin = [0, 0],
4145
+ origin = [0, 0, 0],
3793
4146
  /** Destination buffer */
3794
4147
  destinationBuffer,
3795
4148
  /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
@@ -3818,7 +4171,8 @@ function _copyTextureToBuffer(device, options) {
3818
4171
  const webglBuffer = destinationBuffer;
3819
4172
  const sourceWidth = width || framebuffer.width;
3820
4173
  const sourceHeight = height || framebuffer.height;
3821
- const sourceParams = getTextureFormatWebGL(framebuffer.colorAttachments[0].texture.props.format);
4174
+ const colorAttachment0 = (0, import_core19.assertDefined)(framebuffer.colorAttachments[0]);
4175
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
3822
4176
  const sourceFormat = sourceParams.format;
3823
4177
  const sourceType = sourceParams.type;
3824
4178
  device.gl.bindBuffer(35051, webglBuffer.handle);
@@ -3845,7 +4199,7 @@ function _copyTextureToTexture(device, options) {
3845
4199
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
3846
4200
  origin = [0, 0],
3847
4201
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
3848
- destinationOrigin = [0, 0],
4202
+ destinationOrigin = [0, 0, 0],
3849
4203
  /** Texture to copy to/from. */
3850
4204
  destinationTexture
3851
4205
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -3861,7 +4215,7 @@ function _copyTextureToTexture(device, options) {
3861
4215
  // depthOrArrayLayers = 0
3862
4216
  } = options;
3863
4217
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
3864
- const [sourceX, sourceY] = origin;
4218
+ const [sourceX = 0, sourceY = 0] = origin;
3865
4219
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
3866
4220
  const prevHandle = device.gl.bindFramebuffer(36160, framebuffer.handle);
3867
4221
  let texture;
@@ -3895,7 +4249,7 @@ function _copyTextureToTexture(device, options) {
3895
4249
  }
3896
4250
  }
3897
4251
  function getFramebuffer(source) {
3898
- if (source instanceof import_core17.Texture) {
4252
+ if (source instanceof import_core19.Texture) {
3899
4253
  const { width, height, id } = source;
3900
4254
  const framebuffer = source.device.createFramebuffer({
3901
4255
  id: `framebuffer-for-${id}`,
@@ -3907,20 +4261,20 @@ function getFramebuffer(source) {
3907
4261
  }
3908
4262
  return { framebuffer: source, destroyFramebuffer: false };
3909
4263
  }
3910
- var import_core17, import_constants21, WEBGLCommandBuffer;
4264
+ var import_core19, import_constants22, WEBGLCommandBuffer;
3911
4265
  var init_webgl_command_buffer = __esm({
3912
4266
  "dist/adapter/resources/webgl-command-buffer.js"() {
3913
4267
  "use strict";
3914
- import_core17 = require("@luma.gl/core");
3915
- import_constants21 = require("@luma.gl/constants");
4268
+ import_core19 = require("@luma.gl/core");
4269
+ import_constants22 = require("@luma.gl/constants");
3916
4270
  init_webgl_texture();
3917
4271
  init_webgl_texture_table();
3918
- WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
4272
+ WEBGLCommandBuffer = class extends import_core19.CommandBuffer {
3919
4273
  device;
3920
4274
  handle = null;
3921
4275
  commands = [];
3922
- constructor(device) {
3923
- super(device, {});
4276
+ constructor(device, props = {}) {
4277
+ super(device, props);
3924
4278
  this.device = device;
3925
4279
  }
3926
4280
  _executeCommands(commands = this.commands) {
@@ -3948,16 +4302,16 @@ var init_webgl_command_buffer = __esm({
3948
4302
  });
3949
4303
 
3950
4304
  // dist/adapter/resources/webgl-render-pass.js
3951
- var import_core18, import_constants22, COLOR_CHANNELS, WEBGLRenderPass;
4305
+ var import_core20, import_constants23, COLOR_CHANNELS, WEBGLRenderPass;
3952
4306
  var init_webgl_render_pass = __esm({
3953
4307
  "dist/adapter/resources/webgl-render-pass.js"() {
3954
4308
  "use strict";
3955
- import_core18 = require("@luma.gl/core");
3956
- import_constants22 = require("@luma.gl/constants");
4309
+ import_core20 = require("@luma.gl/core");
4310
+ import_constants23 = require("@luma.gl/constants");
3957
4311
  init_with_parameters();
3958
4312
  init_unified_parameter_api();
3959
4313
  COLOR_CHANNELS = [1, 2, 4, 8];
3960
- WEBGLRenderPass = class extends import_core18.RenderPass {
4314
+ WEBGLRenderPass = class extends import_core20.RenderPass {
3961
4315
  device;
3962
4316
  handle = null;
3963
4317
  /** Parameters that should be applied before each draw call */
@@ -3966,6 +4320,9 @@ var init_webgl_render_pass = __esm({
3966
4320
  var _a;
3967
4321
  super(device, props);
3968
4322
  this.device = device;
4323
+ if (!(props == null ? void 0 : props.framebuffer)) {
4324
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4325
+ }
3969
4326
  let viewport;
3970
4327
  if (!((_a = props == null ? void 0 : props.parameters) == null ? void 0 : _a.viewport)) {
3971
4328
  if (props == null ? void 0 : props.framebuffer) {
@@ -3986,9 +4343,21 @@ var init_webgl_render_pass = __esm({
3986
4343
  this.device.gl.drawBuffers([1029]);
3987
4344
  }
3988
4345
  this.clear();
4346
+ if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== void 0) {
4347
+ const webglQuerySet = this.props.timestampQuerySet;
4348
+ webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
4349
+ }
3989
4350
  }
3990
4351
  end() {
4352
+ if (this.destroyed) {
4353
+ return;
4354
+ }
4355
+ if (this.props.timestampQuerySet && this.props.endTimestampIndex !== void 0) {
4356
+ const webglQuerySet = this.props.timestampQuerySet;
4357
+ webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
4358
+ }
3991
4359
  this.device.popState();
4360
+ this.destroy();
3992
4361
  }
3993
4362
  pushDebugGroup(groupLabel) {
3994
4363
  }
@@ -4108,31 +4477,39 @@ var init_webgl_render_pass = __esm({
4108
4477
  });
4109
4478
 
4110
4479
  // dist/adapter/resources/webgl-command-encoder.js
4111
- var import_core19, WEBGLCommandEncoder;
4480
+ var import_core21, WEBGLCommandEncoder;
4112
4481
  var init_webgl_command_encoder = __esm({
4113
4482
  "dist/adapter/resources/webgl-command-encoder.js"() {
4114
4483
  "use strict";
4115
- import_core19 = require("@luma.gl/core");
4484
+ import_core21 = require("@luma.gl/core");
4116
4485
  init_webgl_command_buffer();
4117
4486
  init_webgl_render_pass();
4118
- WEBGLCommandEncoder = class extends import_core19.CommandEncoder {
4487
+ WEBGLCommandEncoder = class extends import_core21.CommandEncoder {
4119
4488
  device;
4120
4489
  handle = null;
4121
4490
  commandBuffer;
4122
4491
  constructor(device, props) {
4123
4492
  super(device, props);
4124
4493
  this.device = device;
4125
- this.commandBuffer = new WEBGLCommandBuffer(device);
4494
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
4495
+ id: `${this.props.id}-command-buffer`
4496
+ });
4126
4497
  }
4127
4498
  destroy() {
4499
+ this.destroyResource();
4128
4500
  }
4129
- finish() {
4501
+ finish(props) {
4502
+ if ((props == null ? void 0 : props.id) && this.commandBuffer.id !== props.id) {
4503
+ this.commandBuffer.id = props.id;
4504
+ this.commandBuffer.props.id = props.id;
4505
+ }
4506
+ this.destroy();
4130
4507
  return this.commandBuffer;
4131
4508
  }
4132
- beginRenderPass(props) {
4133
- return new WEBGLRenderPass(this.device, props);
4509
+ beginRenderPass(props = {}) {
4510
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4134
4511
  }
4135
- beginComputePass(props) {
4512
+ beginComputePass(props = {}) {
4136
4513
  throw new Error("ComputePass not supported in WebGL");
4137
4514
  }
4138
4515
  copyBufferToBuffer(options) {
@@ -4158,6 +4535,10 @@ var init_webgl_command_encoder = __esm({
4158
4535
  }
4159
4536
  resolveQuerySet(querySet, destination, options) {
4160
4537
  }
4538
+ writeTimestamp(querySet, queryIndex) {
4539
+ const webglQuerySet = querySet;
4540
+ webglQuerySet.writeTimestamp(queryIndex);
4541
+ }
4161
4542
  };
4162
4543
  }
4163
4544
  });
@@ -4169,7 +4550,7 @@ function fillArray(options) {
4169
4550
  const total = count * length;
4170
4551
  let copied = 0;
4171
4552
  for (let i = start; copied < length; copied++) {
4172
- target2[i++] = source[copied];
4553
+ target2[i++] = source[copied] ?? 0;
4173
4554
  }
4174
4555
  while (copied < total) {
4175
4556
  if (copied < total - copied) {
@@ -4206,16 +4587,16 @@ function compareConstantArrayValues(v1, v2) {
4206
4587
  }
4207
4588
  return true;
4208
4589
  }
4209
- var import_core20, import_constants23, import_env2, WEBGLVertexArray;
4590
+ var import_core22, import_constants24, import_env2, WEBGLVertexArray;
4210
4591
  var init_webgl_vertex_array = __esm({
4211
4592
  "dist/adapter/resources/webgl-vertex-array.js"() {
4212
4593
  "use strict";
4213
- import_core20 = require("@luma.gl/core");
4214
- import_constants23 = require("@luma.gl/constants");
4594
+ import_core22 = require("@luma.gl/core");
4595
+ import_constants24 = require("@luma.gl/constants");
4215
4596
  import_env2 = require("@probe.gl/env");
4216
4597
  init_webgl_vertex_formats();
4217
4598
  init_fill_array();
4218
- WEBGLVertexArray = class extends import_core20.VertexArray {
4599
+ WEBGLVertexArray = class extends import_core22.VertexArray {
4219
4600
  get [Symbol.toStringTag]() {
4220
4601
  return "VertexArray";
4221
4602
  }
@@ -4382,7 +4763,7 @@ var init_webgl_vertex_array = __esm({
4382
4763
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4383
4764
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4384
4765
  if (updateNeeded) {
4385
- const typedArray = (0, import_core20.getScratchArray)(value.constructor, length);
4766
+ const typedArray = (0, import_core22.getScratchArray)(value.constructor, length);
4386
4767
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4387
4768
  this.buffer.write(typedArray);
4388
4769
  this.bufferValue = value;
@@ -4400,15 +4781,15 @@ function isIndex(value) {
4400
4781
  }
4401
4782
  return /^\d+$/.test(value);
4402
4783
  }
4403
- var import_core21, import_constants24, WEBGLTransformFeedback;
4784
+ var import_core23, import_constants25, WEBGLTransformFeedback;
4404
4785
  var init_webgl_transform_feedback = __esm({
4405
4786
  "dist/adapter/resources/webgl-transform-feedback.js"() {
4406
4787
  "use strict";
4407
- import_core21 = require("@luma.gl/core");
4408
- import_constants24 = require("@luma.gl/constants");
4788
+ import_core23 = require("@luma.gl/core");
4789
+ import_constants25 = require("@luma.gl/constants");
4409
4790
  init_dist();
4410
4791
  init_webgl_topology_utils();
4411
- WEBGLTransformFeedback = class extends import_core21.TransformFeedback {
4792
+ WEBGLTransformFeedback = class extends import_core23.TransformFeedback {
4412
4793
  device;
4413
4794
  gl;
4414
4795
  handle;
@@ -4461,8 +4842,8 @@ var init_webgl_transform_feedback = __esm({
4461
4842
  this.buffers = {};
4462
4843
  this.unusedBuffers = {};
4463
4844
  this.bind(() => {
4464
- for (const bufferName in buffers) {
4465
- this.setBuffer(bufferName, buffers[bufferName]);
4845
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
4846
+ this.setBuffer(bufferName, buffer);
4466
4847
  }
4467
4848
  });
4468
4849
  }
@@ -4471,7 +4852,7 @@ var init_webgl_transform_feedback = __esm({
4471
4852
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
4472
4853
  if (location < 0) {
4473
4854
  this.unusedBuffers[locationOrName] = buffer;
4474
- import_core21.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4855
+ import_core23.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4475
4856
  return;
4476
4857
  }
4477
4858
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -4484,7 +4865,7 @@ var init_webgl_transform_feedback = __esm({
4484
4865
  return this.buffers[locationOrName] || null;
4485
4866
  }
4486
4867
  const location = this._getVaryingIndex(locationOrName);
4487
- return location >= 0 ? this.buffers[location] : null;
4868
+ return this.buffers[location] ?? null;
4488
4869
  }
4489
4870
  bind(funcOrHandle = this.handle) {
4490
4871
  if (typeof funcOrHandle !== "function") {
@@ -4531,8 +4912,8 @@ var init_webgl_transform_feedback = __esm({
4531
4912
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
4532
4913
  */
4533
4914
  _bindBuffers() {
4534
- for (const bufferIndex in this.buffers) {
4535
- const { buffer, byteLength, byteOffset } = this._getBufferRange(this.buffers[bufferIndex]);
4915
+ for (const [bufferIndex, bufferEntry] of Object.entries(this.buffers)) {
4916
+ const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferEntry);
4536
4917
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
4537
4918
  }
4538
4919
  }
@@ -4554,152 +4935,245 @@ var init_webgl_transform_feedback = __esm({
4554
4935
  });
4555
4936
 
4556
4937
  // dist/adapter/resources/webgl-query-set.js
4557
- var import_core22, import_constants25, WEBGLQuerySet;
4938
+ var import_core24, import_constants26, WEBGLQuerySet;
4558
4939
  var init_webgl_query_set = __esm({
4559
4940
  "dist/adapter/resources/webgl-query-set.js"() {
4560
4941
  "use strict";
4561
- import_core22 = require("@luma.gl/core");
4562
- import_constants25 = require("@luma.gl/constants");
4563
- WEBGLQuerySet = class extends import_core22.QuerySet {
4942
+ import_core24 = require("@luma.gl/core");
4943
+ import_constants26 = require("@luma.gl/constants");
4944
+ WEBGLQuerySet = class extends import_core24.QuerySet {
4564
4945
  device;
4565
4946
  handle;
4566
- target = null;
4567
- _queryPending = false;
4568
- _pollingPromise = null;
4947
+ _timestampPairs = [];
4948
+ _occlusionQuery = null;
4949
+ _occlusionActive = false;
4569
4950
  get [Symbol.toStringTag]() {
4570
- return "Query";
4951
+ return "QuerySet";
4571
4952
  }
4572
- // Create a query class
4573
4953
  constructor(device, props) {
4574
4954
  super(device, props);
4575
4955
  this.device = device;
4576
- if (props.count > 1) {
4577
- throw new Error("WebGL QuerySet can only have one value");
4578
- }
4579
- const handle = this.device.gl.createQuery();
4580
- if (!handle) {
4581
- throw new Error("WebGL query not supported");
4956
+ if (props.type === "timestamp") {
4957
+ if (props.count < 2) {
4958
+ throw new Error("Timestamp QuerySet requires at least two query slots");
4959
+ }
4960
+ this._timestampPairs = new Array(Math.ceil(props.count / 2)).fill(null).map(() => ({ activeQuery: null, completedQueries: [] }));
4961
+ this.handle = null;
4962
+ } else {
4963
+ if (props.count > 1) {
4964
+ throw new Error("WebGL occlusion QuerySet can only have one value");
4965
+ }
4966
+ const handle = this.device.gl.createQuery();
4967
+ if (!handle) {
4968
+ throw new Error("WebGL query not supported");
4969
+ }
4970
+ this.handle = handle;
4582
4971
  }
4583
- this.handle = handle;
4584
4972
  Object.seal(this);
4585
4973
  }
4586
4974
  destroy() {
4587
- this.device.gl.deleteQuery(this.handle);
4975
+ if (this.destroyed) {
4976
+ return;
4977
+ }
4978
+ if (this.handle) {
4979
+ this.device.gl.deleteQuery(this.handle);
4980
+ }
4981
+ for (const pair of this._timestampPairs) {
4982
+ if (pair.activeQuery) {
4983
+ this.device.gl.deleteQuery(pair.activeQuery.handle);
4984
+ }
4985
+ for (const query of pair.completedQueries) {
4986
+ this.device.gl.deleteQuery(query.handle);
4987
+ }
4988
+ }
4989
+ if (this._occlusionQuery) {
4990
+ this.device.gl.deleteQuery(this._occlusionQuery.handle);
4991
+ }
4992
+ this.destroyResource();
4588
4993
  }
4589
- // FOR RENDER PASS AND COMMAND ENCODER
4590
- /**
4591
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
4592
- * Measures GPU time delta between this call and a matching `end` call in the
4593
- * GPU instruction stream.
4594
- */
4595
- beginTimestampQuery() {
4596
- return this._begin(35007);
4994
+ isResultAvailable(queryIndex) {
4995
+ if (this.props.type === "timestamp") {
4996
+ if (queryIndex === void 0) {
4997
+ return this._timestampPairs.some((_, pairIndex) => this._isTimestampPairAvailable(pairIndex));
4998
+ }
4999
+ return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
5000
+ }
5001
+ if (!this._occlusionQuery) {
5002
+ return false;
5003
+ }
5004
+ return this._pollQueryAvailability(this._occlusionQuery);
5005
+ }
5006
+ async readResults(options) {
5007
+ const firstQuery = (options == null ? void 0 : options.firstQuery) || 0;
5008
+ const queryCount = (options == null ? void 0 : options.queryCount) || this.props.count - firstQuery;
5009
+ this._validateRange(firstQuery, queryCount);
5010
+ if (this.props.type === "timestamp") {
5011
+ const results = new Array(queryCount).fill(0n);
5012
+ const startPairIndex = Math.floor(firstQuery / 2);
5013
+ const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
5014
+ for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
5015
+ const duration = await this._consumeTimestampPairResult(pairIndex);
5016
+ const beginSlot = pairIndex * 2;
5017
+ const endSlot = beginSlot + 1;
5018
+ if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
5019
+ results[beginSlot - firstQuery] = 0n;
5020
+ }
5021
+ if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
5022
+ results[endSlot - firstQuery] = duration;
5023
+ }
5024
+ }
5025
+ return results;
5026
+ }
5027
+ if (!this._occlusionQuery) {
5028
+ throw new Error("Occlusion query has not been started");
5029
+ }
5030
+ return [await this._consumeQueryResult(this._occlusionQuery)];
4597
5031
  }
4598
- endTimestampQuery() {
4599
- this._end();
5032
+ async readTimestampDuration(beginIndex, endIndex) {
5033
+ if (this.props.type !== "timestamp") {
5034
+ throw new Error("Timestamp durations require a timestamp QuerySet");
5035
+ }
5036
+ if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
5037
+ throw new Error("Timestamp duration range is out of bounds");
5038
+ }
5039
+ if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
5040
+ throw new Error("WebGL timestamp durations require adjacent even/odd query indices");
5041
+ }
5042
+ const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
5043
+ return Number(result) / 1e6;
4600
5044
  }
4601
- // Shortcut for occlusion queries
4602
- beginOcclusionQuery(options) {
4603
- return this._begin((options == null ? void 0 : options.conservative) ? 36202 : 35887);
5045
+ beginOcclusionQuery() {
5046
+ if (this.props.type !== "occlusion") {
5047
+ throw new Error("Occlusion queries require an occlusion QuerySet");
5048
+ }
5049
+ if (!this.handle) {
5050
+ throw new Error("WebGL occlusion query is not available");
5051
+ }
5052
+ if (this._occlusionActive) {
5053
+ throw new Error("Occlusion query is already active");
5054
+ }
5055
+ this.device.gl.beginQuery(35887, this.handle);
5056
+ this._occlusionQuery = {
5057
+ handle: this.handle,
5058
+ promise: null,
5059
+ result: null,
5060
+ disjoint: false
5061
+ };
5062
+ this._occlusionActive = true;
4604
5063
  }
4605
5064
  endOcclusionQuery() {
4606
- this._end();
4607
- }
4608
- // Shortcut for transformFeedbackQuery
4609
- beginTransformFeedbackQuery() {
4610
- return this._begin(35976);
4611
- }
4612
- endTransformFeedbackQuery() {
4613
- this._end();
4614
- }
4615
- async resolveQuery() {
4616
- const value = await this.pollQuery();
4617
- return [value];
4618
- }
4619
- // PRIVATE METHODS
4620
- /**
4621
- * Due to OpenGL API limitations, after calling `begin()` on one Query
4622
- * instance, `end()` must be called on that same instance before
4623
- * calling `begin()` on another query. While there can be multiple
4624
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
4625
- * It is not possible to interleave or overlap `begin` and `end` calls.
4626
- */
4627
- _begin(target2) {
4628
- if (this._queryPending) {
4629
- return;
5065
+ if (!this._occlusionActive) {
5066
+ throw new Error("Occlusion query is not active");
4630
5067
  }
4631
- this.target = target2;
4632
- this.device.gl.beginQuery(this.target, this.handle);
4633
- return;
5068
+ this.device.gl.endQuery(35887);
5069
+ this._occlusionActive = false;
4634
5070
  }
4635
- // ends the current query
4636
- _end() {
4637
- if (this._queryPending) {
5071
+ writeTimestamp(queryIndex) {
5072
+ if (this.props.type !== "timestamp") {
5073
+ throw new Error("Timestamp writes require a timestamp QuerySet");
5074
+ }
5075
+ const pairIndex = this._getTimestampPairIndex(queryIndex);
5076
+ const pair = this._timestampPairs[pairIndex];
5077
+ if (queryIndex % 2 === 0) {
5078
+ if (pair.activeQuery) {
5079
+ throw new Error("Timestamp query pair is already active");
5080
+ }
5081
+ const handle = this.device.gl.createQuery();
5082
+ if (!handle) {
5083
+ throw new Error("WebGL query not supported");
5084
+ }
5085
+ const query = {
5086
+ handle,
5087
+ promise: null,
5088
+ result: null,
5089
+ disjoint: false
5090
+ };
5091
+ this.device.gl.beginQuery(35007, handle);
5092
+ pair.activeQuery = query;
4638
5093
  return;
4639
5094
  }
4640
- if (this.target) {
4641
- this.device.gl.endQuery(this.target);
4642
- this.target = null;
4643
- this._queryPending = true;
5095
+ if (!pair.activeQuery) {
5096
+ throw new Error("Timestamp query pair was ended before it was started");
4644
5097
  }
4645
- return;
5098
+ this.device.gl.endQuery(35007);
5099
+ pair.completedQueries.push(pair.activeQuery);
5100
+ pair.activeQuery = null;
4646
5101
  }
4647
- // Returns true if the query result is available
4648
- isResultAvailable() {
4649
- if (!this._queryPending) {
4650
- return false;
5102
+ _validateRange(firstQuery, queryCount) {
5103
+ if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
5104
+ throw new Error("Query read range is out of bounds");
4651
5105
  }
4652
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
4653
- if (resultAvailable) {
4654
- this._queryPending = false;
5106
+ }
5107
+ _getTimestampPairIndex(queryIndex) {
5108
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
5109
+ throw new Error("Query index is out of bounds");
4655
5110
  }
4656
- return resultAvailable;
5111
+ return Math.floor(queryIndex / 2);
4657
5112
  }
4658
- // Timing query is disjoint, i.e. results are invalid
4659
- isTimerDisjoint() {
4660
- return this.device.gl.getParameter(36795);
5113
+ _isTimestampPairAvailable(pairIndex) {
5114
+ const pair = this._timestampPairs[pairIndex];
5115
+ if (!pair || pair.completedQueries.length === 0) {
5116
+ return false;
5117
+ }
5118
+ return this._pollQueryAvailability(pair.completedQueries[0]);
4661
5119
  }
4662
- // Returns query result.
4663
- getResult() {
4664
- return this.device.gl.getQueryParameter(this.handle, 34918);
5120
+ _pollQueryAvailability(query) {
5121
+ if (query.result !== null || query.disjoint) {
5122
+ return true;
5123
+ }
5124
+ const resultAvailable = this.device.gl.getQueryParameter(query.handle, 34919);
5125
+ if (!resultAvailable) {
5126
+ return false;
5127
+ }
5128
+ const isDisjoint = Boolean(this.device.gl.getParameter(36795));
5129
+ query.disjoint = isDisjoint;
5130
+ query.result = isDisjoint ? 0n : BigInt(this.device.gl.getQueryParameter(query.handle, 34918));
5131
+ return true;
4665
5132
  }
4666
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
4667
- getTimerMilliseconds() {
4668
- return this.getResult() / 1e6;
5133
+ async _consumeTimestampPairResult(pairIndex) {
5134
+ const pair = this._timestampPairs[pairIndex];
5135
+ if (!pair || pair.completedQueries.length === 0) {
5136
+ throw new Error("Timestamp query pair has no completed result");
5137
+ }
5138
+ const query = pair.completedQueries.shift();
5139
+ try {
5140
+ return await this._consumeQueryResult(query);
5141
+ } finally {
5142
+ this.device.gl.deleteQuery(query.handle);
5143
+ }
4669
5144
  }
4670
- // Polls the query
4671
- pollQuery(limit = Number.POSITIVE_INFINITY) {
4672
- if (this._pollingPromise) {
4673
- return this._pollingPromise;
5145
+ _consumeQueryResult(query) {
5146
+ if (query.promise) {
5147
+ return query.promise;
4674
5148
  }
4675
- let counter = 0;
4676
- this._pollingPromise = new Promise((resolve, reject) => {
5149
+ query.promise = new Promise((resolve, reject) => {
4677
5150
  const poll = () => {
4678
- if (this.isResultAvailable()) {
4679
- resolve(this.getResult());
4680
- this._pollingPromise = null;
4681
- } else if (counter++ > limit) {
4682
- reject("Timed out");
4683
- this._pollingPromise = null;
4684
- } else {
5151
+ if (!this._pollQueryAvailability(query)) {
4685
5152
  requestAnimationFrame(poll);
5153
+ return;
5154
+ }
5155
+ query.promise = null;
5156
+ if (query.disjoint) {
5157
+ reject(new Error("GPU timestamp query was invalidated by a disjoint event"));
5158
+ } else {
5159
+ resolve(query.result || 0n);
4686
5160
  }
4687
5161
  };
4688
- requestAnimationFrame(poll);
5162
+ poll();
4689
5163
  });
4690
- return this._pollingPromise;
5164
+ return query.promise;
4691
5165
  }
4692
5166
  };
4693
5167
  }
4694
5168
  });
4695
5169
 
4696
5170
  // dist/adapter/resources/webgl-fence.js
4697
- var import_core23, WEBGLFence;
5171
+ var import_core25, WEBGLFence;
4698
5172
  var init_webgl_fence = __esm({
4699
5173
  "dist/adapter/resources/webgl-fence.js"() {
4700
5174
  "use strict";
4701
- import_core23 = require("@luma.gl/core");
4702
- WEBGLFence = class extends import_core23.Fence {
5175
+ import_core25 = require("@luma.gl/core");
5176
+ WEBGLFence = class extends import_core25.Fence {
4703
5177
  device;
4704
5178
  gl;
4705
5179
  handle;
@@ -4784,11 +5258,11 @@ function glTypeToBytes(type) {
4784
5258
  return 0;
4785
5259
  }
4786
5260
  }
4787
- var import_constants26;
5261
+ var import_constants27;
4788
5262
  var init_format_utils = __esm({
4789
5263
  "dist/adapter/helpers/format-utils.js"() {
4790
5264
  "use strict";
4791
- import_constants26 = require("@luma.gl/constants");
5265
+ import_constants27 = require("@luma.gl/constants");
4792
5266
  }
4793
5267
  });
4794
5268
 
@@ -4822,7 +5296,7 @@ function readPixelsToArray(source, options) {
4822
5296
  sourceFormat ||= (texture == null ? void 0 : texture.glFormat) || 6408;
4823
5297
  sourceType ||= (texture == null ? void 0 : texture.glType) || 5121;
4824
5298
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
4825
- const signedType = (0, import_core24.getDataType)(target2);
5299
+ const signedType = (0, import_core26.getDataType)(target2);
4826
5300
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
4827
5301
  const prevHandle = gl.bindFramebuffer(36160, handle);
4828
5302
  gl.readBuffer(36064 + sourceAttachment);
@@ -4865,7 +5339,7 @@ function readPixelsToBuffer(source, options) {
4865
5339
  return webglBufferTarget;
4866
5340
  }
4867
5341
  function getFramebuffer2(source) {
4868
- if (!(source instanceof import_core24.Framebuffer)) {
5342
+ if (!(source instanceof import_core26.Framebuffer)) {
4869
5343
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
4870
5344
  }
4871
5345
  return { framebuffer: source, deleteFramebuffer: false };
@@ -4887,16 +5361,16 @@ function getPixelArray(pixelArray, glType, glFormat, width, height, depth) {
4887
5361
  }
4888
5362
  glType ||= 5121;
4889
5363
  const shaderType = convertGLDataTypeToDataType(glType);
4890
- const ArrayType = (0, import_core24.getTypedArrayConstructor)(shaderType);
5364
+ const ArrayType = (0, import_core26.getTypedArrayConstructor)(shaderType);
4891
5365
  const components = glFormatToComponents(glFormat);
4892
5366
  return new ArrayType(width * height * components);
4893
5367
  }
4894
- var import_core24, import_constants27;
5368
+ var import_core26, import_constants28;
4895
5369
  var init_webgl_texture_utils = __esm({
4896
5370
  "dist/adapter/helpers/webgl-texture-utils.js"() {
4897
5371
  "use strict";
4898
- import_core24 = require("@luma.gl/core");
4899
- import_constants27 = require("@luma.gl/constants");
5372
+ import_core26 = require("@luma.gl/core");
5373
+ import_constants28 = require("@luma.gl/constants");
4900
5374
  init_webgl_shadertypes();
4901
5375
  init_format_utils();
4902
5376
  init_shader_formats();
@@ -4942,17 +5416,19 @@ function compareConstantArrayValues2(v1, v2) {
4942
5416
  }
4943
5417
  return true;
4944
5418
  }
4945
- var import_core25, WebGLDevice;
5419
+ var import_core27, WebGLDevice;
4946
5420
  var init_webgl_device = __esm({
4947
5421
  "dist/adapter/webgl-device.js"() {
4948
5422
  "use strict";
4949
- import_core25 = require("@luma.gl/core");
5423
+ import_core27 = require("@luma.gl/core");
4950
5424
  init_webgl_state_tracker();
4951
5425
  init_create_browser_context();
5426
+ init_webgl_context_data();
4952
5427
  init_webgl_device_info();
4953
5428
  init_webgl_device_features();
4954
5429
  init_webgl_device_limits();
4955
5430
  init_webgl_canvas_context();
5431
+ init_webgl_presentation_context();
4956
5432
  init_spector();
4957
5433
  init_webgl_developer_tools();
4958
5434
  init_webgl_texture_table();
@@ -4963,6 +5439,7 @@ var init_webgl_device = __esm({
4963
5439
  init_webgl_texture();
4964
5440
  init_webgl_framebuffer();
4965
5441
  init_webgl_render_pipeline();
5442
+ init_webgl_shared_render_pipeline();
4966
5443
  init_webgl_command_encoder();
4967
5444
  init_webgl_vertex_array();
4968
5445
  init_webgl_transform_feedback();
@@ -4972,7 +5449,14 @@ var init_webgl_device = __esm({
4972
5449
  init_unified_parameter_api();
4973
5450
  init_with_parameters();
4974
5451
  init_webgl_extensions();
4975
- WebGLDevice = class extends import_core25.Device {
5452
+ WebGLDevice = class extends import_core27.Device {
5453
+ static getDeviceFromContext(gl) {
5454
+ var _a;
5455
+ if (!gl) {
5456
+ return null;
5457
+ }
5458
+ return ((_a = gl.luma) == null ? void 0 : _a.device) ?? null;
5459
+ }
4976
5460
  // Public `Device` API
4977
5461
  /** type of this device */
4978
5462
  type = "webgl";
@@ -4994,7 +5478,7 @@ var init_webgl_device = __esm({
4994
5478
  // @ts-ignore TODO fix
4995
5479
  _constants;
4996
5480
  /** State used by luma.gl classes - TODO - not used? */
4997
- _extensions = {};
5481
+ extensions;
4998
5482
  _polyfilled = false;
4999
5483
  /** Instance of Spector.js (if initialized) */
5000
5484
  spectorJS;
@@ -5016,13 +5500,14 @@ var init_webgl_device = __esm({
5016
5500
  }
5017
5501
  }
5018
5502
  constructor(props) {
5019
- var _a, _b;
5503
+ var _a;
5020
5504
  super({ ...props, id: props.id || uid("webgl-device") });
5021
- const canvasContextProps = import_core25.Device._getCanvasContextProps(props);
5505
+ const canvasContextProps = import_core27.Device._getCanvasContextProps(props);
5022
5506
  if (!canvasContextProps) {
5023
5507
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5024
5508
  }
5025
- let device = (_b = (_a = canvasContextProps.canvas) == null ? void 0 : _a.gl) == null ? void 0 : _b.device;
5509
+ const existingContext = ((_a = canvasContextProps.canvas) == null ? void 0 : _a.gl) ?? null;
5510
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5026
5511
  if (device) {
5027
5512
  throw new Error(`WebGL context already attached to device ${device.id}`);
5028
5513
  }
@@ -5055,10 +5540,11 @@ var init_webgl_device = __esm({
5055
5540
  if (!gl) {
5056
5541
  throw new Error("WebGL context creation failed");
5057
5542
  }
5058
- device = gl.device;
5543
+ device = WebGLDevice.getDeviceFromContext(gl);
5059
5544
  if (device) {
5060
5545
  if (props._reuseDevices) {
5061
- import_core25.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
5546
+ import_core27.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
5547
+ this.canvasContext.destroy();
5062
5548
  device._reused = true;
5063
5549
  return device;
5064
5550
  }
@@ -5067,25 +5553,28 @@ var init_webgl_device = __esm({
5067
5553
  this.handle = gl;
5068
5554
  this.gl = gl;
5069
5555
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5070
- this.gl.device = this;
5071
- this.info = getDeviceInfo(this.gl, this._extensions);
5556
+ const contextData = getWebGLContextData(this.handle);
5557
+ contextData.device = this;
5558
+ this.extensions = contextData.extensions || (contextData.extensions = {});
5559
+ this.info = getDeviceInfo(this.gl, this.extensions);
5072
5560
  this.limits = new WebGLDeviceLimits(this.gl);
5073
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
5561
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5074
5562
  if (this.props._initializeFeatures) {
5075
5563
  this.features.initializeFeatures();
5076
5564
  }
5077
5565
  const glState = new WebGLStateTracker(this.gl, {
5078
- log: (...args) => import_core25.log.log(1, ...args)()
5566
+ log: (...args) => import_core27.log.log(1, ...args)()
5079
5567
  });
5080
5568
  glState.trackState(this.gl, { copyState: false });
5081
5569
  if (props.debug || props.debugWebGL) {
5082
5570
  this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
5083
- import_core25.log.warn("WebGL debug mode activated. Performance reduced.")();
5571
+ import_core27.log.warn("WebGL debug mode activated. Performance reduced.")();
5084
5572
  }
5085
5573
  if (props.debugWebGL) {
5086
- import_core25.log.level = Math.max(import_core25.log.level, 1);
5574
+ import_core27.log.level = Math.max(import_core27.log.level, 1);
5087
5575
  }
5088
5576
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
5577
+ this.canvasContext._startObservers();
5089
5578
  }
5090
5579
  /**
5091
5580
  * Destroys the device
@@ -5098,8 +5587,11 @@ var init_webgl_device = __esm({
5098
5587
  * browser API for destroying WebGL contexts.
5099
5588
  */
5100
5589
  destroy() {
5590
+ var _a;
5591
+ (_a = this.commandEncoder) == null ? void 0 : _a.destroy();
5101
5592
  if (!this.props._reuseDevices && !this._reused) {
5102
- delete this.gl.device;
5593
+ const contextData = getWebGLContextData(this.handle);
5594
+ contextData.device = null;
5103
5595
  }
5104
5596
  }
5105
5597
  get isLost() {
@@ -5109,6 +5601,9 @@ var init_webgl_device = __esm({
5109
5601
  createCanvasContext(props) {
5110
5602
  throw new Error("WebGL only supports a single canvas");
5111
5603
  }
5604
+ createPresentationContext(props) {
5605
+ return new WebGLPresentationContext(this, props || {});
5606
+ }
5112
5607
  createBuffer(props) {
5113
5608
  const newProps = this._normalizeBufferProps(props);
5114
5609
  return new WEBGLBuffer(this, newProps);
@@ -5143,6 +5638,9 @@ var init_webgl_device = __esm({
5143
5638
  createRenderPipeline(props) {
5144
5639
  return new WEBGLRenderPipeline(this, props);
5145
5640
  }
5641
+ _createSharedRenderPipelineWebGL(props) {
5642
+ return new WEBGLSharedRenderPipeline(this, props);
5643
+ }
5146
5644
  createComputePipeline(props) {
5147
5645
  throw new Error("ComputePipeline not supported in WebGL");
5148
5646
  }
@@ -5155,12 +5653,27 @@ var init_webgl_device = __esm({
5155
5653
  * Chrome's offscreen canvas does not require gl.commit
5156
5654
  */
5157
5655
  submit(commandBuffer) {
5656
+ let submittedCommandEncoder = null;
5158
5657
  if (!commandBuffer) {
5159
- commandBuffer = this.commandEncoder.finish();
5658
+ submittedCommandEncoder = this.commandEncoder;
5659
+ commandBuffer = submittedCommandEncoder.finish();
5160
5660
  this.commandEncoder.destroy();
5161
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
5661
+ this.commandEncoder = this.createCommandEncoder({
5662
+ id: submittedCommandEncoder.props.id,
5663
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
5664
+ });
5665
+ }
5666
+ try {
5667
+ commandBuffer._executeCommands();
5668
+ if (submittedCommandEncoder) {
5669
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
5670
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
5671
+ }).catch(() => {
5672
+ });
5673
+ }
5674
+ } finally {
5675
+ commandBuffer.destroy();
5162
5676
  }
5163
- commandBuffer._executeCommands();
5164
5677
  }
5165
5678
  //
5166
5679
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5183,11 +5696,11 @@ var init_webgl_device = __esm({
5183
5696
  return withGLParameters(this.gl, parameters, func);
5184
5697
  }
5185
5698
  resetWebGL() {
5186
- import_core25.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5699
+ import_core27.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5187
5700
  resetGLParameters(this.gl);
5188
5701
  }
5189
5702
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5190
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
5703
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5191
5704
  }
5192
5705
  //
5193
5706
  // WebGL-only API (not part of `Device` API)
@@ -5256,7 +5769,7 @@ var init_webgl_device = __esm({
5256
5769
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5257
5770
  const currentConstant = this._constants[location];
5258
5771
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5259
- import_core25.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
5772
+ import_core27.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
5260
5773
  }
5261
5774
  this._constants[location] = constant;
5262
5775
  switch (constant.constructor) {
@@ -5275,8 +5788,8 @@ var init_webgl_device = __esm({
5275
5788
  }
5276
5789
  /** Ensure extensions are only requested once */
5277
5790
  getExtension(name) {
5278
- getWebGLExtension(this.gl, name, this._extensions);
5279
- return this._extensions;
5791
+ getWebGLExtension(this.gl, name, this.extensions);
5792
+ return this.extensions;
5280
5793
  }
5281
5794
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
5282
5795
  /**
@@ -5299,21 +5812,21 @@ function isWebGL(gl) {
5299
5812
  }
5300
5813
  return Boolean(gl && typeof gl.createVertexArray === "function");
5301
5814
  }
5302
- var import_core26, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
5815
+ var import_core28, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
5303
5816
  var init_webgl_adapter = __esm({
5304
5817
  "dist/adapter/webgl-adapter.js"() {
5305
5818
  "use strict";
5306
- import_core26 = require("@luma.gl/core");
5819
+ import_core28 = require("@luma.gl/core");
5307
5820
  init_polyfill_webgl1_extensions();
5308
5821
  init_spector();
5309
5822
  init_webgl_developer_tools();
5310
5823
  LOG_LEVEL2 = 1;
5311
- WebGLAdapter = class extends import_core26.Adapter {
5824
+ WebGLAdapter = class extends import_core28.Adapter {
5312
5825
  /** type of device's created by this adapter */
5313
5826
  type = "webgl";
5314
5827
  constructor() {
5315
5828
  super();
5316
- import_core26.Device.defaultProps = { ...import_core26.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
5829
+ import_core28.Device.defaultProps = { ...import_core28.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
5317
5830
  }
5318
5831
  /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
5319
5832
  enforceWebGL2(enable2) {
@@ -5328,7 +5841,7 @@ var init_webgl_adapter = __esm({
5328
5841
  return true;
5329
5842
  }
5330
5843
  if (typeof WebGLRenderingContext !== "undefined" && handle instanceof WebGLRenderingContext) {
5331
- import_core26.log.warn("WebGL1 is not supported", handle)();
5844
+ import_core28.log.warn("WebGL1 is not supported", handle)();
5332
5845
  }
5333
5846
  return false;
5334
5847
  }
@@ -5344,8 +5857,9 @@ var init_webgl_adapter = __esm({
5344
5857
  if (gl instanceof WebGLDevice2) {
5345
5858
  return gl;
5346
5859
  }
5347
- if ((gl == null ? void 0 : gl.device) instanceof WebGLDevice2) {
5348
- return gl.device;
5860
+ const existingDevice = WebGLDevice2.getDeviceFromContext(gl);
5861
+ if (existingDevice) {
5862
+ return existingDevice;
5349
5863
  }
5350
5864
  if (!isWebGL(gl)) {
5351
5865
  throw new Error("Invalid WebGL2RenderingContext");
@@ -5369,19 +5883,19 @@ var init_webgl_adapter = __esm({
5369
5883
  const results = await Promise.allSettled(promises);
5370
5884
  for (const result of results) {
5371
5885
  if (result.status === "rejected") {
5372
- import_core26.log.error(`Failed to initialize debug libraries ${result.reason}`)();
5886
+ import_core28.log.error(`Failed to initialize debug libraries ${result.reason}`)();
5373
5887
  }
5374
5888
  }
5375
5889
  try {
5376
5890
  const device = new WebGLDevice2(props);
5377
- import_core26.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
5891
+ import_core28.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
5378
5892
  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}`;
5379
- import_core26.log.probe(LOG_LEVEL2, message2)();
5380
- import_core26.log.table(LOG_LEVEL2, device.info)();
5893
+ import_core28.log.probe(LOG_LEVEL2, message2)();
5894
+ import_core28.log.table(LOG_LEVEL2, device.info)();
5381
5895
  return device;
5382
5896
  } finally {
5383
- import_core26.log.groupEnd(LOG_LEVEL2)();
5384
- import_core26.log.info(LOG_LEVEL2, `%cWebGL call tracing: luma.log.set('debug-webgl') `, "color: white; background: blue; padding: 2px 6px; border-radius: 3px;")();
5897
+ import_core28.log.groupEnd(LOG_LEVEL2)();
5898
+ import_core28.log.info(LOG_LEVEL2, `%cWebGL call tracing: luma.log.set('debug-webgl') `, "color: white; background: blue; padding: 2px 6px; border-radius: 3px;")();
5385
5899
  }
5386
5900
  }
5387
5901
  };