@deck.gl/arcgis 9.3.0-alpha.1 → 9.3.0-alpha.3

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
  }
@@ -1427,7 +1447,7 @@ var __exports__ = (() => {
1427
1447
  }
1428
1448
  }
1429
1449
  }
1430
- const cache = gl.state && gl.state.cache;
1450
+ const cache = gl.lumaState?.cache;
1431
1451
  if (cache) {
1432
1452
  for (const key in compositeSetters) {
1433
1453
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -1547,7 +1567,7 @@ var __exports__ = (() => {
1547
1567
  init_webgl_parameter_tables();
1548
1568
  WebGLStateTracker = class {
1549
1569
  static get(gl) {
1550
- return gl.state;
1570
+ return gl.lumaState;
1551
1571
  }
1552
1572
  gl;
1553
1573
  program = null;
@@ -1585,7 +1605,7 @@ var __exports__ = (() => {
1585
1605
  throw new Error("WebGLStateTracker");
1586
1606
  }
1587
1607
  this.initialized = true;
1588
- this.gl.state = this;
1608
+ this.gl.lumaState = this;
1589
1609
  installProgramSpy(gl);
1590
1610
  for (const key in GL_HOOKED_SETTERS) {
1591
1611
  const setter = GL_HOOKED_SETTERS[key];
@@ -1645,13 +1665,11 @@ var __exports__ = (() => {
1645
1665
  if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1646
1666
  errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1647
1667
  }
1668
+ let softwareRenderer = false;
1648
1669
  if (!gl && allowSoftwareRenderer) {
1649
1670
  webglProps.failIfMajorPerformanceCaveat = false;
1650
1671
  gl = canvas.getContext("webgl2", webglProps);
1651
- if (gl) {
1652
- gl.luma ||= {};
1653
- gl.luma.softwareRenderer = true;
1654
- }
1672
+ softwareRenderer = true;
1655
1673
  }
1656
1674
  if (!gl) {
1657
1675
  gl = canvas.getContext("webgl", {});
@@ -1664,10 +1682,11 @@ var __exports__ = (() => {
1664
1682
  errorMessage ||= "Your browser does not support WebGL";
1665
1683
  throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1666
1684
  }
1685
+ const luma = getWebGLContextData(gl);
1686
+ luma.softwareRenderer = softwareRenderer;
1667
1687
  const { onContextLost, onContextRestored } = props;
1668
1688
  canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1669
1689
  canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1670
- gl.luma ||= {};
1671
1690
  return gl;
1672
1691
  } finally {
1673
1692
  canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
@@ -1675,6 +1694,7 @@ var __exports__ = (() => {
1675
1694
  }
1676
1695
  var init_create_browser_context = __esm({
1677
1696
  "../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js"() {
1697
+ init_webgl_context_data();
1678
1698
  }
1679
1699
  });
1680
1700
 
@@ -1751,6 +1771,8 @@ var __exports__ = (() => {
1751
1771
  }
1752
1772
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1753
1773
  switch (gpuVendor) {
1774
+ case "apple":
1775
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1754
1776
  case "intel":
1755
1777
  return "integrated";
1756
1778
  case "software":
@@ -1761,6 +1783,9 @@ var __exports__ = (() => {
1761
1783
  return "discrete";
1762
1784
  }
1763
1785
  }
1786
+ function isAppleSiliconGPU(vendor, renderer) {
1787
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1788
+ }
1764
1789
  var init_webgl_device_info = __esm({
1765
1790
  "../../node_modules/@luma.gl/webgl/dist/adapter/device-helpers/webgl-device-info.js"() {
1766
1791
  init_webgl_extensions();
@@ -1807,8 +1832,23 @@ var __exports__ = (() => {
1807
1832
  return feature in TEXTURE_FEATURES;
1808
1833
  }
1809
1834
  function checkTextureFeature(gl, feature, extensions) {
1810
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1811
- 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)));
1812
1852
  }
1813
1853
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1814
1854
  let supported = formatSupport.create;
@@ -1819,12 +1859,17 @@ var __exports__ = (() => {
1819
1859
  if (webglFormatInfo?.x) {
1820
1860
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1821
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);
1822
1867
  return {
1823
1868
  format: formatSupport.format,
1824
1869
  // @ts-ignore
1825
1870
  create: supported && formatSupport.create,
1826
1871
  // @ts-ignore
1827
- render: supported && formatSupport.render,
1872
+ render: renderable,
1828
1873
  // @ts-ignore
1829
1874
  filter: supported && formatSupport.filter,
1830
1875
  // @ts-ignore
@@ -1833,6 +1878,45 @@ var __exports__ = (() => {
1833
1878
  store: supported && formatSupport.store
1834
1879
  };
1835
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
+ }
1836
1920
  function getTextureFormatWebGL(format) {
1837
1921
  const formatData = WEBGL_TEXTURE_FORMATS[format];
1838
1922
  const webglFormat = convertTextureFormatToGL(format);
@@ -1888,7 +1972,7 @@ var __exports__ = (() => {
1888
1972
  }
1889
1973
  return webglFormat;
1890
1974
  }
1891
- 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;
1892
1976
  var init_webgl_texture_table = __esm({
1893
1977
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-texture-table.js"() {
1894
1978
  import_core4 = __toESM(require_core2(), 1);
@@ -1906,44 +1990,51 @@ var __exports__ = (() => {
1906
1990
  EXT_texture_norm16 = "EXT_texture_norm16";
1907
1991
  EXT_render_snorm = "EXT_render_snorm";
1908
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";
1909
1999
  TEXTURE_FEATURES = {
1910
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1911
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1912
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1913
- "snorm8-renderable-webgl": [EXT_render_snorm],
1914
- "norm16-renderable-webgl": [EXT_texture_norm16],
1915
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1916
- "float32-filterable": ["OES_texture_float_linear"],
1917
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1918
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1919
- "texture-blend-float-webgl": ["EXT_float_blend"],
1920
- "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] },
1921
2012
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1922
2013
  // 'texture-compression-bc3-webgl': [X_S3TC],
1923
- "texture-compression-bc5-webgl": [X_RGTC],
1924
- "texture-compression-bc7-webgl": [X_BPTC],
1925
- "texture-compression-etc2": [X_ETC2],
1926
- "texture-compression-astc": [X_ASTC],
1927
- "texture-compression-etc1-webgl": [X_ETC1],
1928
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1929
- "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] }
1930
2021
  };
1931
2022
  WEBGL_TEXTURE_FORMATS = {
1932
2023
  // 8-bit formats
1933
2024
  "r8unorm": { gl: 33321, rb: true },
1934
- "r8snorm": { gl: 36756 },
2025
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1935
2026
  "r8uint": { gl: 33330, rb: true },
1936
2027
  "r8sint": { gl: 33329, rb: true },
1937
2028
  // 16-bit formats
1938
2029
  "rg8unorm": { gl: 33323, rb: true },
1939
- "rg8snorm": { gl: 36757 },
2030
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1940
2031
  "rg8uint": { gl: 33336, rb: true },
1941
2032
  "rg8sint": { gl: 33335, rb: true },
1942
2033
  "r16uint": { gl: 33332, rb: true },
1943
2034
  "r16sint": { gl: 33331, rb: true },
1944
- "r16float": { gl: 33325, rb: true },
1945
- "r16unorm": { gl: 33322, rb: true },
1946
- "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 },
1947
2038
  // Packed 16-bit formats
1948
2039
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1949
2040
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1954,7 +2045,7 @@ var __exports__ = (() => {
1954
2045
  // 32-bit formats
1955
2046
  "rgba8unorm": { gl: 32856 },
1956
2047
  "rgba8unorm-srgb": { gl: 35907 },
1957
- "rgba8snorm": { gl: 36759 },
2048
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1958
2049
  "rgba8uint": { gl: 36220 },
1959
2050
  "rgba8sint": { gl: 36238 },
1960
2051
  // reverse colors, webgpu only
@@ -1962,38 +2053,38 @@ var __exports__ = (() => {
1962
2053
  "bgra8unorm-srgb": {},
1963
2054
  "rg16uint": { gl: 33338 },
1964
2055
  "rg16sint": { gl: 33337 },
1965
- "rg16float": { gl: 33327, rb: true },
1966
- "rg16unorm": { gl: 33324 },
1967
- "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 },
1968
2059
  "r32uint": { gl: 33334, rb: true },
1969
2060
  "r32sint": { gl: 33333, rb: true },
1970
- "r32float": { gl: 33326 },
2061
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1971
2062
  // Packed 32-bit formats
1972
- "rgb9e5ufloat": { gl: 35901 },
2063
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1973
2064
  // , filter: true},
1974
2065
  "rg11b10ufloat": { gl: 35898, rb: true },
1975
2066
  "rgb10a2unorm": { gl: 32857, rb: true },
1976
2067
  "rgb10a2uint": { gl: 36975, rb: true },
1977
2068
  // 48-bit formats
1978
- "rgb16unorm-webgl": { gl: 32852 },
2069
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1979
2070
  // rgb not renderable
1980
- "rgb16snorm-webgl": { gl: 36762 },
2071
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1981
2072
  // rgb not renderable
1982
2073
  // 64-bit formats
1983
2074
  "rg32uint": { gl: 33340, rb: true },
1984
2075
  "rg32sint": { gl: 33339, rb: true },
1985
- "rg32float": { gl: 33328, rb: true },
2076
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1986
2077
  "rgba16uint": { gl: 36214, rb: true },
1987
2078
  "rgba16sint": { gl: 36232, rb: true },
1988
- "rgba16float": { gl: 34842 },
1989
- "rgba16unorm": { gl: 32859, rb: true },
1990
- "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 },
1991
2082
  // 96-bit formats (deprecated!)
1992
- "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] },
1993
2084
  // 128-bit formats
1994
2085
  "rgba32uint": { gl: 36208, rb: true },
1995
2086
  "rgba32sint": { gl: 36226, rb: true },
1996
- "rgba32float": { gl: 34836, rb: true },
2087
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1997
2088
  // Depth and stencil formats
1998
2089
  "stencil8": { gl: 36168, rb: true },
1999
2090
  // 8 stencil bits
@@ -2051,8 +2142,8 @@ var __exports__ = (() => {
2051
2142
  "astc-8x6-unorm-srgb": { gl: 37846 },
2052
2143
  "astc-8x8-unorm": { gl: 37815 },
2053
2144
  "astc-8x8-unorm-srgb": { gl: 37847 },
2054
- "astc-10x5-unorm": { gl: 37819 },
2055
- "astc-10x5-unorm-srgb": { gl: 37851 },
2145
+ "astc-10x5-unorm": { gl: 37816 },
2146
+ "astc-10x5-unorm-srgb": { gl: 37848 },
2056
2147
  "astc-10x6-unorm": { gl: 37817 },
2057
2148
  "astc-10x6-unorm-srgb": { gl: 37849 },
2058
2149
  "astc-10x8-unorm": { gl: 37818 },
@@ -2066,7 +2157,7 @@ var __exports__ = (() => {
2066
2157
  // WEBGL_compressed_texture_pvrtc
2067
2158
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
2068
2159
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
2069
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
2160
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
2070
2161
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
2071
2162
  // WEBGL_compressed_texture_etc1
2072
2163
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -2089,12 +2180,11 @@ var __exports__ = (() => {
2089
2180
  // optional WebGPU features
2090
2181
  "depth-clip-control": "EXT_depth_clamp",
2091
2182
  // TODO these seem subtly different
2092
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2183
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2093
2184
  // "indirect-first-instance"
2094
2185
  // Textures are handled by getTextureFeatures()
2095
2186
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2096
2187
  // optional WebGL features
2097
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2098
2188
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2099
2189
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2100
2190
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2431,6 +2521,60 @@ var __exports__ = (() => {
2431
2521
  }
2432
2522
  });
2433
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);
2573
+ }
2574
+ };
2575
+ }
2576
+ });
2577
+
2434
2578
  // ../../node_modules/@luma.gl/webgl/dist/utils/uid.js
2435
2579
  function uid(id = "id") {
2436
2580
  uidCounters[id] = uidCounters[id] || 1;
@@ -2446,34 +2590,34 @@ var __exports__ = (() => {
2446
2590
 
2447
2591
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js
2448
2592
  function getWebGLTarget(usage) {
2449
- if (usage & import_core9.Buffer.INDEX) {
2593
+ if (usage & import_core10.Buffer.INDEX) {
2450
2594
  return 34963;
2451
2595
  }
2452
- if (usage & import_core9.Buffer.VERTEX) {
2596
+ if (usage & import_core10.Buffer.VERTEX) {
2453
2597
  return 34962;
2454
2598
  }
2455
- if (usage & import_core9.Buffer.UNIFORM) {
2599
+ if (usage & import_core10.Buffer.UNIFORM) {
2456
2600
  return 35345;
2457
2601
  }
2458
2602
  return 34962;
2459
2603
  }
2460
2604
  function getWebGLUsage(usage) {
2461
- if (usage & import_core9.Buffer.INDEX) {
2605
+ if (usage & import_core10.Buffer.INDEX) {
2462
2606
  return 35044;
2463
2607
  }
2464
- if (usage & import_core9.Buffer.VERTEX) {
2608
+ if (usage & import_core10.Buffer.VERTEX) {
2465
2609
  return 35044;
2466
2610
  }
2467
- if (usage & import_core9.Buffer.UNIFORM) {
2611
+ if (usage & import_core10.Buffer.UNIFORM) {
2468
2612
  return 35048;
2469
2613
  }
2470
2614
  return 35044;
2471
2615
  }
2472
- var import_core9, WEBGLBuffer;
2616
+ var import_core10, WEBGLBuffer;
2473
2617
  var init_webgl_buffer = __esm({
2474
2618
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js"() {
2475
- import_core9 = __toESM(require_core2(), 1);
2476
- WEBGLBuffer = class extends import_core9.Buffer {
2619
+ import_core10 = __toESM(require_core2(), 1);
2620
+ WEBGLBuffer = class extends import_core10.Buffer {
2477
2621
  device;
2478
2622
  gl;
2479
2623
  handle;
@@ -2508,8 +2652,12 @@ var __exports__ = (() => {
2508
2652
  destroy() {
2509
2653
  if (!this.destroyed && this.handle) {
2510
2654
  this.removeStats();
2511
- this.trackDeallocatedMemory();
2512
- 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
+ }
2513
2661
  this.destroyed = true;
2514
2662
  this.handle = null;
2515
2663
  }
@@ -2524,7 +2672,11 @@ var __exports__ = (() => {
2524
2672
  this.bytesUsed = byteLength;
2525
2673
  this.byteLength = byteLength;
2526
2674
  this._setDebugData(data, byteOffset, byteLength);
2527
- this.trackAllocatedMemory(byteLength);
2675
+ if (!this.props.handle) {
2676
+ this.trackAllocatedMemory(byteLength);
2677
+ } else {
2678
+ this.trackReferencedMemory(byteLength, "Buffer");
2679
+ }
2528
2680
  }
2529
2681
  // Allocate a GPU buffer of specified size.
2530
2682
  _initWithByteLength(byteLength) {
@@ -2539,7 +2691,11 @@ var __exports__ = (() => {
2539
2691
  this.bytesUsed = byteLength;
2540
2692
  this.byteLength = byteLength;
2541
2693
  this._setDebugData(null, 0, byteLength);
2542
- this.trackAllocatedMemory(byteLength);
2694
+ if (!this.props.handle) {
2695
+ this.trackAllocatedMemory(byteLength);
2696
+ } else {
2697
+ this.trackReferencedMemory(byteLength, "Buffer");
2698
+ }
2543
2699
  return this;
2544
2700
  }
2545
2701
  write(data, byteOffset = 0) {
@@ -2590,9 +2746,20 @@ var __exports__ = (() => {
2590
2746
  if (line.length <= 1) {
2591
2747
  continue;
2592
2748
  }
2749
+ const lineWithTrimmedWhitespace = line.trim();
2593
2750
  const segments = line.split(":");
2751
+ const trimmedMessageType = segments[0]?.trim();
2594
2752
  if (segments.length === 2) {
2595
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
+ }
2596
2763
  messages.push({
2597
2764
  message: message2.trim(),
2598
2765
  type: getMessageType(messageType2),
@@ -2602,6 +2769,15 @@ var __exports__ = (() => {
2602
2769
  continue;
2603
2770
  }
2604
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
+ }
2605
2781
  let lineNum = parseInt(lineNumber, 10);
2606
2782
  if (isNaN(lineNum)) {
2607
2783
  lineNum = 0;
@@ -2631,12 +2807,12 @@ var __exports__ = (() => {
2631
2807
  });
2632
2808
 
2633
2809
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js
2634
- var import_core10, WEBGLShader;
2810
+ var import_core11, WEBGLShader;
2635
2811
  var init_webgl_shader = __esm({
2636
2812
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js"() {
2637
- import_core10 = __toESM(require_core2(), 1);
2813
+ import_core11 = __toESM(require_core2(), 1);
2638
2814
  init_parse_shader_compiler_log();
2639
- WEBGLShader = class extends import_core10.Shader {
2815
+ WEBGLShader = class extends import_core11.Shader {
2640
2816
  device;
2641
2817
  handle;
2642
2818
  constructor(device, props) {
@@ -2702,9 +2878,9 @@ ${source}`;
2702
2878
  }
2703
2879
  return;
2704
2880
  }
2705
- import_core10.log.once(1, "Shader compilation is asynchronous")();
2881
+ import_core11.log.once(1, "Shader compilation is asynchronous")();
2706
2882
  await this._waitForCompilationComplete();
2707
- 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}`)();
2708
2884
  this._getCompilationStatus();
2709
2885
  this.debugShader();
2710
2886
  }
@@ -2852,7 +3028,7 @@ ${source}`;
2852
3028
  gl.stencilMaskSeparate(1029, mask);
2853
3029
  }
2854
3030
  if (parameters.stencilReadMask) {
2855
- import_core11.log.warn("stencilReadMask not supported under WebGL");
3031
+ import_core12.log.warn("stencilReadMask not supported under WebGL");
2856
3032
  }
2857
3033
  if (parameters.stencilCompare) {
2858
3034
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2965,10 +3141,10 @@ ${source}`;
2965
3141
  }
2966
3142
  return isEmpty;
2967
3143
  }
2968
- var import_core11;
3144
+ var import_core12;
2969
3145
  var init_device_parameters = __esm({
2970
3146
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/device-parameters.js"() {
2971
- import_core11 = __toESM(require_core2(), 1);
3147
+ import_core12 = __toESM(require_core2(), 1);
2972
3148
  init_unified_parameter_api();
2973
3149
  }
2974
3150
  });
@@ -3057,12 +3233,12 @@ ${source}`;
3057
3233
  });
3058
3234
 
3059
3235
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js
3060
- var import_core12, WEBGLSampler;
3236
+ var import_core13, WEBGLSampler;
3061
3237
  var init_webgl_sampler = __esm({
3062
3238
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js"() {
3063
- import_core12 = __toESM(require_core2(), 1);
3239
+ import_core13 = __toESM(require_core2(), 1);
3064
3240
  init_sampler_parameters();
3065
- WEBGLSampler = class extends import_core12.Sampler {
3241
+ WEBGLSampler = class extends import_core13.Sampler {
3066
3242
  device;
3067
3243
  handle;
3068
3244
  parameters;
@@ -3137,18 +3313,18 @@ ${source}`;
3137
3313
  });
3138
3314
 
3139
3315
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js
3140
- var import_core13, WEBGLTextureView;
3316
+ var import_core14, WEBGLTextureView;
3141
3317
  var init_webgl_texture_view = __esm({
3142
3318
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js"() {
3143
- import_core13 = __toESM(require_core2(), 1);
3144
- WEBGLTextureView = class extends import_core13.TextureView {
3319
+ import_core14 = __toESM(require_core2(), 1);
3320
+ WEBGLTextureView = class extends import_core14.TextureView {
3145
3321
  device;
3146
3322
  gl;
3147
3323
  handle;
3148
3324
  // Does not have a WebGL representation
3149
3325
  texture;
3150
3326
  constructor(device, props) {
3151
- super(device, { ...import_core13.Texture.defaultProps, ...props });
3327
+ super(device, { ...import_core14.Texture.defaultProps, ...props });
3152
3328
  this.device = device;
3153
3329
  this.gl = this.device.gl;
3154
3330
  this.handle = null;
@@ -3158,87 +3334,6 @@ ${source}`;
3158
3334
  }
3159
3335
  });
3160
3336
 
3161
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
3162
- function convertDataTypeToGLDataType(normalizedType) {
3163
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3164
- }
3165
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
3166
- return WEBGL_SHADER_TYPES[glUniformType];
3167
- }
3168
- function isGLSamplerType(type) {
3169
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3170
- }
3171
- function getTextureBindingFromGLSamplerType(glSamplerType) {
3172
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3173
- }
3174
- var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
3175
- var init_webgl_shadertypes = __esm({
3176
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
3177
- WEBGL_SHADER_TYPES = {
3178
- [5126]: "f32",
3179
- [35664]: "vec2<f32>",
3180
- [35665]: "vec3<f32>",
3181
- [35666]: "vec4<f32>",
3182
- [5124]: "i32",
3183
- [35667]: "vec2<i32>",
3184
- [35668]: "vec3<i32>",
3185
- [35669]: "vec4<i32>",
3186
- [5125]: "u32",
3187
- [36294]: "vec2<u32>",
3188
- [36295]: "vec3<u32>",
3189
- [36296]: "vec4<u32>",
3190
- [35670]: "f32",
3191
- [35671]: "vec2<f32>",
3192
- [35672]: "vec3<f32>",
3193
- [35673]: "vec4<f32>",
3194
- // TODO - are sizes/components below correct?
3195
- [35674]: "mat2x2<f32>",
3196
- [35685]: "mat2x3<f32>",
3197
- [35686]: "mat2x4<f32>",
3198
- [35687]: "mat3x2<f32>",
3199
- [35675]: "mat3x3<f32>",
3200
- [35688]: "mat3x4<f32>",
3201
- [35689]: "mat4x2<f32>",
3202
- [35690]: "mat4x3<f32>",
3203
- [35676]: "mat4x4<f32>"
3204
- };
3205
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3206
- [35678]: { viewDimension: "2d", sampleType: "float" },
3207
- [35680]: { viewDimension: "cube", sampleType: "float" },
3208
- [35679]: { viewDimension: "3d", sampleType: "float" },
3209
- [35682]: { viewDimension: "3d", sampleType: "depth" },
3210
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
3211
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
3212
- [36293]: { viewDimension: "cube", sampleType: "float" },
3213
- [36298]: { viewDimension: "2d", sampleType: "sint" },
3214
- [36299]: { viewDimension: "3d", sampleType: "sint" },
3215
- [36300]: { viewDimension: "cube", sampleType: "sint" },
3216
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
3217
- [36306]: { viewDimension: "2d", sampleType: "uint" },
3218
- [36307]: { viewDimension: "3d", sampleType: "uint" },
3219
- [36308]: { viewDimension: "cube", sampleType: "uint" },
3220
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
3221
- };
3222
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3223
- uint8: 5121,
3224
- sint8: 5120,
3225
- unorm8: 5121,
3226
- snorm8: 5120,
3227
- uint16: 5123,
3228
- sint16: 5122,
3229
- unorm16: 5123,
3230
- snorm16: 5122,
3231
- uint32: 5125,
3232
- sint32: 5124,
3233
- // WebGPU does not support normalized 32 bit integer attributes
3234
- // 'unorm32': GL.UNSIGNED_INT,
3235
- // 'snorm32': GL.INT,
3236
- float16: 5131,
3237
- float32: 5126
3238
- };
3239
- }
3240
- });
3241
-
3242
3337
  // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
3243
3338
  function convertGLDataTypeToDataType(type) {
3244
3339
  return GL_DATA_TYPE_MAP[type];
@@ -3268,6 +3363,18 @@ ${source}`;
3268
3363
  });
3269
3364
 
3270
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
+ }
3271
3378
  function getWebGLTextureTarget(dimension) {
3272
3379
  switch (dimension) {
3273
3380
  case "1d":
@@ -3288,18 +3395,17 @@ ${source}`;
3288
3395
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3289
3396
  return dimension === "cube" ? 34069 + level : glTarget;
3290
3397
  }
3291
- var import_core14, import_core15, WEBGLTexture;
3398
+ var import_core15, import_core16, WEBGLTexture;
3292
3399
  var init_webgl_texture = __esm({
3293
3400
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js"() {
3294
- import_core14 = __toESM(require_core2(), 1);
3401
+ import_core15 = __toESM(require_core2(), 1);
3295
3402
  init_webgl_texture_table();
3296
3403
  init_sampler_parameters();
3297
3404
  init_with_parameters();
3298
3405
  init_webgl_texture_view();
3299
- init_webgl_shadertypes();
3300
3406
  init_shader_formats();
3301
- import_core15 = __toESM(require_core2(), 1);
3302
- WEBGLTexture = class extends import_core14.Texture {
3407
+ import_core16 = __toESM(require_core2(), 1);
3408
+ WEBGLTexture = class extends import_core15.Texture {
3303
3409
  // readonly MAX_ATTRIBUTES: number;
3304
3410
  device;
3305
3411
  gl;
@@ -3328,8 +3434,10 @@ ${source}`;
3328
3434
  // state
3329
3435
  /** Texture binding slot - TODO - move to texture view? */
3330
3436
  _textureUnit = 0;
3331
- /** Chached framebuffer */
3437
+ /** Cached framebuffer reused for color texture readback. */
3332
3438
  _framebuffer = null;
3439
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3440
+ _framebufferAttachmentKey = null;
3333
3441
  constructor(device, props) {
3334
3442
  super(device, props, { byteAlignment: 1 });
3335
3443
  this.device = device;
@@ -3344,20 +3452,27 @@ ${source}`;
3344
3452
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3345
3453
  this.gl.bindTexture(this.glTarget, this.handle);
3346
3454
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3347
- switch (dimension) {
3348
- case "2d":
3349
- case "cube":
3350
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3351
- break;
3352
- case "2d-array":
3353
- case "3d":
3354
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3355
- break;
3356
- default:
3357
- 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
+ }
3358
3468
  }
3359
3469
  this.gl.bindTexture(this.glTarget, null);
3360
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
+ }
3361
3476
  this.setSampler(this.props.sampler);
3362
3477
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3363
3478
  Object.seal(this);
@@ -3366,9 +3481,14 @@ ${source}`;
3366
3481
  if (this.handle) {
3367
3482
  this._framebuffer?.destroy();
3368
3483
  this._framebuffer = null;
3369
- this.gl.deleteTexture(this.handle);
3484
+ this._framebufferAttachmentKey = null;
3370
3485
  this.removeStats();
3371
- 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
+ }
3372
3492
  this.destroyed = true;
3373
3493
  }
3374
3494
  }
@@ -3407,97 +3527,128 @@ ${source}`;
3407
3527
  return { width: options.width, height: options.height };
3408
3528
  }
3409
3529
  copyImageData(options_) {
3410
- const options = this._normalizeCopyImageDataOptions(options_);
3411
- const typedArray = options.data;
3412
- const { width, height, depth, z = 0 } = options;
3413
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 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;
3414
3568
  const { glFormat, glType, compressed } = this;
3415
3569
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3416
- let unpackRowLength;
3417
- if (!this.compressed) {
3418
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3419
- if (bytesPerPixel) {
3420
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3421
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
3422
- }
3423
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
3424
- }
3570
+ if (compressed) {
3571
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
3425
3572
  }
3426
- const glParameters = !this.compressed ? {
3573
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3574
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3575
+ const glParameters = {
3427
3576
  [3317]: this.byteAlignment,
3428
3577
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3429
3578
  [32878]: options.rowsPerImage
3430
- } : {};
3579
+ };
3431
3580
  this.gl.bindTexture(this.glTarget, this.handle);
3581
+ this.gl.bindBuffer(35052, buffer.handle);
3432
3582
  withGLParameters(this.gl, glParameters, () => {
3433
3583
  switch (this.dimension) {
3434
3584
  case "2d":
3435
3585
  case "cube":
3436
- if (compressed) {
3437
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
3438
- } else {
3439
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3440
- }
3586
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
3441
3587
  break;
3442
3588
  case "2d-array":
3443
3589
  case "3d":
3444
- if (compressed) {
3445
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
3446
- } else {
3447
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
3448
- }
3590
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
3449
3591
  break;
3450
3592
  default:
3451
3593
  }
3452
3594
  });
3595
+ this.gl.bindBuffer(35052, null);
3453
3596
  this.gl.bindTexture(this.glTarget, null);
3454
3597
  }
3455
- readBuffer(options = {}, buffer) {
3456
- throw new Error("readBuffer not implemented");
3457
- }
3458
- async readDataAsync(options = {}) {
3459
- return this.readDataSyncWebGL(options);
3460
- }
3461
- writeBuffer(buffer, options_ = {}) {
3462
- }
3463
3598
  writeData(data, options_ = {}) {
3464
3599
  const options = this._normalizeTextureWriteOptions(options_);
3465
3600
  const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3466
- const {} = this;
3467
- const { width, height, mipLevel, x, y, z } = options;
3601
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
3468
3602
  const { glFormat, glType, compressed } = this;
3469
- const depth = 0;
3470
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
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
+ }
3610
+ }
3471
3611
  const glParameters = !this.compressed ? {
3472
- // WebGL does not require byte alignment, but allows it to be specified
3473
- [3317]: this.byteAlignment
3474
- // [GL.UNPACK_ROW_LENGTH]: bytesPerRow,
3475
- // [GL.UNPACK_IMAGE_HEIGHT]: rowsPerImage
3612
+ [3317]: this.byteAlignment,
3613
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3614
+ [32878]: options.rowsPerImage
3476
3615
  } : {};
3477
- this.gl.bindTexture(glTarget, this.handle);
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;
3620
+ this.gl.bindTexture(this.glTarget, this.handle);
3478
3621
  this.gl.bindBuffer(35052, null);
3479
3622
  withGLParameters(this.gl, glParameters, () => {
3480
3623
  switch (this.dimension) {
3481
3624
  case "2d":
3482
3625
  case "cube":
3483
3626
  if (compressed) {
3484
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray);
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
+ }
3485
3632
  } else {
3486
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray);
3633
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3487
3634
  }
3488
3635
  break;
3489
3636
  case "2d-array":
3490
3637
  case "3d":
3491
3638
  if (compressed) {
3492
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray);
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
+ }
3493
3644
  } else {
3494
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray);
3645
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
3495
3646
  }
3496
3647
  break;
3497
3648
  default:
3498
3649
  }
3499
3650
  });
3500
- this.gl.bindTexture(glTarget, null);
3651
+ this.gl.bindTexture(this.glTarget, null);
3501
3652
  }
3502
3653
  // IMPLEMENTATION SPECIFIC
3503
3654
  /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
@@ -3519,36 +3670,91 @@ ${source}`;
3519
3670
  }
3520
3671
  // WEBGL SPECIFIC
3521
3672
  readDataSyncWebGL(options_ = {}) {
3522
- const options = this._normalizeTextureReadOptions(options_);
3673
+ const options = this._getSupportedColorReadOptions(options_);
3523
3674
  const memoryLayout = this.computeMemoryLayout(options);
3524
3675
  const shaderType = convertGLDataTypeToDataType(this.glType);
3525
- const ArrayType = (0, import_core15.getTypedArrayConstructor)(shaderType);
3526
- const targetArray = new ArrayType(memoryLayout.byteLength);
3527
- const signedType = (0, import_core15.getDataType)(targetArray);
3528
- const sourceType = convertDataTypeToGLDataType(signedType);
3529
- const framebuffer = this._getFramebuffer();
3530
- const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3531
- this.gl.readBuffer(36064);
3532
- this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, sourceType, targetArray);
3533
- this.gl.bindFramebuffer(36160, prevHandle || null);
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
+ });
3534
3682
  return targetArray.buffer;
3535
3683
  }
3536
3684
  /**
3537
- * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
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.
3538
3687
  */
3539
- generateMipmapsWebGL(options) {
3540
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3541
- if (!isFilterableAndRenderable) {
3542
- import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3543
- if (!options?.force) {
3544
- return;
3545
- }
3546
- }
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);
3547
3697
  try {
3548
- this.gl.bindTexture(this.glTarget, this.handle);
3549
- this.gl.generateMipmap(this.glTarget);
3550
- } catch (error) {
3551
- 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
+ });
3705
+ } finally {
3706
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3707
+ this.gl.readBuffer(prevReadBuffer);
3708
+ }
3709
+ }
3710
+ /**
3711
+ * Attaches a single color subresource to the cached read framebuffer.
3712
+ *
3713
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3714
+ */
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}`)();
3552
3758
  } finally {
3553
3759
  this.gl.bindTexture(this.glTarget, null);
3554
3760
  }
@@ -3558,7 +3764,7 @@ ${source}`;
3558
3764
  * Sets sampler parameters on texture
3559
3765
  */
3560
3766
  _setSamplerParameters(parameters) {
3561
- import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3767
+ import_core15.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3562
3768
  this.gl.bindTexture(this.glTarget, this.handle);
3563
3769
  for (const [pname, pvalue] of Object.entries(parameters)) {
3564
3770
  const param = Number(pname);
@@ -3615,206 +3821,6 @@ ${source}`;
3615
3821
  }
3616
3822
  });
3617
3823
 
3618
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
3619
- function getShaderLayoutFromGLSL(gl, program) {
3620
- const shaderLayout = {
3621
- attributes: [],
3622
- bindings: []
3623
- };
3624
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3625
- const uniformBlocks = readUniformBlocks(gl, program);
3626
- for (const uniformBlock of uniformBlocks) {
3627
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3628
- name: uniform.name,
3629
- format: uniform.format,
3630
- byteOffset: uniform.byteOffset,
3631
- byteStride: uniform.byteStride,
3632
- arrayLength: uniform.arrayLength
3633
- }));
3634
- shaderLayout.bindings.push({
3635
- type: "uniform",
3636
- name: uniformBlock.name,
3637
- group: 0,
3638
- location: uniformBlock.location,
3639
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3640
- minBindingSize: uniformBlock.byteLength,
3641
- uniforms: uniforms2
3642
- });
3643
- }
3644
- const uniforms = readUniformBindings(gl, program);
3645
- let textureUnit = 0;
3646
- for (const uniform of uniforms) {
3647
- if (isGLSamplerType(uniform.type)) {
3648
- const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3649
- shaderLayout.bindings.push({
3650
- type: "texture",
3651
- name: uniform.name,
3652
- group: 0,
3653
- location: textureUnit,
3654
- viewDimension,
3655
- sampleType
3656
- });
3657
- uniform.textureUnit = textureUnit;
3658
- textureUnit += 1;
3659
- }
3660
- }
3661
- if (uniforms.length) {
3662
- shaderLayout.uniforms = uniforms;
3663
- }
3664
- const varyings = readVaryings(gl, program);
3665
- if (varyings?.length) {
3666
- shaderLayout.varyings = varyings;
3667
- }
3668
- return shaderLayout;
3669
- }
3670
- function readAttributeDeclarations(gl, program) {
3671
- const attributes = [];
3672
- const count = gl.getProgramParameter(program, 35721);
3673
- for (let index = 0; index < count; index++) {
3674
- const activeInfo = gl.getActiveAttrib(program, index);
3675
- if (!activeInfo) {
3676
- throw new Error("activeInfo");
3677
- }
3678
- const {
3679
- name,
3680
- type: compositeType
3681
- /* , size*/
3682
- } = activeInfo;
3683
- const location = gl.getAttribLocation(program, name);
3684
- if (location >= 0) {
3685
- const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
3686
- const stepMode = /instance/i.test(name) ? "instance" : "vertex";
3687
- attributes.push({
3688
- name,
3689
- location,
3690
- stepMode,
3691
- type: attributeType
3692
- // size - for arrays, size is the number of elements in the array
3693
- });
3694
- }
3695
- }
3696
- attributes.sort((a, b) => a.location - b.location);
3697
- return attributes;
3698
- }
3699
- function readVaryings(gl, program) {
3700
- const varyings = [];
3701
- const count = gl.getProgramParameter(program, 35971);
3702
- for (let location = 0; location < count; location++) {
3703
- const activeInfo = gl.getTransformFeedbackVarying(program, location);
3704
- if (!activeInfo) {
3705
- throw new Error("activeInfo");
3706
- }
3707
- const { name, type: glUniformType, size } = activeInfo;
3708
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3709
- const { type, components } = (0, import_core16.getVariableShaderTypeInfo)(uniformType);
3710
- varyings.push({ location, name, type, size: size * components });
3711
- }
3712
- varyings.sort((a, b) => a.location - b.location);
3713
- return varyings;
3714
- }
3715
- function readUniformBindings(gl, program) {
3716
- const uniforms = [];
3717
- const uniformCount = gl.getProgramParameter(program, 35718);
3718
- for (let i = 0; i < uniformCount; i++) {
3719
- const activeInfo = gl.getActiveUniform(program, i);
3720
- if (!activeInfo) {
3721
- throw new Error("activeInfo");
3722
- }
3723
- const { name: rawName, size, type } = activeInfo;
3724
- const { name, isArray: isArray3 } = parseUniformName(rawName);
3725
- let webglLocation = gl.getUniformLocation(program, name);
3726
- const uniformInfo = {
3727
- // WebGL locations are uniquely typed but just numbers
3728
- location: webglLocation,
3729
- name,
3730
- size,
3731
- type,
3732
- isArray: isArray3
3733
- };
3734
- uniforms.push(uniformInfo);
3735
- if (uniformInfo.size > 1) {
3736
- for (let j = 0; j < uniformInfo.size; j++) {
3737
- const elementName = `${name}[${j}]`;
3738
- webglLocation = gl.getUniformLocation(program, elementName);
3739
- const arrayElementUniformInfo = {
3740
- ...uniformInfo,
3741
- name: elementName,
3742
- location: webglLocation
3743
- };
3744
- uniforms.push(arrayElementUniformInfo);
3745
- }
3746
- }
3747
- }
3748
- return uniforms;
3749
- }
3750
- function readUniformBlocks(gl, program) {
3751
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3752
- const uniformBlocks = [];
3753
- const blockCount = gl.getProgramParameter(program, 35382);
3754
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3755
- const blockInfo = {
3756
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3757
- location: getBlockParameter(blockIndex, 35391),
3758
- byteLength: getBlockParameter(blockIndex, 35392),
3759
- vertex: getBlockParameter(blockIndex, 35396),
3760
- fragment: getBlockParameter(blockIndex, 35398),
3761
- uniformCount: getBlockParameter(blockIndex, 35394),
3762
- uniforms: []
3763
- };
3764
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3765
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3766
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3767
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3768
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3769
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3770
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3771
- if (!activeInfo) {
3772
- throw new Error("activeInfo");
3773
- }
3774
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3775
- blockInfo.uniforms.push({
3776
- name: activeInfo.name,
3777
- format,
3778
- type: uniformType[i],
3779
- arrayLength: uniformArrayLength[i],
3780
- byteOffset: uniformOffset[i],
3781
- byteStride: uniformStride[i]
3782
- // matrixStride: uniformStride[i],
3783
- // rowMajor: uniformRowMajor[i]
3784
- });
3785
- }
3786
- uniformBlocks.push(blockInfo);
3787
- }
3788
- uniformBlocks.sort((a, b) => a.location - b.location);
3789
- return uniformBlocks;
3790
- }
3791
- function parseUniformName(name) {
3792
- if (name[name.length - 1] !== "]") {
3793
- return {
3794
- name,
3795
- length: 1,
3796
- isArray: false
3797
- };
3798
- }
3799
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3800
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3801
- if (!matches || matches.length < 2) {
3802
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3803
- }
3804
- return {
3805
- name: matches[1],
3806
- length: matches[2] ? 1 : 0,
3807
- isArray: Boolean(matches[2])
3808
- };
3809
- }
3810
- var import_core16;
3811
- var init_get_shader_layout_from_glsl = __esm({
3812
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3813
- import_core16 = __toESM(require_core2(), 1);
3814
- init_webgl_shadertypes();
3815
- }
3816
- });
3817
-
3818
3824
  // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3819
3825
  function setUniform(gl, location, type, value) {
3820
3826
  const gl2 = gl;
@@ -3959,11 +3965,10 @@ ${source}`;
3959
3965
  }
3960
3966
  return mergedLayout;
3961
3967
  }
3962
- var import_core17, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3968
+ var import_core17, WEBGLRenderPipeline;
3963
3969
  var init_webgl_render_pipeline = __esm({
3964
3970
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3965
3971
  import_core17 = __toESM(require_core2(), 1);
3966
- init_get_shader_layout_from_glsl();
3967
3972
  init_device_parameters();
3968
3973
  init_set_uniform();
3969
3974
  init_webgl_buffer();
@@ -3971,7 +3976,6 @@ ${source}`;
3971
3976
  init_webgl_texture();
3972
3977
  init_webgl_texture_view();
3973
3978
  init_webgl_topology_utils();
3974
- LOG_PROGRAM_PERF_PRIORITY = 4;
3975
3979
  WEBGLRenderPipeline = class extends import_core17.RenderPipeline {
3976
3980
  /** The WebGL device that created this render pipeline */
3977
3981
  device;
@@ -3983,10 +3987,10 @@ ${source}`;
3983
3987
  fs;
3984
3988
  /** The layout extracted from shader by WebGL introspection APIs */
3985
3989
  introspectedLayout;
3986
- /** Uniforms set on this model */
3987
- uniforms = {};
3988
- /** Bindings set on this model */
3990
+ /** Compatibility path for direct pipeline.setBindings() usage */
3989
3991
  bindings = {};
3992
+ /** Compatibility path for direct pipeline.uniforms usage */
3993
+ uniforms = {};
3990
3994
  /** WebGL varyings */
3991
3995
  varyings = null;
3992
3996
  _uniformCount = 0;
@@ -3998,33 +4002,28 @@ ${source}`;
3998
4002
  constructor(device, props) {
3999
4003
  super(device, props);
4000
4004
  this.device = device;
4001
- this.handle = this.props.handle || this.device.gl.createProgram();
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;
4002
4012
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
4003
- this.vs = props.vs;
4004
- this.fs = props.fs;
4005
- const { varyings, bufferMode = 35981 } = props;
4006
- if (varyings && varyings.length > 0) {
4007
- this.varyings = varyings;
4008
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4009
- }
4010
- this._linkShaders();
4011
- import_core17.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4012
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4013
- import_core17.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4014
4013
  this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4015
4014
  }
4016
4015
  destroy() {
4017
- if (this.handle) {
4018
- this.device.gl.useProgram(null);
4019
- this.device.gl.deleteProgram(this.handle);
4020
- this.destroyed = true;
4021
- this.handle.destroyed = true;
4022
- this.handle = null;
4016
+ if (this.destroyed) {
4017
+ return;
4023
4018
  }
4019
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4020
+ this.sharedRenderPipeline.destroy();
4021
+ }
4022
+ this.destroyResource();
4024
4023
  }
4025
4024
  /**
4026
- * Bindings include: textures, samplers and uniform buffers
4027
- * @todo needed for portable model
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.
4028
4027
  */
4029
4028
  setBindings(bindings, options) {
4030
4029
  for (const [name, value] of Object.entries(bindings)) {
@@ -4064,6 +4063,7 @@ ${source}`;
4064
4063
  * This function unifies those ways into a single call using common parameters with sane defaults
4065
4064
  */
4066
4065
  draw(options) {
4066
+ this._syncLinkStatus();
4067
4067
  const {
4068
4068
  renderPass,
4069
4069
  parameters = this.props.parameters,
@@ -4077,7 +4077,9 @@ ${source}`;
4077
4077
  // firstIndex,
4078
4078
  // firstInstance,
4079
4079
  // baseVertex,
4080
- transformFeedback
4080
+ transformFeedback,
4081
+ bindings = this.bindings,
4082
+ uniforms = this.uniforms
4081
4083
  } = options;
4082
4084
  const glDrawMode = getGLDrawMode(topology);
4083
4085
  const isIndexed = Boolean(vertexArray.indexBuffer);
@@ -4086,66 +4088,482 @@ ${source}`;
4086
4088
  import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4087
4089
  return false;
4088
4090
  }
4089
- if (!this._areTexturesRenderable()) {
4091
+ if (!this._areTexturesRenderable(bindings)) {
4090
4092
  import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4091
4093
  return false;
4092
4094
  }
4093
- this.device.gl.useProgram(this.handle);
4094
- vertexArray.bindBeforeRender(renderPass);
4095
- if (transformFeedback) {
4096
- transformFeedback.begin(this.props.topology);
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({
4326
+ type: "uniform",
4327
+ name: uniformBlock.name,
4328
+ group: 0,
4329
+ location: uniformBlock.location,
4330
+ visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
4331
+ minBindingSize: uniformBlock.byteLength,
4332
+ uniforms: uniforms2
4333
+ });
4334
+ }
4335
+ const uniforms = readUniformBindings(gl, program);
4336
+ let textureUnit = 0;
4337
+ for (const uniform of uniforms) {
4338
+ if (isGLSamplerType(uniform.type)) {
4339
+ const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
4340
+ shaderLayout.bindings.push({
4341
+ type: "texture",
4342
+ name: uniform.name,
4343
+ group: 0,
4344
+ location: textureUnit,
4345
+ viewDimension,
4346
+ sampleType
4347
+ });
4348
+ uniform.textureUnit = textureUnit;
4349
+ textureUnit += 1;
4350
+ }
4351
+ }
4352
+ if (uniforms.length) {
4353
+ shaderLayout.uniforms = uniforms;
4354
+ }
4355
+ const varyings = readVaryings(gl, program);
4356
+ if (varyings?.length) {
4357
+ shaderLayout.varyings = varyings;
4358
+ }
4359
+ return shaderLayout;
4360
+ }
4361
+ function readAttributeDeclarations(gl, program) {
4362
+ const attributes = [];
4363
+ const count = gl.getProgramParameter(program, 35721);
4364
+ for (let index = 0; index < count; index++) {
4365
+ const activeInfo = gl.getActiveAttrib(program, index);
4366
+ if (!activeInfo) {
4367
+ throw new Error("activeInfo");
4368
+ }
4369
+ const {
4370
+ name,
4371
+ type: compositeType
4372
+ /* , size*/
4373
+ } = activeInfo;
4374
+ const location = gl.getAttribLocation(program, name);
4375
+ if (location >= 0) {
4376
+ const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
4377
+ const stepMode = /instance/i.test(name) ? "instance" : "vertex";
4378
+ attributes.push({
4379
+ name,
4380
+ location,
4381
+ stepMode,
4382
+ type: attributeType
4383
+ // size - for arrays, size is the number of elements in the array
4384
+ });
4385
+ }
4386
+ }
4387
+ attributes.sort((a, b) => a.location - b.location);
4388
+ return attributes;
4389
+ }
4390
+ function readVaryings(gl, program) {
4391
+ const varyings = [];
4392
+ const count = gl.getProgramParameter(program, 35971);
4393
+ for (let location = 0; location < count; location++) {
4394
+ const activeInfo = gl.getTransformFeedbackVarying(program, location);
4395
+ if (!activeInfo) {
4396
+ throw new Error("activeInfo");
4397
+ }
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 });
4402
+ }
4403
+ varyings.sort((a, b) => a.location - b.location);
4404
+ return varyings;
4405
+ }
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
+ }
4438
+ }
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);
4481
+ }
4482
+ uniformBlocks.sort((a, b) => a.location - b.location);
4483
+ return uniformBlocks;
4484
+ }
4485
+ function parseUniformName(name) {
4486
+ if (name[name.length - 1] !== "]") {
4487
+ return {
4488
+ name,
4489
+ length: 1,
4490
+ isArray: false
4491
+ };
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
+ };
4502
+ }
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();
4508
+ }
4509
+ });
4510
+
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);
4516
+ init_get_shader_layout_from_glsl();
4517
+ init_webgl_shadertypes();
4518
+ LOG_PROGRAM_PERF_PRIORITY = 4;
4519
+ WEBGLSharedRenderPipeline = class extends import_core19.SharedRenderPipeline {
4520
+ device;
4521
+ handle;
4522
+ vs;
4523
+ fs;
4524
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4525
+ linkStatus = "pending";
4526
+ constructor(device, props) {
4527
+ super(device, props);
4528
+ this.device = device;
4529
+ this.handle = props.handle || this.device.gl.createProgram();
4530
+ this.vs = props.vs;
4531
+ this.fs = props.fs;
4532
+ if (props.varyings && props.varyings.length > 0) {
4533
+ this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
4534
+ }
4535
+ this._linkShaders();
4536
+ import_core19.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4537
+ this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4538
+ import_core19.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4539
+ }
4540
+ destroy() {
4541
+ if (this.destroyed) {
4542
+ return;
4097
4543
  }
4098
- this._applyBindings();
4099
- this._applyUniforms();
4100
- const webglRenderPass = renderPass;
4101
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4102
- if (isIndexed && isInstanced) {
4103
- this.device.gl.drawElementsInstanced(
4104
- glDrawMode,
4105
- vertexCount || 0,
4106
- // indexCount?
4107
- glIndexType,
4108
- firstVertex,
4109
- instanceCount || 0
4110
- );
4111
- } else if (isIndexed) {
4112
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4113
- } else if (isInstanced) {
4114
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4115
- } else {
4116
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4117
- }
4118
- if (transformFeedback) {
4119
- transformFeedback.end();
4120
- }
4121
- });
4122
- vertexArray.unbindAfterRender(renderPass);
4123
- return true;
4544
+ this.device.gl.useProgram(null);
4545
+ this.device.gl.deleteProgram(this.handle);
4546
+ this.handle.destroyed = true;
4547
+ this.destroyResource();
4124
4548
  }
4125
- // PRIVATE METHODS
4126
- // setAttributes(attributes: Record<string, Buffer>): void {}
4127
- // setBindings(bindings: Record<string, Binding>): void {}
4128
4549
  async _linkShaders() {
4129
4550
  const { gl } = this.device;
4130
4551
  gl.attachShader(this.handle, this.vs.handle);
4131
4552
  gl.attachShader(this.handle, this.fs.handle);
4132
- import_core17.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4553
+ import_core19.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4133
4554
  gl.linkProgram(this.handle);
4134
- import_core17.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4135
- if (import_core17.log.level === 0) {
4136
- }
4555
+ import_core19.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4137
4556
  if (!this.device.features.has("compilation-status-async-webgl")) {
4138
4557
  const status2 = this._getLinkStatus();
4139
4558
  this._reportLinkStatus(status2);
4140
4559
  return;
4141
4560
  }
4142
- import_core17.log.once(1, "RenderPipeline linking is asynchronous")();
4561
+ import_core19.log.once(1, "RenderPipeline linking is asynchronous")();
4143
4562
  await this._waitForLinkComplete();
4144
- import_core17.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}`)();
4145
4564
  const status = this._getLinkStatus();
4146
4565
  this._reportLinkStatus(status);
4147
4566
  }
4148
- /** Report link status. First, check for shader compilation failures if linking fails */
4149
4567
  async _reportLinkStatus(status) {
4150
4568
  switch (status) {
4151
4569
  case "success":
@@ -4179,11 +4597,6 @@ ${source}`;
4179
4597
  this.device.debug();
4180
4598
  }
4181
4599
  }
4182
- /**
4183
- * Get the shader compilation status
4184
- * TODO - Load log even when no error reported, to catch warnings?
4185
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4186
- */
4187
4600
  _getLinkStatus() {
4188
4601
  const { gl } = this.device;
4189
4602
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -4191,6 +4604,7 @@ ${source}`;
4191
4604
  this.linkStatus = "error";
4192
4605
  return "link-error";
4193
4606
  }
4607
+ this._initializeSamplerUniforms();
4194
4608
  gl.validateProgram(this.handle);
4195
4609
  const validated = gl.getProgramParameter(this.handle, 35715);
4196
4610
  if (!validated) {
@@ -4200,7 +4614,33 @@ ${source}`;
4200
4614
  this.linkStatus = "success";
4201
4615
  return "success";
4202
4616
  }
4203
- /** 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
+ }
4204
4644
  async _waitForLinkComplete() {
4205
4645
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4206
4646
  const DELAY_MS = 10;
@@ -4217,99 +4657,6 @@ ${source}`;
4217
4657
  await waitMs(DELAY_MS);
4218
4658
  }
4219
4659
  }
4220
- /**
4221
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4222
- * Update a texture if needed (e.g. from video)
4223
- * Note: This is currently done before every draw call
4224
- */
4225
- _areTexturesRenderable() {
4226
- let texturesRenderable = true;
4227
- for (const bindingInfo of this.shaderLayout.bindings) {
4228
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4229
- import_core17.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4230
- texturesRenderable = false;
4231
- }
4232
- }
4233
- return texturesRenderable;
4234
- }
4235
- /** Apply any bindings (before each draw call) */
4236
- _applyBindings() {
4237
- if (this.linkStatus !== "success") {
4238
- return;
4239
- }
4240
- const { gl } = this.device;
4241
- gl.useProgram(this.handle);
4242
- let textureUnit = 0;
4243
- let uniformBufferIndex = 0;
4244
- for (const binding of this.shaderLayout.bindings) {
4245
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4246
- if (!value) {
4247
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4248
- }
4249
- switch (binding.type) {
4250
- case "uniform":
4251
- const { name } = binding;
4252
- const location = gl.getUniformBlockIndex(this.handle, name);
4253
- if (location === 4294967295) {
4254
- throw new Error(`Invalid uniform block name ${name}`);
4255
- }
4256
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
4257
- if (value instanceof WEBGLBuffer) {
4258
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4259
- } else {
4260
- gl.bindBufferRange(
4261
- 35345,
4262
- uniformBufferIndex,
4263
- // @ts-expect-error
4264
- value.buffer.handle,
4265
- // @ts-expect-error
4266
- value.offset || 0,
4267
- // @ts-expect-error
4268
- value.size || value.buffer.byteLength - value.offset
4269
- );
4270
- }
4271
- uniformBufferIndex += 1;
4272
- break;
4273
- case "texture":
4274
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4275
- throw new Error("texture");
4276
- }
4277
- let texture;
4278
- if (value instanceof WEBGLTextureView) {
4279
- texture = value.texture;
4280
- } else if (value instanceof WEBGLTexture) {
4281
- texture = value;
4282
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4283
- import_core17.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4284
- texture = value.colorAttachments[0].texture;
4285
- } else {
4286
- throw new Error("No texture");
4287
- }
4288
- gl.activeTexture(33984 + textureUnit);
4289
- gl.bindTexture(texture.glTarget, texture.handle);
4290
- textureUnit += 1;
4291
- break;
4292
- case "sampler":
4293
- break;
4294
- case "storage":
4295
- case "read-only-storage":
4296
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4297
- }
4298
- }
4299
- }
4300
- /**
4301
- * Due to program sharing, uniforms need to be reset before every draw call
4302
- * (though caching will avoid redundant WebGL calls)
4303
- */
4304
- _applyUniforms() {
4305
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4306
- const { name, location, type, textureUnit } = uniformLayout;
4307
- const value = this.uniforms[name] ?? textureUnit;
4308
- if (value !== void 0) {
4309
- setUniform(this.device.gl, location, type, value);
4310
- }
4311
- }
4312
- }
4313
4660
  };
4314
4661
  }
4315
4662
  });
@@ -4341,7 +4688,7 @@ ${source}`;
4341
4688
  height = options.sourceTexture.height,
4342
4689
  depthOrArrayLayers = 0,
4343
4690
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
4344
- origin = [0, 0],
4691
+ origin = [0, 0, 0],
4345
4692
  /** Destination buffer */
4346
4693
  destinationBuffer,
4347
4694
  /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
@@ -4370,7 +4717,8 @@ ${source}`;
4370
4717
  const webglBuffer = destinationBuffer;
4371
4718
  const sourceWidth = width || framebuffer.width;
4372
4719
  const sourceHeight = height || framebuffer.height;
4373
- 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);
4374
4722
  const sourceFormat = sourceParams.format;
4375
4723
  const sourceType = sourceParams.type;
4376
4724
  device.gl.bindBuffer(35051, webglBuffer.handle);
@@ -4397,7 +4745,7 @@ ${source}`;
4397
4745
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
4398
4746
  origin = [0, 0],
4399
4747
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
4400
- destinationOrigin = [0, 0],
4748
+ destinationOrigin = [0, 0, 0],
4401
4749
  /** Texture to copy to/from. */
4402
4750
  destinationTexture
4403
4751
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -4413,7 +4761,7 @@ ${source}`;
4413
4761
  // depthOrArrayLayers = 0
4414
4762
  } = options;
4415
4763
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
4416
- const [sourceX, sourceY] = origin;
4764
+ const [sourceX = 0, sourceY = 0] = origin;
4417
4765
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
4418
4766
  const prevHandle = device.gl.bindFramebuffer(36160, framebuffer.handle);
4419
4767
  let texture;
@@ -4447,7 +4795,7 @@ ${source}`;
4447
4795
  }
4448
4796
  }
4449
4797
  function getFramebuffer(source) {
4450
- if (source instanceof import_core18.Texture) {
4798
+ if (source instanceof import_core20.Texture) {
4451
4799
  const { width, height, id } = source;
4452
4800
  const framebuffer = source.device.createFramebuffer({
4453
4801
  id: `framebuffer-for-${id}`,
@@ -4459,18 +4807,18 @@ ${source}`;
4459
4807
  }
4460
4808
  return { framebuffer: source, destroyFramebuffer: false };
4461
4809
  }
4462
- var import_core18, WEBGLCommandBuffer;
4810
+ var import_core20, WEBGLCommandBuffer;
4463
4811
  var init_webgl_command_buffer = __esm({
4464
4812
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-buffer.js"() {
4465
- import_core18 = __toESM(require_core2(), 1);
4813
+ import_core20 = __toESM(require_core2(), 1);
4466
4814
  init_webgl_texture();
4467
4815
  init_webgl_texture_table();
4468
- WEBGLCommandBuffer = class extends import_core18.CommandBuffer {
4816
+ WEBGLCommandBuffer = class extends import_core20.CommandBuffer {
4469
4817
  device;
4470
4818
  handle = null;
4471
4819
  commands = [];
4472
- constructor(device) {
4473
- super(device, {});
4820
+ constructor(device, props = {}) {
4821
+ super(device, props);
4474
4822
  this.device = device;
4475
4823
  }
4476
4824
  _executeCommands(commands = this.commands) {
@@ -4498,14 +4846,14 @@ ${source}`;
4498
4846
  });
4499
4847
 
4500
4848
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js
4501
- var import_core19, COLOR_CHANNELS, WEBGLRenderPass;
4849
+ var import_core21, COLOR_CHANNELS, WEBGLRenderPass;
4502
4850
  var init_webgl_render_pass = __esm({
4503
4851
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js"() {
4504
- import_core19 = __toESM(require_core2(), 1);
4852
+ import_core21 = __toESM(require_core2(), 1);
4505
4853
  init_with_parameters();
4506
4854
  init_unified_parameter_api();
4507
4855
  COLOR_CHANNELS = [1, 2, 4, 8];
4508
- WEBGLRenderPass = class extends import_core19.RenderPass {
4856
+ WEBGLRenderPass = class extends import_core21.RenderPass {
4509
4857
  device;
4510
4858
  handle = null;
4511
4859
  /** Parameters that should be applied before each draw call */
@@ -4513,6 +4861,9 @@ ${source}`;
4513
4861
  constructor(device, props) {
4514
4862
  super(device, props);
4515
4863
  this.device = device;
4864
+ if (!props?.framebuffer) {
4865
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4866
+ }
4516
4867
  let viewport;
4517
4868
  if (!props?.parameters?.viewport) {
4518
4869
  if (props?.framebuffer) {
@@ -4533,9 +4884,21 @@ ${source}`;
4533
4884
  this.device.gl.drawBuffers([1029]);
4534
4885
  }
4535
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
+ }
4536
4891
  }
4537
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
+ }
4538
4900
  this.device.popState();
4901
+ this.destroy();
4539
4902
  }
4540
4903
  pushDebugGroup(groupLabel) {
4541
4904
  }
@@ -4655,30 +5018,38 @@ ${source}`;
4655
5018
  });
4656
5019
 
4657
5020
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js
4658
- var import_core20, WEBGLCommandEncoder;
5021
+ var import_core22, WEBGLCommandEncoder;
4659
5022
  var init_webgl_command_encoder = __esm({
4660
5023
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js"() {
4661
- import_core20 = __toESM(require_core2(), 1);
5024
+ import_core22 = __toESM(require_core2(), 1);
4662
5025
  init_webgl_command_buffer();
4663
5026
  init_webgl_render_pass();
4664
- WEBGLCommandEncoder = class extends import_core20.CommandEncoder {
5027
+ WEBGLCommandEncoder = class extends import_core22.CommandEncoder {
4665
5028
  device;
4666
5029
  handle = null;
4667
5030
  commandBuffer;
4668
5031
  constructor(device, props) {
4669
5032
  super(device, props);
4670
5033
  this.device = device;
4671
- this.commandBuffer = new WEBGLCommandBuffer(device);
5034
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5035
+ id: `${this.props.id}-command-buffer`
5036
+ });
4672
5037
  }
4673
5038
  destroy() {
5039
+ this.destroyResource();
4674
5040
  }
4675
- 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();
4676
5047
  return this.commandBuffer;
4677
5048
  }
4678
- beginRenderPass(props) {
4679
- return new WEBGLRenderPass(this.device, props);
5049
+ beginRenderPass(props = {}) {
5050
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4680
5051
  }
4681
- beginComputePass(props) {
5052
+ beginComputePass(props = {}) {
4682
5053
  throw new Error("ComputePass not supported in WebGL");
4683
5054
  }
4684
5055
  copyBufferToBuffer(options) {
@@ -4704,6 +5075,10 @@ ${source}`;
4704
5075
  }
4705
5076
  resolveQuerySet(querySet, destination, options) {
4706
5077
  }
5078
+ writeTimestamp(querySet, queryIndex) {
5079
+ const webglQuerySet = querySet;
5080
+ webglQuerySet.writeTimestamp(queryIndex);
5081
+ }
4707
5082
  };
4708
5083
  }
4709
5084
  });
@@ -4715,7 +5090,7 @@ ${source}`;
4715
5090
  const total = count * length;
4716
5091
  let copied = 0;
4717
5092
  for (let i = start; copied < length; copied++) {
4718
- target2[i++] = source[copied];
5093
+ target2[i++] = source[copied] ?? 0;
4719
5094
  }
4720
5095
  while (copied < total) {
4721
5096
  if (copied < total - copied) {
@@ -4751,14 +5126,14 @@ ${source}`;
4751
5126
  }
4752
5127
  return true;
4753
5128
  }
4754
- var import_core21, WEBGLVertexArray;
5129
+ var import_core23, WEBGLVertexArray;
4755
5130
  var init_webgl_vertex_array = __esm({
4756
5131
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-vertex-array.js"() {
4757
- import_core21 = __toESM(require_core2(), 1);
5132
+ import_core23 = __toESM(require_core2(), 1);
4758
5133
  init_dist2();
4759
5134
  init_webgl_vertex_formats();
4760
5135
  init_fill_array();
4761
- WEBGLVertexArray = class extends import_core21.VertexArray {
5136
+ WEBGLVertexArray = class extends import_core23.VertexArray {
4762
5137
  get [Symbol.toStringTag]() {
4763
5138
  return "VertexArray";
4764
5139
  }
@@ -4924,7 +5299,7 @@ ${source}`;
4924
5299
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4925
5300
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4926
5301
  if (updateNeeded) {
4927
- const typedArray = (0, import_core21.getScratchArray)(value.constructor, length);
5302
+ const typedArray = (0, import_core23.getScratchArray)(value.constructor, length);
4928
5303
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4929
5304
  this.buffer.write(typedArray);
4930
5305
  this.bufferValue = value;
@@ -4942,13 +5317,13 @@ ${source}`;
4942
5317
  }
4943
5318
  return /^\d+$/.test(value);
4944
5319
  }
4945
- var import_core22, WEBGLTransformFeedback;
5320
+ var import_core24, WEBGLTransformFeedback;
4946
5321
  var init_webgl_transform_feedback = __esm({
4947
5322
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-transform-feedback.js"() {
4948
- import_core22 = __toESM(require_core2(), 1);
5323
+ import_core24 = __toESM(require_core2(), 1);
4949
5324
  init_dist3();
4950
5325
  init_webgl_topology_utils();
4951
- WEBGLTransformFeedback = class extends import_core22.TransformFeedback {
5326
+ WEBGLTransformFeedback = class extends import_core24.TransformFeedback {
4952
5327
  device;
4953
5328
  gl;
4954
5329
  handle;
@@ -5001,8 +5376,8 @@ ${source}`;
5001
5376
  this.buffers = {};
5002
5377
  this.unusedBuffers = {};
5003
5378
  this.bind(() => {
5004
- for (const bufferName in buffers) {
5005
- this.setBuffer(bufferName, buffers[bufferName]);
5379
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
5380
+ this.setBuffer(bufferName, buffer);
5006
5381
  }
5007
5382
  });
5008
5383
  }
@@ -5011,7 +5386,7 @@ ${source}`;
5011
5386
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
5012
5387
  if (location < 0) {
5013
5388
  this.unusedBuffers[locationOrName] = buffer;
5014
- import_core22.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5389
+ import_core24.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5015
5390
  return;
5016
5391
  }
5017
5392
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -5024,7 +5399,7 @@ ${source}`;
5024
5399
  return this.buffers[locationOrName] || null;
5025
5400
  }
5026
5401
  const location = this._getVaryingIndex(locationOrName);
5027
- return location >= 0 ? this.buffers[location] : null;
5402
+ return this.buffers[location] ?? null;
5028
5403
  }
5029
5404
  bind(funcOrHandle = this.handle) {
5030
5405
  if (typeof funcOrHandle !== "function") {
@@ -5071,8 +5446,8 @@ ${source}`;
5071
5446
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
5072
5447
  */
5073
5448
  _bindBuffers() {
5074
- for (const bufferIndex in this.buffers) {
5075
- 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);
5076
5451
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
5077
5452
  }
5078
5453
  }
@@ -5094,149 +5469,242 @@ ${source}`;
5094
5469
  });
5095
5470
 
5096
5471
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js
5097
- var import_core23, WEBGLQuerySet;
5472
+ var import_core25, WEBGLQuerySet;
5098
5473
  var init_webgl_query_set = __esm({
5099
5474
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js"() {
5100
- import_core23 = __toESM(require_core2(), 1);
5101
- WEBGLQuerySet = class extends import_core23.QuerySet {
5475
+ import_core25 = __toESM(require_core2(), 1);
5476
+ WEBGLQuerySet = class extends import_core25.QuerySet {
5102
5477
  device;
5103
5478
  handle;
5104
- target = null;
5105
- _queryPending = false;
5106
- _pollingPromise = null;
5479
+ _timestampPairs = [];
5480
+ _occlusionQuery = null;
5481
+ _occlusionActive = false;
5107
5482
  get [Symbol.toStringTag]() {
5108
- return "Query";
5483
+ return "QuerySet";
5109
5484
  }
5110
- // Create a query class
5111
5485
  constructor(device, props) {
5112
5486
  super(device, props);
5113
5487
  this.device = device;
5114
- if (props.count > 1) {
5115
- throw new Error("WebGL QuerySet can only have one value");
5116
- }
5117
- const handle = this.device.gl.createQuery();
5118
- if (!handle) {
5119
- 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;
5120
5503
  }
5121
- this.handle = handle;
5122
5504
  Object.seal(this);
5123
5505
  }
5124
5506
  destroy() {
5125
- 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();
5126
5525
  }
5127
- // FOR RENDER PASS AND COMMAND ENCODER
5128
- /**
5129
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
5130
- * Measures GPU time delta between this call and a matching `end` call in the
5131
- * GPU instruction stream.
5132
- */
5133
- beginTimestampQuery() {
5134
- 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)];
5135
5563
  }
5136
- endTimestampQuery() {
5137
- 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;
5138
5576
  }
5139
- // Shortcut for occlusion queries
5140
- beginOcclusionQuery(options) {
5141
- 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;
5142
5595
  }
5143
5596
  endOcclusionQuery() {
5144
- this._end();
5145
- }
5146
- // Shortcut for transformFeedbackQuery
5147
- beginTransformFeedbackQuery() {
5148
- return this._begin(35976);
5149
- }
5150
- endTransformFeedbackQuery() {
5151
- this._end();
5152
- }
5153
- async resolveQuery() {
5154
- const value = await this.pollQuery();
5155
- return [value];
5156
- }
5157
- // PRIVATE METHODS
5158
- /**
5159
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5160
- * instance, `end()` must be called on that same instance before
5161
- * calling `begin()` on another query. While there can be multiple
5162
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5163
- * It is not possible to interleave or overlap `begin` and `end` calls.
5164
- */
5165
- _begin(target2) {
5166
- if (this._queryPending) {
5167
- return;
5597
+ if (!this._occlusionActive) {
5598
+ throw new Error("Occlusion query is not active");
5168
5599
  }
5169
- this.target = target2;
5170
- this.device.gl.beginQuery(this.target, this.handle);
5171
- return;
5600
+ this.device.gl.endQuery(35887);
5601
+ this._occlusionActive = false;
5172
5602
  }
5173
- // ends the current query
5174
- _end() {
5175
- 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;
5176
5625
  return;
5177
5626
  }
5178
- if (this.target) {
5179
- this.device.gl.endQuery(this.target);
5180
- this.target = null;
5181
- this._queryPending = true;
5627
+ if (!pair.activeQuery) {
5628
+ throw new Error("Timestamp query pair was ended before it was started");
5182
5629
  }
5183
- return;
5630
+ this.device.gl.endQuery(35007);
5631
+ pair.completedQueries.push(pair.activeQuery);
5632
+ pair.activeQuery = null;
5184
5633
  }
5185
- // Returns true if the query result is available
5186
- isResultAvailable() {
5187
- if (!this._queryPending) {
5188
- return false;
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");
5189
5637
  }
5190
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
5191
- if (resultAvailable) {
5192
- this._queryPending = false;
5638
+ }
5639
+ _getTimestampPairIndex(queryIndex) {
5640
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
5641
+ throw new Error("Query index is out of bounds");
5193
5642
  }
5194
- return resultAvailable;
5643
+ return Math.floor(queryIndex / 2);
5195
5644
  }
5196
- // Timing query is disjoint, i.e. results are invalid
5197
- isTimerDisjoint() {
5198
- return this.device.gl.getParameter(36795);
5645
+ _isTimestampPairAvailable(pairIndex) {
5646
+ const pair = this._timestampPairs[pairIndex];
5647
+ if (!pair || pair.completedQueries.length === 0) {
5648
+ return false;
5649
+ }
5650
+ return this._pollQueryAvailability(pair.completedQueries[0]);
5199
5651
  }
5200
- // Returns query result.
5201
- getResult() {
5202
- return this.device.gl.getQueryParameter(this.handle, 34918);
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;
5203
5664
  }
5204
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5205
- getTimerMilliseconds() {
5206
- return this.getResult() / 1e6;
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
+ }
5207
5676
  }
5208
- // Polls the query
5209
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5210
- if (this._pollingPromise) {
5211
- return this._pollingPromise;
5677
+ _consumeQueryResult(query) {
5678
+ if (query.promise) {
5679
+ return query.promise;
5212
5680
  }
5213
- let counter = 0;
5214
- this._pollingPromise = new Promise((resolve, reject) => {
5681
+ query.promise = new Promise((resolve, reject) => {
5215
5682
  const poll = () => {
5216
- if (this.isResultAvailable()) {
5217
- resolve(this.getResult());
5218
- this._pollingPromise = null;
5219
- } else if (counter++ > limit) {
5220
- reject("Timed out");
5221
- this._pollingPromise = null;
5222
- } else {
5683
+ if (!this._pollQueryAvailability(query)) {
5223
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);
5224
5692
  }
5225
5693
  };
5226
- requestAnimationFrame(poll);
5694
+ poll();
5227
5695
  });
5228
- return this._pollingPromise;
5696
+ return query.promise;
5229
5697
  }
5230
5698
  };
5231
5699
  }
5232
5700
  });
5233
5701
 
5234
5702
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js
5235
- var import_core24, WEBGLFence;
5703
+ var import_core26, WEBGLFence;
5236
5704
  var init_webgl_fence = __esm({
5237
5705
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js"() {
5238
- import_core24 = __toESM(require_core2(), 1);
5239
- WEBGLFence = class extends import_core24.Fence {
5706
+ import_core26 = __toESM(require_core2(), 1);
5707
+ WEBGLFence = class extends import_core26.Fence {
5240
5708
  device;
5241
5709
  gl;
5242
5710
  handle;
@@ -5355,7 +5823,7 @@ ${source}`;
5355
5823
  sourceFormat ||= texture?.glFormat || 6408;
5356
5824
  sourceType ||= texture?.glType || 5121;
5357
5825
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5358
- const signedType = (0, import_core25.getDataType)(target2);
5826
+ const signedType = (0, import_core27.getDataType)(target2);
5359
5827
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5360
5828
  const prevHandle = gl.bindFramebuffer(36160, handle);
5361
5829
  gl.readBuffer(36064 + sourceAttachment);
@@ -5398,7 +5866,7 @@ ${source}`;
5398
5866
  return webglBufferTarget;
5399
5867
  }
5400
5868
  function getFramebuffer2(source) {
5401
- if (!(source instanceof import_core25.Framebuffer)) {
5869
+ if (!(source instanceof import_core27.Framebuffer)) {
5402
5870
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5403
5871
  }
5404
5872
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5420,14 +5888,14 @@ ${source}`;
5420
5888
  }
5421
5889
  glType ||= 5121;
5422
5890
  const shaderType = convertGLDataTypeToDataType(glType);
5423
- const ArrayType = (0, import_core25.getTypedArrayConstructor)(shaderType);
5891
+ const ArrayType = (0, import_core27.getTypedArrayConstructor)(shaderType);
5424
5892
  const components = glFormatToComponents(glFormat);
5425
5893
  return new ArrayType(width * height * components);
5426
5894
  }
5427
- var import_core25;
5895
+ var import_core27;
5428
5896
  var init_webgl_texture_utils = __esm({
5429
5897
  "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js"() {
5430
- import_core25 = __toESM(require_core2(), 1);
5898
+ import_core27 = __toESM(require_core2(), 1);
5431
5899
  init_webgl_shadertypes();
5432
5900
  init_format_utils();
5433
5901
  init_shader_formats();
@@ -5469,16 +5937,18 @@ ${source}`;
5469
5937
  }
5470
5938
  return true;
5471
5939
  }
5472
- var import_core26, WebGLDevice;
5940
+ var import_core28, WebGLDevice;
5473
5941
  var init_webgl_device = __esm({
5474
5942
  "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-device.js"() {
5475
- import_core26 = __toESM(require_core2(), 1);
5943
+ import_core28 = __toESM(require_core2(), 1);
5476
5944
  init_webgl_state_tracker();
5477
5945
  init_create_browser_context();
5946
+ init_webgl_context_data();
5478
5947
  init_webgl_device_info();
5479
5948
  init_webgl_device_features();
5480
5949
  init_webgl_device_limits();
5481
5950
  init_webgl_canvas_context();
5951
+ init_webgl_presentation_context();
5482
5952
  init_spector();
5483
5953
  init_webgl_developer_tools();
5484
5954
  init_webgl_texture_table();
@@ -5489,6 +5959,7 @@ ${source}`;
5489
5959
  init_webgl_texture();
5490
5960
  init_webgl_framebuffer();
5491
5961
  init_webgl_render_pipeline();
5962
+ init_webgl_shared_render_pipeline();
5492
5963
  init_webgl_command_encoder();
5493
5964
  init_webgl_vertex_array();
5494
5965
  init_webgl_transform_feedback();
@@ -5498,7 +5969,13 @@ ${source}`;
5498
5969
  init_unified_parameter_api();
5499
5970
  init_with_parameters();
5500
5971
  init_webgl_extensions();
5501
- WebGLDevice = class extends import_core26.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
+ }
5502
5979
  // Public `Device` API
5503
5980
  /** type of this device */
5504
5981
  type = "webgl";
@@ -5520,7 +5997,7 @@ ${source}`;
5520
5997
  // @ts-ignore TODO fix
5521
5998
  _constants;
5522
5999
  /** State used by luma.gl classes - TODO - not used? */
5523
- _extensions = {};
6000
+ extensions;
5524
6001
  _polyfilled = false;
5525
6002
  /** Instance of Spector.js (if initialized) */
5526
6003
  spectorJS;
@@ -5543,11 +6020,12 @@ ${source}`;
5543
6020
  }
5544
6021
  constructor(props) {
5545
6022
  super({ ...props, id: props.id || uid("webgl-device") });
5546
- const canvasContextProps = import_core26.Device._getCanvasContextProps(props);
6023
+ const canvasContextProps = import_core28.Device._getCanvasContextProps(props);
5547
6024
  if (!canvasContextProps) {
5548
6025
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5549
6026
  }
5550
- let device = canvasContextProps.canvas?.gl?.device;
6027
+ const existingContext = canvasContextProps.canvas?.gl ?? null;
6028
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5551
6029
  if (device) {
5552
6030
  throw new Error(`WebGL context already attached to device ${device.id}`);
5553
6031
  }
@@ -5577,10 +6055,11 @@ ${source}`;
5577
6055
  if (!gl) {
5578
6056
  throw new Error("WebGL context creation failed");
5579
6057
  }
5580
- device = gl.device;
6058
+ device = WebGLDevice.getDeviceFromContext(gl);
5581
6059
  if (device) {
5582
6060
  if (props._reuseDevices) {
5583
- import_core26.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();
5584
6063
  device._reused = true;
5585
6064
  return device;
5586
6065
  }
@@ -5589,25 +6068,28 @@ ${source}`;
5589
6068
  this.handle = gl;
5590
6069
  this.gl = gl;
5591
6070
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5592
- this.gl.device = this;
5593
- 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);
5594
6075
  this.limits = new WebGLDeviceLimits(this.gl);
5595
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
6076
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5596
6077
  if (this.props._initializeFeatures) {
5597
6078
  this.features.initializeFeatures();
5598
6079
  }
5599
6080
  const glState = new WebGLStateTracker(this.gl, {
5600
- log: (...args) => import_core26.log.log(1, ...args)()
6081
+ log: (...args) => import_core28.log.log(1, ...args)()
5601
6082
  });
5602
6083
  glState.trackState(this.gl, { copyState: false });
5603
6084
  if (props.debug || props.debugWebGL) {
5604
6085
  this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
5605
- import_core26.log.warn("WebGL debug mode activated. Performance reduced.")();
6086
+ import_core28.log.warn("WebGL debug mode activated. Performance reduced.")();
5606
6087
  }
5607
6088
  if (props.debugWebGL) {
5608
- import_core26.log.level = Math.max(import_core26.log.level, 1);
6089
+ import_core28.log.level = Math.max(import_core28.log.level, 1);
5609
6090
  }
5610
6091
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6092
+ this.canvasContext._startObservers();
5611
6093
  }
5612
6094
  /**
5613
6095
  * Destroys the device
@@ -5620,8 +6102,10 @@ ${source}`;
5620
6102
  * browser API for destroying WebGL contexts.
5621
6103
  */
5622
6104
  destroy() {
6105
+ this.commandEncoder?.destroy();
5623
6106
  if (!this.props._reuseDevices && !this._reused) {
5624
- delete this.gl.device;
6107
+ const contextData = getWebGLContextData(this.handle);
6108
+ contextData.device = null;
5625
6109
  }
5626
6110
  }
5627
6111
  get isLost() {
@@ -5631,6 +6115,9 @@ ${source}`;
5631
6115
  createCanvasContext(props) {
5632
6116
  throw new Error("WebGL only supports a single canvas");
5633
6117
  }
6118
+ createPresentationContext(props) {
6119
+ return new WebGLPresentationContext(this, props || {});
6120
+ }
5634
6121
  createBuffer(props) {
5635
6122
  const newProps = this._normalizeBufferProps(props);
5636
6123
  return new WEBGLBuffer(this, newProps);
@@ -5665,6 +6152,9 @@ ${source}`;
5665
6152
  createRenderPipeline(props) {
5666
6153
  return new WEBGLRenderPipeline(this, props);
5667
6154
  }
6155
+ _createSharedRenderPipelineWebGL(props) {
6156
+ return new WEBGLSharedRenderPipeline(this, props);
6157
+ }
5668
6158
  createComputePipeline(props) {
5669
6159
  throw new Error("ComputePipeline not supported in WebGL");
5670
6160
  }
@@ -5677,12 +6167,27 @@ ${source}`;
5677
6167
  * Chrome's offscreen canvas does not require gl.commit
5678
6168
  */
5679
6169
  submit(commandBuffer) {
6170
+ let submittedCommandEncoder = null;
5680
6171
  if (!commandBuffer) {
5681
- commandBuffer = this.commandEncoder.finish();
6172
+ submittedCommandEncoder = this.commandEncoder;
6173
+ commandBuffer = submittedCommandEncoder.finish();
5682
6174
  this.commandEncoder.destroy();
5683
- 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();
5684
6190
  }
5685
- commandBuffer._executeCommands();
5686
6191
  }
5687
6192
  //
5688
6193
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5705,11 +6210,11 @@ ${source}`;
5705
6210
  return withGLParameters(this.gl, parameters, func);
5706
6211
  }
5707
6212
  resetWebGL() {
5708
- import_core26.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6213
+ import_core28.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5709
6214
  resetGLParameters(this.gl);
5710
6215
  }
5711
6216
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5712
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
6217
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5713
6218
  }
5714
6219
  //
5715
6220
  // WebGL-only API (not part of `Device` API)
@@ -5777,7 +6282,7 @@ ${source}`;
5777
6282
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5778
6283
  const currentConstant = this._constants[location];
5779
6284
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5780
- import_core26.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`)();
5781
6286
  }
5782
6287
  this._constants[location] = constant;
5783
6288
  switch (constant.constructor) {
@@ -5796,8 +6301,8 @@ ${source}`;
5796
6301
  }
5797
6302
  /** Ensure extensions are only requested once */
5798
6303
  getExtension(name) {
5799
- getWebGLExtension(this.gl, name, this._extensions);
5800
- return this._extensions;
6304
+ getWebGLExtension(this.gl, name, this.extensions);
6305
+ return this.extensions;
5801
6306
  }
5802
6307
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
5803
6308
  /**
@@ -6121,12 +6626,12 @@ ${source}`;
6121
6626
  }
6122
6627
 
6123
6628
  // dist/commons.js
6124
- var import_core27 = __toESM(require_core(), 1);
6629
+ var import_core29 = __toESM(require_core(), 1);
6125
6630
  var import_engine = __toESM(require_engine(), 1);
6126
6631
  init_dist3();
6127
6632
  async function createDeckInstance(gl) {
6128
6633
  return new Promise((resolve) => {
6129
- const deckInstance = new import_core27.Deck({
6634
+ const deckInstance = new import_core29.Deck({
6130
6635
  // Input is handled by the ArcGIS API for JavaScript.
6131
6636
  controller: false,
6132
6637
  // We use the same WebGL context as the ArcGIS API for JavaScript.