@luma.gl/engine 9.3.0-alpha.2 → 9.3.0-alpha.4

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
@@ -899,8 +899,8 @@ var __exports__ = (() => {
899
899
  }
900
900
 
901
901
  // src/model/model.ts
902
- var import_core10 = __toESM(require_core(), 1);
903
- var import_shadertools2 = __toESM(require_shadertools(), 1);
902
+ var import_core12 = __toESM(require_core(), 1);
903
+ var import_shadertools3 = __toESM(require_shadertools(), 1);
904
904
 
905
905
  // src/geometry/gpu-geometry.ts
906
906
  var import_core3 = __toESM(require_core(), 1);
@@ -1408,6 +1408,16 @@ var __exports__ = (() => {
1408
1408
  };
1409
1409
 
1410
1410
  // src/utils/buffer-layout-order.ts
1411
+ function getMinLocation(attributeNames, shaderLayoutMap) {
1412
+ let minLocation = Infinity;
1413
+ for (const name of attributeNames) {
1414
+ const location = shaderLayoutMap[name];
1415
+ if (location !== void 0) {
1416
+ minLocation = Math.min(minLocation, location);
1417
+ }
1418
+ }
1419
+ return minLocation;
1420
+ }
1411
1421
  function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
1412
1422
  const shaderLayoutMap = Object.fromEntries(
1413
1423
  shaderLayout.attributes.map((attr) => [attr.name, attr.location])
@@ -1416,8 +1426,8 @@ var __exports__ = (() => {
1416
1426
  sortedLayout.sort((a, b) => {
1417
1427
  const attributeNamesA = a.attributes ? a.attributes.map((attr) => attr.attribute) : [a.name];
1418
1428
  const attributeNamesB = b.attributes ? b.attributes.map((attr) => attr.attribute) : [b.name];
1419
- const minLocationA = Math.min(...attributeNamesA.map((name) => shaderLayoutMap[name]));
1420
- const minLocationB = Math.min(...attributeNamesB.map((name) => shaderLayoutMap[name]));
1429
+ const minLocationA = getMinLocation(attributeNamesA, shaderLayoutMap);
1430
+ const minLocationB = getMinLocation(attributeNamesB, shaderLayoutMap);
1421
1431
  return minLocationA - minLocationB;
1422
1432
  });
1423
1433
  return sortedLayout;
@@ -1564,7 +1574,7 @@ var __exports__ = (() => {
1564
1574
  };
1565
1575
 
1566
1576
  // src/dynamic-texture/dynamic-texture.ts
1567
- var import_core9 = __toESM(require_core(), 1);
1577
+ var import_core11 = __toESM(require_core(), 1);
1568
1578
 
1569
1579
  // src/dynamic-texture/texture-data.ts
1570
1580
  var import_core8 = __toESM(require_core(), 1);
@@ -1700,12 +1710,662 @@ var __exports__ = (() => {
1700
1710
  data.forEach((cubeData, cubeIndex) => {
1701
1711
  for (const [face, faceData] of Object.entries(cubeData)) {
1702
1712
  const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
1703
- getTexture2DSubresources(faceDepth, faceData);
1713
+ subresources.push(...getTexture2DSubresources(faceDepth, faceData));
1704
1714
  }
1705
1715
  });
1706
1716
  return subresources;
1707
1717
  }
1708
1718
 
1719
+ // src/dynamic-texture/mipmaps.ts
1720
+ var import_core10 = __toESM(require_core(), 1);
1721
+
1722
+ // src/compute/computation.ts
1723
+ var import_core9 = __toESM(require_core(), 1);
1724
+ var import_shadertools2 = __toESM(require_shadertools(), 1);
1725
+ var LOG_DRAW_PRIORITY = 2;
1726
+ var LOG_DRAW_TIMEOUT = 1e4;
1727
+ var _Computation = class {
1728
+ device;
1729
+ id;
1730
+ pipelineFactory;
1731
+ shaderFactory;
1732
+ userData = {};
1733
+ /** Bindings (textures, samplers, uniform buffers) */
1734
+ bindings = {};
1735
+ /** The underlying GPU pipeline. */
1736
+ pipeline;
1737
+ /** Assembled compute shader source */
1738
+ source;
1739
+ /** the underlying compiled compute shader */
1740
+ // @ts-ignore Set in function called from constructor
1741
+ shader;
1742
+ /** ShaderInputs instance */
1743
+ shaderInputs;
1744
+ // @ts-ignore Set in function called from constructor
1745
+ _uniformStore;
1746
+ _pipelineNeedsUpdate = "newly created";
1747
+ _getModuleUniforms;
1748
+ props;
1749
+ _destroyed = false;
1750
+ constructor(device, props) {
1751
+ if (device.type !== "webgpu") {
1752
+ throw new Error("Computation is only supported in WebGPU");
1753
+ }
1754
+ this.props = { ..._Computation.defaultProps, ...props };
1755
+ props = this.props;
1756
+ this.id = props.id || uid("model");
1757
+ this.device = device;
1758
+ Object.assign(this.userData, props.userData);
1759
+ const moduleMap = Object.fromEntries(
1760
+ this.props.modules?.map((module) => [module.name, module]) || []
1761
+ );
1762
+ this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
1763
+ this.setShaderInputs(this.shaderInputs);
1764
+ this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
1765
+ const platformInfo = getPlatformInfo(device);
1766
+ const modules = (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
1767
+ this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
1768
+ this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
1769
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
1770
+ platformInfo,
1771
+ ...this.props,
1772
+ modules
1773
+ });
1774
+ this.source = source3;
1775
+ this._getModuleUniforms = getUniforms2;
1776
+ this.pipeline = this._updatePipeline();
1777
+ if (props.bindings) {
1778
+ this.setBindings(props.bindings);
1779
+ }
1780
+ Object.seal(this);
1781
+ }
1782
+ destroy() {
1783
+ if (this._destroyed)
1784
+ return;
1785
+ this.pipelineFactory.release(this.pipeline);
1786
+ this.shaderFactory.release(this.shader);
1787
+ this._uniformStore.destroy();
1788
+ this._destroyed = true;
1789
+ }
1790
+ // Draw call
1791
+ predraw() {
1792
+ this.updateShaderInputs();
1793
+ }
1794
+ dispatch(computePass, x, y, z) {
1795
+ try {
1796
+ this._logDrawCallStart();
1797
+ this.pipeline = this._updatePipeline();
1798
+ this.pipeline.setBindings(this.bindings);
1799
+ computePass.setPipeline(this.pipeline);
1800
+ computePass.setBindings([]);
1801
+ computePass.dispatch(x, y, z);
1802
+ } finally {
1803
+ this._logDrawCallEnd();
1804
+ }
1805
+ }
1806
+ // Update fixed fields (can trigger pipeline rebuild)
1807
+ // Update dynamic fields
1808
+ /**
1809
+ * Updates the vertex count (used in draw calls)
1810
+ * @note Any attributes with stepMode=vertex need to be at least this big
1811
+ */
1812
+ setVertexCount(vertexCount) {
1813
+ }
1814
+ /**
1815
+ * Updates the instance count (used in draw calls)
1816
+ * @note Any attributes with stepMode=instance need to be at least this big
1817
+ */
1818
+ setInstanceCount(instanceCount) {
1819
+ }
1820
+ setShaderInputs(shaderInputs) {
1821
+ this.shaderInputs = shaderInputs;
1822
+ this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
1823
+ for (const moduleName of Object.keys(this.shaderInputs.modules)) {
1824
+ const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
1825
+ this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
1826
+ }
1827
+ }
1828
+ /**
1829
+ * Updates shader module settings (which results in uniforms being set)
1830
+ */
1831
+ setShaderModuleProps(props) {
1832
+ const uniforms = this._getModuleUniforms(props);
1833
+ const keys = Object.keys(uniforms).filter((k) => {
1834
+ const uniform = uniforms[k];
1835
+ return !isNumericArray(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
1836
+ });
1837
+ const bindings = {};
1838
+ for (const k of keys) {
1839
+ bindings[k] = uniforms[k];
1840
+ delete uniforms[k];
1841
+ }
1842
+ }
1843
+ updateShaderInputs() {
1844
+ this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
1845
+ }
1846
+ /**
1847
+ * Sets bindings (textures, samplers, uniform buffers)
1848
+ */
1849
+ setBindings(bindings) {
1850
+ Object.assign(this.bindings, bindings);
1851
+ }
1852
+ _setPipelineNeedsUpdate(reason) {
1853
+ this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
1854
+ }
1855
+ _updatePipeline() {
1856
+ if (this._pipelineNeedsUpdate) {
1857
+ let prevShader = null;
1858
+ if (this.pipeline) {
1859
+ import_core9.log.log(
1860
+ 1,
1861
+ `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
1862
+ )();
1863
+ prevShader = this.shader;
1864
+ }
1865
+ this._pipelineNeedsUpdate = false;
1866
+ this.shader = this.shaderFactory.createShader({
1867
+ id: `${this.id}-fragment`,
1868
+ stage: "compute",
1869
+ source: this.source,
1870
+ debugShaders: this.props.debugShaders
1871
+ });
1872
+ this.pipeline = this.pipelineFactory.createComputePipeline({
1873
+ ...this.props,
1874
+ shader: this.shader
1875
+ });
1876
+ if (prevShader) {
1877
+ this.shaderFactory.release(prevShader);
1878
+ }
1879
+ }
1880
+ return this.pipeline;
1881
+ }
1882
+ /** Throttle draw call logging */
1883
+ _lastLogTime = 0;
1884
+ _logOpen = false;
1885
+ _logDrawCallStart() {
1886
+ const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
1887
+ if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
1888
+ return;
1889
+ }
1890
+ this._lastLogTime = Date.now();
1891
+ this._logOpen = true;
1892
+ import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
1893
+ }
1894
+ _logDrawCallEnd() {
1895
+ if (this._logOpen) {
1896
+ const uniformTable = this.shaderInputs.getDebugTable();
1897
+ import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1898
+ import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
1899
+ this._logOpen = false;
1900
+ }
1901
+ }
1902
+ _drawCount = 0;
1903
+ // TODO - fix typing of luma data types
1904
+ _getBufferOrConstantValues(attribute, dataType) {
1905
+ const TypedArrayConstructor = (0, import_core9.getTypedArrayConstructor)(dataType);
1906
+ const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
1907
+ return typedArray.toString();
1908
+ }
1909
+ };
1910
+ var Computation = _Computation;
1911
+ __publicField(Computation, "defaultProps", {
1912
+ ...import_core9.ComputePipeline.defaultProps,
1913
+ id: "unnamed",
1914
+ handle: void 0,
1915
+ userData: {},
1916
+ source: "",
1917
+ modules: [],
1918
+ defines: {},
1919
+ bindings: void 0,
1920
+ shaderInputs: void 0,
1921
+ pipelineFactory: void 0,
1922
+ shaderFactory: void 0,
1923
+ shaderAssembler: import_shadertools2.ShaderAssembler.getDefaultShaderAssembler(),
1924
+ debugShaders: void 0
1925
+ });
1926
+ function getPlatformInfo(device) {
1927
+ return {
1928
+ type: device.type,
1929
+ shaderLanguage: device.info.shadingLanguage,
1930
+ shaderLanguageVersion: device.info.shadingLanguageVersion,
1931
+ gpu: device.info.gpu,
1932
+ // HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
1933
+ features: device.features
1934
+ };
1935
+ }
1936
+
1937
+ // src/dynamic-texture/mipmaps.ts
1938
+ var RENDER_DIMENSIONS = [
1939
+ "2d",
1940
+ "2d-array",
1941
+ "cube",
1942
+ "cube-array"
1943
+ ];
1944
+ var WORKGROUP_SIZE = {
1945
+ x: 4,
1946
+ y: 4,
1947
+ z: 4
1948
+ };
1949
+ function generateMipmap(device, texture) {
1950
+ if (texture.mipLevels <= 1) {
1951
+ return;
1952
+ }
1953
+ if (device.type !== "webgpu") {
1954
+ throw new Error(
1955
+ `Cannot generate mipmaps on device type "${device.type}". Use generateMipmapsWebGL for WebGL devices.`
1956
+ );
1957
+ }
1958
+ if (texture.dimension === "3d") {
1959
+ generateMipmaps3D(device, texture);
1960
+ return;
1961
+ }
1962
+ if (RENDER_DIMENSIONS.includes(texture.dimension)) {
1963
+ generateMipmapsRender(device, texture);
1964
+ return;
1965
+ }
1966
+ throw new Error(
1967
+ `Cannot generate mipmaps for texture dimension "${texture.dimension}" with WebGPU.`
1968
+ );
1969
+ }
1970
+ function generateMipmapsRender(device, texture) {
1971
+ validateFormatCapabilities(device, texture, ["render", "filter"], "render");
1972
+ const colorAttachmentFormat = getColorAttachmentFormat(
1973
+ texture.format,
1974
+ "render",
1975
+ texture.dimension
1976
+ );
1977
+ const viewDimension = texture.dimension;
1978
+ const shader = getRenderMipmapWGSL(viewDimension);
1979
+ const sampler = device.createSampler({ minFilter: "linear", magFilter: "linear" });
1980
+ const uniformValues = new Uint32Array(1);
1981
+ const uniformsBuffer = device.createBuffer({
1982
+ byteLength: 16,
1983
+ usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
1984
+ });
1985
+ const model = new Model(device, {
1986
+ source: shader,
1987
+ colorAttachmentFormats: [colorAttachmentFormat],
1988
+ topology: "triangle-list",
1989
+ vertexCount: 3,
1990
+ shaderLayout: {
1991
+ attributes: [],
1992
+ bindings: [
1993
+ { type: "sampler", name: "sourceSampler", group: 0, location: 0 },
1994
+ {
1995
+ type: "texture",
1996
+ name: "sourceTexture",
1997
+ group: 0,
1998
+ location: 1,
1999
+ viewDimension,
2000
+ sampleType: "float"
2001
+ },
2002
+ { type: "uniform", name: "uniforms", group: 0, location: 2 }
2003
+ ]
2004
+ },
2005
+ bindings: {
2006
+ sourceSampler: sampler,
2007
+ sourceTexture: texture,
2008
+ uniforms: uniformsBuffer
2009
+ }
2010
+ });
2011
+ let sourceWidth = texture.width;
2012
+ let sourceHeight = texture.height;
2013
+ const layerCount = texture.dimension === "2d" ? 1 : texture.depth;
2014
+ try {
2015
+ for (let baseMipLevel = 1; baseMipLevel < texture.mipLevels; ++baseMipLevel) {
2016
+ validateFormatCapabilities(device, texture, ["render", "filter"], "render");
2017
+ const sourceMipLevel = baseMipLevel - 1;
2018
+ const destinationWidth = Math.max(1, sourceWidth >> 1);
2019
+ const destinationHeight = Math.max(1, sourceHeight >> 1);
2020
+ const sourceView = texture.createView({
2021
+ dimension: viewDimension,
2022
+ baseMipLevel: sourceMipLevel,
2023
+ mipLevelCount: 1,
2024
+ baseArrayLayer: 0,
2025
+ arrayLayerCount: texture.depth
2026
+ });
2027
+ model.setBindings({ sourceTexture: sourceView });
2028
+ for (let baseArrayLayer = 0; baseArrayLayer < layerCount; ++baseArrayLayer) {
2029
+ uniformValues[0] = baseArrayLayer;
2030
+ uniformsBuffer.write(uniformValues);
2031
+ const destinationView = texture.createView({
2032
+ dimension: "2d",
2033
+ baseMipLevel,
2034
+ mipLevelCount: 1,
2035
+ baseArrayLayer,
2036
+ arrayLayerCount: 1
2037
+ });
2038
+ const framebuffer = device.createFramebuffer({
2039
+ colorAttachments: [destinationView]
2040
+ });
2041
+ const renderPass = device.beginRenderPass({
2042
+ id: `mipmap-generation:${texture.format}:${baseMipLevel}:${baseArrayLayer}`,
2043
+ framebuffer
2044
+ });
2045
+ renderPass.setParameters({
2046
+ viewport: [0, 0, destinationWidth, destinationHeight, 0, 1],
2047
+ scissorRect: [0, 0, destinationWidth, destinationHeight]
2048
+ });
2049
+ model.draw(renderPass);
2050
+ renderPass.end();
2051
+ device.submit();
2052
+ destinationView.destroy();
2053
+ framebuffer.destroy();
2054
+ }
2055
+ sourceView.destroy();
2056
+ sourceWidth = destinationWidth;
2057
+ sourceHeight = destinationHeight;
2058
+ }
2059
+ } finally {
2060
+ model.destroy();
2061
+ sampler.destroy();
2062
+ uniformsBuffer.destroy();
2063
+ }
2064
+ }
2065
+ function getColorAttachmentFormat(format, path, dimension) {
2066
+ if (import_core10.textureFormatDecoder.isColor(format)) {
2067
+ return format;
2068
+ }
2069
+ throw new Error(
2070
+ `Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Only color textures can be used for this operation. Required capabilities: color. Actual capabilities: color=false.`
2071
+ );
2072
+ }
2073
+ function generateMipmaps3D(device, texture) {
2074
+ validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
2075
+ const format = getColorAttachmentFormat(texture.format, "compute", texture.dimension);
2076
+ const shaderSource = get3DComputeMipmapWGSL(format);
2077
+ const uniformsBuffer = device.createBuffer({
2078
+ byteLength: 32,
2079
+ usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
2080
+ });
2081
+ const uniformValues = new Uint32Array(8);
2082
+ let sourceWidth = texture.width;
2083
+ let sourceHeight = texture.height;
2084
+ let sourceDepth = texture.depth;
2085
+ try {
2086
+ for (let destinationMipLevel = 1; destinationMipLevel < texture.mipLevels; ++destinationMipLevel) {
2087
+ validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
2088
+ const destinationWidth = Math.max(1, sourceWidth >> 1);
2089
+ const destinationHeight = Math.max(1, sourceHeight >> 1);
2090
+ const destinationDepth = Math.max(1, sourceDepth >> 1);
2091
+ uniformValues[0] = sourceWidth;
2092
+ uniformValues[1] = sourceHeight;
2093
+ uniformValues[2] = sourceDepth;
2094
+ uniformValues[3] = destinationWidth;
2095
+ uniformValues[4] = destinationHeight;
2096
+ uniformValues[5] = destinationDepth;
2097
+ uniformValues[6] = 0;
2098
+ uniformsBuffer.write(uniformValues);
2099
+ const sourceView = texture.createView({
2100
+ dimension: "3d",
2101
+ baseMipLevel: destinationMipLevel - 1,
2102
+ mipLevelCount: 1,
2103
+ baseArrayLayer: 0,
2104
+ arrayLayerCount: 1
2105
+ });
2106
+ const destinationView = texture.createView({
2107
+ dimension: "3d",
2108
+ baseMipLevel: destinationMipLevel,
2109
+ mipLevelCount: 1,
2110
+ baseArrayLayer: 0,
2111
+ arrayLayerCount: 1
2112
+ });
2113
+ const computation = new Computation(device, {
2114
+ source: shaderSource,
2115
+ shaderLayout: {
2116
+ bindings: [
2117
+ {
2118
+ type: "texture",
2119
+ name: "sourceTexture",
2120
+ group: 0,
2121
+ location: 0,
2122
+ viewDimension: "3d",
2123
+ sampleType: "float"
2124
+ },
2125
+ {
2126
+ type: "storage",
2127
+ name: "destinationTexture",
2128
+ group: 0,
2129
+ location: 1,
2130
+ format,
2131
+ viewDimension: "3d",
2132
+ access: "write-only"
2133
+ },
2134
+ { type: "uniform", name: "uniforms", group: 0, location: 2 }
2135
+ ]
2136
+ },
2137
+ bindings: {
2138
+ sourceTexture: sourceView,
2139
+ destinationTexture: destinationView,
2140
+ uniforms: uniformsBuffer
2141
+ }
2142
+ });
2143
+ const workgroupsX = Math.ceil(destinationWidth / WORKGROUP_SIZE.x);
2144
+ const workgroupsY = Math.ceil(destinationHeight / WORKGROUP_SIZE.y);
2145
+ const workgroupsZ = Math.ceil(destinationDepth / WORKGROUP_SIZE.z);
2146
+ const computePass = device.beginComputePass({});
2147
+ computation.dispatch(computePass, workgroupsX, workgroupsY, workgroupsZ);
2148
+ computePass.end();
2149
+ device.submit();
2150
+ computation.destroy();
2151
+ sourceView.destroy();
2152
+ destinationView.destroy();
2153
+ sourceWidth = destinationWidth;
2154
+ sourceHeight = destinationHeight;
2155
+ sourceDepth = destinationDepth;
2156
+ }
2157
+ } finally {
2158
+ uniformsBuffer.destroy();
2159
+ }
2160
+ }
2161
+ function validateFormatCapabilities(device, texture, requiredCapabilities, path) {
2162
+ const { format, dimension } = texture;
2163
+ const capabilities = device.getTextureFormatCapabilities(format);
2164
+ const missingCapabilities = requiredCapabilities.filter((capability) => !capabilities[capability]);
2165
+ if (missingCapabilities.length > 0) {
2166
+ const required = requiredCapabilities.join(" + ");
2167
+ const actual = requiredCapabilities.map((capability) => `${capability}=${capabilities[capability]}`).join(", ");
2168
+ throw new Error(
2169
+ `Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Required capabilities: ${required}. Actual capabilities: ${actual}.`
2170
+ );
2171
+ }
2172
+ }
2173
+ function getSourceTextureType(dimension) {
2174
+ switch (dimension) {
2175
+ case "2d":
2176
+ return "texture_2d<f32>";
2177
+ case "2d-array":
2178
+ return "texture_2d_array<f32>";
2179
+ case "cube":
2180
+ return "texture_cube<f32>";
2181
+ case "cube-array":
2182
+ return "texture_cube_array<f32>";
2183
+ default:
2184
+ throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
2185
+ }
2186
+ }
2187
+ function getRenderMipmapWGSL(dimension) {
2188
+ const sourceSnippet = getRenderMipmapSampleSnippet(dimension);
2189
+ return `
2190
+ struct MipmapUniforms {
2191
+ sourceLayer: u32,
2192
+ };
2193
+
2194
+ fn _touchUniform(uniforms: MipmapUniforms) {
2195
+ let unusedSourceLayer = uniforms.sourceLayer;
2196
+ }
2197
+
2198
+ const faceMat = array(
2199
+ mat3x3f(
2200
+ 0.0, 0.0, -2.0,
2201
+ 0.0, -2.0, 0.0,
2202
+ 1.0, 1.0, 1.0
2203
+ ), // pos-x
2204
+ mat3x3f(
2205
+ 0.0, 0.0, 2.0,
2206
+ 0.0, -2.0, 0.0,
2207
+ -1.0, 1.0, -1.0
2208
+ ), // neg-x
2209
+ mat3x3f(
2210
+ 2.0, 0.0, 0.0,
2211
+ 0.0, 0.0, 2.0,
2212
+ -1.0, 1.0, -1.0
2213
+ ), // pos-y
2214
+ mat3x3f(
2215
+ 2.0, 0.0, 0.0,
2216
+ 0.0, 0.0, -2.0,
2217
+ -1.0, -1.0, 1.0
2218
+ ), // neg-y
2219
+ mat3x3f(
2220
+ 2.0, 0.0, 0.0,
2221
+ 0.0, -2.0, 0.0,
2222
+ -1.0, 1.0, 1.0
2223
+ ), // pos-z
2224
+ mat3x3f(
2225
+ -2.0, 0.0, 0.0,
2226
+ 0.0, -2.0, 0.0,
2227
+ 1.0, 1.0, -1.0
2228
+ ) // neg-z
2229
+ );
2230
+
2231
+ struct FragmentInputs {
2232
+ @builtin(position) position: vec4f,
2233
+ @location(0) texcoord: vec2f
2234
+ };
2235
+
2236
+ struct VertexOutput {
2237
+ @builtin(position) position: vec4f,
2238
+ @location(0) texcoord: vec2f
2239
+ };
2240
+
2241
+ @group(0) @binding(0) var sourceSampler: sampler;
2242
+ @group(0) @binding(1) var sourceTexture: ${getSourceTextureType(dimension)};
2243
+ @group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
2244
+
2245
+ @vertex
2246
+ fn vertexMain(
2247
+ @builtin(vertex_index) vertexIndex: u32
2248
+ ) -> VertexOutput {
2249
+ const positions = array(
2250
+ vec2f(-1.0, -1.0),
2251
+ vec2f(-1.0, 3.0),
2252
+ vec2f( 3.0, -1.0)
2253
+ );
2254
+
2255
+ let xy = positions[vertexIndex];
2256
+ return VertexOutput(
2257
+ vec4f(xy, 0.0, 1.0),
2258
+ xy * vec2f(0.5, -0.5) + vec2f(0.5)
2259
+ );
2260
+ }
2261
+
2262
+ @fragment
2263
+ fn fragmentMain(fsInput: VertexOutput) -> @location(0) vec4f {
2264
+ _touchUniform(uniforms);
2265
+ return ${sourceSnippet};
2266
+ }
2267
+ `;
2268
+ }
2269
+ function getRenderMipmapSampleSnippet(dimension) {
2270
+ const layer = "uniforms.sourceLayer";
2271
+ switch (dimension) {
2272
+ case "2d":
2273
+ return "textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, 0.0)";
2274
+ case "2d-array":
2275
+ return `textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, i32(${layer}), 0.0)`;
2276
+ case "cube":
2277
+ return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer})] * vec3f(fract(fsInput.texcoord), 1.0), 0.0)`;
2278
+ case "cube-array":
2279
+ return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer} % 6u)] * vec3f(fract(fsInput.texcoord), 1.0), i32(${layer} / 6u), 0.0)`;
2280
+ default:
2281
+ throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
2282
+ }
2283
+ }
2284
+ function get3DComputeMipmapWGSL(format) {
2285
+ return `
2286
+ struct MipmapUniforms {
2287
+ sourceWidth: u32,
2288
+ sourceHeight: u32,
2289
+ sourceDepth: u32,
2290
+ destinationWidth: u32,
2291
+ destinationHeight: u32,
2292
+ destinationDepth: u32,
2293
+ padding: u32,
2294
+ };
2295
+
2296
+ @group(0) @binding(0) var sourceTexture: texture_3d<f32>;
2297
+ @group(0) @binding(1) var destinationTexture: texture_storage_3d<${format}, write>;
2298
+ @group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
2299
+
2300
+ @compute @workgroup_size(${WORKGROUP_SIZE.x}, ${WORKGROUP_SIZE.y}, ${WORKGROUP_SIZE.z})
2301
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
2302
+ if (
2303
+ id.x >= uniforms.destinationWidth ||
2304
+ id.y >= uniforms.destinationHeight ||
2305
+ id.z >= uniforms.destinationDepth
2306
+ ) {
2307
+ return;
2308
+ }
2309
+
2310
+ let sourceBase = id * 2u;
2311
+ let sourceX0 = min(sourceBase.x, uniforms.sourceWidth - 1u);
2312
+ let sourceY0 = min(sourceBase.y, uniforms.sourceHeight - 1u);
2313
+ let sourceZ0 = min(sourceBase.z, uniforms.sourceDepth - 1u);
2314
+
2315
+ let sourceX1 = min(sourceBase.x + 1u, uniforms.sourceWidth - 1u);
2316
+ let sourceY1 = min(sourceBase.y + 1u, uniforms.sourceHeight - 1u);
2317
+ let sourceZ1 = min(sourceBase.z + 1u, uniforms.sourceDepth - 1u);
2318
+
2319
+ var sum = textureLoad(
2320
+ sourceTexture,
2321
+ vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ0)),
2322
+ 0
2323
+ );
2324
+ sum += textureLoad(
2325
+ sourceTexture,
2326
+ vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ0)),
2327
+ 0
2328
+ );
2329
+ sum += textureLoad(
2330
+ sourceTexture,
2331
+ vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ0)),
2332
+ 0
2333
+ );
2334
+ sum += textureLoad(
2335
+ sourceTexture,
2336
+ vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ0)),
2337
+ 0
2338
+ );
2339
+ sum += textureLoad(
2340
+ sourceTexture,
2341
+ vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ1)),
2342
+ 0
2343
+ );
2344
+ sum += textureLoad(
2345
+ sourceTexture,
2346
+ vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ1)),
2347
+ 0
2348
+ );
2349
+ sum += textureLoad(
2350
+ sourceTexture,
2351
+ vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ1)),
2352
+ 0
2353
+ );
2354
+ sum += textureLoad(
2355
+ sourceTexture,
2356
+ vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ1)),
2357
+ 0
2358
+ );
2359
+
2360
+ textureStore(
2361
+ destinationTexture,
2362
+ vec3<i32>(i32(id.x), i32(id.y), i32(id.z)),
2363
+ vec4<f32>(sum.xyz / 8.0, sum.w / 8.0)
2364
+ );
2365
+ }
2366
+ `;
2367
+ }
2368
+
1709
2369
  // src/dynamic-texture/dynamic-texture.ts
1710
2370
  var _DynamicTexture = class {
1711
2371
  device;
@@ -1783,6 +2443,10 @@ var __exports__ = (() => {
1783
2443
  // temporary; updated below
1784
2444
  data: void 0
1785
2445
  };
2446
+ if (this.device.type === "webgpu" && this.props.mipmaps) {
2447
+ const requiredUsage = this.props.dimension === "3d" ? import_core11.Texture.SAMPLE | import_core11.Texture.STORAGE | import_core11.Texture.COPY_DST | import_core11.Texture.COPY_SRC : import_core11.Texture.SAMPLE | import_core11.Texture.RENDER | import_core11.Texture.COPY_DST | import_core11.Texture.COPY_SRC;
2448
+ baseTextureProps.usage |= requiredUsage;
2449
+ }
1786
2450
  const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
1787
2451
  const desired = this.props.mipLevels === "auto" ? maxMips : Math.max(1, Math.min(maxMips, this.props.mipLevels ?? 1));
1788
2452
  const finalTextureProps = { ...baseTextureProps, mipLevels: desired };
@@ -1819,7 +2483,7 @@ var __exports__ = (() => {
1819
2483
  }
1820
2484
  this.isReady = true;
1821
2485
  this.resolveReady(this.texture);
1822
- import_core9.log.info(0, `${this} created`)();
2486
+ import_core11.log.info(0, `${this} created`)();
1823
2487
  } catch (e) {
1824
2488
  const err = e instanceof Error ? e : new Error(String(e));
1825
2489
  this.rejectReady(err);
@@ -1838,16 +2502,16 @@ var __exports__ = (() => {
1838
2502
  generateMipmaps() {
1839
2503
  if (this.device.type === "webgl") {
1840
2504
  this.texture.generateMipmapsWebGL();
2505
+ } else if (this.device.type === "webgpu") {
2506
+ generateMipmap(this.device, this.texture);
1841
2507
  } else {
1842
- import_core9.log.warn(
1843
- "Mipmap generation not yet implemented on WebGPU: your texture data will not be correctly initialized"
1844
- );
2508
+ import_core11.log.warn(`${this} mipmaps not supported on ${this.device.type}`);
1845
2509
  }
1846
2510
  }
1847
2511
  /** Set sampler or create one from props */
1848
2512
  setSampler(sampler = {}) {
1849
2513
  this._checkReady();
1850
- const s = sampler instanceof import_core9.Sampler ? sampler : this.device.createSampler(sampler);
2514
+ const s = sampler instanceof import_core11.Sampler ? sampler : this.device.createSampler(sampler);
1851
2515
  this.texture.setSampler(s);
1852
2516
  this._sampler = s;
1853
2517
  }
@@ -1865,7 +2529,7 @@ var __exports__ = (() => {
1865
2529
  this._sampler = this.texture.sampler;
1866
2530
  this._view = this.texture.view;
1867
2531
  prev.destroy();
1868
- import_core9.log.info(`${this} resized`);
2532
+ import_core11.log.info(`${this} resized`);
1869
2533
  return true;
1870
2534
  }
1871
2535
  /** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
@@ -1940,7 +2604,15 @@ var __exports__ = (() => {
1940
2604
  break;
1941
2605
  case "texture-data":
1942
2606
  const { data } = subresource;
1943
- this.texture.copyImageData({ data: data.data, z, mipLevel });
2607
+ this.texture.writeData(getAlignedUploadData(this.texture, data), {
2608
+ x: 0,
2609
+ y: 0,
2610
+ z,
2611
+ width: data.width,
2612
+ height: data.height,
2613
+ depthOrArrayLayers: 1,
2614
+ mipLevel
2615
+ });
1944
2616
  break;
1945
2617
  default:
1946
2618
  throw new Error("Unsupported 2D mip-level payload");
@@ -1956,22 +2628,46 @@ var __exports__ = (() => {
1956
2628
  }
1957
2629
  _checkNotDestroyed() {
1958
2630
  if (this.destroyed) {
1959
- import_core9.log.warn(`${this} already destroyed`);
2631
+ import_core11.log.warn(`${this} already destroyed`);
1960
2632
  }
1961
2633
  }
1962
2634
  _checkReady() {
1963
2635
  if (!this.isReady) {
1964
- import_core9.log.warn(`${this} Cannot perform this operation before ready`);
2636
+ import_core11.log.warn(`${this} Cannot perform this operation before ready`);
1965
2637
  }
1966
2638
  }
1967
2639
  };
1968
2640
  var DynamicTexture = _DynamicTexture;
1969
2641
  __publicField(DynamicTexture, "defaultProps", {
1970
- ...import_core9.Texture.defaultProps,
2642
+ ...import_core11.Texture.defaultProps,
1971
2643
  dimension: "2d",
1972
2644
  data: null,
1973
2645
  mipmaps: false
1974
2646
  });
2647
+ function getAlignedUploadData(texture, data) {
2648
+ const { width, height, data: uploadData } = data;
2649
+ const { bytesPerPixel } = texture.device.getTextureFormatInfo(texture.format);
2650
+ const bytesPerRow = width * bytesPerPixel;
2651
+ const alignedBytesPerRow = Math.ceil(bytesPerRow / texture.byteAlignment) * texture.byteAlignment;
2652
+ if (alignedBytesPerRow === bytesPerRow) {
2653
+ return uploadData;
2654
+ }
2655
+ const sourceBytes = new Uint8Array(
2656
+ uploadData.buffer,
2657
+ uploadData.byteOffset,
2658
+ uploadData.byteLength
2659
+ );
2660
+ const paddedBytes = new Uint8Array(alignedBytesPerRow * height);
2661
+ for (let row = 0; row < height; row++) {
2662
+ const sourceOffset = row * bytesPerRow;
2663
+ const destinationOffset = row * alignedBytesPerRow;
2664
+ paddedBytes.set(
2665
+ sourceBytes.subarray(sourceOffset, sourceOffset + bytesPerRow),
2666
+ destinationOffset
2667
+ );
2668
+ }
2669
+ return paddedBytes;
2670
+ }
1975
2671
  async function awaitAllPromises(x) {
1976
2672
  x = await x;
1977
2673
  if (Array.isArray(x)) {
@@ -1991,8 +2687,8 @@ var __exports__ = (() => {
1991
2687
  }
1992
2688
 
1993
2689
  // src/model/model.ts
1994
- var LOG_DRAW_PRIORITY = 2;
1995
- var LOG_DRAW_TIMEOUT = 1e4;
2690
+ var LOG_DRAW_PRIORITY2 = 2;
2691
+ var LOG_DRAW_TIMEOUT2 = 1e4;
1996
2692
  var _Model = class {
1997
2693
  /** Device that created this model */
1998
2694
  device;
@@ -2075,7 +2771,7 @@ var __exports__ = (() => {
2075
2771
  );
2076
2772
  const shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap, { disableWarnings: this.props.disableWarnings });
2077
2773
  this.setShaderInputs(shaderInputs);
2078
- const platformInfo = getPlatformInfo(device);
2774
+ const platformInfo = getPlatformInfo2(device);
2079
2775
  const modules = (
2080
2776
  // @ts-ignore shaderInputs is assigned in setShaderInputs above.
2081
2777
  (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || []
@@ -2182,7 +2878,7 @@ var __exports__ = (() => {
2182
2878
  draw(renderPass) {
2183
2879
  const loadingBinding = this._areBindingsLoading();
2184
2880
  if (loadingBinding) {
2185
- import_core10.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
2881
+ import_core12.log.info(LOG_DRAW_PRIORITY2, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
2186
2882
  return false;
2187
2883
  }
2188
2884
  try {
@@ -2312,7 +3008,7 @@ var __exports__ = (() => {
2312
3008
  /** Set the shader inputs */
2313
3009
  setShaderInputs(shaderInputs) {
2314
3010
  this.shaderInputs = shaderInputs;
2315
- this._uniformStore = new import_core10.UniformStore(this.shaderInputs.modules);
3011
+ this._uniformStore = new import_core12.UniformStore(this.shaderInputs.modules);
2316
3012
  for (const [moduleName, module] of Object.entries(this.shaderInputs.modules)) {
2317
3013
  if (shaderModuleHasUniforms(module)) {
2318
3014
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
@@ -2356,7 +3052,7 @@ var __exports__ = (() => {
2356
3052
  setAttributes(buffers, options) {
2357
3053
  const disableWarnings = options?.disableWarnings ?? this.props.disableWarnings;
2358
3054
  if (buffers["indices"]) {
2359
- import_core10.log.warn(
3055
+ import_core12.log.warn(
2360
3056
  `Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`
2361
3057
  )();
2362
3058
  }
@@ -2369,7 +3065,7 @@ var __exports__ = (() => {
2369
3065
  const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
2370
3066
  if (!bufferLayout) {
2371
3067
  if (!disableWarnings) {
2372
- import_core10.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
3068
+ import_core12.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2373
3069
  }
2374
3070
  continue;
2375
3071
  }
@@ -2384,7 +3080,7 @@ var __exports__ = (() => {
2384
3080
  }
2385
3081
  }
2386
3082
  if (!set && !disableWarnings) {
2387
- import_core10.log.warn(
3083
+ import_core12.log.warn(
2388
3084
  `Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`
2389
3085
  )();
2390
3086
  }
@@ -2405,7 +3101,7 @@ var __exports__ = (() => {
2405
3101
  if (attributeInfo) {
2406
3102
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
2407
3103
  } else if (!(options?.disableWarnings ?? this.props.disableWarnings)) {
2408
- import_core10.log.warn(
3104
+ import_core12.log.warn(
2409
3105
  `Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`
2410
3106
  )();
2411
3107
  }
@@ -2440,16 +3136,16 @@ var __exports__ = (() => {
2440
3136
  _getBindingsUpdateTimestamp() {
2441
3137
  let timestamp = 0;
2442
3138
  for (const binding of Object.values(this.bindings)) {
2443
- if (binding instanceof import_core10.TextureView) {
3139
+ if (binding instanceof import_core12.TextureView) {
2444
3140
  timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
2445
- } else if (binding instanceof import_core10.Buffer || binding instanceof import_core10.Texture) {
3141
+ } else if (binding instanceof import_core12.Buffer || binding instanceof import_core12.Texture) {
2446
3142
  timestamp = Math.max(timestamp, binding.updateTimestamp);
2447
3143
  } else if (binding instanceof DynamicTexture) {
2448
3144
  timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
2449
3145
  // The texture will become available in the future
2450
3146
  Infinity
2451
3147
  );
2452
- } else if (!(binding instanceof import_core10.Sampler)) {
3148
+ } else if (!(binding instanceof import_core12.Sampler)) {
2453
3149
  timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
2454
3150
  }
2455
3151
  }
@@ -2484,7 +3180,7 @@ var __exports__ = (() => {
2484
3180
  let prevShaderVs = null;
2485
3181
  let prevShaderFs = null;
2486
3182
  if (this.pipeline) {
2487
- import_core10.log.log(
3183
+ import_core12.log.log(
2488
3184
  1,
2489
3185
  `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
2490
3186
  )();
@@ -2520,7 +3216,7 @@ var __exports__ = (() => {
2520
3216
  vs: vs3,
2521
3217
  fs: fs3
2522
3218
  });
2523
- this._attributeInfos = (0, import_core10.getAttributeInfosFromLayouts)(
3219
+ this._attributeInfos = (0, import_core12.getAttributeInfosFromLayouts)(
2524
3220
  this.pipeline.shaderLayout,
2525
3221
  this.bufferLayout
2526
3222
  );
@@ -2535,24 +3231,24 @@ var __exports__ = (() => {
2535
3231
  _lastLogTime = 0;
2536
3232
  _logOpen = false;
2537
3233
  _logDrawCallStart() {
2538
- const logDrawTimeout = import_core10.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2539
- if (import_core10.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
3234
+ const logDrawTimeout = import_core12.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
3235
+ if (import_core12.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2540
3236
  return;
2541
3237
  }
2542
3238
  this._lastLogTime = Date.now();
2543
3239
  this._logOpen = true;
2544
- import_core10.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core10.log.level <= 2 })();
3240
+ import_core12.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core12.log.level <= 2 })();
2545
3241
  }
2546
3242
  _logDrawCallEnd() {
2547
3243
  if (this._logOpen) {
2548
3244
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
2549
- import_core10.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
3245
+ import_core12.log.table(LOG_DRAW_PRIORITY2, shaderLayoutTable)();
2550
3246
  const uniformTable = this.shaderInputs.getDebugTable();
2551
- import_core10.log.table(LOG_DRAW_PRIORITY, uniformTable)();
3247
+ import_core12.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
2552
3248
  const attributeTable = this._getAttributeDebugTable();
2553
- import_core10.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2554
- import_core10.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2555
- import_core10.log.groupEnd(LOG_DRAW_PRIORITY)();
3249
+ import_core12.log.table(LOG_DRAW_PRIORITY2, this._attributeInfos)();
3250
+ import_core12.log.table(LOG_DRAW_PRIORITY2, attributeTable)();
3251
+ import_core12.log.groupEnd(LOG_DRAW_PRIORITY2)();
2556
3252
  this._logOpen = false;
2557
3253
  }
2558
3254
  }
@@ -2591,14 +3287,14 @@ var __exports__ = (() => {
2591
3287
  }
2592
3288
  // TODO - fix typing of luma data types
2593
3289
  _getBufferOrConstantValues(attribute, dataType) {
2594
- const TypedArrayConstructor = (0, import_core10.getTypedArrayConstructor)(dataType);
2595
- const typedArray = attribute instanceof import_core10.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
3290
+ const TypedArrayConstructor = (0, import_core12.getTypedArrayConstructor)(dataType);
3291
+ const typedArray = attribute instanceof import_core12.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2596
3292
  return typedArray.toString();
2597
3293
  }
2598
3294
  };
2599
3295
  var Model = _Model;
2600
3296
  __publicField(Model, "defaultProps", {
2601
- ...import_core10.RenderPipeline.defaultProps,
3297
+ ...import_core12.RenderPipeline.defaultProps,
2602
3298
  source: void 0,
2603
3299
  vs: null,
2604
3300
  fs: null,
@@ -2619,14 +3315,14 @@ var __exports__ = (() => {
2619
3315
  pipelineFactory: void 0,
2620
3316
  shaderFactory: void 0,
2621
3317
  transformFeedback: void 0,
2622
- shaderAssembler: import_shadertools2.ShaderAssembler.getDefaultShaderAssembler(),
3318
+ shaderAssembler: import_shadertools3.ShaderAssembler.getDefaultShaderAssembler(),
2623
3319
  debugShaders: void 0,
2624
3320
  disableWarnings: void 0
2625
3321
  });
2626
3322
  function shaderModuleHasUniforms(module) {
2627
3323
  return Boolean(module.uniformTypes && !isObjectEmpty(module.uniformTypes));
2628
3324
  }
2629
- function getPlatformInfo(device) {
3325
+ function getPlatformInfo2(device) {
2630
3326
  return {
2631
3327
  type: device.type,
2632
3328
  shaderLanguage: device.info.shadingLanguage,
@@ -2644,8 +3340,8 @@ var __exports__ = (() => {
2644
3340
  }
2645
3341
 
2646
3342
  // src/compute/buffer-transform.ts
2647
- var import_core11 = __toESM(require_core(), 1);
2648
- var import_shadertools3 = __toESM(require_shadertools(), 1);
3343
+ var import_core13 = __toESM(require_core(), 1);
3344
+ var import_shadertools4 = __toESM(require_shadertools(), 1);
2649
3345
  var _BufferTransform = class {
2650
3346
  device;
2651
3347
  model;
@@ -2660,7 +3356,7 @@ var __exports__ = (() => {
2660
3356
  this.device = device;
2661
3357
  this.model = new Model(this.device, {
2662
3358
  id: props.id || "buffer-transform-model",
2663
- fs: props.fs || (0, import_shadertools3.getPassthroughFS)(),
3359
+ fs: props.fs || (0, import_shadertools4.getPassthroughFS)(),
2664
3360
  topology: props.topology || "point-list",
2665
3361
  varyings: props.outputs || props.varyings,
2666
3362
  ...props
@@ -2706,7 +3402,7 @@ var __exports__ = (() => {
2706
3402
  if (!result) {
2707
3403
  throw new Error("BufferTransform#getBuffer");
2708
3404
  }
2709
- if (result instanceof import_core11.Buffer) {
3405
+ if (result instanceof import_core13.Buffer) {
2710
3406
  return result.readAsync();
2711
3407
  }
2712
3408
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
@@ -2721,7 +3417,7 @@ var __exports__ = (() => {
2721
3417
  });
2722
3418
 
2723
3419
  // src/compute/texture-transform.ts
2724
- var import_shadertools4 = __toESM(require_shadertools(), 1);
3420
+ var import_shadertools5 = __toESM(require_shadertools(), 1);
2725
3421
  var FS_OUTPUT_VARIABLE = "transform_output";
2726
3422
  var TextureTransform = class {
2727
3423
  device;
@@ -2744,7 +3440,7 @@ var __exports__ = (() => {
2744
3440
  });
2745
3441
  this.model = new Model(this.device, {
2746
3442
  id: props.id || uid("texture-transform-model"),
2747
- fs: props.fs || (0, import_shadertools4.getPassthroughFS)({
3443
+ fs: props.fs || (0, import_shadertools5.getPassthroughFS)({
2748
3444
  input: props.targetTextureVarying,
2749
3445
  inputChannels: props.targetTextureChannels,
2750
3446
  output: FS_OUTPUT_VARIABLE
@@ -5283,13 +5979,13 @@ void main(void) {
5283
5979
  };
5284
5980
 
5285
5981
  // src/scenegraph/group-node.ts
5286
- var import_core14 = __toESM(require_core(), 1);
5982
+ var import_core16 = __toESM(require_core(), 1);
5287
5983
  var GroupNode = class extends ScenegraphNode {
5288
5984
  children;
5289
5985
  constructor(props = {}) {
5290
5986
  props = Array.isArray(props) ? { children: props } : props;
5291
5987
  const { children = [] } = props;
5292
- import_core14.log.assert(
5988
+ import_core16.log.assert(
5293
5989
  children.every((child) => child instanceof ScenegraphNode),
5294
5990
  "every child must an instance of ScenegraphNode"
5295
5991
  );
@@ -6530,10 +7226,10 @@ void main(void) {
6530
7226
  }
6531
7227
 
6532
7228
  // src/passes/shader-pass-renderer.ts
6533
- var import_shadertools5 = __toESM(require_shadertools(), 1);
7229
+ var import_shadertools6 = __toESM(require_shadertools(), 1);
6534
7230
 
6535
7231
  // src/compute/swap.ts
6536
- var import_core16 = __toESM(require_core(), 1);
7232
+ var import_core18 = __toESM(require_core(), 1);
6537
7233
  var Swap = class {
6538
7234
  id;
6539
7235
  /** The current resource - usually the source for renders or computations */
@@ -6565,7 +7261,7 @@ void main(void) {
6565
7261
  (colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
6566
7262
  id: `${props.id}-texture-0`,
6567
7263
  format: colorAttachment,
6568
- usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
7264
+ usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
6569
7265
  width,
6570
7266
  height
6571
7267
  })
@@ -6575,7 +7271,7 @@ void main(void) {
6575
7271
  (colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
6576
7272
  id: `${props.id}-texture-1`,
6577
7273
  format: colorAttachment,
6578
- usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
7274
+ usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
6579
7275
  width,
6580
7276
  height
6581
7277
  })
@@ -6747,7 +7443,7 @@ void main() {
6747
7443
  textureModel;
6748
7444
  constructor(device, props) {
6749
7445
  this.device = device;
6750
- props.shaderPasses.map((shaderPass) => (0, import_shadertools5.initializeShaderModule)(shaderPass));
7446
+ props.shaderPasses.map((shaderPass) => (0, import_shadertools6.initializeShaderModule)(shaderPass));
6751
7447
  const modules = props.shaderPasses.reduce(
6752
7448
  (object, shaderPass) => ({ ...object, [shaderPass.name]: shaderPass }),
6753
7449
  {}
@@ -6922,221 +7618,6 @@ void main() {
6922
7618
  }
6923
7619
  };
6924
7620
 
6925
- // src/compute/computation.ts
6926
- var import_core17 = __toESM(require_core(), 1);
6927
- var import_shadertools6 = __toESM(require_shadertools(), 1);
6928
- var LOG_DRAW_PRIORITY2 = 2;
6929
- var LOG_DRAW_TIMEOUT2 = 1e4;
6930
- var _Computation = class {
6931
- device;
6932
- id;
6933
- pipelineFactory;
6934
- shaderFactory;
6935
- userData = {};
6936
- /** Bindings (textures, samplers, uniform buffers) */
6937
- bindings = {};
6938
- /** The underlying GPU pipeline. */
6939
- pipeline;
6940
- /** Assembled compute shader source */
6941
- source;
6942
- /** the underlying compiled compute shader */
6943
- // @ts-ignore Set in function called from constructor
6944
- shader;
6945
- /** ShaderInputs instance */
6946
- shaderInputs;
6947
- // @ts-ignore Set in function called from constructor
6948
- _uniformStore;
6949
- _pipelineNeedsUpdate = "newly created";
6950
- _getModuleUniforms;
6951
- props;
6952
- _destroyed = false;
6953
- constructor(device, props) {
6954
- if (device.type !== "webgpu") {
6955
- throw new Error("Computation is only supported in WebGPU");
6956
- }
6957
- this.props = { ..._Computation.defaultProps, ...props };
6958
- props = this.props;
6959
- this.id = props.id || uid("model");
6960
- this.device = device;
6961
- Object.assign(this.userData, props.userData);
6962
- const moduleMap = Object.fromEntries(
6963
- this.props.modules?.map((module) => [module.name, module]) || []
6964
- );
6965
- this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
6966
- this.setShaderInputs(this.shaderInputs);
6967
- this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
6968
- const platformInfo = getPlatformInfo2(device);
6969
- const modules = (this.props.modules?.length > 0 ? this.props.modules : this.shaderInputs?.getModules()) || [];
6970
- this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
6971
- this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
6972
- const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
6973
- platformInfo,
6974
- ...this.props,
6975
- modules
6976
- });
6977
- this.source = source3;
6978
- this._getModuleUniforms = getUniforms2;
6979
- this.pipeline = this._updatePipeline();
6980
- if (props.bindings) {
6981
- this.setBindings(props.bindings);
6982
- }
6983
- Object.seal(this);
6984
- }
6985
- destroy() {
6986
- if (this._destroyed)
6987
- return;
6988
- this.pipelineFactory.release(this.pipeline);
6989
- this.shaderFactory.release(this.shader);
6990
- this._uniformStore.destroy();
6991
- this._destroyed = true;
6992
- }
6993
- // Draw call
6994
- predraw() {
6995
- this.updateShaderInputs();
6996
- }
6997
- dispatch(computePass, x, y, z) {
6998
- try {
6999
- this._logDrawCallStart();
7000
- this.pipeline = this._updatePipeline();
7001
- this.pipeline.setBindings(this.bindings);
7002
- computePass.setPipeline(this.pipeline);
7003
- computePass.setBindings([]);
7004
- computePass.dispatch(x, y, z);
7005
- } finally {
7006
- this._logDrawCallEnd();
7007
- }
7008
- }
7009
- // Update fixed fields (can trigger pipeline rebuild)
7010
- // Update dynamic fields
7011
- /**
7012
- * Updates the vertex count (used in draw calls)
7013
- * @note Any attributes with stepMode=vertex need to be at least this big
7014
- */
7015
- setVertexCount(vertexCount) {
7016
- }
7017
- /**
7018
- * Updates the instance count (used in draw calls)
7019
- * @note Any attributes with stepMode=instance need to be at least this big
7020
- */
7021
- setInstanceCount(instanceCount) {
7022
- }
7023
- setShaderInputs(shaderInputs) {
7024
- this.shaderInputs = shaderInputs;
7025
- this._uniformStore = new import_core17.UniformStore(this.shaderInputs.modules);
7026
- for (const moduleName of Object.keys(this.shaderInputs.modules)) {
7027
- const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
7028
- this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
7029
- }
7030
- }
7031
- /**
7032
- * Updates shader module settings (which results in uniforms being set)
7033
- */
7034
- setShaderModuleProps(props) {
7035
- const uniforms = this._getModuleUniforms(props);
7036
- const keys = Object.keys(uniforms).filter((k) => {
7037
- const uniform = uniforms[k];
7038
- return !isNumericArray(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
7039
- });
7040
- const bindings = {};
7041
- for (const k of keys) {
7042
- bindings[k] = uniforms[k];
7043
- delete uniforms[k];
7044
- }
7045
- }
7046
- updateShaderInputs() {
7047
- this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
7048
- }
7049
- /**
7050
- * Sets bindings (textures, samplers, uniform buffers)
7051
- */
7052
- setBindings(bindings) {
7053
- Object.assign(this.bindings, bindings);
7054
- }
7055
- _setPipelineNeedsUpdate(reason) {
7056
- this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
7057
- }
7058
- _updatePipeline() {
7059
- if (this._pipelineNeedsUpdate) {
7060
- let prevShader = null;
7061
- if (this.pipeline) {
7062
- import_core17.log.log(
7063
- 1,
7064
- `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`
7065
- )();
7066
- prevShader = this.shader;
7067
- }
7068
- this._pipelineNeedsUpdate = false;
7069
- this.shader = this.shaderFactory.createShader({
7070
- id: `${this.id}-fragment`,
7071
- stage: "compute",
7072
- source: this.source,
7073
- debugShaders: this.props.debugShaders
7074
- });
7075
- this.pipeline = this.pipelineFactory.createComputePipeline({
7076
- ...this.props,
7077
- shader: this.shader
7078
- });
7079
- if (prevShader) {
7080
- this.shaderFactory.release(prevShader);
7081
- }
7082
- }
7083
- return this.pipeline;
7084
- }
7085
- /** Throttle draw call logging */
7086
- _lastLogTime = 0;
7087
- _logOpen = false;
7088
- _logDrawCallStart() {
7089
- const logDrawTimeout = import_core17.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
7090
- if (import_core17.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
7091
- return;
7092
- }
7093
- this._lastLogTime = Date.now();
7094
- this._logOpen = true;
7095
- import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
7096
- }
7097
- _logDrawCallEnd() {
7098
- if (this._logOpen) {
7099
- const uniformTable = this.shaderInputs.getDebugTable();
7100
- import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
7101
- import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
7102
- this._logOpen = false;
7103
- }
7104
- }
7105
- _drawCount = 0;
7106
- // TODO - fix typing of luma data types
7107
- _getBufferOrConstantValues(attribute, dataType) {
7108
- const TypedArrayConstructor = (0, import_core17.getTypedArrayConstructor)(dataType);
7109
- const typedArray = attribute instanceof import_core17.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
7110
- return typedArray.toString();
7111
- }
7112
- };
7113
- var Computation = _Computation;
7114
- __publicField(Computation, "defaultProps", {
7115
- ...import_core17.ComputePipeline.defaultProps,
7116
- id: "unnamed",
7117
- handle: void 0,
7118
- userData: {},
7119
- source: "",
7120
- modules: [],
7121
- defines: {},
7122
- bindings: void 0,
7123
- shaderInputs: void 0,
7124
- pipelineFactory: void 0,
7125
- shaderFactory: void 0,
7126
- shaderAssembler: import_shadertools6.ShaderAssembler.getDefaultShaderAssembler(),
7127
- debugShaders: void 0
7128
- });
7129
- function getPlatformInfo2(device) {
7130
- return {
7131
- type: device.type,
7132
- shaderLanguage: device.info.shadingLanguage,
7133
- shaderLanguageVersion: device.info.shadingLanguageVersion,
7134
- gpu: device.info.gpu,
7135
- // HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
7136
- features: device.features
7137
- };
7138
- }
7139
-
7140
7621
  // src/modules/picking/picking-uniforms.ts
7141
7622
  var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
7142
7623
  var INVALID_INDEX = -1;