@deck.gl/google-maps 9.2.11 → 9.3.0-alpha.2

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.
package/dist/dist.dev.js CHANGED
@@ -717,6 +717,23 @@ var __exports__ = (() => {
717
717
  }
718
718
  });
719
719
 
720
+ // ../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js
721
+ function getWebGLContextData(gl) {
722
+ const contextData = gl.luma || {
723
+ _polyfilled: false,
724
+ extensions: {},
725
+ softwareRenderer: false
726
+ };
727
+ contextData._polyfilled ??= false;
728
+ contextData.extensions ||= {};
729
+ gl.luma = contextData;
730
+ return contextData;
731
+ }
732
+ var init_webgl_context_data = __esm({
733
+ "../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js"() {
734
+ }
735
+ });
736
+
720
737
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js
721
738
  function initializeSpectorJS(props) {
722
739
  props = { ...DEFAULT_SPECTOR_PROPS, ...props };
@@ -747,9 +764,10 @@ var __exports__ = (() => {
747
764
  }
748
765
  if (props.gl) {
749
766
  const gl = props.gl;
750
- const device = gl.device;
767
+ const contextData = getWebGLContextData(gl);
768
+ const device = contextData.device;
751
769
  spector?.startCapture(props.gl, 500);
752
- gl.device = device;
770
+ contextData.device = device;
753
771
  new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
754
772
  import_core2.log.info("Spector capture stopped after 2 seconds")();
755
773
  spector?.stopCapture();
@@ -761,6 +779,7 @@ var __exports__ = (() => {
761
779
  var init_spector = __esm({
762
780
  "../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js"() {
763
781
  import_core2 = __toESM(require_core2(), 1);
782
+ init_webgl_context_data();
764
783
  LOG_LEVEL = 1;
765
784
  spector = null;
766
785
  initialized = false;
@@ -856,7 +875,7 @@ var __exports__ = (() => {
856
875
  });
857
876
 
858
877
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/webgl-developer-tools.js
859
- function getWebGLContextData(gl) {
878
+ function getWebGLContextData2(gl) {
860
879
  gl.luma = gl.luma || {};
861
880
  return gl.luma;
862
881
  }
@@ -864,7 +883,7 @@ var __exports__ = (() => {
864
883
  return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
865
884
  }
866
885
  function getRealContext(gl) {
867
- const data = getWebGLContextData(gl);
886
+ const data = getWebGLContextData2(gl);
868
887
  return data.realContext ? data.realContext : gl;
869
888
  }
870
889
  function getDebugContext(gl, props) {
@@ -872,7 +891,7 @@ var __exports__ = (() => {
872
891
  import_core3.log.warn("webgl-debug not loaded")();
873
892
  return gl;
874
893
  }
875
- const data = getWebGLContextData(gl);
894
+ const data = getWebGLContextData2(gl);
876
895
  if (data.debugContext) {
877
896
  return data.debugContext;
878
897
  }
@@ -890,6 +909,7 @@ var __exports__ = (() => {
890
909
  const debugContext = Object.create(WebGLDebugContext);
891
910
  data.realContext = gl;
892
911
  data.debugContext = debugContext;
912
+ debugContext.luma = data;
893
913
  debugContext.debug = true;
894
914
  return debugContext;
895
915
  }
@@ -904,16 +924,15 @@ var __exports__ = (() => {
904
924
  const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
905
925
  const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
906
926
  const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
907
- import_core3.log.error(message2)();
927
+ import_core3.log.error("%cWebGL", "color: white; background: red; padding: 2px 6px; border-radius: 3px;", message2)();
908
928
  debugger;
929
+ throw new Error(message2);
909
930
  }
910
931
  function onValidateGLFunc(props, functionName, functionArgs) {
911
932
  let functionString = "";
912
- if (import_core3.log.level >= 1) {
933
+ if (props.traceWebGL && import_core3.log.level >= 1) {
913
934
  functionString = getFunctionString(functionName, functionArgs);
914
- if (props.traceWebGL) {
915
- import_core3.log.log(1, functionString)();
916
- }
935
+ import_core3.log.info(1, "%cWebGL", "color: white; background: blue; padding: 2px 6px; border-radius: 3px;", functionString)();
917
936
  }
918
937
  for (const arg of functionArgs) {
919
938
  if (arg === void 0) {
@@ -1421,7 +1440,7 @@ var __exports__ = (() => {
1421
1440
  }
1422
1441
  }
1423
1442
  }
1424
- const cache = gl.state && gl.state.cache;
1443
+ const cache = gl.lumaState?.cache;
1425
1444
  if (cache) {
1426
1445
  for (const key in compositeSetters) {
1427
1446
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -1541,7 +1560,7 @@ var __exports__ = (() => {
1541
1560
  init_webgl_parameter_tables();
1542
1561
  WebGLStateTracker = class {
1543
1562
  static get(gl) {
1544
- return gl.state;
1563
+ return gl.lumaState;
1545
1564
  }
1546
1565
  gl;
1547
1566
  program = null;
@@ -1579,7 +1598,7 @@ var __exports__ = (() => {
1579
1598
  throw new Error("WebGLStateTracker");
1580
1599
  }
1581
1600
  this.initialized = true;
1582
- this.gl.state = this;
1601
+ this.gl.lumaState = this;
1583
1602
  installProgramSpy(gl);
1584
1603
  for (const key in GL_HOOKED_SETTERS) {
1585
1604
  const setter = GL_HOOKED_SETTERS[key];
@@ -1619,41 +1638,56 @@ var __exports__ = (() => {
1619
1638
  // ../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js
1620
1639
  function createBrowserContext(canvas, props, webglContextAttributes) {
1621
1640
  let errorMessage = "";
1641
+ const onCreateError = (event) => {
1642
+ const statusMessage = event.statusMessage;
1643
+ if (statusMessage) {
1644
+ errorMessage ||= statusMessage;
1645
+ }
1646
+ };
1647
+ canvas.addEventListener("webglcontextcreationerror", onCreateError, false);
1648
+ const allowSoftwareRenderer = webglContextAttributes.failIfMajorPerformanceCaveat !== true;
1622
1649
  const webglProps = {
1623
1650
  preserveDrawingBuffer: true,
1624
- // failIfMajorPerformanceCaveat: true,
1625
- ...webglContextAttributes
1651
+ ...webglContextAttributes,
1652
+ // Always start by requesting a high-performance context.
1653
+ failIfMajorPerformanceCaveat: true
1626
1654
  };
1627
1655
  let gl = null;
1628
- gl ||= canvas.getContext("webgl2", webglProps);
1629
- if (webglProps.failIfMajorPerformanceCaveat) {
1630
- errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1631
- }
1632
- if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
1633
- webglProps.failIfMajorPerformanceCaveat = false;
1634
- gl = canvas.getContext("webgl2", webglProps);
1635
- gl.luma ||= {};
1636
- gl.luma.softwareRenderer = true;
1637
- }
1638
- if (!gl) {
1639
- gl = canvas.getContext("webgl", {});
1640
- if (gl) {
1641
- gl = null;
1642
- errorMessage ||= "Your browser only supports WebGL1";
1656
+ try {
1657
+ gl ||= canvas.getContext("webgl2", webglProps);
1658
+ if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1659
+ errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1643
1660
  }
1661
+ let softwareRenderer = false;
1662
+ if (!gl && allowSoftwareRenderer) {
1663
+ webglProps.failIfMajorPerformanceCaveat = false;
1664
+ gl = canvas.getContext("webgl2", webglProps);
1665
+ softwareRenderer = true;
1666
+ }
1667
+ if (!gl) {
1668
+ gl = canvas.getContext("webgl", {});
1669
+ if (gl) {
1670
+ gl = null;
1671
+ errorMessage ||= "Your browser only supports WebGL1";
1672
+ }
1673
+ }
1674
+ if (!gl) {
1675
+ errorMessage ||= "Your browser does not support WebGL";
1676
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1677
+ }
1678
+ const luma = getWebGLContextData(gl);
1679
+ luma.softwareRenderer = softwareRenderer;
1680
+ const { onContextLost, onContextRestored } = props;
1681
+ canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1682
+ canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1683
+ return gl;
1684
+ } finally {
1685
+ canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
1644
1686
  }
1645
- if (!gl) {
1646
- errorMessage ||= "Your browser does not support WebGL";
1647
- throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1648
- }
1649
- const { onContextLost, onContextRestored } = props;
1650
- canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1651
- canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1652
- gl.luma ||= {};
1653
- return gl;
1654
1687
  }
1655
1688
  var init_create_browser_context = __esm({
1656
1689
  "../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js"() {
1690
+ init_webgl_context_data();
1657
1691
  }
1658
1692
  });
1659
1693
 
@@ -1730,6 +1764,8 @@ var __exports__ = (() => {
1730
1764
  }
1731
1765
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1732
1766
  switch (gpuVendor) {
1767
+ case "apple":
1768
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1733
1769
  case "intel":
1734
1770
  return "integrated";
1735
1771
  case "software":
@@ -1740,6 +1776,9 @@ var __exports__ = (() => {
1740
1776
  return "discrete";
1741
1777
  }
1742
1778
  }
1779
+ function isAppleSiliconGPU(vendor, renderer) {
1780
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1781
+ }
1743
1782
  var init_webgl_device_info = __esm({
1744
1783
  "../../node_modules/@luma.gl/webgl/dist/adapter/device-helpers/webgl-device-info.js"() {
1745
1784
  init_webgl_extensions();
@@ -1786,8 +1825,23 @@ var __exports__ = (() => {
1786
1825
  return feature in TEXTURE_FEATURES;
1787
1826
  }
1788
1827
  function checkTextureFeature(gl, feature, extensions) {
1789
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1790
- return textureExtensions.every((extension) => getWebGLExtension(gl, extension, extensions));
1828
+ return hasTextureFeature(gl, feature, extensions, /* @__PURE__ */ new Set());
1829
+ }
1830
+ function hasTextureFeature(gl, feature, extensions, seenFeatures) {
1831
+ const definition = TEXTURE_FEATURES[feature];
1832
+ if (!definition) {
1833
+ return false;
1834
+ }
1835
+ if (seenFeatures.has(feature)) {
1836
+ return false;
1837
+ }
1838
+ seenFeatures.add(feature);
1839
+ const hasDependentFeatures = (definition.features || []).every((dependentFeature) => hasTextureFeature(gl, dependentFeature, extensions, seenFeatures));
1840
+ seenFeatures.delete(feature);
1841
+ if (!hasDependentFeatures) {
1842
+ return false;
1843
+ }
1844
+ return (definition.extensions || []).every((extension) => Boolean(getWebGLExtension(gl, extension, extensions)));
1791
1845
  }
1792
1846
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1793
1847
  let supported = formatSupport.create;
@@ -1798,12 +1852,17 @@ var __exports__ = (() => {
1798
1852
  if (webglFormatInfo?.x) {
1799
1853
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1800
1854
  }
1855
+ if (formatSupport.format === "stencil8") {
1856
+ supported = false;
1857
+ }
1858
+ const renderFeatureSupported = webglFormatInfo?.r === false ? false : webglFormatInfo?.r === void 0 || checkTextureFeature(gl, webglFormatInfo.r, extensions);
1859
+ const renderable = supported && formatSupport.render && renderFeatureSupported && isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
1801
1860
  return {
1802
1861
  format: formatSupport.format,
1803
1862
  // @ts-ignore
1804
1863
  create: supported && formatSupport.create,
1805
1864
  // @ts-ignore
1806
- render: supported && formatSupport.render,
1865
+ render: renderable,
1807
1866
  // @ts-ignore
1808
1867
  filter: supported && formatSupport.filter,
1809
1868
  // @ts-ignore
@@ -1812,6 +1871,45 @@ var __exports__ = (() => {
1812
1871
  store: supported && formatSupport.store
1813
1872
  };
1814
1873
  }
1874
+ function isColorRenderableTextureFormat(gl, format, extensions) {
1875
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
1876
+ const internalFormat = webglFormatInfo?.gl;
1877
+ if (internalFormat === void 0) {
1878
+ return false;
1879
+ }
1880
+ if (webglFormatInfo?.x && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
1881
+ return false;
1882
+ }
1883
+ const previousTexture = gl.getParameter(32873);
1884
+ const previousFramebuffer = gl.getParameter(36006);
1885
+ const texture = gl.createTexture();
1886
+ const framebuffer = gl.createFramebuffer();
1887
+ if (!texture || !framebuffer) {
1888
+ return false;
1889
+ }
1890
+ const noError = Number(0);
1891
+ let error = Number(gl.getError());
1892
+ while (error !== noError) {
1893
+ error = gl.getError();
1894
+ }
1895
+ let renderable = false;
1896
+ try {
1897
+ gl.bindTexture(3553, texture);
1898
+ gl.texStorage2D(3553, 1, internalFormat, 1, 1);
1899
+ if (Number(gl.getError()) !== noError) {
1900
+ return false;
1901
+ }
1902
+ gl.bindFramebuffer(36160, framebuffer);
1903
+ gl.framebufferTexture2D(36160, 36064, 3553, texture, 0);
1904
+ renderable = Number(gl.checkFramebufferStatus(36160)) === Number(36053) && Number(gl.getError()) === noError;
1905
+ } finally {
1906
+ gl.bindFramebuffer(36160, previousFramebuffer);
1907
+ gl.deleteFramebuffer(framebuffer);
1908
+ gl.bindTexture(3553, previousTexture);
1909
+ gl.deleteTexture(texture);
1910
+ }
1911
+ return renderable;
1912
+ }
1815
1913
  function getTextureFormatWebGL(format) {
1816
1914
  const formatData = WEBGL_TEXTURE_FORMATS[format];
1817
1915
  const webglFormat = convertTextureFormatToGL(format);
@@ -1867,7 +1965,7 @@ var __exports__ = (() => {
1867
1965
  }
1868
1966
  return webglFormat;
1869
1967
  }
1870
- var import_core4, 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;
1968
+ var import_core4, 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;
1871
1969
  var init_webgl_texture_table = __esm({
1872
1970
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-texture-table.js"() {
1873
1971
  import_core4 = __toESM(require_core2(), 1);
@@ -1885,44 +1983,51 @@ var __exports__ = (() => {
1885
1983
  EXT_texture_norm16 = "EXT_texture_norm16";
1886
1984
  EXT_render_snorm = "EXT_render_snorm";
1887
1985
  EXT_color_buffer_float = "EXT_color_buffer_float";
1986
+ SNORM8_COLOR_RENDERABLE = "snorm8-renderable-webgl";
1987
+ NORM16_COLOR_RENDERABLE = "norm16-renderable-webgl";
1988
+ SNORM16_COLOR_RENDERABLE = "snorm16-renderable-webgl";
1989
+ FLOAT16_COLOR_RENDERABLE = "float16-renderable-webgl";
1990
+ FLOAT32_COLOR_RENDERABLE = "float32-renderable-webgl";
1991
+ RGB9E5UFLOAT_COLOR_RENDERABLE = "rgb9e5ufloat-renderable-webgl";
1888
1992
  TEXTURE_FEATURES = {
1889
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1890
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1891
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1892
- "snorm8-renderable-webgl": [EXT_render_snorm],
1893
- "norm16-renderable-webgl": [EXT_texture_norm16],
1894
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1895
- "float32-filterable": ["OES_texture_float_linear"],
1896
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1897
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1898
- "texture-blend-float-webgl": ["EXT_float_blend"],
1899
- "texture-compression-bc": [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
1993
+ "float32-renderable-webgl": { extensions: [EXT_color_buffer_float] },
1994
+ "float16-renderable-webgl": { extensions: ["EXT_color_buffer_half_float"] },
1995
+ "rgb9e5ufloat-renderable-webgl": { extensions: ["WEBGL_render_shared_exponent"] },
1996
+ "snorm8-renderable-webgl": { extensions: [EXT_render_snorm] },
1997
+ "norm16-webgl": { extensions: [EXT_texture_norm16] },
1998
+ "norm16-renderable-webgl": { features: ["norm16-webgl"] },
1999
+ "snorm16-renderable-webgl": { features: ["norm16-webgl"], extensions: [EXT_render_snorm] },
2000
+ "float32-filterable": { extensions: ["OES_texture_float_linear"] },
2001
+ "float16-filterable-webgl": { extensions: ["OES_texture_half_float_linear"] },
2002
+ "texture-filterable-anisotropic-webgl": { extensions: ["EXT_texture_filter_anisotropic"] },
2003
+ "texture-blend-float-webgl": { extensions: ["EXT_float_blend"] },
2004
+ "texture-compression-bc": { extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC] },
1900
2005
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1901
2006
  // 'texture-compression-bc3-webgl': [X_S3TC],
1902
- "texture-compression-bc5-webgl": [X_RGTC],
1903
- "texture-compression-bc7-webgl": [X_BPTC],
1904
- "texture-compression-etc2": [X_ETC2],
1905
- "texture-compression-astc": [X_ASTC],
1906
- "texture-compression-etc1-webgl": [X_ETC1],
1907
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1908
- "texture-compression-atc-webgl": [X_ATC]
2007
+ "texture-compression-bc5-webgl": { extensions: [X_RGTC] },
2008
+ "texture-compression-bc7-webgl": { extensions: [X_BPTC] },
2009
+ "texture-compression-etc2": { extensions: [X_ETC2] },
2010
+ "texture-compression-astc": { extensions: [X_ASTC] },
2011
+ "texture-compression-etc1-webgl": { extensions: [X_ETC1] },
2012
+ "texture-compression-pvrtc-webgl": { extensions: [X_PVRTC] },
2013
+ "texture-compression-atc-webgl": { extensions: [X_ATC] }
1909
2014
  };
1910
2015
  WEBGL_TEXTURE_FORMATS = {
1911
2016
  // 8-bit formats
1912
2017
  "r8unorm": { gl: 33321, rb: true },
1913
- "r8snorm": { gl: 36756 },
2018
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1914
2019
  "r8uint": { gl: 33330, rb: true },
1915
2020
  "r8sint": { gl: 33329, rb: true },
1916
2021
  // 16-bit formats
1917
2022
  "rg8unorm": { gl: 33323, rb: true },
1918
- "rg8snorm": { gl: 36757 },
2023
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1919
2024
  "rg8uint": { gl: 33336, rb: true },
1920
2025
  "rg8sint": { gl: 33335, rb: true },
1921
2026
  "r16uint": { gl: 33332, rb: true },
1922
2027
  "r16sint": { gl: 33331, rb: true },
1923
- "r16float": { gl: 33325, rb: true },
1924
- "r16unorm": { gl: 33322, rb: true },
1925
- "r16snorm": { gl: 36760 },
2028
+ "r16float": { gl: 33325, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2029
+ "r16unorm": { gl: 33322, rb: true, r: NORM16_COLOR_RENDERABLE },
2030
+ "r16snorm": { gl: 36760, r: SNORM16_COLOR_RENDERABLE },
1926
2031
  // Packed 16-bit formats
1927
2032
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1928
2033
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1933,7 +2038,7 @@ var __exports__ = (() => {
1933
2038
  // 32-bit formats
1934
2039
  "rgba8unorm": { gl: 32856 },
1935
2040
  "rgba8unorm-srgb": { gl: 35907 },
1936
- "rgba8snorm": { gl: 36759 },
2041
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1937
2042
  "rgba8uint": { gl: 36220 },
1938
2043
  "rgba8sint": { gl: 36238 },
1939
2044
  // reverse colors, webgpu only
@@ -1941,38 +2046,38 @@ var __exports__ = (() => {
1941
2046
  "bgra8unorm-srgb": {},
1942
2047
  "rg16uint": { gl: 33338 },
1943
2048
  "rg16sint": { gl: 33337 },
1944
- "rg16float": { gl: 33327, rb: true },
1945
- "rg16unorm": { gl: 33324 },
1946
- "rg16snorm": { gl: 36761 },
2049
+ "rg16float": { gl: 33327, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2050
+ "rg16unorm": { gl: 33324, r: NORM16_COLOR_RENDERABLE },
2051
+ "rg16snorm": { gl: 36761, r: SNORM16_COLOR_RENDERABLE },
1947
2052
  "r32uint": { gl: 33334, rb: true },
1948
2053
  "r32sint": { gl: 33333, rb: true },
1949
- "r32float": { gl: 33326 },
2054
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1950
2055
  // Packed 32-bit formats
1951
- "rgb9e5ufloat": { gl: 35901 },
2056
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1952
2057
  // , filter: true},
1953
2058
  "rg11b10ufloat": { gl: 35898, rb: true },
1954
2059
  "rgb10a2unorm": { gl: 32857, rb: true },
1955
2060
  "rgb10a2uint": { gl: 36975, rb: true },
1956
2061
  // 48-bit formats
1957
- "rgb16unorm-webgl": { gl: 32852 },
2062
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1958
2063
  // rgb not renderable
1959
- "rgb16snorm-webgl": { gl: 36762 },
2064
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1960
2065
  // rgb not renderable
1961
2066
  // 64-bit formats
1962
2067
  "rg32uint": { gl: 33340, rb: true },
1963
2068
  "rg32sint": { gl: 33339, rb: true },
1964
- "rg32float": { gl: 33328, rb: true },
2069
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1965
2070
  "rgba16uint": { gl: 36214, rb: true },
1966
2071
  "rgba16sint": { gl: 36232, rb: true },
1967
- "rgba16float": { gl: 34842 },
1968
- "rgba16unorm": { gl: 32859, rb: true },
1969
- "rgba16snorm": { gl: 36763 },
2072
+ "rgba16float": { gl: 34842, r: FLOAT16_COLOR_RENDERABLE },
2073
+ "rgba16unorm": { gl: 32859, rb: true, r: NORM16_COLOR_RENDERABLE },
2074
+ "rgba16snorm": { gl: 36763, r: SNORM16_COLOR_RENDERABLE },
1970
2075
  // 96-bit formats (deprecated!)
1971
- "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, dataFormat: 6407, types: [5126] },
2076
+ "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: 6407, types: [5126] },
1972
2077
  // 128-bit formats
1973
2078
  "rgba32uint": { gl: 36208, rb: true },
1974
2079
  "rgba32sint": { gl: 36226, rb: true },
1975
- "rgba32float": { gl: 34836, rb: true },
2080
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1976
2081
  // Depth and stencil formats
1977
2082
  "stencil8": { gl: 36168, rb: true },
1978
2083
  // 8 stencil bits
@@ -2030,8 +2135,8 @@ var __exports__ = (() => {
2030
2135
  "astc-8x6-unorm-srgb": { gl: 37846 },
2031
2136
  "astc-8x8-unorm": { gl: 37815 },
2032
2137
  "astc-8x8-unorm-srgb": { gl: 37847 },
2033
- "astc-10x5-unorm": { gl: 37819 },
2034
- "astc-10x5-unorm-srgb": { gl: 37851 },
2138
+ "astc-10x5-unorm": { gl: 37816 },
2139
+ "astc-10x5-unorm-srgb": { gl: 37848 },
2035
2140
  "astc-10x6-unorm": { gl: 37817 },
2036
2141
  "astc-10x6-unorm-srgb": { gl: 37849 },
2037
2142
  "astc-10x8-unorm": { gl: 37818 },
@@ -2045,7 +2150,7 @@ var __exports__ = (() => {
2045
2150
  // WEBGL_compressed_texture_pvrtc
2046
2151
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
2047
2152
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
2048
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
2153
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
2049
2154
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
2050
2155
  // WEBGL_compressed_texture_etc1
2051
2156
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -2068,12 +2173,11 @@ var __exports__ = (() => {
2068
2173
  // optional WebGPU features
2069
2174
  "depth-clip-control": "EXT_depth_clamp",
2070
2175
  // TODO these seem subtly different
2071
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2176
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2072
2177
  // "indirect-first-instance"
2073
2178
  // Textures are handled by getTextureFeatures()
2074
2179
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2075
2180
  // optional WebGL features
2076
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2077
2181
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2078
2182
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2079
2183
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2387,14 +2491,78 @@ var __exports__ = (() => {
2387
2491
  super(props);
2388
2492
  this.device = device;
2389
2493
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
2390
- this._updateDevice();
2494
+ this._configureDevice();
2495
+ }
2496
+ // IMPLEMENTATION OF ABSTRACT METHODS
2497
+ _configureDevice() {
2498
+ const shouldResize = this.drawingBufferWidth !== this._framebuffer?.width || this.drawingBufferHeight !== this._framebuffer?.height;
2499
+ if (shouldResize) {
2500
+ this._framebuffer?.resize([this.drawingBufferWidth, this.drawingBufferHeight]);
2501
+ }
2391
2502
  }
2392
- getCurrentFramebuffer() {
2393
- this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
2503
+ _getCurrentFramebuffer() {
2504
+ this._framebuffer ||= new WEBGLFramebuffer(this.device, {
2505
+ id: "canvas-context-framebuffer",
2506
+ handle: null,
2507
+ // Setting handle to null returns a reference to the default WebGL framebuffer
2508
+ width: this.drawingBufferWidth,
2509
+ height: this.drawingBufferHeight
2510
+ });
2394
2511
  return this._framebuffer;
2395
2512
  }
2396
- // IMPLEMENTATION OF ABSTRACT METHODS
2397
- _updateDevice() {
2513
+ };
2514
+ }
2515
+ });
2516
+
2517
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js
2518
+ var import_core9, WebGLPresentationContext;
2519
+ var init_webgl_presentation_context = __esm({
2520
+ "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js"() {
2521
+ import_core9 = __toESM(require_core2(), 1);
2522
+ WebGLPresentationContext = class extends import_core9.PresentationContext {
2523
+ device;
2524
+ handle = null;
2525
+ context2d;
2526
+ get [Symbol.toStringTag]() {
2527
+ return "WebGLPresentationContext";
2528
+ }
2529
+ constructor(device, props = {}) {
2530
+ super(props);
2531
+ this.device = device;
2532
+ const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
2533
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2534
+ if (!defaultCanvasContext.offscreenCanvas) {
2535
+ throw new Error(`${contextLabel}: WebGL PresentationContext requires the default CanvasContext canvas to be an OffscreenCanvas`);
2536
+ }
2537
+ const context2d = this.canvas.getContext("2d");
2538
+ if (!context2d) {
2539
+ throw new Error(`${contextLabel}: Failed to create 2d presentation context`);
2540
+ }
2541
+ this.context2d = context2d;
2542
+ this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
2543
+ this._configureDevice();
2544
+ this._startObservers();
2545
+ }
2546
+ present() {
2547
+ this._resizeDrawingBufferIfNeeded();
2548
+ this.device.submit();
2549
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2550
+ const [sourceWidth, sourceHeight] = defaultCanvasContext.getDrawingBufferSize();
2551
+ if (this.drawingBufferWidth === 0 || this.drawingBufferHeight === 0 || sourceWidth === 0 || sourceHeight === 0 || defaultCanvasContext.canvas.width === 0 || defaultCanvasContext.canvas.height === 0) {
2552
+ return;
2553
+ }
2554
+ if (sourceWidth !== this.drawingBufferWidth || sourceHeight !== this.drawingBufferHeight || defaultCanvasContext.canvas.width !== this.drawingBufferWidth || defaultCanvasContext.canvas.height !== this.drawingBufferHeight) {
2555
+ 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}`);
2556
+ }
2557
+ this.context2d.clearRect(0, 0, this.drawingBufferWidth, this.drawingBufferHeight);
2558
+ this.context2d.drawImage(defaultCanvasContext.canvas, 0, 0);
2559
+ }
2560
+ _configureDevice() {
2561
+ }
2562
+ _getCurrentFramebuffer(options) {
2563
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2564
+ defaultCanvasContext.setDrawingBufferSize(this.drawingBufferWidth, this.drawingBufferHeight);
2565
+ return defaultCanvasContext.getCurrentFramebuffer(options);
2398
2566
  }
2399
2567
  };
2400
2568
  }
@@ -2415,34 +2583,34 @@ var __exports__ = (() => {
2415
2583
 
2416
2584
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js
2417
2585
  function getWebGLTarget(usage) {
2418
- if (usage & import_core9.Buffer.INDEX) {
2586
+ if (usage & import_core10.Buffer.INDEX) {
2419
2587
  return 34963;
2420
2588
  }
2421
- if (usage & import_core9.Buffer.VERTEX) {
2589
+ if (usage & import_core10.Buffer.VERTEX) {
2422
2590
  return 34962;
2423
2591
  }
2424
- if (usage & import_core9.Buffer.UNIFORM) {
2592
+ if (usage & import_core10.Buffer.UNIFORM) {
2425
2593
  return 35345;
2426
2594
  }
2427
2595
  return 34962;
2428
2596
  }
2429
2597
  function getWebGLUsage(usage) {
2430
- if (usage & import_core9.Buffer.INDEX) {
2598
+ if (usage & import_core10.Buffer.INDEX) {
2431
2599
  return 35044;
2432
2600
  }
2433
- if (usage & import_core9.Buffer.VERTEX) {
2601
+ if (usage & import_core10.Buffer.VERTEX) {
2434
2602
  return 35044;
2435
2603
  }
2436
- if (usage & import_core9.Buffer.UNIFORM) {
2604
+ if (usage & import_core10.Buffer.UNIFORM) {
2437
2605
  return 35048;
2438
2606
  }
2439
2607
  return 35044;
2440
2608
  }
2441
- var import_core9, WEBGLBuffer;
2609
+ var import_core10, WEBGLBuffer;
2442
2610
  var init_webgl_buffer = __esm({
2443
2611
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js"() {
2444
- import_core9 = __toESM(require_core2(), 1);
2445
- WEBGLBuffer = class extends import_core9.Buffer {
2612
+ import_core10 = __toESM(require_core2(), 1);
2613
+ WEBGLBuffer = class extends import_core10.Buffer {
2446
2614
  device;
2447
2615
  gl;
2448
2616
  handle;
@@ -2477,8 +2645,12 @@ var __exports__ = (() => {
2477
2645
  destroy() {
2478
2646
  if (!this.destroyed && this.handle) {
2479
2647
  this.removeStats();
2480
- this.trackDeallocatedMemory();
2481
- this.gl.deleteBuffer(this.handle);
2648
+ if (!this.props.handle) {
2649
+ this.trackDeallocatedMemory();
2650
+ this.gl.deleteBuffer(this.handle);
2651
+ } else {
2652
+ this.trackDeallocatedReferencedMemory("Buffer");
2653
+ }
2482
2654
  this.destroyed = true;
2483
2655
  this.handle = null;
2484
2656
  }
@@ -2493,7 +2665,11 @@ var __exports__ = (() => {
2493
2665
  this.bytesUsed = byteLength;
2494
2666
  this.byteLength = byteLength;
2495
2667
  this._setDebugData(data, byteOffset, byteLength);
2496
- this.trackAllocatedMemory(byteLength);
2668
+ if (!this.props.handle) {
2669
+ this.trackAllocatedMemory(byteLength);
2670
+ } else {
2671
+ this.trackReferencedMemory(byteLength, "Buffer");
2672
+ }
2497
2673
  }
2498
2674
  // Allocate a GPU buffer of specified size.
2499
2675
  _initWithByteLength(byteLength) {
@@ -2508,7 +2684,11 @@ var __exports__ = (() => {
2508
2684
  this.bytesUsed = byteLength;
2509
2685
  this.byteLength = byteLength;
2510
2686
  this._setDebugData(null, 0, byteLength);
2511
- this.trackAllocatedMemory(byteLength);
2687
+ if (!this.props.handle) {
2688
+ this.trackAllocatedMemory(byteLength);
2689
+ } else {
2690
+ this.trackReferencedMemory(byteLength, "Buffer");
2691
+ }
2512
2692
  return this;
2513
2693
  }
2514
2694
  write(data, byteOffset = 0) {
@@ -2559,9 +2739,20 @@ var __exports__ = (() => {
2559
2739
  if (line.length <= 1) {
2560
2740
  continue;
2561
2741
  }
2742
+ const lineWithTrimmedWhitespace = line.trim();
2562
2743
  const segments = line.split(":");
2744
+ const trimmedMessageType = segments[0]?.trim();
2563
2745
  if (segments.length === 2) {
2564
2746
  const [messageType2, message2] = segments;
2747
+ if (!messageType2 || !message2) {
2748
+ messages.push({
2749
+ message: lineWithTrimmedWhitespace,
2750
+ type: getMessageType(trimmedMessageType || "info"),
2751
+ lineNum: 0,
2752
+ linePos: 0
2753
+ });
2754
+ continue;
2755
+ }
2565
2756
  messages.push({
2566
2757
  message: message2.trim(),
2567
2758
  type: getMessageType(messageType2),
@@ -2571,6 +2762,15 @@ var __exports__ = (() => {
2571
2762
  continue;
2572
2763
  }
2573
2764
  const [messageType, linePosition, lineNumber, ...rest] = segments;
2765
+ if (!messageType || !linePosition || !lineNumber) {
2766
+ messages.push({
2767
+ message: segments.slice(1).join(":").trim() || lineWithTrimmedWhitespace,
2768
+ type: getMessageType(trimmedMessageType || "info"),
2769
+ lineNum: 0,
2770
+ linePos: 0
2771
+ });
2772
+ continue;
2773
+ }
2574
2774
  let lineNum = parseInt(lineNumber, 10);
2575
2775
  if (isNaN(lineNum)) {
2576
2776
  lineNum = 0;
@@ -2600,12 +2800,12 @@ var __exports__ = (() => {
2600
2800
  });
2601
2801
 
2602
2802
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js
2603
- var import_core10, WEBGLShader;
2803
+ var import_core11, WEBGLShader;
2604
2804
  var init_webgl_shader = __esm({
2605
2805
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js"() {
2606
- import_core10 = __toESM(require_core2(), 1);
2806
+ import_core11 = __toESM(require_core2(), 1);
2607
2807
  init_parse_shader_compiler_log();
2608
- WEBGLShader = class extends import_core10.Shader {
2808
+ WEBGLShader = class extends import_core11.Shader {
2609
2809
  device;
2610
2810
  handle;
2611
2811
  constructor(device, props) {
@@ -2671,9 +2871,9 @@ ${source}`;
2671
2871
  }
2672
2872
  return;
2673
2873
  }
2674
- import_core10.log.once(1, "Shader compilation is asynchronous")();
2874
+ import_core11.log.once(1, "Shader compilation is asynchronous")();
2675
2875
  await this._waitForCompilationComplete();
2676
- import_core10.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2876
+ import_core11.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2677
2877
  this._getCompilationStatus();
2678
2878
  this.debugShader();
2679
2879
  }
@@ -2821,7 +3021,7 @@ ${source}`;
2821
3021
  gl.stencilMaskSeparate(1029, mask);
2822
3022
  }
2823
3023
  if (parameters.stencilReadMask) {
2824
- import_core11.log.warn("stencilReadMask not supported under WebGL");
3024
+ import_core12.log.warn("stencilReadMask not supported under WebGL");
2825
3025
  }
2826
3026
  if (parameters.stencilCompare) {
2827
3027
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2934,10 +3134,10 @@ ${source}`;
2934
3134
  }
2935
3135
  return isEmpty;
2936
3136
  }
2937
- var import_core11;
3137
+ var import_core12;
2938
3138
  var init_device_parameters = __esm({
2939
3139
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/device-parameters.js"() {
2940
- import_core11 = __toESM(require_core2(), 1);
3140
+ import_core12 = __toESM(require_core2(), 1);
2941
3141
  init_unified_parameter_api();
2942
3142
  }
2943
3143
  });
@@ -3026,12 +3226,12 @@ ${source}`;
3026
3226
  });
3027
3227
 
3028
3228
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js
3029
- var import_core12, WEBGLSampler;
3229
+ var import_core13, WEBGLSampler;
3030
3230
  var init_webgl_sampler = __esm({
3031
3231
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js"() {
3032
- import_core12 = __toESM(require_core2(), 1);
3232
+ import_core13 = __toESM(require_core2(), 1);
3033
3233
  init_sampler_parameters();
3034
- WEBGLSampler = class extends import_core12.Sampler {
3234
+ WEBGLSampler = class extends import_core13.Sampler {
3035
3235
  device;
3036
3236
  handle;
3037
3237
  parameters;
@@ -3106,18 +3306,18 @@ ${source}`;
3106
3306
  });
3107
3307
 
3108
3308
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js
3109
- var import_core13, WEBGLTextureView;
3309
+ var import_core14, WEBGLTextureView;
3110
3310
  var init_webgl_texture_view = __esm({
3111
3311
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js"() {
3112
- import_core13 = __toESM(require_core2(), 1);
3113
- WEBGLTextureView = class extends import_core13.TextureView {
3312
+ import_core14 = __toESM(require_core2(), 1);
3313
+ WEBGLTextureView = class extends import_core14.TextureView {
3114
3314
  device;
3115
3315
  gl;
3116
3316
  handle;
3117
3317
  // Does not have a WebGL representation
3118
3318
  texture;
3119
3319
  constructor(device, props) {
3120
- super(device, { ...import_core13.Texture.defaultProps, ...props });
3320
+ super(device, { ...import_core14.Texture.defaultProps, ...props });
3121
3321
  this.device = device;
3122
3322
  this.gl = this.device.gl;
3123
3323
  this.handle = null;
@@ -3127,7 +3327,47 @@ ${source}`;
3127
3327
  }
3128
3328
  });
3129
3329
 
3330
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
3331
+ function convertGLDataTypeToDataType(type) {
3332
+ return GL_DATA_TYPE_MAP[type];
3333
+ }
3334
+ var GL_DATA_TYPE_MAP;
3335
+ var init_shader_formats = __esm({
3336
+ "../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js"() {
3337
+ GL_DATA_TYPE_MAP = {
3338
+ [5124]: "sint32",
3339
+ [5125]: "uint32",
3340
+ [5122]: "sint16",
3341
+ [5123]: "uint16",
3342
+ [5120]: "sint8",
3343
+ [5121]: "uint8",
3344
+ [5126]: "float32",
3345
+ [5131]: "float16",
3346
+ [33635]: "uint16",
3347
+ [32819]: "uint16",
3348
+ [32820]: "uint16",
3349
+ [33640]: "uint32",
3350
+ [35899]: "uint32",
3351
+ [35902]: "uint32",
3352
+ [34042]: "uint32",
3353
+ [36269]: "uint32"
3354
+ };
3355
+ }
3356
+ });
3357
+
3130
3358
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js
3359
+ function getArrayBufferView(typedArray, byteOffset = 0) {
3360
+ if (!byteOffset) {
3361
+ return typedArray;
3362
+ }
3363
+ return new typedArray.constructor(typedArray.buffer, typedArray.byteOffset + byteOffset, (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT);
3364
+ }
3365
+ function getWebGLTextureSourceElementOffset(typedArray, byteOffset) {
3366
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
3367
+ throw new Error(`Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`);
3368
+ }
3369
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
3370
+ }
3131
3371
  function getWebGLTextureTarget(dimension) {
3132
3372
  switch (dimension) {
3133
3373
  case "1d":
@@ -3148,15 +3388,17 @@ ${source}`;
3148
3388
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3149
3389
  return dimension === "cube" ? 34069 + level : glTarget;
3150
3390
  }
3151
- var import_core14, WEBGLTexture;
3391
+ var import_core15, import_core16, WEBGLTexture;
3152
3392
  var init_webgl_texture = __esm({
3153
3393
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js"() {
3154
- import_core14 = __toESM(require_core2(), 1);
3394
+ import_core15 = __toESM(require_core2(), 1);
3155
3395
  init_webgl_texture_table();
3156
3396
  init_sampler_parameters();
3157
3397
  init_with_parameters();
3158
3398
  init_webgl_texture_view();
3159
- WEBGLTexture = class extends import_core14.Texture {
3399
+ init_shader_formats();
3400
+ import_core16 = __toESM(require_core2(), 1);
3401
+ WEBGLTexture = class extends import_core15.Texture {
3160
3402
  // readonly MAX_ATTRIBUTES: number;
3161
3403
  device;
3162
3404
  gl;
@@ -3185,8 +3427,12 @@ ${source}`;
3185
3427
  // state
3186
3428
  /** Texture binding slot - TODO - move to texture view? */
3187
3429
  _textureUnit = 0;
3430
+ /** Cached framebuffer reused for color texture readback. */
3431
+ _framebuffer = null;
3432
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3433
+ _framebufferAttachmentKey = null;
3188
3434
  constructor(device, props) {
3189
- super(device, props);
3435
+ super(device, props, { byteAlignment: 1 });
3190
3436
  this.device = device;
3191
3437
  this.gl = this.device.gl;
3192
3438
  const formatInfo = getTextureFormatWebGL(this.props.format);
@@ -3199,29 +3445,43 @@ ${source}`;
3199
3445
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3200
3446
  this.gl.bindTexture(this.glTarget, this.handle);
3201
3447
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3202
- switch (dimension) {
3203
- case "2d":
3204
- case "cube":
3205
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3206
- break;
3207
- case "2d-array":
3208
- case "3d":
3209
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3210
- break;
3211
- default:
3212
- throw new Error(dimension);
3448
+ if (!this.compressed) {
3449
+ switch (dimension) {
3450
+ case "2d":
3451
+ case "cube":
3452
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3453
+ break;
3454
+ case "2d-array":
3455
+ case "3d":
3456
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3457
+ break;
3458
+ default:
3459
+ throw new Error(dimension);
3460
+ }
3213
3461
  }
3214
3462
  this.gl.bindTexture(this.glTarget, null);
3215
3463
  this._initializeData(props.data);
3464
+ if (!this.props.handle) {
3465
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
3466
+ } else {
3467
+ this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
3468
+ }
3216
3469
  this.setSampler(this.props.sampler);
3217
3470
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3218
3471
  Object.seal(this);
3219
3472
  }
3220
3473
  destroy() {
3221
3474
  if (this.handle) {
3222
- this.gl.deleteTexture(this.handle);
3475
+ this._framebuffer?.destroy();
3476
+ this._framebuffer = null;
3477
+ this._framebufferAttachmentKey = null;
3223
3478
  this.removeStats();
3224
- this.trackDeallocatedMemory("Texture");
3479
+ if (!this.props.handle) {
3480
+ this.gl.deleteTexture(this.handle);
3481
+ this.trackDeallocatedMemory("Texture");
3482
+ } else {
3483
+ this.trackDeallocatedReferencedMemory("Texture");
3484
+ }
3225
3485
  this.destroyed = true;
3226
3486
  }
3227
3487
  }
@@ -3233,101 +3493,271 @@ ${source}`;
3233
3493
  const parameters = convertSamplerParametersToWebGL(this.sampler.props);
3234
3494
  this._setSamplerParameters(parameters);
3235
3495
  }
3496
+ copyExternalImage(options_) {
3497
+ const options = this._normalizeCopyExternalImageOptions(options_);
3498
+ if (options.sourceX || options.sourceY) {
3499
+ throw new Error("WebGL does not support sourceX/sourceY)");
3500
+ }
3501
+ const { glFormat, glType } = this;
3502
+ const { image, depth, mipLevel, x, y, z, width, height } = options;
3503
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3504
+ const glParameters = options.flipY ? { [37440]: true } : {};
3505
+ this.gl.bindTexture(this.glTarget, this.handle);
3506
+ withGLParameters(this.gl, glParameters, () => {
3507
+ switch (this.dimension) {
3508
+ case "2d":
3509
+ case "cube":
3510
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3511
+ break;
3512
+ case "2d-array":
3513
+ case "3d":
3514
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3515
+ break;
3516
+ default:
3517
+ }
3518
+ });
3519
+ this.gl.bindTexture(this.glTarget, null);
3520
+ return { width: options.width, height: options.height };
3521
+ }
3236
3522
  copyImageData(options_) {
3237
- const options = this._normalizeCopyImageDataOptions(options_);
3238
- const typedArray = options.data;
3239
- const { width, height, depth } = this;
3240
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0, z = 0 } = options;
3523
+ super.copyImageData(options_);
3524
+ }
3525
+ /**
3526
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
3527
+ *
3528
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
3529
+ * before any WebGL calls are issued.
3530
+ */
3531
+ readBuffer(options = {}, buffer) {
3532
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
3533
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
3534
+ const readBuffer = buffer || this.device.createBuffer({
3535
+ byteLength: memoryLayout.byteLength,
3536
+ usage: import_core15.Buffer.COPY_DST | import_core15.Buffer.MAP_READ
3537
+ });
3538
+ if (readBuffer.byteLength < memoryLayout.byteLength) {
3539
+ throw new Error(`${this} readBuffer target is too small (${readBuffer.byteLength} < ${memoryLayout.byteLength})`);
3540
+ }
3541
+ const webglBuffer = readBuffer;
3542
+ this.gl.bindBuffer(35051, webglBuffer.handle);
3543
+ try {
3544
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, (destinationByteOffset) => {
3545
+ this.gl.readPixels(normalizedOptions.x, normalizedOptions.y, normalizedOptions.width, normalizedOptions.height, this.glFormat, this.glType, destinationByteOffset);
3546
+ });
3547
+ } finally {
3548
+ this.gl.bindBuffer(35051, null);
3549
+ }
3550
+ return readBuffer;
3551
+ }
3552
+ async readDataAsync(options = {}) {
3553
+ const buffer = this.readBuffer(options);
3554
+ const data = await buffer.readAsync();
3555
+ buffer.destroy();
3556
+ return data.buffer;
3557
+ }
3558
+ writeBuffer(buffer, options_ = {}) {
3559
+ const options = this._normalizeTextureWriteOptions(options_);
3560
+ const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
3241
3561
  const { glFormat, glType, compressed } = this;
3242
3562
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3243
- let unpackRowLength;
3244
- if (!this.compressed) {
3245
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3246
- if (bytesPerPixel) {
3247
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3248
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
3249
- }
3250
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
3251
- }
3563
+ if (compressed) {
3564
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
3252
3565
  }
3253
- const glParameters = !this.compressed ? {
3566
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3567
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3568
+ const glParameters = {
3569
+ [3317]: this.byteAlignment,
3254
3570
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3255
3571
  [32878]: options.rowsPerImage
3256
- } : {};
3257
- this.gl.bindTexture(glTarget, this.handle);
3572
+ };
3573
+ this.gl.bindTexture(this.glTarget, this.handle);
3574
+ this.gl.bindBuffer(35052, buffer.handle);
3258
3575
  withGLParameters(this.gl, glParameters, () => {
3259
3576
  switch (this.dimension) {
3260
3577
  case "2d":
3261
3578
  case "cube":
3262
- if (compressed) {
3263
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
3264
- } else {
3265
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3266
- }
3579
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
3267
3580
  break;
3268
3581
  case "2d-array":
3269
3582
  case "3d":
3270
- if (compressed) {
3271
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
3272
- } else {
3273
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
3274
- }
3583
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
3275
3584
  break;
3276
3585
  default:
3277
3586
  }
3278
3587
  });
3279
- this.gl.bindTexture(glTarget, null);
3588
+ this.gl.bindBuffer(35052, null);
3589
+ this.gl.bindTexture(this.glTarget, null);
3280
3590
  }
3281
- copyExternalImage(options_) {
3282
- const options = this._normalizeCopyExternalImageOptions(options_);
3283
- if (options.sourceX || options.sourceY) {
3284
- throw new Error("WebGL does not support sourceX/sourceY)");
3591
+ writeData(data, options_ = {}) {
3592
+ const options = this._normalizeTextureWriteOptions(options_);
3593
+ const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3594
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
3595
+ const { glFormat, glType, compressed } = this;
3596
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3597
+ let unpackRowLength;
3598
+ if (!compressed) {
3599
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3600
+ if (bytesPerPixel) {
3601
+ unpackRowLength = options.bytesPerRow / bytesPerPixel;
3602
+ }
3285
3603
  }
3286
- const { glFormat, glType } = this;
3287
- const { image, depth, mipLevel, x, y, z, width, height } = options;
3288
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3289
- const glParameters = options.flipY ? { [37440]: true } : {};
3604
+ const glParameters = !this.compressed ? {
3605
+ [3317]: this.byteAlignment,
3606
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3607
+ [32878]: options.rowsPerImage
3608
+ } : {};
3609
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
3610
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
3611
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
3612
+ const isFullMipUpload = x === 0 && y === 0 && z === 0 && width === mipLevelSize.width && height === mipLevelSize.height && depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
3290
3613
  this.gl.bindTexture(this.glTarget, this.handle);
3614
+ this.gl.bindBuffer(35052, null);
3291
3615
  withGLParameters(this.gl, glParameters, () => {
3292
3616
  switch (this.dimension) {
3293
3617
  case "2d":
3294
3618
  case "cube":
3295
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3619
+ if (compressed) {
3620
+ if (isFullMipUpload) {
3621
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
3622
+ } else {
3623
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
3624
+ }
3625
+ } else {
3626
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3627
+ }
3296
3628
  break;
3297
3629
  case "2d-array":
3298
3630
  case "3d":
3299
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3631
+ if (compressed) {
3632
+ if (isFullMipUpload) {
3633
+ this.gl.compressedTexImage3D(glTarget, mipLevel, glFormat, width, height, depthOrArrayLayers, 0, compressedData);
3634
+ } else {
3635
+ this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, compressedData);
3636
+ }
3637
+ } else {
3638
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
3639
+ }
3300
3640
  break;
3301
3641
  default:
3302
3642
  }
3303
3643
  });
3304
3644
  this.gl.bindTexture(this.glTarget, null);
3305
- return { width: options.width, height: options.height };
3645
+ }
3646
+ // IMPLEMENTATION SPECIFIC
3647
+ /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
3648
+ _getRowByteAlignment(format, width) {
3649
+ return 1;
3650
+ }
3651
+ /**
3652
+ * Wraps a given texture into a framebuffer object, that can be further used
3653
+ * to read data from the texture object.
3654
+ */
3655
+ _getFramebuffer() {
3656
+ this._framebuffer ||= this.device.createFramebuffer({
3657
+ id: `framebuffer-for-${this.id}`,
3658
+ width: this.width,
3659
+ height: this.height,
3660
+ colorAttachments: [this]
3661
+ });
3662
+ return this._framebuffer;
3306
3663
  }
3307
3664
  // WEBGL SPECIFIC
3308
- generateMipmapsWebGL(options) {
3309
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3310
- if (!isFilterableAndRenderable) {
3311
- import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3312
- if (!options?.force) {
3313
- return;
3314
- }
3315
- }
3665
+ readDataSyncWebGL(options_ = {}) {
3666
+ const options = this._getSupportedColorReadOptions(options_);
3667
+ const memoryLayout = this.computeMemoryLayout(options);
3668
+ const shaderType = convertGLDataTypeToDataType(this.glType);
3669
+ const ArrayType = (0, import_core16.getTypedArrayConstructor)(shaderType);
3670
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT);
3671
+ this._readColorTextureLayers(options, memoryLayout, (destinationByteOffset) => {
3672
+ const layerView = new ArrayType(targetArray.buffer, targetArray.byteOffset + destinationByteOffset, memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT);
3673
+ this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, this.glType, layerView);
3674
+ });
3675
+ return targetArray.buffer;
3676
+ }
3677
+ /**
3678
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
3679
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
3680
+ */
3681
+ _readColorTextureLayers(options, memoryLayout, readLayer) {
3682
+ const framebuffer = this._getFramebuffer();
3683
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
3684
+ const glParameters = {
3685
+ [3333]: this.byteAlignment,
3686
+ ...packRowLength !== options.width ? { [3330]: packRowLength } : {}
3687
+ };
3688
+ const prevReadBuffer = this.gl.getParameter(3074);
3689
+ const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3316
3690
  try {
3317
- this.gl.bindTexture(this.glTarget, this.handle);
3318
- this.gl.generateMipmap(this.glTarget);
3319
- } catch (error) {
3320
- import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3691
+ this.gl.readBuffer(36064);
3692
+ withGLParameters(this.gl, glParameters, () => {
3693
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
3694
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
3695
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
3696
+ }
3697
+ });
3321
3698
  } finally {
3322
- this.gl.bindTexture(this.glTarget, null);
3699
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3700
+ this.gl.readBuffer(prevReadBuffer);
3323
3701
  }
3324
3702
  }
3325
- // INTERNAL
3326
3703
  /**
3327
- * Sets sampler parameters on texture
3704
+ * Attaches a single color subresource to the cached read framebuffer.
3705
+ *
3706
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3707
+ */
3708
+ _attachReadSubresource(framebuffer, mipLevel, layer) {
3709
+ const attachmentKey = `${mipLevel}:${layer}`;
3710
+ if (this._framebufferAttachmentKey === attachmentKey) {
3711
+ return;
3712
+ }
3713
+ switch (this.dimension) {
3714
+ case "2d":
3715
+ this.gl.framebufferTexture2D(36160, 36064, 3553, this.handle, mipLevel);
3716
+ break;
3717
+ case "cube":
3718
+ this.gl.framebufferTexture2D(36160, 36064, getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer), this.handle, mipLevel);
3719
+ break;
3720
+ case "2d-array":
3721
+ case "3d":
3722
+ this.gl.framebufferTextureLayer(36160, 36064, this.handle, mipLevel, layer);
3723
+ break;
3724
+ default:
3725
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
3726
+ }
3727
+ if (this.device.props.debug) {
3728
+ const status = Number(this.gl.checkFramebufferStatus(36160));
3729
+ if (status !== Number(36053)) {
3730
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
3731
+ }
3732
+ }
3733
+ this._framebufferAttachmentKey = attachmentKey;
3734
+ }
3735
+ /**
3736
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3737
+ */
3738
+ generateMipmapsWebGL(options) {
3739
+ const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3740
+ if (!isFilterableAndRenderable) {
3741
+ import_core15.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3742
+ if (!options?.force) {
3743
+ return;
3744
+ }
3745
+ }
3746
+ try {
3747
+ this.gl.bindTexture(this.glTarget, this.handle);
3748
+ this.gl.generateMipmap(this.glTarget);
3749
+ } catch (error) {
3750
+ import_core15.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3751
+ } finally {
3752
+ this.gl.bindTexture(this.glTarget, null);
3753
+ }
3754
+ }
3755
+ // INTERNAL
3756
+ /**
3757
+ * Sets sampler parameters on texture
3328
3758
  */
3329
3759
  _setSamplerParameters(parameters) {
3330
- import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3760
+ import_core15.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3331
3761
  this.gl.bindTexture(this.glTarget, this.handle);
3332
3762
  for (const [pname, pvalue] of Object.entries(parameters)) {
3333
3763
  const param = Number(pname);
@@ -3384,106 +3814,510 @@ ${source}`;
3384
3814
  }
3385
3815
  });
3386
3816
 
3387
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
3388
- function convertDataTypeToGLDataType(normalizedType) {
3389
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3390
- }
3391
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
3392
- return WEBGL_SHADER_TYPES[glUniformType];
3817
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3818
+ function setUniform(gl, location, type, value) {
3819
+ const gl2 = gl;
3820
+ let uniformValue = value;
3821
+ if (uniformValue === true) {
3822
+ uniformValue = 1;
3823
+ }
3824
+ if (uniformValue === false) {
3825
+ uniformValue = 0;
3826
+ }
3827
+ const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
3828
+ switch (type) {
3829
+ case 35678:
3830
+ case 35680:
3831
+ case 35679:
3832
+ case 35682:
3833
+ case 36289:
3834
+ case 36292:
3835
+ case 36293:
3836
+ case 36298:
3837
+ case 36299:
3838
+ case 36300:
3839
+ case 36303:
3840
+ case 36306:
3841
+ case 36307:
3842
+ case 36308:
3843
+ case 36311:
3844
+ if (typeof value !== "number") {
3845
+ throw new Error("samplers must be set to integers");
3846
+ }
3847
+ return gl.uniform1i(location, value);
3848
+ case 5126:
3849
+ return gl.uniform1fv(location, arrayValue);
3850
+ case 35664:
3851
+ return gl.uniform2fv(location, arrayValue);
3852
+ case 35665:
3853
+ return gl.uniform3fv(location, arrayValue);
3854
+ case 35666:
3855
+ return gl.uniform4fv(location, arrayValue);
3856
+ case 5124:
3857
+ return gl.uniform1iv(location, arrayValue);
3858
+ case 35667:
3859
+ return gl.uniform2iv(location, arrayValue);
3860
+ case 35668:
3861
+ return gl.uniform3iv(location, arrayValue);
3862
+ case 35669:
3863
+ return gl.uniform4iv(location, arrayValue);
3864
+ case 35670:
3865
+ return gl.uniform1iv(location, arrayValue);
3866
+ case 35671:
3867
+ return gl.uniform2iv(location, arrayValue);
3868
+ case 35672:
3869
+ return gl.uniform3iv(location, arrayValue);
3870
+ case 35673:
3871
+ return gl.uniform4iv(location, arrayValue);
3872
+ case 5125:
3873
+ return gl2.uniform1uiv(location, arrayValue, 1);
3874
+ case 36294:
3875
+ return gl2.uniform2uiv(location, arrayValue, 2);
3876
+ case 36295:
3877
+ return gl2.uniform3uiv(location, arrayValue, 3);
3878
+ case 36296:
3879
+ return gl2.uniform4uiv(location, arrayValue, 4);
3880
+ case 35674:
3881
+ return gl.uniformMatrix2fv(location, false, arrayValue);
3882
+ case 35675:
3883
+ return gl.uniformMatrix3fv(location, false, arrayValue);
3884
+ case 35676:
3885
+ return gl.uniformMatrix4fv(location, false, arrayValue);
3886
+ case 35685:
3887
+ return gl2.uniformMatrix2x3fv(location, false, arrayValue);
3888
+ case 35686:
3889
+ return gl2.uniformMatrix2x4fv(location, false, arrayValue);
3890
+ case 35687:
3891
+ return gl2.uniformMatrix3x2fv(location, false, arrayValue);
3892
+ case 35688:
3893
+ return gl2.uniformMatrix3x4fv(location, false, arrayValue);
3894
+ case 35689:
3895
+ return gl2.uniformMatrix4x2fv(location, false, arrayValue);
3896
+ case 35690:
3897
+ return gl2.uniformMatrix4x3fv(location, false, arrayValue);
3898
+ }
3899
+ throw new Error("Illegal uniform");
3393
3900
  }
3394
- function isGLSamplerType(type) {
3395
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3901
+ var init_set_uniform = __esm({
3902
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js"() {
3903
+ }
3904
+ });
3905
+
3906
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
3907
+ function getGLDrawMode(topology) {
3908
+ switch (topology) {
3909
+ case "point-list":
3910
+ return 0;
3911
+ case "line-list":
3912
+ return 1;
3913
+ case "line-strip":
3914
+ return 3;
3915
+ case "triangle-list":
3916
+ return 4;
3917
+ case "triangle-strip":
3918
+ return 5;
3919
+ default:
3920
+ throw new Error(topology);
3921
+ }
3396
3922
  }
3397
- function getTextureBindingFromGLSamplerType(glSamplerType) {
3398
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3923
+ function getGLPrimitive(topology) {
3924
+ switch (topology) {
3925
+ case "point-list":
3926
+ return 0;
3927
+ case "line-list":
3928
+ return 1;
3929
+ case "line-strip":
3930
+ return 1;
3931
+ case "triangle-list":
3932
+ return 4;
3933
+ case "triangle-strip":
3934
+ return 4;
3935
+ default:
3936
+ throw new Error(topology);
3937
+ }
3399
3938
  }
3400
- var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
3401
- var init_webgl_shadertypes = __esm({
3402
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
3403
- WEBGL_SHADER_TYPES = {
3404
- [5126]: "f32",
3405
- [35664]: "vec2<f32>",
3406
- [35665]: "vec3<f32>",
3407
- [35666]: "vec4<f32>",
3408
- [5124]: "i32",
3409
- [35667]: "vec2<i32>",
3410
- [35668]: "vec3<i32>",
3411
- [35669]: "vec4<i32>",
3412
- [5125]: "u32",
3413
- [36294]: "vec2<u32>",
3414
- [36295]: "vec3<u32>",
3415
- [36296]: "vec4<u32>",
3416
- [35670]: "f32",
3417
- [35671]: "vec2<f32>",
3418
- [35672]: "vec3<f32>",
3419
- [35673]: "vec4<f32>",
3420
- // TODO - are sizes/components below correct?
3421
- [35674]: "mat2x2<f32>",
3422
- [35685]: "mat2x3<f32>",
3423
- [35686]: "mat2x4<f32>",
3424
- [35687]: "mat3x2<f32>",
3425
- [35675]: "mat3x3<f32>",
3426
- [35688]: "mat3x4<f32>",
3427
- [35689]: "mat4x2<f32>",
3428
- [35690]: "mat4x3<f32>",
3429
- [35676]: "mat4x4<f32>"
3430
- };
3431
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3432
- [35678]: { viewDimension: "2d", sampleType: "float" },
3433
- [35680]: { viewDimension: "cube", sampleType: "float" },
3434
- [35679]: { viewDimension: "3d", sampleType: "float" },
3435
- [35682]: { viewDimension: "3d", sampleType: "depth" },
3436
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
3437
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
3438
- [36293]: { viewDimension: "cube", sampleType: "float" },
3439
- [36298]: { viewDimension: "2d", sampleType: "sint" },
3440
- [36299]: { viewDimension: "3d", sampleType: "sint" },
3441
- [36300]: { viewDimension: "cube", sampleType: "sint" },
3442
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
3443
- [36306]: { viewDimension: "2d", sampleType: "uint" },
3444
- [36307]: { viewDimension: "3d", sampleType: "uint" },
3445
- [36308]: { viewDimension: "cube", sampleType: "uint" },
3446
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
3447
- };
3448
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3449
- uint8: 5121,
3450
- sint8: 5120,
3451
- unorm8: 5121,
3452
- snorm8: 5120,
3453
- uint16: 5123,
3454
- sint16: 5122,
3455
- unorm16: 5123,
3456
- snorm16: 5122,
3457
- uint32: 5125,
3458
- sint32: 5124,
3459
- // WebGPU does not support normalized 32 bit integer attributes
3460
- // 'unorm32': GL.UNSIGNED_INT,
3461
- // 'snorm32': GL.INT,
3462
- float16: 5131,
3463
- float32: 5126
3464
- };
3939
+ var init_webgl_topology_utils = __esm({
3940
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
3465
3941
  }
3466
3942
  });
3467
3943
 
3468
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
3469
- function getShaderLayoutFromGLSL(gl, program) {
3470
- const shaderLayout = {
3471
- attributes: [],
3472
- bindings: []
3944
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3945
+ function mergeShaderLayout(baseLayout, overrideLayout) {
3946
+ const mergedLayout = {
3947
+ ...baseLayout,
3948
+ attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
3473
3949
  };
3474
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3475
- const uniformBlocks = readUniformBlocks(gl, program);
3476
- for (const uniformBlock of uniformBlocks) {
3477
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3478
- name: uniform.name,
3479
- format: uniform.format,
3480
- byteOffset: uniform.byteOffset,
3481
- byteStride: uniform.byteStride,
3482
- arrayLength: uniform.arrayLength
3483
- }));
3484
- shaderLayout.bindings.push({
3485
- type: "uniform",
3486
- name: uniformBlock.name,
3950
+ for (const attribute of overrideLayout?.attributes || []) {
3951
+ const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3952
+ if (!baseAttribute) {
3953
+ import_core17.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3954
+ } else {
3955
+ baseAttribute.type = attribute.type || baseAttribute.type;
3956
+ baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3957
+ }
3958
+ }
3959
+ return mergedLayout;
3960
+ }
3961
+ var import_core17, WEBGLRenderPipeline;
3962
+ var init_webgl_render_pipeline = __esm({
3963
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3964
+ import_core17 = __toESM(require_core2(), 1);
3965
+ init_device_parameters();
3966
+ init_set_uniform();
3967
+ init_webgl_buffer();
3968
+ init_webgl_framebuffer();
3969
+ init_webgl_texture();
3970
+ init_webgl_texture_view();
3971
+ init_webgl_topology_utils();
3972
+ WEBGLRenderPipeline = class extends import_core17.RenderPipeline {
3973
+ /** The WebGL device that created this render pipeline */
3974
+ device;
3975
+ /** Handle to underlying WebGL program */
3976
+ handle;
3977
+ /** vertex shader */
3978
+ vs;
3979
+ /** fragment shader */
3980
+ fs;
3981
+ /** The layout extracted from shader by WebGL introspection APIs */
3982
+ introspectedLayout;
3983
+ /** Compatibility path for direct pipeline.setBindings() usage */
3984
+ bindings = {};
3985
+ /** Compatibility path for direct pipeline.uniforms usage */
3986
+ uniforms = {};
3987
+ /** WebGL varyings */
3988
+ varyings = null;
3989
+ _uniformCount = 0;
3990
+ _uniformSetters = {};
3991
+ // TODO are these used?
3992
+ get [Symbol.toStringTag]() {
3993
+ return "WEBGLRenderPipeline";
3994
+ }
3995
+ constructor(device, props) {
3996
+ super(device, props);
3997
+ this.device = device;
3998
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
3999
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
4000
+ this.handle = webglSharedRenderPipeline.handle;
4001
+ this.vs = webglSharedRenderPipeline.vs;
4002
+ this.fs = webglSharedRenderPipeline.fs;
4003
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
4004
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
4005
+ this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4006
+ this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4007
+ }
4008
+ destroy() {
4009
+ if (this.destroyed) {
4010
+ return;
4011
+ }
4012
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4013
+ this.sharedRenderPipeline.destroy();
4014
+ }
4015
+ this.destroyResource();
4016
+ }
4017
+ /**
4018
+ * Compatibility shim for code paths that still set bindings on the pipeline.
4019
+ * Shared-model draws pass bindings per draw and do not rely on this state.
4020
+ */
4021
+ setBindings(bindings, options) {
4022
+ for (const [name, value] of Object.entries(bindings)) {
4023
+ const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
4024
+ if (!binding) {
4025
+ const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
4026
+ if (!options?.disableWarnings) {
4027
+ import_core17.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
4028
+ }
4029
+ continue;
4030
+ }
4031
+ if (!value) {
4032
+ import_core17.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4033
+ }
4034
+ switch (binding.type) {
4035
+ case "uniform":
4036
+ if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
4037
+ throw new Error("buffer value");
4038
+ }
4039
+ break;
4040
+ case "texture":
4041
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4042
+ throw new Error(`${this} Bad texture binding for ${name}`);
4043
+ }
4044
+ break;
4045
+ case "sampler":
4046
+ import_core17.log.warn(`Ignoring sampler ${name}`)();
4047
+ break;
4048
+ default:
4049
+ throw new Error(binding.type);
4050
+ }
4051
+ this.bindings[name] = value;
4052
+ }
4053
+ }
4054
+ /** @todo needed for portable model
4055
+ * @note The WebGL API is offers many ways to draw things
4056
+ * This function unifies those ways into a single call using common parameters with sane defaults
4057
+ */
4058
+ draw(options) {
4059
+ this._syncLinkStatus();
4060
+ const {
4061
+ renderPass,
4062
+ parameters = this.props.parameters,
4063
+ topology = this.props.topology,
4064
+ vertexArray,
4065
+ vertexCount,
4066
+ // indexCount,
4067
+ instanceCount,
4068
+ isInstanced = false,
4069
+ firstVertex = 0,
4070
+ // firstIndex,
4071
+ // firstInstance,
4072
+ // baseVertex,
4073
+ transformFeedback,
4074
+ bindings = this.bindings,
4075
+ uniforms = this.uniforms
4076
+ } = options;
4077
+ const glDrawMode = getGLDrawMode(topology);
4078
+ const isIndexed = Boolean(vertexArray.indexBuffer);
4079
+ const glIndexType = vertexArray.indexBuffer?.glIndexType;
4080
+ if (this.linkStatus !== "success") {
4081
+ import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4082
+ return false;
4083
+ }
4084
+ if (!this._areTexturesRenderable(bindings)) {
4085
+ import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4086
+ return false;
4087
+ }
4088
+ this.device.gl.useProgram(this.handle);
4089
+ vertexArray.bindBeforeRender(renderPass);
4090
+ if (transformFeedback) {
4091
+ transformFeedback.begin(this.props.topology);
4092
+ }
4093
+ this._applyBindings(bindings, { disableWarnings: this.props.disableWarnings });
4094
+ this._applyUniforms(uniforms);
4095
+ const webglRenderPass = renderPass;
4096
+ withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4097
+ if (isIndexed && isInstanced) {
4098
+ this.device.gl.drawElementsInstanced(
4099
+ glDrawMode,
4100
+ vertexCount || 0,
4101
+ // indexCount?
4102
+ glIndexType,
4103
+ firstVertex,
4104
+ instanceCount || 0
4105
+ );
4106
+ } else if (isIndexed) {
4107
+ this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4108
+ } else if (isInstanced) {
4109
+ this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4110
+ } else {
4111
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4112
+ }
4113
+ if (transformFeedback) {
4114
+ transformFeedback.end();
4115
+ }
4116
+ });
4117
+ vertexArray.unbindAfterRender(renderPass);
4118
+ return true;
4119
+ }
4120
+ /**
4121
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
4122
+ * Update a texture if needed (e.g. from video)
4123
+ * Note: This is currently done before every draw call
4124
+ */
4125
+ _areTexturesRenderable(bindings) {
4126
+ let texturesRenderable = true;
4127
+ for (const bindingInfo of this.shaderLayout.bindings) {
4128
+ if (!bindings[bindingInfo.name] && !bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4129
+ import_core17.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4130
+ texturesRenderable = false;
4131
+ }
4132
+ }
4133
+ return texturesRenderable;
4134
+ }
4135
+ /** Apply any bindings (before each draw call) */
4136
+ _applyBindings(bindings, _options) {
4137
+ this._syncLinkStatus();
4138
+ if (this.linkStatus !== "success") {
4139
+ return;
4140
+ }
4141
+ const { gl } = this.device;
4142
+ gl.useProgram(this.handle);
4143
+ let textureUnit = 0;
4144
+ let uniformBufferIndex = 0;
4145
+ for (const binding of this.shaderLayout.bindings) {
4146
+ const value = bindings[binding.name] || bindings[binding.name.replace(/Uniforms$/, "")];
4147
+ if (!value) {
4148
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4149
+ }
4150
+ switch (binding.type) {
4151
+ case "uniform":
4152
+ const { name } = binding;
4153
+ const location = gl.getUniformBlockIndex(this.handle, name);
4154
+ if (location === 4294967295) {
4155
+ throw new Error(`Invalid uniform block name ${name}`);
4156
+ }
4157
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
4158
+ if (value instanceof WEBGLBuffer) {
4159
+ gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4160
+ } else {
4161
+ gl.bindBufferRange(
4162
+ 35345,
4163
+ uniformBufferIndex,
4164
+ // @ts-expect-error
4165
+ value.buffer.handle,
4166
+ // @ts-expect-error
4167
+ value.offset || 0,
4168
+ // @ts-expect-error
4169
+ value.size || value.buffer.byteLength - value.offset
4170
+ );
4171
+ }
4172
+ uniformBufferIndex += 1;
4173
+ break;
4174
+ case "texture":
4175
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4176
+ throw new Error("texture");
4177
+ }
4178
+ let texture;
4179
+ if (value instanceof WEBGLTextureView) {
4180
+ texture = value.texture;
4181
+ } else if (value instanceof WEBGLTexture) {
4182
+ texture = value;
4183
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4184
+ import_core17.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4185
+ texture = value.colorAttachments[0].texture;
4186
+ } else {
4187
+ throw new Error("No texture");
4188
+ }
4189
+ gl.activeTexture(33984 + textureUnit);
4190
+ gl.bindTexture(texture.glTarget, texture.handle);
4191
+ textureUnit += 1;
4192
+ break;
4193
+ case "sampler":
4194
+ break;
4195
+ case "storage":
4196
+ case "read-only-storage":
4197
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4198
+ }
4199
+ }
4200
+ }
4201
+ /**
4202
+ * Due to program sharing, uniforms need to be reset before every draw call
4203
+ * (though caching will avoid redundant WebGL calls)
4204
+ */
4205
+ _applyUniforms(uniforms) {
4206
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
4207
+ const { name, location, type, textureUnit } = uniformLayout;
4208
+ const value = uniforms[name] ?? textureUnit;
4209
+ if (value !== void 0) {
4210
+ setUniform(this.device.gl, location, type, value);
4211
+ }
4212
+ }
4213
+ }
4214
+ _syncLinkStatus() {
4215
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
4216
+ }
4217
+ };
4218
+ }
4219
+ });
4220
+
4221
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
4222
+ function convertDataTypeToGLDataType(normalizedType) {
4223
+ return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
4224
+ }
4225
+ function convertGLUniformTypeToShaderVariableType(glUniformType) {
4226
+ return WEBGL_SHADER_TYPES[glUniformType];
4227
+ }
4228
+ function isGLSamplerType(type) {
4229
+ return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
4230
+ }
4231
+ function getTextureBindingFromGLSamplerType(glSamplerType) {
4232
+ return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
4233
+ }
4234
+ var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
4235
+ var init_webgl_shadertypes = __esm({
4236
+ "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
4237
+ WEBGL_SHADER_TYPES = {
4238
+ [5126]: "f32",
4239
+ [35664]: "vec2<f32>",
4240
+ [35665]: "vec3<f32>",
4241
+ [35666]: "vec4<f32>",
4242
+ [5124]: "i32",
4243
+ [35667]: "vec2<i32>",
4244
+ [35668]: "vec3<i32>",
4245
+ [35669]: "vec4<i32>",
4246
+ [5125]: "u32",
4247
+ [36294]: "vec2<u32>",
4248
+ [36295]: "vec3<u32>",
4249
+ [36296]: "vec4<u32>",
4250
+ [35670]: "f32",
4251
+ [35671]: "vec2<f32>",
4252
+ [35672]: "vec3<f32>",
4253
+ [35673]: "vec4<f32>",
4254
+ // TODO - are sizes/components below correct?
4255
+ [35674]: "mat2x2<f32>",
4256
+ [35685]: "mat2x3<f32>",
4257
+ [35686]: "mat2x4<f32>",
4258
+ [35687]: "mat3x2<f32>",
4259
+ [35675]: "mat3x3<f32>",
4260
+ [35688]: "mat3x4<f32>",
4261
+ [35689]: "mat4x2<f32>",
4262
+ [35690]: "mat4x3<f32>",
4263
+ [35676]: "mat4x4<f32>"
4264
+ };
4265
+ WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
4266
+ [35678]: { viewDimension: "2d", sampleType: "float" },
4267
+ [35680]: { viewDimension: "cube", sampleType: "float" },
4268
+ [35679]: { viewDimension: "3d", sampleType: "float" },
4269
+ [35682]: { viewDimension: "3d", sampleType: "depth" },
4270
+ [36289]: { viewDimension: "2d-array", sampleType: "float" },
4271
+ [36292]: { viewDimension: "2d-array", sampleType: "depth" },
4272
+ [36293]: { viewDimension: "cube", sampleType: "float" },
4273
+ [36298]: { viewDimension: "2d", sampleType: "sint" },
4274
+ [36299]: { viewDimension: "3d", sampleType: "sint" },
4275
+ [36300]: { viewDimension: "cube", sampleType: "sint" },
4276
+ [36303]: { viewDimension: "2d-array", sampleType: "uint" },
4277
+ [36306]: { viewDimension: "2d", sampleType: "uint" },
4278
+ [36307]: { viewDimension: "3d", sampleType: "uint" },
4279
+ [36308]: { viewDimension: "cube", sampleType: "uint" },
4280
+ [36311]: { viewDimension: "2d-array", sampleType: "uint" }
4281
+ };
4282
+ NORMALIZED_SHADER_TYPE_TO_WEBGL = {
4283
+ uint8: 5121,
4284
+ sint8: 5120,
4285
+ unorm8: 5121,
4286
+ snorm8: 5120,
4287
+ uint16: 5123,
4288
+ sint16: 5122,
4289
+ unorm16: 5123,
4290
+ snorm16: 5122,
4291
+ uint32: 5125,
4292
+ sint32: 5124,
4293
+ // WebGPU does not support normalized 32 bit integer attributes
4294
+ // 'unorm32': GL.UNSIGNED_INT,
4295
+ // 'snorm32': GL.INT,
4296
+ float16: 5131,
4297
+ float32: 5126
4298
+ };
4299
+ }
4300
+ });
4301
+
4302
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
4303
+ function getShaderLayoutFromGLSL(gl, program) {
4304
+ const shaderLayout = {
4305
+ attributes: [],
4306
+ bindings: []
4307
+ };
4308
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
4309
+ const uniformBlocks = readUniformBlocks(gl, program);
4310
+ for (const uniformBlock of uniformBlocks) {
4311
+ const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
4312
+ name: uniform.name,
4313
+ format: uniform.format,
4314
+ byteOffset: uniform.byteOffset,
4315
+ byteStride: uniform.byteStride,
4316
+ arrayLength: uniform.arrayLength
4317
+ }));
4318
+ shaderLayout.bindings.push({
4319
+ type: "uniform",
4320
+ name: uniformBlock.name,
3487
4321
  group: 0,
3488
4322
  location: uniformBlock.location,
3489
4323
  visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
@@ -3555,447 +4389,174 @@ ${source}`;
3555
4389
  throw new Error("activeInfo");
3556
4390
  }
3557
4391
  const { name, type: glUniformType, size } = activeInfo;
3558
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3559
- const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
3560
- varyings.push({ location, name, type, size: size * components });
3561
- }
3562
- varyings.sort((a, b) => a.location - b.location);
3563
- return varyings;
3564
- }
3565
- function readUniformBindings(gl, program) {
3566
- const uniforms = [];
3567
- const uniformCount = gl.getProgramParameter(program, 35718);
3568
- for (let i = 0; i < uniformCount; i++) {
3569
- const activeInfo = gl.getActiveUniform(program, i);
3570
- if (!activeInfo) {
3571
- throw new Error("activeInfo");
3572
- }
3573
- const { name: rawName, size, type } = activeInfo;
3574
- const { name, isArray: isArray4 } = parseUniformName(rawName);
3575
- let webglLocation = gl.getUniformLocation(program, name);
3576
- const uniformInfo = {
3577
- // WebGL locations are uniquely typed but just numbers
3578
- location: webglLocation,
3579
- name,
3580
- size,
3581
- type,
3582
- isArray: isArray4
3583
- };
3584
- uniforms.push(uniformInfo);
3585
- if (uniformInfo.size > 1) {
3586
- for (let j = 0; j < uniformInfo.size; j++) {
3587
- const elementName = `${name}[${j}]`;
3588
- webglLocation = gl.getUniformLocation(program, elementName);
3589
- const arrayElementUniformInfo = {
3590
- ...uniformInfo,
3591
- name: elementName,
3592
- location: webglLocation
3593
- };
3594
- uniforms.push(arrayElementUniformInfo);
3595
- }
3596
- }
3597
- }
3598
- return uniforms;
3599
- }
3600
- function readUniformBlocks(gl, program) {
3601
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3602
- const uniformBlocks = [];
3603
- const blockCount = gl.getProgramParameter(program, 35382);
3604
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3605
- const blockInfo = {
3606
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3607
- location: getBlockParameter(blockIndex, 35391),
3608
- byteLength: getBlockParameter(blockIndex, 35392),
3609
- vertex: getBlockParameter(blockIndex, 35396),
3610
- fragment: getBlockParameter(blockIndex, 35398),
3611
- uniformCount: getBlockParameter(blockIndex, 35394),
3612
- uniforms: []
3613
- };
3614
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3615
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3616
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3617
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3618
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3619
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3620
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3621
- if (!activeInfo) {
3622
- throw new Error("activeInfo");
3623
- }
3624
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3625
- blockInfo.uniforms.push({
3626
- name: activeInfo.name,
3627
- format,
3628
- type: uniformType[i],
3629
- arrayLength: uniformArrayLength[i],
3630
- byteOffset: uniformOffset[i],
3631
- byteStride: uniformStride[i]
3632
- // matrixStride: uniformStride[i],
3633
- // rowMajor: uniformRowMajor[i]
3634
- });
3635
- }
3636
- uniformBlocks.push(blockInfo);
3637
- }
3638
- uniformBlocks.sort((a, b) => a.location - b.location);
3639
- return uniformBlocks;
3640
- }
3641
- function parseUniformName(name) {
3642
- if (name[name.length - 1] !== "]") {
3643
- return {
3644
- name,
3645
- length: 1,
3646
- isArray: false
3647
- };
3648
- }
3649
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3650
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3651
- if (!matches || matches.length < 2) {
3652
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3653
- }
3654
- return {
3655
- name: matches[1],
3656
- length: matches[2] ? 1 : 0,
3657
- isArray: Boolean(matches[2])
3658
- };
3659
- }
3660
- var import_core15;
3661
- var init_get_shader_layout_from_glsl = __esm({
3662
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3663
- import_core15 = __toESM(require_core2(), 1);
3664
- init_webgl_shadertypes();
3665
- }
3666
- });
3667
-
3668
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3669
- function setUniform(gl, location, type, value) {
3670
- const gl2 = gl;
3671
- let uniformValue = value;
3672
- if (uniformValue === true) {
3673
- uniformValue = 1;
3674
- }
3675
- if (uniformValue === false) {
3676
- uniformValue = 0;
3677
- }
3678
- const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
3679
- switch (type) {
3680
- case 35678:
3681
- case 35680:
3682
- case 35679:
3683
- case 35682:
3684
- case 36289:
3685
- case 36292:
3686
- case 36293:
3687
- case 36298:
3688
- case 36299:
3689
- case 36300:
3690
- case 36303:
3691
- case 36306:
3692
- case 36307:
3693
- case 36308:
3694
- case 36311:
3695
- if (typeof value !== "number") {
3696
- throw new Error("samplers must be set to integers");
3697
- }
3698
- return gl.uniform1i(location, value);
3699
- case 5126:
3700
- return gl.uniform1fv(location, arrayValue);
3701
- case 35664:
3702
- return gl.uniform2fv(location, arrayValue);
3703
- case 35665:
3704
- return gl.uniform3fv(location, arrayValue);
3705
- case 35666:
3706
- return gl.uniform4fv(location, arrayValue);
3707
- case 5124:
3708
- return gl.uniform1iv(location, arrayValue);
3709
- case 35667:
3710
- return gl.uniform2iv(location, arrayValue);
3711
- case 35668:
3712
- return gl.uniform3iv(location, arrayValue);
3713
- case 35669:
3714
- return gl.uniform4iv(location, arrayValue);
3715
- case 35670:
3716
- return gl.uniform1iv(location, arrayValue);
3717
- case 35671:
3718
- return gl.uniform2iv(location, arrayValue);
3719
- case 35672:
3720
- return gl.uniform3iv(location, arrayValue);
3721
- case 35673:
3722
- return gl.uniform4iv(location, arrayValue);
3723
- case 5125:
3724
- return gl2.uniform1uiv(location, arrayValue, 1);
3725
- case 36294:
3726
- return gl2.uniform2uiv(location, arrayValue, 2);
3727
- case 36295:
3728
- return gl2.uniform3uiv(location, arrayValue, 3);
3729
- case 36296:
3730
- return gl2.uniform4uiv(location, arrayValue, 4);
3731
- case 35674:
3732
- return gl.uniformMatrix2fv(location, false, arrayValue);
3733
- case 35675:
3734
- return gl.uniformMatrix3fv(location, false, arrayValue);
3735
- case 35676:
3736
- return gl.uniformMatrix4fv(location, false, arrayValue);
3737
- case 35685:
3738
- return gl2.uniformMatrix2x3fv(location, false, arrayValue);
3739
- case 35686:
3740
- return gl2.uniformMatrix2x4fv(location, false, arrayValue);
3741
- case 35687:
3742
- return gl2.uniformMatrix3x2fv(location, false, arrayValue);
3743
- case 35688:
3744
- return gl2.uniformMatrix3x4fv(location, false, arrayValue);
3745
- case 35689:
3746
- return gl2.uniformMatrix4x2fv(location, false, arrayValue);
3747
- case 35690:
3748
- return gl2.uniformMatrix4x3fv(location, false, arrayValue);
4392
+ const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
4393
+ const { type, components } = (0, import_core18.getVariableShaderTypeInfo)(uniformType);
4394
+ varyings.push({ location, name, type, size: size * components });
3749
4395
  }
3750
- throw new Error("Illegal uniform");
4396
+ varyings.sort((a, b) => a.location - b.location);
4397
+ return varyings;
3751
4398
  }
3752
- var init_set_uniform = __esm({
3753
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js"() {
4399
+ function readUniformBindings(gl, program) {
4400
+ const uniforms = [];
4401
+ const uniformCount = gl.getProgramParameter(program, 35718);
4402
+ for (let i = 0; i < uniformCount; i++) {
4403
+ const activeInfo = gl.getActiveUniform(program, i);
4404
+ if (!activeInfo) {
4405
+ throw new Error("activeInfo");
4406
+ }
4407
+ const { name: rawName, size, type } = activeInfo;
4408
+ const { name, isArray: isArray4 } = parseUniformName(rawName);
4409
+ let webglLocation = gl.getUniformLocation(program, name);
4410
+ const uniformInfo = {
4411
+ // WebGL locations are uniquely typed but just numbers
4412
+ location: webglLocation,
4413
+ name,
4414
+ size,
4415
+ type,
4416
+ isArray: isArray4
4417
+ };
4418
+ uniforms.push(uniformInfo);
4419
+ if (uniformInfo.size > 1) {
4420
+ for (let j = 0; j < uniformInfo.size; j++) {
4421
+ const elementName = `${name}[${j}]`;
4422
+ webglLocation = gl.getUniformLocation(program, elementName);
4423
+ const arrayElementUniformInfo = {
4424
+ ...uniformInfo,
4425
+ name: elementName,
4426
+ location: webglLocation
4427
+ };
4428
+ uniforms.push(arrayElementUniformInfo);
4429
+ }
4430
+ }
3754
4431
  }
3755
- });
3756
-
3757
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
3758
- function getGLDrawMode(topology) {
3759
- switch (topology) {
3760
- case "point-list":
3761
- return 0;
3762
- case "line-list":
3763
- return 1;
3764
- case "line-strip":
3765
- return 3;
3766
- case "triangle-list":
3767
- return 4;
3768
- case "triangle-strip":
3769
- return 5;
3770
- default:
3771
- throw new Error(topology);
4432
+ return uniforms;
4433
+ }
4434
+ function readUniformBlocks(gl, program) {
4435
+ const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
4436
+ const uniformBlocks = [];
4437
+ const blockCount = gl.getProgramParameter(program, 35382);
4438
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
4439
+ const blockInfo = {
4440
+ name: gl.getActiveUniformBlockName(program, blockIndex) || "",
4441
+ location: getBlockParameter(blockIndex, 35391),
4442
+ byteLength: getBlockParameter(blockIndex, 35392),
4443
+ vertex: getBlockParameter(blockIndex, 35396),
4444
+ fragment: getBlockParameter(blockIndex, 35398),
4445
+ uniformCount: getBlockParameter(blockIndex, 35394),
4446
+ uniforms: []
4447
+ };
4448
+ const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
4449
+ const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
4450
+ const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
4451
+ const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
4452
+ const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
4453
+ for (let i = 0; i < blockInfo.uniformCount; ++i) {
4454
+ const uniformIndex = uniformIndices[i];
4455
+ if (uniformIndex !== void 0) {
4456
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
4457
+ if (!activeInfo) {
4458
+ throw new Error("activeInfo");
4459
+ }
4460
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
4461
+ blockInfo.uniforms.push({
4462
+ name: activeInfo.name,
4463
+ format,
4464
+ type: uniformType[i],
4465
+ arrayLength: uniformArrayLength[i],
4466
+ byteOffset: uniformOffset[i],
4467
+ byteStride: uniformStride[i]
4468
+ // matrixStride: uniformStride[i],
4469
+ // rowMajor: uniformRowMajor[i]
4470
+ });
4471
+ }
4472
+ }
4473
+ uniformBlocks.push(blockInfo);
3772
4474
  }
4475
+ uniformBlocks.sort((a, b) => a.location - b.location);
4476
+ return uniformBlocks;
3773
4477
  }
3774
- function getGLPrimitive(topology) {
3775
- switch (topology) {
3776
- case "point-list":
3777
- return 0;
3778
- case "line-list":
3779
- return 1;
3780
- case "line-strip":
3781
- return 1;
3782
- case "triangle-list":
3783
- return 4;
3784
- case "triangle-strip":
3785
- return 4;
3786
- default:
3787
- throw new Error(topology);
4478
+ function parseUniformName(name) {
4479
+ if (name[name.length - 1] !== "]") {
4480
+ return {
4481
+ name,
4482
+ length: 1,
4483
+ isArray: false
4484
+ };
3788
4485
  }
4486
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
4487
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
4488
+ const uniformName = (0, import_core18.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
4489
+ return {
4490
+ name: uniformName,
4491
+ // TODO - is this a bug, shouldn't we return the value?
4492
+ length: matches?.[2] ? 1 : 0,
4493
+ isArray: Boolean(matches?.[2])
4494
+ };
3789
4495
  }
3790
- var init_webgl_topology_utils = __esm({
3791
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
4496
+ var import_core18;
4497
+ var init_get_shader_layout_from_glsl = __esm({
4498
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
4499
+ import_core18 = __toESM(require_core2(), 1);
4500
+ init_webgl_shadertypes();
3792
4501
  }
3793
4502
  });
3794
4503
 
3795
- // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3796
- function mergeShaderLayout(baseLayout, overrideLayout) {
3797
- const mergedLayout = {
3798
- ...baseLayout,
3799
- attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
3800
- };
3801
- for (const attribute of overrideLayout?.attributes || []) {
3802
- const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3803
- if (!baseAttribute) {
3804
- import_core16.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3805
- } else {
3806
- baseAttribute.type = attribute.type || baseAttribute.type;
3807
- baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3808
- }
3809
- }
3810
- return mergedLayout;
3811
- }
3812
- var import_core16, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3813
- var init_webgl_render_pipeline = __esm({
3814
- "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3815
- import_core16 = __toESM(require_core2(), 1);
4504
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js
4505
+ var import_core19, LOG_PROGRAM_PERF_PRIORITY, WEBGLSharedRenderPipeline;
4506
+ var init_webgl_shared_render_pipeline = __esm({
4507
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js"() {
4508
+ import_core19 = __toESM(require_core2(), 1);
3816
4509
  init_get_shader_layout_from_glsl();
3817
- init_device_parameters();
3818
- init_set_uniform();
3819
- init_webgl_buffer();
3820
- init_webgl_framebuffer();
3821
- init_webgl_texture();
3822
- init_webgl_texture_view();
3823
- init_webgl_topology_utils();
4510
+ init_webgl_shadertypes();
3824
4511
  LOG_PROGRAM_PERF_PRIORITY = 4;
3825
- WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3826
- /** The WebGL device that created this render pipeline */
4512
+ WEBGLSharedRenderPipeline = class extends import_core19.SharedRenderPipeline {
3827
4513
  device;
3828
- /** Handle to underlying WebGL program */
3829
4514
  handle;
3830
- /** vertex shader */
3831
4515
  vs;
3832
- /** fragment shader */
3833
4516
  fs;
3834
- /** The layout extracted from shader by WebGL introspection APIs */
3835
- introspectedLayout;
3836
- /** Uniforms set on this model */
3837
- uniforms = {};
3838
- /** Bindings set on this model */
3839
- bindings = {};
3840
- /** WebGL varyings */
3841
- varyings = null;
3842
- _uniformCount = 0;
3843
- _uniformSetters = {};
3844
- // TODO are these used?
3845
- get [Symbol.toStringTag]() {
3846
- return "WEBGLRenderPipeline";
3847
- }
4517
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4518
+ linkStatus = "pending";
3848
4519
  constructor(device, props) {
3849
4520
  super(device, props);
3850
4521
  this.device = device;
3851
- this.handle = this.props.handle || this.device.gl.createProgram();
3852
- this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4522
+ this.handle = props.handle || this.device.gl.createProgram();
3853
4523
  this.vs = props.vs;
3854
4524
  this.fs = props.fs;
3855
- const { varyings, bufferMode = 35981 } = props;
3856
- if (varyings && varyings.length > 0) {
3857
- this.varyings = varyings;
3858
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4525
+ if (props.varyings && props.varyings.length > 0) {
4526
+ this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
3859
4527
  }
3860
4528
  this._linkShaders();
3861
- import_core16.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4529
+ import_core19.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3862
4530
  this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3863
- import_core16.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3864
- this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4531
+ import_core19.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3865
4532
  }
3866
4533
  destroy() {
3867
- if (this.handle) {
3868
- this.device.gl.useProgram(null);
3869
- this.device.gl.deleteProgram(this.handle);
3870
- this.destroyed = true;
3871
- this.handle.destroyed = true;
3872
- this.handle = null;
3873
- }
3874
- }
3875
- /**
3876
- * Bindings include: textures, samplers and uniform buffers
3877
- * @todo needed for portable model
3878
- */
3879
- setBindings(bindings, options) {
3880
- for (const [name, value] of Object.entries(bindings)) {
3881
- const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
3882
- if (!binding) {
3883
- const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
3884
- if (!options?.disableWarnings) {
3885
- import_core16.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
3886
- }
3887
- continue;
3888
- }
3889
- if (!value) {
3890
- import_core16.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
3891
- }
3892
- switch (binding.type) {
3893
- case "uniform":
3894
- if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
3895
- throw new Error("buffer value");
3896
- }
3897
- break;
3898
- case "texture":
3899
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3900
- throw new Error(`${this} Bad texture binding for ${name}`);
3901
- }
3902
- break;
3903
- case "sampler":
3904
- import_core16.log.warn(`Ignoring sampler ${name}`)();
3905
- break;
3906
- default:
3907
- throw new Error(binding.type);
3908
- }
3909
- this.bindings[name] = value;
3910
- }
3911
- }
3912
- /** @todo needed for portable model
3913
- * @note The WebGL API is offers many ways to draw things
3914
- * This function unifies those ways into a single call using common parameters with sane defaults
3915
- */
3916
- draw(options) {
3917
- const {
3918
- renderPass,
3919
- parameters = this.props.parameters,
3920
- topology = this.props.topology,
3921
- vertexArray,
3922
- vertexCount,
3923
- // indexCount,
3924
- instanceCount,
3925
- isInstanced = false,
3926
- firstVertex = 0,
3927
- // firstIndex,
3928
- // firstInstance,
3929
- // baseVertex,
3930
- transformFeedback
3931
- } = options;
3932
- const glDrawMode = getGLDrawMode(topology);
3933
- const isIndexed = Boolean(vertexArray.indexBuffer);
3934
- const glIndexType = vertexArray.indexBuffer?.glIndexType;
3935
- if (this.linkStatus !== "success") {
3936
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
3937
- return false;
3938
- }
3939
- if (!this._areTexturesRenderable()) {
3940
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
3941
- return false;
3942
- }
3943
- this.device.gl.useProgram(this.handle);
3944
- vertexArray.bindBeforeRender(renderPass);
3945
- if (transformFeedback) {
3946
- transformFeedback.begin(this.props.topology);
3947
- }
3948
- this._applyBindings();
3949
- this._applyUniforms();
3950
- const webglRenderPass = renderPass;
3951
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
3952
- if (isIndexed && isInstanced) {
3953
- this.device.gl.drawElementsInstanced(
3954
- glDrawMode,
3955
- vertexCount || 0,
3956
- // indexCount?
3957
- glIndexType,
3958
- firstVertex,
3959
- instanceCount || 0
3960
- );
3961
- } else if (isIndexed) {
3962
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
3963
- } else if (isInstanced) {
3964
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
3965
- } else {
3966
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
3967
- }
3968
- if (transformFeedback) {
3969
- transformFeedback.end();
3970
- }
3971
- });
3972
- vertexArray.unbindAfterRender(renderPass);
3973
- return true;
4534
+ if (this.destroyed) {
4535
+ return;
4536
+ }
4537
+ this.device.gl.useProgram(null);
4538
+ this.device.gl.deleteProgram(this.handle);
4539
+ this.handle.destroyed = true;
4540
+ this.destroyResource();
3974
4541
  }
3975
- // PRIVATE METHODS
3976
- // setAttributes(attributes: Record<string, Buffer>): void {}
3977
- // setBindings(bindings: Record<string, Binding>): void {}
3978
4542
  async _linkShaders() {
3979
4543
  const { gl } = this.device;
3980
4544
  gl.attachShader(this.handle, this.vs.handle);
3981
4545
  gl.attachShader(this.handle, this.fs.handle);
3982
- import_core16.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4546
+ import_core19.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3983
4547
  gl.linkProgram(this.handle);
3984
- import_core16.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3985
- if (import_core16.log.level === 0) {
3986
- }
4548
+ import_core19.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3987
4549
  if (!this.device.features.has("compilation-status-async-webgl")) {
3988
4550
  const status2 = this._getLinkStatus();
3989
4551
  this._reportLinkStatus(status2);
3990
4552
  return;
3991
4553
  }
3992
- import_core16.log.once(1, "RenderPipeline linking is asynchronous")();
4554
+ import_core19.log.once(1, "RenderPipeline linking is asynchronous")();
3993
4555
  await this._waitForLinkComplete();
3994
- import_core16.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4556
+ import_core19.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
3995
4557
  const status = this._getLinkStatus();
3996
4558
  this._reportLinkStatus(status);
3997
4559
  }
3998
- /** Report link status. First, check for shader compilation failures if linking fails */
3999
4560
  async _reportLinkStatus(status) {
4000
4561
  switch (status) {
4001
4562
  case "success":
@@ -4029,11 +4590,6 @@ ${source}`;
4029
4590
  this.device.debug();
4030
4591
  }
4031
4592
  }
4032
- /**
4033
- * Get the shader compilation status
4034
- * TODO - Load log even when no error reported, to catch warnings?
4035
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4036
- */
4037
4593
  _getLinkStatus() {
4038
4594
  const { gl } = this.device;
4039
4595
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -4041,6 +4597,7 @@ ${source}`;
4041
4597
  this.linkStatus = "error";
4042
4598
  return "link-error";
4043
4599
  }
4600
+ this._initializeSamplerUniforms();
4044
4601
  gl.validateProgram(this.handle);
4045
4602
  const validated = gl.getProgramParameter(this.handle, 35715);
4046
4603
  if (!validated) {
@@ -4050,7 +4607,33 @@ ${source}`;
4050
4607
  this.linkStatus = "success";
4051
4608
  return "success";
4052
4609
  }
4053
- /** Use KHR_parallel_shader_compile extension if available */
4610
+ _initializeSamplerUniforms() {
4611
+ const { gl } = this.device;
4612
+ gl.useProgram(this.handle);
4613
+ let textureUnit = 0;
4614
+ const uniformCount = gl.getProgramParameter(this.handle, 35718);
4615
+ for (let uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) {
4616
+ const activeInfo = gl.getActiveUniform(this.handle, uniformIndex);
4617
+ if (activeInfo && isGLSamplerType(activeInfo.type)) {
4618
+ const isArray4 = activeInfo.name.endsWith("[0]");
4619
+ const uniformName = isArray4 ? activeInfo.name.slice(0, -3) : activeInfo.name;
4620
+ const location = gl.getUniformLocation(this.handle, uniformName);
4621
+ if (location !== null) {
4622
+ textureUnit = this._assignSamplerUniform(location, activeInfo, isArray4, textureUnit);
4623
+ }
4624
+ }
4625
+ }
4626
+ }
4627
+ _assignSamplerUniform(location, activeInfo, isArray4, textureUnit) {
4628
+ const { gl } = this.device;
4629
+ if (isArray4 && activeInfo.size > 1) {
4630
+ const textureUnits = Int32Array.from({ length: activeInfo.size }, (_, arrayIndex) => textureUnit + arrayIndex);
4631
+ gl.uniform1iv(location, textureUnits);
4632
+ return textureUnit + activeInfo.size;
4633
+ }
4634
+ gl.uniform1i(location, textureUnit);
4635
+ return textureUnit + 1;
4636
+ }
4054
4637
  async _waitForLinkComplete() {
4055
4638
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4056
4639
  const DELAY_MS = 10;
@@ -4067,99 +4650,6 @@ ${source}`;
4067
4650
  await waitMs(DELAY_MS);
4068
4651
  }
4069
4652
  }
4070
- /**
4071
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4072
- * Update a texture if needed (e.g. from video)
4073
- * Note: This is currently done before every draw call
4074
- */
4075
- _areTexturesRenderable() {
4076
- let texturesRenderable = true;
4077
- for (const bindingInfo of this.shaderLayout.bindings) {
4078
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4079
- import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4080
- texturesRenderable = false;
4081
- }
4082
- }
4083
- return texturesRenderable;
4084
- }
4085
- /** Apply any bindings (before each draw call) */
4086
- _applyBindings() {
4087
- if (this.linkStatus !== "success") {
4088
- return;
4089
- }
4090
- const { gl } = this.device;
4091
- gl.useProgram(this.handle);
4092
- let textureUnit = 0;
4093
- let uniformBufferIndex = 0;
4094
- for (const binding of this.shaderLayout.bindings) {
4095
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4096
- if (!value) {
4097
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4098
- }
4099
- switch (binding.type) {
4100
- case "uniform":
4101
- const { name } = binding;
4102
- const location = gl.getUniformBlockIndex(this.handle, name);
4103
- if (location === 4294967295) {
4104
- throw new Error(`Invalid uniform block name ${name}`);
4105
- }
4106
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
4107
- if (value instanceof WEBGLBuffer) {
4108
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4109
- } else {
4110
- gl.bindBufferRange(
4111
- 35345,
4112
- uniformBufferIndex,
4113
- // @ts-expect-error
4114
- value.buffer.handle,
4115
- // @ts-expect-error
4116
- value.offset || 0,
4117
- // @ts-expect-error
4118
- value.size || value.buffer.byteLength - value.offset
4119
- );
4120
- }
4121
- uniformBufferIndex += 1;
4122
- break;
4123
- case "texture":
4124
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4125
- throw new Error("texture");
4126
- }
4127
- let texture;
4128
- if (value instanceof WEBGLTextureView) {
4129
- texture = value.texture;
4130
- } else if (value instanceof WEBGLTexture) {
4131
- texture = value;
4132
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4133
- import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4134
- texture = value.colorAttachments[0].texture;
4135
- } else {
4136
- throw new Error("No texture");
4137
- }
4138
- gl.activeTexture(33984 + textureUnit);
4139
- gl.bindTexture(texture.glTarget, texture.handle);
4140
- textureUnit += 1;
4141
- break;
4142
- case "sampler":
4143
- break;
4144
- case "storage":
4145
- case "read-only-storage":
4146
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4147
- }
4148
- }
4149
- }
4150
- /**
4151
- * Due to program sharing, uniforms need to be reset before every draw call
4152
- * (though caching will avoid redundant WebGL calls)
4153
- */
4154
- _applyUniforms() {
4155
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4156
- const { name, location, type, textureUnit } = uniformLayout;
4157
- const value = this.uniforms[name] ?? textureUnit;
4158
- if (value !== void 0) {
4159
- setUniform(this.device.gl, location, type, value);
4160
- }
4161
- }
4162
- }
4163
4653
  };
4164
4654
  }
4165
4655
  });
@@ -4191,7 +4681,7 @@ ${source}`;
4191
4681
  height = options.sourceTexture.height,
4192
4682
  depthOrArrayLayers = 0,
4193
4683
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
4194
- origin = [0, 0],
4684
+ origin = [0, 0, 0],
4195
4685
  /** Destination buffer */
4196
4686
  destinationBuffer,
4197
4687
  /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
@@ -4220,7 +4710,8 @@ ${source}`;
4220
4710
  const webglBuffer = destinationBuffer;
4221
4711
  const sourceWidth = width || framebuffer.width;
4222
4712
  const sourceHeight = height || framebuffer.height;
4223
- const sourceParams = getTextureFormatWebGL(framebuffer.colorAttachments[0].texture.props.format);
4713
+ const colorAttachment0 = (0, import_core20.assertDefined)(framebuffer.colorAttachments[0]);
4714
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
4224
4715
  const sourceFormat = sourceParams.format;
4225
4716
  const sourceType = sourceParams.type;
4226
4717
  device.gl.bindBuffer(35051, webglBuffer.handle);
@@ -4247,7 +4738,7 @@ ${source}`;
4247
4738
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
4248
4739
  origin = [0, 0],
4249
4740
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
4250
- destinationOrigin = [0, 0],
4741
+ destinationOrigin = [0, 0, 0],
4251
4742
  /** Texture to copy to/from. */
4252
4743
  destinationTexture
4253
4744
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -4263,7 +4754,7 @@ ${source}`;
4263
4754
  // depthOrArrayLayers = 0
4264
4755
  } = options;
4265
4756
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
4266
- const [sourceX, sourceY] = origin;
4757
+ const [sourceX = 0, sourceY = 0] = origin;
4267
4758
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
4268
4759
  const prevHandle = device.gl.bindFramebuffer(36160, framebuffer.handle);
4269
4760
  let texture;
@@ -4297,7 +4788,7 @@ ${source}`;
4297
4788
  }
4298
4789
  }
4299
4790
  function getFramebuffer(source) {
4300
- if (source instanceof import_core17.Texture) {
4791
+ if (source instanceof import_core20.Texture) {
4301
4792
  const { width, height, id } = source;
4302
4793
  const framebuffer = source.device.createFramebuffer({
4303
4794
  id: `framebuffer-for-${id}`,
@@ -4309,18 +4800,18 @@ ${source}`;
4309
4800
  }
4310
4801
  return { framebuffer: source, destroyFramebuffer: false };
4311
4802
  }
4312
- var import_core17, WEBGLCommandBuffer;
4803
+ var import_core20, WEBGLCommandBuffer;
4313
4804
  var init_webgl_command_buffer = __esm({
4314
4805
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-buffer.js"() {
4315
- import_core17 = __toESM(require_core2(), 1);
4806
+ import_core20 = __toESM(require_core2(), 1);
4316
4807
  init_webgl_texture();
4317
4808
  init_webgl_texture_table();
4318
- WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
4809
+ WEBGLCommandBuffer = class extends import_core20.CommandBuffer {
4319
4810
  device;
4320
4811
  handle = null;
4321
4812
  commands = [];
4322
- constructor(device) {
4323
- super(device, {});
4813
+ constructor(device, props = {}) {
4814
+ super(device, props);
4324
4815
  this.device = device;
4325
4816
  }
4326
4817
  _executeCommands(commands = this.commands) {
@@ -4348,14 +4839,14 @@ ${source}`;
4348
4839
  });
4349
4840
 
4350
4841
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js
4351
- var import_core18, COLOR_CHANNELS, WEBGLRenderPass;
4842
+ var import_core21, COLOR_CHANNELS, WEBGLRenderPass;
4352
4843
  var init_webgl_render_pass = __esm({
4353
4844
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js"() {
4354
- import_core18 = __toESM(require_core2(), 1);
4845
+ import_core21 = __toESM(require_core2(), 1);
4355
4846
  init_with_parameters();
4356
4847
  init_unified_parameter_api();
4357
4848
  COLOR_CHANNELS = [1, 2, 4, 8];
4358
- WEBGLRenderPass = class extends import_core18.RenderPass {
4849
+ WEBGLRenderPass = class extends import_core21.RenderPass {
4359
4850
  device;
4360
4851
  handle = null;
4361
4852
  /** Parameters that should be applied before each draw call */
@@ -4363,6 +4854,9 @@ ${source}`;
4363
4854
  constructor(device, props) {
4364
4855
  super(device, props);
4365
4856
  this.device = device;
4857
+ if (!props?.framebuffer) {
4858
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4859
+ }
4366
4860
  let viewport;
4367
4861
  if (!props?.parameters?.viewport) {
4368
4862
  if (props?.framebuffer) {
@@ -4379,13 +4873,25 @@ ${source}`;
4379
4873
  if (this.props.framebuffer && webglFramebuffer?.handle) {
4380
4874
  const drawBuffers = this.props.framebuffer.colorAttachments.map((_, i) => 36064 + i);
4381
4875
  this.device.gl.drawBuffers(drawBuffers);
4382
- } else {
4876
+ } else if (!this.props.framebuffer) {
4383
4877
  this.device.gl.drawBuffers([1029]);
4384
4878
  }
4385
4879
  this.clear();
4880
+ if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== void 0) {
4881
+ const webglQuerySet = this.props.timestampQuerySet;
4882
+ webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
4883
+ }
4386
4884
  }
4387
4885
  end() {
4886
+ if (this.destroyed) {
4887
+ return;
4888
+ }
4889
+ if (this.props.timestampQuerySet && this.props.endTimestampIndex !== void 0) {
4890
+ const webglQuerySet = this.props.timestampQuerySet;
4891
+ webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
4892
+ }
4388
4893
  this.device.popState();
4894
+ this.destroy();
4389
4895
  }
4390
4896
  pushDebugGroup(groupLabel) {
4391
4897
  }
@@ -4425,9 +4931,9 @@ ${source}`;
4425
4931
  if (parameters.blendConstant) {
4426
4932
  glParameters.blendColor = parameters.blendConstant;
4427
4933
  }
4428
- if (parameters.stencilReference) {
4429
- console.warn("RenderPassParameters.stencilReference not yet implemented in WebGL");
4934
+ if (parameters.stencilReference !== void 0) {
4430
4935
  glParameters[2967] = parameters.stencilReference;
4936
+ glParameters[36003] = parameters.stencilReference;
4431
4937
  }
4432
4938
  if ("colorMask" in parameters) {
4433
4939
  glParameters.colorMask = COLOR_CHANNELS.map((channel) => Boolean(channel & parameters.colorMask));
@@ -4505,30 +5011,38 @@ ${source}`;
4505
5011
  });
4506
5012
 
4507
5013
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js
4508
- var import_core19, WEBGLCommandEncoder;
5014
+ var import_core22, WEBGLCommandEncoder;
4509
5015
  var init_webgl_command_encoder = __esm({
4510
5016
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js"() {
4511
- import_core19 = __toESM(require_core2(), 1);
5017
+ import_core22 = __toESM(require_core2(), 1);
4512
5018
  init_webgl_command_buffer();
4513
5019
  init_webgl_render_pass();
4514
- WEBGLCommandEncoder = class extends import_core19.CommandEncoder {
5020
+ WEBGLCommandEncoder = class extends import_core22.CommandEncoder {
4515
5021
  device;
4516
5022
  handle = null;
4517
5023
  commandBuffer;
4518
5024
  constructor(device, props) {
4519
5025
  super(device, props);
4520
5026
  this.device = device;
4521
- this.commandBuffer = new WEBGLCommandBuffer(device);
5027
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5028
+ id: `${this.props.id}-command-buffer`
5029
+ });
4522
5030
  }
4523
5031
  destroy() {
5032
+ this.destroyResource();
4524
5033
  }
4525
- finish() {
5034
+ finish(props) {
5035
+ if (props?.id && this.commandBuffer.id !== props.id) {
5036
+ this.commandBuffer.id = props.id;
5037
+ this.commandBuffer.props.id = props.id;
5038
+ }
5039
+ this.destroy();
4526
5040
  return this.commandBuffer;
4527
5041
  }
4528
- beginRenderPass(props) {
4529
- return new WEBGLRenderPass(this.device, props);
5042
+ beginRenderPass(props = {}) {
5043
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4530
5044
  }
4531
- beginComputePass(props) {
5045
+ beginComputePass(props = {}) {
4532
5046
  throw new Error("ComputePass not supported in WebGL");
4533
5047
  }
4534
5048
  copyBufferToBuffer(options) {
@@ -4554,6 +5068,10 @@ ${source}`;
4554
5068
  }
4555
5069
  resolveQuerySet(querySet, destination, options) {
4556
5070
  }
5071
+ writeTimestamp(querySet, queryIndex) {
5072
+ const webglQuerySet = querySet;
5073
+ webglQuerySet.writeTimestamp(queryIndex);
5074
+ }
4557
5075
  };
4558
5076
  }
4559
5077
  });
@@ -4565,7 +5083,7 @@ ${source}`;
4565
5083
  const total = count * length;
4566
5084
  let copied = 0;
4567
5085
  for (let i = start; copied < length; copied++) {
4568
- target2[i++] = source[copied];
5086
+ target2[i++] = source[copied] ?? 0;
4569
5087
  }
4570
5088
  while (copied < total) {
4571
5089
  if (copied < total - copied) {
@@ -4601,14 +5119,14 @@ ${source}`;
4601
5119
  }
4602
5120
  return true;
4603
5121
  }
4604
- var import_core20, WEBGLVertexArray;
5122
+ var import_core23, WEBGLVertexArray;
4605
5123
  var init_webgl_vertex_array = __esm({
4606
5124
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-vertex-array.js"() {
4607
- import_core20 = __toESM(require_core2(), 1);
5125
+ import_core23 = __toESM(require_core2(), 1);
4608
5126
  init_dist2();
4609
5127
  init_webgl_vertex_formats();
4610
5128
  init_fill_array();
4611
- WEBGLVertexArray = class extends import_core20.VertexArray {
5129
+ WEBGLVertexArray = class extends import_core23.VertexArray {
4612
5130
  get [Symbol.toStringTag]() {
4613
5131
  return "VertexArray";
4614
5132
  }
@@ -4774,7 +5292,7 @@ ${source}`;
4774
5292
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4775
5293
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4776
5294
  if (updateNeeded) {
4777
- const typedArray = (0, import_core20.getScratchArray)(value.constructor, length);
5295
+ const typedArray = (0, import_core23.getScratchArray)(value.constructor, length);
4778
5296
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4779
5297
  this.buffer.write(typedArray);
4780
5298
  this.bufferValue = value;
@@ -4792,13 +5310,13 @@ ${source}`;
4792
5310
  }
4793
5311
  return /^\d+$/.test(value);
4794
5312
  }
4795
- var import_core21, WEBGLTransformFeedback;
5313
+ var import_core24, WEBGLTransformFeedback;
4796
5314
  var init_webgl_transform_feedback = __esm({
4797
5315
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-transform-feedback.js"() {
4798
- import_core21 = __toESM(require_core2(), 1);
5316
+ import_core24 = __toESM(require_core2(), 1);
4799
5317
  init_dist3();
4800
5318
  init_webgl_topology_utils();
4801
- WEBGLTransformFeedback = class extends import_core21.TransformFeedback {
5319
+ WEBGLTransformFeedback = class extends import_core24.TransformFeedback {
4802
5320
  device;
4803
5321
  gl;
4804
5322
  handle;
@@ -4851,8 +5369,8 @@ ${source}`;
4851
5369
  this.buffers = {};
4852
5370
  this.unusedBuffers = {};
4853
5371
  this.bind(() => {
4854
- for (const bufferName in buffers) {
4855
- this.setBuffer(bufferName, buffers[bufferName]);
5372
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
5373
+ this.setBuffer(bufferName, buffer);
4856
5374
  }
4857
5375
  });
4858
5376
  }
@@ -4861,7 +5379,7 @@ ${source}`;
4861
5379
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
4862
5380
  if (location < 0) {
4863
5381
  this.unusedBuffers[locationOrName] = buffer;
4864
- import_core21.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5382
+ import_core24.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4865
5383
  return;
4866
5384
  }
4867
5385
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -4874,7 +5392,7 @@ ${source}`;
4874
5392
  return this.buffers[locationOrName] || null;
4875
5393
  }
4876
5394
  const location = this._getVaryingIndex(locationOrName);
4877
- return location >= 0 ? this.buffers[location] : null;
5395
+ return this.buffers[location] ?? null;
4878
5396
  }
4879
5397
  bind(funcOrHandle = this.handle) {
4880
5398
  if (typeof funcOrHandle !== "function") {
@@ -4921,8 +5439,8 @@ ${source}`;
4921
5439
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
4922
5440
  */
4923
5441
  _bindBuffers() {
4924
- for (const bufferIndex in this.buffers) {
4925
- const { buffer, byteLength, byteOffset } = this._getBufferRange(this.buffers[bufferIndex]);
5442
+ for (const [bufferIndex, bufferEntry] of Object.entries(this.buffers)) {
5443
+ const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferEntry);
4926
5444
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
4927
5445
  }
4928
5446
  }
@@ -4944,138 +5462,281 @@ ${source}`;
4944
5462
  });
4945
5463
 
4946
5464
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js
4947
- var import_core22, WEBGLQuerySet;
5465
+ var import_core25, WEBGLQuerySet;
4948
5466
  var init_webgl_query_set = __esm({
4949
5467
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js"() {
4950
- import_core22 = __toESM(require_core2(), 1);
4951
- WEBGLQuerySet = class extends import_core22.QuerySet {
5468
+ import_core25 = __toESM(require_core2(), 1);
5469
+ WEBGLQuerySet = class extends import_core25.QuerySet {
4952
5470
  device;
4953
5471
  handle;
4954
- target = null;
4955
- _queryPending = false;
4956
- _pollingPromise = null;
5472
+ _timestampPairs = [];
5473
+ _occlusionQuery = null;
5474
+ _occlusionActive = false;
4957
5475
  get [Symbol.toStringTag]() {
4958
- return "Query";
5476
+ return "QuerySet";
4959
5477
  }
4960
- // Create a query class
4961
5478
  constructor(device, props) {
4962
5479
  super(device, props);
4963
5480
  this.device = device;
4964
- if (props.count > 1) {
4965
- throw new Error("WebGL QuerySet can only have one value");
4966
- }
4967
- const handle = this.device.gl.createQuery();
4968
- if (!handle) {
4969
- throw new Error("WebGL query not supported");
5481
+ if (props.type === "timestamp") {
5482
+ if (props.count < 2) {
5483
+ throw new Error("Timestamp QuerySet requires at least two query slots");
5484
+ }
5485
+ this._timestampPairs = new Array(Math.ceil(props.count / 2)).fill(null).map(() => ({ activeQuery: null, completedQueries: [] }));
5486
+ this.handle = null;
5487
+ } else {
5488
+ if (props.count > 1) {
5489
+ throw new Error("WebGL occlusion QuerySet can only have one value");
5490
+ }
5491
+ const handle = this.device.gl.createQuery();
5492
+ if (!handle) {
5493
+ throw new Error("WebGL query not supported");
5494
+ }
5495
+ this.handle = handle;
4970
5496
  }
4971
- this.handle = handle;
4972
5497
  Object.seal(this);
4973
5498
  }
4974
5499
  destroy() {
4975
- this.device.gl.deleteQuery(this.handle);
5500
+ if (this.destroyed) {
5501
+ return;
5502
+ }
5503
+ if (this.handle) {
5504
+ this.device.gl.deleteQuery(this.handle);
5505
+ }
5506
+ for (const pair of this._timestampPairs) {
5507
+ if (pair.activeQuery) {
5508
+ this.device.gl.deleteQuery(pair.activeQuery.handle);
5509
+ }
5510
+ for (const query of pair.completedQueries) {
5511
+ this.device.gl.deleteQuery(query.handle);
5512
+ }
5513
+ }
5514
+ if (this._occlusionQuery) {
5515
+ this.device.gl.deleteQuery(this._occlusionQuery.handle);
5516
+ }
5517
+ this.destroyResource();
4976
5518
  }
4977
- // FOR RENDER PASS AND COMMAND ENCODER
4978
- /**
4979
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
4980
- * Measures GPU time delta between this call and a matching `end` call in the
4981
- * GPU instruction stream.
4982
- */
4983
- beginTimestampQuery() {
4984
- return this._begin(35007);
5519
+ isResultAvailable(queryIndex) {
5520
+ if (this.props.type === "timestamp") {
5521
+ if (queryIndex === void 0) {
5522
+ return this._timestampPairs.some((_, pairIndex) => this._isTimestampPairAvailable(pairIndex));
5523
+ }
5524
+ return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
5525
+ }
5526
+ if (!this._occlusionQuery) {
5527
+ return false;
5528
+ }
5529
+ return this._pollQueryAvailability(this._occlusionQuery);
5530
+ }
5531
+ async readResults(options) {
5532
+ const firstQuery = options?.firstQuery || 0;
5533
+ const queryCount = options?.queryCount || this.props.count - firstQuery;
5534
+ this._validateRange(firstQuery, queryCount);
5535
+ if (this.props.type === "timestamp") {
5536
+ const results = new Array(queryCount).fill(0n);
5537
+ const startPairIndex = Math.floor(firstQuery / 2);
5538
+ const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
5539
+ for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
5540
+ const duration = await this._consumeTimestampPairResult(pairIndex);
5541
+ const beginSlot = pairIndex * 2;
5542
+ const endSlot = beginSlot + 1;
5543
+ if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
5544
+ results[beginSlot - firstQuery] = 0n;
5545
+ }
5546
+ if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
5547
+ results[endSlot - firstQuery] = duration;
5548
+ }
5549
+ }
5550
+ return results;
5551
+ }
5552
+ if (!this._occlusionQuery) {
5553
+ throw new Error("Occlusion query has not been started");
5554
+ }
5555
+ return [await this._consumeQueryResult(this._occlusionQuery)];
4985
5556
  }
4986
- endTimestampQuery() {
4987
- this._end();
5557
+ async readTimestampDuration(beginIndex, endIndex) {
5558
+ if (this.props.type !== "timestamp") {
5559
+ throw new Error("Timestamp durations require a timestamp QuerySet");
5560
+ }
5561
+ if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
5562
+ throw new Error("Timestamp duration range is out of bounds");
5563
+ }
5564
+ if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
5565
+ throw new Error("WebGL timestamp durations require adjacent even/odd query indices");
5566
+ }
5567
+ const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
5568
+ return Number(result) / 1e6;
4988
5569
  }
4989
- // Shortcut for occlusion queries
4990
- beginOcclusionQuery(options) {
4991
- return this._begin(options?.conservative ? 36202 : 35887);
5570
+ beginOcclusionQuery() {
5571
+ if (this.props.type !== "occlusion") {
5572
+ throw new Error("Occlusion queries require an occlusion QuerySet");
5573
+ }
5574
+ if (!this.handle) {
5575
+ throw new Error("WebGL occlusion query is not available");
5576
+ }
5577
+ if (this._occlusionActive) {
5578
+ throw new Error("Occlusion query is already active");
5579
+ }
5580
+ this.device.gl.beginQuery(35887, this.handle);
5581
+ this._occlusionQuery = {
5582
+ handle: this.handle,
5583
+ promise: null,
5584
+ result: null,
5585
+ disjoint: false
5586
+ };
5587
+ this._occlusionActive = true;
4992
5588
  }
4993
5589
  endOcclusionQuery() {
4994
- this._end();
4995
- }
4996
- // Shortcut for transformFeedbackQuery
4997
- beginTransformFeedbackQuery() {
4998
- return this._begin(35976);
4999
- }
5000
- endTransformFeedbackQuery() {
5001
- this._end();
5002
- }
5003
- async resolveQuery() {
5004
- const value = await this.pollQuery();
5005
- return [value];
5590
+ if (!this._occlusionActive) {
5591
+ throw new Error("Occlusion query is not active");
5592
+ }
5593
+ this.device.gl.endQuery(35887);
5594
+ this._occlusionActive = false;
5006
5595
  }
5007
- // PRIVATE METHODS
5008
- /**
5009
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5010
- * instance, `end()` must be called on that same instance before
5011
- * calling `begin()` on another query. While there can be multiple
5012
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5013
- * It is not possible to interleave or overlap `begin` and `end` calls.
5014
- */
5015
- _begin(target2) {
5016
- if (this._queryPending) {
5596
+ writeTimestamp(queryIndex) {
5597
+ if (this.props.type !== "timestamp") {
5598
+ throw new Error("Timestamp writes require a timestamp QuerySet");
5599
+ }
5600
+ const pairIndex = this._getTimestampPairIndex(queryIndex);
5601
+ const pair = this._timestampPairs[pairIndex];
5602
+ if (queryIndex % 2 === 0) {
5603
+ if (pair.activeQuery) {
5604
+ throw new Error("Timestamp query pair is already active");
5605
+ }
5606
+ const handle = this.device.gl.createQuery();
5607
+ if (!handle) {
5608
+ throw new Error("WebGL query not supported");
5609
+ }
5610
+ const query = {
5611
+ handle,
5612
+ promise: null,
5613
+ result: null,
5614
+ disjoint: false
5615
+ };
5616
+ this.device.gl.beginQuery(35007, handle);
5617
+ pair.activeQuery = query;
5017
5618
  return;
5018
5619
  }
5019
- this.target = target2;
5020
- this.device.gl.beginQuery(this.target, this.handle);
5021
- return;
5620
+ if (!pair.activeQuery) {
5621
+ throw new Error("Timestamp query pair was ended before it was started");
5622
+ }
5623
+ this.device.gl.endQuery(35007);
5624
+ pair.completedQueries.push(pair.activeQuery);
5625
+ pair.activeQuery = null;
5022
5626
  }
5023
- // ends the current query
5024
- _end() {
5025
- if (this._queryPending) {
5026
- return;
5627
+ _validateRange(firstQuery, queryCount) {
5628
+ if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
5629
+ throw new Error("Query read range is out of bounds");
5027
5630
  }
5028
- if (this.target) {
5029
- this.device.gl.endQuery(this.target);
5030
- this.target = null;
5031
- this._queryPending = true;
5631
+ }
5632
+ _getTimestampPairIndex(queryIndex) {
5633
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
5634
+ throw new Error("Query index is out of bounds");
5032
5635
  }
5033
- return;
5636
+ return Math.floor(queryIndex / 2);
5034
5637
  }
5035
- // Returns true if the query result is available
5036
- isResultAvailable() {
5037
- if (!this._queryPending) {
5638
+ _isTimestampPairAvailable(pairIndex) {
5639
+ const pair = this._timestampPairs[pairIndex];
5640
+ if (!pair || pair.completedQueries.length === 0) {
5038
5641
  return false;
5039
5642
  }
5040
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
5041
- if (resultAvailable) {
5042
- this._queryPending = false;
5043
- }
5044
- return resultAvailable;
5643
+ return this._pollQueryAvailability(pair.completedQueries[0]);
5045
5644
  }
5046
- // Timing query is disjoint, i.e. results are invalid
5047
- isTimerDisjoint() {
5048
- return this.device.gl.getParameter(36795);
5645
+ _pollQueryAvailability(query) {
5646
+ if (query.result !== null || query.disjoint) {
5647
+ return true;
5648
+ }
5649
+ const resultAvailable = this.device.gl.getQueryParameter(query.handle, 34919);
5650
+ if (!resultAvailable) {
5651
+ return false;
5652
+ }
5653
+ const isDisjoint = Boolean(this.device.gl.getParameter(36795));
5654
+ query.disjoint = isDisjoint;
5655
+ query.result = isDisjoint ? 0n : BigInt(this.device.gl.getQueryParameter(query.handle, 34918));
5656
+ return true;
5049
5657
  }
5050
- // Returns query result.
5051
- getResult() {
5052
- return this.device.gl.getQueryParameter(this.handle, 34918);
5658
+ async _consumeTimestampPairResult(pairIndex) {
5659
+ const pair = this._timestampPairs[pairIndex];
5660
+ if (!pair || pair.completedQueries.length === 0) {
5661
+ throw new Error("Timestamp query pair has no completed result");
5662
+ }
5663
+ const query = pair.completedQueries.shift();
5664
+ try {
5665
+ return await this._consumeQueryResult(query);
5666
+ } finally {
5667
+ this.device.gl.deleteQuery(query.handle);
5668
+ }
5053
5669
  }
5054
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5055
- getTimerMilliseconds() {
5056
- return this.getResult() / 1e6;
5670
+ _consumeQueryResult(query) {
5671
+ if (query.promise) {
5672
+ return query.promise;
5673
+ }
5674
+ query.promise = new Promise((resolve, reject) => {
5675
+ const poll = () => {
5676
+ if (!this._pollQueryAvailability(query)) {
5677
+ requestAnimationFrame(poll);
5678
+ return;
5679
+ }
5680
+ query.promise = null;
5681
+ if (query.disjoint) {
5682
+ reject(new Error("GPU timestamp query was invalidated by a disjoint event"));
5683
+ } else {
5684
+ resolve(query.result || 0n);
5685
+ }
5686
+ };
5687
+ poll();
5688
+ });
5689
+ return query.promise;
5057
5690
  }
5058
- // Polls the query
5059
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5060
- if (this._pollingPromise) {
5061
- return this._pollingPromise;
5691
+ };
5692
+ }
5693
+ });
5694
+
5695
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js
5696
+ var import_core26, WEBGLFence;
5697
+ var init_webgl_fence = __esm({
5698
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js"() {
5699
+ import_core26 = __toESM(require_core2(), 1);
5700
+ WEBGLFence = class extends import_core26.Fence {
5701
+ device;
5702
+ gl;
5703
+ handle;
5704
+ signaled;
5705
+ _signaled = false;
5706
+ constructor(device, props = {}) {
5707
+ super(device, {});
5708
+ this.device = device;
5709
+ this.gl = device.gl;
5710
+ const sync = this.props.handle || this.gl.fenceSync(this.gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
5711
+ if (!sync) {
5712
+ throw new Error("Failed to create WebGL fence");
5062
5713
  }
5063
- let counter = 0;
5064
- this._pollingPromise = new Promise((resolve, reject) => {
5714
+ this.handle = sync;
5715
+ this.signaled = new Promise((resolve) => {
5065
5716
  const poll = () => {
5066
- if (this.isResultAvailable()) {
5067
- resolve(this.getResult());
5068
- this._pollingPromise = null;
5069
- } else if (counter++ > limit) {
5070
- reject("Timed out");
5071
- this._pollingPromise = null;
5717
+ const status = this.gl.clientWaitSync(this.handle, 0, 0);
5718
+ if (status === this.gl.ALREADY_SIGNALED || status === this.gl.CONDITION_SATISFIED) {
5719
+ this._signaled = true;
5720
+ resolve();
5072
5721
  } else {
5073
- requestAnimationFrame(poll);
5722
+ setTimeout(poll, 1);
5074
5723
  }
5075
5724
  };
5076
- requestAnimationFrame(poll);
5725
+ poll();
5077
5726
  });
5078
- return this._pollingPromise;
5727
+ }
5728
+ isSignaled() {
5729
+ if (this._signaled) {
5730
+ return true;
5731
+ }
5732
+ const status = this.gl.getSyncParameter(this.handle, this.gl.SYNC_STATUS);
5733
+ this._signaled = status === this.gl.SIGNALED;
5734
+ return this._signaled;
5735
+ }
5736
+ destroy() {
5737
+ if (!this.destroyed) {
5738
+ this.gl.deleteSync(this.handle);
5739
+ }
5079
5740
  }
5080
5741
  };
5081
5742
  }
@@ -5126,34 +5787,6 @@ ${source}`;
5126
5787
  }
5127
5788
  });
5128
5789
 
5129
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
5130
- function convertGLDataTypeToDataType(type) {
5131
- return GL_DATA_TYPE_MAP[type];
5132
- }
5133
- var GL_DATA_TYPE_MAP;
5134
- var init_shader_formats = __esm({
5135
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js"() {
5136
- GL_DATA_TYPE_MAP = {
5137
- [5124]: "sint32",
5138
- [5125]: "uint32",
5139
- [5122]: "sint16",
5140
- [5123]: "uint16",
5141
- [5120]: "sint8",
5142
- [5121]: "uint8",
5143
- [5126]: "float32",
5144
- [5131]: "float16",
5145
- [33635]: "uint16",
5146
- [32819]: "uint16",
5147
- [32820]: "uint16",
5148
- [33640]: "uint32",
5149
- [35899]: "uint32",
5150
- [35902]: "uint32",
5151
- [34042]: "uint32",
5152
- [36269]: "uint32"
5153
- };
5154
- }
5155
- });
5156
-
5157
5790
  // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js
5158
5791
  function readPixelsToArray(source, options) {
5159
5792
  const {
@@ -5183,7 +5816,7 @@ ${source}`;
5183
5816
  sourceFormat ||= texture?.glFormat || 6408;
5184
5817
  sourceType ||= texture?.glType || 5121;
5185
5818
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5186
- const signedType = (0, import_core23.getDataType)(target2);
5819
+ const signedType = (0, import_core27.getDataType)(target2);
5187
5820
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5188
5821
  const prevHandle = gl.bindFramebuffer(36160, handle);
5189
5822
  gl.readBuffer(36064 + sourceAttachment);
@@ -5226,7 +5859,7 @@ ${source}`;
5226
5859
  return webglBufferTarget;
5227
5860
  }
5228
5861
  function getFramebuffer2(source) {
5229
- if (!(source instanceof import_core23.Framebuffer)) {
5862
+ if (!(source instanceof import_core27.Framebuffer)) {
5230
5863
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5231
5864
  }
5232
5865
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5248,14 +5881,14 @@ ${source}`;
5248
5881
  }
5249
5882
  glType ||= 5121;
5250
5883
  const shaderType = convertGLDataTypeToDataType(glType);
5251
- const ArrayType = (0, import_core23.getTypedArrayConstructor)(shaderType);
5884
+ const ArrayType = (0, import_core27.getTypedArrayConstructor)(shaderType);
5252
5885
  const components = glFormatToComponents(glFormat);
5253
5886
  return new ArrayType(width * height * components);
5254
5887
  }
5255
- var import_core23;
5888
+ var import_core27;
5256
5889
  var init_webgl_texture_utils = __esm({
5257
5890
  "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js"() {
5258
- import_core23 = __toESM(require_core2(), 1);
5891
+ import_core27 = __toESM(require_core2(), 1);
5259
5892
  init_webgl_shadertypes();
5260
5893
  init_format_utils();
5261
5894
  init_shader_formats();
@@ -5297,16 +5930,18 @@ ${source}`;
5297
5930
  }
5298
5931
  return true;
5299
5932
  }
5300
- var import_core24, WebGLDevice;
5933
+ var import_core28, WebGLDevice;
5301
5934
  var init_webgl_device = __esm({
5302
5935
  "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-device.js"() {
5303
- import_core24 = __toESM(require_core2(), 1);
5936
+ import_core28 = __toESM(require_core2(), 1);
5304
5937
  init_webgl_state_tracker();
5305
5938
  init_create_browser_context();
5939
+ init_webgl_context_data();
5306
5940
  init_webgl_device_info();
5307
5941
  init_webgl_device_features();
5308
5942
  init_webgl_device_limits();
5309
5943
  init_webgl_canvas_context();
5944
+ init_webgl_presentation_context();
5310
5945
  init_spector();
5311
5946
  init_webgl_developer_tools();
5312
5947
  init_webgl_texture_table();
@@ -5317,15 +5952,23 @@ ${source}`;
5317
5952
  init_webgl_texture();
5318
5953
  init_webgl_framebuffer();
5319
5954
  init_webgl_render_pipeline();
5955
+ init_webgl_shared_render_pipeline();
5320
5956
  init_webgl_command_encoder();
5321
5957
  init_webgl_vertex_array();
5322
5958
  init_webgl_transform_feedback();
5323
5959
  init_webgl_query_set();
5960
+ init_webgl_fence();
5324
5961
  init_webgl_texture_utils();
5325
5962
  init_unified_parameter_api();
5326
5963
  init_with_parameters();
5327
5964
  init_webgl_extensions();
5328
- WebGLDevice = class extends import_core24.Device {
5965
+ WebGLDevice = class extends import_core28.Device {
5966
+ static getDeviceFromContext(gl) {
5967
+ if (!gl) {
5968
+ return null;
5969
+ }
5970
+ return gl.luma?.device ?? null;
5971
+ }
5329
5972
  // Public `Device` API
5330
5973
  /** type of this device */
5331
5974
  type = "webgl";
@@ -5347,7 +5990,7 @@ ${source}`;
5347
5990
  // @ts-ignore TODO fix
5348
5991
  _constants;
5349
5992
  /** State used by luma.gl classes - TODO - not used? */
5350
- _extensions = {};
5993
+ extensions;
5351
5994
  _polyfilled = false;
5352
5995
  /** Instance of Spector.js (if initialized) */
5353
5996
  spectorJS;
@@ -5370,11 +6013,12 @@ ${source}`;
5370
6013
  }
5371
6014
  constructor(props) {
5372
6015
  super({ ...props, id: props.id || uid("webgl-device") });
5373
- const canvasContextProps = import_core24.Device._getCanvasContextProps(props);
6016
+ const canvasContextProps = import_core28.Device._getCanvasContextProps(props);
5374
6017
  if (!canvasContextProps) {
5375
6018
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5376
6019
  }
5377
- let device = canvasContextProps.canvas?.gl?.device;
6020
+ const existingContext = canvasContextProps.canvas?.gl ?? null;
6021
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5378
6022
  if (device) {
5379
6023
  throw new Error(`WebGL context already attached to device ${device.id}`);
5380
6024
  }
@@ -5389,6 +6033,9 @@ ${source}`;
5389
6033
  if (props.powerPreference !== void 0) {
5390
6034
  webglContextAttributes.powerPreference = props.powerPreference;
5391
6035
  }
6036
+ if (props.failIfMajorPerformanceCaveat !== void 0) {
6037
+ webglContextAttributes.failIfMajorPerformanceCaveat = props.failIfMajorPerformanceCaveat;
6038
+ }
5392
6039
  const externalGLContext = this.props._handle;
5393
6040
  const gl = externalGLContext || createBrowserContext(this.canvasContext.canvas, {
5394
6041
  onContextLost: (event) => this._resolveContextLost?.({
@@ -5401,10 +6048,11 @@ ${source}`;
5401
6048
  if (!gl) {
5402
6049
  throw new Error("WebGL context creation failed");
5403
6050
  }
5404
- device = gl.device;
6051
+ device = WebGLDevice.getDeviceFromContext(gl);
5405
6052
  if (device) {
5406
6053
  if (props._reuseDevices) {
5407
- import_core24.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6054
+ import_core28.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6055
+ this.canvasContext.destroy();
5408
6056
  device._reused = true;
5409
6057
  return device;
5410
6058
  }
@@ -5413,28 +6061,28 @@ ${source}`;
5413
6061
  this.handle = gl;
5414
6062
  this.gl = gl;
5415
6063
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5416
- this.gl.device = this;
5417
- this.gl._version = 2;
5418
- this.info = getDeviceInfo(this.gl, this._extensions);
6064
+ const contextData = getWebGLContextData(this.handle);
6065
+ contextData.device = this;
6066
+ this.extensions = contextData.extensions || (contextData.extensions = {});
6067
+ this.info = getDeviceInfo(this.gl, this.extensions);
5419
6068
  this.limits = new WebGLDeviceLimits(this.gl);
5420
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
6069
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5421
6070
  if (this.props._initializeFeatures) {
5422
6071
  this.features.initializeFeatures();
5423
6072
  }
5424
6073
  const glState = new WebGLStateTracker(this.gl, {
5425
- log: (...args) => import_core24.log.log(1, ...args)()
6074
+ log: (...args) => import_core28.log.log(1, ...args)()
5426
6075
  });
5427
6076
  glState.trackState(this.gl, { copyState: false });
5428
- const debugWebGL = props.debugWebGL || props.debug;
5429
- const traceWebGL = props.debugWebGL;
5430
- if (debugWebGL) {
5431
- this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
5432
- import_core24.log.warn("WebGL debug mode activated. Performance reduced.")();
5433
- if (props.debugWebGL) {
5434
- import_core24.log.level = Math.max(import_core24.log.level, 1);
5435
- }
6077
+ if (props.debug || props.debugWebGL) {
6078
+ this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
6079
+ import_core28.log.warn("WebGL debug mode activated. Performance reduced.")();
6080
+ }
6081
+ if (props.debugWebGL) {
6082
+ import_core28.log.level = Math.max(import_core28.log.level, 1);
5436
6083
  }
5437
6084
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6085
+ this.canvasContext._startObservers();
5438
6086
  }
5439
6087
  /**
5440
6088
  * Destroys the device
@@ -5447,20 +6095,22 @@ ${source}`;
5447
6095
  * browser API for destroying WebGL contexts.
5448
6096
  */
5449
6097
  destroy() {
6098
+ this.commandEncoder?.destroy();
5450
6099
  if (!this.props._reuseDevices && !this._reused) {
5451
- delete this.gl.device;
6100
+ const contextData = getWebGLContextData(this.handle);
6101
+ contextData.device = null;
5452
6102
  }
5453
6103
  }
5454
6104
  get isLost() {
5455
6105
  return this.gl.isContextLost();
5456
6106
  }
5457
6107
  // IMPLEMENTATION OF ABSTRACT DEVICE
5458
- getTextureByteAlignment() {
5459
- return 4;
5460
- }
5461
6108
  createCanvasContext(props) {
5462
6109
  throw new Error("WebGL only supports a single canvas");
5463
6110
  }
6111
+ createPresentationContext(props) {
6112
+ return new WebGLPresentationContext(this, props || {});
6113
+ }
5464
6114
  createBuffer(props) {
5465
6115
  const newProps = this._normalizeBufferProps(props);
5466
6116
  return new WEBGLBuffer(this, newProps);
@@ -5489,9 +6139,15 @@ ${source}`;
5489
6139
  createQuerySet(props) {
5490
6140
  return new WEBGLQuerySet(this, props);
5491
6141
  }
6142
+ createFence() {
6143
+ return new WEBGLFence(this);
6144
+ }
5492
6145
  createRenderPipeline(props) {
5493
6146
  return new WEBGLRenderPipeline(this, props);
5494
6147
  }
6148
+ _createSharedRenderPipelineWebGL(props) {
6149
+ return new WEBGLSharedRenderPipeline(this, props);
6150
+ }
5495
6151
  createComputePipeline(props) {
5496
6152
  throw new Error("ComputePipeline not supported in WebGL");
5497
6153
  }
@@ -5504,12 +6160,27 @@ ${source}`;
5504
6160
  * Chrome's offscreen canvas does not require gl.commit
5505
6161
  */
5506
6162
  submit(commandBuffer) {
6163
+ let submittedCommandEncoder = null;
5507
6164
  if (!commandBuffer) {
5508
- commandBuffer = this.commandEncoder.finish();
6165
+ submittedCommandEncoder = this.commandEncoder;
6166
+ commandBuffer = submittedCommandEncoder.finish();
5509
6167
  this.commandEncoder.destroy();
5510
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
6168
+ this.commandEncoder = this.createCommandEncoder({
6169
+ id: submittedCommandEncoder.props.id,
6170
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
6171
+ });
6172
+ }
6173
+ try {
6174
+ commandBuffer._executeCommands();
6175
+ if (submittedCommandEncoder) {
6176
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
6177
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
6178
+ }).catch(() => {
6179
+ });
6180
+ }
6181
+ } finally {
6182
+ commandBuffer.destroy();
5511
6183
  }
5512
- commandBuffer._executeCommands();
5513
6184
  }
5514
6185
  //
5515
6186
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5532,11 +6203,11 @@ ${source}`;
5532
6203
  return withGLParameters(this.gl, parameters, func);
5533
6204
  }
5534
6205
  resetWebGL() {
5535
- import_core24.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6206
+ import_core28.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5536
6207
  resetGLParameters(this.gl);
5537
6208
  }
5538
6209
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5539
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
6210
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5540
6211
  }
5541
6212
  //
5542
6213
  // WebGL-only API (not part of `Device` API)
@@ -5604,7 +6275,7 @@ ${source}`;
5604
6275
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5605
6276
  const currentConstant = this._constants[location];
5606
6277
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5607
- import_core24.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
6278
+ import_core28.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
5608
6279
  }
5609
6280
  this._constants[location] = constant;
5610
6281
  switch (constant.constructor) {
@@ -5623,8 +6294,8 @@ ${source}`;
5623
6294
  }
5624
6295
  /** Ensure extensions are only requested once */
5625
6296
  getExtension(name) {
5626
- getWebGLExtension(this.gl, name, this._extensions);
5627
- return this._extensions;
6297
+ getWebGLExtension(this.gl, name, this.extensions);
6298
+ return this.extensions;
5628
6299
  }
5629
6300
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
5630
6301
  /**
@@ -5670,7 +6341,7 @@ ${source}`;
5670
6341
  init_dist3();
5671
6342
 
5672
6343
  // src/utils.ts
5673
- var import_core25 = __toESM(require_core(), 1);
6344
+ var import_core29 = __toESM(require_core(), 1);
5674
6345
 
5675
6346
  // ../../node_modules/@math.gl/core/dist/lib/common.js
5676
6347
  var RADIANS_TO_DEGREES = 1 / Math.PI * 180;
@@ -7612,13 +8283,13 @@ ${source}`;
7612
8283
  mousemove: null,
7613
8284
  mouseout: null
7614
8285
  };
7615
- const newDeck = new import_core25.Deck({
8286
+ const newDeck = new import_core29.Deck({
7616
8287
  ...props,
7617
8288
  // Default to true for high-DPI displays, but allow user override
7618
8289
  useDevicePixels: props.useDevicePixels ?? true,
7619
8290
  style: props.interleaved ? null : { pointerEvents: "none" },
7620
8291
  parent: getContainer(overlay, props.style),
7621
- views: new import_core25.MapView({ repeat: true }),
8292
+ views: new import_core29.MapView({ repeat: true }),
7622
8293
  initialViewState: {
7623
8294
  longitude: 0,
7624
8295
  latitude: 0,