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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -717,6 +717,23 @@ var __exports__ = (() => {
717
717
  }
718
718
  });
719
719
 
720
+ // ../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js
721
+ function getWebGLContextData(gl) {
722
+ const contextData = gl.luma || {
723
+ _polyfilled: false,
724
+ extensions: {},
725
+ softwareRenderer: false
726
+ };
727
+ contextData._polyfilled ??= false;
728
+ contextData.extensions ||= {};
729
+ gl.luma = contextData;
730
+ return contextData;
731
+ }
732
+ var init_webgl_context_data = __esm({
733
+ "../../node_modules/@luma.gl/webgl/dist/context/helpers/webgl-context-data.js"() {
734
+ }
735
+ });
736
+
720
737
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js
721
738
  function initializeSpectorJS(props) {
722
739
  props = { ...DEFAULT_SPECTOR_PROPS, ...props };
@@ -747,9 +764,10 @@ var __exports__ = (() => {
747
764
  }
748
765
  if (props.gl) {
749
766
  const gl = props.gl;
750
- const device = gl.device;
767
+ const contextData = getWebGLContextData(gl);
768
+ const device = contextData.device;
751
769
  spector?.startCapture(props.gl, 500);
752
- gl.device = device;
770
+ contextData.device = device;
753
771
  new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
754
772
  import_core2.log.info("Spector capture stopped after 2 seconds")();
755
773
  spector?.stopCapture();
@@ -761,6 +779,7 @@ var __exports__ = (() => {
761
779
  var init_spector = __esm({
762
780
  "../../node_modules/@luma.gl/webgl/dist/context/debug/spector.js"() {
763
781
  import_core2 = __toESM(require_core2(), 1);
782
+ init_webgl_context_data();
764
783
  LOG_LEVEL = 1;
765
784
  spector = null;
766
785
  initialized = false;
@@ -856,7 +875,7 @@ var __exports__ = (() => {
856
875
  });
857
876
 
858
877
  // ../../node_modules/@luma.gl/webgl/dist/context/debug/webgl-developer-tools.js
859
- function getWebGLContextData(gl) {
878
+ function getWebGLContextData2(gl) {
860
879
  gl.luma = gl.luma || {};
861
880
  return gl.luma;
862
881
  }
@@ -864,7 +883,7 @@ var __exports__ = (() => {
864
883
  return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
865
884
  }
866
885
  function getRealContext(gl) {
867
- const data = getWebGLContextData(gl);
886
+ const data = getWebGLContextData2(gl);
868
887
  return data.realContext ? data.realContext : gl;
869
888
  }
870
889
  function getDebugContext(gl, props) {
@@ -872,7 +891,7 @@ var __exports__ = (() => {
872
891
  import_core3.log.warn("webgl-debug not loaded")();
873
892
  return gl;
874
893
  }
875
- const data = getWebGLContextData(gl);
894
+ const data = getWebGLContextData2(gl);
876
895
  if (data.debugContext) {
877
896
  return data.debugContext;
878
897
  }
@@ -890,6 +909,7 @@ var __exports__ = (() => {
890
909
  const debugContext = Object.create(WebGLDebugContext);
891
910
  data.realContext = gl;
892
911
  data.debugContext = debugContext;
912
+ debugContext.luma = data;
893
913
  debugContext.debug = true;
894
914
  return debugContext;
895
915
  }
@@ -1420,7 +1440,7 @@ var __exports__ = (() => {
1420
1440
  }
1421
1441
  }
1422
1442
  }
1423
- const cache = gl.state && gl.state.cache;
1443
+ const cache = gl.lumaState?.cache;
1424
1444
  if (cache) {
1425
1445
  for (const key in compositeSetters) {
1426
1446
  const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key];
@@ -1540,7 +1560,7 @@ var __exports__ = (() => {
1540
1560
  init_webgl_parameter_tables();
1541
1561
  WebGLStateTracker = class {
1542
1562
  static get(gl) {
1543
- return gl.state;
1563
+ return gl.lumaState;
1544
1564
  }
1545
1565
  gl;
1546
1566
  program = null;
@@ -1578,7 +1598,7 @@ var __exports__ = (() => {
1578
1598
  throw new Error("WebGLStateTracker");
1579
1599
  }
1580
1600
  this.initialized = true;
1581
- this.gl.state = this;
1601
+ this.gl.lumaState = this;
1582
1602
  installProgramSpy(gl);
1583
1603
  for (const key in GL_HOOKED_SETTERS) {
1584
1604
  const setter = GL_HOOKED_SETTERS[key];
@@ -1638,13 +1658,11 @@ var __exports__ = (() => {
1638
1658
  if (!gl && webglProps.failIfMajorPerformanceCaveat) {
1639
1659
  errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
1640
1660
  }
1661
+ let softwareRenderer = false;
1641
1662
  if (!gl && allowSoftwareRenderer) {
1642
1663
  webglProps.failIfMajorPerformanceCaveat = false;
1643
1664
  gl = canvas.getContext("webgl2", webglProps);
1644
- if (gl) {
1645
- gl.luma ||= {};
1646
- gl.luma.softwareRenderer = true;
1647
- }
1665
+ softwareRenderer = true;
1648
1666
  }
1649
1667
  if (!gl) {
1650
1668
  gl = canvas.getContext("webgl", {});
@@ -1657,10 +1675,11 @@ var __exports__ = (() => {
1657
1675
  errorMessage ||= "Your browser does not support WebGL";
1658
1676
  throw new Error(`Failed to create WebGL context: ${errorMessage}`);
1659
1677
  }
1678
+ const luma = getWebGLContextData(gl);
1679
+ luma.softwareRenderer = softwareRenderer;
1660
1680
  const { onContextLost, onContextRestored } = props;
1661
1681
  canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
1662
1682
  canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
1663
- gl.luma ||= {};
1664
1683
  return gl;
1665
1684
  } finally {
1666
1685
  canvas.removeEventListener("webglcontextcreationerror", onCreateError, false);
@@ -1668,6 +1687,7 @@ var __exports__ = (() => {
1668
1687
  }
1669
1688
  var init_create_browser_context = __esm({
1670
1689
  "../../node_modules/@luma.gl/webgl/dist/context/helpers/create-browser-context.js"() {
1690
+ init_webgl_context_data();
1671
1691
  }
1672
1692
  });
1673
1693
 
@@ -1744,6 +1764,8 @@ var __exports__ = (() => {
1744
1764
  }
1745
1765
  const gpuVendor = identifyGPUVendor(vendor, renderer);
1746
1766
  switch (gpuVendor) {
1767
+ case "apple":
1768
+ return isAppleSiliconGPU(vendor, renderer) ? "integrated" : "unknown";
1747
1769
  case "intel":
1748
1770
  return "integrated";
1749
1771
  case "software":
@@ -1754,6 +1776,9 @@ var __exports__ = (() => {
1754
1776
  return "discrete";
1755
1777
  }
1756
1778
  }
1779
+ function isAppleSiliconGPU(vendor, renderer) {
1780
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
1781
+ }
1757
1782
  var init_webgl_device_info = __esm({
1758
1783
  "../../node_modules/@luma.gl/webgl/dist/adapter/device-helpers/webgl-device-info.js"() {
1759
1784
  init_webgl_extensions();
@@ -1800,8 +1825,23 @@ var __exports__ = (() => {
1800
1825
  return feature in TEXTURE_FEATURES;
1801
1826
  }
1802
1827
  function checkTextureFeature(gl, feature, extensions) {
1803
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
1804
- return textureExtensions.every((extension) => getWebGLExtension(gl, extension, extensions));
1828
+ return hasTextureFeature(gl, feature, extensions, /* @__PURE__ */ new Set());
1829
+ }
1830
+ function hasTextureFeature(gl, feature, extensions, seenFeatures) {
1831
+ const definition = TEXTURE_FEATURES[feature];
1832
+ if (!definition) {
1833
+ return false;
1834
+ }
1835
+ if (seenFeatures.has(feature)) {
1836
+ return false;
1837
+ }
1838
+ seenFeatures.add(feature);
1839
+ const hasDependentFeatures = (definition.features || []).every((dependentFeature) => hasTextureFeature(gl, dependentFeature, extensions, seenFeatures));
1840
+ seenFeatures.delete(feature);
1841
+ if (!hasDependentFeatures) {
1842
+ return false;
1843
+ }
1844
+ return (definition.extensions || []).every((extension) => Boolean(getWebGLExtension(gl, extension, extensions)));
1805
1845
  }
1806
1846
  function getTextureFormatCapabilitiesWebGL(gl, formatSupport, extensions) {
1807
1847
  let supported = formatSupport.create;
@@ -1812,12 +1852,17 @@ var __exports__ = (() => {
1812
1852
  if (webglFormatInfo?.x) {
1813
1853
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
1814
1854
  }
1855
+ if (formatSupport.format === "stencil8") {
1856
+ supported = false;
1857
+ }
1858
+ const renderFeatureSupported = webglFormatInfo?.r === false ? false : webglFormatInfo?.r === void 0 || checkTextureFeature(gl, webglFormatInfo.r, extensions);
1859
+ const renderable = supported && formatSupport.render && renderFeatureSupported && isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
1815
1860
  return {
1816
1861
  format: formatSupport.format,
1817
1862
  // @ts-ignore
1818
1863
  create: supported && formatSupport.create,
1819
1864
  // @ts-ignore
1820
- render: supported && formatSupport.render,
1865
+ render: renderable,
1821
1866
  // @ts-ignore
1822
1867
  filter: supported && formatSupport.filter,
1823
1868
  // @ts-ignore
@@ -1826,6 +1871,45 @@ var __exports__ = (() => {
1826
1871
  store: supported && formatSupport.store
1827
1872
  };
1828
1873
  }
1874
+ function isColorRenderableTextureFormat(gl, format, extensions) {
1875
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
1876
+ const internalFormat = webglFormatInfo?.gl;
1877
+ if (internalFormat === void 0) {
1878
+ return false;
1879
+ }
1880
+ if (webglFormatInfo?.x && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
1881
+ return false;
1882
+ }
1883
+ const previousTexture = gl.getParameter(32873);
1884
+ const previousFramebuffer = gl.getParameter(36006);
1885
+ const texture = gl.createTexture();
1886
+ const framebuffer = gl.createFramebuffer();
1887
+ if (!texture || !framebuffer) {
1888
+ return false;
1889
+ }
1890
+ const noError = Number(0);
1891
+ let error = Number(gl.getError());
1892
+ while (error !== noError) {
1893
+ error = gl.getError();
1894
+ }
1895
+ let renderable = false;
1896
+ try {
1897
+ gl.bindTexture(3553, texture);
1898
+ gl.texStorage2D(3553, 1, internalFormat, 1, 1);
1899
+ if (Number(gl.getError()) !== noError) {
1900
+ return false;
1901
+ }
1902
+ gl.bindFramebuffer(36160, framebuffer);
1903
+ gl.framebufferTexture2D(36160, 36064, 3553, texture, 0);
1904
+ renderable = Number(gl.checkFramebufferStatus(36160)) === Number(36053) && Number(gl.getError()) === noError;
1905
+ } finally {
1906
+ gl.bindFramebuffer(36160, previousFramebuffer);
1907
+ gl.deleteFramebuffer(framebuffer);
1908
+ gl.bindTexture(3553, previousTexture);
1909
+ gl.deleteTexture(texture);
1910
+ }
1911
+ return renderable;
1912
+ }
1829
1913
  function getTextureFormatWebGL(format) {
1830
1914
  const formatData = WEBGL_TEXTURE_FORMATS[format];
1831
1915
  const webglFormat = convertTextureFormatToGL(format);
@@ -1881,7 +1965,7 @@ var __exports__ = (() => {
1881
1965
  }
1882
1966
  return webglFormat;
1883
1967
  }
1884
- var import_core4, X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC, X_ETC2, X_ASTC, X_ETC1, X_PVRTC, X_ATC, EXT_texture_norm16, EXT_render_snorm, EXT_color_buffer_float, TEXTURE_FEATURES, WEBGL_TEXTURE_FORMATS;
1968
+ var import_core4, X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC, X_ETC2, X_ASTC, X_ETC1, X_PVRTC, X_ATC, EXT_texture_norm16, EXT_render_snorm, EXT_color_buffer_float, SNORM8_COLOR_RENDERABLE, NORM16_COLOR_RENDERABLE, SNORM16_COLOR_RENDERABLE, FLOAT16_COLOR_RENDERABLE, FLOAT32_COLOR_RENDERABLE, RGB9E5UFLOAT_COLOR_RENDERABLE, TEXTURE_FEATURES, WEBGL_TEXTURE_FORMATS;
1885
1969
  var init_webgl_texture_table = __esm({
1886
1970
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-texture-table.js"() {
1887
1971
  import_core4 = __toESM(require_core2(), 1);
@@ -1899,44 +1983,51 @@ var __exports__ = (() => {
1899
1983
  EXT_texture_norm16 = "EXT_texture_norm16";
1900
1984
  EXT_render_snorm = "EXT_render_snorm";
1901
1985
  EXT_color_buffer_float = "EXT_color_buffer_float";
1986
+ SNORM8_COLOR_RENDERABLE = "snorm8-renderable-webgl";
1987
+ NORM16_COLOR_RENDERABLE = "norm16-renderable-webgl";
1988
+ SNORM16_COLOR_RENDERABLE = "snorm16-renderable-webgl";
1989
+ FLOAT16_COLOR_RENDERABLE = "float16-renderable-webgl";
1990
+ FLOAT32_COLOR_RENDERABLE = "float32-renderable-webgl";
1991
+ RGB9E5UFLOAT_COLOR_RENDERABLE = "rgb9e5ufloat-renderable-webgl";
1902
1992
  TEXTURE_FEATURES = {
1903
- "float32-renderable-webgl": ["EXT_color_buffer_float"],
1904
- "float16-renderable-webgl": ["EXT_color_buffer_half_float"],
1905
- "rgb9e5ufloat-renderable-webgl": ["WEBGL_render_shared_exponent"],
1906
- "snorm8-renderable-webgl": [EXT_render_snorm],
1907
- "norm16-renderable-webgl": [EXT_texture_norm16],
1908
- "snorm16-renderable-webgl": [EXT_texture_norm16, EXT_render_snorm],
1909
- "float32-filterable": ["OES_texture_float_linear"],
1910
- "float16-filterable-webgl": ["OES_texture_half_float_linear"],
1911
- "texture-filterable-anisotropic-webgl": ["EXT_texture_filter_anisotropic"],
1912
- "texture-blend-float-webgl": ["EXT_float_blend"],
1913
- "texture-compression-bc": [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
1993
+ "float32-renderable-webgl": { extensions: [EXT_color_buffer_float] },
1994
+ "float16-renderable-webgl": { extensions: ["EXT_color_buffer_half_float"] },
1995
+ "rgb9e5ufloat-renderable-webgl": { extensions: ["WEBGL_render_shared_exponent"] },
1996
+ "snorm8-renderable-webgl": { extensions: [EXT_render_snorm] },
1997
+ "norm16-webgl": { extensions: [EXT_texture_norm16] },
1998
+ "norm16-renderable-webgl": { features: ["norm16-webgl"] },
1999
+ "snorm16-renderable-webgl": { features: ["norm16-webgl"], extensions: [EXT_render_snorm] },
2000
+ "float32-filterable": { extensions: ["OES_texture_float_linear"] },
2001
+ "float16-filterable-webgl": { extensions: ["OES_texture_half_float_linear"] },
2002
+ "texture-filterable-anisotropic-webgl": { extensions: ["EXT_texture_filter_anisotropic"] },
2003
+ "texture-blend-float-webgl": { extensions: ["EXT_float_blend"] },
2004
+ "texture-compression-bc": { extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC] },
1914
2005
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
1915
2006
  // 'texture-compression-bc3-webgl': [X_S3TC],
1916
- "texture-compression-bc5-webgl": [X_RGTC],
1917
- "texture-compression-bc7-webgl": [X_BPTC],
1918
- "texture-compression-etc2": [X_ETC2],
1919
- "texture-compression-astc": [X_ASTC],
1920
- "texture-compression-etc1-webgl": [X_ETC1],
1921
- "texture-compression-pvrtc-webgl": [X_PVRTC],
1922
- "texture-compression-atc-webgl": [X_ATC]
2007
+ "texture-compression-bc5-webgl": { extensions: [X_RGTC] },
2008
+ "texture-compression-bc7-webgl": { extensions: [X_BPTC] },
2009
+ "texture-compression-etc2": { extensions: [X_ETC2] },
2010
+ "texture-compression-astc": { extensions: [X_ASTC] },
2011
+ "texture-compression-etc1-webgl": { extensions: [X_ETC1] },
2012
+ "texture-compression-pvrtc-webgl": { extensions: [X_PVRTC] },
2013
+ "texture-compression-atc-webgl": { extensions: [X_ATC] }
1923
2014
  };
1924
2015
  WEBGL_TEXTURE_FORMATS = {
1925
2016
  // 8-bit formats
1926
2017
  "r8unorm": { gl: 33321, rb: true },
1927
- "r8snorm": { gl: 36756 },
2018
+ "r8snorm": { gl: 36756, r: SNORM8_COLOR_RENDERABLE },
1928
2019
  "r8uint": { gl: 33330, rb: true },
1929
2020
  "r8sint": { gl: 33329, rb: true },
1930
2021
  // 16-bit formats
1931
2022
  "rg8unorm": { gl: 33323, rb: true },
1932
- "rg8snorm": { gl: 36757 },
2023
+ "rg8snorm": { gl: 36757, r: SNORM8_COLOR_RENDERABLE },
1933
2024
  "rg8uint": { gl: 33336, rb: true },
1934
2025
  "rg8sint": { gl: 33335, rb: true },
1935
2026
  "r16uint": { gl: 33332, rb: true },
1936
2027
  "r16sint": { gl: 33331, rb: true },
1937
- "r16float": { gl: 33325, rb: true },
1938
- "r16unorm": { gl: 33322, rb: true },
1939
- "r16snorm": { gl: 36760 },
2028
+ "r16float": { gl: 33325, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2029
+ "r16unorm": { gl: 33322, rb: true, r: NORM16_COLOR_RENDERABLE },
2030
+ "r16snorm": { gl: 36760, r: SNORM16_COLOR_RENDERABLE },
1940
2031
  // Packed 16-bit formats
1941
2032
  "rgba4unorm-webgl": { gl: 32854, rb: true },
1942
2033
  "rgb565unorm-webgl": { gl: 36194, rb: true },
@@ -1947,7 +2038,7 @@ var __exports__ = (() => {
1947
2038
  // 32-bit formats
1948
2039
  "rgba8unorm": { gl: 32856 },
1949
2040
  "rgba8unorm-srgb": { gl: 35907 },
1950
- "rgba8snorm": { gl: 36759 },
2041
+ "rgba8snorm": { gl: 36759, r: SNORM8_COLOR_RENDERABLE },
1951
2042
  "rgba8uint": { gl: 36220 },
1952
2043
  "rgba8sint": { gl: 36238 },
1953
2044
  // reverse colors, webgpu only
@@ -1955,38 +2046,38 @@ var __exports__ = (() => {
1955
2046
  "bgra8unorm-srgb": {},
1956
2047
  "rg16uint": { gl: 33338 },
1957
2048
  "rg16sint": { gl: 33337 },
1958
- "rg16float": { gl: 33327, rb: true },
1959
- "rg16unorm": { gl: 33324 },
1960
- "rg16snorm": { gl: 36761 },
2049
+ "rg16float": { gl: 33327, rb: true, r: FLOAT16_COLOR_RENDERABLE },
2050
+ "rg16unorm": { gl: 33324, r: NORM16_COLOR_RENDERABLE },
2051
+ "rg16snorm": { gl: 36761, r: SNORM16_COLOR_RENDERABLE },
1961
2052
  "r32uint": { gl: 33334, rb: true },
1962
2053
  "r32sint": { gl: 33333, rb: true },
1963
- "r32float": { gl: 33326 },
2054
+ "r32float": { gl: 33326, r: FLOAT32_COLOR_RENDERABLE },
1964
2055
  // Packed 32-bit formats
1965
- "rgb9e5ufloat": { gl: 35901 },
2056
+ "rgb9e5ufloat": { gl: 35901, r: RGB9E5UFLOAT_COLOR_RENDERABLE },
1966
2057
  // , filter: true},
1967
2058
  "rg11b10ufloat": { gl: 35898, rb: true },
1968
2059
  "rgb10a2unorm": { gl: 32857, rb: true },
1969
2060
  "rgb10a2uint": { gl: 36975, rb: true },
1970
2061
  // 48-bit formats
1971
- "rgb16unorm-webgl": { gl: 32852 },
2062
+ "rgb16unorm-webgl": { gl: 32852, r: false },
1972
2063
  // rgb not renderable
1973
- "rgb16snorm-webgl": { gl: 36762 },
2064
+ "rgb16snorm-webgl": { gl: 36762, r: false },
1974
2065
  // rgb not renderable
1975
2066
  // 64-bit formats
1976
2067
  "rg32uint": { gl: 33340, rb: true },
1977
2068
  "rg32sint": { gl: 33339, rb: true },
1978
- "rg32float": { gl: 33328, rb: true },
2069
+ "rg32float": { gl: 33328, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1979
2070
  "rgba16uint": { gl: 36214, rb: true },
1980
2071
  "rgba16sint": { gl: 36232, rb: true },
1981
- "rgba16float": { gl: 34842 },
1982
- "rgba16unorm": { gl: 32859, rb: true },
1983
- "rgba16snorm": { gl: 36763 },
2072
+ "rgba16float": { gl: 34842, r: FLOAT16_COLOR_RENDERABLE },
2073
+ "rgba16unorm": { gl: 32859, rb: true, r: NORM16_COLOR_RENDERABLE },
2074
+ "rgba16snorm": { gl: 36763, r: SNORM16_COLOR_RENDERABLE },
1984
2075
  // 96-bit formats (deprecated!)
1985
- "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, dataFormat: 6407, types: [5126] },
2076
+ "rgb32float-webgl": { gl: 34837, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: 6407, types: [5126] },
1986
2077
  // 128-bit formats
1987
2078
  "rgba32uint": { gl: 36208, rb: true },
1988
2079
  "rgba32sint": { gl: 36226, rb: true },
1989
- "rgba32float": { gl: 34836, rb: true },
2080
+ "rgba32float": { gl: 34836, rb: true, r: FLOAT32_COLOR_RENDERABLE },
1990
2081
  // Depth and stencil formats
1991
2082
  "stencil8": { gl: 36168, rb: true },
1992
2083
  // 8 stencil bits
@@ -2044,8 +2135,8 @@ var __exports__ = (() => {
2044
2135
  "astc-8x6-unorm-srgb": { gl: 37846 },
2045
2136
  "astc-8x8-unorm": { gl: 37815 },
2046
2137
  "astc-8x8-unorm-srgb": { gl: 37847 },
2047
- "astc-10x5-unorm": { gl: 37819 },
2048
- "astc-10x5-unorm-srgb": { gl: 37851 },
2138
+ "astc-10x5-unorm": { gl: 37816 },
2139
+ "astc-10x5-unorm-srgb": { gl: 37848 },
2049
2140
  "astc-10x6-unorm": { gl: 37817 },
2050
2141
  "astc-10x6-unorm-srgb": { gl: 37849 },
2051
2142
  "astc-10x8-unorm": { gl: 37818 },
@@ -2059,7 +2150,7 @@ var __exports__ = (() => {
2059
2150
  // WEBGL_compressed_texture_pvrtc
2060
2151
  "pvrtc-rgb4unorm-webgl": { gl: 35840 },
2061
2152
  "pvrtc-rgba4unorm-webgl": { gl: 35842 },
2062
- "pvrtc-rbg2unorm-webgl": { gl: 35841 },
2153
+ "pvrtc-rgb2unorm-webgl": { gl: 35841 },
2063
2154
  "pvrtc-rgba2unorm-webgl": { gl: 35843 },
2064
2155
  // WEBGL_compressed_texture_etc1
2065
2156
  "etc1-rbg-unorm-webgl": { gl: 36196 },
@@ -2082,12 +2173,11 @@ var __exports__ = (() => {
2082
2173
  // optional WebGPU features
2083
2174
  "depth-clip-control": "EXT_depth_clamp",
2084
2175
  // TODO these seem subtly different
2085
- // 'timestamp-query' // GPUQueryType "timestamp-query"
2176
+ "timestamp-query": "EXT_disjoint_timer_query_webgl2",
2086
2177
  // "indirect-first-instance"
2087
2178
  // Textures are handled by getTextureFeatures()
2088
2179
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2089
2180
  // optional WebGL features
2090
- "timer-query-webgl": "EXT_disjoint_timer_query_webgl2",
2091
2181
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2092
2182
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2093
2183
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
@@ -2424,6 +2514,60 @@ var __exports__ = (() => {
2424
2514
  }
2425
2515
  });
2426
2516
 
2517
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js
2518
+ var import_core9, WebGLPresentationContext;
2519
+ var init_webgl_presentation_context = __esm({
2520
+ "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-presentation-context.js"() {
2521
+ import_core9 = __toESM(require_core2(), 1);
2522
+ WebGLPresentationContext = class extends import_core9.PresentationContext {
2523
+ device;
2524
+ handle = null;
2525
+ context2d;
2526
+ get [Symbol.toStringTag]() {
2527
+ return "WebGLPresentationContext";
2528
+ }
2529
+ constructor(device, props = {}) {
2530
+ super(props);
2531
+ this.device = device;
2532
+ const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
2533
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2534
+ if (!defaultCanvasContext.offscreenCanvas) {
2535
+ throw new Error(`${contextLabel}: WebGL PresentationContext requires the default CanvasContext canvas to be an OffscreenCanvas`);
2536
+ }
2537
+ const context2d = this.canvas.getContext("2d");
2538
+ if (!context2d) {
2539
+ throw new Error(`${contextLabel}: Failed to create 2d presentation context`);
2540
+ }
2541
+ this.context2d = context2d;
2542
+ this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
2543
+ this._configureDevice();
2544
+ this._startObservers();
2545
+ }
2546
+ present() {
2547
+ this._resizeDrawingBufferIfNeeded();
2548
+ this.device.submit();
2549
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2550
+ const [sourceWidth, sourceHeight] = defaultCanvasContext.getDrawingBufferSize();
2551
+ if (this.drawingBufferWidth === 0 || this.drawingBufferHeight === 0 || sourceWidth === 0 || sourceHeight === 0 || defaultCanvasContext.canvas.width === 0 || defaultCanvasContext.canvas.height === 0) {
2552
+ return;
2553
+ }
2554
+ if (sourceWidth !== this.drawingBufferWidth || sourceHeight !== this.drawingBufferHeight || defaultCanvasContext.canvas.width !== this.drawingBufferWidth || defaultCanvasContext.canvas.height !== this.drawingBufferHeight) {
2555
+ throw new Error(`${this[Symbol.toStringTag]}(${this.id}): Default canvas context size ${sourceWidth}x${sourceHeight} does not match presentation size ${this.drawingBufferWidth}x${this.drawingBufferHeight}`);
2556
+ }
2557
+ this.context2d.clearRect(0, 0, this.drawingBufferWidth, this.drawingBufferHeight);
2558
+ this.context2d.drawImage(defaultCanvasContext.canvas, 0, 0);
2559
+ }
2560
+ _configureDevice() {
2561
+ }
2562
+ _getCurrentFramebuffer(options) {
2563
+ const defaultCanvasContext = this.device.getDefaultCanvasContext();
2564
+ defaultCanvasContext.setDrawingBufferSize(this.drawingBufferWidth, this.drawingBufferHeight);
2565
+ return defaultCanvasContext.getCurrentFramebuffer(options);
2566
+ }
2567
+ };
2568
+ }
2569
+ });
2570
+
2427
2571
  // ../../node_modules/@luma.gl/webgl/dist/utils/uid.js
2428
2572
  function uid(id = "id") {
2429
2573
  uidCounters[id] = uidCounters[id] || 1;
@@ -2439,34 +2583,34 @@ var __exports__ = (() => {
2439
2583
 
2440
2584
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js
2441
2585
  function getWebGLTarget(usage) {
2442
- if (usage & import_core9.Buffer.INDEX) {
2586
+ if (usage & import_core10.Buffer.INDEX) {
2443
2587
  return 34963;
2444
2588
  }
2445
- if (usage & import_core9.Buffer.VERTEX) {
2589
+ if (usage & import_core10.Buffer.VERTEX) {
2446
2590
  return 34962;
2447
2591
  }
2448
- if (usage & import_core9.Buffer.UNIFORM) {
2592
+ if (usage & import_core10.Buffer.UNIFORM) {
2449
2593
  return 35345;
2450
2594
  }
2451
2595
  return 34962;
2452
2596
  }
2453
2597
  function getWebGLUsage(usage) {
2454
- if (usage & import_core9.Buffer.INDEX) {
2598
+ if (usage & import_core10.Buffer.INDEX) {
2455
2599
  return 35044;
2456
2600
  }
2457
- if (usage & import_core9.Buffer.VERTEX) {
2601
+ if (usage & import_core10.Buffer.VERTEX) {
2458
2602
  return 35044;
2459
2603
  }
2460
- if (usage & import_core9.Buffer.UNIFORM) {
2604
+ if (usage & import_core10.Buffer.UNIFORM) {
2461
2605
  return 35048;
2462
2606
  }
2463
2607
  return 35044;
2464
2608
  }
2465
- var import_core9, WEBGLBuffer;
2609
+ var import_core10, WEBGLBuffer;
2466
2610
  var init_webgl_buffer = __esm({
2467
2611
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-buffer.js"() {
2468
- import_core9 = __toESM(require_core2(), 1);
2469
- WEBGLBuffer = class extends import_core9.Buffer {
2612
+ import_core10 = __toESM(require_core2(), 1);
2613
+ WEBGLBuffer = class extends import_core10.Buffer {
2470
2614
  device;
2471
2615
  gl;
2472
2616
  handle;
@@ -2501,8 +2645,12 @@ var __exports__ = (() => {
2501
2645
  destroy() {
2502
2646
  if (!this.destroyed && this.handle) {
2503
2647
  this.removeStats();
2504
- this.trackDeallocatedMemory();
2505
- this.gl.deleteBuffer(this.handle);
2648
+ if (!this.props.handle) {
2649
+ this.trackDeallocatedMemory();
2650
+ this.gl.deleteBuffer(this.handle);
2651
+ } else {
2652
+ this.trackDeallocatedReferencedMemory("Buffer");
2653
+ }
2506
2654
  this.destroyed = true;
2507
2655
  this.handle = null;
2508
2656
  }
@@ -2517,7 +2665,11 @@ var __exports__ = (() => {
2517
2665
  this.bytesUsed = byteLength;
2518
2666
  this.byteLength = byteLength;
2519
2667
  this._setDebugData(data, byteOffset, byteLength);
2520
- this.trackAllocatedMemory(byteLength);
2668
+ if (!this.props.handle) {
2669
+ this.trackAllocatedMemory(byteLength);
2670
+ } else {
2671
+ this.trackReferencedMemory(byteLength, "Buffer");
2672
+ }
2521
2673
  }
2522
2674
  // Allocate a GPU buffer of specified size.
2523
2675
  _initWithByteLength(byteLength) {
@@ -2532,7 +2684,11 @@ var __exports__ = (() => {
2532
2684
  this.bytesUsed = byteLength;
2533
2685
  this.byteLength = byteLength;
2534
2686
  this._setDebugData(null, 0, byteLength);
2535
- this.trackAllocatedMemory(byteLength);
2687
+ if (!this.props.handle) {
2688
+ this.trackAllocatedMemory(byteLength);
2689
+ } else {
2690
+ this.trackReferencedMemory(byteLength, "Buffer");
2691
+ }
2536
2692
  return this;
2537
2693
  }
2538
2694
  write(data, byteOffset = 0) {
@@ -2583,9 +2739,20 @@ var __exports__ = (() => {
2583
2739
  if (line.length <= 1) {
2584
2740
  continue;
2585
2741
  }
2742
+ const lineWithTrimmedWhitespace = line.trim();
2586
2743
  const segments = line.split(":");
2744
+ const trimmedMessageType = segments[0]?.trim();
2587
2745
  if (segments.length === 2) {
2588
2746
  const [messageType2, message2] = segments;
2747
+ if (!messageType2 || !message2) {
2748
+ messages.push({
2749
+ message: lineWithTrimmedWhitespace,
2750
+ type: getMessageType(trimmedMessageType || "info"),
2751
+ lineNum: 0,
2752
+ linePos: 0
2753
+ });
2754
+ continue;
2755
+ }
2589
2756
  messages.push({
2590
2757
  message: message2.trim(),
2591
2758
  type: getMessageType(messageType2),
@@ -2595,6 +2762,15 @@ var __exports__ = (() => {
2595
2762
  continue;
2596
2763
  }
2597
2764
  const [messageType, linePosition, lineNumber, ...rest] = segments;
2765
+ if (!messageType || !linePosition || !lineNumber) {
2766
+ messages.push({
2767
+ message: segments.slice(1).join(":").trim() || lineWithTrimmedWhitespace,
2768
+ type: getMessageType(trimmedMessageType || "info"),
2769
+ lineNum: 0,
2770
+ linePos: 0
2771
+ });
2772
+ continue;
2773
+ }
2598
2774
  let lineNum = parseInt(lineNumber, 10);
2599
2775
  if (isNaN(lineNum)) {
2600
2776
  lineNum = 0;
@@ -2624,12 +2800,12 @@ var __exports__ = (() => {
2624
2800
  });
2625
2801
 
2626
2802
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js
2627
- var import_core10, WEBGLShader;
2803
+ var import_core11, WEBGLShader;
2628
2804
  var init_webgl_shader = __esm({
2629
2805
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js"() {
2630
- import_core10 = __toESM(require_core2(), 1);
2806
+ import_core11 = __toESM(require_core2(), 1);
2631
2807
  init_parse_shader_compiler_log();
2632
- WEBGLShader = class extends import_core10.Shader {
2808
+ WEBGLShader = class extends import_core11.Shader {
2633
2809
  device;
2634
2810
  handle;
2635
2811
  constructor(device, props) {
@@ -2695,9 +2871,9 @@ ${source}`;
2695
2871
  }
2696
2872
  return;
2697
2873
  }
2698
- import_core10.log.once(1, "Shader compilation is asynchronous")();
2874
+ import_core11.log.once(1, "Shader compilation is asynchronous")();
2699
2875
  await this._waitForCompilationComplete();
2700
- import_core10.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2876
+ import_core11.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
2701
2877
  this._getCompilationStatus();
2702
2878
  this.debugShader();
2703
2879
  }
@@ -2845,7 +3021,7 @@ ${source}`;
2845
3021
  gl.stencilMaskSeparate(1029, mask);
2846
3022
  }
2847
3023
  if (parameters.stencilReadMask) {
2848
- import_core11.log.warn("stencilReadMask not supported under WebGL");
3024
+ import_core12.log.warn("stencilReadMask not supported under WebGL");
2849
3025
  }
2850
3026
  if (parameters.stencilCompare) {
2851
3027
  const mask = parameters.stencilReadMask || 4294967295;
@@ -2958,10 +3134,10 @@ ${source}`;
2958
3134
  }
2959
3135
  return isEmpty;
2960
3136
  }
2961
- var import_core11;
3137
+ var import_core12;
2962
3138
  var init_device_parameters = __esm({
2963
3139
  "../../node_modules/@luma.gl/webgl/dist/adapter/converters/device-parameters.js"() {
2964
- import_core11 = __toESM(require_core2(), 1);
3140
+ import_core12 = __toESM(require_core2(), 1);
2965
3141
  init_unified_parameter_api();
2966
3142
  }
2967
3143
  });
@@ -3050,12 +3226,12 @@ ${source}`;
3050
3226
  });
3051
3227
 
3052
3228
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js
3053
- var import_core12, WEBGLSampler;
3229
+ var import_core13, WEBGLSampler;
3054
3230
  var init_webgl_sampler = __esm({
3055
3231
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-sampler.js"() {
3056
- import_core12 = __toESM(require_core2(), 1);
3232
+ import_core13 = __toESM(require_core2(), 1);
3057
3233
  init_sampler_parameters();
3058
- WEBGLSampler = class extends import_core12.Sampler {
3234
+ WEBGLSampler = class extends import_core13.Sampler {
3059
3235
  device;
3060
3236
  handle;
3061
3237
  parameters;
@@ -3130,18 +3306,18 @@ ${source}`;
3130
3306
  });
3131
3307
 
3132
3308
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js
3133
- var import_core13, WEBGLTextureView;
3309
+ var import_core14, WEBGLTextureView;
3134
3310
  var init_webgl_texture_view = __esm({
3135
3311
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture-view.js"() {
3136
- import_core13 = __toESM(require_core2(), 1);
3137
- WEBGLTextureView = class extends import_core13.TextureView {
3312
+ import_core14 = __toESM(require_core2(), 1);
3313
+ WEBGLTextureView = class extends import_core14.TextureView {
3138
3314
  device;
3139
3315
  gl;
3140
3316
  handle;
3141
3317
  // Does not have a WebGL representation
3142
3318
  texture;
3143
3319
  constructor(device, props) {
3144
- super(device, { ...import_core13.Texture.defaultProps, ...props });
3320
+ super(device, { ...import_core14.Texture.defaultProps, ...props });
3145
3321
  this.device = device;
3146
3322
  this.gl = this.device.gl;
3147
3323
  this.handle = null;
@@ -3151,87 +3327,6 @@ ${source}`;
3151
3327
  }
3152
3328
  });
3153
3329
 
3154
- // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
3155
- function convertDataTypeToGLDataType(normalizedType) {
3156
- return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
3157
- }
3158
- function convertGLUniformTypeToShaderVariableType(glUniformType) {
3159
- return WEBGL_SHADER_TYPES[glUniformType];
3160
- }
3161
- function isGLSamplerType(type) {
3162
- return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
3163
- }
3164
- function getTextureBindingFromGLSamplerType(glSamplerType) {
3165
- return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
3166
- }
3167
- var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
3168
- var init_webgl_shadertypes = __esm({
3169
- "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
3170
- WEBGL_SHADER_TYPES = {
3171
- [5126]: "f32",
3172
- [35664]: "vec2<f32>",
3173
- [35665]: "vec3<f32>",
3174
- [35666]: "vec4<f32>",
3175
- [5124]: "i32",
3176
- [35667]: "vec2<i32>",
3177
- [35668]: "vec3<i32>",
3178
- [35669]: "vec4<i32>",
3179
- [5125]: "u32",
3180
- [36294]: "vec2<u32>",
3181
- [36295]: "vec3<u32>",
3182
- [36296]: "vec4<u32>",
3183
- [35670]: "f32",
3184
- [35671]: "vec2<f32>",
3185
- [35672]: "vec3<f32>",
3186
- [35673]: "vec4<f32>",
3187
- // TODO - are sizes/components below correct?
3188
- [35674]: "mat2x2<f32>",
3189
- [35685]: "mat2x3<f32>",
3190
- [35686]: "mat2x4<f32>",
3191
- [35687]: "mat3x2<f32>",
3192
- [35675]: "mat3x3<f32>",
3193
- [35688]: "mat3x4<f32>",
3194
- [35689]: "mat4x2<f32>",
3195
- [35690]: "mat4x3<f32>",
3196
- [35676]: "mat4x4<f32>"
3197
- };
3198
- WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
3199
- [35678]: { viewDimension: "2d", sampleType: "float" },
3200
- [35680]: { viewDimension: "cube", sampleType: "float" },
3201
- [35679]: { viewDimension: "3d", sampleType: "float" },
3202
- [35682]: { viewDimension: "3d", sampleType: "depth" },
3203
- [36289]: { viewDimension: "2d-array", sampleType: "float" },
3204
- [36292]: { viewDimension: "2d-array", sampleType: "depth" },
3205
- [36293]: { viewDimension: "cube", sampleType: "float" },
3206
- [36298]: { viewDimension: "2d", sampleType: "sint" },
3207
- [36299]: { viewDimension: "3d", sampleType: "sint" },
3208
- [36300]: { viewDimension: "cube", sampleType: "sint" },
3209
- [36303]: { viewDimension: "2d-array", sampleType: "uint" },
3210
- [36306]: { viewDimension: "2d", sampleType: "uint" },
3211
- [36307]: { viewDimension: "3d", sampleType: "uint" },
3212
- [36308]: { viewDimension: "cube", sampleType: "uint" },
3213
- [36311]: { viewDimension: "2d-array", sampleType: "uint" }
3214
- };
3215
- NORMALIZED_SHADER_TYPE_TO_WEBGL = {
3216
- uint8: 5121,
3217
- sint8: 5120,
3218
- unorm8: 5121,
3219
- snorm8: 5120,
3220
- uint16: 5123,
3221
- sint16: 5122,
3222
- unorm16: 5123,
3223
- snorm16: 5122,
3224
- uint32: 5125,
3225
- sint32: 5124,
3226
- // WebGPU does not support normalized 32 bit integer attributes
3227
- // 'unorm32': GL.UNSIGNED_INT,
3228
- // 'snorm32': GL.INT,
3229
- float16: 5131,
3230
- float32: 5126
3231
- };
3232
- }
3233
- });
3234
-
3235
3330
  // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/shader-formats.js
3236
3331
  function convertGLDataTypeToDataType(type) {
3237
3332
  return GL_DATA_TYPE_MAP[type];
@@ -3261,6 +3356,18 @@ ${source}`;
3261
3356
  });
3262
3357
 
3263
3358
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js
3359
+ function getArrayBufferView(typedArray, byteOffset = 0) {
3360
+ if (!byteOffset) {
3361
+ return typedArray;
3362
+ }
3363
+ return new typedArray.constructor(typedArray.buffer, typedArray.byteOffset + byteOffset, (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT);
3364
+ }
3365
+ function getWebGLTextureSourceElementOffset(typedArray, byteOffset) {
3366
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
3367
+ throw new Error(`Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`);
3368
+ }
3369
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
3370
+ }
3264
3371
  function getWebGLTextureTarget(dimension) {
3265
3372
  switch (dimension) {
3266
3373
  case "1d":
@@ -3281,18 +3388,17 @@ ${source}`;
3281
3388
  function getWebGLCubeFaceTarget(glTarget, dimension, level) {
3282
3389
  return dimension === "cube" ? 34069 + level : glTarget;
3283
3390
  }
3284
- var import_core14, import_core15, WEBGLTexture;
3391
+ var import_core15, import_core16, WEBGLTexture;
3285
3392
  var init_webgl_texture = __esm({
3286
3393
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-texture.js"() {
3287
- import_core14 = __toESM(require_core2(), 1);
3394
+ import_core15 = __toESM(require_core2(), 1);
3288
3395
  init_webgl_texture_table();
3289
3396
  init_sampler_parameters();
3290
3397
  init_with_parameters();
3291
3398
  init_webgl_texture_view();
3292
- init_webgl_shadertypes();
3293
3399
  init_shader_formats();
3294
- import_core15 = __toESM(require_core2(), 1);
3295
- WEBGLTexture = class extends import_core14.Texture {
3400
+ import_core16 = __toESM(require_core2(), 1);
3401
+ WEBGLTexture = class extends import_core15.Texture {
3296
3402
  // readonly MAX_ATTRIBUTES: number;
3297
3403
  device;
3298
3404
  gl;
@@ -3321,8 +3427,10 @@ ${source}`;
3321
3427
  // state
3322
3428
  /** Texture binding slot - TODO - move to texture view? */
3323
3429
  _textureUnit = 0;
3324
- /** Chached framebuffer */
3430
+ /** Cached framebuffer reused for color texture readback. */
3325
3431
  _framebuffer = null;
3432
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
3433
+ _framebufferAttachmentKey = null;
3326
3434
  constructor(device, props) {
3327
3435
  super(device, props, { byteAlignment: 1 });
3328
3436
  this.device = device;
@@ -3337,20 +3445,27 @@ ${source}`;
3337
3445
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3338
3446
  this.gl.bindTexture(this.glTarget, this.handle);
3339
3447
  const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3340
- switch (dimension) {
3341
- case "2d":
3342
- case "cube":
3343
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3344
- break;
3345
- case "2d-array":
3346
- case "3d":
3347
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3348
- break;
3349
- default:
3350
- throw new Error(dimension);
3448
+ if (!this.compressed) {
3449
+ switch (dimension) {
3450
+ case "2d":
3451
+ case "cube":
3452
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3453
+ break;
3454
+ case "2d-array":
3455
+ case "3d":
3456
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3457
+ break;
3458
+ default:
3459
+ throw new Error(dimension);
3460
+ }
3351
3461
  }
3352
3462
  this.gl.bindTexture(this.glTarget, null);
3353
3463
  this._initializeData(props.data);
3464
+ if (!this.props.handle) {
3465
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
3466
+ } else {
3467
+ this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
3468
+ }
3354
3469
  this.setSampler(this.props.sampler);
3355
3470
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3356
3471
  Object.seal(this);
@@ -3359,9 +3474,14 @@ ${source}`;
3359
3474
  if (this.handle) {
3360
3475
  this._framebuffer?.destroy();
3361
3476
  this._framebuffer = null;
3362
- this.gl.deleteTexture(this.handle);
3477
+ this._framebufferAttachmentKey = null;
3363
3478
  this.removeStats();
3364
- this.trackDeallocatedMemory("Texture");
3479
+ if (!this.props.handle) {
3480
+ this.gl.deleteTexture(this.handle);
3481
+ this.trackDeallocatedMemory("Texture");
3482
+ } else {
3483
+ this.trackDeallocatedReferencedMemory("Texture");
3484
+ }
3365
3485
  this.destroyed = true;
3366
3486
  }
3367
3487
  }
@@ -3400,97 +3520,128 @@ ${source}`;
3400
3520
  return { width: options.width, height: options.height };
3401
3521
  }
3402
3522
  copyImageData(options_) {
3403
- const options = this._normalizeCopyImageDataOptions(options_);
3404
- const typedArray = options.data;
3405
- const { width, height, depth, z = 0 } = options;
3406
- const { mipLevel = 0, byteOffset = 0, x = 0, y = 0 } = options;
3523
+ super.copyImageData(options_);
3524
+ }
3525
+ /**
3526
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
3527
+ *
3528
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
3529
+ * before any WebGL calls are issued.
3530
+ */
3531
+ readBuffer(options = {}, buffer) {
3532
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
3533
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
3534
+ const readBuffer = buffer || this.device.createBuffer({
3535
+ byteLength: memoryLayout.byteLength,
3536
+ usage: import_core15.Buffer.COPY_DST | import_core15.Buffer.MAP_READ
3537
+ });
3538
+ if (readBuffer.byteLength < memoryLayout.byteLength) {
3539
+ throw new Error(`${this} readBuffer target is too small (${readBuffer.byteLength} < ${memoryLayout.byteLength})`);
3540
+ }
3541
+ const webglBuffer = readBuffer;
3542
+ this.gl.bindBuffer(35051, webglBuffer.handle);
3543
+ try {
3544
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, (destinationByteOffset) => {
3545
+ this.gl.readPixels(normalizedOptions.x, normalizedOptions.y, normalizedOptions.width, normalizedOptions.height, this.glFormat, this.glType, destinationByteOffset);
3546
+ });
3547
+ } finally {
3548
+ this.gl.bindBuffer(35051, null);
3549
+ }
3550
+ return readBuffer;
3551
+ }
3552
+ async readDataAsync(options = {}) {
3553
+ const buffer = this.readBuffer(options);
3554
+ const data = await buffer.readAsync();
3555
+ buffer.destroy();
3556
+ return data.buffer;
3557
+ }
3558
+ writeBuffer(buffer, options_ = {}) {
3559
+ const options = this._normalizeTextureWriteOptions(options_);
3560
+ const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
3407
3561
  const { glFormat, glType, compressed } = this;
3408
3562
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3409
- let unpackRowLength;
3410
- if (!this.compressed) {
3411
- const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3412
- if (bytesPerPixel) {
3413
- if (options.bytesPerRow % bytesPerPixel !== 0) {
3414
- throw new Error(`bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`);
3415
- }
3416
- unpackRowLength = options.bytesPerRow / bytesPerPixel;
3417
- }
3563
+ if (compressed) {
3564
+ throw new Error("writeBuffer for compressed textures is not implemented in WebGL");
3418
3565
  }
3419
- const glParameters = !this.compressed ? {
3566
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3567
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : void 0;
3568
+ const glParameters = {
3420
3569
  [3317]: this.byteAlignment,
3421
3570
  ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3422
3571
  [32878]: options.rowsPerImage
3423
- } : {};
3572
+ };
3424
3573
  this.gl.bindTexture(this.glTarget, this.handle);
3574
+ this.gl.bindBuffer(35052, buffer.handle);
3425
3575
  withGLParameters(this.gl, glParameters, () => {
3426
3576
  switch (this.dimension) {
3427
3577
  case "2d":
3428
3578
  case "cube":
3429
- if (compressed) {
3430
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
3431
- } else {
3432
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
3433
- }
3579
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, byteOffset);
3434
3580
  break;
3435
3581
  case "2d-array":
3436
3582
  case "3d":
3437
- if (compressed) {
3438
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
3439
- } else {
3440
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
3441
- }
3583
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, byteOffset);
3442
3584
  break;
3443
3585
  default:
3444
3586
  }
3445
3587
  });
3588
+ this.gl.bindBuffer(35052, null);
3446
3589
  this.gl.bindTexture(this.glTarget, null);
3447
3590
  }
3448
- readBuffer(options = {}, buffer) {
3449
- throw new Error("readBuffer not implemented");
3450
- }
3451
- async readDataAsync(options = {}) {
3452
- return this.readDataSyncWebGL(options);
3453
- }
3454
- writeBuffer(buffer, options_ = {}) {
3455
- }
3456
3591
  writeData(data, options_ = {}) {
3457
3592
  const options = this._normalizeTextureWriteOptions(options_);
3458
3593
  const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3459
- const {} = this;
3460
- const { width, height, mipLevel, x, y, z } = options;
3594
+ const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
3461
3595
  const { glFormat, glType, compressed } = this;
3462
- const depth = 0;
3463
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
3596
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3597
+ let unpackRowLength;
3598
+ if (!compressed) {
3599
+ const { bytesPerPixel } = this.device.getTextureFormatInfo(this.format);
3600
+ if (bytesPerPixel) {
3601
+ unpackRowLength = options.bytesPerRow / bytesPerPixel;
3602
+ }
3603
+ }
3464
3604
  const glParameters = !this.compressed ? {
3465
- // WebGL does not require byte alignment, but allows it to be specified
3466
- [3317]: this.byteAlignment
3467
- // [GL.UNPACK_ROW_LENGTH]: bytesPerRow,
3468
- // [GL.UNPACK_IMAGE_HEIGHT]: rowsPerImage
3605
+ [3317]: this.byteAlignment,
3606
+ ...unpackRowLength !== void 0 ? { [3314]: unpackRowLength } : {},
3607
+ [32878]: options.rowsPerImage
3469
3608
  } : {};
3470
- this.gl.bindTexture(glTarget, this.handle);
3609
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
3610
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
3611
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
3612
+ const isFullMipUpload = x === 0 && y === 0 && z === 0 && width === mipLevelSize.width && height === mipLevelSize.height && depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
3613
+ this.gl.bindTexture(this.glTarget, this.handle);
3471
3614
  this.gl.bindBuffer(35052, null);
3472
3615
  withGLParameters(this.gl, glParameters, () => {
3473
3616
  switch (this.dimension) {
3474
3617
  case "2d":
3475
3618
  case "cube":
3476
3619
  if (compressed) {
3477
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray);
3620
+ if (isFullMipUpload) {
3621
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
3622
+ } else {
3623
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
3624
+ }
3478
3625
  } else {
3479
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray);
3626
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
3480
3627
  }
3481
3628
  break;
3482
3629
  case "2d-array":
3483
3630
  case "3d":
3484
3631
  if (compressed) {
3485
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray);
3632
+ if (isFullMipUpload) {
3633
+ this.gl.compressedTexImage3D(glTarget, mipLevel, glFormat, width, height, depthOrArrayLayers, 0, compressedData);
3634
+ } else {
3635
+ this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, compressedData);
3636
+ }
3486
3637
  } else {
3487
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray);
3638
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
3488
3639
  }
3489
3640
  break;
3490
3641
  default:
3491
3642
  }
3492
3643
  });
3493
- this.gl.bindTexture(glTarget, null);
3644
+ this.gl.bindTexture(this.glTarget, null);
3494
3645
  }
3495
3646
  // IMPLEMENTATION SPECIFIC
3496
3647
  /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
@@ -3512,36 +3663,91 @@ ${source}`;
3512
3663
  }
3513
3664
  // WEBGL SPECIFIC
3514
3665
  readDataSyncWebGL(options_ = {}) {
3515
- const options = this._normalizeTextureReadOptions(options_);
3666
+ const options = this._getSupportedColorReadOptions(options_);
3516
3667
  const memoryLayout = this.computeMemoryLayout(options);
3517
3668
  const shaderType = convertGLDataTypeToDataType(this.glType);
3518
- const ArrayType = (0, import_core15.getTypedArrayConstructor)(shaderType);
3519
- const targetArray = new ArrayType(memoryLayout.byteLength);
3520
- const signedType = (0, import_core15.getDataType)(targetArray);
3521
- const sourceType = convertDataTypeToGLDataType(signedType);
3522
- const framebuffer = this._getFramebuffer();
3523
- const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3524
- this.gl.readBuffer(36064);
3525
- this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, sourceType, targetArray);
3526
- this.gl.bindFramebuffer(36160, prevHandle || null);
3669
+ const ArrayType = (0, import_core16.getTypedArrayConstructor)(shaderType);
3670
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT);
3671
+ this._readColorTextureLayers(options, memoryLayout, (destinationByteOffset) => {
3672
+ const layerView = new ArrayType(targetArray.buffer, targetArray.byteOffset + destinationByteOffset, memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT);
3673
+ this.gl.readPixels(options.x, options.y, options.width, options.height, this.glFormat, this.glType, layerView);
3674
+ });
3527
3675
  return targetArray.buffer;
3528
3676
  }
3529
3677
  /**
3530
- * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3678
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
3679
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
3531
3680
  */
3532
- generateMipmapsWebGL(options) {
3533
- const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3534
- if (!isFilterableAndRenderable) {
3535
- import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3536
- if (!options?.force) {
3537
- return;
3538
- }
3539
- }
3681
+ _readColorTextureLayers(options, memoryLayout, readLayer) {
3682
+ const framebuffer = this._getFramebuffer();
3683
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
3684
+ const glParameters = {
3685
+ [3333]: this.byteAlignment,
3686
+ ...packRowLength !== options.width ? { [3330]: packRowLength } : {}
3687
+ };
3688
+ const prevReadBuffer = this.gl.getParameter(3074);
3689
+ const prevHandle = this.gl.bindFramebuffer(36160, framebuffer.handle);
3540
3690
  try {
3541
- this.gl.bindTexture(this.glTarget, this.handle);
3542
- this.gl.generateMipmap(this.glTarget);
3543
- } catch (error) {
3544
- import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3691
+ this.gl.readBuffer(36064);
3692
+ withGLParameters(this.gl, glParameters, () => {
3693
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
3694
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
3695
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
3696
+ }
3697
+ });
3698
+ } finally {
3699
+ this.gl.bindFramebuffer(36160, prevHandle || null);
3700
+ this.gl.readBuffer(prevReadBuffer);
3701
+ }
3702
+ }
3703
+ /**
3704
+ * Attaches a single color subresource to the cached read framebuffer.
3705
+ *
3706
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
3707
+ */
3708
+ _attachReadSubresource(framebuffer, mipLevel, layer) {
3709
+ const attachmentKey = `${mipLevel}:${layer}`;
3710
+ if (this._framebufferAttachmentKey === attachmentKey) {
3711
+ return;
3712
+ }
3713
+ switch (this.dimension) {
3714
+ case "2d":
3715
+ this.gl.framebufferTexture2D(36160, 36064, 3553, this.handle, mipLevel);
3716
+ break;
3717
+ case "cube":
3718
+ this.gl.framebufferTexture2D(36160, 36064, getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer), this.handle, mipLevel);
3719
+ break;
3720
+ case "2d-array":
3721
+ case "3d":
3722
+ this.gl.framebufferTextureLayer(36160, 36064, this.handle, mipLevel, layer);
3723
+ break;
3724
+ default:
3725
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
3726
+ }
3727
+ if (this.device.props.debug) {
3728
+ const status = Number(this.gl.checkFramebufferStatus(36160));
3729
+ if (status !== Number(36053)) {
3730
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
3731
+ }
3732
+ }
3733
+ this._framebufferAttachmentKey = attachmentKey;
3734
+ }
3735
+ /**
3736
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3737
+ */
3738
+ generateMipmapsWebGL(options) {
3739
+ const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3740
+ if (!isFilterableAndRenderable) {
3741
+ import_core15.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
3742
+ if (!options?.force) {
3743
+ return;
3744
+ }
3745
+ }
3746
+ try {
3747
+ this.gl.bindTexture(this.glTarget, this.handle);
3748
+ this.gl.generateMipmap(this.glTarget);
3749
+ } catch (error) {
3750
+ import_core15.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
3545
3751
  } finally {
3546
3752
  this.gl.bindTexture(this.glTarget, null);
3547
3753
  }
@@ -3551,7 +3757,7 @@ ${source}`;
3551
3757
  * Sets sampler parameters on texture
3552
3758
  */
3553
3759
  _setSamplerParameters(parameters) {
3554
- import_core14.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3760
+ import_core15.log.log(2, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3555
3761
  this.gl.bindTexture(this.glTarget, this.handle);
3556
3762
  for (const [pname, pvalue] of Object.entries(parameters)) {
3557
3763
  const param = Number(pname);
@@ -3608,206 +3814,6 @@ ${source}`;
3608
3814
  }
3609
3815
  });
3610
3816
 
3611
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
3612
- function getShaderLayoutFromGLSL(gl, program) {
3613
- const shaderLayout = {
3614
- attributes: [],
3615
- bindings: []
3616
- };
3617
- shaderLayout.attributes = readAttributeDeclarations(gl, program);
3618
- const uniformBlocks = readUniformBlocks(gl, program);
3619
- for (const uniformBlock of uniformBlocks) {
3620
- const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3621
- name: uniform.name,
3622
- format: uniform.format,
3623
- byteOffset: uniform.byteOffset,
3624
- byteStride: uniform.byteStride,
3625
- arrayLength: uniform.arrayLength
3626
- }));
3627
- shaderLayout.bindings.push({
3628
- type: "uniform",
3629
- name: uniformBlock.name,
3630
- group: 0,
3631
- location: uniformBlock.location,
3632
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3633
- minBindingSize: uniformBlock.byteLength,
3634
- uniforms: uniforms2
3635
- });
3636
- }
3637
- const uniforms = readUniformBindings(gl, program);
3638
- let textureUnit = 0;
3639
- for (const uniform of uniforms) {
3640
- if (isGLSamplerType(uniform.type)) {
3641
- const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
3642
- shaderLayout.bindings.push({
3643
- type: "texture",
3644
- name: uniform.name,
3645
- group: 0,
3646
- location: textureUnit,
3647
- viewDimension,
3648
- sampleType
3649
- });
3650
- uniform.textureUnit = textureUnit;
3651
- textureUnit += 1;
3652
- }
3653
- }
3654
- if (uniforms.length) {
3655
- shaderLayout.uniforms = uniforms;
3656
- }
3657
- const varyings = readVaryings(gl, program);
3658
- if (varyings?.length) {
3659
- shaderLayout.varyings = varyings;
3660
- }
3661
- return shaderLayout;
3662
- }
3663
- function readAttributeDeclarations(gl, program) {
3664
- const attributes = [];
3665
- const count = gl.getProgramParameter(program, 35721);
3666
- for (let index = 0; index < count; index++) {
3667
- const activeInfo = gl.getActiveAttrib(program, index);
3668
- if (!activeInfo) {
3669
- throw new Error("activeInfo");
3670
- }
3671
- const {
3672
- name,
3673
- type: compositeType
3674
- /* , size*/
3675
- } = activeInfo;
3676
- const location = gl.getAttribLocation(program, name);
3677
- if (location >= 0) {
3678
- const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
3679
- const stepMode = /instance/i.test(name) ? "instance" : "vertex";
3680
- attributes.push({
3681
- name,
3682
- location,
3683
- stepMode,
3684
- type: attributeType
3685
- // size - for arrays, size is the number of elements in the array
3686
- });
3687
- }
3688
- }
3689
- attributes.sort((a, b) => a.location - b.location);
3690
- return attributes;
3691
- }
3692
- function readVaryings(gl, program) {
3693
- const varyings = [];
3694
- const count = gl.getProgramParameter(program, 35971);
3695
- for (let location = 0; location < count; location++) {
3696
- const activeInfo = gl.getTransformFeedbackVarying(program, location);
3697
- if (!activeInfo) {
3698
- throw new Error("activeInfo");
3699
- }
3700
- const { name, type: glUniformType, size } = activeInfo;
3701
- const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3702
- const { type, components } = (0, import_core16.getVariableShaderTypeInfo)(uniformType);
3703
- varyings.push({ location, name, type, size: size * components });
3704
- }
3705
- varyings.sort((a, b) => a.location - b.location);
3706
- return varyings;
3707
- }
3708
- function readUniformBindings(gl, program) {
3709
- const uniforms = [];
3710
- const uniformCount = gl.getProgramParameter(program, 35718);
3711
- for (let i = 0; i < uniformCount; i++) {
3712
- const activeInfo = gl.getActiveUniform(program, i);
3713
- if (!activeInfo) {
3714
- throw new Error("activeInfo");
3715
- }
3716
- const { name: rawName, size, type } = activeInfo;
3717
- const { name, isArray: isArray4 } = parseUniformName(rawName);
3718
- let webglLocation = gl.getUniformLocation(program, name);
3719
- const uniformInfo = {
3720
- // WebGL locations are uniquely typed but just numbers
3721
- location: webglLocation,
3722
- name,
3723
- size,
3724
- type,
3725
- isArray: isArray4
3726
- };
3727
- uniforms.push(uniformInfo);
3728
- if (uniformInfo.size > 1) {
3729
- for (let j = 0; j < uniformInfo.size; j++) {
3730
- const elementName = `${name}[${j}]`;
3731
- webglLocation = gl.getUniformLocation(program, elementName);
3732
- const arrayElementUniformInfo = {
3733
- ...uniformInfo,
3734
- name: elementName,
3735
- location: webglLocation
3736
- };
3737
- uniforms.push(arrayElementUniformInfo);
3738
- }
3739
- }
3740
- }
3741
- return uniforms;
3742
- }
3743
- function readUniformBlocks(gl, program) {
3744
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3745
- const uniformBlocks = [];
3746
- const blockCount = gl.getProgramParameter(program, 35382);
3747
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3748
- const blockInfo = {
3749
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3750
- location: getBlockParameter(blockIndex, 35391),
3751
- byteLength: getBlockParameter(blockIndex, 35392),
3752
- vertex: getBlockParameter(blockIndex, 35396),
3753
- fragment: getBlockParameter(blockIndex, 35398),
3754
- uniformCount: getBlockParameter(blockIndex, 35394),
3755
- uniforms: []
3756
- };
3757
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3758
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3759
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3760
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3761
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3762
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3763
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
3764
- if (!activeInfo) {
3765
- throw new Error("activeInfo");
3766
- }
3767
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3768
- blockInfo.uniforms.push({
3769
- name: activeInfo.name,
3770
- format,
3771
- type: uniformType[i],
3772
- arrayLength: uniformArrayLength[i],
3773
- byteOffset: uniformOffset[i],
3774
- byteStride: uniformStride[i]
3775
- // matrixStride: uniformStride[i],
3776
- // rowMajor: uniformRowMajor[i]
3777
- });
3778
- }
3779
- uniformBlocks.push(blockInfo);
3780
- }
3781
- uniformBlocks.sort((a, b) => a.location - b.location);
3782
- return uniformBlocks;
3783
- }
3784
- function parseUniformName(name) {
3785
- if (name[name.length - 1] !== "]") {
3786
- return {
3787
- name,
3788
- length: 1,
3789
- isArray: false
3790
- };
3791
- }
3792
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3793
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3794
- if (!matches || matches.length < 2) {
3795
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
3796
- }
3797
- return {
3798
- name: matches[1],
3799
- length: matches[2] ? 1 : 0,
3800
- isArray: Boolean(matches[2])
3801
- };
3802
- }
3803
- var import_core16;
3804
- var init_get_shader_layout_from_glsl = __esm({
3805
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3806
- import_core16 = __toESM(require_core2(), 1);
3807
- init_webgl_shadertypes();
3808
- }
3809
- });
3810
-
3811
3817
  // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/set-uniform.js
3812
3818
  function setUniform(gl, location, type, value) {
3813
3819
  const gl2 = gl;
@@ -3952,11 +3958,10 @@ ${source}`;
3952
3958
  }
3953
3959
  return mergedLayout;
3954
3960
  }
3955
- var import_core17, LOG_PROGRAM_PERF_PRIORITY, WEBGLRenderPipeline;
3961
+ var import_core17, WEBGLRenderPipeline;
3956
3962
  var init_webgl_render_pipeline = __esm({
3957
3963
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3958
3964
  import_core17 = __toESM(require_core2(), 1);
3959
- init_get_shader_layout_from_glsl();
3960
3965
  init_device_parameters();
3961
3966
  init_set_uniform();
3962
3967
  init_webgl_buffer();
@@ -3964,7 +3969,6 @@ ${source}`;
3964
3969
  init_webgl_texture();
3965
3970
  init_webgl_texture_view();
3966
3971
  init_webgl_topology_utils();
3967
- LOG_PROGRAM_PERF_PRIORITY = 4;
3968
3972
  WEBGLRenderPipeline = class extends import_core17.RenderPipeline {
3969
3973
  /** The WebGL device that created this render pipeline */
3970
3974
  device;
@@ -3976,10 +3980,10 @@ ${source}`;
3976
3980
  fs;
3977
3981
  /** The layout extracted from shader by WebGL introspection APIs */
3978
3982
  introspectedLayout;
3979
- /** Uniforms set on this model */
3980
- uniforms = {};
3981
- /** Bindings set on this model */
3983
+ /** Compatibility path for direct pipeline.setBindings() usage */
3982
3984
  bindings = {};
3985
+ /** Compatibility path for direct pipeline.uniforms usage */
3986
+ uniforms = {};
3983
3987
  /** WebGL varyings */
3984
3988
  varyings = null;
3985
3989
  _uniformCount = 0;
@@ -3991,33 +3995,28 @@ ${source}`;
3991
3995
  constructor(device, props) {
3992
3996
  super(device, props);
3993
3997
  this.device = device;
3994
- this.handle = this.props.handle || this.device.gl.createProgram();
3998
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
3999
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
4000
+ this.handle = webglSharedRenderPipeline.handle;
4001
+ this.vs = webglSharedRenderPipeline.vs;
4002
+ this.fs = webglSharedRenderPipeline.fs;
4003
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
4004
+ this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
3995
4005
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
3996
- this.vs = props.vs;
3997
- this.fs = props.fs;
3998
- const { varyings, bufferMode = 35981 } = props;
3999
- if (varyings && varyings.length > 0) {
4000
- this.varyings = varyings;
4001
- this.device.gl.transformFeedbackVaryings(this.handle, varyings, bufferMode);
4002
- }
4003
- this._linkShaders();
4004
- import_core17.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4005
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4006
- import_core17.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4007
4006
  this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
4008
4007
  }
4009
4008
  destroy() {
4010
- if (this.handle) {
4011
- this.device.gl.useProgram(null);
4012
- this.device.gl.deleteProgram(this.handle);
4013
- this.destroyed = true;
4014
- this.handle.destroyed = true;
4015
- this.handle = null;
4009
+ if (this.destroyed) {
4010
+ return;
4016
4011
  }
4012
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
4013
+ this.sharedRenderPipeline.destroy();
4014
+ }
4015
+ this.destroyResource();
4017
4016
  }
4018
4017
  /**
4019
- * Bindings include: textures, samplers and uniform buffers
4020
- * @todo needed for portable model
4018
+ * Compatibility shim for code paths that still set bindings on the pipeline.
4019
+ * Shared-model draws pass bindings per draw and do not rely on this state.
4021
4020
  */
4022
4021
  setBindings(bindings, options) {
4023
4022
  for (const [name, value] of Object.entries(bindings)) {
@@ -4057,6 +4056,7 @@ ${source}`;
4057
4056
  * This function unifies those ways into a single call using common parameters with sane defaults
4058
4057
  */
4059
4058
  draw(options) {
4059
+ this._syncLinkStatus();
4060
4060
  const {
4061
4061
  renderPass,
4062
4062
  parameters = this.props.parameters,
@@ -4070,7 +4070,9 @@ ${source}`;
4070
4070
  // firstIndex,
4071
4071
  // firstInstance,
4072
4072
  // baseVertex,
4073
- transformFeedback
4073
+ transformFeedback,
4074
+ bindings = this.bindings,
4075
+ uniforms = this.uniforms
4074
4076
  } = options;
4075
4077
  const glDrawMode = getGLDrawMode(topology);
4076
4078
  const isIndexed = Boolean(vertexArray.indexBuffer);
@@ -4079,66 +4081,482 @@ ${source}`;
4079
4081
  import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4080
4082
  return false;
4081
4083
  }
4082
- if (!this._areTexturesRenderable()) {
4084
+ if (!this._areTexturesRenderable(bindings)) {
4083
4085
  import_core17.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4084
4086
  return false;
4085
4087
  }
4086
- this.device.gl.useProgram(this.handle);
4087
- vertexArray.bindBeforeRender(renderPass);
4088
- if (transformFeedback) {
4089
- transformFeedback.begin(this.props.topology);
4088
+ this.device.gl.useProgram(this.handle);
4089
+ vertexArray.bindBeforeRender(renderPass);
4090
+ if (transformFeedback) {
4091
+ transformFeedback.begin(this.props.topology);
4092
+ }
4093
+ this._applyBindings(bindings, { disableWarnings: this.props.disableWarnings });
4094
+ this._applyUniforms(uniforms);
4095
+ const webglRenderPass = renderPass;
4096
+ withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4097
+ if (isIndexed && isInstanced) {
4098
+ this.device.gl.drawElementsInstanced(
4099
+ glDrawMode,
4100
+ vertexCount || 0,
4101
+ // indexCount?
4102
+ glIndexType,
4103
+ firstVertex,
4104
+ instanceCount || 0
4105
+ );
4106
+ } else if (isIndexed) {
4107
+ this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4108
+ } else if (isInstanced) {
4109
+ this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4110
+ } else {
4111
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4112
+ }
4113
+ if (transformFeedback) {
4114
+ transformFeedback.end();
4115
+ }
4116
+ });
4117
+ vertexArray.unbindAfterRender(renderPass);
4118
+ return true;
4119
+ }
4120
+ /**
4121
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
4122
+ * Update a texture if needed (e.g. from video)
4123
+ * Note: This is currently done before every draw call
4124
+ */
4125
+ _areTexturesRenderable(bindings) {
4126
+ let texturesRenderable = true;
4127
+ for (const bindingInfo of this.shaderLayout.bindings) {
4128
+ if (!bindings[bindingInfo.name] && !bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4129
+ import_core17.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4130
+ texturesRenderable = false;
4131
+ }
4132
+ }
4133
+ return texturesRenderable;
4134
+ }
4135
+ /** Apply any bindings (before each draw call) */
4136
+ _applyBindings(bindings, _options) {
4137
+ this._syncLinkStatus();
4138
+ if (this.linkStatus !== "success") {
4139
+ return;
4140
+ }
4141
+ const { gl } = this.device;
4142
+ gl.useProgram(this.handle);
4143
+ let textureUnit = 0;
4144
+ let uniformBufferIndex = 0;
4145
+ for (const binding of this.shaderLayout.bindings) {
4146
+ const value = bindings[binding.name] || bindings[binding.name.replace(/Uniforms$/, "")];
4147
+ if (!value) {
4148
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4149
+ }
4150
+ switch (binding.type) {
4151
+ case "uniform":
4152
+ const { name } = binding;
4153
+ const location = gl.getUniformBlockIndex(this.handle, name);
4154
+ if (location === 4294967295) {
4155
+ throw new Error(`Invalid uniform block name ${name}`);
4156
+ }
4157
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
4158
+ if (value instanceof WEBGLBuffer) {
4159
+ gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4160
+ } else {
4161
+ gl.bindBufferRange(
4162
+ 35345,
4163
+ uniformBufferIndex,
4164
+ // @ts-expect-error
4165
+ value.buffer.handle,
4166
+ // @ts-expect-error
4167
+ value.offset || 0,
4168
+ // @ts-expect-error
4169
+ value.size || value.buffer.byteLength - value.offset
4170
+ );
4171
+ }
4172
+ uniformBufferIndex += 1;
4173
+ break;
4174
+ case "texture":
4175
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4176
+ throw new Error("texture");
4177
+ }
4178
+ let texture;
4179
+ if (value instanceof WEBGLTextureView) {
4180
+ texture = value.texture;
4181
+ } else if (value instanceof WEBGLTexture) {
4182
+ texture = value;
4183
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4184
+ import_core17.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4185
+ texture = value.colorAttachments[0].texture;
4186
+ } else {
4187
+ throw new Error("No texture");
4188
+ }
4189
+ gl.activeTexture(33984 + textureUnit);
4190
+ gl.bindTexture(texture.glTarget, texture.handle);
4191
+ textureUnit += 1;
4192
+ break;
4193
+ case "sampler":
4194
+ break;
4195
+ case "storage":
4196
+ case "read-only-storage":
4197
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4198
+ }
4199
+ }
4200
+ }
4201
+ /**
4202
+ * Due to program sharing, uniforms need to be reset before every draw call
4203
+ * (though caching will avoid redundant WebGL calls)
4204
+ */
4205
+ _applyUniforms(uniforms) {
4206
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
4207
+ const { name, location, type, textureUnit } = uniformLayout;
4208
+ const value = uniforms[name] ?? textureUnit;
4209
+ if (value !== void 0) {
4210
+ setUniform(this.device.gl, location, type, value);
4211
+ }
4212
+ }
4213
+ }
4214
+ _syncLinkStatus() {
4215
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
4216
+ }
4217
+ };
4218
+ }
4219
+ });
4220
+
4221
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
4222
+ function convertDataTypeToGLDataType(normalizedType) {
4223
+ return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
4224
+ }
4225
+ function convertGLUniformTypeToShaderVariableType(glUniformType) {
4226
+ return WEBGL_SHADER_TYPES[glUniformType];
4227
+ }
4228
+ function isGLSamplerType(type) {
4229
+ return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]);
4230
+ }
4231
+ function getTextureBindingFromGLSamplerType(glSamplerType) {
4232
+ return WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[glSamplerType];
4233
+ }
4234
+ var WEBGL_SHADER_TYPES, WEBGL_SAMPLER_TO_TEXTURE_BINDINGS, NORMALIZED_SHADER_TYPE_TO_WEBGL;
4235
+ var init_webgl_shadertypes = __esm({
4236
+ "../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js"() {
4237
+ WEBGL_SHADER_TYPES = {
4238
+ [5126]: "f32",
4239
+ [35664]: "vec2<f32>",
4240
+ [35665]: "vec3<f32>",
4241
+ [35666]: "vec4<f32>",
4242
+ [5124]: "i32",
4243
+ [35667]: "vec2<i32>",
4244
+ [35668]: "vec3<i32>",
4245
+ [35669]: "vec4<i32>",
4246
+ [5125]: "u32",
4247
+ [36294]: "vec2<u32>",
4248
+ [36295]: "vec3<u32>",
4249
+ [36296]: "vec4<u32>",
4250
+ [35670]: "f32",
4251
+ [35671]: "vec2<f32>",
4252
+ [35672]: "vec3<f32>",
4253
+ [35673]: "vec4<f32>",
4254
+ // TODO - are sizes/components below correct?
4255
+ [35674]: "mat2x2<f32>",
4256
+ [35685]: "mat2x3<f32>",
4257
+ [35686]: "mat2x4<f32>",
4258
+ [35687]: "mat3x2<f32>",
4259
+ [35675]: "mat3x3<f32>",
4260
+ [35688]: "mat3x4<f32>",
4261
+ [35689]: "mat4x2<f32>",
4262
+ [35690]: "mat4x3<f32>",
4263
+ [35676]: "mat4x4<f32>"
4264
+ };
4265
+ WEBGL_SAMPLER_TO_TEXTURE_BINDINGS = {
4266
+ [35678]: { viewDimension: "2d", sampleType: "float" },
4267
+ [35680]: { viewDimension: "cube", sampleType: "float" },
4268
+ [35679]: { viewDimension: "3d", sampleType: "float" },
4269
+ [35682]: { viewDimension: "3d", sampleType: "depth" },
4270
+ [36289]: { viewDimension: "2d-array", sampleType: "float" },
4271
+ [36292]: { viewDimension: "2d-array", sampleType: "depth" },
4272
+ [36293]: { viewDimension: "cube", sampleType: "float" },
4273
+ [36298]: { viewDimension: "2d", sampleType: "sint" },
4274
+ [36299]: { viewDimension: "3d", sampleType: "sint" },
4275
+ [36300]: { viewDimension: "cube", sampleType: "sint" },
4276
+ [36303]: { viewDimension: "2d-array", sampleType: "uint" },
4277
+ [36306]: { viewDimension: "2d", sampleType: "uint" },
4278
+ [36307]: { viewDimension: "3d", sampleType: "uint" },
4279
+ [36308]: { viewDimension: "cube", sampleType: "uint" },
4280
+ [36311]: { viewDimension: "2d-array", sampleType: "uint" }
4281
+ };
4282
+ NORMALIZED_SHADER_TYPE_TO_WEBGL = {
4283
+ uint8: 5121,
4284
+ sint8: 5120,
4285
+ unorm8: 5121,
4286
+ snorm8: 5120,
4287
+ uint16: 5123,
4288
+ sint16: 5122,
4289
+ unorm16: 5123,
4290
+ snorm16: 5122,
4291
+ uint32: 5125,
4292
+ sint32: 5124,
4293
+ // WebGPU does not support normalized 32 bit integer attributes
4294
+ // 'unorm32': GL.UNSIGNED_INT,
4295
+ // 'snorm32': GL.INT,
4296
+ float16: 5131,
4297
+ float32: 5126
4298
+ };
4299
+ }
4300
+ });
4301
+
4302
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
4303
+ function getShaderLayoutFromGLSL(gl, program) {
4304
+ const shaderLayout = {
4305
+ attributes: [],
4306
+ bindings: []
4307
+ };
4308
+ shaderLayout.attributes = readAttributeDeclarations(gl, program);
4309
+ const uniformBlocks = readUniformBlocks(gl, program);
4310
+ for (const uniformBlock of uniformBlocks) {
4311
+ const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
4312
+ name: uniform.name,
4313
+ format: uniform.format,
4314
+ byteOffset: uniform.byteOffset,
4315
+ byteStride: uniform.byteStride,
4316
+ arrayLength: uniform.arrayLength
4317
+ }));
4318
+ shaderLayout.bindings.push({
4319
+ type: "uniform",
4320
+ name: uniformBlock.name,
4321
+ group: 0,
4322
+ location: uniformBlock.location,
4323
+ visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
4324
+ minBindingSize: uniformBlock.byteLength,
4325
+ uniforms: uniforms2
4326
+ });
4327
+ }
4328
+ const uniforms = readUniformBindings(gl, program);
4329
+ let textureUnit = 0;
4330
+ for (const uniform of uniforms) {
4331
+ if (isGLSamplerType(uniform.type)) {
4332
+ const { viewDimension, sampleType } = getTextureBindingFromGLSamplerType(uniform.type);
4333
+ shaderLayout.bindings.push({
4334
+ type: "texture",
4335
+ name: uniform.name,
4336
+ group: 0,
4337
+ location: textureUnit,
4338
+ viewDimension,
4339
+ sampleType
4340
+ });
4341
+ uniform.textureUnit = textureUnit;
4342
+ textureUnit += 1;
4343
+ }
4344
+ }
4345
+ if (uniforms.length) {
4346
+ shaderLayout.uniforms = uniforms;
4347
+ }
4348
+ const varyings = readVaryings(gl, program);
4349
+ if (varyings?.length) {
4350
+ shaderLayout.varyings = varyings;
4351
+ }
4352
+ return shaderLayout;
4353
+ }
4354
+ function readAttributeDeclarations(gl, program) {
4355
+ const attributes = [];
4356
+ const count = gl.getProgramParameter(program, 35721);
4357
+ for (let index = 0; index < count; index++) {
4358
+ const activeInfo = gl.getActiveAttrib(program, index);
4359
+ if (!activeInfo) {
4360
+ throw new Error("activeInfo");
4361
+ }
4362
+ const {
4363
+ name,
4364
+ type: compositeType
4365
+ /* , size*/
4366
+ } = activeInfo;
4367
+ const location = gl.getAttribLocation(program, name);
4368
+ if (location >= 0) {
4369
+ const attributeType = convertGLUniformTypeToShaderVariableType(compositeType);
4370
+ const stepMode = /instance/i.test(name) ? "instance" : "vertex";
4371
+ attributes.push({
4372
+ name,
4373
+ location,
4374
+ stepMode,
4375
+ type: attributeType
4376
+ // size - for arrays, size is the number of elements in the array
4377
+ });
4378
+ }
4379
+ }
4380
+ attributes.sort((a, b) => a.location - b.location);
4381
+ return attributes;
4382
+ }
4383
+ function readVaryings(gl, program) {
4384
+ const varyings = [];
4385
+ const count = gl.getProgramParameter(program, 35971);
4386
+ for (let location = 0; location < count; location++) {
4387
+ const activeInfo = gl.getTransformFeedbackVarying(program, location);
4388
+ if (!activeInfo) {
4389
+ throw new Error("activeInfo");
4390
+ }
4391
+ const { name, type: glUniformType, size } = activeInfo;
4392
+ const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
4393
+ const { type, components } = (0, import_core18.getVariableShaderTypeInfo)(uniformType);
4394
+ varyings.push({ location, name, type, size: size * components });
4395
+ }
4396
+ varyings.sort((a, b) => a.location - b.location);
4397
+ return varyings;
4398
+ }
4399
+ function readUniformBindings(gl, program) {
4400
+ const uniforms = [];
4401
+ const uniformCount = gl.getProgramParameter(program, 35718);
4402
+ for (let i = 0; i < uniformCount; i++) {
4403
+ const activeInfo = gl.getActiveUniform(program, i);
4404
+ if (!activeInfo) {
4405
+ throw new Error("activeInfo");
4406
+ }
4407
+ const { name: rawName, size, type } = activeInfo;
4408
+ const { name, isArray: isArray4 } = parseUniformName(rawName);
4409
+ let webglLocation = gl.getUniformLocation(program, name);
4410
+ const uniformInfo = {
4411
+ // WebGL locations are uniquely typed but just numbers
4412
+ location: webglLocation,
4413
+ name,
4414
+ size,
4415
+ type,
4416
+ isArray: isArray4
4417
+ };
4418
+ uniforms.push(uniformInfo);
4419
+ if (uniformInfo.size > 1) {
4420
+ for (let j = 0; j < uniformInfo.size; j++) {
4421
+ const elementName = `${name}[${j}]`;
4422
+ webglLocation = gl.getUniformLocation(program, elementName);
4423
+ const arrayElementUniformInfo = {
4424
+ ...uniformInfo,
4425
+ name: elementName,
4426
+ location: webglLocation
4427
+ };
4428
+ uniforms.push(arrayElementUniformInfo);
4429
+ }
4430
+ }
4431
+ }
4432
+ return uniforms;
4433
+ }
4434
+ function readUniformBlocks(gl, program) {
4435
+ const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
4436
+ const uniformBlocks = [];
4437
+ const blockCount = gl.getProgramParameter(program, 35382);
4438
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
4439
+ const blockInfo = {
4440
+ name: gl.getActiveUniformBlockName(program, blockIndex) || "",
4441
+ location: getBlockParameter(blockIndex, 35391),
4442
+ byteLength: getBlockParameter(blockIndex, 35392),
4443
+ vertex: getBlockParameter(blockIndex, 35396),
4444
+ fragment: getBlockParameter(blockIndex, 35398),
4445
+ uniformCount: getBlockParameter(blockIndex, 35394),
4446
+ uniforms: []
4447
+ };
4448
+ const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
4449
+ const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
4450
+ const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
4451
+ const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
4452
+ const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
4453
+ for (let i = 0; i < blockInfo.uniformCount; ++i) {
4454
+ const uniformIndex = uniformIndices[i];
4455
+ if (uniformIndex !== void 0) {
4456
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
4457
+ if (!activeInfo) {
4458
+ throw new Error("activeInfo");
4459
+ }
4460
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
4461
+ blockInfo.uniforms.push({
4462
+ name: activeInfo.name,
4463
+ format,
4464
+ type: uniformType[i],
4465
+ arrayLength: uniformArrayLength[i],
4466
+ byteOffset: uniformOffset[i],
4467
+ byteStride: uniformStride[i]
4468
+ // matrixStride: uniformStride[i],
4469
+ // rowMajor: uniformRowMajor[i]
4470
+ });
4471
+ }
4472
+ }
4473
+ uniformBlocks.push(blockInfo);
4474
+ }
4475
+ uniformBlocks.sort((a, b) => a.location - b.location);
4476
+ return uniformBlocks;
4477
+ }
4478
+ function parseUniformName(name) {
4479
+ if (name[name.length - 1] !== "]") {
4480
+ return {
4481
+ name,
4482
+ length: 1,
4483
+ isArray: false
4484
+ };
4485
+ }
4486
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
4487
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
4488
+ const uniformName = (0, import_core18.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
4489
+ return {
4490
+ name: uniformName,
4491
+ // TODO - is this a bug, shouldn't we return the value?
4492
+ length: matches?.[2] ? 1 : 0,
4493
+ isArray: Boolean(matches?.[2])
4494
+ };
4495
+ }
4496
+ var import_core18;
4497
+ var init_get_shader_layout_from_glsl = __esm({
4498
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
4499
+ import_core18 = __toESM(require_core2(), 1);
4500
+ init_webgl_shadertypes();
4501
+ }
4502
+ });
4503
+
4504
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js
4505
+ var import_core19, LOG_PROGRAM_PERF_PRIORITY, WEBGLSharedRenderPipeline;
4506
+ var init_webgl_shared_render_pipeline = __esm({
4507
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js"() {
4508
+ import_core19 = __toESM(require_core2(), 1);
4509
+ init_get_shader_layout_from_glsl();
4510
+ init_webgl_shadertypes();
4511
+ LOG_PROGRAM_PERF_PRIORITY = 4;
4512
+ WEBGLSharedRenderPipeline = class extends import_core19.SharedRenderPipeline {
4513
+ device;
4514
+ handle;
4515
+ vs;
4516
+ fs;
4517
+ introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
4518
+ linkStatus = "pending";
4519
+ constructor(device, props) {
4520
+ super(device, props);
4521
+ this.device = device;
4522
+ this.handle = props.handle || this.device.gl.createProgram();
4523
+ this.vs = props.vs;
4524
+ this.fs = props.fs;
4525
+ if (props.varyings && props.varyings.length > 0) {
4526
+ this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
4527
+ }
4528
+ this._linkShaders();
4529
+ import_core19.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4530
+ this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
4531
+ import_core19.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
4532
+ }
4533
+ destroy() {
4534
+ if (this.destroyed) {
4535
+ return;
4090
4536
  }
4091
- this._applyBindings();
4092
- this._applyUniforms();
4093
- const webglRenderPass = renderPass;
4094
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4095
- if (isIndexed && isInstanced) {
4096
- this.device.gl.drawElementsInstanced(
4097
- glDrawMode,
4098
- vertexCount || 0,
4099
- // indexCount?
4100
- glIndexType,
4101
- firstVertex,
4102
- instanceCount || 0
4103
- );
4104
- } else if (isIndexed) {
4105
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4106
- } else if (isInstanced) {
4107
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4108
- } else {
4109
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4110
- }
4111
- if (transformFeedback) {
4112
- transformFeedback.end();
4113
- }
4114
- });
4115
- vertexArray.unbindAfterRender(renderPass);
4116
- return true;
4537
+ this.device.gl.useProgram(null);
4538
+ this.device.gl.deleteProgram(this.handle);
4539
+ this.handle.destroyed = true;
4540
+ this.destroyResource();
4117
4541
  }
4118
- // PRIVATE METHODS
4119
- // setAttributes(attributes: Record<string, Buffer>): void {}
4120
- // setBindings(bindings: Record<string, Binding>): void {}
4121
4542
  async _linkShaders() {
4122
4543
  const { gl } = this.device;
4123
4544
  gl.attachShader(this.handle, this.vs.handle);
4124
4545
  gl.attachShader(this.handle, this.fs.handle);
4125
- import_core17.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4546
+ import_core19.log.time(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4126
4547
  gl.linkProgram(this.handle);
4127
- import_core17.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4128
- if (import_core17.log.level === 0) {
4129
- }
4548
+ import_core19.log.timeEnd(LOG_PROGRAM_PERF_PRIORITY, `linkProgram for ${this.id}`)();
4130
4549
  if (!this.device.features.has("compilation-status-async-webgl")) {
4131
4550
  const status2 = this._getLinkStatus();
4132
4551
  this._reportLinkStatus(status2);
4133
4552
  return;
4134
4553
  }
4135
- import_core17.log.once(1, "RenderPipeline linking is asynchronous")();
4554
+ import_core19.log.once(1, "RenderPipeline linking is asynchronous")();
4136
4555
  await this._waitForLinkComplete();
4137
- import_core17.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4556
+ import_core19.log.info(2, `RenderPipeline ${this.id} - async linking complete: ${this.linkStatus}`)();
4138
4557
  const status = this._getLinkStatus();
4139
4558
  this._reportLinkStatus(status);
4140
4559
  }
4141
- /** Report link status. First, check for shader compilation failures if linking fails */
4142
4560
  async _reportLinkStatus(status) {
4143
4561
  switch (status) {
4144
4562
  case "success":
@@ -4172,11 +4590,6 @@ ${source}`;
4172
4590
  this.device.debug();
4173
4591
  }
4174
4592
  }
4175
- /**
4176
- * Get the shader compilation status
4177
- * TODO - Load log even when no error reported, to catch warnings?
4178
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
4179
- */
4180
4593
  _getLinkStatus() {
4181
4594
  const { gl } = this.device;
4182
4595
  const linked = gl.getProgramParameter(this.handle, 35714);
@@ -4184,6 +4597,7 @@ ${source}`;
4184
4597
  this.linkStatus = "error";
4185
4598
  return "link-error";
4186
4599
  }
4600
+ this._initializeSamplerUniforms();
4187
4601
  gl.validateProgram(this.handle);
4188
4602
  const validated = gl.getProgramParameter(this.handle, 35715);
4189
4603
  if (!validated) {
@@ -4193,7 +4607,33 @@ ${source}`;
4193
4607
  this.linkStatus = "success";
4194
4608
  return "success";
4195
4609
  }
4196
- /** Use KHR_parallel_shader_compile extension if available */
4610
+ _initializeSamplerUniforms() {
4611
+ const { gl } = this.device;
4612
+ gl.useProgram(this.handle);
4613
+ let textureUnit = 0;
4614
+ const uniformCount = gl.getProgramParameter(this.handle, 35718);
4615
+ for (let uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) {
4616
+ const activeInfo = gl.getActiveUniform(this.handle, uniformIndex);
4617
+ if (activeInfo && isGLSamplerType(activeInfo.type)) {
4618
+ const isArray4 = activeInfo.name.endsWith("[0]");
4619
+ const uniformName = isArray4 ? activeInfo.name.slice(0, -3) : activeInfo.name;
4620
+ const location = gl.getUniformLocation(this.handle, uniformName);
4621
+ if (location !== null) {
4622
+ textureUnit = this._assignSamplerUniform(location, activeInfo, isArray4, textureUnit);
4623
+ }
4624
+ }
4625
+ }
4626
+ }
4627
+ _assignSamplerUniform(location, activeInfo, isArray4, textureUnit) {
4628
+ const { gl } = this.device;
4629
+ if (isArray4 && activeInfo.size > 1) {
4630
+ const textureUnits = Int32Array.from({ length: activeInfo.size }, (_, arrayIndex) => textureUnit + arrayIndex);
4631
+ gl.uniform1iv(location, textureUnits);
4632
+ return textureUnit + activeInfo.size;
4633
+ }
4634
+ gl.uniform1i(location, textureUnit);
4635
+ return textureUnit + 1;
4636
+ }
4197
4637
  async _waitForLinkComplete() {
4198
4638
  const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
4199
4639
  const DELAY_MS = 10;
@@ -4210,99 +4650,6 @@ ${source}`;
4210
4650
  await waitMs(DELAY_MS);
4211
4651
  }
4212
4652
  }
4213
- /**
4214
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
4215
- * Update a texture if needed (e.g. from video)
4216
- * Note: This is currently done before every draw call
4217
- */
4218
- _areTexturesRenderable() {
4219
- let texturesRenderable = true;
4220
- for (const bindingInfo of this.shaderLayout.bindings) {
4221
- if (!this.bindings[bindingInfo.name] && !this.bindings[bindingInfo.name.replace(/Uniforms$/, "")]) {
4222
- import_core17.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
4223
- texturesRenderable = false;
4224
- }
4225
- }
4226
- return texturesRenderable;
4227
- }
4228
- /** Apply any bindings (before each draw call) */
4229
- _applyBindings() {
4230
- if (this.linkStatus !== "success") {
4231
- return;
4232
- }
4233
- const { gl } = this.device;
4234
- gl.useProgram(this.handle);
4235
- let textureUnit = 0;
4236
- let uniformBufferIndex = 0;
4237
- for (const binding of this.shaderLayout.bindings) {
4238
- const value = this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, "")];
4239
- if (!value) {
4240
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
4241
- }
4242
- switch (binding.type) {
4243
- case "uniform":
4244
- const { name } = binding;
4245
- const location = gl.getUniformBlockIndex(this.handle, name);
4246
- if (location === 4294967295) {
4247
- throw new Error(`Invalid uniform block name ${name}`);
4248
- }
4249
- gl.uniformBlockBinding(this.handle, uniformBufferIndex, location);
4250
- if (value instanceof WEBGLBuffer) {
4251
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
4252
- } else {
4253
- gl.bindBufferRange(
4254
- 35345,
4255
- uniformBufferIndex,
4256
- // @ts-expect-error
4257
- value.buffer.handle,
4258
- // @ts-expect-error
4259
- value.offset || 0,
4260
- // @ts-expect-error
4261
- value.size || value.buffer.byteLength - value.offset
4262
- );
4263
- }
4264
- uniformBufferIndex += 1;
4265
- break;
4266
- case "texture":
4267
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
4268
- throw new Error("texture");
4269
- }
4270
- let texture;
4271
- if (value instanceof WEBGLTextureView) {
4272
- texture = value.texture;
4273
- } else if (value instanceof WEBGLTexture) {
4274
- texture = value;
4275
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
4276
- import_core17.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
4277
- texture = value.colorAttachments[0].texture;
4278
- } else {
4279
- throw new Error("No texture");
4280
- }
4281
- gl.activeTexture(33984 + textureUnit);
4282
- gl.bindTexture(texture.glTarget, texture.handle);
4283
- textureUnit += 1;
4284
- break;
4285
- case "sampler":
4286
- break;
4287
- case "storage":
4288
- case "read-only-storage":
4289
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
4290
- }
4291
- }
4292
- }
4293
- /**
4294
- * Due to program sharing, uniforms need to be reset before every draw call
4295
- * (though caching will avoid redundant WebGL calls)
4296
- */
4297
- _applyUniforms() {
4298
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
4299
- const { name, location, type, textureUnit } = uniformLayout;
4300
- const value = this.uniforms[name] ?? textureUnit;
4301
- if (value !== void 0) {
4302
- setUniform(this.device.gl, location, type, value);
4303
- }
4304
- }
4305
- }
4306
4653
  };
4307
4654
  }
4308
4655
  });
@@ -4334,7 +4681,7 @@ ${source}`;
4334
4681
  height = options.sourceTexture.height,
4335
4682
  depthOrArrayLayers = 0,
4336
4683
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
4337
- origin = [0, 0],
4684
+ origin = [0, 0, 0],
4338
4685
  /** Destination buffer */
4339
4686
  destinationBuffer,
4340
4687
  /** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
@@ -4363,7 +4710,8 @@ ${source}`;
4363
4710
  const webglBuffer = destinationBuffer;
4364
4711
  const sourceWidth = width || framebuffer.width;
4365
4712
  const sourceHeight = height || framebuffer.height;
4366
- const sourceParams = getTextureFormatWebGL(framebuffer.colorAttachments[0].texture.props.format);
4713
+ const colorAttachment0 = (0, import_core20.assertDefined)(framebuffer.colorAttachments[0]);
4714
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
4367
4715
  const sourceFormat = sourceParams.format;
4368
4716
  const sourceType = sourceParams.type;
4369
4717
  device.gl.bindBuffer(35051, webglBuffer.handle);
@@ -4390,7 +4738,7 @@ ${source}`;
4390
4738
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy from. */
4391
4739
  origin = [0, 0],
4392
4740
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
4393
- destinationOrigin = [0, 0],
4741
+ destinationOrigin = [0, 0, 0],
4394
4742
  /** Texture to copy to/from. */
4395
4743
  destinationTexture
4396
4744
  /** Mip-map level of the texture to copy to/from. (Default 0) */
@@ -4406,7 +4754,7 @@ ${source}`;
4406
4754
  // depthOrArrayLayers = 0
4407
4755
  } = options;
4408
4756
  const { framebuffer, destroyFramebuffer } = getFramebuffer(sourceTexture);
4409
- const [sourceX, sourceY] = origin;
4757
+ const [sourceX = 0, sourceY = 0] = origin;
4410
4758
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
4411
4759
  const prevHandle = device.gl.bindFramebuffer(36160, framebuffer.handle);
4412
4760
  let texture;
@@ -4440,7 +4788,7 @@ ${source}`;
4440
4788
  }
4441
4789
  }
4442
4790
  function getFramebuffer(source) {
4443
- if (source instanceof import_core18.Texture) {
4791
+ if (source instanceof import_core20.Texture) {
4444
4792
  const { width, height, id } = source;
4445
4793
  const framebuffer = source.device.createFramebuffer({
4446
4794
  id: `framebuffer-for-${id}`,
@@ -4452,18 +4800,18 @@ ${source}`;
4452
4800
  }
4453
4801
  return { framebuffer: source, destroyFramebuffer: false };
4454
4802
  }
4455
- var import_core18, WEBGLCommandBuffer;
4803
+ var import_core20, WEBGLCommandBuffer;
4456
4804
  var init_webgl_command_buffer = __esm({
4457
4805
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-buffer.js"() {
4458
- import_core18 = __toESM(require_core2(), 1);
4806
+ import_core20 = __toESM(require_core2(), 1);
4459
4807
  init_webgl_texture();
4460
4808
  init_webgl_texture_table();
4461
- WEBGLCommandBuffer = class extends import_core18.CommandBuffer {
4809
+ WEBGLCommandBuffer = class extends import_core20.CommandBuffer {
4462
4810
  device;
4463
4811
  handle = null;
4464
4812
  commands = [];
4465
- constructor(device) {
4466
- super(device, {});
4813
+ constructor(device, props = {}) {
4814
+ super(device, props);
4467
4815
  this.device = device;
4468
4816
  }
4469
4817
  _executeCommands(commands = this.commands) {
@@ -4491,14 +4839,14 @@ ${source}`;
4491
4839
  });
4492
4840
 
4493
4841
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js
4494
- var import_core19, COLOR_CHANNELS, WEBGLRenderPass;
4842
+ var import_core21, COLOR_CHANNELS, WEBGLRenderPass;
4495
4843
  var init_webgl_render_pass = __esm({
4496
4844
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js"() {
4497
- import_core19 = __toESM(require_core2(), 1);
4845
+ import_core21 = __toESM(require_core2(), 1);
4498
4846
  init_with_parameters();
4499
4847
  init_unified_parameter_api();
4500
4848
  COLOR_CHANNELS = [1, 2, 4, 8];
4501
- WEBGLRenderPass = class extends import_core19.RenderPass {
4849
+ WEBGLRenderPass = class extends import_core21.RenderPass {
4502
4850
  device;
4503
4851
  handle = null;
4504
4852
  /** Parameters that should be applied before each draw call */
@@ -4506,6 +4854,9 @@ ${source}`;
4506
4854
  constructor(device, props) {
4507
4855
  super(device, props);
4508
4856
  this.device = device;
4857
+ if (!props?.framebuffer) {
4858
+ device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
4859
+ }
4509
4860
  let viewport;
4510
4861
  if (!props?.parameters?.viewport) {
4511
4862
  if (props?.framebuffer) {
@@ -4526,9 +4877,21 @@ ${source}`;
4526
4877
  this.device.gl.drawBuffers([1029]);
4527
4878
  }
4528
4879
  this.clear();
4880
+ if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== void 0) {
4881
+ const webglQuerySet = this.props.timestampQuerySet;
4882
+ webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
4883
+ }
4529
4884
  }
4530
4885
  end() {
4886
+ if (this.destroyed) {
4887
+ return;
4888
+ }
4889
+ if (this.props.timestampQuerySet && this.props.endTimestampIndex !== void 0) {
4890
+ const webglQuerySet = this.props.timestampQuerySet;
4891
+ webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
4892
+ }
4531
4893
  this.device.popState();
4894
+ this.destroy();
4532
4895
  }
4533
4896
  pushDebugGroup(groupLabel) {
4534
4897
  }
@@ -4648,30 +5011,38 @@ ${source}`;
4648
5011
  });
4649
5012
 
4650
5013
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js
4651
- var import_core20, WEBGLCommandEncoder;
5014
+ var import_core22, WEBGLCommandEncoder;
4652
5015
  var init_webgl_command_encoder = __esm({
4653
5016
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-command-encoder.js"() {
4654
- import_core20 = __toESM(require_core2(), 1);
5017
+ import_core22 = __toESM(require_core2(), 1);
4655
5018
  init_webgl_command_buffer();
4656
5019
  init_webgl_render_pass();
4657
- WEBGLCommandEncoder = class extends import_core20.CommandEncoder {
5020
+ WEBGLCommandEncoder = class extends import_core22.CommandEncoder {
4658
5021
  device;
4659
5022
  handle = null;
4660
5023
  commandBuffer;
4661
5024
  constructor(device, props) {
4662
5025
  super(device, props);
4663
5026
  this.device = device;
4664
- this.commandBuffer = new WEBGLCommandBuffer(device);
5027
+ this.commandBuffer = new WEBGLCommandBuffer(device, {
5028
+ id: `${this.props.id}-command-buffer`
5029
+ });
4665
5030
  }
4666
5031
  destroy() {
5032
+ this.destroyResource();
4667
5033
  }
4668
- finish() {
5034
+ finish(props) {
5035
+ if (props?.id && this.commandBuffer.id !== props.id) {
5036
+ this.commandBuffer.id = props.id;
5037
+ this.commandBuffer.props.id = props.id;
5038
+ }
5039
+ this.destroy();
4669
5040
  return this.commandBuffer;
4670
5041
  }
4671
- beginRenderPass(props) {
4672
- return new WEBGLRenderPass(this.device, props);
5042
+ beginRenderPass(props = {}) {
5043
+ return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
4673
5044
  }
4674
- beginComputePass(props) {
5045
+ beginComputePass(props = {}) {
4675
5046
  throw new Error("ComputePass not supported in WebGL");
4676
5047
  }
4677
5048
  copyBufferToBuffer(options) {
@@ -4697,6 +5068,10 @@ ${source}`;
4697
5068
  }
4698
5069
  resolveQuerySet(querySet, destination, options) {
4699
5070
  }
5071
+ writeTimestamp(querySet, queryIndex) {
5072
+ const webglQuerySet = querySet;
5073
+ webglQuerySet.writeTimestamp(queryIndex);
5074
+ }
4700
5075
  };
4701
5076
  }
4702
5077
  });
@@ -4708,7 +5083,7 @@ ${source}`;
4708
5083
  const total = count * length;
4709
5084
  let copied = 0;
4710
5085
  for (let i = start; copied < length; copied++) {
4711
- target2[i++] = source[copied];
5086
+ target2[i++] = source[copied] ?? 0;
4712
5087
  }
4713
5088
  while (copied < total) {
4714
5089
  if (copied < total - copied) {
@@ -4744,14 +5119,14 @@ ${source}`;
4744
5119
  }
4745
5120
  return true;
4746
5121
  }
4747
- var import_core21, WEBGLVertexArray;
5122
+ var import_core23, WEBGLVertexArray;
4748
5123
  var init_webgl_vertex_array = __esm({
4749
5124
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-vertex-array.js"() {
4750
- import_core21 = __toESM(require_core2(), 1);
5125
+ import_core23 = __toESM(require_core2(), 1);
4751
5126
  init_dist2();
4752
5127
  init_webgl_vertex_formats();
4753
5128
  init_fill_array();
4754
- WEBGLVertexArray = class extends import_core21.VertexArray {
5129
+ WEBGLVertexArray = class extends import_core23.VertexArray {
4755
5130
  get [Symbol.toStringTag]() {
4756
5131
  return "VertexArray";
4757
5132
  }
@@ -4917,7 +5292,7 @@ ${source}`;
4917
5292
  this.buffer = this.buffer || this.device.createBuffer({ byteLength });
4918
5293
  updateNeeded ||= !compareConstantArrayValues(constantValue, this.bufferValue);
4919
5294
  if (updateNeeded) {
4920
- const typedArray = (0, import_core21.getScratchArray)(value.constructor, length);
5295
+ const typedArray = (0, import_core23.getScratchArray)(value.constructor, length);
4921
5296
  fillArray({ target: typedArray, source: constantValue, start: 0, count: length });
4922
5297
  this.buffer.write(typedArray);
4923
5298
  this.bufferValue = value;
@@ -4935,13 +5310,13 @@ ${source}`;
4935
5310
  }
4936
5311
  return /^\d+$/.test(value);
4937
5312
  }
4938
- var import_core22, WEBGLTransformFeedback;
5313
+ var import_core24, WEBGLTransformFeedback;
4939
5314
  var init_webgl_transform_feedback = __esm({
4940
5315
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-transform-feedback.js"() {
4941
- import_core22 = __toESM(require_core2(), 1);
5316
+ import_core24 = __toESM(require_core2(), 1);
4942
5317
  init_dist3();
4943
5318
  init_webgl_topology_utils();
4944
- WEBGLTransformFeedback = class extends import_core22.TransformFeedback {
5319
+ WEBGLTransformFeedback = class extends import_core24.TransformFeedback {
4945
5320
  device;
4946
5321
  gl;
4947
5322
  handle;
@@ -4994,8 +5369,8 @@ ${source}`;
4994
5369
  this.buffers = {};
4995
5370
  this.unusedBuffers = {};
4996
5371
  this.bind(() => {
4997
- for (const bufferName in buffers) {
4998
- this.setBuffer(bufferName, buffers[bufferName]);
5372
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
5373
+ this.setBuffer(bufferName, buffer);
4999
5374
  }
5000
5375
  });
5001
5376
  }
@@ -5004,7 +5379,7 @@ ${source}`;
5004
5379
  const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferOrRange);
5005
5380
  if (location < 0) {
5006
5381
  this.unusedBuffers[locationOrName] = buffer;
5007
- import_core22.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5382
+ import_core24.log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
5008
5383
  return;
5009
5384
  }
5010
5385
  this.buffers[location] = { buffer, byteLength, byteOffset };
@@ -5017,7 +5392,7 @@ ${source}`;
5017
5392
  return this.buffers[locationOrName] || null;
5018
5393
  }
5019
5394
  const location = this._getVaryingIndex(locationOrName);
5020
- return location >= 0 ? this.buffers[location] : null;
5395
+ return this.buffers[location] ?? null;
5021
5396
  }
5022
5397
  bind(funcOrHandle = this.handle) {
5023
5398
  if (typeof funcOrHandle !== "function") {
@@ -5064,8 +5439,8 @@ ${source}`;
5064
5439
  * cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
5065
5440
  */
5066
5441
  _bindBuffers() {
5067
- for (const bufferIndex in this.buffers) {
5068
- const { buffer, byteLength, byteOffset } = this._getBufferRange(this.buffers[bufferIndex]);
5442
+ for (const [bufferIndex, bufferEntry] of Object.entries(this.buffers)) {
5443
+ const { buffer, byteLength, byteOffset } = this._getBufferRange(bufferEntry);
5069
5444
  this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
5070
5445
  }
5071
5446
  }
@@ -5087,149 +5462,242 @@ ${source}`;
5087
5462
  });
5088
5463
 
5089
5464
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js
5090
- var import_core23, WEBGLQuerySet;
5465
+ var import_core25, WEBGLQuerySet;
5091
5466
  var init_webgl_query_set = __esm({
5092
5467
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-query-set.js"() {
5093
- import_core23 = __toESM(require_core2(), 1);
5094
- WEBGLQuerySet = class extends import_core23.QuerySet {
5468
+ import_core25 = __toESM(require_core2(), 1);
5469
+ WEBGLQuerySet = class extends import_core25.QuerySet {
5095
5470
  device;
5096
5471
  handle;
5097
- target = null;
5098
- _queryPending = false;
5099
- _pollingPromise = null;
5472
+ _timestampPairs = [];
5473
+ _occlusionQuery = null;
5474
+ _occlusionActive = false;
5100
5475
  get [Symbol.toStringTag]() {
5101
- return "Query";
5476
+ return "QuerySet";
5102
5477
  }
5103
- // Create a query class
5104
5478
  constructor(device, props) {
5105
5479
  super(device, props);
5106
5480
  this.device = device;
5107
- if (props.count > 1) {
5108
- throw new Error("WebGL QuerySet can only have one value");
5109
- }
5110
- const handle = this.device.gl.createQuery();
5111
- if (!handle) {
5112
- throw new Error("WebGL query not supported");
5481
+ if (props.type === "timestamp") {
5482
+ if (props.count < 2) {
5483
+ throw new Error("Timestamp QuerySet requires at least two query slots");
5484
+ }
5485
+ this._timestampPairs = new Array(Math.ceil(props.count / 2)).fill(null).map(() => ({ activeQuery: null, completedQueries: [] }));
5486
+ this.handle = null;
5487
+ } else {
5488
+ if (props.count > 1) {
5489
+ throw new Error("WebGL occlusion QuerySet can only have one value");
5490
+ }
5491
+ const handle = this.device.gl.createQuery();
5492
+ if (!handle) {
5493
+ throw new Error("WebGL query not supported");
5494
+ }
5495
+ this.handle = handle;
5113
5496
  }
5114
- this.handle = handle;
5115
5497
  Object.seal(this);
5116
5498
  }
5117
5499
  destroy() {
5118
- this.device.gl.deleteQuery(this.handle);
5500
+ if (this.destroyed) {
5501
+ return;
5502
+ }
5503
+ if (this.handle) {
5504
+ this.device.gl.deleteQuery(this.handle);
5505
+ }
5506
+ for (const pair of this._timestampPairs) {
5507
+ if (pair.activeQuery) {
5508
+ this.device.gl.deleteQuery(pair.activeQuery.handle);
5509
+ }
5510
+ for (const query of pair.completedQueries) {
5511
+ this.device.gl.deleteQuery(query.handle);
5512
+ }
5513
+ }
5514
+ if (this._occlusionQuery) {
5515
+ this.device.gl.deleteQuery(this._occlusionQuery.handle);
5516
+ }
5517
+ this.destroyResource();
5119
5518
  }
5120
- // FOR RENDER PASS AND COMMAND ENCODER
5121
- /**
5122
- * Shortcut for timer query (dependent on extension in both WebGL1 and 2)
5123
- * Measures GPU time delta between this call and a matching `end` call in the
5124
- * GPU instruction stream.
5125
- */
5126
- beginTimestampQuery() {
5127
- return this._begin(35007);
5519
+ isResultAvailable(queryIndex) {
5520
+ if (this.props.type === "timestamp") {
5521
+ if (queryIndex === void 0) {
5522
+ return this._timestampPairs.some((_, pairIndex) => this._isTimestampPairAvailable(pairIndex));
5523
+ }
5524
+ return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
5525
+ }
5526
+ if (!this._occlusionQuery) {
5527
+ return false;
5528
+ }
5529
+ return this._pollQueryAvailability(this._occlusionQuery);
5530
+ }
5531
+ async readResults(options) {
5532
+ const firstQuery = options?.firstQuery || 0;
5533
+ const queryCount = options?.queryCount || this.props.count - firstQuery;
5534
+ this._validateRange(firstQuery, queryCount);
5535
+ if (this.props.type === "timestamp") {
5536
+ const results = new Array(queryCount).fill(0n);
5537
+ const startPairIndex = Math.floor(firstQuery / 2);
5538
+ const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
5539
+ for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
5540
+ const duration = await this._consumeTimestampPairResult(pairIndex);
5541
+ const beginSlot = pairIndex * 2;
5542
+ const endSlot = beginSlot + 1;
5543
+ if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
5544
+ results[beginSlot - firstQuery] = 0n;
5545
+ }
5546
+ if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
5547
+ results[endSlot - firstQuery] = duration;
5548
+ }
5549
+ }
5550
+ return results;
5551
+ }
5552
+ if (!this._occlusionQuery) {
5553
+ throw new Error("Occlusion query has not been started");
5554
+ }
5555
+ return [await this._consumeQueryResult(this._occlusionQuery)];
5128
5556
  }
5129
- endTimestampQuery() {
5130
- this._end();
5557
+ async readTimestampDuration(beginIndex, endIndex) {
5558
+ if (this.props.type !== "timestamp") {
5559
+ throw new Error("Timestamp durations require a timestamp QuerySet");
5560
+ }
5561
+ if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
5562
+ throw new Error("Timestamp duration range is out of bounds");
5563
+ }
5564
+ if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
5565
+ throw new Error("WebGL timestamp durations require adjacent even/odd query indices");
5566
+ }
5567
+ const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
5568
+ return Number(result) / 1e6;
5131
5569
  }
5132
- // Shortcut for occlusion queries
5133
- beginOcclusionQuery(options) {
5134
- return this._begin(options?.conservative ? 36202 : 35887);
5570
+ beginOcclusionQuery() {
5571
+ if (this.props.type !== "occlusion") {
5572
+ throw new Error("Occlusion queries require an occlusion QuerySet");
5573
+ }
5574
+ if (!this.handle) {
5575
+ throw new Error("WebGL occlusion query is not available");
5576
+ }
5577
+ if (this._occlusionActive) {
5578
+ throw new Error("Occlusion query is already active");
5579
+ }
5580
+ this.device.gl.beginQuery(35887, this.handle);
5581
+ this._occlusionQuery = {
5582
+ handle: this.handle,
5583
+ promise: null,
5584
+ result: null,
5585
+ disjoint: false
5586
+ };
5587
+ this._occlusionActive = true;
5135
5588
  }
5136
5589
  endOcclusionQuery() {
5137
- this._end();
5138
- }
5139
- // Shortcut for transformFeedbackQuery
5140
- beginTransformFeedbackQuery() {
5141
- return this._begin(35976);
5142
- }
5143
- endTransformFeedbackQuery() {
5144
- this._end();
5145
- }
5146
- async resolveQuery() {
5147
- const value = await this.pollQuery();
5148
- return [value];
5149
- }
5150
- // PRIVATE METHODS
5151
- /**
5152
- * Due to OpenGL API limitations, after calling `begin()` on one Query
5153
- * instance, `end()` must be called on that same instance before
5154
- * calling `begin()` on another query. While there can be multiple
5155
- * outstanding queries representing disjoint `begin()`/`end()` intervals.
5156
- * It is not possible to interleave or overlap `begin` and `end` calls.
5157
- */
5158
- _begin(target2) {
5159
- if (this._queryPending) {
5160
- return;
5590
+ if (!this._occlusionActive) {
5591
+ throw new Error("Occlusion query is not active");
5161
5592
  }
5162
- this.target = target2;
5163
- this.device.gl.beginQuery(this.target, this.handle);
5164
- return;
5593
+ this.device.gl.endQuery(35887);
5594
+ this._occlusionActive = false;
5165
5595
  }
5166
- // ends the current query
5167
- _end() {
5168
- if (this._queryPending) {
5596
+ writeTimestamp(queryIndex) {
5597
+ if (this.props.type !== "timestamp") {
5598
+ throw new Error("Timestamp writes require a timestamp QuerySet");
5599
+ }
5600
+ const pairIndex = this._getTimestampPairIndex(queryIndex);
5601
+ const pair = this._timestampPairs[pairIndex];
5602
+ if (queryIndex % 2 === 0) {
5603
+ if (pair.activeQuery) {
5604
+ throw new Error("Timestamp query pair is already active");
5605
+ }
5606
+ const handle = this.device.gl.createQuery();
5607
+ if (!handle) {
5608
+ throw new Error("WebGL query not supported");
5609
+ }
5610
+ const query = {
5611
+ handle,
5612
+ promise: null,
5613
+ result: null,
5614
+ disjoint: false
5615
+ };
5616
+ this.device.gl.beginQuery(35007, handle);
5617
+ pair.activeQuery = query;
5169
5618
  return;
5170
5619
  }
5171
- if (this.target) {
5172
- this.device.gl.endQuery(this.target);
5173
- this.target = null;
5174
- this._queryPending = true;
5620
+ if (!pair.activeQuery) {
5621
+ throw new Error("Timestamp query pair was ended before it was started");
5175
5622
  }
5176
- return;
5623
+ this.device.gl.endQuery(35007);
5624
+ pair.completedQueries.push(pair.activeQuery);
5625
+ pair.activeQuery = null;
5177
5626
  }
5178
- // Returns true if the query result is available
5179
- isResultAvailable() {
5180
- if (!this._queryPending) {
5181
- return false;
5627
+ _validateRange(firstQuery, queryCount) {
5628
+ if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
5629
+ throw new Error("Query read range is out of bounds");
5182
5630
  }
5183
- const resultAvailable = this.device.gl.getQueryParameter(this.handle, 34919);
5184
- if (resultAvailable) {
5185
- this._queryPending = false;
5631
+ }
5632
+ _getTimestampPairIndex(queryIndex) {
5633
+ if (queryIndex < 0 || queryIndex >= this.props.count) {
5634
+ throw new Error("Query index is out of bounds");
5186
5635
  }
5187
- return resultAvailable;
5636
+ return Math.floor(queryIndex / 2);
5188
5637
  }
5189
- // Timing query is disjoint, i.e. results are invalid
5190
- isTimerDisjoint() {
5191
- return this.device.gl.getParameter(36795);
5638
+ _isTimestampPairAvailable(pairIndex) {
5639
+ const pair = this._timestampPairs[pairIndex];
5640
+ if (!pair || pair.completedQueries.length === 0) {
5641
+ return false;
5642
+ }
5643
+ return this._pollQueryAvailability(pair.completedQueries[0]);
5192
5644
  }
5193
- // Returns query result.
5194
- getResult() {
5195
- return this.device.gl.getQueryParameter(this.handle, 34918);
5645
+ _pollQueryAvailability(query) {
5646
+ if (query.result !== null || query.disjoint) {
5647
+ return true;
5648
+ }
5649
+ const resultAvailable = this.device.gl.getQueryParameter(query.handle, 34919);
5650
+ if (!resultAvailable) {
5651
+ return false;
5652
+ }
5653
+ const isDisjoint = Boolean(this.device.gl.getParameter(36795));
5654
+ query.disjoint = isDisjoint;
5655
+ query.result = isDisjoint ? 0n : BigInt(this.device.gl.getQueryParameter(query.handle, 34918));
5656
+ return true;
5196
5657
  }
5197
- // Returns the query result, converted to milliseconds to match JavaScript conventions.
5198
- getTimerMilliseconds() {
5199
- return this.getResult() / 1e6;
5658
+ async _consumeTimestampPairResult(pairIndex) {
5659
+ const pair = this._timestampPairs[pairIndex];
5660
+ if (!pair || pair.completedQueries.length === 0) {
5661
+ throw new Error("Timestamp query pair has no completed result");
5662
+ }
5663
+ const query = pair.completedQueries.shift();
5664
+ try {
5665
+ return await this._consumeQueryResult(query);
5666
+ } finally {
5667
+ this.device.gl.deleteQuery(query.handle);
5668
+ }
5200
5669
  }
5201
- // Polls the query
5202
- pollQuery(limit = Number.POSITIVE_INFINITY) {
5203
- if (this._pollingPromise) {
5204
- return this._pollingPromise;
5670
+ _consumeQueryResult(query) {
5671
+ if (query.promise) {
5672
+ return query.promise;
5205
5673
  }
5206
- let counter = 0;
5207
- this._pollingPromise = new Promise((resolve, reject) => {
5674
+ query.promise = new Promise((resolve, reject) => {
5208
5675
  const poll = () => {
5209
- if (this.isResultAvailable()) {
5210
- resolve(this.getResult());
5211
- this._pollingPromise = null;
5212
- } else if (counter++ > limit) {
5213
- reject("Timed out");
5214
- this._pollingPromise = null;
5215
- } else {
5676
+ if (!this._pollQueryAvailability(query)) {
5216
5677
  requestAnimationFrame(poll);
5678
+ return;
5679
+ }
5680
+ query.promise = null;
5681
+ if (query.disjoint) {
5682
+ reject(new Error("GPU timestamp query was invalidated by a disjoint event"));
5683
+ } else {
5684
+ resolve(query.result || 0n);
5217
5685
  }
5218
5686
  };
5219
- requestAnimationFrame(poll);
5687
+ poll();
5220
5688
  });
5221
- return this._pollingPromise;
5689
+ return query.promise;
5222
5690
  }
5223
5691
  };
5224
5692
  }
5225
5693
  });
5226
5694
 
5227
5695
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js
5228
- var import_core24, WEBGLFence;
5696
+ var import_core26, WEBGLFence;
5229
5697
  var init_webgl_fence = __esm({
5230
5698
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-fence.js"() {
5231
- import_core24 = __toESM(require_core2(), 1);
5232
- WEBGLFence = class extends import_core24.Fence {
5699
+ import_core26 = __toESM(require_core2(), 1);
5700
+ WEBGLFence = class extends import_core26.Fence {
5233
5701
  device;
5234
5702
  gl;
5235
5703
  handle;
@@ -5348,7 +5816,7 @@ ${source}`;
5348
5816
  sourceFormat ||= texture?.glFormat || 6408;
5349
5817
  sourceType ||= texture?.glType || 5121;
5350
5818
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
5351
- const signedType = (0, import_core25.getDataType)(target2);
5819
+ const signedType = (0, import_core27.getDataType)(target2);
5352
5820
  sourceType = sourceType || convertDataTypeToGLDataType(signedType);
5353
5821
  const prevHandle = gl.bindFramebuffer(36160, handle);
5354
5822
  gl.readBuffer(36064 + sourceAttachment);
@@ -5391,7 +5859,7 @@ ${source}`;
5391
5859
  return webglBufferTarget;
5392
5860
  }
5393
5861
  function getFramebuffer2(source) {
5394
- if (!(source instanceof import_core25.Framebuffer)) {
5862
+ if (!(source instanceof import_core27.Framebuffer)) {
5395
5863
  return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
5396
5864
  }
5397
5865
  return { framebuffer: source, deleteFramebuffer: false };
@@ -5413,14 +5881,14 @@ ${source}`;
5413
5881
  }
5414
5882
  glType ||= 5121;
5415
5883
  const shaderType = convertGLDataTypeToDataType(glType);
5416
- const ArrayType = (0, import_core25.getTypedArrayConstructor)(shaderType);
5884
+ const ArrayType = (0, import_core27.getTypedArrayConstructor)(shaderType);
5417
5885
  const components = glFormatToComponents(glFormat);
5418
5886
  return new ArrayType(width * height * components);
5419
5887
  }
5420
- var import_core25;
5888
+ var import_core27;
5421
5889
  var init_webgl_texture_utils = __esm({
5422
5890
  "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-texture-utils.js"() {
5423
- import_core25 = __toESM(require_core2(), 1);
5891
+ import_core27 = __toESM(require_core2(), 1);
5424
5892
  init_webgl_shadertypes();
5425
5893
  init_format_utils();
5426
5894
  init_shader_formats();
@@ -5462,16 +5930,18 @@ ${source}`;
5462
5930
  }
5463
5931
  return true;
5464
5932
  }
5465
- var import_core26, WebGLDevice;
5933
+ var import_core28, WebGLDevice;
5466
5934
  var init_webgl_device = __esm({
5467
5935
  "../../node_modules/@luma.gl/webgl/dist/adapter/webgl-device.js"() {
5468
- import_core26 = __toESM(require_core2(), 1);
5936
+ import_core28 = __toESM(require_core2(), 1);
5469
5937
  init_webgl_state_tracker();
5470
5938
  init_create_browser_context();
5939
+ init_webgl_context_data();
5471
5940
  init_webgl_device_info();
5472
5941
  init_webgl_device_features();
5473
5942
  init_webgl_device_limits();
5474
5943
  init_webgl_canvas_context();
5944
+ init_webgl_presentation_context();
5475
5945
  init_spector();
5476
5946
  init_webgl_developer_tools();
5477
5947
  init_webgl_texture_table();
@@ -5482,6 +5952,7 @@ ${source}`;
5482
5952
  init_webgl_texture();
5483
5953
  init_webgl_framebuffer();
5484
5954
  init_webgl_render_pipeline();
5955
+ init_webgl_shared_render_pipeline();
5485
5956
  init_webgl_command_encoder();
5486
5957
  init_webgl_vertex_array();
5487
5958
  init_webgl_transform_feedback();
@@ -5491,7 +5962,13 @@ ${source}`;
5491
5962
  init_unified_parameter_api();
5492
5963
  init_with_parameters();
5493
5964
  init_webgl_extensions();
5494
- WebGLDevice = class extends import_core26.Device {
5965
+ WebGLDevice = class extends import_core28.Device {
5966
+ static getDeviceFromContext(gl) {
5967
+ if (!gl) {
5968
+ return null;
5969
+ }
5970
+ return gl.luma?.device ?? null;
5971
+ }
5495
5972
  // Public `Device` API
5496
5973
  /** type of this device */
5497
5974
  type = "webgl";
@@ -5513,7 +5990,7 @@ ${source}`;
5513
5990
  // @ts-ignore TODO fix
5514
5991
  _constants;
5515
5992
  /** State used by luma.gl classes - TODO - not used? */
5516
- _extensions = {};
5993
+ extensions;
5517
5994
  _polyfilled = false;
5518
5995
  /** Instance of Spector.js (if initialized) */
5519
5996
  spectorJS;
@@ -5536,11 +6013,12 @@ ${source}`;
5536
6013
  }
5537
6014
  constructor(props) {
5538
6015
  super({ ...props, id: props.id || uid("webgl-device") });
5539
- const canvasContextProps = import_core26.Device._getCanvasContextProps(props);
6016
+ const canvasContextProps = import_core28.Device._getCanvasContextProps(props);
5540
6017
  if (!canvasContextProps) {
5541
6018
  throw new Error("WebGLDevice requires props.createCanvasContext to be set");
5542
6019
  }
5543
- let device = canvasContextProps.canvas?.gl?.device;
6020
+ const existingContext = canvasContextProps.canvas?.gl ?? null;
6021
+ let device = WebGLDevice.getDeviceFromContext(existingContext);
5544
6022
  if (device) {
5545
6023
  throw new Error(`WebGL context already attached to device ${device.id}`);
5546
6024
  }
@@ -5570,10 +6048,11 @@ ${source}`;
5570
6048
  if (!gl) {
5571
6049
  throw new Error("WebGL context creation failed");
5572
6050
  }
5573
- device = gl.device;
6051
+ device = WebGLDevice.getDeviceFromContext(gl);
5574
6052
  if (device) {
5575
6053
  if (props._reuseDevices) {
5576
- import_core26.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6054
+ import_core28.log.log(1, `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`, device)();
6055
+ this.canvasContext.destroy();
5577
6056
  device._reused = true;
5578
6057
  return device;
5579
6058
  }
@@ -5582,25 +6061,28 @@ ${source}`;
5582
6061
  this.handle = gl;
5583
6062
  this.gl = gl;
5584
6063
  this.spectorJS = initializeSpectorJS({ ...this.props, gl: this.handle });
5585
- this.gl.device = this;
5586
- this.info = getDeviceInfo(this.gl, this._extensions);
6064
+ const contextData = getWebGLContextData(this.handle);
6065
+ contextData.device = this;
6066
+ this.extensions = contextData.extensions || (contextData.extensions = {});
6067
+ this.info = getDeviceInfo(this.gl, this.extensions);
5587
6068
  this.limits = new WebGLDeviceLimits(this.gl);
5588
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
6069
+ this.features = new WebGLDeviceFeatures(this.gl, this.extensions, this.props._disabledFeatures);
5589
6070
  if (this.props._initializeFeatures) {
5590
6071
  this.features.initializeFeatures();
5591
6072
  }
5592
6073
  const glState = new WebGLStateTracker(this.gl, {
5593
- log: (...args) => import_core26.log.log(1, ...args)()
6074
+ log: (...args) => import_core28.log.log(1, ...args)()
5594
6075
  });
5595
6076
  glState.trackState(this.gl, { copyState: false });
5596
6077
  if (props.debug || props.debugWebGL) {
5597
6078
  this.gl = makeDebugContext(this.gl, { debugWebGL: true, traceWebGL: props.debugWebGL });
5598
- import_core26.log.warn("WebGL debug mode activated. Performance reduced.")();
6079
+ import_core28.log.warn("WebGL debug mode activated. Performance reduced.")();
5599
6080
  }
5600
6081
  if (props.debugWebGL) {
5601
- import_core26.log.level = Math.max(import_core26.log.level, 1);
6082
+ import_core28.log.level = Math.max(import_core28.log.level, 1);
5602
6083
  }
5603
6084
  this.commandEncoder = new WEBGLCommandEncoder(this, { id: `${this}-command-encoder` });
6085
+ this.canvasContext._startObservers();
5604
6086
  }
5605
6087
  /**
5606
6088
  * Destroys the device
@@ -5613,8 +6095,10 @@ ${source}`;
5613
6095
  * browser API for destroying WebGL contexts.
5614
6096
  */
5615
6097
  destroy() {
6098
+ this.commandEncoder?.destroy();
5616
6099
  if (!this.props._reuseDevices && !this._reused) {
5617
- delete this.gl.device;
6100
+ const contextData = getWebGLContextData(this.handle);
6101
+ contextData.device = null;
5618
6102
  }
5619
6103
  }
5620
6104
  get isLost() {
@@ -5624,6 +6108,9 @@ ${source}`;
5624
6108
  createCanvasContext(props) {
5625
6109
  throw new Error("WebGL only supports a single canvas");
5626
6110
  }
6111
+ createPresentationContext(props) {
6112
+ return new WebGLPresentationContext(this, props || {});
6113
+ }
5627
6114
  createBuffer(props) {
5628
6115
  const newProps = this._normalizeBufferProps(props);
5629
6116
  return new WEBGLBuffer(this, newProps);
@@ -5658,6 +6145,9 @@ ${source}`;
5658
6145
  createRenderPipeline(props) {
5659
6146
  return new WEBGLRenderPipeline(this, props);
5660
6147
  }
6148
+ _createSharedRenderPipelineWebGL(props) {
6149
+ return new WEBGLSharedRenderPipeline(this, props);
6150
+ }
5661
6151
  createComputePipeline(props) {
5662
6152
  throw new Error("ComputePipeline not supported in WebGL");
5663
6153
  }
@@ -5670,12 +6160,27 @@ ${source}`;
5670
6160
  * Chrome's offscreen canvas does not require gl.commit
5671
6161
  */
5672
6162
  submit(commandBuffer) {
6163
+ let submittedCommandEncoder = null;
5673
6164
  if (!commandBuffer) {
5674
- commandBuffer = this.commandEncoder.finish();
6165
+ submittedCommandEncoder = this.commandEncoder;
6166
+ commandBuffer = submittedCommandEncoder.finish();
5675
6167
  this.commandEncoder.destroy();
5676
- this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
6168
+ this.commandEncoder = this.createCommandEncoder({
6169
+ id: submittedCommandEncoder.props.id,
6170
+ timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
6171
+ });
6172
+ }
6173
+ try {
6174
+ commandBuffer._executeCommands();
6175
+ if (submittedCommandEncoder) {
6176
+ submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
6177
+ this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
6178
+ }).catch(() => {
6179
+ });
6180
+ }
6181
+ } finally {
6182
+ commandBuffer.destroy();
5677
6183
  }
5678
- commandBuffer._executeCommands();
5679
6184
  }
5680
6185
  //
5681
6186
  // TEMPORARY HACKS - will be removed in v9.1
@@ -5698,11 +6203,11 @@ ${source}`;
5698
6203
  return withGLParameters(this.gl, parameters, func);
5699
6204
  }
5700
6205
  resetWebGL() {
5701
- import_core26.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
6206
+ import_core28.log.warn("WebGLDevice.resetWebGL is deprecated, use only for debugging")();
5702
6207
  resetGLParameters(this.gl);
5703
6208
  }
5704
6209
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
5705
- return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
6210
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this.extensions);
5706
6211
  }
5707
6212
  //
5708
6213
  // WebGL-only API (not part of `Device` API)
@@ -5770,7 +6275,7 @@ ${source}`;
5770
6275
  this._constants = this._constants || new Array(maxVertexAttributes).fill(null);
5771
6276
  const currentConstant = this._constants[location];
5772
6277
  if (currentConstant && compareConstantArrayValues2(currentConstant, constant)) {
5773
- import_core26.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
6278
+ import_core28.log.info(1, `setConstantAttributeWebGL(${location}) could have been skipped, value unchanged`)();
5774
6279
  }
5775
6280
  this._constants[location] = constant;
5776
6281
  switch (constant.constructor) {
@@ -5789,8 +6294,8 @@ ${source}`;
5789
6294
  }
5790
6295
  /** Ensure extensions are only requested once */
5791
6296
  getExtension(name) {
5792
- getWebGLExtension(this.gl, name, this._extensions);
5793
- return this._extensions;
6297
+ getWebGLExtension(this.gl, name, this.extensions);
6298
+ return this.extensions;
5794
6299
  }
5795
6300
  // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
5796
6301
  /**
@@ -5836,7 +6341,7 @@ ${source}`;
5836
6341
  init_dist3();
5837
6342
 
5838
6343
  // src/utils.ts
5839
- var import_core27 = __toESM(require_core(), 1);
6344
+ var import_core29 = __toESM(require_core(), 1);
5840
6345
 
5841
6346
  // ../../node_modules/@math.gl/core/dist/lib/common.js
5842
6347
  var RADIANS_TO_DEGREES = 1 / Math.PI * 180;
@@ -7778,13 +8283,13 @@ ${source}`;
7778
8283
  mousemove: null,
7779
8284
  mouseout: null
7780
8285
  };
7781
- const newDeck = new import_core27.Deck({
8286
+ const newDeck = new import_core29.Deck({
7782
8287
  ...props,
7783
8288
  // Default to true for high-DPI displays, but allow user override
7784
8289
  useDevicePixels: props.useDevicePixels ?? true,
7785
8290
  style: props.interleaved ? null : { pointerEvents: "none" },
7786
8291
  parent: getContainer(overlay, props.style),
7787
- views: new import_core27.MapView({ repeat: true }),
8292
+ views: new import_core29.MapView({ repeat: true }),
7788
8293
  initialViewState: {
7789
8294
  longitude: 0,
7790
8295
  latitude: 0,