@luma.gl/webgl 9.1.0-alpha.16 → 9.1.0-alpha.17

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 (55) hide show
  1. package/dist/adapter/converters/sampler-parameters.js +6 -4
  2. package/dist/adapter/converters/texture-formats.d.ts +49 -11
  3. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  4. package/dist/adapter/converters/texture-formats.js +150 -160
  5. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  6. package/dist/adapter/helpers/format-utils.js +6 -0
  7. package/dist/adapter/helpers/webgl-texture-utils.d.ts +10 -8
  8. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  9. package/dist/adapter/helpers/webgl-texture-utils.js +46 -32
  10. package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
  11. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  12. package/dist/adapter/resources/webgl-command-buffer.js +72 -16
  13. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  14. package/dist/adapter/resources/webgl-command-encoder.js +3 -0
  15. package/dist/adapter/resources/webgl-external-texture.js +14 -0
  16. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-framebuffer.js +1 -2
  18. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-render-pass.js +38 -20
  20. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-render-pipeline.js +6 -5
  22. package/dist/adapter/resources/webgl-shader.js +1 -1
  23. package/dist/adapter/resources/webgl-texture.d.ts +8 -14
  24. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-texture.js +119 -208
  26. package/dist/adapter/webgl-adapter.js +1 -1
  27. package/dist/adapter/webgl-device.d.ts +7 -1
  28. package/dist/adapter/webgl-device.d.ts.map +1 -1
  29. package/dist/adapter/webgl-device.js +22 -10
  30. package/dist/context/debug/webgl-developer-tools.d.ts +1 -0
  31. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  32. package/dist/context/debug/webgl-developer-tools.js +4 -2
  33. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  34. package/dist/context/helpers/create-browser-context.js +17 -3
  35. package/dist/dist.dev.js +226 -272
  36. package/dist/dist.min.js +2 -2
  37. package/dist/index.cjs +220 -269
  38. package/dist/index.cjs.map +3 -3
  39. package/package.json +4 -4
  40. package/src/adapter/converters/sampler-parameters.ts +6 -4
  41. package/src/adapter/converters/texture-formats.ts +171 -177
  42. package/src/adapter/helpers/format-utils.ts +6 -0
  43. package/src/adapter/helpers/webgl-texture-utils.ts +66 -45
  44. package/src/adapter/resources/webgl-command-buffer.ts +108 -24
  45. package/src/adapter/resources/webgl-command-encoder.ts +6 -0
  46. package/src/adapter/resources/webgl-external-texture.ts +14 -0
  47. package/src/adapter/resources/webgl-framebuffer.ts +1 -2
  48. package/src/adapter/resources/webgl-render-pass.ts +44 -23
  49. package/src/adapter/resources/webgl-render-pipeline.ts +6 -5
  50. package/src/adapter/resources/webgl-shader.ts +1 -1
  51. package/src/adapter/resources/webgl-texture.ts +126 -235
  52. package/src/adapter/webgl-adapter.ts +1 -1
  53. package/src/adapter/webgl-device.ts +23 -10
  54. package/src/context/debug/webgl-developer-tools.ts +5 -2
  55. package/src/context/helpers/create-browser-context.ts +18 -3
package/dist/dist.dev.js CHANGED
@@ -1435,7 +1435,7 @@ var __exports__ = (() => {
1435
1435
 
1436
1436
  // src/context/helpers/create-browser-context.ts
1437
1437
  function createBrowserContext(canvas, props, webglContextAttributes) {
1438
- const errorMessage = null;
1438
+ let errorMessage = "";
1439
1439
  const webglProps = {
1440
1440
  preserveDrawingBuffer: true,
1441
1441
  // failIfMajorPerformanceCaveat: true,
@@ -1443,14 +1443,25 @@ var __exports__ = (() => {
1443
1443
  };
1444
1444
  let gl = null;
1445
1445
  gl ||= canvas.getContext("webgl2", webglProps);
1446
+ if (webglProps.failIfMajorPerformanceCaveat) {
1447
+ errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1448
+ }
1446
1449
  if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
1447
1450
  webglProps.failIfMajorPerformanceCaveat = false;
1448
- gl = canvas.getContext("webgl", webglProps);
1451
+ gl = canvas.getContext("webgl2", webglProps);
1449
1452
  gl.luma ||= {};
1450
1453
  gl.luma.softwareRenderer = true;
1451
1454
  }
1452
1455
  if (!gl) {
1453
- throw new Error(`Failed to create WebGL context: ${errorMessage || "Unknown error"}`);
1456
+ gl = canvas.getContext("webgl", {});
1457
+ if (gl) {
1458
+ gl = null;
1459
+ errorMessage ||= "Your browser only supports WebGL1";
1460
+ }
1461
+ }
1462
+ if (!gl) {
1463
+ errorMessage ||= "Your browser does not support WebGL";
1464
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1454
1465
  }
1455
1466
  const { onContextLost, onContextRestored } = props;
1456
1467
  canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
@@ -1459,6 +1470,7 @@ var __exports__ = (() => {
1459
1470
  (event) => onContextRestored(event),
1460
1471
  false
1461
1472
  );
1473
+ gl.luma ||= {};
1462
1474
  return gl;
1463
1475
  }
1464
1476
 
@@ -1689,7 +1701,7 @@ var __exports__ = (() => {
1689
1701
  // 64-bit formats
1690
1702
  "rg32uint": { gl: 33340 /* RG32UI */, b: 8, c: 2, rb: true },
1691
1703
  "rg32sint": { gl: 33339 /* RG32I */, b: 8, c: 2, rb: true },
1692
- "rg32float": { gl: 33328 /* RG32F */, b: 8, c: 2, render: float32_renderable, filter: float32_filterable, rb: true },
1704
+ "rg32float": { gl: 33328 /* RG32F */, b: 8, c: 2, render: false, filter: float32_filterable, rb: true },
1693
1705
  "rgba16uint": { gl: 36214 /* RGBA16UI */, b: 8, c: 4, rb: true },
1694
1706
  "rgba16sint": { gl: 36232 /* RGBA16I */, b: 8, c: 4, rb: true },
1695
1707
  "rgba16float": { gl: 34842 /* RGBA16F */, b: 8, c: 4, render: float16_renderable, filter: float16_filterable },
@@ -1875,36 +1887,35 @@ var __exports__ = (() => {
1875
1887
  return true;
1876
1888
  }
1877
1889
  function isTextureFormatFilterable(gl, format, extensions) {
1878
- if (!isTextureFormatSupported(gl, format, extensions)) {
1879
- return false;
1880
- }
1881
- if (format.startsWith("depth") || format.startsWith("stencil")) {
1882
- return false;
1883
- }
1884
- try {
1885
- const decoded = (0, import_core.decodeTextureFormat)(format);
1886
- if (decoded.signed) {
1887
- return false;
1888
- }
1889
- } catch {
1890
- return false;
1891
- }
1892
- if (format.endsWith("32float")) {
1893
- return Boolean(getWebGLExtension(gl, "OES_texture_float_linear, extensions", extensions));
1894
- }
1895
- if (format.endsWith("16float")) {
1896
- return Boolean(getWebGLExtension(gl, "OES_texture_half_float_linear, extensions", extensions));
1897
- }
1898
- return true;
1890
+ return getTextureFormatSupportWebGL(gl, format, extensions).filterable || false;
1899
1891
  }
1900
1892
  function isTextureFormatRenderable(gl, format, extensions) {
1901
- if (!isTextureFormatSupported(gl, format, extensions)) {
1902
- return false;
1903
- }
1904
- if (typeof format === "number") {
1905
- return false;
1906
- }
1907
- return true;
1893
+ return getTextureFormatSupportWebGL(gl, format, extensions).renderable || false;
1894
+ }
1895
+ function getTextureFormatSupportWebGL(gl, format, extensions) {
1896
+ const formatInto = (0, import_core.decodeTextureFormat)(format);
1897
+ if (!formatInto) {
1898
+ return { supported: false };
1899
+ }
1900
+ const webglFormatInfo = TEXTURE_FORMATS[format];
1901
+ if (!webglFormatInfo) {
1902
+ return { supported: false };
1903
+ }
1904
+ let supported = webglFormatInfo.gl !== void 0;
1905
+ supported = supported && checkTextureFeature(gl, webglFormatInfo.f, extensions);
1906
+ const isDepthStencil = format.startsWith("depth") || format.startsWith("stencil");
1907
+ const isSigned = formatInto?.signed;
1908
+ const renderable = supported && !isSigned && webglFormatInfo.render && checkTextureFeature(gl, webglFormatInfo.render, extensions);
1909
+ const filterable = supported && !isDepthStencil && !isSigned && webglFormatInfo.filter && checkTextureFeature(gl, webglFormatInfo.filter, extensions);
1910
+ return {
1911
+ supported,
1912
+ renderable,
1913
+ filterable,
1914
+ blendable: false,
1915
+ // TODO,
1916
+ storable: false
1917
+ // TODO
1918
+ };
1908
1919
  }
1909
1920
  function getTextureFormatWebGL(format) {
1910
1921
  const formatData = TEXTURE_FORMATS[format];
@@ -2183,7 +2194,7 @@ var __exports__ = (() => {
2183
2194
  );
2184
2195
  this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
2185
2196
  }
2186
- if (this.props.check !== false) {
2197
+ if (this.device.props.debug) {
2187
2198
  const status = this.gl.checkFramebufferStatus(36160 /* FRAMEBUFFER */);
2188
2199
  if (status !== 36053 /* FRAMEBUFFER_COMPLETE */) {
2189
2200
  throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
@@ -2462,7 +2473,7 @@ var __exports__ = (() => {
2462
2473
  }
2463
2474
  }
2464
2475
  function makeDebugContext(gl, props = {}) {
2465
- return props.debugWebGL ? getDebugContext(gl, props) : getRealContext(gl);
2476
+ return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
2466
2477
  }
2467
2478
  function getRealContext(gl) {
2468
2479
  const data = getWebGLContextData(gl);
@@ -2516,7 +2527,9 @@ var __exports__ = (() => {
2516
2527
  let functionString = "";
2517
2528
  if (import_core7.log.level >= 1) {
2518
2529
  functionString = getFunctionString(functionName, functionArgs);
2519
- import_core7.log.log(1, functionString)();
2530
+ if (props.traceWebGL) {
2531
+ import_core7.log.log(1, functionString)();
2532
+ }
2520
2533
  }
2521
2534
  for (const arg of functionArgs) {
2522
2535
  if (arg === void 0) {
@@ -2755,7 +2768,7 @@ ${source}`;
2755
2768
  const { gl } = this.device;
2756
2769
  gl.shaderSource(this.handle, source);
2757
2770
  gl.compileShader(this.handle);
2758
- if (import_core9.log.level === 0) {
2771
+ if (!this.device.props.debug) {
2759
2772
  this.compilationStatus = "pending";
2760
2773
  return;
2761
2774
  }
@@ -3124,15 +3137,17 @@ ${source}`;
3124
3137
  return 9729 /* LINEAR */;
3125
3138
  }
3126
3139
  }
3127
- function convertMinFilterMode(minFilter, mipmapFilter) {
3140
+ function convertMinFilterMode(minFilter, mipmapFilter = "none") {
3128
3141
  if (!mipmapFilter) {
3129
3142
  return convertMaxFilterMode(minFilter);
3130
3143
  }
3131
- switch (minFilter) {
3144
+ switch (mipmapFilter) {
3145
+ case "none":
3146
+ return convertMaxFilterMode(minFilter);
3132
3147
  case "nearest":
3133
- return mipmapFilter === "nearest" ? 9984 /* NEAREST_MIPMAP_NEAREST */ : 9986 /* NEAREST_MIPMAP_LINEAR */;
3148
+ return minFilter === "nearest" ? 9984 /* NEAREST_MIPMAP_NEAREST */ : 9986 /* NEAREST_MIPMAP_LINEAR */;
3134
3149
  case "linear":
3135
- return mipmapFilter === "nearest" ? 9985 /* LINEAR_MIPMAP_NEAREST */ : 9987 /* LINEAR_MIPMAP_LINEAR */;
3150
+ return minFilter === "nearest" ? 9985 /* LINEAR_MIPMAP_NEAREST */ : 9987 /* LINEAR_MIPMAP_LINEAR */;
3136
3151
  }
3137
3152
  }
3138
3153
 
@@ -3282,14 +3297,20 @@ ${source}`;
3282
3297
  case 6406 /* ALPHA */:
3283
3298
  case 33326 /* R32F */:
3284
3299
  case 6403 /* RED */:
3300
+ case 36244 /* RED_INTEGER */:
3285
3301
  return 1;
3302
+ case 33339 /* RG32I */:
3303
+ case 33340 /* RG32UI */:
3286
3304
  case 33328 /* RG32F */:
3305
+ case 33320 /* RG_INTEGER */:
3287
3306
  case 33319 /* RG */:
3288
3307
  return 2;
3289
3308
  case 6407 /* RGB */:
3309
+ case 36248 /* RGB_INTEGER */:
3290
3310
  case 34837 /* RGB32F */:
3291
3311
  return 3;
3292
3312
  case 6408 /* RGBA */:
3313
+ case 36249 /* RGBA_INTEGER */:
3293
3314
  case 34836 /* RGBA32F */:
3294
3315
  return 4;
3295
3316
  default:
@@ -3331,22 +3352,25 @@ ${source}`;
3331
3352
  const { x = 0, y = 0, z = 0 } = options;
3332
3353
  const { glFormat, glType } = options;
3333
3354
  const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
3334
- switch (dimension) {
3335
- case "2d-array":
3336
- case "3d":
3337
- gl.bindTexture(glTarget, handle);
3338
- gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3339
- gl.bindTexture(glTarget, null);
3340
- break;
3341
- case "2d":
3342
- case "cube":
3343
- gl.bindTexture(glTarget, handle);
3344
- gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3345
- gl.bindTexture(glTarget, null);
3346
- break;
3347
- default:
3348
- throw new Error(dimension);
3349
- }
3355
+ const glParameters = options.flipY ? { [37440 /* UNPACK_FLIP_Y_WEBGL */]: true } : {};
3356
+ withGLParameters(gl, glParameters, () => {
3357
+ switch (dimension) {
3358
+ case "2d-array":
3359
+ case "3d":
3360
+ gl.bindTexture(glTarget, handle);
3361
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3362
+ gl.bindTexture(glTarget, null);
3363
+ break;
3364
+ case "2d":
3365
+ case "cube":
3366
+ gl.bindTexture(glTarget, handle);
3367
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3368
+ gl.bindTexture(glTarget, null);
3369
+ break;
3370
+ default:
3371
+ throw new Error(dimension);
3372
+ }
3373
+ });
3350
3374
  }
3351
3375
  function copyCPUDataToMipLevel(gl, typedArray, options) {
3352
3376
  const { dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0 } = options;
@@ -3398,7 +3422,7 @@ ${source}`;
3398
3422
  const {
3399
3423
  sourceX = 0,
3400
3424
  sourceY = 0,
3401
- sourceAttachment = 36064 /* COLOR_ATTACHMENT0 */
3425
+ sourceAttachment = 0
3402
3426
  // TODO - support gl.readBuffer
3403
3427
  } = options || {};
3404
3428
  let {
@@ -3412,16 +3436,24 @@ ${source}`;
3412
3436
  } = options || {};
3413
3437
  const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
3414
3438
  const { gl, handle } = framebuffer;
3415
- const attachment = sourceAttachment - 36064 /* COLOR_ATTACHMENT0 */;
3416
3439
  sourceWidth ||= framebuffer.width;
3417
3440
  sourceHeight ||= framebuffer.height;
3418
- sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
3419
- sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || 6408 /* RGBA */;
3420
- sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || 5121 /* UNSIGNED_BYTE */;
3441
+ const texture = framebuffer.colorAttachments[sourceAttachment]?.texture;
3442
+ if (!texture) {
3443
+ throw new Error(`Invalid framebuffer attachment ${sourceAttachment}`);
3444
+ }
3445
+ sourceDepth = texture?.depth || 1;
3446
+ sourceFormat ||= texture?.glFormat || 6408 /* RGBA */;
3447
+ sourceType ||= texture?.glType || 5121 /* UNSIGNED_BYTE */;
3421
3448
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
3422
3449
  sourceType = sourceType || getGLTypeFromTypedArray(target2);
3423
- const prevHandle = gl.bindFramebuffer(36160 /* FRAMEBUFFER */, handle);
3450
+ const prevHandle = gl.bindFramebuffer(
3451
+ 36160 /* FRAMEBUFFER */,
3452
+ handle
3453
+ );
3454
+ gl.readBuffer(gl.COLOR_ATTACHMENT0 + sourceAttachment);
3424
3455
  gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target2);
3456
+ gl.readBuffer(gl.COLOR_ATTACHMENT0);
3425
3457
  gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle || null);
3426
3458
  if (deleteFramebuffer) {
3427
3459
  framebuffer.destroy();
@@ -3481,38 +3513,19 @@ ${source}`;
3481
3513
  });
3482
3514
  return framebuffer;
3483
3515
  }
3484
- function getPixelArray(pixelArray, type, format, width, height, depth) {
3516
+ function getPixelArray(pixelArray, glType, glFormat, width, height, depth) {
3485
3517
  if (pixelArray) {
3486
3518
  return pixelArray;
3487
3519
  }
3488
- type = type || 5121 /* UNSIGNED_BYTE */;
3489
- const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
3490
- const components = glFormatToComponents(format);
3520
+ glType ||= 5121 /* UNSIGNED_BYTE */;
3521
+ const ArrayType = getTypedArrayFromGLType(glType, { clamped: false });
3522
+ const components = glFormatToComponents(glFormat);
3491
3523
  return new ArrayType(width * height * components);
3492
3524
  }
3493
3525
 
3494
3526
  // src/adapter/resources/webgl-texture.ts
3495
- function normalizeTextureData(data, options) {
3496
- let lodArray;
3497
- if (ArrayBuffer.isView(data)) {
3498
- lodArray = [
3499
- {
3500
- // ts-expect-error does data really need to be Uint8ClampedArray?
3501
- data,
3502
- width: options.width,
3503
- height: options.height
3504
- // depth: options.depth
3505
- }
3506
- ];
3507
- } else if (!Array.isArray(data)) {
3508
- lodArray = [data];
3509
- } else {
3510
- lodArray = data;
3511
- }
3512
- return lodArray;
3513
- }
3514
3527
  var WEBGLTexture = class extends import_core14.Texture {
3515
- MAX_ATTRIBUTES;
3528
+ // readonly MAX_ATTRIBUTES: number;
3516
3529
  device;
3517
3530
  gl;
3518
3531
  handle;
@@ -3520,8 +3533,12 @@ ${source}`;
3520
3533
  // TODO - currently unused in WebGL. Create dummy sampler?
3521
3534
  view = void 0;
3522
3535
  // TODO - currently unused in WebGL. Create dummy view?
3523
- mipmaps = false;
3536
+ mipmaps;
3537
+ // Texture type
3538
+ /** Whether the internal format is compressed */
3539
+ compressed;
3524
3540
  /**
3541
+ * The WebGL target corresponding to the texture type
3525
3542
  * @note `target` cannot be modified by bind:
3526
3543
  * textures are special because when you first bind them to a target,
3527
3544
  * When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
@@ -3530,122 +3547,79 @@ ${source}`;
3530
3547
  * attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
3531
3548
  */
3532
3549
  glTarget;
3533
- // Texture type
3534
3550
  /** The WebGL format - essentially channel structure */
3535
3551
  glFormat;
3536
3552
  /** The WebGL data format - the type of each channel */
3537
3553
  glType;
3538
3554
  /** The WebGL constant corresponding to the WebGPU style constant in format */
3539
3555
  glInternalFormat;
3540
- /** Whether the internal format is compressed */
3541
- compressed;
3542
- // data;
3543
- // inherited props
3544
- // dimension: ...
3545
- // format: GLTextureTarget;
3546
- // width: number = undefined;
3547
- // height: number = undefined;
3548
- // depth: number = undefined;
3549
3556
  // state
3550
- /** Texture binding slot */
3557
+ /** Texture binding slot - TODO - move to texture view? */
3551
3558
  textureUnit = 0;
3552
- /** For automatically updating video */
3553
- _video = null;
3554
3559
  constructor(device, props) {
3555
- props = import_core14.Texture._fixProps(props);
3556
- super(device, { ...import_core14.Texture.defaultProps, ...props, data: void 0 });
3560
+ super(device, props);
3561
+ const propsWithData = { ...this.props };
3562
+ propsWithData.data = props.data;
3557
3563
  this.device = device;
3558
3564
  this.gl = this.device.gl;
3559
3565
  this.glTarget = getWebGLTextureTarget(this.props.dimension);
3560
- const format = getTextureFormatWebGL(this.props.format);
3561
- this.glInternalFormat = format.internalFormat;
3562
- this.glFormat = format.format;
3563
- this.glType = format.type;
3564
- this.compressed = format.compressed;
3565
- if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
3566
- props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
3567
- const video = props.data;
3568
- this._video = null;
3569
- video.addEventListener("loadeddata", () => this.initialize(props));
3570
- }
3571
- this.initialize({ ...this.props, data: props.data });
3566
+ const formatInfo = getTextureFormatWebGL(this.props.format);
3567
+ this.glInternalFormat = formatInfo.internalFormat;
3568
+ this.glFormat = formatInfo.format;
3569
+ this.glType = formatInfo.type;
3570
+ this.compressed = formatInfo.compressed;
3571
+ this.mipmaps = Boolean(this.props.mipmaps);
3572
+ this._initialize(propsWithData);
3572
3573
  Object.seal(this);
3573
3574
  }
3574
3575
  /**
3575
3576
  * Initialize texture with supplied props
3576
3577
  */
3577
3578
  // eslint-disable-next-line max-statements
3578
- initialize(props = {}) {
3579
+ _initialize(propsWithData) {
3579
3580
  this.handle = this.props.handle || this.gl.createTexture();
3580
- this.device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
3581
- const data = props.data;
3582
- let { width, height } = props;
3581
+ this.device.setSpectorMetadata(this.handle, { ...this.props, data: propsWithData.data });
3582
+ let { width, height } = propsWithData;
3583
3583
  if (!width || !height) {
3584
- const textureSize = import_core14.Texture.getTextureDataSize(data);
3584
+ const textureSize = import_core14.Texture.getTextureDataSize(propsWithData.data);
3585
3585
  width = textureSize?.width || 1;
3586
3586
  height = textureSize?.height || 1;
3587
3587
  }
3588
3588
  this.width = width;
3589
3589
  this.height = height;
3590
- this.depth = props.depth;
3591
- this.setSampler(props.sampler);
3590
+ this.depth = propsWithData.depth;
3591
+ this.setSampler(propsWithData.sampler);
3592
3592
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3593
3593
  this.bind();
3594
- if (!this.props.data) {
3595
- initializeTextureStorage(this.gl, this.mipLevels, this);
3596
- }
3597
- if (props.data) {
3598
- switch (props.dimension) {
3594
+ initializeTextureStorage(this.gl, this.mipLevels, this);
3595
+ if (propsWithData.data) {
3596
+ switch (propsWithData.dimension) {
3599
3597
  case "1d":
3600
- this.setTexture1DData(props.data);
3598
+ this.setTexture1DData(propsWithData.data);
3601
3599
  break;
3602
3600
  case "2d":
3603
- this.setTexture2DData(props.data);
3601
+ this.setTexture2DData(propsWithData.data);
3604
3602
  break;
3605
3603
  case "3d":
3606
- this.setTexture3DData(props.data);
3604
+ this.setTexture3DData(propsWithData.data);
3607
3605
  break;
3608
3606
  case "cube":
3609
- this.setTextureCubeData(props.data);
3607
+ this.setTextureCubeData(propsWithData.data);
3610
3608
  break;
3611
3609
  case "2d-array":
3612
- this.setTextureArrayData(props.data);
3610
+ this.setTextureArrayData(propsWithData.data);
3613
3611
  break;
3614
3612
  case "cube-array":
3615
- this.setTextureCubeArrayData(props.data);
3613
+ this.setTextureCubeArrayData(propsWithData.data);
3616
3614
  break;
3617
3615
  default:
3618
- throw new Error(props.dimension);
3616
+ throw new Error(propsWithData.dimension);
3619
3617
  }
3620
3618
  }
3621
- this.mipmaps = Boolean(props.mipmaps);
3622
3619
  if (this.mipmaps) {
3623
3620
  this.generateMipmap();
3624
3621
  }
3625
3622
  }
3626
- /*
3627
- initializeCube(props?: TextureProps): void {
3628
- const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
3629
-
3630
- // Store props for accessors
3631
- // this.props = props;
3632
-
3633
- // @ts-expect-error
3634
- this.setCubeMapData(props).then(() => {
3635
- // TODO - should genMipmap() be called on the cubemap or on the faces?
3636
- // TODO - without generateMipmap() cube textures do not work at all!!! Why?
3637
- if (mipmaps) {
3638
- this.generateMipmap(props);
3639
- }
3640
-
3641
- this.setSampler(props.sampler);
3642
-
3643
- // v8 compatibility?
3644
- // const {parameters = {} as Record<GL, any>} = props;
3645
- // this._setSamplerParameters(parameters);
3646
- });
3647
- }
3648
- */
3649
3623
  destroy() {
3650
3624
  if (this.handle) {
3651
3625
  this.gl.deleteTexture(this.handle);
@@ -3654,9 +3628,6 @@ ${source}`;
3654
3628
  this.destroyed = true;
3655
3629
  }
3656
3630
  }
3657
- toString() {
3658
- return `Texture(${this.id},${this.width}x${this.height})`;
3659
- }
3660
3631
  createView(props) {
3661
3632
  return new WEBGLTextureView(this.device, { ...props, texture: this });
3662
3633
  }
@@ -3672,35 +3643,33 @@ ${source}`;
3672
3643
  const parameters = convertSamplerParametersToWebGL(samplerProps);
3673
3644
  this._setSamplerParameters(parameters);
3674
3645
  }
3675
- /** Update external texture (video frame or canvas) */
3676
- update() {
3677
- import_core14.log.warn("Texture.update() not implemented");
3678
- }
3679
3646
  // Call to regenerate mipmaps after modifying texture(s)
3680
3647
  generateMipmap(params = {}) {
3681
- if (!this.props.data) {
3682
- return;
3648
+ if (!this.device.isTextureFormatRenderable(this.props.format) || !this.device.isTextureFormatFilterable(this.props.format)) {
3649
+ import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3650
+ }
3651
+ try {
3652
+ this.gl.bindTexture(this.glTarget, this.handle);
3653
+ withGLParameters(this.gl, params, () => {
3654
+ this.gl.generateMipmap(this.glTarget);
3655
+ });
3656
+ } catch (error) {
3657
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3658
+ } finally {
3659
+ this.gl.bindTexture(this.glTarget, null);
3683
3660
  }
3684
- this.mipmaps = true;
3685
- this.gl.bindTexture(this.glTarget, this.handle);
3686
- withGLParameters(this.gl, params, () => {
3687
- this.gl.generateMipmap(this.glTarget);
3688
- });
3689
- this.gl.bindTexture(this.glTarget, null);
3690
3661
  }
3691
3662
  // Image Data Setters
3692
3663
  copyExternalImage(options) {
3693
3664
  const size = import_core14.Texture.getExternalImageSize(options.image);
3694
3665
  const opts = { ...import_core14.Texture.defaultCopyExternalImageOptions, ...size, ...options };
3695
- const { image, depth, mipLevel, x, y, z } = opts;
3666
+ const { image, depth, mipLevel, x, y, z, flipY } = opts;
3696
3667
  let { width, height } = opts;
3697
3668
  const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
3698
3669
  width = Math.min(width, size.width - x);
3699
3670
  height = Math.min(height, size.height - y);
3700
3671
  if (options.sourceX || options.sourceY) {
3701
- throw new Error(
3702
- "WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer"
3703
- );
3672
+ throw new Error("WebGL does not support sourceX/sourceY)");
3704
3673
  }
3705
3674
  copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
3706
3675
  dimension,
@@ -3714,7 +3683,8 @@ ${source}`;
3714
3683
  glFormat,
3715
3684
  glInternalFormat,
3716
3685
  glType,
3717
- glTarget
3686
+ glTarget,
3687
+ flipY
3718
3688
  });
3719
3689
  return { width: opts.width, height: opts.height };
3720
3690
  }
@@ -3724,7 +3694,7 @@ ${source}`;
3724
3694
  /** Set a simple texture */
3725
3695
  setTexture2DData(lodData, depth = 0) {
3726
3696
  this.bind();
3727
- const lodArray = normalizeTextureData(lodData, this);
3697
+ const lodArray = import_core14.Texture.normalizeTextureData(lodData, this);
3728
3698
  if (lodArray.length > 1 && this.props.mipmaps !== false) {
3729
3699
  import_core14.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
3730
3700
  }
@@ -3786,6 +3756,11 @@ ${source}`;
3786
3756
  const faceDepth = import_core14.Texture.CubeFaces.indexOf(face);
3787
3757
  this.setTexture2DData(lodData, faceDepth);
3788
3758
  }
3759
+ // DEPRECATED METHODS
3760
+ /** Update external texture (video frame or canvas) @deprecated Use ExternalTexture */
3761
+ update() {
3762
+ throw new Error("Texture.update() not implemented. Use ExternalTexture");
3763
+ }
3789
3764
  // INTERNAL METHODS
3790
3765
  /** @todo update this method to accept LODs */
3791
3766
  setImageDataForFace(options) {
@@ -3833,7 +3808,7 @@ ${source}`;
3833
3808
  * Sets sampler parameters on texture
3834
3809
  */
3835
3810
  _setSamplerParameters(parameters) {
3836
- import_core14.log.log(1, "texture sampler parameters", parameters)();
3811
+ import_core14.log.log(1, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3837
3812
  this.gl.bindTexture(this.glTarget, this.handle);
3838
3813
  for (const [pname, pvalue] of Object.entries(parameters)) {
3839
3814
  const param = Number(pname);
@@ -3862,61 +3837,6 @@ ${source}`;
3862
3837
  }
3863
3838
  this.gl.bindTexture(this.glTarget, null);
3864
3839
  }
3865
- // CLASSIC
3866
- /*
3867
- setCubeMapData(options: {
3868
- width: number;
3869
- height: number;
3870
- data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
3871
- format?: any;
3872
- type?: any;
3873
- /** @deprecated Use .data *
3874
- pixels: any;
3875
- }): void {
3876
- const {gl} = this;
3877
-
3878
- const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
3879
-
3880
- // pixel data (imageDataMap) is an Object from Face to Image or Promise.
3881
- // For example:
3882
- // {
3883
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
3884
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
3885
- // ... }
3886
- // To provide multiple level-of-details (LODs) this can be Face to Array
3887
- // of Image or Promise, like this
3888
- // {
3889
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3890
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3891
- // ... }
3892
-
3893
- const imageDataMap = this._getImageDataMap(pixels || data);
3894
-
3895
- const resolvedFaces = WEBGLTexture.FACES.map(face => {
3896
- const facePixels = imageDataMap[face];
3897
- return Array.isArray(facePixels) ? facePixels : [facePixels];
3898
- });
3899
- this.bind();
3900
-
3901
- WEBGLTexture.FACES.forEach((face, index) => {
3902
- if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
3903
- // If the user provides multiple LODs, then automatic mipmap
3904
- // generation generateMipmap() should be disabled to avoid overwritting them.
3905
- log.warn(`${this.id} has mipmap and multiple LODs.`)();
3906
- }
3907
- resolvedFaces[index].forEach((image, lodLevel) => {
3908
- // TODO: adjust width & height for LOD!
3909
- if (width && height) {
3910
- gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
3911
- } else {
3912
- gl.texImage2D(face, lodLevel, format, format, type, image);
3913
- }
3914
- });
3915
- });
3916
-
3917
- this.unbind();
3918
- }
3919
- */
3920
3840
  // INTERNAL SETTERS
3921
3841
  /**
3922
3842
  * Copy a region of data from a CPU memory buffer into this texture.
@@ -3928,7 +3848,8 @@ ${source}`;
3928
3848
  ...this,
3929
3849
  depth,
3930
3850
  mipLevel,
3931
- glTarget
3851
+ glTarget,
3852
+ flipY: this.props.flipY
3932
3853
  });
3933
3854
  return;
3934
3855
  }
@@ -3969,10 +3890,6 @@ ${source}`;
3969
3890
 
3970
3891
  // src/adapter/resources/webgl-render-pass.ts
3971
3892
  var import_core15 = __toESM(require_core(), 1);
3972
- var GL_DEPTH_BUFFER_BIT = 256;
3973
- var GL_STENCIL_BUFFER_BIT = 1024;
3974
- var GL_COLOR_BUFFER_BIT = 16384;
3975
- var GL_COLOR = 6144;
3976
3893
  var COLOR_CHANNELS = [1, 2, 4, 8];
3977
3894
  var WEBGLRenderPass = class extends import_core15.RenderPass {
3978
3895
  device;
@@ -3993,6 +3910,14 @@ ${source}`;
3993
3910
  }
3994
3911
  this.device.pushState();
3995
3912
  this.setParameters({ viewport, ...this.props.parameters });
3913
+ if (this.props.framebuffer) {
3914
+ const drawBuffers = this.props.framebuffer.colorAttachments.map(
3915
+ (_, i) => 36064 /* COLOR_ATTACHMENT0 */ + i
3916
+ );
3917
+ this.device.gl.drawBuffers(drawBuffers);
3918
+ } else {
3919
+ this.device.gl.drawBuffers([1029 /* BACK */]);
3920
+ }
3996
3921
  this.clear();
3997
3922
  }
3998
3923
  end() {
@@ -4058,19 +3983,30 @@ ${source}`;
4058
3983
  * Optionally clears depth, color and stencil buffers based on parameters
4059
3984
  */
4060
3985
  clear() {
3986
+ const DEFAULT_CLEAR_COLOR = [0, 0, 0, 1];
3987
+ const DEFAULT_CLEAR_DEPTH = 1;
3988
+ const DEFAULT_CLEAR_STENCIL = 0;
4061
3989
  const glParameters = { ...this.glParameters };
4062
3990
  let clearMask = 0;
4063
- if (this.props.clearColor !== false) {
4064
- clearMask |= GL_COLOR_BUFFER_BIT;
4065
- glParameters.clearColor = this.props.clearColor;
3991
+ if (this.props.clearColors) {
3992
+ this.props.clearColors.forEach((color, drawBufferIndex) => {
3993
+ if (color) {
3994
+ this.clearColorBuffer(drawBufferIndex, color);
3995
+ }
3996
+ });
3997
+ }
3998
+ if (this.props.clearColor !== false && this.props.clearColors === void 0) {
3999
+ clearMask |= 16384 /* COLOR_BUFFER_BIT */;
4000
+ const clearColor = this.props.clearColor === true ? DEFAULT_CLEAR_COLOR : this.props.clearColor;
4001
+ glParameters.clearColor = clearColor;
4066
4002
  }
4067
4003
  if (this.props.clearDepth !== false) {
4068
- clearMask |= GL_DEPTH_BUFFER_BIT;
4069
- glParameters.clearDepth = this.props.clearDepth;
4004
+ clearMask |= 256 /* DEPTH_BUFFER_BIT */;
4005
+ glParameters.clearDepth = this.props.clearDepth === true ? DEFAULT_CLEAR_DEPTH : this.props.clearDepth;
4070
4006
  }
4071
4007
  if (this.props.clearStencil !== false) {
4072
- clearMask |= GL_STENCIL_BUFFER_BIT;
4073
- glParameters.clearStencil = this.props.clearStencil;
4008
+ clearMask |= 1024 /* STENCIL_BUFFER_BIT */;
4009
+ glParameters.clearStencil = this.props.clearStencil === true ? DEFAULT_CLEAR_STENCIL : this.props.clearStencil;
4074
4010
  }
4075
4011
  if (clearMask !== 0) {
4076
4012
  withGLParameters(this.device.gl, glParameters, () => {
@@ -4084,21 +4020,27 @@ ${source}`;
4084
4020
  clearColorBuffer(drawBuffer = 0, value = [0, 0, 0, 0]) {
4085
4021
  withGLParameters(this.device.gl, { framebuffer: this.props.framebuffer }, () => {
4086
4022
  switch (value.constructor) {
4023
+ case Int8Array:
4024
+ case Int16Array:
4087
4025
  case Int32Array:
4088
- this.device.gl.clearBufferiv(GL_COLOR, drawBuffer, value);
4026
+ this.device.gl.clearBufferiv(6144 /* COLOR */, drawBuffer, value);
4089
4027
  break;
4028
+ case Uint8Array:
4029
+ case Uint8ClampedArray:
4030
+ case Uint16Array:
4090
4031
  case Uint32Array:
4091
- this.device.gl.clearBufferuiv(GL_COLOR, drawBuffer, value);
4032
+ this.device.gl.clearBufferuiv(6144 /* COLOR */, drawBuffer, value);
4092
4033
  break;
4093
4034
  case Float32Array:
4094
- default:
4095
- this.device.gl.clearBufferfv(GL_COLOR, drawBuffer, value);
4035
+ this.device.gl.clearBufferfv(6144 /* COLOR */, drawBuffer, value);
4096
4036
  break;
4037
+ default:
4038
+ throw new Error("clearColorBuffer: color must be typed array");
4097
4039
  }
4098
4040
  });
4099
4041
  }
4100
4042
  // clearDepthStencil() {
4101
- // const GL_DEPTH = 0x1801;
4043
+ // const GL.DEPTH = 0x1801;
4102
4044
  // const GL_STENCIL = 0x1802;
4103
4045
  // const GL_DEPTH_STENCIL = 0x84f9;
4104
4046
  // case GL_DEPTH:
@@ -4831,11 +4773,6 @@ ${source}`;
4831
4773
  texturesRenderable = false;
4832
4774
  }
4833
4775
  }
4834
- for (const [, texture] of Object.entries(this.bindings)) {
4835
- if (texture instanceof WEBGLTexture) {
4836
- texture.update();
4837
- }
4838
- }
4839
4776
  return texturesRenderable;
4840
4777
  }
4841
4778
  /** Apply any bindings (before each draw call) */
@@ -4963,6 +4900,8 @@ ${source}`;
4963
4900
  case "copy-texture-to-texture":
4964
4901
  _copyTextureToTexture(this.device, command.options);
4965
4902
  break;
4903
+ default:
4904
+ throw new Error(command.name);
4966
4905
  }
4967
4906
  }
4968
4907
  }
@@ -5179,6 +5118,9 @@ ${source}`;
5179
5118
  copyTextureToTexture(options) {
5180
5119
  this.commandBuffer.commands.push({ name: "copy-texture-to-texture", options });
5181
5120
  }
5121
+ // clearTexture(options: ClearTextureOptions): void {
5122
+ // this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
5123
+ // }
5182
5124
  pushDebugGroup(groupLabel) {
5183
5125
  }
5184
5126
  popDebugGroup() {
@@ -5695,9 +5637,9 @@ ${source}`;
5695
5637
 
5696
5638
  // src/deprecated/clear.ts
5697
5639
  var import_core22 = __toESM(require_core(), 1);
5698
- var GL_DEPTH_BUFFER_BIT2 = 256;
5699
- var GL_STENCIL_BUFFER_BIT2 = 1024;
5700
- var GL_COLOR_BUFFER_BIT2 = 16384;
5640
+ var GL_DEPTH_BUFFER_BIT = 256;
5641
+ var GL_STENCIL_BUFFER_BIT = 1024;
5642
+ var GL_COLOR_BUFFER_BIT = 16384;
5701
5643
  function clear(device, options) {
5702
5644
  import_core22.log.warn("clear will be removed in next minor release");
5703
5645
  const { framebuffer = null, color = null, depth = null, stencil = null } = options || {};
@@ -5707,19 +5649,19 @@ ${source}`;
5707
5649
  }
5708
5650
  let clearFlags = 0;
5709
5651
  if (color) {
5710
- clearFlags |= GL_COLOR_BUFFER_BIT2;
5652
+ clearFlags |= GL_COLOR_BUFFER_BIT;
5711
5653
  if (color !== true) {
5712
5654
  parameters.clearColor = color;
5713
5655
  }
5714
5656
  }
5715
5657
  if (depth) {
5716
- clearFlags |= GL_DEPTH_BUFFER_BIT2;
5658
+ clearFlags |= GL_DEPTH_BUFFER_BIT;
5717
5659
  if (depth !== true) {
5718
5660
  parameters.clearDepth = depth;
5719
5661
  }
5720
5662
  }
5721
5663
  if (stencil) {
5722
- clearFlags |= GL_STENCIL_BUFFER_BIT2;
5664
+ clearFlags |= GL_STENCIL_BUFFER_BIT;
5723
5665
  if (depth !== true) {
5724
5666
  parameters.clearStencil = depth;
5725
5667
  }
@@ -5818,11 +5760,14 @@ ${source}`;
5818
5760
  log: (...args) => import_core23.log.log(1, ...args)()
5819
5761
  });
5820
5762
  glState.trackState(this.gl, { copyState: false });
5821
- if (props.debugWebGL) {
5822
- this.gl = makeDebugContext(this.gl, { ...props });
5823
- this.debug = true;
5824
- import_core23.log.level = Math.max(import_core23.log.level, 1);
5763
+ const debugWebGL = props.debugWebGL || props.debug;
5764
+ const traceWebGL = props.debugWebGL;
5765
+ if (debugWebGL) {
5766
+ this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
5825
5767
  import_core23.log.warn("WebGL debug mode activated. Performance reduced.")();
5768
+ if (props.debugWebGL) {
5769
+ import_core23.log.level = Math.max(import_core23.log.level, 1);
5770
+ }
5826
5771
  }
5827
5772
  }
5828
5773
  /**
@@ -5970,15 +5915,24 @@ ${source}`;
5970
5915
  * Be aware that there are some duplicates especially for constants that are 0,
5971
5916
  * so this isn't guaranteed to return the right key in all cases.
5972
5917
  */
5973
- getGLKey(value, gl) {
5974
- gl = gl || this.gl2 || this.gl;
5918
+ getGLKey(value, options) {
5975
5919
  const number = Number(value);
5976
- for (const key in gl) {
5977
- if (gl[key] === number) {
5920
+ for (const key in this.gl) {
5921
+ if (this.gl[key] === number) {
5978
5922
  return `GL.${key}`;
5979
5923
  }
5980
5924
  }
5981
- return String(value);
5925
+ return options?.emptyIfUnknown ? "" : String(value);
5926
+ }
5927
+ /**
5928
+ * Returns a map with any GL.<KEY> constants mapped to strings, both for keys and values
5929
+ */
5930
+ getGLKeys(glParameters) {
5931
+ const opts = { emptyIfUnknown: true };
5932
+ return Object.entries(glParameters).reduce((keys, [key, value]) => {
5933
+ keys[`${key}:${this.getGLKey(key, opts)}`] = `${value}:${this.getGLKey(value, opts)}`;
5934
+ return keys;
5935
+ }, {});
5982
5936
  }
5983
5937
  /** Store constants */
5984
5938
  _constants;
@@ -6197,7 +6151,7 @@ ${source}`;
6197
6151
  async create(props = {}) {
6198
6152
  import_core24.log.groupCollapsed(LOG_LEVEL2, "WebGLDevice created")();
6199
6153
  const promises = [];
6200
- if (props.debugWebGL) {
6154
+ if (props.debugWebGL || props.debug) {
6201
6155
  promises.push(loadWebGLDeveloperTools());
6202
6156
  }
6203
6157
  if (props.debugSpectorJS) {