@luma.gl/webgl 9.3.0-alpha.4 → 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 (68) 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 +16 -17
  11. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  12. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgl-buffer.js +19 -4
  14. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  15. package/dist/adapter/resources/webgl-command-buffer.d.ts +2 -2
  16. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-command-buffer.js +2 -2
  18. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  19. package/dist/adapter/resources/webgl-command-encoder.d.ts +5 -4
  20. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-command-encoder.js +20 -7
  22. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  23. package/dist/adapter/resources/webgl-query-set.d.ts +29 -31
  24. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-query-set.js +193 -97
  26. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  27. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  28. package/dist/adapter/resources/webgl-render-pass.js +12 -0
  29. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  30. package/dist/adapter/resources/webgl-render-pipeline.d.ts +13 -19
  31. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  32. package/dist/adapter/resources/webgl-render-pipeline.js +35 -152
  33. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  34. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  35. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  36. package/dist/adapter/resources/webgl-shared-render-pipeline.js +152 -0
  37. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  38. package/dist/adapter/resources/webgl-texture.d.ts +23 -4
  39. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  40. package/dist/adapter/resources/webgl-texture.js +203 -100
  41. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  42. package/dist/adapter/webgl-device.d.ts +4 -2
  43. package/dist/adapter/webgl-device.d.ts.map +1 -1
  44. package/dist/adapter/webgl-device.js +31 -3
  45. package/dist/adapter/webgl-device.js.map +1 -1
  46. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  47. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  48. package/dist/adapter/webgl-presentation-context.js +64 -0
  49. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  50. package/dist/dist.dev.js +1332 -788
  51. package/dist/dist.min.js +2 -2
  52. package/dist/index.cjs +1247 -797
  53. package/dist/index.cjs.map +4 -4
  54. package/package.json +3 -3
  55. package/src/adapter/converters/webgl-texture-table.ts +159 -47
  56. package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
  57. package/src/adapter/device-helpers/webgl-device-info.ts +6 -0
  58. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +18 -19
  59. package/src/adapter/resources/webgl-buffer.ts +16 -4
  60. package/src/adapter/resources/webgl-command-buffer.ts +3 -2
  61. package/src/adapter/resources/webgl-command-encoder.ts +22 -7
  62. package/src/adapter/resources/webgl-query-set.ts +229 -102
  63. package/src/adapter/resources/webgl-render-pass.ts +13 -0
  64. package/src/adapter/resources/webgl-render-pipeline.ts +45 -179
  65. package/src/adapter/resources/webgl-shared-render-pipeline.ts +208 -0
  66. package/src/adapter/resources/webgl-texture.ts +326 -121
  67. package/src/adapter/webgl-device.ts +40 -4
  68. package/src/adapter/webgl-presentation-context.ts +93 -0
package/dist/index.cjs CHANGED
@@ -1157,6 +1157,8 @@ function identifyGPUType(vendor, renderer) {
1157
1157
  }
1158
1158
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1159
1159
  switch (gpuVendor) {
1160
+ case "apple":
1161
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1160
1162
  case "intel":
1161
1163
  return "integrated";
1162
1164
  case "software":
@@ -1167,6 +1169,9 @@ function identifyGPUType(vendor, renderer) {
1167
1169
  return "discrete";
1168
1170
  }
1169
1171
  }
1172
+ function isAppleSiliconGPU(vendor, renderer) {
1173
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1174
+ }
1170
1175
  var import_constants4;
1171
1176
  var init_webgl_device_info = __esm({
1172
1177
  "dist/adapter/device-helpers/webgl-device-info.js"() {
@@ -1219,8 +1224,23 @@ function isTextureFeature(feature) {
1219
1224
  return feature in TEXTURE_FEATURES;
1220
1225
  }
1221
1226
  function checkTextureFeature(gl, feature, extensions) {
1222
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1223
- 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)));
1224
1244
  }
1225
1245
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1226
1246
  let supported = formatSupport.create;
@@ -1231,12 +1251,17 @@ function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1231
1251
  if (webglFormatInfo == null ? void 0 : webglFormatInfo.x) {
1232
1252
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1233
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);
1234
1259
  return {
1235
1260
  format: formatSupport.format,
1236
1261
  // @ts-ignore
1237
1262
  create: supported && formatSupport.create,
1238
1263
  // @ts-ignore
1239
- render: supported && formatSupport.render,
1264
+ render: renderable,
1240
1265
  // @ts-ignore
1241
1266
  filter: supported && formatSupport.filter,
1242
1267
  // @ts-ignore
@@ -1245,6 +1270,45 @@ function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1245
1270
  store: supported && formatSupport.store
1246
1271
  };
1247
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
+ }
1248
1312
  function getTextureFormatWebGL(format) {
1249
1313
  var _a;
1250
1314
  const formatData = WEBGL_TEXTURE_FORMATS[format];
@@ -1301,7 +1365,7 @@ function convertTextureFormatToGL(format) {
1301
1365
  }
1302
1366
  return webglFormat;
1303
1367
  }
1304
- 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;
1305
1369
  var init_webgl_texture_table = __esm({
1306
1370
  "dist/adapter/converters/webgl-texture-table.js"() {
1307
1371
  "use strict";
@@ -1321,44 +1385,51 @@ var init_webgl_texture_table = __esm({
1321
1385
  EXT_texture_norm16 = "EXT_texture_norm16";
1322
1386
  EXT_render_snorm = "EXT_render_snorm";
1323
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";
1324
1394
  TEXTURE_FEATURES = {
1325
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1326
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1327
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1328
- "snorm8-renderable-webgl": [EXT_render_snorm],
1329
- "norm16-renderable-webgl": [EXT_texture_norm16],
1330
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1331
- "float32-filterable": ["OES_texture_float_linear"],
1332
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1333
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1334
- "texture-blend-float-webgl": ["EXT_float_blend"],
1335
- "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] },
1336
1407
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1337
1408
  // 'texture-compression-bc3-webgl': [X_S3TC],
1338
- "texture-compression-bc5-webgl": [X_RGTC],
1339
- "texture-compression-bc7-webgl": [X_BPTC],
1340
- "texture-compression-etc2": [X_ETC2],
1341
- "texture-compression-astc": [X_ASTC],
1342
- "texture-compression-etc1-webgl": [X_ETC1],
1343
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1344
- "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] }
1345
1416
  };
1346
1417
  WEBGL_TEXTURE_FORMATS = {
1347
1418
  // 8-bit formats
1348
1419
  "r8unorm": { gl: 33321, rb: true },
1349
- "r8snorm": { gl: 36756 },
1420
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1350
1421
  "r8uint": { gl: 33330, rb: true },
1351
1422
  "r8sint": { gl: 33329, rb: true },
1352
1423
  // 16-bit formats
1353
1424
  "rg8unorm": { gl: 33323, rb: true },
1354
- "rg8snorm": { gl: 36757 },
1425
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1355
1426
  "rg8uint": { gl: 33336, rb: true },
1356
1427
  "rg8sint": { gl: 33335, rb: true },
1357
1428
  "r16uint": { gl: 33332, rb: true },
1358
1429
  "r16sint": { gl: 33331, rb: true },
1359
- "r16float": { gl: 33325, rb: true },
1360
- "r16unorm": { gl: 33322, rb: true },
1361
- "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 },
1362
1433
  // Packed 16-bit formats
1363
1434
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1364
1435
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1369,7 +1440,7 @@ var init_webgl_texture_table = __esm({
1369
1440
  // 32-bit formats
1370
1441
  "rgba8unorm": { gl: 32856 },
1371
1442
  "rgba8unorm-srgb": { gl: 35907 },
1372
- "rgba8snorm": { gl: 36759 },
1443
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1373
1444
  "rgba8uint": { gl: 36220 },
1374
1445
  "rgba8sint": { gl: 36238 },
1375
1446
  // reverse colors, webgpu only
@@ -1377,38 +1448,38 @@ var init_webgl_texture_table = __esm({
1377
1448
  "bgra8unorm-srgb": {},
1378
1449
  "rg16uint": { gl: 33338 },
1379
1450
  "rg16sint": { gl: 33337 },
1380
- "rg16float": { gl: 33327, rb: true },
1381
- "rg16unorm": { gl: 33324 },
1382
- "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 },
1383
1454
  "r32uint": { gl: 33334, rb: true },
1384
1455
  "r32sint": { gl: 33333, rb: true },
1385
- "r32float": { gl: 33326 },
1456
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1386
1457
  // Packed 32-bit formats
1387
- "rgb9e5ufloat": { gl: 35901 },
1458
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1388
1459
  // , filter: true},
1389
1460
  "rg11b10ufloat": { gl: 35898, rb: true },
1390
1461
  "rgb10a2unorm": { gl: 32857, rb: true },
1391
1462
  "rgb10a2uint": { gl: 36975, rb: true },
1392
1463
  // 48-bit formats
1393
- "rgb16unorm-webgl": { gl: 32852 },
1464
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1394
1465
  // rgb not renderable
1395
- "rgb16snorm-webgl": { gl: 36762 },
1466
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1396
1467
  // rgb not renderable
1397
1468
  // 64-bit formats
1398
1469
  "rg32uint": { gl: 33340, rb: true },
1399
1470
  "rg32sint": { gl: 33339, rb: true },
1400
- "rg32float": { gl: 33328, rb: true },
1471
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1401
1472
  "rgba16uint": { gl: 36214, rb: true },
1402
1473
  "rgba16sint": { gl: 36232, rb: true },
1403
- "rgba16float": { gl: 34842 },
1404
- "rgba16unorm": { gl: 32859, rb: true },
1405
- "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 },
1406
1477
  // 96-bit formats (deprecated!)
1407
- "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] },
1408
1479
  // 128-bit formats
1409
1480
  "rgba32uint": { gl: 36208, rb: true },
1410
1481
  "rgba32sint": { gl: 36226, rb: true },
1411
- "rgba32float": { gl: 34836, rb: true },
1482
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1412
1483
  // Depth and stencil formats
1413
1484
  "stencil8": { gl: 36168, rb: true },
1414
1485
  // 8 stencil bits
@@ -1466,8 +1537,8 @@ var init_webgl_texture_table = __esm({
1466
1537
  "astc-8x6-unorm-srgb": { gl: 37846 },
1467
1538
  "astc-8x8-unorm": { gl: 37815 },
1468
1539
  "astc-8x8-unorm-srgb": { gl: 37847 },
1469
- "astc-10x5-unorm": { gl: 37819 },
1470
- "astc-10x5-unorm-srgb": { gl: 37851 },
1540
+ "astc-10x5-unorm": { gl: 37816 },
1541
+ "astc-10x5-unorm-srgb": { gl: 37848 },
1471
1542
  "astc-10x6-unorm": { gl: 37817 },
1472
1543
  "astc-10x6-unorm-srgb": { gl: 37849 },
1473
1544
  "astc-10x8-unorm": { gl: 37818 },
@@ -1481,7 +1552,7 @@ var init_webgl_texture_table = __esm({
1481
1552
  // WEBGL_compressed_texture_pvrtc
1482
1553
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
1483
1554
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
1484
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
1555
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
1485
1556
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
1486
1557
  // WEBGL_compressed_texture_etc1
1487
1558
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -1505,12 +1576,11 @@ var init_webgl_device_features = __esm({
1505
1576
  // optional WebGPU features
1506
1577
  "depth-clip-control": "EXT_depth_clamp",
1507
1578
  // TODO these seem subtly different
1508
- // 'timestamp-query' // GPUQueryType "timestamp-query"
1579
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
1509
1580
  // "indirect-first-instance"
1510
1581
  // Textures are handled by getTextureFeatures()
1511
1582
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
1512
1583
  // optional WebGL features
1513
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
1514
1584
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
1515
1585
  "polygon-mode-webgl": "WEBGL_polygon_mode",
1516
1586
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -1854,6 +1924,61 @@ var init_webgl_canvas_context = __esm({
1854
1924
  }
1855
1925
  });
1856
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
+
1857
1982
  // dist/utils/uid.js
1858
1983
  function uid(id = "id") {
1859
1984
  uidCounters[id] = uidCounters[id] || 1;
@@ -1870,36 +1995,36 @@ var init_uid = __esm({
1870
1995
 
1871
1996
  // dist/adapter/resources/webgl-buffer.js
1872
1997
  function getWebGLTarget(usage) {
1873
- if (usage & import_core8.Buffer.INDEX) {
1998
+ if (usage & import_core9.Buffer.INDEX) {
1874
1999
  return 34963;
1875
2000
  }
1876
- if (usage & import_core8.Buffer.VERTEX) {
2001
+ if (usage & import_core9.Buffer.VERTEX) {
1877
2002
  return 34962;
1878
2003
  }
1879
- if (usage & import_core8.Buffer.UNIFORM) {
2004
+ if (usage & import_core9.Buffer.UNIFORM) {
1880
2005
  return 35345;
1881
2006
  }
1882
2007
  return 34962;
1883
2008
  }
1884
2009
  function getWebGLUsage(usage) {
1885
- if (usage & import_core8.Buffer.INDEX) {
2010
+ if (usage & import_core9.Buffer.INDEX) {
1886
2011
  return 35044;
1887
2012
  }
1888
- if (usage & import_core8.Buffer.VERTEX) {
2013
+ if (usage & import_core9.Buffer.VERTEX) {
1889
2014
  return 35044;
1890
2015
  }
1891
- if (usage & import_core8.Buffer.UNIFORM) {
2016
+ if (usage & import_core9.Buffer.UNIFORM) {
1892
2017
  return 35048;
1893
2018
  }
1894
2019
  return 35044;
1895
2020
  }
1896
- var import_core8, import_constants9, WEBGLBuffer;
2021
+ var import_core9, import_constants9, WEBGLBuffer;
1897
2022
  var init_webgl_buffer = __esm({
1898
2023
  "dist/adapter/resources/webgl-buffer.js"() {
1899
2024
  "use strict";
1900
- import_core8 = require("@luma.gl/core");
2025
+ import_core9 = require("@luma.gl/core");
1901
2026
  import_constants9 = require("@luma.gl/constants");
1902
- WEBGLBuffer = class extends import_core8.Buffer {
2027
+ WEBGLBuffer = class extends import_core9.Buffer {
1903
2028
  device;
1904
2029
  gl;
1905
2030
  handle;
@@ -1934,8 +2059,12 @@ var init_webgl_buffer = __esm({
1934
2059
  destroy() {
1935
2060
  if (!this.destroyed && this.handle) {
1936
2061
  this.removeStats();
1937
- this.trackDeallocatedMemory();
1938
- 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
+ }
1939
2068
  this.destroyed = true;
1940
2069
  this.handle = null;
1941
2070
  }
@@ -1950,7 +2079,11 @@ var init_webgl_buffer = __esm({
1950
2079
  this.bytesUsed = byteLength;
1951
2080
  this.byteLength = byteLength;
1952
2081
  this._setDebugData(data, byteOffset, byteLength);
1953
- this.trackAllocatedMemory(byteLength);
2082
+ if (!this.props.handle) {
2083
+ this.trackAllocatedMemory(byteLength);
2084
+ } else {
2085
+ this.trackReferencedMemory(byteLength, "Buffer");
2086
+ }
1954
2087
  }
1955
2088
  // Allocate a GPU buffer of specified size.
1956
2089
  _initWithByteLength(byteLength) {
@@ -1965,7 +2098,11 @@ var init_webgl_buffer = __esm({
1965
2098
  this.bytesUsed = byteLength;
1966
2099
  this.byteLength = byteLength;
1967
2100
  this._setDebugData(null, 0, byteLength);
1968
- this.trackAllocatedMemory(byteLength);
2101
+ if (!this.props.handle) {
2102
+ this.trackAllocatedMemory(byteLength);
2103
+ } else {
2104
+ this.trackReferencedMemory(byteLength, "Buffer");
2105
+ }
1969
2106
  return this;
1970
2107
  }
1971
2108
  write(data, byteOffset = 0) {
@@ -2079,14 +2216,14 @@ var init_parse_shader_compiler_log = __esm({
2079
2216
  });
2080
2217
 
2081
2218
  // dist/adapter/resources/webgl-shader.js
2082
- var import_core9, import_constants10, WEBGLShader;
2219
+ var import_core10, import_constants10, WEBGLShader;
2083
2220
  var init_webgl_shader = __esm({
2084
2221
  "dist/adapter/resources/webgl-shader.js"() {
2085
2222
  "use strict";
2086
- import_core9 = require("@luma.gl/core");
2223
+ import_core10 = require("@luma.gl/core");
2087
2224
  import_constants10 = require("@luma.gl/constants");
2088
2225
  init_parse_shader_compiler_log();
2089
- WEBGLShader = class extends import_core9.Shader {
2226
+ WEBGLShader = class extends import_core10.Shader {
2090
2227
  device;
2091
2228
  handle;
2092
2229
  constructor(device, props) {
@@ -2152,9 +2289,9 @@ ${source}`;
2152
2289
  }
2153
2290
  return;
2154
2291
  }
2155
- import_core9.log.once(1, "Shader compilation is asynchronous")();
2292
+ import_core10.log.once(1, "Shader compilation is asynchronous")();
2156
2293
  await this._waitForCompilationComplete();
2157
- 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}`)();
2158
2295
  this._getCompilationStatus();
2159
2296
  this.debugShader();
2160
2297
  }
@@ -2315,7 +2452,7 @@ function setDeviceParameters(device, parameters) {
2315
2452
  gl.stencilMaskSeparate(1029, mask);
2316
2453
  }
2317
2454
  if (parameters.stencilReadMask) {
2318
- import_core10.log.warn("stencilReadMask not supported under WebGL");
2455
+ import_core11.log.warn("stencilReadMask not supported under WebGL");
2319
2456
  }
2320
2457
  if (parameters.stencilCompare) {
2321
2458
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2428,11 +2565,11 @@ function isObjectEmpty2(obj) {
2428
2565
  }
2429
2566
  return isEmpty;
2430
2567
  }
2431
- var import_core10, import_constants11;
2568
+ var import_core11, import_constants11;
2432
2569
  var init_device_parameters = __esm({
2433
2570
  "dist/adapter/converters/device-parameters.js"() {
2434
2571
  "use strict";
2435
- import_core10 = require("@luma.gl/core");
2572
+ import_core11 = require("@luma.gl/core");
2436
2573
  import_constants11 = require("@luma.gl/constants");
2437
2574
  init_unified_parameter_api();
2438
2575
  }
@@ -2525,14 +2662,14 @@ var init_sampler_parameters = __esm({
2525
2662
  });
2526
2663
 
2527
2664
  // dist/adapter/resources/webgl-sampler.js
2528
- var import_core11, import_constants13, WEBGLSampler;
2665
+ var import_core12, import_constants13, WEBGLSampler;
2529
2666
  var init_webgl_sampler = __esm({
2530
2667
  "dist/adapter/resources/webgl-sampler.js"() {
2531
2668
  "use strict";
2532
- import_core11 = require("@luma.gl/core");
2669
+ import_core12 = require("@luma.gl/core");
2533
2670
  import_constants13 = require("@luma.gl/constants");
2534
2671
  init_sampler_parameters();
2535
- WEBGLSampler = class extends import_core11.Sampler {
2672
+ WEBGLSampler = class extends import_core12.Sampler {
2536
2673
  device;
2537
2674
  handle;
2538
2675
  parameters;
@@ -2608,19 +2745,19 @@ var init_with_parameters = __esm({
2608
2745
  });
2609
2746
 
2610
2747
  // dist/adapter/resources/webgl-texture-view.js
2611
- var import_core12, WEBGLTextureView;
2748
+ var import_core13, WEBGLTextureView;
2612
2749
  var init_webgl_texture_view = __esm({
2613
2750
  "dist/adapter/resources/webgl-texture-view.js"() {
2614
2751
  "use strict";
2615
- import_core12 = require("@luma.gl/core");
2616
- WEBGLTextureView = class extends import_core12.TextureView {
2752
+ import_core13 = require("@luma.gl/core");
2753
+ WEBGLTextureView = class extends import_core13.TextureView {
2617
2754
  device;
2618
2755
  gl;
2619
2756
  handle;
2620
2757
  // Does not have a WebGL representation
2621
2758
  texture;
2622
2759
  constructor(device, props) {
2623
- super(device, { ...import_core12.Texture.defaultProps, ...props });
2760
+ super(device, { ...import_core13.Texture.defaultProps, ...props });
2624
2761
  this.device = device;
2625
2762
  this.gl = this.device.gl;
2626
2763
  this.handle = null;
@@ -2630,98 +2767,15 @@ var init_webgl_texture_view = __esm({
2630
2767
  }
2631
2768
  });
2632
2769
 
2633
- // dist/adapter/converters/webgl-shadertypes.js
2634
- function convertDataTypeToGLDataType(normalizedType) {
2635
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
2636
- }
2637
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
2638
- return WEBGL_SHADER_TYPES[glUniformType];
2639
- }
2640
- function isGLSamplerType(type) {
2641
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
2642
- }
2643
- function getTextureBindingFromGLSamplerType(glSamplerType) {
2644
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
2645
- }
2646
- var import_constants14, WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
2647
- var init_webgl_shadertypes = __esm({
2648
- "dist/adapter/converters/webgl-shadertypes.js"() {
2649
- "use strict";
2650
- import_constants14 = require("@luma.gl/constants");
2651
- WEBGL_SHADER_TYPES = {
2652
- [5126]: "f32",
2653
- [35664]: "vec2<f32>",
2654
- [35665]: "vec3<f32>",
2655
- [35666]: "vec4<f32>",
2656
- [5124]: "i32",
2657
- [35667]: "vec2<i32>",
2658
- [35668]: "vec3<i32>",
2659
- [35669]: "vec4<i32>",
2660
- [5125]: "u32",
2661
- [36294]: "vec2<u32>",
2662
- [36295]: "vec3<u32>",
2663
- [36296]: "vec4<u32>",
2664
- [35670]: "f32",
2665
- [35671]: "vec2<f32>",
2666
- [35672]: "vec3<f32>",
2667
- [35673]: "vec4<f32>",
2668
- // TODO - are sizes/components below correct?
2669
- [35674]: "mat2x2<f32>",
2670
- [35685]: "mat2x3<f32>",
2671
- [35686]: "mat2x4<f32>",
2672
- [35687]: "mat3x2<f32>",
2673
- [35675]: "mat3x3<f32>",
2674
- [35688]: "mat3x4<f32>",
2675
- [35689]: "mat4x2<f32>",
2676
- [35690]: "mat4x3<f32>",
2677
- [35676]: "mat4x4<f32>"
2678
- };
2679
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
2680
- [35678]: { viewDimension: "2d", sampleType: "float" },
2681
- [35680]: { viewDimension: "cube", sampleType: "float" },
2682
- [35679]: { viewDimension: "3d", sampleType: "float" },
2683
- [35682]: { viewDimension: "3d", sampleType: "depth" },
2684
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
2685
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
2686
- [36293]: { viewDimension: "cube", sampleType: "float" },
2687
- [36298]: { viewDimension: "2d", sampleType: "sint" },
2688
- [36299]: { viewDimension: "3d", sampleType: "sint" },
2689
- [36300]: { viewDimension: "cube", sampleType: "sint" },
2690
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
2691
- [36306]: { viewDimension: "2d", sampleType: "uint" },
2692
- [36307]: { viewDimension: "3d", sampleType: "uint" },
2693
- [36308]: { viewDimension: "cube", sampleType: "uint" },
2694
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
2695
- };
2696
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
2697
- uint8: 5121,
2698
- sint8: 5120,
2699
- unorm8: 5121,
2700
- snorm8: 5120,
2701
- uint16: 5123,
2702
- sint16: 5122,
2703
- unorm16: 5123,
2704
- snorm16: 5122,
2705
- uint32: 5125,
2706
- sint32: 5124,
2707
- // WebGPU does not support normalized 32 bit integer attributes
2708
- // 'unorm32': GL.UNSIGNED_INT,
2709
- // 'snorm32': GL.INT,
2710
- float16: 5131,
2711
- float32: 5126
2712
- };
2713
- }
2714
- });
2715
-
2716
2770
  // dist/adapter/converters/shader-formats.js
2717
2771
  function convertGLDataTypeToDataType(type) {
2718
2772
  return GL_DATA_TYPE_MAP[type];
2719
2773
  }
2720
- var import_constants15, GL_DATA_TYPE_MAP;
2774
+ var import_constants14, GL_DATA_TYPE_MAP;
2721
2775
  var init_shader_formats = __esm({
2722
2776
  "dist/adapter/converters/shader-formats.js"() {
2723
2777
  "use strict";
2724
- import_constants15 = require("@luma.gl/constants");
2778
+ import_constants14 = require("@luma.gl/constants");
2725
2779
  GL_DATA_TYPE_MAP = {
2726
2780
  [5124]: "sint32",
2727
2781
  [5125]: "uint32",
@@ -2744,6 +2798,18 @@ var init_shader_formats = __esm({
2744
2798
  });
2745
2799
 
2746
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
+ }
2747
2813
  function getWebGLTextureTarget(dimension) {
2748
2814
  switch (dimension) {
2749
2815
  case "1d":
@@ -2764,20 +2830,19 @@ function getWebGLTextureTarget(dimension) {
2764
2830
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
2765
2831
  return dimension === "cube" ? 34069 + level : glTarget;
2766
2832
  }
2767
- var import_core13, import_constants16, import_core14, WEBGLTexture;
2833
+ var import_core14, import_constants15, import_core15, WEBGLTexture;
2768
2834
  var init_webgl_texture = __esm({
2769
2835
  "dist/adapter/resources/webgl-texture.js"() {
2770
2836
  "use strict";
2771
- import_core13 = require("@luma.gl/core");
2772
- import_constants16 = require("@luma.gl/constants");
2837
+ import_core14 = require("@luma.gl/core");
2838
+ import_constants15 = require("@luma.gl/constants");
2773
2839
  init_webgl_texture_table();
2774
2840
  init_sampler_parameters();
2775
2841
  init_with_parameters();
2776
2842
  init_webgl_texture_view();
2777
- init_webgl_shadertypes();
2778
2843
  init_shader_formats();
2779
- import_core14 = require("@luma.gl/core");
2780
- WEBGLTexture = class extends import_core13.Texture {
2844
+ import_core15 = require("@luma.gl/core");
2845
+ WEBGLTexture = class extends import_core14.Texture {
2781
2846
  // readonly MAX_ATTRIBUTES: number;
2782
2847
  device;
2783
2848
  gl;
@@ -2806,8 +2871,10 @@ var init_webgl_texture = __esm({
2806
2871
  // state
2807
2872
  /** Texture binding slot - TODO - move to texture view? */
2808
2873
  _textureUnit = 0;
2809
- /** Chached framebuffer */
2874
+ /** Cached framebuffer reused for color texture readback. */
2810
2875
  _framebuffer = null;
2876
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
2877
+ _framebufferAttachmentKey = null;
2811
2878
  constructor(device, props) {
2812
2879
  super(device, props, { byteAlignment: 1 });
2813
2880
  this.device = device;
@@ -2822,20 +2889,27 @@ var init_webgl_texture = __esm({
2822
2889
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
2823
2890
  this.gl.bindTexture(this.glTarget, this.handle);
2824
2891
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
2825
- switch (dimension) {
2826
- case "2d":
2827
- case "cube":
2828
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
2829
- break;
2830
- case "2d-array":
2831
- case "3d":
2832
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
2833
- break;
2834
- default:
2835
- 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
+ }
2836
2905
  }
2837
2906
  this.gl.bindTexture(this.glTarget, null);
2838
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
+ }
2839
2913
  this.setSampler(this.props.sampler);
2840
2914
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
2841
2915
  Object.seal(this);
@@ -2845,9 +2919,14 @@ var init_webgl_texture = __esm({
2845
2919
  if (this.handle) {
2846
2920
  (_a = this._framebuffer) == null ? void 0 : _a.destroy();
2847
2921
  this._framebuffer = null;
2848
- this.gl.deleteTexture(this.handle);
2922
+ this._framebufferAttachmentKey = null;
2849
2923
  this.removeStats();
2850
- 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
+ }
2851
2930
  this.destroyed = true;
2852
2931
  }
2853
2932
  }
@@ -2886,97 +2965,128 @@ var init_webgl_texture = __esm({
2886
2965
  return { width: options.width, height: options.height };
2887
2966
  }
2888
2967
  copyImageData(options_) {
2889
- const options = this._normalizeCopyImageDataOptions(options_);
2890
- const typedArray = options.data;
2891
- const { width, height, depth, z = 0 } = options;
2892
- 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;
2893
3006
  const { glFormat, glType, compressed } = this;
2894
3007
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
2895
- let unpackRowLength;
2896
- if (!this.compressed) {
2897
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
2898
- if (bytesPerPixel) {
2899
- if (options.bytesPerRow % bytesPerPixel !== 0) {
2900
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
2901
- }
2902
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
2903
- }
3008
+ if (compressed) {
3009
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
2904
3010
  }
2905
- const glParameters = !this.compressed ? {
3011
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3012
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3013
+ const glParameters = {
2906
3014
  [3317]: this.byteAlignment,
2907
3015
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
2908
3016
  [32878]: options.rowsPerImage
2909
- } : {};
3017
+ };
2910
3018
  this.gl.bindTexture(this.glTarget, this.handle);
3019
+ this.gl.bindBuffer(35052, buffer.handle);
2911
3020
  withGLParameters(this.gl, glParameters, () => {
2912
3021
  switch (this.dimension) {
2913
3022
  case "2d":
2914
3023
  case "cube":
2915
- if (compressed) {
2916
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
2917
- } else {
2918
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
2919
- }
3024
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
2920
3025
  break;
2921
3026
  case "2d-array":
2922
3027
  case "3d":
2923
- if (compressed) {
2924
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
2925
- } else {
2926
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
2927
- }
3028
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
2928
3029
  break;
2929
3030
  default:
2930
3031
  }
2931
3032
  });
3033
+ this.gl.bindBuffer(35052, null);
2932
3034
  this.gl.bindTexture(this.glTarget, null);
2933
3035
  }
2934
- readBuffer(options = {}, buffer) {
2935
- throw new Error("readBuffer not implemented");
2936
- }
2937
- async readDataAsync(options = {}) {
2938
- return this.readDataSyncWebGL(options);
2939
- }
2940
- writeBuffer(buffer, options_ = {}) {
2941
- }
2942
3036
  writeData(data, options_ = {}) {
2943
3037
  const options = this._normalizeTextureWriteOptions(options_);
2944
3038
  const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
2945
- const {} = this;
2946
- const { width, height, mipLevel, x, y, z } = options;
3039
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
2947
3040
  const { glFormat, glType, compressed } = this;
2948
- const depth = 0;
2949
- 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
+ }
2950
3049
  const glParameters = !this.compressed ? {
2951
- // WebGL does not require byte alignment, but allows it to be specified
2952
- [3317]: this.byteAlignment
2953
- // [GL.UNPACK_ROW_LENGTH]: bytesPerRow,
2954
- // [GL.UNPACK_IMAGE_HEIGHT]: rowsPerImage
3050
+ [3317]: this.byteAlignment,
3051
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3052
+ [32878]: options.rowsPerImage
2955
3053
  } : {};
2956
- 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);
2957
3059
  this.gl.bindBuffer(35052, null);
2958
3060
  withGLParameters(this.gl, glParameters, () => {
2959
3061
  switch (this.dimension) {
2960
3062
  case "2d":
2961
3063
  case "cube":
2962
3064
  if (compressed) {
2963
- 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
+ }
2964
3070
  } else {
2965
- 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);
2966
3072
  }
2967
3073
  break;
2968
3074
  case "2d-array":
2969
3075
  case "3d":
2970
3076
  if (compressed) {
2971
- 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
+ }
2972
3082
  } else {
2973
- 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);
2974
3084
  }
2975
3085
  break;
2976
3086
  default:
2977
3087
  }
2978
3088
  });
2979
- this.gl.bindTexture(glTarget, null);
3089
+ this.gl.bindTexture(this.glTarget, null);
2980
3090
  }
2981
3091
  // IMPLEMENTATION SPECIFIC
2982
3092
  /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
@@ -2998,50 +3108,105 @@ var init_webgl_texture = __esm({
2998
3108
  }
2999
3109
  // WEBGL SPECIFIC
3000
3110
  readDataSyncWebGL(options_ = {}) {
3001
- const options = this._normalizeTextureReadOptions(options_);
3111
+ const options = this._getSupportedColorReadOptions(options_);
3002
3112
  const memoryLayout = this.computeMemoryLayout(options);
3003
3113
  const shaderType = convertGLDataTypeToDataType(this.glType);
3004
- const ArrayType = (0, import_core14.getTypedArrayConstructor)(shaderType);
3005
- const targetArray = new ArrayType(memoryLayout.byteLength);
3006
- const signedType = (0, import_core14.getDataType)(targetArray);
3007
- const sourceType = convertDataTypeToGLDataType(signedType);
3008
- const framebuffer = this._getFramebuffer();
3009
- const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3010
- this.gl.readBuffer(36064);
3011
- this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, sourceType, targetArray);
3012
- 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
+ });
3013
3120
  return targetArray.buffer;
3014
3121
  }
3015
3122
  /**
3016
- * @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.
3017
3125
  */
3018
- generateMipmapsWebGL(options) {
3019
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3020
- if (!isFilterableAndRenderable) {
3021
- import_core13.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3022
- if (!(options == null ? void 0 : options.force)) {
3023
- return;
3024
- }
3025
- }
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);
3026
3135
  try {
3027
- this.gl.bindTexture(this.glTarget, this.handle);
3028
- this.gl.generateMipmap(this.glTarget);
3029
- } catch (error) {
3030
- import_core13.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
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
+ });
3031
3143
  } finally {
3032
- this.gl.bindTexture(this.glTarget, null);
3144
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3145
+ this.gl.readBuffer(prevReadBuffer);
3033
3146
  }
3034
3147
  }
3035
- // INTERNAL
3036
3148
  /**
3037
- * Sets sampler parameters on texture
3149
+ * Attaches a single color subresource to the cached read framebuffer.
3150
+ *
3151
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3038
3152
  */
3039
- _setSamplerParameters(parameters) {
3040
- import_core13.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3041
- this.gl.bindTexture(this.glTarget, this.handle);
3042
- for (const [pname, pvalue] of Object.entries(parameters)) {
3043
- const param = Number(pname);
3044
- const value = pvalue;
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)) {
3188
+ return;
3189
+ }
3190
+ }
3191
+ try {
3192
+ this.gl.bindTexture(this.glTarget, this.handle);
3193
+ this.gl.generateMipmap(this.glTarget);
3194
+ } catch (error) {
3195
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3196
+ } finally {
3197
+ this.gl.bindTexture(this.glTarget, null);
3198
+ }
3199
+ }
3200
+ // INTERNAL
3201
+ /**
3202
+ * Sets sampler parameters on texture
3203
+ */
3204
+ _setSamplerParameters(parameters) {
3205
+ import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3206
+ this.gl.bindTexture(this.glTarget, this.handle);
3207
+ for (const [pname, pvalue] of Object.entries(parameters)) {
3208
+ const param = Number(pname);
3209
+ const value = pvalue;
3045
3210
  switch (param) {
3046
3211
  case 33082:
3047
3212
  case 33083:
@@ -3094,211 +3259,6 @@ var init_webgl_texture = __esm({
3094
3259
  }
3095
3260
  });
3096
3261
 
3097
- // dist/adapter/helpers/get-shader-layout-from-glsl.js
3098
- function getShaderLayoutFromGLSL(gl, program) {
3099
- const shaderLayout = {
3100
- attributes: [],
3101
- bindings: []
3102
- };
3103
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3104
- const uniformBlocks = readUniformBlocks(gl, program);
3105
- for (const uniformBlock of uniformBlocks) {
3106
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3107
- name: uniform.name,
3108
- format: uniform.format,
3109
- byteOffset: uniform.byteOffset,
3110
- byteStride: uniform.byteStride,
3111
- arrayLength: uniform.arrayLength
3112
- }));
3113
- shaderLayout.bindings.push({
3114
- type: "uniform",
3115
- name: uniformBlock.name,
3116
- group: 0,
3117
- location: uniformBlock.location,
3118
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3119
- minBindingSize: uniformBlock.byteLength,
3120
- uniforms: uniforms2
3121
- });
3122
- }
3123
- const uniforms = readUniformBindings(gl, program);
3124
- let textureUnit = 0;
3125
- for (const uniform of uniforms) {
3126
- if (isGLSamplerType(uniform.type)) {
3127
- const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3128
- shaderLayout.bindings.push({
3129
- type: "texture",
3130
- name: uniform.name,
3131
- group: 0,
3132
- location: textureUnit,
3133
- viewDimension,
3134
- sampleType
3135
- });
3136
- uniform.textureUnit = textureUnit;
3137
- textureUnit += 1;
3138
- }
3139
- }
3140
- if (uniforms.length) {
3141
- shaderLayout.uniforms = uniforms;
3142
- }
3143
- const varyings = readVaryings(gl, program);
3144
- if (varyings == null ? void 0 : varyings.length) {
3145
- shaderLayout.varyings = varyings;
3146
- }
3147
- return shaderLayout;
3148
- }
3149
- function readAttributeDeclarations(gl, program) {
3150
- const attributes = [];
3151
- const count = gl.getProgramParameter(program, 35721);
3152
- for (let index = 0; index < count; index++) {
3153
- const activeInfo = gl.getActiveAttrib(program, index);
3154
- if (!activeInfo) {
3155
- throw new Error("activeInfo");
3156
- }
3157
- const {
3158
- name,
3159
- type: compositeType
3160
- /* , size*/
3161
- } = activeInfo;
3162
- const location = gl.getAttribLocation(program, name);
3163
- if (location >= 0) {
3164
- const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
3165
- const stepMode = /instance/i.test(name) ? "instance" : "vertex";
3166
- attributes.push({
3167
- name,
3168
- location,
3169
- stepMode,
3170
- type: attributeType
3171
- // size - for arrays, size is the number of elements in the array
3172
- });
3173
- }
3174
- }
3175
- attributes.sort((a, b) => a.location - b.location);
3176
- return attributes;
3177
- }
3178
- function readVaryings(gl, program) {
3179
- const varyings = [];
3180
- const count = gl.getProgramParameter(program, 35971);
3181
- for (let location = 0; location < count; location++) {
3182
- const activeInfo = gl.getTransformFeedbackVarying(program, location);
3183
- if (!activeInfo) {
3184
- throw new Error("activeInfo");
3185
- }
3186
- const { name, type: glUniformType, size } = activeInfo;
3187
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3188
- const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
3189
- varyings.push({ location, name, type, size: size * components });
3190
- }
3191
- varyings.sort((a, b) => a.location - b.location);
3192
- return varyings;
3193
- }
3194
- function readUniformBindings(gl, program) {
3195
- const uniforms = [];
3196
- const uniformCount = gl.getProgramParameter(program, 35718);
3197
- for (let i = 0; i < uniformCount; i++) {
3198
- const activeInfo = gl.getActiveUniform(program, i);
3199
- if (!activeInfo) {
3200
- throw new Error("activeInfo");
3201
- }
3202
- const { name: rawName, size, type } = activeInfo;
3203
- const { name, isArray: isArray3 } = parseUniformName(rawName);
3204
- let webglLocation = gl.getUniformLocation(program, name);
3205
- const uniformInfo = {
3206
- // WebGL locations are uniquely typed but just numbers
3207
- location: webglLocation,
3208
- name,
3209
- size,
3210
- type,
3211
- isArray: isArray3
3212
- };
3213
- uniforms.push(uniformInfo);
3214
- if (uniformInfo.size > 1) {
3215
- for (let j = 0; j < uniformInfo.size; j++) {
3216
- const elementName = `${name}[${j}]`;
3217
- webglLocation = gl.getUniformLocation(program, elementName);
3218
- const arrayElementUniformInfo = {
3219
- ...uniformInfo,
3220
- name: elementName,
3221
- location: webglLocation
3222
- };
3223
- uniforms.push(arrayElementUniformInfo);
3224
- }
3225
- }
3226
- }
3227
- return uniforms;
3228
- }
3229
- function readUniformBlocks(gl, program) {
3230
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3231
- const uniformBlocks = [];
3232
- const blockCount = gl.getProgramParameter(program, 35382);
3233
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3234
- const blockInfo = {
3235
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3236
- location: getBlockParameter(blockIndex, 35391),
3237
- byteLength: getBlockParameter(blockIndex, 35392),
3238
- vertex: getBlockParameter(blockIndex, 35396),
3239
- fragment: getBlockParameter(blockIndex, 35398),
3240
- uniformCount: getBlockParameter(blockIndex, 35394),
3241
- uniforms: []
3242
- };
3243
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3244
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3245
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3246
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3247
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3248
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3249
- const uniformIndex = uniformIndices[i];
3250
- if (uniformIndex === void 0) {
3251
- continue;
3252
- }
3253
- const activeInfo = gl.getActiveUniform(program, uniformIndex);
3254
- if (!activeInfo) {
3255
- throw new Error("activeInfo");
3256
- }
3257
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3258
- blockInfo.uniforms.push({
3259
- name: activeInfo.name,
3260
- format,
3261
- type: uniformType[i],
3262
- arrayLength: uniformArrayLength[i],
3263
- byteOffset: uniformOffset[i],
3264
- byteStride: uniformStride[i]
3265
- // matrixStride: uniformStride[i],
3266
- // rowMajor: uniformRowMajor[i]
3267
- });
3268
- }
3269
- uniformBlocks.push(blockInfo);
3270
- }
3271
- uniformBlocks.sort((a, b) => a.location - b.location);
3272
- return uniformBlocks;
3273
- }
3274
- function parseUniformName(name) {
3275
- if (name[name.length - 1] !== "]") {
3276
- return {
3277
- name,
3278
- length: 1,
3279
- isArray: false
3280
- };
3281
- }
3282
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3283
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3284
- const uniformName = (0, import_core15.assertDefined)(matches == null ? void 0 : matches[1], `Failed to parse GLSL uniform name ${name}`);
3285
- return {
3286
- name: uniformName,
3287
- // TODO - is this a bug, shouldn't we return the value?
3288
- length: (matches == null ? void 0 : matches[2]) ? 1 : 0,
3289
- isArray: Boolean(matches == null ? void 0 : matches[2])
3290
- };
3291
- }
3292
- var import_core15, import_constants17;
3293
- var init_get_shader_layout_from_glsl = __esm({
3294
- "dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3295
- "use strict";
3296
- import_core15 = require("@luma.gl/core");
3297
- import_constants17 = require("@luma.gl/constants");
3298
- init_webgl_shadertypes();
3299
- }
3300
- });
3301
-
3302
3262
  // dist/adapter/helpers/set-uniform.js
3303
3263
  function setUniform(gl, location, type, value) {
3304
3264
  const gl2 = gl;
@@ -3383,11 +3343,11 @@ function setUniform(gl, location, type, value) {
3383
3343
  }
3384
3344
  throw new Error("Illegal uniform");
3385
3345
  }
3386
- var import_constants18;
3346
+ var import_constants16;
3387
3347
  var init_set_uniform = __esm({
3388
3348
  "dist/adapter/helpers/set-uniform.js"() {
3389
3349
  "use strict";
3390
- import_constants18 = require("@luma.gl/constants");
3350
+ import_constants16 = require("@luma.gl/constants");
3391
3351
  }
3392
3352
  });
3393
3353
 
@@ -3424,11 +3384,11 @@ function getGLPrimitive(topology) {
3424
3384
  throw new Error(topology);
3425
3385
  }
3426
3386
  }
3427
- var import_constants19;
3387
+ var import_constants17;
3428
3388
  var init_webgl_topology_utils = __esm({
3429
3389
  "dist/adapter/helpers/webgl-topology-utils.js"() {
3430
3390
  "use strict";
3431
- import_constants19 = require("@luma.gl/constants");
3391
+ import_constants17 = require("@luma.gl/constants");
3432
3392
  }
3433
3393
  });
3434
3394
 
@@ -3449,13 +3409,12 @@ function mergeShaderLayout(baseLayout, overrideLayout) {
3449
3409
  }
3450
3410
  return mergedLayout;
3451
3411
  }
3452
- var import_core16, import_constants20, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3412
+ var import_core16, import_constants18, WEBGLRenderPipeline;
3453
3413
  var init_webgl_render_pipeline = __esm({
3454
3414
  "dist/adapter/resources/webgl-render-pipeline.js"() {
3455
3415
  "use strict";
3456
3416
  import_core16 = require("@luma.gl/core");
3457
- import_constants20 = require("@luma.gl/constants");
3458
- init_get_shader_layout_from_glsl();
3417
+ import_constants18 = require("@luma.gl/constants");
3459
3418
  init_device_parameters();
3460
3419
  init_set_uniform();
3461
3420
  init_webgl_buffer();
@@ -3463,7 +3422,6 @@ var init_webgl_render_pipeline = __esm({
3463
3422
  init_webgl_texture();
3464
3423
  init_webgl_texture_view();
3465
3424
  init_webgl_topology_utils();
3466
- LOG_PROGRAM_PERF_PRIORITY = 4;
3467
3425
  WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3468
3426
  /** The WebGL device that created this render pipeline */
3469
3427
  device;
@@ -3475,10 +3433,10 @@ var init_webgl_render_pipeline = __esm({
3475
3433
  fs;
3476
3434
  /** The layout extracted from shader by WebGL introspection APIs */
3477
3435
  introspectedLayout;
3478
- /** Uniforms set on this model */
3479
- uniforms = {};
3480
- /** Bindings set on this model */
3436
+ /** Compatibility path for direct pipeline.setBindings() usage */
3481
3437
  bindings = {};
3438
+ /** Compatibility path for direct pipeline.uniforms usage */
3439
+ uniforms = {};
3482
3440
  /** WebGL varyings */
3483
3441
  varyings = null;
3484
3442
  _uniformCount = 0;
@@ -3490,33 +3448,28 @@ var init_webgl_render_pipeline = __esm({
3490
3448
  constructor(device, props) {
3491
3449
  super(device, props);
3492
3450
  this.device = device;
3493
- 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;
3494
3458
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
3495
- this.vs = props.vs;
3496
- this.fs = props.fs;
3497
- const { varyings, bufferMode = 35981 } = props;
3498
- if (varyings && varyings.length > 0) {
3499
- this.varyings = varyings;
3500
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
3501
- }
3502
- this._linkShaders();
3503
- import_core16.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3504
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3505
- import_core16.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3506
3459
  this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
3507
3460
  }
3508
3461
  destroy() {
3509
- if (this.handle) {
3510
- this.device.gl.useProgram(null);
3511
- this.device.gl.deleteProgram(this.handle);
3512
- this.destroyed = true;
3513
- this.handle.destroyed = true;
3514
- this.handle = null;
3462
+ if (this.destroyed) {
3463
+ return;
3464
+ }
3465
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
3466
+ this.sharedRenderPipeline.destroy();
3515
3467
  }
3468
+ this.destroyResource();
3516
3469
  }
3517
3470
  /**
3518
- * Bindings include: textures, samplers and uniform buffers
3519
- * @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.
3520
3473
  */
3521
3474
  setBindings(bindings, options) {
3522
3475
  for (const [name, value] of Object.entries(bindings)) {
@@ -3557,6 +3510,7 @@ var init_webgl_render_pipeline = __esm({
3557
3510
  */
3558
3511
  draw(options) {
3559
3512
  var _a;
3513
+ this._syncLinkStatus();
3560
3514
  const {
3561
3515
  renderPass,
3562
3516
  parameters = this.props.parameters,
@@ -3570,7 +3524,9 @@ var init_webgl_render_pipeline = __esm({
3570
3524
  // firstIndex,
3571
3525
  // firstInstance,
3572
3526
  // baseVertex,
3573
- transformFeedback
3527
+ transformFeedback,
3528
+ bindings = this.bindings,
3529
+ uniforms = this.uniforms
3574
3530
  } = options;
3575
3531
  const glDrawMode = getGLDrawMode(topology);
3576
3532
  const isIndexed = Boolean(vertexArray.indexBuffer);
@@ -3579,66 +3535,488 @@ var init_webgl_render_pipeline = __esm({
3579
3535
  import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
3580
3536
  return false;
3581
3537
  }
3582
- if (!this._areTexturesRenderable()) {
3538
+ if (!this._areTexturesRenderable(bindings)) {
3583
3539
  import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
3584
3540
  return false;
3585
3541
  }
3586
- this.device.gl.useProgram(this.handle);
3587
- vertexArray.bindBeforeRender(renderPass);
3588
- if (transformFeedback) {
3589
- transformFeedback.begin(this.props.topology);
3542
+ this.device.gl.useProgram(this.handle);
3543
+ vertexArray.bindBeforeRender(renderPass);
3544
+ if (transformFeedback) {
3545
+ transformFeedback.begin(this.props.topology);
3546
+ }
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;
3590
3996
  }
3591
- this._applyBindings();
3592
- this._applyUniforms();
3593
- const webglRenderPass = renderPass;
3594
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
3595
- if (isIndexed && isInstanced) {
3596
- this.device.gl.drawElementsInstanced(
3597
- glDrawMode,
3598
- vertexCount || 0,
3599
- // indexCount?
3600
- glIndexType,
3601
- firstVertex,
3602
- instanceCount || 0
3603
- );
3604
- } else if (isIndexed) {
3605
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
3606
- } else if (isInstanced) {
3607
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
3608
- } else {
3609
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
3610
- }
3611
- if (transformFeedback) {
3612
- transformFeedback.end();
3613
- }
3614
- });
3615
- vertexArray.unbindAfterRender(renderPass);
3616
- return true;
3997
+ this.device.gl.useProgram(null);
3998
+ this.device.gl.deleteProgram(this.handle);
3999
+ this.handle.destroyed = true;
4000
+ this.destroyResource();
3617
4001
  }
3618
- // PRIVATE METHODS
3619
- // setAttributes(attributes: Record<string, Buffer>): void {}
3620
- // setBindings(bindings: Record<string, Binding>): void {}
3621
4002
  async _linkShaders() {
3622
4003
  const { gl } = this.device;
3623
4004
  gl.attachShader(this.handle, this.vs.handle);
3624
4005
  gl.attachShader(this.handle, this.fs.handle);
3625
- 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}`)();
3626
4007
  gl.linkProgram(this.handle);
3627
- import_core16.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3628
- if (import_core16.log.level === 0) {
3629
- }
4008
+ import_core18.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3630
4009
  if (!this.device.features.has("compilation-status-async-webgl")) {
3631
4010
  const status2 = this._getLinkStatus();
3632
4011
  this._reportLinkStatus(status2);
3633
4012
  return;
3634
4013
  }
3635
- import_core16.log.once(1, "RenderPipeline linking is asynchronous")();
4014
+ import_core18.log.once(1, "RenderPipeline linking is asynchronous")();
3636
4015
  await this._waitForLinkComplete();
3637
- 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}`)();
3638
4017
  const status = this._getLinkStatus();
3639
4018
  this._reportLinkStatus(status);
3640
4019
  }
3641
- /** Report link status. First, check for shader compilation failures if linking fails */
3642
4020
  async _reportLinkStatus(status) {
3643
4021
  var _a;
3644
4022
  switch (status) {
@@ -3673,11 +4051,6 @@ var init_webgl_render_pipeline = __esm({
3673
4051
  this.device.debug();
3674
4052
  }
3675
4053
  }
3676
- /**
3677
- * Get the shader compilation status
3678
- * TODO - Load log even when no error reported, to catch warnings?
3679
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
3680
- */
3681
4054
  _getLinkStatus() {
3682
4055
  const { gl } = this.device;
3683
4056
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -3685,6 +4058,7 @@ var init_webgl_render_pipeline = __esm({
3685
4058
  this.linkStatus = "error";
3686
4059
  return "link-error";
3687
4060
  }
4061
+ this._initializeSamplerUniforms();
3688
4062
  gl.validateProgram(this.handle);
3689
4063
  const validated = gl.getProgramParameter(this.handle, 35715);
3690
4064
  if (!validated) {
@@ -3694,7 +4068,33 @@ var init_webgl_render_pipeline = __esm({
3694
4068
  this.linkStatus = "success";
3695
4069
  return "success";
3696
4070
  }
3697
- /** 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
+ }
3698
4098
  async _waitForLinkComplete() {
3699
4099
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
3700
4100
  const DELAY_MS = 10;
@@ -3711,99 +4111,6 @@ var init_webgl_render_pipeline = __esm({
3711
4111
  await waitMs(DELAY_MS);
3712
4112
  }
3713
4113
  }
3714
- /**
3715
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
3716
- * Update a texture if needed (e.g. from video)
3717
- * Note: This is currently done before every draw call
3718
- */
3719
- _areTexturesRenderable() {
3720
- let texturesRenderable = true;
3721
- for (const bindingInfo of this.shaderLayout.bindings) {
3722
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
3723
- import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
3724
- texturesRenderable = false;
3725
- }
3726
- }
3727
- return texturesRenderable;
3728
- }
3729
- /** Apply any bindings (before each draw call) */
3730
- _applyBindings() {
3731
- if (this.linkStatus !== "success") {
3732
- return;
3733
- }
3734
- const { gl } = this.device;
3735
- gl.useProgram(this.handle);
3736
- let textureUnit = 0;
3737
- let uniformBufferIndex = 0;
3738
- for (const binding of this.shaderLayout.bindings) {
3739
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
3740
- if (!value) {
3741
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
3742
- }
3743
- switch (binding.type) {
3744
- case "uniform":
3745
- const { name } = binding;
3746
- const location = gl.getUniformBlockIndex(this.handle, name);
3747
- if (location === 4294967295) {
3748
- throw new Error(`Invalid uniform block name ${name}`);
3749
- }
3750
- gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
3751
- if (value instanceof WEBGLBuffer) {
3752
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
3753
- } else {
3754
- gl.bindBufferRange(
3755
- 35345,
3756
- uniformBufferIndex,
3757
- // @ts-expect-error
3758
- value.buffer.handle,
3759
- // @ts-expect-error
3760
- value.offset || 0,
3761
- // @ts-expect-error
3762
- value.size || value.buffer.byteLength - value.offset
3763
- );
3764
- }
3765
- uniformBufferIndex += 1;
3766
- break;
3767
- case "texture":
3768
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3769
- throw new Error("texture");
3770
- }
3771
- let texture;
3772
- if (value instanceof WEBGLTextureView) {
3773
- texture = value.texture;
3774
- } else if (value instanceof WEBGLTexture) {
3775
- texture = value;
3776
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
3777
- import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
3778
- texture = value.colorAttachments[0].texture;
3779
- } else {
3780
- throw new Error("No texture");
3781
- }
3782
- gl.activeTexture(33984 + textureUnit);
3783
- gl.bindTexture(texture.glTarget, texture.handle);
3784
- textureUnit += 1;
3785
- break;
3786
- case "sampler":
3787
- break;
3788
- case "storage":
3789
- case "read-only-storage":
3790
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3791
- }
3792
- }
3793
- }
3794
- /**
3795
- * Due to program sharing, uniforms need to be reset before every draw call
3796
- * (though caching will avoid redundant WebGL calls)
3797
- */
3798
- _applyUniforms() {
3799
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
3800
- const { name, location, type, textureUnit } = uniformLayout;
3801
- const value = this.uniforms[name] ?? textureUnit;
3802
- if (value !== void 0) {
3803
- setUniform(this.device.gl, location, type, value);
3804
- }
3805
- }
3806
- }
3807
4114
  };
3808
4115
  }
3809
4116
  });
@@ -3864,7 +4171,7 @@ function _copyTextureToBuffer(device, options) {
3864
4171
  const webglBuffer = destinationBuffer;
3865
4172
  const sourceWidth = width || framebuffer.width;
3866
4173
  const sourceHeight = height || framebuffer.height;
3867
- const colorAttachment0 = (0, import_core17.assertDefined)(framebuffer.colorAttachments[0]);
4174
+ const colorAttachment0 = (0, import_core19.assertDefined)(framebuffer.colorAttachments[0]);
3868
4175
  const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
3869
4176
  const sourceFormat = sourceParams.format;
3870
4177
  const sourceType = sourceParams.type;
@@ -3942,7 +4249,7 @@ function _copyTextureToTexture(device, options) {
3942
4249
  }
3943
4250
  }
3944
4251
  function getFramebuffer(source) {
3945
- if (source instanceof import_core17.Texture) {
4252
+ if (source instanceof import_core19.Texture) {
3946
4253
  const { width, height, id } = source;
3947
4254
  const framebuffer = source.device.createFramebuffer({
3948
4255
  id: `framebuffer-for-${id}`,
@@ -3954,20 +4261,20 @@ function getFramebuffer(source) {
3954
4261
  }
3955
4262
  return { framebuffer: source, destroyFramebuffer: false };
3956
4263
  }
3957
- var import_core17, import_constants21, WEBGLCommandBuffer;
4264
+ var import_core19, import_constants22, WEBGLCommandBuffer;
3958
4265
  var init_webgl_command_buffer = __esm({
3959
4266
  "dist/adapter/resources/webgl-command-buffer.js"() {
3960
4267
  "use strict";
3961
- import_core17 = require("@luma.gl/core");
3962
- import_constants21 = require("@luma.gl/constants");
4268
+ import_core19 = require("@luma.gl/core");
4269
+ import_constants22 = require("@luma.gl/constants");
3963
4270
  init_webgl_texture();
3964
4271
  init_webgl_texture_table();
3965
- WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
4272
+ WEBGLCommandBuffer = class extends import_core19.CommandBuffer {
3966
4273
  device;
3967
4274
  handle = null;
3968
4275
  commands = [];
3969
- constructor(device) {
3970
- super(device, {});
4276
+ constructor(device, props = {}) {
4277
+ super(device, props);
3971
4278
  this.device = device;
3972
4279
  }
3973
4280
  _executeCommands(commands = this.commands) {
@@ -3995,16 +4302,16 @@ var init_webgl_command_buffer = __esm({
3995
4302
  });
3996
4303
 
3997
4304
  // dist/adapter/resources/webgl-render-pass.js
3998
- var import_core18, import_constants22, COLOR_CHANNELS, WEBGLRenderPass;
4305
+ var import_core20, import_constants23, COLOR_CHANNELS, WEBGLRenderPass;
3999
4306
  var init_webgl_render_pass = __esm({
4000
4307
  "dist/adapter/resources/webgl-render-pass.js"() {
4001
4308
  "use strict";
4002
- import_core18 = require("@luma.gl/core");
4003
- import_constants22 = require("@luma.gl/constants");
4309
+ import_core20 = require("@luma.gl/core");
4310
+ import_constants23 = require("@luma.gl/constants");
4004
4311
  init_with_parameters();
4005
4312
  init_unified_parameter_api();
4006
4313
  COLOR_CHANNELS = [1, 2, 4, 8];
4007
- WEBGLRenderPass = class extends import_core18.RenderPass {
4314
+ WEBGLRenderPass = class extends import_core20.RenderPass {
4008
4315
  device;
4009
4316
  handle = null;
4010
4317
  /** Parameters that should be applied before each draw call */
@@ -4036,9 +4343,21 @@ var init_webgl_render_pass = __esm({
4036
4343
  this.device.gl.drawBuffers([1029]);
4037
4344
  }
4038
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
+ }
4039
4350
  }
4040
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
+ }
4041
4359
  this.device.popState();
4360
+ this.destroy();
4042
4361
  }
4043
4362
  pushDebugGroup(groupLabel) {
4044
4363
  }
@@ -4158,31 +4477,39 @@ var init_webgl_render_pass = __esm({
4158
4477
  });
4159
4478
 
4160
4479
  // dist/adapter/resources/webgl-command-encoder.js
4161
- var import_core19, WEBGLCommandEncoder;
4480
+ var import_core21, WEBGLCommandEncoder;
4162
4481
  var init_webgl_command_encoder = __esm({
4163
4482
  "dist/adapter/resources/webgl-command-encoder.js"() {
4164
4483
  "use strict";
4165
- import_core19 = require("@luma.gl/core");
4484
+ import_core21 = require("@luma.gl/core");
4166
4485
  init_webgl_command_buffer();
4167
4486
  init_webgl_render_pass();
4168
- WEBGLCommandEncoder = class extends import_core19.CommandEncoder {
4487
+ WEBGLCommandEncoder = class extends import_core21.CommandEncoder {
4169
4488
  device;
4170
4489
  handle = null;
4171
4490
  commandBuffer;
4172
4491
  constructor(device, props) {
4173
4492
  super(device, props);
4174
4493
  this.device = device;
4175
- this.commandBuffer = new WEBGLCommandBuffer(device);
4494
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
4495
+ id: `${this.props.id}-command-buffer`
4496
+ });
4176
4497
  }
4177
4498
  destroy() {
4499
+ this.destroyResource();
4178
4500
  }
4179
- 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();
4180
4507
  return this.commandBuffer;
4181
4508
  }
4182
- beginRenderPass(props) {
4183
- return new WEBGLRenderPass(this.device, props);
4509
+ beginRenderPass(props = {}) {
4510
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4184
4511
  }
4185
- beginComputePass(props) {
4512
+ beginComputePass(props = {}) {
4186
4513
  throw new Error("ComputePass not supported in WebGL");
4187
4514
  }
4188
4515
  copyBufferToBuffer(options) {
@@ -4208,6 +4535,10 @@ var init_webgl_command_encoder = __esm({
4208
4535
  }
4209
4536
  resolveQuerySet(querySet, destination, options) {
4210
4537
  }
4538
+ writeTimestamp(querySet, queryIndex) {
4539
+ const webglQuerySet = querySet;
4540
+ webglQuerySet.writeTimestamp(queryIndex);
4541
+ }
4211
4542
  };
4212
4543
  }
4213
4544
  });
@@ -4256,16 +4587,16 @@ function compareConstantArrayValues(v1, v2) {
4256
4587
  }
4257
4588
  return true;
4258
4589
  }
4259
- var import_core20, import_constants23, import_env2, WEBGLVertexArray;
4590
+ var import_core22, import_constants24, import_env2, WEBGLVertexArray;
4260
4591
  var init_webgl_vertex_array = __esm({
4261
4592
  "dist/adapter/resources/webgl-vertex-array.js"() {
4262
4593
  "use strict";
4263
- import_core20 = require("@luma.gl/core");
4264
- import_constants23 = require("@luma.gl/constants");
4594
+ import_core22 = require("@luma.gl/core");
4595
+ import_constants24 = require("@luma.gl/constants");
4265
4596
  import_env2 = require("@probe.gl/env");
4266
4597
  init_webgl_vertex_formats();
4267
4598
  init_fill_array();
4268
- WEBGLVertexArray = class extends import_core20.VertexArray {
4599
+ WEBGLVertexArray = class extends import_core22.VertexArray {
4269
4600
  get [Symbol.toStringTag]() {
4270
4601
  return "VertexArray";
4271
4602
  }
@@ -4432,7 +4763,7 @@ var init_webgl_vertex_array = __esm({
4432
4763
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4433
4764
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4434
4765
  if (updateNeeded) {
4435
- const typedArray = (0, import_core20.getScratchArray)(value.constructor, length);
4766
+ const typedArray = (0, import_core22.getScratchArray)(value.constructor, length);
4436
4767
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4437
4768
  this.buffer.write(typedArray);
4438
4769
  this.bufferValue = value;
@@ -4450,15 +4781,15 @@ function isIndex(value) {
4450
4781
  }
4451
4782
  return /^\d+$/.test(value);
4452
4783
  }
4453
- var import_core21, import_constants24, WEBGLTransformFeedback;
4784
+ var import_core23, import_constants25, WEBGLTransformFeedback;
4454
4785
  var init_webgl_transform_feedback = __esm({
4455
4786
  "dist/adapter/resources/webgl-transform-feedback.js"() {
4456
4787
  "use strict";
4457
- import_core21 = require("@luma.gl/core");
4458
- import_constants24 = require("@luma.gl/constants");
4788
+ import_core23 = require("@luma.gl/core");
4789
+ import_constants25 = require("@luma.gl/constants");
4459
4790
  init_dist();
4460
4791
  init_webgl_topology_utils();
4461
- WEBGLTransformFeedback = class extends import_core21.TransformFeedback {
4792
+ WEBGLTransformFeedback = class extends import_core23.TransformFeedback {
4462
4793
  device;
4463
4794
  gl;
4464
4795
  handle;
@@ -4521,7 +4852,7 @@ var init_webgl_transform_feedback = __esm({
4521
4852
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
4522
4853
  if (location < 0) {
4523
4854
  this.unusedBuffers[locationOrName] = buffer;
4524
- import_core21.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4855
+ import_core23.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4525
4856
  return;
4526
4857
  }
4527
4858
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -4604,152 +4935,245 @@ var init_webgl_transform_feedback = __esm({
4604
4935
  });
4605
4936
 
4606
4937
  // dist/adapter/resources/webgl-query-set.js
4607
- var import_core22, import_constants25, WEBGLQuerySet;
4938
+ var import_core24, import_constants26, WEBGLQuerySet;
4608
4939
  var init_webgl_query_set = __esm({
4609
4940
  "dist/adapter/resources/webgl-query-set.js"() {
4610
4941
  "use strict";
4611
- import_core22 = require("@luma.gl/core");
4612
- import_constants25 = require("@luma.gl/constants");
4613
- 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 {
4614
4945
  device;
4615
4946
  handle;
4616
- target = null;
4617
- _queryPending = false;
4618
- _pollingPromise = null;
4947
+ _timestampPairs = [];
4948
+ _occlusionQuery = null;
4949
+ _occlusionActive = false;
4619
4950
  get [Symbol.toStringTag]() {
4620
- return "Query";
4951
+ return "QuerySet";
4621
4952
  }
4622
- // Create a query class
4623
4953
  constructor(device, props) {
4624
4954
  super(device, props);
4625
4955
  this.device = device;
4626
- if (props.count > 1) {
4627
- throw new Error("WebGL QuerySet can only have one value");
4628
- }
4629
- const handle = this.device.gl.createQuery();
4630
- if (!handle) {
4631
- 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;
4632
4971
  }
4633
- this.handle = handle;
4634
4972
  Object.seal(this);
4635
4973
  }
4636
4974
  destroy() {
4637
- 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();
4638
4993
  }
4639
- // FOR RENDER PASS AND COMMAND ENCODER
4640
- /**
4641
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
4642
- * Measures GPU time delta between this call and a matching `end` call in the
4643
- * GPU instruction stream.
4644
- */
4645
- beginTimestampQuery() {
4646
- 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)];
4647
5031
  }
4648
- endTimestampQuery() {
4649
- 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;
4650
5044
  }
4651
- // Shortcut for occlusion queries
4652
- beginOcclusionQuery(options) {
4653
- 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;
4654
5063
  }
4655
5064
  endOcclusionQuery() {
4656
- this._end();
4657
- }
4658
- // Shortcut for transformFeedbackQuery
4659
- beginTransformFeedbackQuery() {
4660
- return this._begin(35976);
4661
- }
4662
- endTransformFeedbackQuery() {
4663
- this._end();
4664
- }
4665
- async resolveQuery() {
4666
- const value = await this.pollQuery();
4667
- return [value];
4668
- }
4669
- // PRIVATE METHODS
4670
- /**
4671
- * Due to OpenGL API limitations, after calling `begin()` on one Query
4672
- * instance, `end()` must be called on that same instance before
4673
- * calling `begin()` on another query. While there can be multiple
4674
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
4675
- * It is not possible to interleave or overlap `begin` and `end` calls.
4676
- */
4677
- _begin(target2) {
4678
- if (this._queryPending) {
4679
- return;
5065
+ if (!this._occlusionActive) {
5066
+ throw new Error("Occlusion query is not active");
4680
5067
  }
4681
- this.target = target2;
4682
- this.device.gl.beginQuery(this.target, this.handle);
4683
- return;
5068
+ this.device.gl.endQuery(35887);
5069
+ this._occlusionActive = false;
4684
5070
  }
4685
- // ends the current query
4686
- _end() {
4687
- 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;
4688
5093
  return;
4689
5094
  }
4690
- if (this.target) {
4691
- this.device.gl.endQuery(this.target);
4692
- this.target = null;
4693
- this._queryPending = true;
5095
+ if (!pair.activeQuery) {
5096
+ throw new Error("Timestamp query pair was ended before it was started");
4694
5097
  }
4695
- return;
5098
+ this.device.gl.endQuery(35007);
5099
+ pair.completedQueries.push(pair.activeQuery);
5100
+ pair.activeQuery = null;
4696
5101
  }
4697
- // Returns true if the query result is available
4698
- isResultAvailable() {
4699
- if (!this._queryPending) {
4700
- 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");
4701
5105
  }
4702
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
4703
- if (resultAvailable) {
4704
- 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");
4705
5110
  }
4706
- return resultAvailable;
5111
+ return Math.floor(queryIndex / 2);
4707
5112
  }
4708
- // Timing query is disjoint, i.e. results are invalid
4709
- isTimerDisjoint() {
4710
- 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]);
4711
5119
  }
4712
- // Returns query result.
4713
- getResult() {
4714
- 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;
4715
5132
  }
4716
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
4717
- getTimerMilliseconds() {
4718
- 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
+ }
4719
5144
  }
4720
- // Polls the query
4721
- pollQuery(limit = Number.POSITIVE_INFINITY) {
4722
- if (this._pollingPromise) {
4723
- return this._pollingPromise;
5145
+ _consumeQueryResult(query) {
5146
+ if (query.promise) {
5147
+ return query.promise;
4724
5148
  }
4725
- let counter = 0;
4726
- this._pollingPromise = new Promise((resolve, reject) => {
5149
+ query.promise = new Promise((resolve, reject) => {
4727
5150
  const poll = () => {
4728
- if (this.isResultAvailable()) {
4729
- resolve(this.getResult());
4730
- this._pollingPromise = null;
4731
- } else if (counter++ > limit) {
4732
- reject("Timed out");
4733
- this._pollingPromise = null;
4734
- } else {
5151
+ if (!this._pollQueryAvailability(query)) {
4735
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);
4736
5160
  }
4737
5161
  };
4738
- requestAnimationFrame(poll);
5162
+ poll();
4739
5163
  });
4740
- return this._pollingPromise;
5164
+ return query.promise;
4741
5165
  }
4742
5166
  };
4743
5167
  }
4744
5168
  });
4745
5169
 
4746
5170
  // dist/adapter/resources/webgl-fence.js
4747
- var import_core23, WEBGLFence;
5171
+ var import_core25, WEBGLFence;
4748
5172
  var init_webgl_fence = __esm({
4749
5173
  "dist/adapter/resources/webgl-fence.js"() {
4750
5174
  "use strict";
4751
- import_core23 = require("@luma.gl/core");
4752
- WEBGLFence = class extends import_core23.Fence {
5175
+ import_core25 = require("@luma.gl/core");
5176
+ WEBGLFence = class extends import_core25.Fence {
4753
5177
  device;
4754
5178
  gl;
4755
5179
  handle;
@@ -4834,11 +5258,11 @@ function glTypeToBytes(type) {
4834
5258
  return 0;
4835
5259
  }
4836
5260
  }
4837
- var import_constants26;
5261
+ var import_constants27;
4838
5262
  var init_format_utils = __esm({
4839
5263
  "dist/adapter/helpers/format-utils.js"() {
4840
5264
  "use strict";
4841
- import_constants26 = require("@luma.gl/constants");
5265
+ import_constants27 = require("@luma.gl/constants");
4842
5266
  }
4843
5267
  });
4844
5268
 
@@ -4872,7 +5296,7 @@ function readPixelsToArray(source, options) {
4872
5296
  sourceFormat ||= (texture == null ? void 0 : texture.glFormat) || 6408;
4873
5297
  sourceType ||= (texture == null ? void 0 : texture.glType) || 5121;
4874
5298
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
4875
- const signedType = (0, import_core24.getDataType)(target2);
5299
+ const signedType = (0, import_core26.getDataType)(target2);
4876
5300
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
4877
5301
  const prevHandle = gl.bindFramebuffer(36160, handle);
4878
5302
  gl.readBuffer(36064 + sourceAttachment);
@@ -4915,7 +5339,7 @@ function readPixelsToBuffer(source, options) {
4915
5339
  return webglBufferTarget;
4916
5340
  }
4917
5341
  function getFramebuffer2(source) {
4918
- if (!(source instanceof import_core24.Framebuffer)) {
5342
+ if (!(source instanceof import_core26.Framebuffer)) {
4919
5343
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
4920
5344
  }
4921
5345
  return { framebuffer: source, deleteFramebuffer: false };
@@ -4937,16 +5361,16 @@ function getPixelArray(pixelArray, glType, glFormat, width, height, depth) {
4937
5361
  }
4938
5362
  glType ||= 5121;
4939
5363
  const shaderType = convertGLDataTypeToDataType(glType);
4940
- const ArrayType = (0, import_core24.getTypedArrayConstructor)(shaderType);
5364
+ const ArrayType = (0, import_core26.getTypedArrayConstructor)(shaderType);
4941
5365
  const components = glFormatToComponents(glFormat);
4942
5366
  return new ArrayType(width * height * components);
4943
5367
  }
4944
- var import_core24, import_constants27;
5368
+ var import_core26, import_constants28;
4945
5369
  var init_webgl_texture_utils = __esm({
4946
5370
  "dist/adapter/helpers/webgl-texture-utils.js"() {
4947
5371
  "use strict";
4948
- import_core24 = require("@luma.gl/core");
4949
- import_constants27 = require("@luma.gl/constants");
5372
+ import_core26 = require("@luma.gl/core");
5373
+ import_constants28 = require("@luma.gl/constants");
4950
5374
  init_webgl_shadertypes();
4951
5375
  init_format_utils();
4952
5376
  init_shader_formats();
@@ -4992,11 +5416,11 @@ function compareConstantArrayValues2(v1, v2) {
4992
5416
  }
4993
5417
  return true;
4994
5418
  }
4995
- var import_core25, WebGLDevice;
5419
+ var import_core27, WebGLDevice;
4996
5420
  var init_webgl_device = __esm({
4997
5421
  "dist/adapter/webgl-device.js"() {
4998
5422
  "use strict";
4999
- import_core25 = require("@luma.gl/core");
5423
+ import_core27 = require("@luma.gl/core");
5000
5424
  init_webgl_state_tracker();
5001
5425
  init_create_browser_context();
5002
5426
  init_webgl_context_data();
@@ -5004,6 +5428,7 @@ var init_webgl_device = __esm({
5004
5428
  init_webgl_device_features();
5005
5429
  init_webgl_device_limits();
5006
5430
  init_webgl_canvas_context();
5431
+ init_webgl_presentation_context();
5007
5432
  init_spector();
5008
5433
  init_webgl_developer_tools();
5009
5434
  init_webgl_texture_table();
@@ -5014,6 +5439,7 @@ var init_webgl_device = __esm({
5014
5439
  init_webgl_texture();
5015
5440
  init_webgl_framebuffer();
5016
5441
  init_webgl_render_pipeline();
5442
+ init_webgl_shared_render_pipeline();
5017
5443
  init_webgl_command_encoder();
5018
5444
  init_webgl_vertex_array();
5019
5445
  init_webgl_transform_feedback();
@@ -5023,7 +5449,7 @@ var init_webgl_device = __esm({
5023
5449
  init_unified_parameter_api();
5024
5450
  init_with_parameters();
5025
5451
  init_webgl_extensions();
5026
- WebGLDevice = class extends import_core25.Device {
5452
+ WebGLDevice = class extends import_core27.Device {
5027
5453
  static getDeviceFromContext(gl) {
5028
5454
  var _a;
5029
5455
  if (!gl) {
@@ -5076,7 +5502,7 @@ var init_webgl_device = __esm({
5076
5502
  constructor(props) {
5077
5503
  var _a;
5078
5504
  super({ ...props, id: props.id || uid("webgl-device") });
5079
- const canvasContextProps = import_core25.Device._getCanvasContextProps(props);
5505
+ const canvasContextProps = import_core27.Device._getCanvasContextProps(props);
5080
5506
  if (!canvasContextProps) {
5081
5507
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5082
5508
  }
@@ -5117,7 +5543,7 @@ var init_webgl_device = __esm({
5117
5543
  device = WebGLDevice.getDeviceFromContext(gl);
5118
5544
  if (device) {
5119
5545
  if (props._reuseDevices) {
5120
- 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)();
5121
5547
  this.canvasContext.destroy();
5122
5548
  device._reused = true;
5123
5549
  return device;
@@ -5137,17 +5563,18 @@ var init_webgl_device = __esm({
5137
5563
  this.features.initializeFeatures();
5138
5564
  }
5139
5565
  const glState = new WebGLStateTracker(this.gl, {
5140
- log: (...args) => import_core25.log.log(1, ...args)()
5566
+ log: (...args) => import_core27.log.log(1, ...args)()
5141
5567
  });
5142
5568
  glState.trackState(this.gl, { copyState: false });
5143
5569
  if (props.debug || props.debugWebGL) {
5144
5570
  this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
5145
- import_core25.log.warn("WebGL debug mode activated. Performance reduced.")();
5571
+ import_core27.log.warn("WebGL debug mode activated. Performance reduced.")();
5146
5572
  }
5147
5573
  if (props.debugWebGL) {
5148
- import_core25.log.level = Math.max(import_core25.log.level, 1);
5574
+ import_core27.log.level = Math.max(import_core27.log.level, 1);
5149
5575
  }
5150
5576
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
5577
+ this.canvasContext._startObservers();
5151
5578
  }
5152
5579
  /**
5153
5580
  * Destroys the device
@@ -5160,6 +5587,8 @@ var init_webgl_device = __esm({
5160
5587
  * browser API for destroying WebGL contexts.
5161
5588
  */
5162
5589
  destroy() {
5590
+ var _a;
5591
+ (_a = this.commandEncoder) == null ? void 0 : _a.destroy();
5163
5592
  if (!this.props._reuseDevices && !this._reused) {
5164
5593
  const contextData = getWebGLContextData(this.handle);
5165
5594
  contextData.device = null;
@@ -5172,6 +5601,9 @@ var init_webgl_device = __esm({
5172
5601
  createCanvasContext(props) {
5173
5602
  throw new Error("WebGL only supports a single canvas");
5174
5603
  }
5604
+ createPresentationContext(props) {
5605
+ return new WebGLPresentationContext(this, props || {});
5606
+ }
5175
5607
  createBuffer(props) {
5176
5608
  const newProps = this._normalizeBufferProps(props);
5177
5609
  return new WEBGLBuffer(this, newProps);
@@ -5206,6 +5638,9 @@ var init_webgl_device = __esm({
5206
5638
  createRenderPipeline(props) {
5207
5639
  return new WEBGLRenderPipeline(this, props);
5208
5640
  }
5641
+ _createSharedRenderPipelineWebGL(props) {
5642
+ return new WEBGLSharedRenderPipeline(this, props);
5643
+ }
5209
5644
  createComputePipeline(props) {
5210
5645
  throw new Error("ComputePipeline not supported in WebGL");
5211
5646
  }
@@ -5218,12 +5653,27 @@ var init_webgl_device = __esm({
5218
5653
  * Chrome's offscreen canvas does not require gl.commit
5219
5654
  */
5220
5655
  submit(commandBuffer) {
5656
+ let submittedCommandEncoder = null;
5221
5657
  if (!commandBuffer) {
5222
- commandBuffer = this.commandEncoder.finish();
5658
+ submittedCommandEncoder = this.commandEncoder;
5659
+ commandBuffer = submittedCommandEncoder.finish();
5223
5660
  this.commandEncoder.destroy();
5224
- 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();
5225
5676
  }
5226
- commandBuffer._executeCommands();
5227
5677
  }
5228
5678
  //
5229
5679
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5246,7 +5696,7 @@ var init_webgl_device = __esm({
5246
5696
  return withGLParameters(this.gl, parameters, func);
5247
5697
  }
5248
5698
  resetWebGL() {
5249
- 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")();
5250
5700
  resetGLParameters(this.gl);
5251
5701
  }
5252
5702
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
@@ -5319,7 +5769,7 @@ var init_webgl_device = __esm({
5319
5769
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5320
5770
  const currentConstant = this._constants[location];
5321
5771
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5322
- 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`)();
5323
5773
  }
5324
5774
  this._constants[location] = constant;
5325
5775
  switch (constant.constructor) {
@@ -5362,21 +5812,21 @@ function isWebGL(gl) {
5362
5812
  }
5363
5813
  return Boolean(gl && typeof gl.createVertexArray === "function");
5364
5814
  }
5365
- var import_core26, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
5815
+ var import_core28, LOG_LEVEL2, WebGLAdapter, webgl2Adapter;
5366
5816
  var init_webgl_adapter = __esm({
5367
5817
  "dist/adapter/webgl-adapter.js"() {
5368
5818
  "use strict";
5369
- import_core26 = require("@luma.gl/core");
5819
+ import_core28 = require("@luma.gl/core");
5370
5820
  init_polyfill_webgl1_extensions();
5371
5821
  init_spector();
5372
5822
  init_webgl_developer_tools();
5373
5823
  LOG_LEVEL2 = 1;
5374
- WebGLAdapter = class extends import_core26.Adapter {
5824
+ WebGLAdapter = class extends import_core28.Adapter {
5375
5825
  /** type of device's created by this adapter */
5376
5826
  type = "webgl";
5377
5827
  constructor() {
5378
5828
  super();
5379
- import_core26.Device.defaultProps = { ...import_core26.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
5829
+ import_core28.Device.defaultProps = { ...import_core28.Device.defaultProps, ...DEFAULT_SPECTOR_PROPS };
5380
5830
  }
5381
5831
  /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
5382
5832
  enforceWebGL2(enable2) {
@@ -5391,7 +5841,7 @@ var init_webgl_adapter = __esm({
5391
5841
  return true;
5392
5842
  }
5393
5843
  if (typeof WebGLRenderingContext !== "undefined" && handle instanceof WebGLRenderingContext) {
5394
- import_core26.log.warn("WebGL1 is not supported", handle)();
5844
+ import_core28.log.warn("WebGL1 is not supported", handle)();
5395
5845
  }
5396
5846
  return false;
5397
5847
  }
@@ -5433,19 +5883,19 @@ var init_webgl_adapter = __esm({
5433
5883
  const results = await Promise.allSettled(promises);
5434
5884
  for (const result of results) {
5435
5885
  if (result.status === "rejected") {
5436
- import_core26.log.error(`Failed to initialize debug libraries ${result.reason}`)();
5886
+ import_core28.log.error(`Failed to initialize debug libraries ${result.reason}`)();
5437
5887
  }
5438
5888
  }
5439
5889
  try {
5440
5890
  const device = new WebGLDevice2(props);
5441
- import_core26.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
5891
+ import_core28.log.groupCollapsed(LOG_LEVEL2, `WebGLDevice ${device.id} created`)();
5442
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}`;
5443
- import_core26.log.probe(LOG_LEVEL2, message2)();
5444
- 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)();
5445
5895
  return device;
5446
5896
  } finally {
5447
- import_core26.log.groupEnd(LOG_LEVEL2)();
5448
- 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;")();
5449
5899
  }
5450
5900
  }
5451
5901
  };