@deck.gl/arcgis 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
@@ -724,6 +724,23 @@ var __exports__ = (() => {
724
724
  }
725
725
  });
726
726
 
727
+ // ../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js
728
+ function getWebGLContextData(gl) {
729
+ const contextData = gl.luma || {
730
+ _polyfilled: false,
731
+ extensions: {},
732
+ softwareRenderer: false
733
+ };
734
+ contextData._polyfilled ??= false;
735
+ contextData.extensions ||= {};
736
+ gl.luma = contextData;
737
+ return contextData;
738
+ }
739
+ var init_webgl_context_data = __esm({
740
+ "../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js"() {
741
+ }
742
+ });
743
+
727
744
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js
728
745
  function initializeSpectorJS(props) {
729
746
  props = { ...DEFAULT_SPECTOR_PROPS, ...props };
@@ -754,9 +771,10 @@ var __exports__ = (() => {
754
771
  }
755
772
  if (props.gl) {
756
773
  const gl = props.gl;
757
- const device = gl.device;
774
+ const contextData = getWebGLContextData(gl);
775
+ const device = contextData.device;
758
776
  spector?.startCapture(props.gl, 500);
759
- gl.device = device;
777
+ contextData.device = device;
760
778
  new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
761
779
  import_core2.log.info("Spector capture stopped after 2 seconds")();
762
780
  spector?.stopCapture();
@@ -768,6 +786,7 @@ var __exports__ = (() => {
768
786
  var init_spector = __esm({
769
787
  "../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js"() {
770
788
  import_core2 = __toESM(require_core2(), 1);
789
+ init_webgl_context_data();
771
790
  LOG_LEVEL = 1;
772
791
  spector = null;
773
792
  initialized = false;
@@ -863,7 +882,7 @@ var __exports__ = (() => {
863
882
  });
864
883
 
865
884
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/webgl-developer-tools.js
866
- function getWebGLContextData(gl) {
885
+ function getWebGLContextData2(gl) {
867
886
  gl.luma = gl.luma || {};
868
887
  return gl.luma;
869
888
  }
@@ -871,7 +890,7 @@ var __exports__ = (() => {
871
890
  return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
872
891
  }
873
892
  function getRealContext(gl) {
874
- const data = getWebGLContextData(gl);
893
+ const data = getWebGLContextData2(gl);
875
894
  return data.realContext ? data.realContext : gl;
876
895
  }
877
896
  function getDebugContext(gl, props) {
@@ -879,7 +898,7 @@ var __exports__ = (() => {
879
898
  import_core3.log.warn("webgl-debug not loaded")();
880
899
  return gl;
881
900
  }
882
- const data = getWebGLContextData(gl);
901
+ const data = getWebGLContextData2(gl);
883
902
  if (data.debugContext) {
884
903
  return data.debugContext;
885
904
  }
@@ -897,6 +916,7 @@ var __exports__ = (() => {
897
916
  const debugContext = Object.create(WebGLDebugContext);
898
917
  data.realContext = gl;
899
918
  data.debugContext = debugContext;
919
+ debugContext.luma = data;
900
920
  debugContext.debug = true;
901
921
  return debugContext;
902
922
  }
@@ -911,16 +931,15 @@ var __exports__ = (() => {
911
931
  const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
912
932
  const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
913
933
  const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
914
- import_core3.log.error(message2)();
934
+ import_core3.log.error("%cWebGL", "color: white; background: red; padding: 2px 6px; border-radius: 3px;", message2)();
915
935
  debugger;
936
+ throw new Error(message2);
916
937
  }
917
938
  function onValidateGLFunc(props, functionName, functionArgs) {
918
939
  let functionString = "";
919
- if (import_core3.log.level >= 1) {
940
+ if (props.traceWebGL && import_core3.log.level >= 1) {
920
941
  functionString = getFunctionString(functionName, functionArgs);
921
- if (props.traceWebGL) {
922
- import_core3.log.log(1, functionString)();
923
- }
942
+ import_core3.log.info(1, "%cWebGL", "color: white; background: blue; padding: 2px 6px; border-radius: 3px;", functionString)();
924
943
  }
925
944
  for (const arg of functionArgs) {
926
945
  if (arg === void 0) {
@@ -1428,7 +1447,7 @@ var __exports__ = (() => {
1428
1447
  }
1429
1448
  }
1430
1449
  }
1431
- const cache = gl.state && gl.state.cache;
1450
+ const cache = gl.lumaState?.cache;
1432
1451
  if (cache) {
1433
1452
  for (const key in compositeSetters) {
1434
1453
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -1548,7 +1567,7 @@ var __exports__ = (() => {
1548
1567
  init_webgl_parameter_tables();
1549
1568
  WebGLStateTracker = class {
1550
1569
  static get(gl) {
1551
- return gl.state;
1570
+ return gl.lumaState;
1552
1571
  }
1553
1572
  gl;
1554
1573
  program = null;
@@ -1586,7 +1605,7 @@ var __exports__ = (() => {
1586
1605
  throw new Error("WebGLStateTracker");
1587
1606
  }
1588
1607
  this.initialized = true;
1589
- this.gl.state = this;
1608
+ this.gl.lumaState = this;
1590
1609
  installProgramSpy(gl);
1591
1610
  for (const key in GL_HOOKED_SETTERS) {
1592
1611
  const setter = GL_HOOKED_SETTERS[key];
@@ -1626,41 +1645,56 @@ var __exports__ = (() => {
1626
1645
  // ../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js
1627
1646
  function createBrowserContext(canvas, props, webglContextAttributes) {
1628
1647
  let errorMessage = "";
1648
+ const onCreateError = (event) => {
1649
+ const statusMessage = event.statusMessage;
1650
+ if (statusMessage) {
1651
+ errorMessage ||= statusMessage;
1652
+ }
1653
+ };
1654
+ canvas.addEventListener("webglcontextcreationerror", onCreateError, false);
1655
+ const allowSoftwareRenderer = webglContextAttributes.failIfMajorPerformanceCaveat !== true;
1629
1656
  const webglProps = {
1630
1657
  preserveDrawingBuffer: true,
1631
- // failIfMajorPerformanceCaveat: true,
1632
- ...webglContextAttributes
1658
+ ...webglContextAttributes,
1659
+ // Always start by requesting a high-performance context.
1660
+ failIfMajorPerformanceCaveat: true
1633
1661
  };
1634
1662
  let gl = null;
1635
- gl ||= canvas.getContext("webgl2", webglProps);
1636
- if (webglProps.failIfMajorPerformanceCaveat) {
1637
- errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1638
- }
1639
- if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
1640
- webglProps.failIfMajorPerformanceCaveat = false;
1641
- gl = canvas.getContext("webgl2", webglProps);
1642
- gl.luma ||= {};
1643
- gl.luma.softwareRenderer = true;
1644
- }
1645
- if (!gl) {
1646
- gl = canvas.getContext("webgl", {});
1647
- if (gl) {
1648
- gl = null;
1649
- errorMessage ||= "Your browser only supports WebGL1";
1663
+ try {
1664
+ gl ||= canvas.getContext("webgl2", webglProps);
1665
+ if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1666
+ errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1650
1667
  }
1668
+ let softwareRenderer = false;
1669
+ if (!gl && allowSoftwareRenderer) {
1670
+ webglProps.failIfMajorPerformanceCaveat = false;
1671
+ gl = canvas.getContext("webgl2", webglProps);
1672
+ softwareRenderer = true;
1673
+ }
1674
+ if (!gl) {
1675
+ gl = canvas.getContext("webgl", {});
1676
+ if (gl) {
1677
+ gl = null;
1678
+ errorMessage ||= "Your browser only supports WebGL1";
1679
+ }
1680
+ }
1681
+ if (!gl) {
1682
+ errorMessage ||= "Your browser does not support WebGL";
1683
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1684
+ }
1685
+ const luma = getWebGLContextData(gl);
1686
+ luma.softwareRenderer = softwareRenderer;
1687
+ const { onContextLost, onContextRestored } = props;
1688
+ canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1689
+ canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1690
+ return gl;
1691
+ } finally {
1692
+ canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
1651
1693
  }
1652
- if (!gl) {
1653
- errorMessage ||= "Your browser does not support WebGL";
1654
- throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1655
- }
1656
- const { onContextLost, onContextRestored } = props;
1657
- canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1658
- canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1659
- gl.luma ||= {};
1660
- return gl;
1661
1694
  }
1662
1695
  var init_create_browser_context = __esm({
1663
1696
  "../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js"() {
1697
+ init_webgl_context_data();
1664
1698
  }
1665
1699
  });
1666
1700
 
@@ -1737,6 +1771,8 @@ var __exports__ = (() => {
1737
1771
  }
1738
1772
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1739
1773
  switch (gpuVendor) {
1774
+ case "apple":
1775
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1740
1776
  case "intel":
1741
1777
  return "integrated";
1742
1778
  case "software":
@@ -1747,6 +1783,9 @@ var __exports__ = (() => {
1747
1783
  return "discrete";
1748
1784
  }
1749
1785
  }
1786
+ function isAppleSiliconGPU(vendor, renderer) {
1787
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1788
+ }
1750
1789
  var init_webgl_device_info = __esm({
1751
1790
  "../../node_modules/@luma.gl/webgl/dist/adapter/device-helpers/webgl-device-info.js"() {
1752
1791
  init_webgl_extensions();
@@ -1793,8 +1832,23 @@ var __exports__ = (() => {
1793
1832
  return feature in TEXTURE_FEATURES;
1794
1833
  }
1795
1834
  function checkTextureFeature(gl, feature, extensions) {
1796
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1797
- return textureExtensions.every((extension) => getWebGLExtension(gl, extension, extensions));
1835
+ return hasTextureFeature(gl, feature, extensions, /* @__PURE__ */ new Set());
1836
+ }
1837
+ function hasTextureFeature(gl, feature, extensions, seenFeatures) {
1838
+ const definition = TEXTURE_FEATURES[feature];
1839
+ if (!definition) {
1840
+ return false;
1841
+ }
1842
+ if (seenFeatures.has(feature)) {
1843
+ return false;
1844
+ }
1845
+ seenFeatures.add(feature);
1846
+ const hasDependentFeatures = (definition.features || []).every((dependentFeature) => hasTextureFeature(gl, dependentFeature, extensions, seenFeatures));
1847
+ seenFeatures.delete(feature);
1848
+ if (!hasDependentFeatures) {
1849
+ return false;
1850
+ }
1851
+ return (definition.extensions || []).every((extension) => Boolean(getWebGLExtension(gl, extension, extensions)));
1798
1852
  }
1799
1853
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1800
1854
  let supported = formatSupport.create;
@@ -1805,12 +1859,17 @@ var __exports__ = (() => {
1805
1859
  if (webglFormatInfo?.x) {
1806
1860
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1807
1861
  }
1862
+ if (formatSupport.format === "stencil8") {
1863
+ supported = false;
1864
+ }
1865
+ const renderFeatureSupported = webglFormatInfo?.r === false ? false : webglFormatInfo?.r === void 0 || checkTextureFeature(gl, webglFormatInfo.r, extensions);
1866
+ const renderable = supported && formatSupport.render && renderFeatureSupported && isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
1808
1867
  return {
1809
1868
  format: formatSupport.format,
1810
1869
  // @ts-ignore
1811
1870
  create: supported && formatSupport.create,
1812
1871
  // @ts-ignore
1813
- render: supported && formatSupport.render,
1872
+ render: renderable,
1814
1873
  // @ts-ignore
1815
1874
  filter: supported && formatSupport.filter,
1816
1875
  // @ts-ignore
@@ -1819,6 +1878,45 @@ var __exports__ = (() => {
1819
1878
  store: supported && formatSupport.store
1820
1879
  };
1821
1880
  }
1881
+ function isColorRenderableTextureFormat(gl, format, extensions) {
1882
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
1883
+ const internalFormat = webglFormatInfo?.gl;
1884
+ if (internalFormat === void 0) {
1885
+ return false;
1886
+ }
1887
+ if (webglFormatInfo?.x && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
1888
+ return false;
1889
+ }
1890
+ const previousTexture = gl.getParameter(32873);
1891
+ const previousFramebuffer = gl.getParameter(36006);
1892
+ const texture = gl.createTexture();
1893
+ const framebuffer = gl.createFramebuffer();
1894
+ if (!texture || !framebuffer) {
1895
+ return false;
1896
+ }
1897
+ const noError = Number(0);
1898
+ let error = Number(gl.getError());
1899
+ while (error !== noError) {
1900
+ error = gl.getError();
1901
+ }
1902
+ let renderable = false;
1903
+ try {
1904
+ gl.bindTexture(3553, texture);
1905
+ gl.texStorage2D(3553, 1, internalFormat, 1, 1);
1906
+ if (Number(gl.getError()) !== noError) {
1907
+ return false;
1908
+ }
1909
+ gl.bindFramebuffer(36160, framebuffer);
1910
+ gl.framebufferTexture2D(36160, 36064, 3553, texture, 0);
1911
+ renderable = Number(gl.checkFramebufferStatus(36160)) === Number(36053) && Number(gl.getError()) === noError;
1912
+ } finally {
1913
+ gl.bindFramebuffer(36160, previousFramebuffer);
1914
+ gl.deleteFramebuffer(framebuffer);
1915
+ gl.bindTexture(3553, previousTexture);
1916
+ gl.deleteTexture(texture);
1917
+ }
1918
+ return renderable;
1919
+ }
1822
1920
  function getTextureFormatWebGL(format) {
1823
1921
  const formatData = WEBGL_TEXTURE_FORMATS[format];
1824
1922
  const webglFormat = convertTextureFormatToGL(format);
@@ -1874,7 +1972,7 @@ var __exports__ = (() => {
1874
1972
  }
1875
1973
  return webglFormat;
1876
1974
  }
1877
- 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;
1975
+ 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;
1878
1976
  var init_webgl_texture_table = __esm({
1879
1977
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-texture-table.js"() {
1880
1978
  import_core4 = __toESM(require_core2(), 1);
@@ -1892,44 +1990,51 @@ var __exports__ = (() => {
1892
1990
  EXT_texture_norm16 = "EXT_texture_norm16";
1893
1991
  EXT_render_snorm = "EXT_render_snorm";
1894
1992
  EXT_color_buffer_float = "EXT_color_buffer_float";
1993
+ SNORM8_COLOR_RENDERABLE = "snorm8-renderable-webgl";
1994
+ NORM16_COLOR_RENDERABLE = "norm16-renderable-webgl";
1995
+ SNORM16_COLOR_RENDERABLE = "snorm16-renderable-webgl";
1996
+ FLOAT16_COLOR_RENDERABLE = "float16-renderable-webgl";
1997
+ FLOAT32_COLOR_RENDERABLE = "float32-renderable-webgl";
1998
+ RGB9E5UFLOAT_COLOR_RENDERABLE = "rgb9e5ufloat-renderable-webgl";
1895
1999
  TEXTURE_FEATURES = {
1896
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1897
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1898
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1899
- "snorm8-renderable-webgl": [EXT_render_snorm],
1900
- "norm16-renderable-webgl": [EXT_texture_norm16],
1901
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1902
- "float32-filterable": ["OES_texture_float_linear"],
1903
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1904
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1905
- "texture-blend-float-webgl": ["EXT_float_blend"],
1906
- "texture-compression-bc": [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
2000
+ "float32-renderable-webgl": { extensions: [EXT_color_buffer_float] },
2001
+ "float16-renderable-webgl": { extensions: ["EXT_color_buffer_half_float"] },
2002
+ "rgb9e5ufloat-renderable-webgl": { extensions: ["WEBGL_render_shared_exponent"] },
2003
+ "snorm8-renderable-webgl": { extensions: [EXT_render_snorm] },
2004
+ "norm16-webgl": { extensions: [EXT_texture_norm16] },
2005
+ "norm16-renderable-webgl": { features: ["norm16-webgl"] },
2006
+ "snorm16-renderable-webgl": { features: ["norm16-webgl"], extensions: [EXT_render_snorm] },
2007
+ "float32-filterable": { extensions: ["OES_texture_float_linear"] },
2008
+ "float16-filterable-webgl": { extensions: ["OES_texture_half_float_linear"] },
2009
+ "texture-filterable-anisotropic-webgl": { extensions: ["EXT_texture_filter_anisotropic"] },
2010
+ "texture-blend-float-webgl": { extensions: ["EXT_float_blend"] },
2011
+ "texture-compression-bc": { extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC] },
1907
2012
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1908
2013
  // 'texture-compression-bc3-webgl': [X_S3TC],
1909
- "texture-compression-bc5-webgl": [X_RGTC],
1910
- "texture-compression-bc7-webgl": [X_BPTC],
1911
- "texture-compression-etc2": [X_ETC2],
1912
- "texture-compression-astc": [X_ASTC],
1913
- "texture-compression-etc1-webgl": [X_ETC1],
1914
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1915
- "texture-compression-atc-webgl": [X_ATC]
2014
+ "texture-compression-bc5-webgl": { extensions: [X_RGTC] },
2015
+ "texture-compression-bc7-webgl": { extensions: [X_BPTC] },
2016
+ "texture-compression-etc2": { extensions: [X_ETC2] },
2017
+ "texture-compression-astc": { extensions: [X_ASTC] },
2018
+ "texture-compression-etc1-webgl": { extensions: [X_ETC1] },
2019
+ "texture-compression-pvrtc-webgl": { extensions: [X_PVRTC] },
2020
+ "texture-compression-atc-webgl": { extensions: [X_ATC] }
1916
2021
  };
1917
2022
  WEBGL_TEXTURE_FORMATS = {
1918
2023
  // 8-bit formats
1919
2024
  "r8unorm": { gl: 33321, rb: true },
1920
- "r8snorm": { gl: 36756 },
2025
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1921
2026
  "r8uint": { gl: 33330, rb: true },
1922
2027
  "r8sint": { gl: 33329, rb: true },
1923
2028
  // 16-bit formats
1924
2029
  "rg8unorm": { gl: 33323, rb: true },
1925
- "rg8snorm": { gl: 36757 },
2030
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1926
2031
  "rg8uint": { gl: 33336, rb: true },
1927
2032
  "rg8sint": { gl: 33335, rb: true },
1928
2033
  "r16uint": { gl: 33332, rb: true },
1929
2034
  "r16sint": { gl: 33331, rb: true },
1930
- "r16float": { gl: 33325, rb: true },
1931
- "r16unorm": { gl: 33322, rb: true },
1932
- "r16snorm": { gl: 36760 },
2035
+ "r16float": { gl: 33325, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2036
+ "r16unorm": { gl: 33322, rb: true, r: NORM16_COLOR_RENDERABLE },
2037
+ "r16snorm": { gl: 36760, r: SNORM16_COLOR_RENDERABLE },
1933
2038
  // Packed 16-bit formats
1934
2039
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1935
2040
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1940,7 +2045,7 @@ var __exports__ = (() => {
1940
2045
  // 32-bit formats
1941
2046
  "rgba8unorm": { gl: 32856 },
1942
2047
  "rgba8unorm-srgb": { gl: 35907 },
1943
- "rgba8snorm": { gl: 36759 },
2048
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1944
2049
  "rgba8uint": { gl: 36220 },
1945
2050
  "rgba8sint": { gl: 36238 },
1946
2051
  // reverse colors, webgpu only
@@ -1948,38 +2053,38 @@ var __exports__ = (() => {
1948
2053
  "bgra8unorm-srgb": {},
1949
2054
  "rg16uint": { gl: 33338 },
1950
2055
  "rg16sint": { gl: 33337 },
1951
- "rg16float": { gl: 33327, rb: true },
1952
- "rg16unorm": { gl: 33324 },
1953
- "rg16snorm": { gl: 36761 },
2056
+ "rg16float": { gl: 33327, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2057
+ "rg16unorm": { gl: 33324, r: NORM16_COLOR_RENDERABLE },
2058
+ "rg16snorm": { gl: 36761, r: SNORM16_COLOR_RENDERABLE },
1954
2059
  "r32uint": { gl: 33334, rb: true },
1955
2060
  "r32sint": { gl: 33333, rb: true },
1956
- "r32float": { gl: 33326 },
2061
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1957
2062
  // Packed 32-bit formats
1958
- "rgb9e5ufloat": { gl: 35901 },
2063
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1959
2064
  // , filter: true},
1960
2065
  "rg11b10ufloat": { gl: 35898, rb: true },
1961
2066
  "rgb10a2unorm": { gl: 32857, rb: true },
1962
2067
  "rgb10a2uint": { gl: 36975, rb: true },
1963
2068
  // 48-bit formats
1964
- "rgb16unorm-webgl": { gl: 32852 },
2069
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1965
2070
  // rgb not renderable
1966
- "rgb16snorm-webgl": { gl: 36762 },
2071
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1967
2072
  // rgb not renderable
1968
2073
  // 64-bit formats
1969
2074
  "rg32uint": { gl: 33340, rb: true },
1970
2075
  "rg32sint": { gl: 33339, rb: true },
1971
- "rg32float": { gl: 33328, rb: true },
2076
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1972
2077
  "rgba16uint": { gl: 36214, rb: true },
1973
2078
  "rgba16sint": { gl: 36232, rb: true },
1974
- "rgba16float": { gl: 34842 },
1975
- "rgba16unorm": { gl: 32859, rb: true },
1976
- "rgba16snorm": { gl: 36763 },
2079
+ "rgba16float": { gl: 34842, r: FLOAT16_COLOR_RENDERABLE },
2080
+ "rgba16unorm": { gl: 32859, rb: true, r: NORM16_COLOR_RENDERABLE },
2081
+ "rgba16snorm": { gl: 36763, r: SNORM16_COLOR_RENDERABLE },
1977
2082
  // 96-bit formats (deprecated!)
1978
- "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, dataFormat: 6407, types: [5126] },
2083
+ "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: 6407, types: [5126] },
1979
2084
  // 128-bit formats
1980
2085
  "rgba32uint": { gl: 36208, rb: true },
1981
2086
  "rgba32sint": { gl: 36226, rb: true },
1982
- "rgba32float": { gl: 34836, rb: true },
2087
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1983
2088
  // Depth and stencil formats
1984
2089
  "stencil8": { gl: 36168, rb: true },
1985
2090
  // 8 stencil bits
@@ -2037,8 +2142,8 @@ var __exports__ = (() => {
2037
2142
  "astc-8x6-unorm-srgb": { gl: 37846 },
2038
2143
  "astc-8x8-unorm": { gl: 37815 },
2039
2144
  "astc-8x8-unorm-srgb": { gl: 37847 },
2040
- "astc-10x5-unorm": { gl: 37819 },
2041
- "astc-10x5-unorm-srgb": { gl: 37851 },
2145
+ "astc-10x5-unorm": { gl: 37816 },
2146
+ "astc-10x5-unorm-srgb": { gl: 37848 },
2042
2147
  "astc-10x6-unorm": { gl: 37817 },
2043
2148
  "astc-10x6-unorm-srgb": { gl: 37849 },
2044
2149
  "astc-10x8-unorm": { gl: 37818 },
@@ -2052,7 +2157,7 @@ var __exports__ = (() => {
2052
2157
  // WEBGL_compressed_texture_pvrtc
2053
2158
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
2054
2159
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
2055
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
2160
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
2056
2161
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
2057
2162
  // WEBGL_compressed_texture_etc1
2058
2163
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -2075,12 +2180,11 @@ var __exports__ = (() => {
2075
2180
  // optional WebGPU features
2076
2181
  "depth-clip-control": "EXT_depth_clamp",
2077
2182
  // TODO these seem subtly different
2078
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2183
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2079
2184
  // "indirect-first-instance"
2080
2185
  // Textures are handled by getTextureFeatures()
2081
2186
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2082
2187
  // optional WebGL features
2083
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2084
2188
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2085
2189
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2086
2190
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2394,14 +2498,78 @@ var __exports__ = (() => {
2394
2498
  super(props);
2395
2499
  this.device = device;
2396
2500
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
2397
- this._updateDevice();
2501
+ this._configureDevice();
2398
2502
  }
2399
- getCurrentFramebuffer() {
2400
- this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
2503
+ // IMPLEMENTATION OF ABSTRACT METHODS
2504
+ _configureDevice() {
2505
+ const shouldResize = this.drawingBufferWidth !== this._framebuffer?.width || this.drawingBufferHeight !== this._framebuffer?.height;
2506
+ if (shouldResize) {
2507
+ this._framebuffer?.resize([this.drawingBufferWidth, this.drawingBufferHeight]);
2508
+ }
2509
+ }
2510
+ _getCurrentFramebuffer() {
2511
+ this._framebuffer ||= new WEBGLFramebuffer(this.device, {
2512
+ id: "canvas-context-framebuffer",
2513
+ handle: null,
2514
+ // Setting handle to null returns a reference to the default WebGL framebuffer
2515
+ width: this.drawingBufferWidth,
2516
+ height: this.drawingBufferHeight
2517
+ });
2401
2518
  return this._framebuffer;
2402
2519
  }
2403
- // IMPLEMENTATION OF ABSTRACT METHODS
2404
- _updateDevice() {
2520
+ };
2521
+ }
2522
+ });
2523
+
2524
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js
2525
+ var import_core9, WebGLPresentationContext;
2526
+ var init_webgl_presentation_context = __esm({
2527
+ "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js"() {
2528
+ import_core9 = __toESM(require_core2(), 1);
2529
+ WebGLPresentationContext = class extends import_core9.PresentationContext {
2530
+ device;
2531
+ handle = null;
2532
+ context2d;
2533
+ get [Symbol.toStringTag]() {
2534
+ return "WebGLPresentationContext";
2535
+ }
2536
+ constructor(device, props = {}) {
2537
+ super(props);
2538
+ this.device = device;
2539
+ const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
2540
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2541
+ if (!defaultCanvasContext.offscreenCanvas) {
2542
+ throw new Error(`${contextLabel}: WebGL PresentationContext requires the default CanvasContext canvas to be an OffscreenCanvas`);
2543
+ }
2544
+ const context2d = this.canvas.getContext("2d");
2545
+ if (!context2d) {
2546
+ throw new Error(`${contextLabel}: Failed to create 2d presentation context`);
2547
+ }
2548
+ this.context2d = context2d;
2549
+ this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
2550
+ this._configureDevice();
2551
+ this._startObservers();
2552
+ }
2553
+ present() {
2554
+ this._resizeDrawingBufferIfNeeded();
2555
+ this.device.submit();
2556
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2557
+ const [sourceWidth, sourceHeight] = defaultCanvasContext.getDrawingBufferSize();
2558
+ if (this.drawingBufferWidth === 0 || this.drawingBufferHeight === 0 || sourceWidth === 0 || sourceHeight === 0 || defaultCanvasContext.canvas.width === 0 || defaultCanvasContext.canvas.height === 0) {
2559
+ return;
2560
+ }
2561
+ if (sourceWidth !== this.drawingBufferWidth || sourceHeight !== this.drawingBufferHeight || defaultCanvasContext.canvas.width !== this.drawingBufferWidth || defaultCanvasContext.canvas.height !== this.drawingBufferHeight) {
2562
+ 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}`);
2563
+ }
2564
+ this.context2d.clearRect(0, 0, this.drawingBufferWidth, this.drawingBufferHeight);
2565
+ this.context2d.drawImage(defaultCanvasContext.canvas, 0, 0);
2566
+ }
2567
+ _configureDevice() {
2568
+ }
2569
+ _getCurrentFramebuffer(options) {
2570
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2571
+ defaultCanvasContext.setDrawingBufferSize(this.drawingBufferWidth, this.drawingBufferHeight);
2572
+ return defaultCanvasContext.getCurrentFramebuffer(options);
2405
2573
  }
2406
2574
  };
2407
2575
  }
@@ -2422,34 +2590,34 @@ var __exports__ = (() => {
2422
2590
 
2423
2591
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js
2424
2592
  function getWebGLTarget(usage) {
2425
- if (usage & import_core9.Buffer.INDEX) {
2593
+ if (usage & import_core10.Buffer.INDEX) {
2426
2594
  return 34963;
2427
2595
  }
2428
- if (usage & import_core9.Buffer.VERTEX) {
2596
+ if (usage & import_core10.Buffer.VERTEX) {
2429
2597
  return 34962;
2430
2598
  }
2431
- if (usage & import_core9.Buffer.UNIFORM) {
2599
+ if (usage & import_core10.Buffer.UNIFORM) {
2432
2600
  return 35345;
2433
2601
  }
2434
2602
  return 34962;
2435
2603
  }
2436
2604
  function getWebGLUsage(usage) {
2437
- if (usage & import_core9.Buffer.INDEX) {
2605
+ if (usage & import_core10.Buffer.INDEX) {
2438
2606
  return 35044;
2439
2607
  }
2440
- if (usage & import_core9.Buffer.VERTEX) {
2608
+ if (usage & import_core10.Buffer.VERTEX) {
2441
2609
  return 35044;
2442
2610
  }
2443
- if (usage & import_core9.Buffer.UNIFORM) {
2611
+ if (usage & import_core10.Buffer.UNIFORM) {
2444
2612
  return 35048;
2445
2613
  }
2446
2614
  return 35044;
2447
2615
  }
2448
- var import_core9, WEBGLBuffer;
2616
+ var import_core10, WEBGLBuffer;
2449
2617
  var init_webgl_buffer = __esm({
2450
2618
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js"() {
2451
- import_core9 = __toESM(require_core2(), 1);
2452
- WEBGLBuffer = class extends import_core9.Buffer {
2619
+ import_core10 = __toESM(require_core2(), 1);
2620
+ WEBGLBuffer = class extends import_core10.Buffer {
2453
2621
  device;
2454
2622
  gl;
2455
2623
  handle;
@@ -2484,8 +2652,12 @@ var __exports__ = (() => {
2484
2652
  destroy() {
2485
2653
  if (!this.destroyed && this.handle) {
2486
2654
  this.removeStats();
2487
- this.trackDeallocatedMemory();
2488
- this.gl.deleteBuffer(this.handle);
2655
+ if (!this.props.handle) {
2656
+ this.trackDeallocatedMemory();
2657
+ this.gl.deleteBuffer(this.handle);
2658
+ } else {
2659
+ this.trackDeallocatedReferencedMemory("Buffer");
2660
+ }
2489
2661
  this.destroyed = true;
2490
2662
  this.handle = null;
2491
2663
  }
@@ -2500,7 +2672,11 @@ var __exports__ = (() => {
2500
2672
  this.bytesUsed = byteLength;
2501
2673
  this.byteLength = byteLength;
2502
2674
  this._setDebugData(data, byteOffset, byteLength);
2503
- this.trackAllocatedMemory(byteLength);
2675
+ if (!this.props.handle) {
2676
+ this.trackAllocatedMemory(byteLength);
2677
+ } else {
2678
+ this.trackReferencedMemory(byteLength, "Buffer");
2679
+ }
2504
2680
  }
2505
2681
  // Allocate a GPU buffer of specified size.
2506
2682
  _initWithByteLength(byteLength) {
@@ -2515,7 +2691,11 @@ var __exports__ = (() => {
2515
2691
  this.bytesUsed = byteLength;
2516
2692
  this.byteLength = byteLength;
2517
2693
  this._setDebugData(null, 0, byteLength);
2518
- this.trackAllocatedMemory(byteLength);
2694
+ if (!this.props.handle) {
2695
+ this.trackAllocatedMemory(byteLength);
2696
+ } else {
2697
+ this.trackReferencedMemory(byteLength, "Buffer");
2698
+ }
2519
2699
  return this;
2520
2700
  }
2521
2701
  write(data, byteOffset = 0) {
@@ -2566,9 +2746,20 @@ var __exports__ = (() => {
2566
2746
  if (line.length <= 1) {
2567
2747
  continue;
2568
2748
  }
2749
+ const lineWithTrimmedWhitespace = line.trim();
2569
2750
  const segments = line.split(":");
2751
+ const trimmedMessageType = segments[0]?.trim();
2570
2752
  if (segments.length === 2) {
2571
2753
  const [messageType2, message2] = segments;
2754
+ if (!messageType2 || !message2) {
2755
+ messages.push({
2756
+ message: lineWithTrimmedWhitespace,
2757
+ type: getMessageType(trimmedMessageType || "info"),
2758
+ lineNum: 0,
2759
+ linePos: 0
2760
+ });
2761
+ continue;
2762
+ }
2572
2763
  messages.push({
2573
2764
  message: message2.trim(),
2574
2765
  type: getMessageType(messageType2),
@@ -2578,6 +2769,15 @@ var __exports__ = (() => {
2578
2769
  continue;
2579
2770
  }
2580
2771
  const [messageType, linePosition, lineNumber, ...rest] = segments;
2772
+ if (!messageType || !linePosition || !lineNumber) {
2773
+ messages.push({
2774
+ message: segments.slice(1).join(":").trim() || lineWithTrimmedWhitespace,
2775
+ type: getMessageType(trimmedMessageType || "info"),
2776
+ lineNum: 0,
2777
+ linePos: 0
2778
+ });
2779
+ continue;
2780
+ }
2581
2781
  let lineNum = parseInt(lineNumber, 10);
2582
2782
  if (isNaN(lineNum)) {
2583
2783
  lineNum = 0;
@@ -2607,12 +2807,12 @@ var __exports__ = (() => {
2607
2807
  });
2608
2808
 
2609
2809
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js
2610
- var import_core10, WEBGLShader;
2810
+ var import_core11, WEBGLShader;
2611
2811
  var init_webgl_shader = __esm({
2612
2812
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js"() {
2613
- import_core10 = __toESM(require_core2(), 1);
2813
+ import_core11 = __toESM(require_core2(), 1);
2614
2814
  init_parse_shader_compiler_log();
2615
- WEBGLShader = class extends import_core10.Shader {
2815
+ WEBGLShader = class extends import_core11.Shader {
2616
2816
  device;
2617
2817
  handle;
2618
2818
  constructor(device, props) {
@@ -2678,9 +2878,9 @@ ${source}`;
2678
2878
  }
2679
2879
  return;
2680
2880
  }
2681
- import_core10.log.once(1, "Shader compilation is asynchronous")();
2881
+ import_core11.log.once(1, "Shader compilation is asynchronous")();
2682
2882
  await this._waitForCompilationComplete();
2683
- import_core10.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2883
+ import_core11.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2684
2884
  this._getCompilationStatus();
2685
2885
  this.debugShader();
2686
2886
  }
@@ -2828,7 +3028,7 @@ ${source}`;
2828
3028
  gl.stencilMaskSeparate(1029, mask);
2829
3029
  }
2830
3030
  if (parameters.stencilReadMask) {
2831
- import_core11.log.warn("stencilReadMask not supported under WebGL");
3031
+ import_core12.log.warn("stencilReadMask not supported under WebGL");
2832
3032
  }
2833
3033
  if (parameters.stencilCompare) {
2834
3034
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2941,10 +3141,10 @@ ${source}`;
2941
3141
  }
2942
3142
  return isEmpty;
2943
3143
  }
2944
- var import_core11;
3144
+ var import_core12;
2945
3145
  var init_device_parameters = __esm({
2946
3146
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/device-parameters.js"() {
2947
- import_core11 = __toESM(require_core2(), 1);
3147
+ import_core12 = __toESM(require_core2(), 1);
2948
3148
  init_unified_parameter_api();
2949
3149
  }
2950
3150
  });
@@ -3033,12 +3233,12 @@ ${source}`;
3033
3233
  });
3034
3234
 
3035
3235
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js
3036
- var import_core12, WEBGLSampler;
3236
+ var import_core13, WEBGLSampler;
3037
3237
  var init_webgl_sampler = __esm({
3038
3238
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js"() {
3039
- import_core12 = __toESM(require_core2(), 1);
3239
+ import_core13 = __toESM(require_core2(), 1);
3040
3240
  init_sampler_parameters();
3041
- WEBGLSampler = class extends import_core12.Sampler {
3241
+ WEBGLSampler = class extends import_core13.Sampler {
3042
3242
  device;
3043
3243
  handle;
3044
3244
  parameters;
@@ -3113,18 +3313,18 @@ ${source}`;
3113
3313
  });
3114
3314
 
3115
3315
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js
3116
- var import_core13, WEBGLTextureView;
3316
+ var import_core14, WEBGLTextureView;
3117
3317
  var init_webgl_texture_view = __esm({
3118
3318
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js"() {
3119
- import_core13 = __toESM(require_core2(), 1);
3120
- WEBGLTextureView = class extends import_core13.TextureView {
3319
+ import_core14 = __toESM(require_core2(), 1);
3320
+ WEBGLTextureView = class extends import_core14.TextureView {
3121
3321
  device;
3122
3322
  gl;
3123
3323
  handle;
3124
3324
  // Does not have a WebGL representation
3125
3325
  texture;
3126
3326
  constructor(device, props) {
3127
- super(device, { ...import_core13.Texture.defaultProps, ...props });
3327
+ super(device, { ...import_core14.Texture.defaultProps, ...props });
3128
3328
  this.device = device;
3129
3329
  this.gl = this.device.gl;
3130
3330
  this.handle = null;
@@ -3134,7 +3334,47 @@ ${source}`;
3134
3334
  }
3135
3335
  });
3136
3336
 
3337
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
3338
+ function convertGLDataTypeToDataType(type) {
3339
+ return GL_DATA_TYPE_MAP[type];
3340
+ }
3341
+ var GL_DATA_TYPE_MAP;
3342
+ var init_shader_formats = __esm({
3343
+ "../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js"() {
3344
+ GL_DATA_TYPE_MAP = {
3345
+ [5124]: "sint32",
3346
+ [5125]: "uint32",
3347
+ [5122]: "sint16",
3348
+ [5123]: "uint16",
3349
+ [5120]: "sint8",
3350
+ [5121]: "uint8",
3351
+ [5126]: "float32",
3352
+ [5131]: "float16",
3353
+ [33635]: "uint16",
3354
+ [32819]: "uint16",
3355
+ [32820]: "uint16",
3356
+ [33640]: "uint32",
3357
+ [35899]: "uint32",
3358
+ [35902]: "uint32",
3359
+ [34042]: "uint32",
3360
+ [36269]: "uint32"
3361
+ };
3362
+ }
3363
+ });
3364
+
3137
3365
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js
3366
+ function getArrayBufferView(typedArray, byteOffset = 0) {
3367
+ if (!byteOffset) {
3368
+ return typedArray;
3369
+ }
3370
+ return new typedArray.constructor(typedArray.buffer, typedArray.byteOffset + byteOffset, (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT);
3371
+ }
3372
+ function getWebGLTextureSourceElementOffset(typedArray, byteOffset) {
3373
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
3374
+ throw new Error(`Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`);
3375
+ }
3376
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
3377
+ }
3138
3378
  function getWebGLTextureTarget(dimension) {
3139
3379
  switch (dimension) {
3140
3380
  case "1d":
@@ -3155,15 +3395,17 @@ ${source}`;
3155
3395
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3156
3396
  return dimension === "cube" ? 34069 + level : glTarget;
3157
3397
  }
3158
- var import_core14, WEBGLTexture;
3398
+ var import_core15, import_core16, WEBGLTexture;
3159
3399
  var init_webgl_texture = __esm({
3160
3400
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js"() {
3161
- import_core14 = __toESM(require_core2(), 1);
3401
+ import_core15 = __toESM(require_core2(), 1);
3162
3402
  init_webgl_texture_table();
3163
3403
  init_sampler_parameters();
3164
3404
  init_with_parameters();
3165
3405
  init_webgl_texture_view();
3166
- WEBGLTexture = class extends import_core14.Texture {
3406
+ init_shader_formats();
3407
+ import_core16 = __toESM(require_core2(), 1);
3408
+ WEBGLTexture = class extends import_core15.Texture {
3167
3409
  // readonly MAX_ATTRIBUTES: number;
3168
3410
  device;
3169
3411
  gl;
@@ -3192,8 +3434,12 @@ ${source}`;
3192
3434
  // state
3193
3435
  /** Texture binding slot - TODO - move to texture view? */
3194
3436
  _textureUnit = 0;
3437
+ /** Cached framebuffer reused for color texture readback. */
3438
+ _framebuffer = null;
3439
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3440
+ _framebufferAttachmentKey = null;
3195
3441
  constructor(device, props) {
3196
- super(device, props);
3442
+ super(device, props, { byteAlignment: 1 });
3197
3443
  this.device = device;
3198
3444
  this.gl = this.device.gl;
3199
3445
  const formatInfo = getTextureFormatWebGL(this.props.format);
@@ -3206,29 +3452,43 @@ ${source}`;
3206
3452
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3207
3453
  this.gl.bindTexture(this.glTarget, this.handle);
3208
3454
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3209
- switch (dimension) {
3210
- case "2d":
3211
- case "cube":
3212
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3213
- break;
3214
- case "2d-array":
3215
- case "3d":
3216
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3217
- break;
3218
- default:
3219
- throw new Error(dimension);
3455
+ if (!this.compressed) {
3456
+ switch (dimension) {
3457
+ case "2d":
3458
+ case "cube":
3459
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3460
+ break;
3461
+ case "2d-array":
3462
+ case "3d":
3463
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3464
+ break;
3465
+ default:
3466
+ throw new Error(dimension);
3467
+ }
3220
3468
  }
3221
3469
  this.gl.bindTexture(this.glTarget, null);
3222
3470
  this._initializeData(props.data);
3471
+ if (!this.props.handle) {
3472
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
3473
+ } else {
3474
+ this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
3475
+ }
3223
3476
  this.setSampler(this.props.sampler);
3224
3477
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3225
3478
  Object.seal(this);
3226
3479
  }
3227
3480
  destroy() {
3228
3481
  if (this.handle) {
3229
- this.gl.deleteTexture(this.handle);
3482
+ this._framebuffer?.destroy();
3483
+ this._framebuffer = null;
3484
+ this._framebufferAttachmentKey = null;
3230
3485
  this.removeStats();
3231
- this.trackDeallocatedMemory("Texture");
3486
+ if (!this.props.handle) {
3487
+ this.gl.deleteTexture(this.handle);
3488
+ this.trackDeallocatedMemory("Texture");
3489
+ } else {
3490
+ this.trackDeallocatedReferencedMemory("Texture");
3491
+ }
3232
3492
  this.destroyed = true;
3233
3493
  }
3234
3494
  }
@@ -3240,103 +3500,273 @@ ${source}`;
3240
3500
  const parameters = convertSamplerParametersToWebGL(this.sampler.props);
3241
3501
  this._setSamplerParameters(parameters);
3242
3502
  }
3503
+ copyExternalImage(options_) {
3504
+ const options = this._normalizeCopyExternalImageOptions(options_);
3505
+ if (options.sourceX || options.sourceY) {
3506
+ throw new Error("WebGL does not support sourceX/sourceY)");
3507
+ }
3508
+ const { glFormat, glType } = this;
3509
+ const { image, depth, mipLevel, x, y, z, width, height } = options;
3510
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3511
+ const glParameters = options.flipY ? { [37440]: true } : {};
3512
+ this.gl.bindTexture(this.glTarget, this.handle);
3513
+ withGLParameters(this.gl, glParameters, () => {
3514
+ switch (this.dimension) {
3515
+ case "2d":
3516
+ case "cube":
3517
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3518
+ break;
3519
+ case "2d-array":
3520
+ case "3d":
3521
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3522
+ break;
3523
+ default:
3524
+ }
3525
+ });
3526
+ this.gl.bindTexture(this.glTarget, null);
3527
+ return { width: options.width, height: options.height };
3528
+ }
3243
3529
  copyImageData(options_) {
3244
- const options = this._normalizeCopyImageDataOptions(options_);
3245
- const typedArray = options.data;
3246
- const { width, height, depth } = this;
3247
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0, z = 0 } = options;
3530
+ super.copyImageData(options_);
3531
+ }
3532
+ /**
3533
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
3534
+ *
3535
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
3536
+ * before any WebGL calls are issued.
3537
+ */
3538
+ readBuffer(options = {}, buffer) {
3539
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
3540
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
3541
+ const readBuffer = buffer || this.device.createBuffer({
3542
+ byteLength: memoryLayout.byteLength,
3543
+ usage: import_core15.Buffer.COPY_DST | import_core15.Buffer.MAP_READ
3544
+ });
3545
+ if (readBuffer.byteLength < memoryLayout.byteLength) {
3546
+ throw new Error(`${this} readBuffer target is too small (${readBuffer.byteLength} < ${memoryLayout.byteLength})`);
3547
+ }
3548
+ const webglBuffer = readBuffer;
3549
+ this.gl.bindBuffer(35051, webglBuffer.handle);
3550
+ try {
3551
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, (destinationByteOffset) => {
3552
+ this.gl.readPixels(normalizedOptions.x, normalizedOptions.y, normalizedOptions.width, normalizedOptions.height, this.glFormat, this.glType, destinationByteOffset);
3553
+ });
3554
+ } finally {
3555
+ this.gl.bindBuffer(35051, null);
3556
+ }
3557
+ return readBuffer;
3558
+ }
3559
+ async readDataAsync(options = {}) {
3560
+ const buffer = this.readBuffer(options);
3561
+ const data = await buffer.readAsync();
3562
+ buffer.destroy();
3563
+ return data.buffer;
3564
+ }
3565
+ writeBuffer(buffer, options_ = {}) {
3566
+ const options = this._normalizeTextureWriteOptions(options_);
3567
+ const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
3248
3568
  const { glFormat, glType, compressed } = this;
3249
3569
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3250
- let unpackRowLength;
3251
- if (!this.compressed) {
3252
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3253
- if (bytesPerPixel) {
3254
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3255
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
3256
- }
3257
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
3258
- }
3570
+ if (compressed) {
3571
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
3259
3572
  }
3260
- const glParameters = !this.compressed ? {
3573
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3574
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3575
+ const glParameters = {
3576
+ [3317]: this.byteAlignment,
3261
3577
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3262
3578
  [32878]: options.rowsPerImage
3263
- } : {};
3264
- this.gl.bindTexture(glTarget, this.handle);
3579
+ };
3580
+ this.gl.bindTexture(this.glTarget, this.handle);
3581
+ this.gl.bindBuffer(35052, buffer.handle);
3265
3582
  withGLParameters(this.gl, glParameters, () => {
3266
3583
  switch (this.dimension) {
3267
3584
  case "2d":
3268
3585
  case "cube":
3269
- if (compressed) {
3270
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
3271
- } else {
3272
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3273
- }
3586
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
3274
3587
  break;
3275
3588
  case "2d-array":
3276
3589
  case "3d":
3277
- if (compressed) {
3278
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
3279
- } else {
3280
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
3281
- }
3590
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
3282
3591
  break;
3283
3592
  default:
3284
3593
  }
3285
3594
  });
3286
- this.gl.bindTexture(glTarget, null);
3595
+ this.gl.bindBuffer(35052, null);
3596
+ this.gl.bindTexture(this.glTarget, null);
3287
3597
  }
3288
- copyExternalImage(options_) {
3289
- const options = this._normalizeCopyExternalImageOptions(options_);
3290
- if (options.sourceX || options.sourceY) {
3291
- throw new Error("WebGL does not support sourceX/sourceY)");
3598
+ writeData(data, options_ = {}) {
3599
+ const options = this._normalizeTextureWriteOptions(options_);
3600
+ const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3601
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
3602
+ const { glFormat, glType, compressed } = this;
3603
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3604
+ let unpackRowLength;
3605
+ if (!compressed) {
3606
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3607
+ if (bytesPerPixel) {
3608
+ unpackRowLength = options.bytesPerRow / bytesPerPixel;
3609
+ }
3292
3610
  }
3293
- const { glFormat, glType } = this;
3294
- const { image, depth, mipLevel, x, y, z, width, height } = options;
3295
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3296
- const glParameters = options.flipY ? { [37440]: true } : {};
3611
+ const glParameters = !this.compressed ? {
3612
+ [3317]: this.byteAlignment,
3613
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3614
+ [32878]: options.rowsPerImage
3615
+ } : {};
3616
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
3617
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
3618
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
3619
+ const isFullMipUpload = x === 0 && y === 0 && z === 0 && width === mipLevelSize.width && height === mipLevelSize.height && depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
3297
3620
  this.gl.bindTexture(this.glTarget, this.handle);
3621
+ this.gl.bindBuffer(35052, null);
3298
3622
  withGLParameters(this.gl, glParameters, () => {
3299
3623
  switch (this.dimension) {
3300
3624
  case "2d":
3301
3625
  case "cube":
3302
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
3626
+ if (compressed) {
3627
+ if (isFullMipUpload) {
3628
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
3629
+ } else {
3630
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
3631
+ }
3632
+ } else {
3633
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3634
+ }
3303
3635
  break;
3304
3636
  case "2d-array":
3305
3637
  case "3d":
3306
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
3638
+ if (compressed) {
3639
+ if (isFullMipUpload) {
3640
+ this.gl.compressedTexImage3D(glTarget, mipLevel, glFormat, width, height, depthOrArrayLayers, 0, compressedData);
3641
+ } else {
3642
+ this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, compressedData);
3643
+ }
3644
+ } else {
3645
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
3646
+ }
3307
3647
  break;
3308
3648
  default:
3309
3649
  }
3310
3650
  });
3311
3651
  this.gl.bindTexture(this.glTarget, null);
3312
- return { width: options.width, height: options.height };
3652
+ }
3653
+ // IMPLEMENTATION SPECIFIC
3654
+ /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
3655
+ _getRowByteAlignment(format, width) {
3656
+ return 1;
3657
+ }
3658
+ /**
3659
+ * Wraps a given texture into a framebuffer object, that can be further used
3660
+ * to read data from the texture object.
3661
+ */
3662
+ _getFramebuffer() {
3663
+ this._framebuffer ||= this.device.createFramebuffer({
3664
+ id: `framebuffer-for-${this.id}`,
3665
+ width: this.width,
3666
+ height: this.height,
3667
+ colorAttachments: [this]
3668
+ });
3669
+ return this._framebuffer;
3313
3670
  }
3314
3671
  // WEBGL SPECIFIC
3315
- generateMipmapsWebGL(options) {
3316
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3317
- if (!isFilterableAndRenderable) {
3318
- import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3319
- if (!options?.force) {
3320
- return;
3321
- }
3322
- }
3672
+ readDataSyncWebGL(options_ = {}) {
3673
+ const options = this._getSupportedColorReadOptions(options_);
3674
+ const memoryLayout = this.computeMemoryLayout(options);
3675
+ const shaderType = convertGLDataTypeToDataType(this.glType);
3676
+ const ArrayType = (0, import_core16.getTypedArrayConstructor)(shaderType);
3677
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT);
3678
+ this._readColorTextureLayers(options, memoryLayout, (destinationByteOffset) => {
3679
+ const layerView = new ArrayType(targetArray.buffer, targetArray.byteOffset + destinationByteOffset, memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT);
3680
+ this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, this.glType, layerView);
3681
+ });
3682
+ return targetArray.buffer;
3683
+ }
3684
+ /**
3685
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
3686
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
3687
+ */
3688
+ _readColorTextureLayers(options, memoryLayout, readLayer) {
3689
+ const framebuffer = this._getFramebuffer();
3690
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
3691
+ const glParameters = {
3692
+ [3333]: this.byteAlignment,
3693
+ ...packRowLength !== options.width ? { [3330]: packRowLength } : {}
3694
+ };
3695
+ const prevReadBuffer = this.gl.getParameter(3074);
3696
+ const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3323
3697
  try {
3324
- this.gl.bindTexture(this.glTarget, this.handle);
3325
- this.gl.generateMipmap(this.glTarget);
3326
- } catch (error) {
3327
- import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3698
+ this.gl.readBuffer(36064);
3699
+ withGLParameters(this.gl, glParameters, () => {
3700
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
3701
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
3702
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
3703
+ }
3704
+ });
3328
3705
  } finally {
3329
- this.gl.bindTexture(this.glTarget, null);
3706
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3707
+ this.gl.readBuffer(prevReadBuffer);
3330
3708
  }
3331
3709
  }
3332
- // INTERNAL
3333
3710
  /**
3334
- * Sets sampler parameters on texture
3711
+ * Attaches a single color subresource to the cached read framebuffer.
3712
+ *
3713
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3335
3714
  */
3336
- _setSamplerParameters(parameters) {
3337
- import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3338
- this.gl.bindTexture(this.glTarget, this.handle);
3339
- for (const [pname, pvalue] of Object.entries(parameters)) {
3715
+ _attachReadSubresource(framebuffer, mipLevel, layer) {
3716
+ const attachmentKey = `${mipLevel}:${layer}`;
3717
+ if (this._framebufferAttachmentKey === attachmentKey) {
3718
+ return;
3719
+ }
3720
+ switch (this.dimension) {
3721
+ case "2d":
3722
+ this.gl.framebufferTexture2D(36160, 36064, 3553, this.handle, mipLevel);
3723
+ break;
3724
+ case "cube":
3725
+ this.gl.framebufferTexture2D(36160, 36064, getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer), this.handle, mipLevel);
3726
+ break;
3727
+ case "2d-array":
3728
+ case "3d":
3729
+ this.gl.framebufferTextureLayer(36160, 36064, this.handle, mipLevel, layer);
3730
+ break;
3731
+ default:
3732
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
3733
+ }
3734
+ if (this.device.props.debug) {
3735
+ const status = Number(this.gl.checkFramebufferStatus(36160));
3736
+ if (status !== Number(36053)) {
3737
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
3738
+ }
3739
+ }
3740
+ this._framebufferAttachmentKey = attachmentKey;
3741
+ }
3742
+ /**
3743
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3744
+ */
3745
+ generateMipmapsWebGL(options) {
3746
+ const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3747
+ if (!isFilterableAndRenderable) {
3748
+ import_core15.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3749
+ if (!options?.force) {
3750
+ return;
3751
+ }
3752
+ }
3753
+ try {
3754
+ this.gl.bindTexture(this.glTarget, this.handle);
3755
+ this.gl.generateMipmap(this.glTarget);
3756
+ } catch (error) {
3757
+ import_core15.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3758
+ } finally {
3759
+ this.gl.bindTexture(this.glTarget, null);
3760
+ }
3761
+ }
3762
+ // INTERNAL
3763
+ /**
3764
+ * Sets sampler parameters on texture
3765
+ */
3766
+ _setSamplerParameters(parameters) {
3767
+ import_core15.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3768
+ this.gl.bindTexture(this.glTarget, this.handle);
3769
+ for (const [pname, pvalue] of Object.entries(parameters)) {
3340
3770
  const param = Number(pname);
3341
3771
  const value = pvalue;
3342
3772
  switch (param) {
@@ -3391,104 +3821,508 @@ ${source}`;
3391
3821
  }
3392
3822
  });
3393
3823
 
3394
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
3395
- function convertDataTypeToGLDataType(normalizedType) {
3396
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3397
- }
3398
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
3399
- return WEBGL_SHADER_TYPES[glUniformType];
3824
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3825
+ function setUniform(gl, location, type, value) {
3826
+ const gl2 = gl;
3827
+ let uniformValue = value;
3828
+ if (uniformValue === true) {
3829
+ uniformValue = 1;
3830
+ }
3831
+ if (uniformValue === false) {
3832
+ uniformValue = 0;
3833
+ }
3834
+ const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
3835
+ switch (type) {
3836
+ case 35678:
3837
+ case 35680:
3838
+ case 35679:
3839
+ case 35682:
3840
+ case 36289:
3841
+ case 36292:
3842
+ case 36293:
3843
+ case 36298:
3844
+ case 36299:
3845
+ case 36300:
3846
+ case 36303:
3847
+ case 36306:
3848
+ case 36307:
3849
+ case 36308:
3850
+ case 36311:
3851
+ if (typeof value !== "number") {
3852
+ throw new Error("samplers must be set to integers");
3853
+ }
3854
+ return gl.uniform1i(location, value);
3855
+ case 5126:
3856
+ return gl.uniform1fv(location, arrayValue);
3857
+ case 35664:
3858
+ return gl.uniform2fv(location, arrayValue);
3859
+ case 35665:
3860
+ return gl.uniform3fv(location, arrayValue);
3861
+ case 35666:
3862
+ return gl.uniform4fv(location, arrayValue);
3863
+ case 5124:
3864
+ return gl.uniform1iv(location, arrayValue);
3865
+ case 35667:
3866
+ return gl.uniform2iv(location, arrayValue);
3867
+ case 35668:
3868
+ return gl.uniform3iv(location, arrayValue);
3869
+ case 35669:
3870
+ return gl.uniform4iv(location, arrayValue);
3871
+ case 35670:
3872
+ return gl.uniform1iv(location, arrayValue);
3873
+ case 35671:
3874
+ return gl.uniform2iv(location, arrayValue);
3875
+ case 35672:
3876
+ return gl.uniform3iv(location, arrayValue);
3877
+ case 35673:
3878
+ return gl.uniform4iv(location, arrayValue);
3879
+ case 5125:
3880
+ return gl2.uniform1uiv(location, arrayValue, 1);
3881
+ case 36294:
3882
+ return gl2.uniform2uiv(location, arrayValue, 2);
3883
+ case 36295:
3884
+ return gl2.uniform3uiv(location, arrayValue, 3);
3885
+ case 36296:
3886
+ return gl2.uniform4uiv(location, arrayValue, 4);
3887
+ case 35674:
3888
+ return gl.uniformMatrix2fv(location, false, arrayValue);
3889
+ case 35675:
3890
+ return gl.uniformMatrix3fv(location, false, arrayValue);
3891
+ case 35676:
3892
+ return gl.uniformMatrix4fv(location, false, arrayValue);
3893
+ case 35685:
3894
+ return gl2.uniformMatrix2x3fv(location, false, arrayValue);
3895
+ case 35686:
3896
+ return gl2.uniformMatrix2x4fv(location, false, arrayValue);
3897
+ case 35687:
3898
+ return gl2.uniformMatrix3x2fv(location, false, arrayValue);
3899
+ case 35688:
3900
+ return gl2.uniformMatrix3x4fv(location, false, arrayValue);
3901
+ case 35689:
3902
+ return gl2.uniformMatrix4x2fv(location, false, arrayValue);
3903
+ case 35690:
3904
+ return gl2.uniformMatrix4x3fv(location, false, arrayValue);
3905
+ }
3906
+ throw new Error("Illegal uniform");
3400
3907
  }
3401
- function isGLSamplerType(type) {
3402
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3908
+ var init_set_uniform = __esm({
3909
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js"() {
3910
+ }
3911
+ });
3912
+
3913
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
3914
+ function getGLDrawMode(topology) {
3915
+ switch (topology) {
3916
+ case "point-list":
3917
+ return 0;
3918
+ case "line-list":
3919
+ return 1;
3920
+ case "line-strip":
3921
+ return 3;
3922
+ case "triangle-list":
3923
+ return 4;
3924
+ case "triangle-strip":
3925
+ return 5;
3926
+ default:
3927
+ throw new Error(topology);
3928
+ }
3403
3929
  }
3404
- function getTextureBindingFromGLSamplerType(glSamplerType) {
3405
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3930
+ function getGLPrimitive(topology) {
3931
+ switch (topology) {
3932
+ case "point-list":
3933
+ return 0;
3934
+ case "line-list":
3935
+ return 1;
3936
+ case "line-strip":
3937
+ return 1;
3938
+ case "triangle-list":
3939
+ return 4;
3940
+ case "triangle-strip":
3941
+ return 4;
3942
+ default:
3943
+ throw new Error(topology);
3944
+ }
3406
3945
  }
3407
- var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
3408
- var init_webgl_shadertypes = __esm({
3409
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
3410
- WEBGL_SHADER_TYPES = {
3411
- [5126]: "f32",
3412
- [35664]: "vec2<f32>",
3413
- [35665]: "vec3<f32>",
3414
- [35666]: "vec4<f32>",
3415
- [5124]: "i32",
3416
- [35667]: "vec2<i32>",
3417
- [35668]: "vec3<i32>",
3418
- [35669]: "vec4<i32>",
3419
- [5125]: "u32",
3420
- [36294]: "vec2<u32>",
3421
- [36295]: "vec3<u32>",
3422
- [36296]: "vec4<u32>",
3423
- [35670]: "f32",
3424
- [35671]: "vec2<f32>",
3425
- [35672]: "vec3<f32>",
3426
- [35673]: "vec4<f32>",
3427
- // TODO - are sizes/components below correct?
3428
- [35674]: "mat2x2<f32>",
3429
- [35685]: "mat2x3<f32>",
3430
- [35686]: "mat2x4<f32>",
3431
- [35687]: "mat3x2<f32>",
3432
- [35675]: "mat3x3<f32>",
3433
- [35688]: "mat3x4<f32>",
3434
- [35689]: "mat4x2<f32>",
3435
- [35690]: "mat4x3<f32>",
3436
- [35676]: "mat4x4<f32>"
3437
- };
3438
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3439
- [35678]: { viewDimension: "2d", sampleType: "float" },
3440
- [35680]: { viewDimension: "cube", sampleType: "float" },
3441
- [35679]: { viewDimension: "3d", sampleType: "float" },
3442
- [35682]: { viewDimension: "3d", sampleType: "depth" },
3443
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
3444
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
3445
- [36293]: { viewDimension: "cube", sampleType: "float" },
3446
- [36298]: { viewDimension: "2d", sampleType: "sint" },
3447
- [36299]: { viewDimension: "3d", sampleType: "sint" },
3448
- [36300]: { viewDimension: "cube", sampleType: "sint" },
3449
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
3450
- [36306]: { viewDimension: "2d", sampleType: "uint" },
3451
- [36307]: { viewDimension: "3d", sampleType: "uint" },
3452
- [36308]: { viewDimension: "cube", sampleType: "uint" },
3453
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
3454
- };
3455
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3456
- uint8: 5121,
3457
- sint8: 5120,
3458
- unorm8: 5121,
3459
- snorm8: 5120,
3460
- uint16: 5123,
3461
- sint16: 5122,
3462
- unorm16: 5123,
3463
- snorm16: 5122,
3464
- uint32: 5125,
3465
- sint32: 5124,
3466
- // WebGPU does not support normalized 32 bit integer attributes
3467
- // 'unorm32': GL.UNSIGNED_INT,
3468
- // 'snorm32': GL.INT,
3469
- float16: 5131,
3470
- float32: 5126
3471
- };
3946
+ var init_webgl_topology_utils = __esm({
3947
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
3472
3948
  }
3473
3949
  });
3474
3950
 
3475
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
3476
- function getShaderLayoutFromGLSL(gl, program) {
3477
- const shaderLayout = {
3478
- attributes: [],
3479
- bindings: []
3951
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3952
+ function mergeShaderLayout(baseLayout, overrideLayout) {
3953
+ const mergedLayout = {
3954
+ ...baseLayout,
3955
+ attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
3480
3956
  };
3481
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3482
- const uniformBlocks = readUniformBlocks(gl, program);
3483
- for (const uniformBlock of uniformBlocks) {
3484
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3485
- name: uniform.name,
3486
- format: uniform.format,
3487
- byteOffset: uniform.byteOffset,
3488
- byteStride: uniform.byteStride,
3489
- arrayLength: uniform.arrayLength
3490
- }));
3491
- shaderLayout.bindings.push({
3957
+ for (const attribute of overrideLayout?.attributes || []) {
3958
+ const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3959
+ if (!baseAttribute) {
3960
+ import_core17.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3961
+ } else {
3962
+ baseAttribute.type = attribute.type || baseAttribute.type;
3963
+ baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3964
+ }
3965
+ }
3966
+ return mergedLayout;
3967
+ }
3968
+ var import_core17, WEBGLRenderPipeline;
3969
+ var init_webgl_render_pipeline = __esm({
3970
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3971
+ import_core17 = __toESM(require_core2(), 1);
3972
+ init_device_parameters();
3973
+ init_set_uniform();
3974
+ init_webgl_buffer();
3975
+ init_webgl_framebuffer();
3976
+ init_webgl_texture();
3977
+ init_webgl_texture_view();
3978
+ init_webgl_topology_utils();
3979
+ WEBGLRenderPipeline = class extends import_core17.RenderPipeline {
3980
+ /** The WebGL device that created this render pipeline */
3981
+ device;
3982
+ /** Handle to underlying WebGL program */
3983
+ handle;
3984
+ /** vertex shader */
3985
+ vs;
3986
+ /** fragment shader */
3987
+ fs;
3988
+ /** The layout extracted from shader by WebGL introspection APIs */
3989
+ introspectedLayout;
3990
+ /** Compatibility path for direct pipeline.setBindings() usage */
3991
+ bindings = {};
3992
+ /** Compatibility path for direct pipeline.uniforms usage */
3993
+ uniforms = {};
3994
+ /** WebGL varyings */
3995
+ varyings = null;
3996
+ _uniformCount = 0;
3997
+ _uniformSetters = {};
3998
+ // TODO are these used?
3999
+ get [Symbol.toStringTag]() {
4000
+ return "WEBGLRenderPipeline";
4001
+ }
4002
+ constructor(device, props) {
4003
+ super(device, props);
4004
+ this.device = device;
4005
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
4006
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
4007
+ this.handle = webglSharedRenderPipeline.handle;
4008
+ this.vs = webglSharedRenderPipeline.vs;
4009
+ this.fs = webglSharedRenderPipeline.fs;
4010
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
4011
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
4012
+ this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4013
+ this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4014
+ }
4015
+ destroy() {
4016
+ if (this.destroyed) {
4017
+ return;
4018
+ }
4019
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4020
+ this.sharedRenderPipeline.destroy();
4021
+ }
4022
+ this.destroyResource();
4023
+ }
4024
+ /**
4025
+ * Compatibility shim for code paths that still set bindings on the pipeline.
4026
+ * Shared-model draws pass bindings per draw and do not rely on this state.
4027
+ */
4028
+ setBindings(bindings, options) {
4029
+ for (const [name, value] of Object.entries(bindings)) {
4030
+ const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
4031
+ if (!binding) {
4032
+ const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
4033
+ if (!options?.disableWarnings) {
4034
+ import_core17.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
4035
+ }
4036
+ continue;
4037
+ }
4038
+ if (!value) {
4039
+ import_core17.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
4040
+ }
4041
+ switch (binding.type) {
4042
+ case "uniform":
4043
+ if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
4044
+ throw new Error("buffer value");
4045
+ }
4046
+ break;
4047
+ case "texture":
4048
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4049
+ throw new Error(`${this} Bad texture binding for ${name}`);
4050
+ }
4051
+ break;
4052
+ case "sampler":
4053
+ import_core17.log.warn(`Ignoring sampler ${name}`)();
4054
+ break;
4055
+ default:
4056
+ throw new Error(binding.type);
4057
+ }
4058
+ this.bindings[name] = value;
4059
+ }
4060
+ }
4061
+ /** @todo needed for portable model
4062
+ * @note The WebGL API is offers many ways to draw things
4063
+ * This function unifies those ways into a single call using common parameters with sane defaults
4064
+ */
4065
+ draw(options) {
4066
+ this._syncLinkStatus();
4067
+ const {
4068
+ renderPass,
4069
+ parameters = this.props.parameters,
4070
+ topology = this.props.topology,
4071
+ vertexArray,
4072
+ vertexCount,
4073
+ // indexCount,
4074
+ instanceCount,
4075
+ isInstanced = false,
4076
+ firstVertex = 0,
4077
+ // firstIndex,
4078
+ // firstInstance,
4079
+ // baseVertex,
4080
+ transformFeedback,
4081
+ bindings = this.bindings,
4082
+ uniforms = this.uniforms
4083
+ } = options;
4084
+ const glDrawMode = getGLDrawMode(topology);
4085
+ const isIndexed = Boolean(vertexArray.indexBuffer);
4086
+ const glIndexType = vertexArray.indexBuffer?.glIndexType;
4087
+ if (this.linkStatus !== "success") {
4088
+ import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4089
+ return false;
4090
+ }
4091
+ if (!this._areTexturesRenderable(bindings)) {
4092
+ import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4093
+ return false;
4094
+ }
4095
+ this.device.gl.useProgram(this.handle);
4096
+ vertexArray.bindBeforeRender(renderPass);
4097
+ if (transformFeedback) {
4098
+ transformFeedback.begin(this.props.topology);
4099
+ }
4100
+ this._applyBindings(bindings, { disableWarnings: this.props.disableWarnings });
4101
+ this._applyUniforms(uniforms);
4102
+ const webglRenderPass = renderPass;
4103
+ withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4104
+ if (isIndexed && isInstanced) {
4105
+ this.device.gl.drawElementsInstanced(
4106
+ glDrawMode,
4107
+ vertexCount || 0,
4108
+ // indexCount?
4109
+ glIndexType,
4110
+ firstVertex,
4111
+ instanceCount || 0
4112
+ );
4113
+ } else if (isIndexed) {
4114
+ this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4115
+ } else if (isInstanced) {
4116
+ this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4117
+ } else {
4118
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4119
+ }
4120
+ if (transformFeedback) {
4121
+ transformFeedback.end();
4122
+ }
4123
+ });
4124
+ vertexArray.unbindAfterRender(renderPass);
4125
+ return true;
4126
+ }
4127
+ /**
4128
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
4129
+ * Update a texture if needed (e.g. from video)
4130
+ * Note: This is currently done before every draw call
4131
+ */
4132
+ _areTexturesRenderable(bindings) {
4133
+ let texturesRenderable = true;
4134
+ for (const bindingInfo of this.shaderLayout.bindings) {
4135
+ if (!bindings[bindingInfo.name] && !bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4136
+ import_core17.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4137
+ texturesRenderable = false;
4138
+ }
4139
+ }
4140
+ return texturesRenderable;
4141
+ }
4142
+ /** Apply any bindings (before each draw call) */
4143
+ _applyBindings(bindings, _options) {
4144
+ this._syncLinkStatus();
4145
+ if (this.linkStatus !== "success") {
4146
+ return;
4147
+ }
4148
+ const { gl } = this.device;
4149
+ gl.useProgram(this.handle);
4150
+ let textureUnit = 0;
4151
+ let uniformBufferIndex = 0;
4152
+ for (const binding of this.shaderLayout.bindings) {
4153
+ const value = bindings[binding.name] || bindings[binding.name.replace(/Uniforms$/, "")];
4154
+ if (!value) {
4155
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4156
+ }
4157
+ switch (binding.type) {
4158
+ case "uniform":
4159
+ const { name } = binding;
4160
+ const location = gl.getUniformBlockIndex(this.handle, name);
4161
+ if (location === 4294967295) {
4162
+ throw new Error(`Invalid uniform block name ${name}`);
4163
+ }
4164
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
4165
+ if (value instanceof WEBGLBuffer) {
4166
+ gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4167
+ } else {
4168
+ gl.bindBufferRange(
4169
+ 35345,
4170
+ uniformBufferIndex,
4171
+ // @ts-expect-error
4172
+ value.buffer.handle,
4173
+ // @ts-expect-error
4174
+ value.offset || 0,
4175
+ // @ts-expect-error
4176
+ value.size || value.buffer.byteLength - value.offset
4177
+ );
4178
+ }
4179
+ uniformBufferIndex += 1;
4180
+ break;
4181
+ case "texture":
4182
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4183
+ throw new Error("texture");
4184
+ }
4185
+ let texture;
4186
+ if (value instanceof WEBGLTextureView) {
4187
+ texture = value.texture;
4188
+ } else if (value instanceof WEBGLTexture) {
4189
+ texture = value;
4190
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4191
+ import_core17.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4192
+ texture = value.colorAttachments[0].texture;
4193
+ } else {
4194
+ throw new Error("No texture");
4195
+ }
4196
+ gl.activeTexture(33984 + textureUnit);
4197
+ gl.bindTexture(texture.glTarget, texture.handle);
4198
+ textureUnit += 1;
4199
+ break;
4200
+ case "sampler":
4201
+ break;
4202
+ case "storage":
4203
+ case "read-only-storage":
4204
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4205
+ }
4206
+ }
4207
+ }
4208
+ /**
4209
+ * Due to program sharing, uniforms need to be reset before every draw call
4210
+ * (though caching will avoid redundant WebGL calls)
4211
+ */
4212
+ _applyUniforms(uniforms) {
4213
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
4214
+ const { name, location, type, textureUnit } = uniformLayout;
4215
+ const value = uniforms[name] ?? textureUnit;
4216
+ if (value !== void 0) {
4217
+ setUniform(this.device.gl, location, type, value);
4218
+ }
4219
+ }
4220
+ }
4221
+ _syncLinkStatus() {
4222
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
4223
+ }
4224
+ };
4225
+ }
4226
+ });
4227
+
4228
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
4229
+ function convertDataTypeToGLDataType(normalizedType) {
4230
+ return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
4231
+ }
4232
+ function convertGLUniformTypeToShaderVariableType(glUniformType) {
4233
+ return WEBGL_SHADER_TYPES[glUniformType];
4234
+ }
4235
+ function isGLSamplerType(type) {
4236
+ return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
4237
+ }
4238
+ function getTextureBindingFromGLSamplerType(glSamplerType) {
4239
+ return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
4240
+ }
4241
+ var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
4242
+ var init_webgl_shadertypes = __esm({
4243
+ "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
4244
+ WEBGL_SHADER_TYPES = {
4245
+ [5126]: "f32",
4246
+ [35664]: "vec2<f32>",
4247
+ [35665]: "vec3<f32>",
4248
+ [35666]: "vec4<f32>",
4249
+ [5124]: "i32",
4250
+ [35667]: "vec2<i32>",
4251
+ [35668]: "vec3<i32>",
4252
+ [35669]: "vec4<i32>",
4253
+ [5125]: "u32",
4254
+ [36294]: "vec2<u32>",
4255
+ [36295]: "vec3<u32>",
4256
+ [36296]: "vec4<u32>",
4257
+ [35670]: "f32",
4258
+ [35671]: "vec2<f32>",
4259
+ [35672]: "vec3<f32>",
4260
+ [35673]: "vec4<f32>",
4261
+ // TODO - are sizes/components below correct?
4262
+ [35674]: "mat2x2<f32>",
4263
+ [35685]: "mat2x3<f32>",
4264
+ [35686]: "mat2x4<f32>",
4265
+ [35687]: "mat3x2<f32>",
4266
+ [35675]: "mat3x3<f32>",
4267
+ [35688]: "mat3x4<f32>",
4268
+ [35689]: "mat4x2<f32>",
4269
+ [35690]: "mat4x3<f32>",
4270
+ [35676]: "mat4x4<f32>"
4271
+ };
4272
+ WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
4273
+ [35678]: { viewDimension: "2d", sampleType: "float" },
4274
+ [35680]: { viewDimension: "cube", sampleType: "float" },
4275
+ [35679]: { viewDimension: "3d", sampleType: "float" },
4276
+ [35682]: { viewDimension: "3d", sampleType: "depth" },
4277
+ [36289]: { viewDimension: "2d-array", sampleType: "float" },
4278
+ [36292]: { viewDimension: "2d-array", sampleType: "depth" },
4279
+ [36293]: { viewDimension: "cube", sampleType: "float" },
4280
+ [36298]: { viewDimension: "2d", sampleType: "sint" },
4281
+ [36299]: { viewDimension: "3d", sampleType: "sint" },
4282
+ [36300]: { viewDimension: "cube", sampleType: "sint" },
4283
+ [36303]: { viewDimension: "2d-array", sampleType: "uint" },
4284
+ [36306]: { viewDimension: "2d", sampleType: "uint" },
4285
+ [36307]: { viewDimension: "3d", sampleType: "uint" },
4286
+ [36308]: { viewDimension: "cube", sampleType: "uint" },
4287
+ [36311]: { viewDimension: "2d-array", sampleType: "uint" }
4288
+ };
4289
+ NORMALIZED_SHADER_TYPE_TO_WEBGL = {
4290
+ uint8: 5121,
4291
+ sint8: 5120,
4292
+ unorm8: 5121,
4293
+ snorm8: 5120,
4294
+ uint16: 5123,
4295
+ sint16: 5122,
4296
+ unorm16: 5123,
4297
+ snorm16: 5122,
4298
+ uint32: 5125,
4299
+ sint32: 5124,
4300
+ // WebGPU does not support normalized 32 bit integer attributes
4301
+ // 'unorm32': GL.UNSIGNED_INT,
4302
+ // 'snorm32': GL.INT,
4303
+ float16: 5131,
4304
+ float32: 5126
4305
+ };
4306
+ }
4307
+ });
4308
+
4309
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
4310
+ function getShaderLayoutFromGLSL(gl, program) {
4311
+ const shaderLayout = {
4312
+ attributes: [],
4313
+ bindings: []
4314
+ };
4315
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
4316
+ const uniformBlocks = readUniformBlocks(gl, program);
4317
+ for (const uniformBlock of uniformBlocks) {
4318
+ const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
4319
+ name: uniform.name,
4320
+ format: uniform.format,
4321
+ byteOffset: uniform.byteOffset,
4322
+ byteStride: uniform.byteStride,
4323
+ arrayLength: uniform.arrayLength
4324
+ }));
4325
+ shaderLayout.bindings.push({
3492
4326
  type: "uniform",
3493
4327
  name: uniformBlock.name,
3494
4328
  group: 0,
@@ -3561,448 +4395,175 @@ ${source}`;
3561
4395
  if (!activeInfo) {
3562
4396
  throw new Error("activeInfo");
3563
4397
  }
3564
- const { name, type: glUniformType, size } = activeInfo;
3565
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3566
- const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
3567
- varyings.push({ location, name, type, size: size * components });
3568
- }
3569
- varyings.sort((a, b) => a.location - b.location);
3570
- return varyings;
3571
- }
3572
- function readUniformBindings(gl, program) {
3573
- const uniforms = [];
3574
- const uniformCount = gl.getProgramParameter(program, 35718);
3575
- for (let i = 0; i < uniformCount; i++) {
3576
- const activeInfo = gl.getActiveUniform(program, i);
3577
- if (!activeInfo) {
3578
- throw new Error("activeInfo");
3579
- }
3580
- const { name: rawName, size, type } = activeInfo;
3581
- const { name, isArray: isArray3 } = parseUniformName(rawName);
3582
- let webglLocation = gl.getUniformLocation(program, name);
3583
- const uniformInfo = {
3584
- // WebGL locations are uniquely typed but just numbers
3585
- location: webglLocation,
3586
- name,
3587
- size,
3588
- type,
3589
- isArray: isArray3
3590
- };
3591
- uniforms.push(uniformInfo);
3592
- if (uniformInfo.size > 1) {
3593
- for (let j = 0; j < uniformInfo.size; j++) {
3594
- const elementName = `${name}[${j}]`;
3595
- webglLocation = gl.getUniformLocation(program, elementName);
3596
- const arrayElementUniformInfo = {
3597
- ...uniformInfo,
3598
- name: elementName,
3599
- location: webglLocation
3600
- };
3601
- uniforms.push(arrayElementUniformInfo);
3602
- }
3603
- }
3604
- }
3605
- return uniforms;
3606
- }
3607
- function readUniformBlocks(gl, program) {
3608
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3609
- const uniformBlocks = [];
3610
- const blockCount = gl.getProgramParameter(program, 35382);
3611
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3612
- const blockInfo = {
3613
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3614
- location: getBlockParameter(blockIndex, 35391),
3615
- byteLength: getBlockParameter(blockIndex, 35392),
3616
- vertex: getBlockParameter(blockIndex, 35396),
3617
- fragment: getBlockParameter(blockIndex, 35398),
3618
- uniformCount: getBlockParameter(blockIndex, 35394),
3619
- uniforms: []
3620
- };
3621
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3622
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3623
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3624
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3625
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3626
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3627
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3628
- if (!activeInfo) {
3629
- throw new Error("activeInfo");
3630
- }
3631
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3632
- blockInfo.uniforms.push({
3633
- name: activeInfo.name,
3634
- format,
3635
- type: uniformType[i],
3636
- arrayLength: uniformArrayLength[i],
3637
- byteOffset: uniformOffset[i],
3638
- byteStride: uniformStride[i]
3639
- // matrixStride: uniformStride[i],
3640
- // rowMajor: uniformRowMajor[i]
3641
- });
3642
- }
3643
- uniformBlocks.push(blockInfo);
3644
- }
3645
- uniformBlocks.sort((a, b) => a.location - b.location);
3646
- return uniformBlocks;
3647
- }
3648
- function parseUniformName(name) {
3649
- if (name[name.length - 1] !== "]") {
3650
- return {
3651
- name,
3652
- length: 1,
3653
- isArray: false
3654
- };
3655
- }
3656
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3657
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3658
- if (!matches || matches.length < 2) {
3659
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3660
- }
3661
- return {
3662
- name: matches[1],
3663
- length: matches[2] ? 1 : 0,
3664
- isArray: Boolean(matches[2])
3665
- };
3666
- }
3667
- var import_core15;
3668
- var init_get_shader_layout_from_glsl = __esm({
3669
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3670
- import_core15 = __toESM(require_core2(), 1);
3671
- init_webgl_shadertypes();
3672
- }
3673
- });
3674
-
3675
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3676
- function setUniform(gl, location, type, value) {
3677
- const gl2 = gl;
3678
- let uniformValue = value;
3679
- if (uniformValue === true) {
3680
- uniformValue = 1;
3681
- }
3682
- if (uniformValue === false) {
3683
- uniformValue = 0;
3684
- }
3685
- const arrayValue = typeof uniformValue === "number" ? [uniformValue] : uniformValue;
3686
- switch (type) {
3687
- case 35678:
3688
- case 35680:
3689
- case 35679:
3690
- case 35682:
3691
- case 36289:
3692
- case 36292:
3693
- case 36293:
3694
- case 36298:
3695
- case 36299:
3696
- case 36300:
3697
- case 36303:
3698
- case 36306:
3699
- case 36307:
3700
- case 36308:
3701
- case 36311:
3702
- if (typeof value !== "number") {
3703
- throw new Error("samplers must be set to integers");
3704
- }
3705
- return gl.uniform1i(location, value);
3706
- case 5126:
3707
- return gl.uniform1fv(location, arrayValue);
3708
- case 35664:
3709
- return gl.uniform2fv(location, arrayValue);
3710
- case 35665:
3711
- return gl.uniform3fv(location, arrayValue);
3712
- case 35666:
3713
- return gl.uniform4fv(location, arrayValue);
3714
- case 5124:
3715
- return gl.uniform1iv(location, arrayValue);
3716
- case 35667:
3717
- return gl.uniform2iv(location, arrayValue);
3718
- case 35668:
3719
- return gl.uniform3iv(location, arrayValue);
3720
- case 35669:
3721
- return gl.uniform4iv(location, arrayValue);
3722
- case 35670:
3723
- return gl.uniform1iv(location, arrayValue);
3724
- case 35671:
3725
- return gl.uniform2iv(location, arrayValue);
3726
- case 35672:
3727
- return gl.uniform3iv(location, arrayValue);
3728
- case 35673:
3729
- return gl.uniform4iv(location, arrayValue);
3730
- case 5125:
3731
- return gl2.uniform1uiv(location, arrayValue, 1);
3732
- case 36294:
3733
- return gl2.uniform2uiv(location, arrayValue, 2);
3734
- case 36295:
3735
- return gl2.uniform3uiv(location, arrayValue, 3);
3736
- case 36296:
3737
- return gl2.uniform4uiv(location, arrayValue, 4);
3738
- case 35674:
3739
- return gl.uniformMatrix2fv(location, false, arrayValue);
3740
- case 35675:
3741
- return gl.uniformMatrix3fv(location, false, arrayValue);
3742
- case 35676:
3743
- return gl.uniformMatrix4fv(location, false, arrayValue);
3744
- case 35685:
3745
- return gl2.uniformMatrix2x3fv(location, false, arrayValue);
3746
- case 35686:
3747
- return gl2.uniformMatrix2x4fv(location, false, arrayValue);
3748
- case 35687:
3749
- return gl2.uniformMatrix3x2fv(location, false, arrayValue);
3750
- case 35688:
3751
- return gl2.uniformMatrix3x4fv(location, false, arrayValue);
3752
- case 35689:
3753
- return gl2.uniformMatrix4x2fv(location, false, arrayValue);
3754
- case 35690:
3755
- return gl2.uniformMatrix4x3fv(location, false, arrayValue);
4398
+ const { name, type: glUniformType, size } = activeInfo;
4399
+ const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
4400
+ const { type, components } = (0, import_core18.getVariableShaderTypeInfo)(uniformType);
4401
+ varyings.push({ location, name, type, size: size * components });
3756
4402
  }
3757
- throw new Error("Illegal uniform");
4403
+ varyings.sort((a, b) => a.location - b.location);
4404
+ return varyings;
3758
4405
  }
3759
- var init_set_uniform = __esm({
3760
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js"() {
4406
+ function readUniformBindings(gl, program) {
4407
+ const uniforms = [];
4408
+ const uniformCount = gl.getProgramParameter(program, 35718);
4409
+ for (let i = 0; i < uniformCount; i++) {
4410
+ const activeInfo = gl.getActiveUniform(program, i);
4411
+ if (!activeInfo) {
4412
+ throw new Error("activeInfo");
4413
+ }
4414
+ const { name: rawName, size, type } = activeInfo;
4415
+ const { name, isArray: isArray3 } = parseUniformName(rawName);
4416
+ let webglLocation = gl.getUniformLocation(program, name);
4417
+ const uniformInfo = {
4418
+ // WebGL locations are uniquely typed but just numbers
4419
+ location: webglLocation,
4420
+ name,
4421
+ size,
4422
+ type,
4423
+ isArray: isArray3
4424
+ };
4425
+ uniforms.push(uniformInfo);
4426
+ if (uniformInfo.size > 1) {
4427
+ for (let j = 0; j < uniformInfo.size; j++) {
4428
+ const elementName = `${name}[${j}]`;
4429
+ webglLocation = gl.getUniformLocation(program, elementName);
4430
+ const arrayElementUniformInfo = {
4431
+ ...uniformInfo,
4432
+ name: elementName,
4433
+ location: webglLocation
4434
+ };
4435
+ uniforms.push(arrayElementUniformInfo);
4436
+ }
4437
+ }
3761
4438
  }
3762
- });
3763
-
3764
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
3765
- function getGLDrawMode(topology) {
3766
- switch (topology) {
3767
- case "point-list":
3768
- return 0;
3769
- case "line-list":
3770
- return 1;
3771
- case "line-strip":
3772
- return 3;
3773
- case "triangle-list":
3774
- return 4;
3775
- case "triangle-strip":
3776
- return 5;
3777
- default:
3778
- throw new Error(topology);
4439
+ return uniforms;
4440
+ }
4441
+ function readUniformBlocks(gl, program) {
4442
+ const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
4443
+ const uniformBlocks = [];
4444
+ const blockCount = gl.getProgramParameter(program, 35382);
4445
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
4446
+ const blockInfo = {
4447
+ name: gl.getActiveUniformBlockName(program, blockIndex) || "",
4448
+ location: getBlockParameter(blockIndex, 35391),
4449
+ byteLength: getBlockParameter(blockIndex, 35392),
4450
+ vertex: getBlockParameter(blockIndex, 35396),
4451
+ fragment: getBlockParameter(blockIndex, 35398),
4452
+ uniformCount: getBlockParameter(blockIndex, 35394),
4453
+ uniforms: []
4454
+ };
4455
+ const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
4456
+ const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
4457
+ const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
4458
+ const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
4459
+ const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
4460
+ for (let i = 0; i < blockInfo.uniformCount; ++i) {
4461
+ const uniformIndex = uniformIndices[i];
4462
+ if (uniformIndex !== void 0) {
4463
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
4464
+ if (!activeInfo) {
4465
+ throw new Error("activeInfo");
4466
+ }
4467
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
4468
+ blockInfo.uniforms.push({
4469
+ name: activeInfo.name,
4470
+ format,
4471
+ type: uniformType[i],
4472
+ arrayLength: uniformArrayLength[i],
4473
+ byteOffset: uniformOffset[i],
4474
+ byteStride: uniformStride[i]
4475
+ // matrixStride: uniformStride[i],
4476
+ // rowMajor: uniformRowMajor[i]
4477
+ });
4478
+ }
4479
+ }
4480
+ uniformBlocks.push(blockInfo);
3779
4481
  }
4482
+ uniformBlocks.sort((a, b) => a.location - b.location);
4483
+ return uniformBlocks;
3780
4484
  }
3781
- function getGLPrimitive(topology) {
3782
- switch (topology) {
3783
- case "point-list":
3784
- return 0;
3785
- case "line-list":
3786
- return 1;
3787
- case "line-strip":
3788
- return 1;
3789
- case "triangle-list":
3790
- return 4;
3791
- case "triangle-strip":
3792
- return 4;
3793
- default:
3794
- throw new Error(topology);
4485
+ function parseUniformName(name) {
4486
+ if (name[name.length - 1] !== "]") {
4487
+ return {
4488
+ name,
4489
+ length: 1,
4490
+ isArray: false
4491
+ };
3795
4492
  }
4493
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
4494
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
4495
+ const uniformName = (0, import_core18.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
4496
+ return {
4497
+ name: uniformName,
4498
+ // TODO - is this a bug, shouldn't we return the value?
4499
+ length: matches?.[2] ? 1 : 0,
4500
+ isArray: Boolean(matches?.[2])
4501
+ };
3796
4502
  }
3797
- var init_webgl_topology_utils = __esm({
3798
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
4503
+ var import_core18;
4504
+ var init_get_shader_layout_from_glsl = __esm({
4505
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
4506
+ import_core18 = __toESM(require_core2(), 1);
4507
+ init_webgl_shadertypes();
3799
4508
  }
3800
4509
  });
3801
4510
 
3802
- // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3803
- function mergeShaderLayout(baseLayout, overrideLayout) {
3804
- const mergedLayout = {
3805
- ...baseLayout,
3806
- attributes: baseLayout.attributes.map((attribute) => ({ ...attribute }))
3807
- };
3808
- for (const attribute of overrideLayout?.attributes || []) {
3809
- const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3810
- if (!baseAttribute) {
3811
- import_core16.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3812
- } else {
3813
- baseAttribute.type = attribute.type || baseAttribute.type;
3814
- baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3815
- }
3816
- }
3817
- return mergedLayout;
3818
- }
3819
- var import_core16, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3820
- var init_webgl_render_pipeline = __esm({
3821
- "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3822
- import_core16 = __toESM(require_core2(), 1);
4511
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js
4512
+ var import_core19, LOG_PROGRAM_PERF_PRIORITY, WEBGLSharedRenderPipeline;
4513
+ var init_webgl_shared_render_pipeline = __esm({
4514
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js"() {
4515
+ import_core19 = __toESM(require_core2(), 1);
3823
4516
  init_get_shader_layout_from_glsl();
3824
- init_device_parameters();
3825
- init_set_uniform();
3826
- init_webgl_buffer();
3827
- init_webgl_framebuffer();
3828
- init_webgl_texture();
3829
- init_webgl_texture_view();
3830
- init_webgl_topology_utils();
4517
+ init_webgl_shadertypes();
3831
4518
  LOG_PROGRAM_PERF_PRIORITY = 4;
3832
- WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3833
- /** The WebGL device that created this render pipeline */
4519
+ WEBGLSharedRenderPipeline = class extends import_core19.SharedRenderPipeline {
3834
4520
  device;
3835
- /** Handle to underlying WebGL program */
3836
4521
  handle;
3837
- /** vertex shader */
3838
4522
  vs;
3839
- /** fragment shader */
3840
4523
  fs;
3841
- /** The layout extracted from shader by WebGL introspection APIs */
3842
- introspectedLayout;
3843
- /** Uniforms set on this model */
3844
- uniforms = {};
3845
- /** Bindings set on this model */
3846
- bindings = {};
3847
- /** WebGL varyings */
3848
- varyings = null;
3849
- _uniformCount = 0;
3850
- _uniformSetters = {};
3851
- // TODO are these used?
3852
- get [Symbol.toStringTag]() {
3853
- return "WEBGLRenderPipeline";
3854
- }
4524
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4525
+ linkStatus = "pending";
3855
4526
  constructor(device, props) {
3856
4527
  super(device, props);
3857
4528
  this.device = device;
3858
- this.handle = this.props.handle || this.device.gl.createProgram();
3859
- this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4529
+ this.handle = props.handle || this.device.gl.createProgram();
3860
4530
  this.vs = props.vs;
3861
4531
  this.fs = props.fs;
3862
- const { varyings, bufferMode = 35981 } = props;
3863
- if (varyings && varyings.length > 0) {
3864
- this.varyings = varyings;
3865
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4532
+ if (props.varyings && props.varyings.length > 0) {
4533
+ this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
3866
4534
  }
3867
4535
  this._linkShaders();
3868
- import_core16.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4536
+ import_core19.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3869
4537
  this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3870
- import_core16.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3871
- this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4538
+ import_core19.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3872
4539
  }
3873
4540
  destroy() {
3874
- if (this.handle) {
3875
- this.device.gl.useProgram(null);
3876
- this.device.gl.deleteProgram(this.handle);
3877
- this.destroyed = true;
3878
- this.handle.destroyed = true;
3879
- this.handle = null;
3880
- }
3881
- }
3882
- /**
3883
- * Bindings include: textures, samplers and uniform buffers
3884
- * @todo needed for portable model
3885
- */
3886
- setBindings(bindings, options) {
3887
- for (const [name, value] of Object.entries(bindings)) {
3888
- const binding = this.shaderLayout.bindings.find((binding_) => binding_.name === name) || this.shaderLayout.bindings.find((binding_) => binding_.name === `${name}Uniforms`);
3889
- if (!binding) {
3890
- const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
3891
- if (!options?.disableWarnings) {
3892
- import_core16.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
3893
- }
3894
- continue;
3895
- }
3896
- if (!value) {
3897
- import_core16.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
3898
- }
3899
- switch (binding.type) {
3900
- case "uniform":
3901
- if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
3902
- throw new Error("buffer value");
3903
- }
3904
- break;
3905
- case "texture":
3906
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3907
- throw new Error(`${this} Bad texture binding for ${name}`);
3908
- }
3909
- break;
3910
- case "sampler":
3911
- import_core16.log.warn(`Ignoring sampler ${name}`)();
3912
- break;
3913
- default:
3914
- throw new Error(binding.type);
3915
- }
3916
- this.bindings[name] = value;
3917
- }
3918
- }
3919
- /** @todo needed for portable model
3920
- * @note The WebGL API is offers many ways to draw things
3921
- * This function unifies those ways into a single call using common parameters with sane defaults
3922
- */
3923
- draw(options) {
3924
- const {
3925
- renderPass,
3926
- parameters = this.props.parameters,
3927
- topology = this.props.topology,
3928
- vertexArray,
3929
- vertexCount,
3930
- // indexCount,
3931
- instanceCount,
3932
- isInstanced = false,
3933
- firstVertex = 0,
3934
- // firstIndex,
3935
- // firstInstance,
3936
- // baseVertex,
3937
- transformFeedback
3938
- } = options;
3939
- const glDrawMode = getGLDrawMode(topology);
3940
- const isIndexed = Boolean(vertexArray.indexBuffer);
3941
- const glIndexType = vertexArray.indexBuffer?.glIndexType;
3942
- if (this.linkStatus !== "success") {
3943
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
3944
- return false;
3945
- }
3946
- if (!this._areTexturesRenderable()) {
3947
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
3948
- return false;
3949
- }
3950
- this.device.gl.useProgram(this.handle);
3951
- vertexArray.bindBeforeRender(renderPass);
3952
- if (transformFeedback) {
3953
- transformFeedback.begin(this.props.topology);
4541
+ if (this.destroyed) {
4542
+ return;
3954
4543
  }
3955
- this._applyBindings();
3956
- this._applyUniforms();
3957
- const webglRenderPass = renderPass;
3958
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
3959
- if (isIndexed && isInstanced) {
3960
- this.device.gl.drawElementsInstanced(
3961
- glDrawMode,
3962
- vertexCount || 0,
3963
- // indexCount?
3964
- glIndexType,
3965
- firstVertex,
3966
- instanceCount || 0
3967
- );
3968
- } else if (isIndexed) {
3969
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
3970
- } else if (isInstanced) {
3971
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
3972
- } else {
3973
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
3974
- }
3975
- if (transformFeedback) {
3976
- transformFeedback.end();
3977
- }
3978
- });
3979
- vertexArray.unbindAfterRender(renderPass);
3980
- return true;
4544
+ this.device.gl.useProgram(null);
4545
+ this.device.gl.deleteProgram(this.handle);
4546
+ this.handle.destroyed = true;
4547
+ this.destroyResource();
3981
4548
  }
3982
- // PRIVATE METHODS
3983
- // setAttributes(attributes: Record<string, Buffer>): void {}
3984
- // setBindings(bindings: Record<string, Binding>): void {}
3985
4549
  async _linkShaders() {
3986
4550
  const { gl } = this.device;
3987
4551
  gl.attachShader(this.handle, this.vs.handle);
3988
4552
  gl.attachShader(this.handle, this.fs.handle);
3989
- import_core16.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4553
+ import_core19.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3990
4554
  gl.linkProgram(this.handle);
3991
- import_core16.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3992
- if (import_core16.log.level === 0) {
3993
- }
4555
+ import_core19.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
3994
4556
  if (!this.device.features.has("compilation-status-async-webgl")) {
3995
4557
  const status2 = this._getLinkStatus();
3996
4558
  this._reportLinkStatus(status2);
3997
4559
  return;
3998
4560
  }
3999
- import_core16.log.once(1, "RenderPipeline linking is asynchronous")();
4561
+ import_core19.log.once(1, "RenderPipeline linking is asynchronous")();
4000
4562
  await this._waitForLinkComplete();
4001
- import_core16.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4563
+ import_core19.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4002
4564
  const status = this._getLinkStatus();
4003
4565
  this._reportLinkStatus(status);
4004
4566
  }
4005
- /** Report link status. First, check for shader compilation failures if linking fails */
4006
4567
  async _reportLinkStatus(status) {
4007
4568
  switch (status) {
4008
4569
  case "success":
@@ -4036,11 +4597,6 @@ ${source}`;
4036
4597
  this.device.debug();
4037
4598
  }
4038
4599
  }
4039
- /**
4040
- * Get the shader compilation status
4041
- * TODO - Load log even when no error reported, to catch warnings?
4042
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4043
- */
4044
4600
  _getLinkStatus() {
4045
4601
  const { gl } = this.device;
4046
4602
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -4048,6 +4604,7 @@ ${source}`;
4048
4604
  this.linkStatus = "error";
4049
4605
  return "link-error";
4050
4606
  }
4607
+ this._initializeSamplerUniforms();
4051
4608
  gl.validateProgram(this.handle);
4052
4609
  const validated = gl.getProgramParameter(this.handle, 35715);
4053
4610
  if (!validated) {
@@ -4057,7 +4614,33 @@ ${source}`;
4057
4614
  this.linkStatus = "success";
4058
4615
  return "success";
4059
4616
  }
4060
- /** Use KHR_parallel_shader_compile extension if available */
4617
+ _initializeSamplerUniforms() {
4618
+ const { gl } = this.device;
4619
+ gl.useProgram(this.handle);
4620
+ let textureUnit = 0;
4621
+ const uniformCount = gl.getProgramParameter(this.handle, 35718);
4622
+ for (let uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) {
4623
+ const activeInfo = gl.getActiveUniform(this.handle, uniformIndex);
4624
+ if (activeInfo && isGLSamplerType(activeInfo.type)) {
4625
+ const isArray3 = activeInfo.name.endsWith("[0]");
4626
+ const uniformName = isArray3 ? activeInfo.name.slice(0, -3) : activeInfo.name;
4627
+ const location = gl.getUniformLocation(this.handle, uniformName);
4628
+ if (location !== null) {
4629
+ textureUnit = this._assignSamplerUniform(location, activeInfo, isArray3, textureUnit);
4630
+ }
4631
+ }
4632
+ }
4633
+ }
4634
+ _assignSamplerUniform(location, activeInfo, isArray3, textureUnit) {
4635
+ const { gl } = this.device;
4636
+ if (isArray3 && activeInfo.size > 1) {
4637
+ const textureUnits = Int32Array.from({ length: activeInfo.size }, (_, arrayIndex) => textureUnit + arrayIndex);
4638
+ gl.uniform1iv(location, textureUnits);
4639
+ return textureUnit + activeInfo.size;
4640
+ }
4641
+ gl.uniform1i(location, textureUnit);
4642
+ return textureUnit + 1;
4643
+ }
4061
4644
  async _waitForLinkComplete() {
4062
4645
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4063
4646
  const DELAY_MS = 10;
@@ -4074,99 +4657,6 @@ ${source}`;
4074
4657
  await waitMs(DELAY_MS);
4075
4658
  }
4076
4659
  }
4077
- /**
4078
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4079
- * Update a texture if needed (e.g. from video)
4080
- * Note: This is currently done before every draw call
4081
- */
4082
- _areTexturesRenderable() {
4083
- let texturesRenderable = true;
4084
- for (const bindingInfo of this.shaderLayout.bindings) {
4085
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4086
- import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4087
- texturesRenderable = false;
4088
- }
4089
- }
4090
- return texturesRenderable;
4091
- }
4092
- /** Apply any bindings (before each draw call) */
4093
- _applyBindings() {
4094
- if (this.linkStatus !== "success") {
4095
- return;
4096
- }
4097
- const { gl } = this.device;
4098
- gl.useProgram(this.handle);
4099
- let textureUnit = 0;
4100
- let uniformBufferIndex = 0;
4101
- for (const binding of this.shaderLayout.bindings) {
4102
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4103
- if (!value) {
4104
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4105
- }
4106
- switch (binding.type) {
4107
- case "uniform":
4108
- const { name } = binding;
4109
- const location = gl.getUniformBlockIndex(this.handle, name);
4110
- if (location === 4294967295) {
4111
- throw new Error(`Invalid uniform block name ${name}`);
4112
- }
4113
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
4114
- if (value instanceof WEBGLBuffer) {
4115
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4116
- } else {
4117
- gl.bindBufferRange(
4118
- 35345,
4119
- uniformBufferIndex,
4120
- // @ts-expect-error
4121
- value.buffer.handle,
4122
- // @ts-expect-error
4123
- value.offset || 0,
4124
- // @ts-expect-error
4125
- value.size || value.buffer.byteLength - value.offset
4126
- );
4127
- }
4128
- uniformBufferIndex += 1;
4129
- break;
4130
- case "texture":
4131
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4132
- throw new Error("texture");
4133
- }
4134
- let texture;
4135
- if (value instanceof WEBGLTextureView) {
4136
- texture = value.texture;
4137
- } else if (value instanceof WEBGLTexture) {
4138
- texture = value;
4139
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4140
- import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4141
- texture = value.colorAttachments[0].texture;
4142
- } else {
4143
- throw new Error("No texture");
4144
- }
4145
- gl.activeTexture(33984 + textureUnit);
4146
- gl.bindTexture(texture.glTarget, texture.handle);
4147
- textureUnit += 1;
4148
- break;
4149
- case "sampler":
4150
- break;
4151
- case "storage":
4152
- case "read-only-storage":
4153
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4154
- }
4155
- }
4156
- }
4157
- /**
4158
- * Due to program sharing, uniforms need to be reset before every draw call
4159
- * (though caching will avoid redundant WebGL calls)
4160
- */
4161
- _applyUniforms() {
4162
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4163
- const { name, location, type, textureUnit } = uniformLayout;
4164
- const value = this.uniforms[name] ?? textureUnit;
4165
- if (value !== void 0) {
4166
- setUniform(this.device.gl, location, type, value);
4167
- }
4168
- }
4169
- }
4170
4660
  };
4171
4661
  }
4172
4662
  });
@@ -4198,7 +4688,7 @@ ${source}`;
4198
4688
  height = options.sourceTexture.height,
4199
4689
  depthOrArrayLayers = 0,
4200
4690
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
4201
- origin = [0, 0],
4691
+ origin = [0, 0, 0],
4202
4692
  /** Destination buffer */
4203
4693
  destinationBuffer,
4204
4694
  /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
@@ -4227,7 +4717,8 @@ ${source}`;
4227
4717
  const webglBuffer = destinationBuffer;
4228
4718
  const sourceWidth = width || framebuffer.width;
4229
4719
  const sourceHeight = height || framebuffer.height;
4230
- const sourceParams = getTextureFormatWebGL(framebuffer.colorAttachments[0].texture.props.format);
4720
+ const colorAttachment0 = (0, import_core20.assertDefined)(framebuffer.colorAttachments[0]);
4721
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
4231
4722
  const sourceFormat = sourceParams.format;
4232
4723
  const sourceType = sourceParams.type;
4233
4724
  device.gl.bindBuffer(35051, webglBuffer.handle);
@@ -4254,7 +4745,7 @@ ${source}`;
4254
4745
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
4255
4746
  origin = [0, 0],
4256
4747
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
4257
- destinationOrigin = [0, 0],
4748
+ destinationOrigin = [0, 0, 0],
4258
4749
  /** Texture to copy to/from. */
4259
4750
  destinationTexture
4260
4751
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -4270,7 +4761,7 @@ ${source}`;
4270
4761
  // depthOrArrayLayers = 0
4271
4762
  } = options;
4272
4763
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
4273
- const [sourceX, sourceY] = origin;
4764
+ const [sourceX = 0, sourceY = 0] = origin;
4274
4765
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
4275
4766
  const prevHandle = device.gl.bindFramebuffer(36160, framebuffer.handle);
4276
4767
  let texture;
@@ -4304,7 +4795,7 @@ ${source}`;
4304
4795
  }
4305
4796
  }
4306
4797
  function getFramebuffer(source) {
4307
- if (source instanceof import_core17.Texture) {
4798
+ if (source instanceof import_core20.Texture) {
4308
4799
  const { width, height, id } = source;
4309
4800
  const framebuffer = source.device.createFramebuffer({
4310
4801
  id: `framebuffer-for-${id}`,
@@ -4316,18 +4807,18 @@ ${source}`;
4316
4807
  }
4317
4808
  return { framebuffer: source, destroyFramebuffer: false };
4318
4809
  }
4319
- var import_core17, WEBGLCommandBuffer;
4810
+ var import_core20, WEBGLCommandBuffer;
4320
4811
  var init_webgl_command_buffer = __esm({
4321
4812
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-buffer.js"() {
4322
- import_core17 = __toESM(require_core2(), 1);
4813
+ import_core20 = __toESM(require_core2(), 1);
4323
4814
  init_webgl_texture();
4324
4815
  init_webgl_texture_table();
4325
- WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
4816
+ WEBGLCommandBuffer = class extends import_core20.CommandBuffer {
4326
4817
  device;
4327
4818
  handle = null;
4328
4819
  commands = [];
4329
- constructor(device) {
4330
- super(device, {});
4820
+ constructor(device, props = {}) {
4821
+ super(device, props);
4331
4822
  this.device = device;
4332
4823
  }
4333
4824
  _executeCommands(commands = this.commands) {
@@ -4355,14 +4846,14 @@ ${source}`;
4355
4846
  });
4356
4847
 
4357
4848
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js
4358
- var import_core18, COLOR_CHANNELS, WEBGLRenderPass;
4849
+ var import_core21, COLOR_CHANNELS, WEBGLRenderPass;
4359
4850
  var init_webgl_render_pass = __esm({
4360
4851
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js"() {
4361
- import_core18 = __toESM(require_core2(), 1);
4852
+ import_core21 = __toESM(require_core2(), 1);
4362
4853
  init_with_parameters();
4363
4854
  init_unified_parameter_api();
4364
4855
  COLOR_CHANNELS = [1, 2, 4, 8];
4365
- WEBGLRenderPass = class extends import_core18.RenderPass {
4856
+ WEBGLRenderPass = class extends import_core21.RenderPass {
4366
4857
  device;
4367
4858
  handle = null;
4368
4859
  /** Parameters that should be applied before each draw call */
@@ -4370,6 +4861,9 @@ ${source}`;
4370
4861
  constructor(device, props) {
4371
4862
  super(device, props);
4372
4863
  this.device = device;
4864
+ if (!props?.framebuffer) {
4865
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4866
+ }
4373
4867
  let viewport;
4374
4868
  if (!props?.parameters?.viewport) {
4375
4869
  if (props?.framebuffer) {
@@ -4386,13 +4880,25 @@ ${source}`;
4386
4880
  if (this.props.framebuffer && webglFramebuffer?.handle) {
4387
4881
  const drawBuffers = this.props.framebuffer.colorAttachments.map((_, i) => 36064 + i);
4388
4882
  this.device.gl.drawBuffers(drawBuffers);
4389
- } else {
4883
+ } else if (!this.props.framebuffer) {
4390
4884
  this.device.gl.drawBuffers([1029]);
4391
4885
  }
4392
4886
  this.clear();
4887
+ if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== void 0) {
4888
+ const webglQuerySet = this.props.timestampQuerySet;
4889
+ webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
4890
+ }
4393
4891
  }
4394
4892
  end() {
4893
+ if (this.destroyed) {
4894
+ return;
4895
+ }
4896
+ if (this.props.timestampQuerySet && this.props.endTimestampIndex !== void 0) {
4897
+ const webglQuerySet = this.props.timestampQuerySet;
4898
+ webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
4899
+ }
4395
4900
  this.device.popState();
4901
+ this.destroy();
4396
4902
  }
4397
4903
  pushDebugGroup(groupLabel) {
4398
4904
  }
@@ -4432,9 +4938,9 @@ ${source}`;
4432
4938
  if (parameters.blendConstant) {
4433
4939
  glParameters.blendColor = parameters.blendConstant;
4434
4940
  }
4435
- if (parameters.stencilReference) {
4436
- console.warn("RenderPassParameters.stencilReference not yet implemented in WebGL");
4941
+ if (parameters.stencilReference !== void 0) {
4437
4942
  glParameters[2967] = parameters.stencilReference;
4943
+ glParameters[36003] = parameters.stencilReference;
4438
4944
  }
4439
4945
  if ("colorMask" in parameters) {
4440
4946
  glParameters.colorMask = COLOR_CHANNELS.map((channel) => Boolean(channel & parameters.colorMask));
@@ -4512,30 +5018,38 @@ ${source}`;
4512
5018
  });
4513
5019
 
4514
5020
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js
4515
- var import_core19, WEBGLCommandEncoder;
5021
+ var import_core22, WEBGLCommandEncoder;
4516
5022
  var init_webgl_command_encoder = __esm({
4517
5023
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js"() {
4518
- import_core19 = __toESM(require_core2(), 1);
5024
+ import_core22 = __toESM(require_core2(), 1);
4519
5025
  init_webgl_command_buffer();
4520
5026
  init_webgl_render_pass();
4521
- WEBGLCommandEncoder = class extends import_core19.CommandEncoder {
5027
+ WEBGLCommandEncoder = class extends import_core22.CommandEncoder {
4522
5028
  device;
4523
5029
  handle = null;
4524
5030
  commandBuffer;
4525
5031
  constructor(device, props) {
4526
5032
  super(device, props);
4527
5033
  this.device = device;
4528
- this.commandBuffer = new WEBGLCommandBuffer(device);
5034
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5035
+ id: `${this.props.id}-command-buffer`
5036
+ });
4529
5037
  }
4530
5038
  destroy() {
5039
+ this.destroyResource();
4531
5040
  }
4532
- finish() {
5041
+ finish(props) {
5042
+ if (props?.id && this.commandBuffer.id !== props.id) {
5043
+ this.commandBuffer.id = props.id;
5044
+ this.commandBuffer.props.id = props.id;
5045
+ }
5046
+ this.destroy();
4533
5047
  return this.commandBuffer;
4534
5048
  }
4535
- beginRenderPass(props) {
4536
- return new WEBGLRenderPass(this.device, props);
5049
+ beginRenderPass(props = {}) {
5050
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4537
5051
  }
4538
- beginComputePass(props) {
5052
+ beginComputePass(props = {}) {
4539
5053
  throw new Error("ComputePass not supported in WebGL");
4540
5054
  }
4541
5055
  copyBufferToBuffer(options) {
@@ -4561,6 +5075,10 @@ ${source}`;
4561
5075
  }
4562
5076
  resolveQuerySet(querySet, destination, options) {
4563
5077
  }
5078
+ writeTimestamp(querySet, queryIndex) {
5079
+ const webglQuerySet = querySet;
5080
+ webglQuerySet.writeTimestamp(queryIndex);
5081
+ }
4564
5082
  };
4565
5083
  }
4566
5084
  });
@@ -4572,7 +5090,7 @@ ${source}`;
4572
5090
  const total = count * length;
4573
5091
  let copied = 0;
4574
5092
  for (let i = start; copied < length; copied++) {
4575
- target2[i++] = source[copied];
5093
+ target2[i++] = source[copied] ?? 0;
4576
5094
  }
4577
5095
  while (copied < total) {
4578
5096
  if (copied < total - copied) {
@@ -4608,14 +5126,14 @@ ${source}`;
4608
5126
  }
4609
5127
  return true;
4610
5128
  }
4611
- var import_core20, WEBGLVertexArray;
5129
+ var import_core23, WEBGLVertexArray;
4612
5130
  var init_webgl_vertex_array = __esm({
4613
5131
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-vertex-array.js"() {
4614
- import_core20 = __toESM(require_core2(), 1);
5132
+ import_core23 = __toESM(require_core2(), 1);
4615
5133
  init_dist2();
4616
5134
  init_webgl_vertex_formats();
4617
5135
  init_fill_array();
4618
- WEBGLVertexArray = class extends import_core20.VertexArray {
5136
+ WEBGLVertexArray = class extends import_core23.VertexArray {
4619
5137
  get [Symbol.toStringTag]() {
4620
5138
  return "VertexArray";
4621
5139
  }
@@ -4781,7 +5299,7 @@ ${source}`;
4781
5299
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4782
5300
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4783
5301
  if (updateNeeded) {
4784
- const typedArray = (0, import_core20.getScratchArray)(value.constructor, length);
5302
+ const typedArray = (0, import_core23.getScratchArray)(value.constructor, length);
4785
5303
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4786
5304
  this.buffer.write(typedArray);
4787
5305
  this.bufferValue = value;
@@ -4799,13 +5317,13 @@ ${source}`;
4799
5317
  }
4800
5318
  return /^\d+$/.test(value);
4801
5319
  }
4802
- var import_core21, WEBGLTransformFeedback;
5320
+ var import_core24, WEBGLTransformFeedback;
4803
5321
  var init_webgl_transform_feedback = __esm({
4804
5322
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-transform-feedback.js"() {
4805
- import_core21 = __toESM(require_core2(), 1);
5323
+ import_core24 = __toESM(require_core2(), 1);
4806
5324
  init_dist3();
4807
5325
  init_webgl_topology_utils();
4808
- WEBGLTransformFeedback = class extends import_core21.TransformFeedback {
5326
+ WEBGLTransformFeedback = class extends import_core24.TransformFeedback {
4809
5327
  device;
4810
5328
  gl;
4811
5329
  handle;
@@ -4858,8 +5376,8 @@ ${source}`;
4858
5376
  this.buffers = {};
4859
5377
  this.unusedBuffers = {};
4860
5378
  this.bind(() => {
4861
- for (const bufferName in buffers) {
4862
- this.setBuffer(bufferName, buffers[bufferName]);
5379
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
5380
+ this.setBuffer(bufferName, buffer);
4863
5381
  }
4864
5382
  });
4865
5383
  }
@@ -4868,7 +5386,7 @@ ${source}`;
4868
5386
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
4869
5387
  if (location < 0) {
4870
5388
  this.unusedBuffers[locationOrName] = buffer;
4871
- import_core21.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5389
+ import_core24.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
4872
5390
  return;
4873
5391
  }
4874
5392
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -4881,7 +5399,7 @@ ${source}`;
4881
5399
  return this.buffers[locationOrName] || null;
4882
5400
  }
4883
5401
  const location = this._getVaryingIndex(locationOrName);
4884
- return location >= 0 ? this.buffers[location] : null;
5402
+ return this.buffers[location] ?? null;
4885
5403
  }
4886
5404
  bind(funcOrHandle = this.handle) {
4887
5405
  if (typeof funcOrHandle !== "function") {
@@ -4928,8 +5446,8 @@ ${source}`;
4928
5446
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
4929
5447
  */
4930
5448
  _bindBuffers() {
4931
- for (const bufferIndex in this.buffers) {
4932
- const { buffer, byteLength, byteOffset } = this._getBufferRange(this.buffers[bufferIndex]);
5449
+ for (const [bufferIndex, bufferEntry] of Object.entries(this.buffers)) {
5450
+ const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferEntry);
4933
5451
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
4934
5452
  }
4935
5453
  }
@@ -4951,138 +5469,281 @@ ${source}`;
4951
5469
  });
4952
5470
 
4953
5471
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js
4954
- var import_core22, WEBGLQuerySet;
5472
+ var import_core25, WEBGLQuerySet;
4955
5473
  var init_webgl_query_set = __esm({
4956
5474
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js"() {
4957
- import_core22 = __toESM(require_core2(), 1);
4958
- WEBGLQuerySet = class extends import_core22.QuerySet {
5475
+ import_core25 = __toESM(require_core2(), 1);
5476
+ WEBGLQuerySet = class extends import_core25.QuerySet {
4959
5477
  device;
4960
5478
  handle;
4961
- target = null;
4962
- _queryPending = false;
4963
- _pollingPromise = null;
5479
+ _timestampPairs = [];
5480
+ _occlusionQuery = null;
5481
+ _occlusionActive = false;
4964
5482
  get [Symbol.toStringTag]() {
4965
- return "Query";
5483
+ return "QuerySet";
4966
5484
  }
4967
- // Create a query class
4968
5485
  constructor(device, props) {
4969
5486
  super(device, props);
4970
5487
  this.device = device;
4971
- if (props.count > 1) {
4972
- throw new Error("WebGL QuerySet can only have one value");
4973
- }
4974
- const handle = this.device.gl.createQuery();
4975
- if (!handle) {
4976
- throw new Error("WebGL query not supported");
5488
+ if (props.type === "timestamp") {
5489
+ if (props.count < 2) {
5490
+ throw new Error("Timestamp QuerySet requires at least two query slots");
5491
+ }
5492
+ this._timestampPairs = new Array(Math.ceil(props.count / 2)).fill(null).map(() => ({ activeQuery: null, completedQueries: [] }));
5493
+ this.handle = null;
5494
+ } else {
5495
+ if (props.count > 1) {
5496
+ throw new Error("WebGL occlusion QuerySet can only have one value");
5497
+ }
5498
+ const handle = this.device.gl.createQuery();
5499
+ if (!handle) {
5500
+ throw new Error("WebGL query not supported");
5501
+ }
5502
+ this.handle = handle;
4977
5503
  }
4978
- this.handle = handle;
4979
5504
  Object.seal(this);
4980
5505
  }
4981
5506
  destroy() {
4982
- this.device.gl.deleteQuery(this.handle);
5507
+ if (this.destroyed) {
5508
+ return;
5509
+ }
5510
+ if (this.handle) {
5511
+ this.device.gl.deleteQuery(this.handle);
5512
+ }
5513
+ for (const pair of this._timestampPairs) {
5514
+ if (pair.activeQuery) {
5515
+ this.device.gl.deleteQuery(pair.activeQuery.handle);
5516
+ }
5517
+ for (const query of pair.completedQueries) {
5518
+ this.device.gl.deleteQuery(query.handle);
5519
+ }
5520
+ }
5521
+ if (this._occlusionQuery) {
5522
+ this.device.gl.deleteQuery(this._occlusionQuery.handle);
5523
+ }
5524
+ this.destroyResource();
4983
5525
  }
4984
- // FOR RENDER PASS AND COMMAND ENCODER
4985
- /**
4986
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
4987
- * Measures GPU time delta between this call and a matching `end` call in the
4988
- * GPU instruction stream.
4989
- */
4990
- beginTimestampQuery() {
4991
- return this._begin(35007);
5526
+ isResultAvailable(queryIndex) {
5527
+ if (this.props.type === "timestamp") {
5528
+ if (queryIndex === void 0) {
5529
+ return this._timestampPairs.some((_, pairIndex) => this._isTimestampPairAvailable(pairIndex));
5530
+ }
5531
+ return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
5532
+ }
5533
+ if (!this._occlusionQuery) {
5534
+ return false;
5535
+ }
5536
+ return this._pollQueryAvailability(this._occlusionQuery);
5537
+ }
5538
+ async readResults(options) {
5539
+ const firstQuery = options?.firstQuery || 0;
5540
+ const queryCount = options?.queryCount || this.props.count - firstQuery;
5541
+ this._validateRange(firstQuery, queryCount);
5542
+ if (this.props.type === "timestamp") {
5543
+ const results = new Array(queryCount).fill(0n);
5544
+ const startPairIndex = Math.floor(firstQuery / 2);
5545
+ const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
5546
+ for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
5547
+ const duration = await this._consumeTimestampPairResult(pairIndex);
5548
+ const beginSlot = pairIndex * 2;
5549
+ const endSlot = beginSlot + 1;
5550
+ if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
5551
+ results[beginSlot - firstQuery] = 0n;
5552
+ }
5553
+ if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
5554
+ results[endSlot - firstQuery] = duration;
5555
+ }
5556
+ }
5557
+ return results;
5558
+ }
5559
+ if (!this._occlusionQuery) {
5560
+ throw new Error("Occlusion query has not been started");
5561
+ }
5562
+ return [await this._consumeQueryResult(this._occlusionQuery)];
4992
5563
  }
4993
- endTimestampQuery() {
4994
- this._end();
5564
+ async readTimestampDuration(beginIndex, endIndex) {
5565
+ if (this.props.type !== "timestamp") {
5566
+ throw new Error("Timestamp durations require a timestamp QuerySet");
5567
+ }
5568
+ if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
5569
+ throw new Error("Timestamp duration range is out of bounds");
5570
+ }
5571
+ if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
5572
+ throw new Error("WebGL timestamp durations require adjacent even/odd query indices");
5573
+ }
5574
+ const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
5575
+ return Number(result) / 1e6;
4995
5576
  }
4996
- // Shortcut for occlusion queries
4997
- beginOcclusionQuery(options) {
4998
- return this._begin(options?.conservative ? 36202 : 35887);
5577
+ beginOcclusionQuery() {
5578
+ if (this.props.type !== "occlusion") {
5579
+ throw new Error("Occlusion queries require an occlusion QuerySet");
5580
+ }
5581
+ if (!this.handle) {
5582
+ throw new Error("WebGL occlusion query is not available");
5583
+ }
5584
+ if (this._occlusionActive) {
5585
+ throw new Error("Occlusion query is already active");
5586
+ }
5587
+ this.device.gl.beginQuery(35887, this.handle);
5588
+ this._occlusionQuery = {
5589
+ handle: this.handle,
5590
+ promise: null,
5591
+ result: null,
5592
+ disjoint: false
5593
+ };
5594
+ this._occlusionActive = true;
4999
5595
  }
5000
5596
  endOcclusionQuery() {
5001
- this._end();
5002
- }
5003
- // Shortcut for transformFeedbackQuery
5004
- beginTransformFeedbackQuery() {
5005
- return this._begin(35976);
5006
- }
5007
- endTransformFeedbackQuery() {
5008
- this._end();
5009
- }
5010
- async resolveQuery() {
5011
- const value = await this.pollQuery();
5012
- return [value];
5597
+ if (!this._occlusionActive) {
5598
+ throw new Error("Occlusion query is not active");
5599
+ }
5600
+ this.device.gl.endQuery(35887);
5601
+ this._occlusionActive = false;
5013
5602
  }
5014
- // PRIVATE METHODS
5015
- /**
5016
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5017
- * instance, `end()` must be called on that same instance before
5018
- * calling `begin()` on another query. While there can be multiple
5019
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5020
- * It is not possible to interleave or overlap `begin` and `end` calls.
5021
- */
5022
- _begin(target2) {
5023
- if (this._queryPending) {
5603
+ writeTimestamp(queryIndex) {
5604
+ if (this.props.type !== "timestamp") {
5605
+ throw new Error("Timestamp writes require a timestamp QuerySet");
5606
+ }
5607
+ const pairIndex = this._getTimestampPairIndex(queryIndex);
5608
+ const pair = this._timestampPairs[pairIndex];
5609
+ if (queryIndex % 2 === 0) {
5610
+ if (pair.activeQuery) {
5611
+ throw new Error("Timestamp query pair is already active");
5612
+ }
5613
+ const handle = this.device.gl.createQuery();
5614
+ if (!handle) {
5615
+ throw new Error("WebGL query not supported");
5616
+ }
5617
+ const query = {
5618
+ handle,
5619
+ promise: null,
5620
+ result: null,
5621
+ disjoint: false
5622
+ };
5623
+ this.device.gl.beginQuery(35007, handle);
5624
+ pair.activeQuery = query;
5024
5625
  return;
5025
5626
  }
5026
- this.target = target2;
5027
- this.device.gl.beginQuery(this.target, this.handle);
5028
- return;
5627
+ if (!pair.activeQuery) {
5628
+ throw new Error("Timestamp query pair was ended before it was started");
5629
+ }
5630
+ this.device.gl.endQuery(35007);
5631
+ pair.completedQueries.push(pair.activeQuery);
5632
+ pair.activeQuery = null;
5029
5633
  }
5030
- // ends the current query
5031
- _end() {
5032
- if (this._queryPending) {
5033
- return;
5634
+ _validateRange(firstQuery, queryCount) {
5635
+ if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
5636
+ throw new Error("Query read range is out of bounds");
5034
5637
  }
5035
- if (this.target) {
5036
- this.device.gl.endQuery(this.target);
5037
- this.target = null;
5038
- this._queryPending = true;
5638
+ }
5639
+ _getTimestampPairIndex(queryIndex) {
5640
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
5641
+ throw new Error("Query index is out of bounds");
5039
5642
  }
5040
- return;
5643
+ return Math.floor(queryIndex / 2);
5041
5644
  }
5042
- // Returns true if the query result is available
5043
- isResultAvailable() {
5044
- if (!this._queryPending) {
5645
+ _isTimestampPairAvailable(pairIndex) {
5646
+ const pair = this._timestampPairs[pairIndex];
5647
+ if (!pair || pair.completedQueries.length === 0) {
5045
5648
  return false;
5046
5649
  }
5047
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
5048
- if (resultAvailable) {
5049
- this._queryPending = false;
5050
- }
5051
- return resultAvailable;
5650
+ return this._pollQueryAvailability(pair.completedQueries[0]);
5052
5651
  }
5053
- // Timing query is disjoint, i.e. results are invalid
5054
- isTimerDisjoint() {
5055
- return this.device.gl.getParameter(36795);
5652
+ _pollQueryAvailability(query) {
5653
+ if (query.result !== null || query.disjoint) {
5654
+ return true;
5655
+ }
5656
+ const resultAvailable = this.device.gl.getQueryParameter(query.handle, 34919);
5657
+ if (!resultAvailable) {
5658
+ return false;
5659
+ }
5660
+ const isDisjoint = Boolean(this.device.gl.getParameter(36795));
5661
+ query.disjoint = isDisjoint;
5662
+ query.result = isDisjoint ? 0n : BigInt(this.device.gl.getQueryParameter(query.handle, 34918));
5663
+ return true;
5056
5664
  }
5057
- // Returns query result.
5058
- getResult() {
5059
- return this.device.gl.getQueryParameter(this.handle, 34918);
5665
+ async _consumeTimestampPairResult(pairIndex) {
5666
+ const pair = this._timestampPairs[pairIndex];
5667
+ if (!pair || pair.completedQueries.length === 0) {
5668
+ throw new Error("Timestamp query pair has no completed result");
5669
+ }
5670
+ const query = pair.completedQueries.shift();
5671
+ try {
5672
+ return await this._consumeQueryResult(query);
5673
+ } finally {
5674
+ this.device.gl.deleteQuery(query.handle);
5675
+ }
5060
5676
  }
5061
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5062
- getTimerMilliseconds() {
5063
- return this.getResult() / 1e6;
5677
+ _consumeQueryResult(query) {
5678
+ if (query.promise) {
5679
+ return query.promise;
5680
+ }
5681
+ query.promise = new Promise((resolve, reject) => {
5682
+ const poll = () => {
5683
+ if (!this._pollQueryAvailability(query)) {
5684
+ requestAnimationFrame(poll);
5685
+ return;
5686
+ }
5687
+ query.promise = null;
5688
+ if (query.disjoint) {
5689
+ reject(new Error("GPU timestamp query was invalidated by a disjoint event"));
5690
+ } else {
5691
+ resolve(query.result || 0n);
5692
+ }
5693
+ };
5694
+ poll();
5695
+ });
5696
+ return query.promise;
5064
5697
  }
5065
- // Polls the query
5066
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5067
- if (this._pollingPromise) {
5068
- return this._pollingPromise;
5698
+ };
5699
+ }
5700
+ });
5701
+
5702
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js
5703
+ var import_core26, WEBGLFence;
5704
+ var init_webgl_fence = __esm({
5705
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js"() {
5706
+ import_core26 = __toESM(require_core2(), 1);
5707
+ WEBGLFence = class extends import_core26.Fence {
5708
+ device;
5709
+ gl;
5710
+ handle;
5711
+ signaled;
5712
+ _signaled = false;
5713
+ constructor(device, props = {}) {
5714
+ super(device, {});
5715
+ this.device = device;
5716
+ this.gl = device.gl;
5717
+ const sync = this.props.handle || this.gl.fenceSync(this.gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
5718
+ if (!sync) {
5719
+ throw new Error("Failed to create WebGL fence");
5069
5720
  }
5070
- let counter = 0;
5071
- this._pollingPromise = new Promise((resolve, reject) => {
5721
+ this.handle = sync;
5722
+ this.signaled = new Promise((resolve) => {
5072
5723
  const poll = () => {
5073
- if (this.isResultAvailable()) {
5074
- resolve(this.getResult());
5075
- this._pollingPromise = null;
5076
- } else if (counter++ > limit) {
5077
- reject("Timed out");
5078
- this._pollingPromise = null;
5724
+ const status = this.gl.clientWaitSync(this.handle, 0, 0);
5725
+ if (status === this.gl.ALREADY_SIGNALED || status === this.gl.CONDITION_SATISFIED) {
5726
+ this._signaled = true;
5727
+ resolve();
5079
5728
  } else {
5080
- requestAnimationFrame(poll);
5729
+ setTimeout(poll, 1);
5081
5730
  }
5082
5731
  };
5083
- requestAnimationFrame(poll);
5732
+ poll();
5084
5733
  });
5085
- return this._pollingPromise;
5734
+ }
5735
+ isSignaled() {
5736
+ if (this._signaled) {
5737
+ return true;
5738
+ }
5739
+ const status = this.gl.getSyncParameter(this.handle, this.gl.SYNC_STATUS);
5740
+ this._signaled = status === this.gl.SIGNALED;
5741
+ return this._signaled;
5742
+ }
5743
+ destroy() {
5744
+ if (!this.destroyed) {
5745
+ this.gl.deleteSync(this.handle);
5746
+ }
5086
5747
  }
5087
5748
  };
5088
5749
  }
@@ -5133,34 +5794,6 @@ ${source}`;
5133
5794
  }
5134
5795
  });
5135
5796
 
5136
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
5137
- function convertGLDataTypeToDataType(type) {
5138
- return GL_DATA_TYPE_MAP[type];
5139
- }
5140
- var GL_DATA_TYPE_MAP;
5141
- var init_shader_formats = __esm({
5142
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js"() {
5143
- GL_DATA_TYPE_MAP = {
5144
- [5124]: "sint32",
5145
- [5125]: "uint32",
5146
- [5122]: "sint16",
5147
- [5123]: "uint16",
5148
- [5120]: "sint8",
5149
- [5121]: "uint8",
5150
- [5126]: "float32",
5151
- [5131]: "float16",
5152
- [33635]: "uint16",
5153
- [32819]: "uint16",
5154
- [32820]: "uint16",
5155
- [33640]: "uint32",
5156
- [35899]: "uint32",
5157
- [35902]: "uint32",
5158
- [34042]: "uint32",
5159
- [36269]: "uint32"
5160
- };
5161
- }
5162
- });
5163
-
5164
5797
  // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js
5165
5798
  function readPixelsToArray(source, options) {
5166
5799
  const {
@@ -5190,7 +5823,7 @@ ${source}`;
5190
5823
  sourceFormat ||= texture?.glFormat || 6408;
5191
5824
  sourceType ||= texture?.glType || 5121;
5192
5825
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5193
- const signedType = (0, import_core23.getDataType)(target2);
5826
+ const signedType = (0, import_core27.getDataType)(target2);
5194
5827
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5195
5828
  const prevHandle = gl.bindFramebuffer(36160, handle);
5196
5829
  gl.readBuffer(36064 + sourceAttachment);
@@ -5233,7 +5866,7 @@ ${source}`;
5233
5866
  return webglBufferTarget;
5234
5867
  }
5235
5868
  function getFramebuffer2(source) {
5236
- if (!(source instanceof import_core23.Framebuffer)) {
5869
+ if (!(source instanceof import_core27.Framebuffer)) {
5237
5870
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5238
5871
  }
5239
5872
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5255,14 +5888,14 @@ ${source}`;
5255
5888
  }
5256
5889
  glType ||= 5121;
5257
5890
  const shaderType = convertGLDataTypeToDataType(glType);
5258
- const ArrayType = (0, import_core23.getTypedArrayConstructor)(shaderType);
5891
+ const ArrayType = (0, import_core27.getTypedArrayConstructor)(shaderType);
5259
5892
  const components = glFormatToComponents(glFormat);
5260
5893
  return new ArrayType(width * height * components);
5261
5894
  }
5262
- var import_core23;
5895
+ var import_core27;
5263
5896
  var init_webgl_texture_utils = __esm({
5264
5897
  "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js"() {
5265
- import_core23 = __toESM(require_core2(), 1);
5898
+ import_core27 = __toESM(require_core2(), 1);
5266
5899
  init_webgl_shadertypes();
5267
5900
  init_format_utils();
5268
5901
  init_shader_formats();
@@ -5304,16 +5937,18 @@ ${source}`;
5304
5937
  }
5305
5938
  return true;
5306
5939
  }
5307
- var import_core24, WebGLDevice;
5940
+ var import_core28, WebGLDevice;
5308
5941
  var init_webgl_device = __esm({
5309
5942
  "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-device.js"() {
5310
- import_core24 = __toESM(require_core2(), 1);
5943
+ import_core28 = __toESM(require_core2(), 1);
5311
5944
  init_webgl_state_tracker();
5312
5945
  init_create_browser_context();
5946
+ init_webgl_context_data();
5313
5947
  init_webgl_device_info();
5314
5948
  init_webgl_device_features();
5315
5949
  init_webgl_device_limits();
5316
5950
  init_webgl_canvas_context();
5951
+ init_webgl_presentation_context();
5317
5952
  init_spector();
5318
5953
  init_webgl_developer_tools();
5319
5954
  init_webgl_texture_table();
@@ -5324,15 +5959,23 @@ ${source}`;
5324
5959
  init_webgl_texture();
5325
5960
  init_webgl_framebuffer();
5326
5961
  init_webgl_render_pipeline();
5962
+ init_webgl_shared_render_pipeline();
5327
5963
  init_webgl_command_encoder();
5328
5964
  init_webgl_vertex_array();
5329
5965
  init_webgl_transform_feedback();
5330
5966
  init_webgl_query_set();
5967
+ init_webgl_fence();
5331
5968
  init_webgl_texture_utils();
5332
5969
  init_unified_parameter_api();
5333
5970
  init_with_parameters();
5334
5971
  init_webgl_extensions();
5335
- WebGLDevice = class extends import_core24.Device {
5972
+ WebGLDevice = class extends import_core28.Device {
5973
+ static getDeviceFromContext(gl) {
5974
+ if (!gl) {
5975
+ return null;
5976
+ }
5977
+ return gl.luma?.device ?? null;
5978
+ }
5336
5979
  // Public `Device` API
5337
5980
  /** type of this device */
5338
5981
  type = "webgl";
@@ -5354,7 +5997,7 @@ ${source}`;
5354
5997
  // @ts-ignore TODO fix
5355
5998
  _constants;
5356
5999
  /** State used by luma.gl classes - TODO - not used? */
5357
- _extensions = {};
6000
+ extensions;
5358
6001
  _polyfilled = false;
5359
6002
  /** Instance of Spector.js (if initialized) */
5360
6003
  spectorJS;
@@ -5377,11 +6020,12 @@ ${source}`;
5377
6020
  }
5378
6021
  constructor(props) {
5379
6022
  super({ ...props, id: props.id || uid("webgl-device") });
5380
- const canvasContextProps = import_core24.Device._getCanvasContextProps(props);
6023
+ const canvasContextProps = import_core28.Device._getCanvasContextProps(props);
5381
6024
  if (!canvasContextProps) {
5382
6025
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5383
6026
  }
5384
- let device = canvasContextProps.canvas?.gl?.device;
6027
+ const existingContext = canvasContextProps.canvas?.gl ?? null;
6028
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5385
6029
  if (device) {
5386
6030
  throw new Error(`WebGL context already attached to device ${device.id}`);
5387
6031
  }
@@ -5396,6 +6040,9 @@ ${source}`;
5396
6040
  if (props.powerPreference !== void 0) {
5397
6041
  webglContextAttributes.powerPreference = props.powerPreference;
5398
6042
  }
6043
+ if (props.failIfMajorPerformanceCaveat !== void 0) {
6044
+ webglContextAttributes.failIfMajorPerformanceCaveat = props.failIfMajorPerformanceCaveat;
6045
+ }
5399
6046
  const externalGLContext = this.props._handle;
5400
6047
  const gl = externalGLContext || createBrowserContext(this.canvasContext.canvas, {
5401
6048
  onContextLost: (event) => this._resolveContextLost?.({
@@ -5408,10 +6055,11 @@ ${source}`;
5408
6055
  if (!gl) {
5409
6056
  throw new Error("WebGL context creation failed");
5410
6057
  }
5411
- device = gl.device;
6058
+ device = WebGLDevice.getDeviceFromContext(gl);
5412
6059
  if (device) {
5413
6060
  if (props._reuseDevices) {
5414
- import_core24.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6061
+ import_core28.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6062
+ this.canvasContext.destroy();
5415
6063
  device._reused = true;
5416
6064
  return device;
5417
6065
  }
@@ -5420,28 +6068,28 @@ ${source}`;
5420
6068
  this.handle = gl;
5421
6069
  this.gl = gl;
5422
6070
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5423
- this.gl.device = this;
5424
- this.gl._version = 2;
5425
- this.info = getDeviceInfo(this.gl, this._extensions);
6071
+ const contextData = getWebGLContextData(this.handle);
6072
+ contextData.device = this;
6073
+ this.extensions = contextData.extensions || (contextData.extensions = {});
6074
+ this.info = getDeviceInfo(this.gl, this.extensions);
5426
6075
  this.limits = new WebGLDeviceLimits(this.gl);
5427
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
6076
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5428
6077
  if (this.props._initializeFeatures) {
5429
6078
  this.features.initializeFeatures();
5430
6079
  }
5431
6080
  const glState = new WebGLStateTracker(this.gl, {
5432
- log: (...args) => import_core24.log.log(1, ...args)()
6081
+ log: (...args) => import_core28.log.log(1, ...args)()
5433
6082
  });
5434
6083
  glState.trackState(this.gl, { copyState: false });
5435
- const debugWebGL = props.debugWebGL || props.debug;
5436
- const traceWebGL = props.debugWebGL;
5437
- if (debugWebGL) {
5438
- this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
5439
- import_core24.log.warn("WebGL debug mode activated. Performance reduced.")();
5440
- if (props.debugWebGL) {
5441
- import_core24.log.level = Math.max(import_core24.log.level, 1);
5442
- }
6084
+ if (props.debug || props.debugWebGL) {
6085
+ this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
6086
+ import_core28.log.warn("WebGL debug mode activated. Performance reduced.")();
6087
+ }
6088
+ if (props.debugWebGL) {
6089
+ import_core28.log.level = Math.max(import_core28.log.level, 1);
5443
6090
  }
5444
6091
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6092
+ this.canvasContext._startObservers();
5445
6093
  }
5446
6094
  /**
5447
6095
  * Destroys the device
@@ -5454,20 +6102,22 @@ ${source}`;
5454
6102
  * browser API for destroying WebGL contexts.
5455
6103
  */
5456
6104
  destroy() {
6105
+ this.commandEncoder?.destroy();
5457
6106
  if (!this.props._reuseDevices && !this._reused) {
5458
- delete this.gl.device;
6107
+ const contextData = getWebGLContextData(this.handle);
6108
+ contextData.device = null;
5459
6109
  }
5460
6110
  }
5461
6111
  get isLost() {
5462
6112
  return this.gl.isContextLost();
5463
6113
  }
5464
6114
  // IMPLEMENTATION OF ABSTRACT DEVICE
5465
- getTextureByteAlignment() {
5466
- return 4;
5467
- }
5468
6115
  createCanvasContext(props) {
5469
6116
  throw new Error("WebGL only supports a single canvas");
5470
6117
  }
6118
+ createPresentationContext(props) {
6119
+ return new WebGLPresentationContext(this, props || {});
6120
+ }
5471
6121
  createBuffer(props) {
5472
6122
  const newProps = this._normalizeBufferProps(props);
5473
6123
  return new WEBGLBuffer(this, newProps);
@@ -5496,9 +6146,15 @@ ${source}`;
5496
6146
  createQuerySet(props) {
5497
6147
  return new WEBGLQuerySet(this, props);
5498
6148
  }
6149
+ createFence() {
6150
+ return new WEBGLFence(this);
6151
+ }
5499
6152
  createRenderPipeline(props) {
5500
6153
  return new WEBGLRenderPipeline(this, props);
5501
6154
  }
6155
+ _createSharedRenderPipelineWebGL(props) {
6156
+ return new WEBGLSharedRenderPipeline(this, props);
6157
+ }
5502
6158
  createComputePipeline(props) {
5503
6159
  throw new Error("ComputePipeline not supported in WebGL");
5504
6160
  }
@@ -5511,12 +6167,27 @@ ${source}`;
5511
6167
  * Chrome's offscreen canvas does not require gl.commit
5512
6168
  */
5513
6169
  submit(commandBuffer) {
6170
+ let submittedCommandEncoder = null;
5514
6171
  if (!commandBuffer) {
5515
- commandBuffer = this.commandEncoder.finish();
6172
+ submittedCommandEncoder = this.commandEncoder;
6173
+ commandBuffer = submittedCommandEncoder.finish();
5516
6174
  this.commandEncoder.destroy();
5517
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
6175
+ this.commandEncoder = this.createCommandEncoder({
6176
+ id: submittedCommandEncoder.props.id,
6177
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
6178
+ });
6179
+ }
6180
+ try {
6181
+ commandBuffer._executeCommands();
6182
+ if (submittedCommandEncoder) {
6183
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
6184
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
6185
+ }).catch(() => {
6186
+ });
6187
+ }
6188
+ } finally {
6189
+ commandBuffer.destroy();
5518
6190
  }
5519
- commandBuffer._executeCommands();
5520
6191
  }
5521
6192
  //
5522
6193
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5539,11 +6210,11 @@ ${source}`;
5539
6210
  return withGLParameters(this.gl, parameters, func);
5540
6211
  }
5541
6212
  resetWebGL() {
5542
- import_core24.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6213
+ import_core28.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5543
6214
  resetGLParameters(this.gl);
5544
6215
  }
5545
6216
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5546
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
6217
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5547
6218
  }
5548
6219
  //
5549
6220
  // WebGL-only API (not part of `Device` API)
@@ -5611,7 +6282,7 @@ ${source}`;
5611
6282
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5612
6283
  const currentConstant = this._constants[location];
5613
6284
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5614
- import_core24.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
6285
+ import_core28.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
5615
6286
  }
5616
6287
  this._constants[location] = constant;
5617
6288
  switch (constant.constructor) {
@@ -5630,8 +6301,8 @@ ${source}`;
5630
6301
  }
5631
6302
  /** Ensure extensions are only requested once */
5632
6303
  getExtension(name) {
5633
- getWebGLExtension(this.gl, name, this._extensions);
5634
- return this._extensions;
6304
+ getWebGLExtension(this.gl, name, this.extensions);
6305
+ return this.extensions;
5635
6306
  }
5636
6307
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
5637
6308
  /**
@@ -5955,12 +6626,12 @@ ${source}`;
5955
6626
  }
5956
6627
 
5957
6628
  // dist/commons.js
5958
- var import_core25 = __toESM(require_core(), 1);
6629
+ var import_core29 = __toESM(require_core(), 1);
5959
6630
  var import_engine = __toESM(require_engine(), 1);
5960
6631
  init_dist3();
5961
6632
  async function createDeckInstance(gl) {
5962
6633
  return new Promise((resolve) => {
5963
- const deckInstance = new import_core25.Deck({
6634
+ const deckInstance = new import_core29.Deck({
5964
6635
  // Input is handled by the ArcGIS API for JavaScript.
5965
6636
  controller: false,
5966
6637
  // We use the same WebGL context as the ArcGIS API for JavaScript.