@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/index.cjs CHANGED
@@ -677,8 +677,8 @@ function clearError(device) {
677
677
  }
678
678
 
679
679
  // dist/model/model.js
680
- var import_core10 = require("@luma.gl/core");
681
- var import_shadertools2 = require("@luma.gl/shadertools");
680
+ var import_core12 = require("@luma.gl/core");
681
+ var import_shadertools3 = require("@luma.gl/shadertools");
682
682
 
683
683
  // dist/geometry/gpu-geometry.js
684
684
  var import_core3 = require("@luma.gl/core");
@@ -1175,14 +1175,24 @@ var BufferLayoutHelper = class {
1175
1175
  };
1176
1176
 
1177
1177
  // dist/utils/buffer-layout-order.js
1178
+ function getMinLocation(attributeNames, shaderLayoutMap) {
1179
+ let minLocation = Infinity;
1180
+ for (const name of attributeNames) {
1181
+ const location = shaderLayoutMap[name];
1182
+ if (location !== void 0) {
1183
+ minLocation = Math.min(minLocation, location);
1184
+ }
1185
+ }
1186
+ return minLocation;
1187
+ }
1178
1188
  function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
1179
1189
  const shaderLayoutMap = Object.fromEntries(shaderLayout.attributes.map((attr) => [attr.name, attr.location]));
1180
1190
  const sortedLayout = bufferLayout.slice();
1181
1191
  sortedLayout.sort((a, b) => {
1182
1192
  const attributeNamesA = a.attributes ? a.attributes.map((attr) => attr.attribute) : [a.name];
1183
1193
  const attributeNamesB = b.attributes ? b.attributes.map((attr) => attr.attribute) : [b.name];
1184
- const minLocationA = Math.min(...attributeNamesA.map((name) => shaderLayoutMap[name]));
1185
- const minLocationB = Math.min(...attributeNamesB.map((name) => shaderLayoutMap[name]));
1194
+ const minLocationA = getMinLocation(attributeNamesA, shaderLayoutMap);
1195
+ const minLocationB = getMinLocation(attributeNamesB, shaderLayoutMap);
1186
1196
  return minLocationA - minLocationB;
1187
1197
  });
1188
1198
  return sortedLayout;
@@ -1316,7 +1326,7 @@ var ShaderInputs = class {
1316
1326
  };
1317
1327
 
1318
1328
  // dist/dynamic-texture/dynamic-texture.js
1319
- var import_core9 = require("@luma.gl/core");
1329
+ var import_core11 = require("@luma.gl/core");
1320
1330
 
1321
1331
  // dist/dynamic-texture/texture-data.js
1322
1332
  var import_core8 = require("@luma.gl/core");
@@ -1437,25 +1447,660 @@ function getTextureArraySubresources(data) {
1437
1447
  for (let layer = 0; layer < data.length; layer++) {
1438
1448
  subresources.push(...getTexture2DSubresources(layer, data[layer]));
1439
1449
  }
1440
- return subresources;
1450
+ return subresources;
1451
+ }
1452
+ function getTextureCubeSubresources(data) {
1453
+ const subresources = [];
1454
+ for (const [face, faceData] of Object.entries(data)) {
1455
+ const faceDepth = getCubeFaceIndex(face);
1456
+ subresources.push(...getTexture2DSubresources(faceDepth, faceData));
1457
+ }
1458
+ return subresources;
1459
+ }
1460
+ function getTextureCubeArraySubresources(data) {
1461
+ const subresources = [];
1462
+ data.forEach((cubeData, cubeIndex) => {
1463
+ for (const [face, faceData] of Object.entries(cubeData)) {
1464
+ const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
1465
+ subresources.push(...getTexture2DSubresources(faceDepth, faceData));
1466
+ }
1467
+ });
1468
+ return subresources;
1469
+ }
1470
+
1471
+ // dist/dynamic-texture/mipmaps.js
1472
+ var import_core10 = require("@luma.gl/core");
1473
+
1474
+ // dist/compute/computation.js
1475
+ var import_core9 = require("@luma.gl/core");
1476
+ var import_shadertools2 = require("@luma.gl/shadertools");
1477
+ var import_types2 = require("@math.gl/types");
1478
+ var LOG_DRAW_PRIORITY = 2;
1479
+ var LOG_DRAW_TIMEOUT = 1e4;
1480
+ var _Computation = class {
1481
+ device;
1482
+ id;
1483
+ pipelineFactory;
1484
+ shaderFactory;
1485
+ userData = {};
1486
+ /** Bindings (textures, samplers, uniform buffers) */
1487
+ bindings = {};
1488
+ /** The underlying GPU pipeline. */
1489
+ pipeline;
1490
+ /** Assembled compute shader source */
1491
+ source;
1492
+ /** the underlying compiled compute shader */
1493
+ // @ts-ignore Set in function called from constructor
1494
+ shader;
1495
+ /** ShaderInputs instance */
1496
+ shaderInputs;
1497
+ // @ts-ignore Set in function called from constructor
1498
+ _uniformStore;
1499
+ _pipelineNeedsUpdate = "newly created";
1500
+ _getModuleUniforms;
1501
+ props;
1502
+ _destroyed = false;
1503
+ constructor(device, props) {
1504
+ var _a, _b, _c;
1505
+ if (device.type !== "webgpu") {
1506
+ throw new Error("Computation is only supported in WebGPU");
1507
+ }
1508
+ this.props = { ..._Computation.defaultProps, ...props };
1509
+ props = this.props;
1510
+ this.id = props.id || uid("model");
1511
+ this.device = device;
1512
+ Object.assign(this.userData, props.userData);
1513
+ const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
1514
+ this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
1515
+ this.setShaderInputs(this.shaderInputs);
1516
+ this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
1517
+ const platformInfo = getPlatformInfo(device);
1518
+ const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
1519
+ this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
1520
+ this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
1521
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
1522
+ platformInfo,
1523
+ ...this.props,
1524
+ modules
1525
+ });
1526
+ this.source = source3;
1527
+ this._getModuleUniforms = getUniforms2;
1528
+ this.pipeline = this._updatePipeline();
1529
+ if (props.bindings) {
1530
+ this.setBindings(props.bindings);
1531
+ }
1532
+ Object.seal(this);
1533
+ }
1534
+ destroy() {
1535
+ if (this._destroyed)
1536
+ return;
1537
+ this.pipelineFactory.release(this.pipeline);
1538
+ this.shaderFactory.release(this.shader);
1539
+ this._uniformStore.destroy();
1540
+ this._destroyed = true;
1541
+ }
1542
+ // Draw call
1543
+ predraw() {
1544
+ this.updateShaderInputs();
1545
+ }
1546
+ dispatch(computePass, x, y, z) {
1547
+ try {
1548
+ this._logDrawCallStart();
1549
+ this.pipeline = this._updatePipeline();
1550
+ this.pipeline.setBindings(this.bindings);
1551
+ computePass.setPipeline(this.pipeline);
1552
+ computePass.setBindings([]);
1553
+ computePass.dispatch(x, y, z);
1554
+ } finally {
1555
+ this._logDrawCallEnd();
1556
+ }
1557
+ }
1558
+ // Update fixed fields (can trigger pipeline rebuild)
1559
+ // Update dynamic fields
1560
+ /**
1561
+ * Updates the vertex count (used in draw calls)
1562
+ * @note Any attributes with stepMode=vertex need to be at least this big
1563
+ */
1564
+ setVertexCount(vertexCount) {
1565
+ }
1566
+ /**
1567
+ * Updates the instance count (used in draw calls)
1568
+ * @note Any attributes with stepMode=instance need to be at least this big
1569
+ */
1570
+ setInstanceCount(instanceCount) {
1571
+ }
1572
+ setShaderInputs(shaderInputs) {
1573
+ this.shaderInputs = shaderInputs;
1574
+ this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
1575
+ for (const moduleName of Object.keys(this.shaderInputs.modules)) {
1576
+ const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
1577
+ this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
1578
+ }
1579
+ }
1580
+ /**
1581
+ * Updates shader module settings (which results in uniforms being set)
1582
+ */
1583
+ setShaderModuleProps(props) {
1584
+ const uniforms = this._getModuleUniforms(props);
1585
+ const keys = Object.keys(uniforms).filter((k) => {
1586
+ const uniform = uniforms[k];
1587
+ return !(0, import_types2.isNumericArray)(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
1588
+ });
1589
+ const bindings = {};
1590
+ for (const k of keys) {
1591
+ bindings[k] = uniforms[k];
1592
+ delete uniforms[k];
1593
+ }
1594
+ }
1595
+ updateShaderInputs() {
1596
+ this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
1597
+ }
1598
+ /**
1599
+ * Sets bindings (textures, samplers, uniform buffers)
1600
+ */
1601
+ setBindings(bindings) {
1602
+ Object.assign(this.bindings, bindings);
1603
+ }
1604
+ _setPipelineNeedsUpdate(reason) {
1605
+ this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
1606
+ }
1607
+ _updatePipeline() {
1608
+ if (this._pipelineNeedsUpdate) {
1609
+ let prevShader = null;
1610
+ if (this.pipeline) {
1611
+ import_core9.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1612
+ prevShader = this.shader;
1613
+ }
1614
+ this._pipelineNeedsUpdate = false;
1615
+ this.shader = this.shaderFactory.createShader({
1616
+ id: `${this.id}-fragment`,
1617
+ stage: "compute",
1618
+ source: this.source,
1619
+ debugShaders: this.props.debugShaders
1620
+ });
1621
+ this.pipeline = this.pipelineFactory.createComputePipeline({
1622
+ ...this.props,
1623
+ shader: this.shader
1624
+ });
1625
+ if (prevShader) {
1626
+ this.shaderFactory.release(prevShader);
1627
+ }
1628
+ }
1629
+ return this.pipeline;
1630
+ }
1631
+ /** Throttle draw call logging */
1632
+ _lastLogTime = 0;
1633
+ _logOpen = false;
1634
+ _logDrawCallStart() {
1635
+ const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
1636
+ if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
1637
+ return;
1638
+ }
1639
+ this._lastLogTime = Date.now();
1640
+ this._logOpen = true;
1641
+ import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
1642
+ }
1643
+ _logDrawCallEnd() {
1644
+ if (this._logOpen) {
1645
+ const uniformTable = this.shaderInputs.getDebugTable();
1646
+ import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1647
+ import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
1648
+ this._logOpen = false;
1649
+ }
1650
+ }
1651
+ _drawCount = 0;
1652
+ // TODO - fix typing of luma data types
1653
+ _getBufferOrConstantValues(attribute, dataType) {
1654
+ const TypedArrayConstructor = (0, import_core9.getTypedArrayConstructor)(dataType);
1655
+ const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
1656
+ return typedArray.toString();
1657
+ }
1658
+ };
1659
+ var Computation = _Computation;
1660
+ __publicField(Computation, "defaultProps", {
1661
+ ...import_core9.ComputePipeline.defaultProps,
1662
+ id: "unnamed",
1663
+ handle: void 0,
1664
+ userData: {},
1665
+ source: "",
1666
+ modules: [],
1667
+ defines: {},
1668
+ bindings: void 0,
1669
+ shaderInputs: void 0,
1670
+ pipelineFactory: void 0,
1671
+ shaderFactory: void 0,
1672
+ shaderAssembler: import_shadertools2.ShaderAssembler.getDefaultShaderAssembler(),
1673
+ debugShaders: void 0
1674
+ });
1675
+ function getPlatformInfo(device) {
1676
+ return {
1677
+ type: device.type,
1678
+ shaderLanguage: device.info.shadingLanguage,
1679
+ shaderLanguageVersion: device.info.shadingLanguageVersion,
1680
+ gpu: device.info.gpu,
1681
+ // HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
1682
+ features: device.features
1683
+ };
1684
+ }
1685
+
1686
+ // dist/dynamic-texture/mipmaps.js
1687
+ var RENDER_DIMENSIONS = [
1688
+ "2d",
1689
+ "2d-array",
1690
+ "cube",
1691
+ "cube-array"
1692
+ ];
1693
+ var WORKGROUP_SIZE = {
1694
+ x: 4,
1695
+ y: 4,
1696
+ z: 4
1697
+ };
1698
+ function generateMipmap(device, texture) {
1699
+ if (texture.mipLevels <= 1) {
1700
+ return;
1701
+ }
1702
+ if (device.type !== "webgpu") {
1703
+ throw new Error(`Cannot generate mipmaps on device type "${device.type}". Use generateMipmapsWebGL for WebGL devices.`);
1704
+ }
1705
+ if (texture.dimension === "3d") {
1706
+ generateMipmaps3D(device, texture);
1707
+ return;
1708
+ }
1709
+ if (RENDER_DIMENSIONS.includes(texture.dimension)) {
1710
+ generateMipmapsRender(device, texture);
1711
+ return;
1712
+ }
1713
+ throw new Error(`Cannot generate mipmaps for texture dimension "${texture.dimension}" with WebGPU.`);
1714
+ }
1715
+ function generateMipmapsRender(device, texture) {
1716
+ validateFormatCapabilities(device, texture, ["render", "filter"], "render");
1717
+ const colorAttachmentFormat = getColorAttachmentFormat(texture.format, "render", texture.dimension);
1718
+ const viewDimension = texture.dimension;
1719
+ const shader = getRenderMipmapWGSL(viewDimension);
1720
+ const sampler = device.createSampler({ minFilter: "linear", magFilter: "linear" });
1721
+ const uniformValues = new Uint32Array(1);
1722
+ const uniformsBuffer = device.createBuffer({
1723
+ byteLength: 16,
1724
+ usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
1725
+ });
1726
+ const model = new Model(device, {
1727
+ source: shader,
1728
+ colorAttachmentFormats: [colorAttachmentFormat],
1729
+ topology: "triangle-list",
1730
+ vertexCount: 3,
1731
+ shaderLayout: {
1732
+ attributes: [],
1733
+ bindings: [
1734
+ { type: "sampler", name: "sourceSampler", group: 0, location: 0 },
1735
+ {
1736
+ type: "texture",
1737
+ name: "sourceTexture",
1738
+ group: 0,
1739
+ location: 1,
1740
+ viewDimension,
1741
+ sampleType: "float"
1742
+ },
1743
+ { type: "uniform", name: "uniforms", group: 0, location: 2 }
1744
+ ]
1745
+ },
1746
+ bindings: {
1747
+ sourceSampler: sampler,
1748
+ sourceTexture: texture,
1749
+ uniforms: uniformsBuffer
1750
+ }
1751
+ });
1752
+ let sourceWidth = texture.width;
1753
+ let sourceHeight = texture.height;
1754
+ const layerCount = texture.dimension === "2d" ? 1 : texture.depth;
1755
+ try {
1756
+ for (let baseMipLevel = 1; baseMipLevel < texture.mipLevels; ++baseMipLevel) {
1757
+ validateFormatCapabilities(device, texture, ["render", "filter"], "render");
1758
+ const sourceMipLevel = baseMipLevel - 1;
1759
+ const destinationWidth = Math.max(1, sourceWidth >> 1);
1760
+ const destinationHeight = Math.max(1, sourceHeight >> 1);
1761
+ const sourceView = texture.createView({
1762
+ dimension: viewDimension,
1763
+ baseMipLevel: sourceMipLevel,
1764
+ mipLevelCount: 1,
1765
+ baseArrayLayer: 0,
1766
+ arrayLayerCount: texture.depth
1767
+ });
1768
+ model.setBindings({ sourceTexture: sourceView });
1769
+ for (let baseArrayLayer = 0; baseArrayLayer < layerCount; ++baseArrayLayer) {
1770
+ uniformValues[0] = baseArrayLayer;
1771
+ uniformsBuffer.write(uniformValues);
1772
+ const destinationView = texture.createView({
1773
+ dimension: "2d",
1774
+ baseMipLevel,
1775
+ mipLevelCount: 1,
1776
+ baseArrayLayer,
1777
+ arrayLayerCount: 1
1778
+ });
1779
+ const framebuffer = device.createFramebuffer({
1780
+ colorAttachments: [destinationView]
1781
+ });
1782
+ const renderPass = device.beginRenderPass({
1783
+ id: `mipmap-generation:${texture.format}:${baseMipLevel}:${baseArrayLayer}`,
1784
+ framebuffer
1785
+ });
1786
+ renderPass.setParameters({
1787
+ viewport: [0, 0, destinationWidth, destinationHeight, 0, 1],
1788
+ scissorRect: [0, 0, destinationWidth, destinationHeight]
1789
+ });
1790
+ model.draw(renderPass);
1791
+ renderPass.end();
1792
+ device.submit();
1793
+ destinationView.destroy();
1794
+ framebuffer.destroy();
1795
+ }
1796
+ sourceView.destroy();
1797
+ sourceWidth = destinationWidth;
1798
+ sourceHeight = destinationHeight;
1799
+ }
1800
+ } finally {
1801
+ model.destroy();
1802
+ sampler.destroy();
1803
+ uniformsBuffer.destroy();
1804
+ }
1805
+ }
1806
+ function getColorAttachmentFormat(format, path, dimension) {
1807
+ if (import_core10.textureFormatDecoder.isColor(format)) {
1808
+ return format;
1809
+ }
1810
+ throw new Error(`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.`);
1811
+ }
1812
+ function generateMipmaps3D(device, texture) {
1813
+ validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
1814
+ const format = getColorAttachmentFormat(texture.format, "compute", texture.dimension);
1815
+ const shaderSource = get3DComputeMipmapWGSL(format);
1816
+ const uniformsBuffer = device.createBuffer({
1817
+ byteLength: 32,
1818
+ usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
1819
+ });
1820
+ const uniformValues = new Uint32Array(8);
1821
+ let sourceWidth = texture.width;
1822
+ let sourceHeight = texture.height;
1823
+ let sourceDepth = texture.depth;
1824
+ try {
1825
+ for (let destinationMipLevel = 1; destinationMipLevel < texture.mipLevels; ++destinationMipLevel) {
1826
+ validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
1827
+ const destinationWidth = Math.max(1, sourceWidth >> 1);
1828
+ const destinationHeight = Math.max(1, sourceHeight >> 1);
1829
+ const destinationDepth = Math.max(1, sourceDepth >> 1);
1830
+ uniformValues[0] = sourceWidth;
1831
+ uniformValues[1] = sourceHeight;
1832
+ uniformValues[2] = sourceDepth;
1833
+ uniformValues[3] = destinationWidth;
1834
+ uniformValues[4] = destinationHeight;
1835
+ uniformValues[5] = destinationDepth;
1836
+ uniformValues[6] = 0;
1837
+ uniformsBuffer.write(uniformValues);
1838
+ const sourceView = texture.createView({
1839
+ dimension: "3d",
1840
+ baseMipLevel: destinationMipLevel - 1,
1841
+ mipLevelCount: 1,
1842
+ baseArrayLayer: 0,
1843
+ arrayLayerCount: 1
1844
+ });
1845
+ const destinationView = texture.createView({
1846
+ dimension: "3d",
1847
+ baseMipLevel: destinationMipLevel,
1848
+ mipLevelCount: 1,
1849
+ baseArrayLayer: 0,
1850
+ arrayLayerCount: 1
1851
+ });
1852
+ const computation = new Computation(device, {
1853
+ source: shaderSource,
1854
+ shaderLayout: {
1855
+ bindings: [
1856
+ {
1857
+ type: "texture",
1858
+ name: "sourceTexture",
1859
+ group: 0,
1860
+ location: 0,
1861
+ viewDimension: "3d",
1862
+ sampleType: "float"
1863
+ },
1864
+ {
1865
+ type: "storage",
1866
+ name: "destinationTexture",
1867
+ group: 0,
1868
+ location: 1,
1869
+ format,
1870
+ viewDimension: "3d",
1871
+ access: "write-only"
1872
+ },
1873
+ { type: "uniform", name: "uniforms", group: 0, location: 2 }
1874
+ ]
1875
+ },
1876
+ bindings: {
1877
+ sourceTexture: sourceView,
1878
+ destinationTexture: destinationView,
1879
+ uniforms: uniformsBuffer
1880
+ }
1881
+ });
1882
+ const workgroupsX = Math.ceil(destinationWidth / WORKGROUP_SIZE.x);
1883
+ const workgroupsY = Math.ceil(destinationHeight / WORKGROUP_SIZE.y);
1884
+ const workgroupsZ = Math.ceil(destinationDepth / WORKGROUP_SIZE.z);
1885
+ const computePass = device.beginComputePass({});
1886
+ computation.dispatch(computePass, workgroupsX, workgroupsY, workgroupsZ);
1887
+ computePass.end();
1888
+ device.submit();
1889
+ computation.destroy();
1890
+ sourceView.destroy();
1891
+ destinationView.destroy();
1892
+ sourceWidth = destinationWidth;
1893
+ sourceHeight = destinationHeight;
1894
+ sourceDepth = destinationDepth;
1895
+ }
1896
+ } finally {
1897
+ uniformsBuffer.destroy();
1898
+ }
1899
+ }
1900
+ function validateFormatCapabilities(device, texture, requiredCapabilities, path) {
1901
+ const { format, dimension } = texture;
1902
+ const capabilities = device.getTextureFormatCapabilities(format);
1903
+ const missingCapabilities = requiredCapabilities.filter((capability) => !capabilities[capability]);
1904
+ if (missingCapabilities.length > 0) {
1905
+ const required = requiredCapabilities.join(" + ");
1906
+ const actual = requiredCapabilities.map((capability) => `${capability}=${capabilities[capability]}`).join(", ");
1907
+ throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Required capabilities: ${required}. Actual capabilities: ${actual}.`);
1908
+ }
1909
+ }
1910
+ function getSourceTextureType(dimension) {
1911
+ switch (dimension) {
1912
+ case "2d":
1913
+ return "texture_2d<f32>";
1914
+ case "2d-array":
1915
+ return "texture_2d_array<f32>";
1916
+ case "cube":
1917
+ return "texture_cube<f32>";
1918
+ case "cube-array":
1919
+ return "texture_cube_array<f32>";
1920
+ default:
1921
+ throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
1922
+ }
1923
+ }
1924
+ function getRenderMipmapWGSL(dimension) {
1925
+ const sourceSnippet = getRenderMipmapSampleSnippet(dimension);
1926
+ return `
1927
+ struct MipmapUniforms {
1928
+ sourceLayer: u32,
1929
+ };
1930
+
1931
+ fn _touchUniform(uniforms: MipmapUniforms) {
1932
+ let unusedSourceLayer = uniforms.sourceLayer;
1933
+ }
1934
+
1935
+ const faceMat = array(
1936
+ mat3x3f(
1937
+ 0.0, 0.0, -2.0,
1938
+ 0.0, -2.0, 0.0,
1939
+ 1.0, 1.0, 1.0
1940
+ ), // pos-x
1941
+ mat3x3f(
1942
+ 0.0, 0.0, 2.0,
1943
+ 0.0, -2.0, 0.0,
1944
+ -1.0, 1.0, -1.0
1945
+ ), // neg-x
1946
+ mat3x3f(
1947
+ 2.0, 0.0, 0.0,
1948
+ 0.0, 0.0, 2.0,
1949
+ -1.0, 1.0, -1.0
1950
+ ), // pos-y
1951
+ mat3x3f(
1952
+ 2.0, 0.0, 0.0,
1953
+ 0.0, 0.0, -2.0,
1954
+ -1.0, -1.0, 1.0
1955
+ ), // neg-y
1956
+ mat3x3f(
1957
+ 2.0, 0.0, 0.0,
1958
+ 0.0, -2.0, 0.0,
1959
+ -1.0, 1.0, 1.0
1960
+ ), // pos-z
1961
+ mat3x3f(
1962
+ -2.0, 0.0, 0.0,
1963
+ 0.0, -2.0, 0.0,
1964
+ 1.0, 1.0, -1.0
1965
+ ) // neg-z
1966
+ );
1967
+
1968
+ struct FragmentInputs {
1969
+ @builtin(position) position: vec4f,
1970
+ @location(0) texcoord: vec2f
1971
+ };
1972
+
1973
+ struct VertexOutput {
1974
+ @builtin(position) position: vec4f,
1975
+ @location(0) texcoord: vec2f
1976
+ };
1977
+
1978
+ @group(0) @binding(0) var sourceSampler: sampler;
1979
+ @group(0) @binding(1) var sourceTexture: ${getSourceTextureType(dimension)};
1980
+ @group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
1981
+
1982
+ @vertex
1983
+ fn vertexMain(
1984
+ @builtin(vertex_index) vertexIndex: u32
1985
+ ) -> VertexOutput {
1986
+ const positions = array(
1987
+ vec2f(-1.0, -1.0),
1988
+ vec2f(-1.0, 3.0),
1989
+ vec2f( 3.0, -1.0)
1990
+ );
1991
+
1992
+ let xy = positions[vertexIndex];
1993
+ return VertexOutput(
1994
+ vec4f(xy, 0.0, 1.0),
1995
+ xy * vec2f(0.5, -0.5) + vec2f(0.5)
1996
+ );
1997
+ }
1998
+
1999
+ @fragment
2000
+ fn fragmentMain(fsInput: VertexOutput) -> @location(0) vec4f {
2001
+ _touchUniform(uniforms);
2002
+ return ${sourceSnippet};
2003
+ }
2004
+ `;
2005
+ }
2006
+ function getRenderMipmapSampleSnippet(dimension) {
2007
+ const layer = "uniforms.sourceLayer";
2008
+ switch (dimension) {
2009
+ case "2d":
2010
+ return "textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, 0.0)";
2011
+ case "2d-array":
2012
+ return `textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, i32(${layer}), 0.0)`;
2013
+ case "cube":
2014
+ return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer})] * vec3f(fract(fsInput.texcoord), 1.0), 0.0)`;
2015
+ case "cube-array":
2016
+ return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer} % 6u)] * vec3f(fract(fsInput.texcoord), 1.0), i32(${layer} / 6u), 0.0)`;
2017
+ default:
2018
+ throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
2019
+ }
1441
2020
  }
1442
- function getTextureCubeSubresources(data) {
1443
- const subresources = [];
1444
- for (const [face, faceData] of Object.entries(data)) {
1445
- const faceDepth = getCubeFaceIndex(face);
1446
- subresources.push(...getTexture2DSubresources(faceDepth, faceData));
2021
+ function get3DComputeMipmapWGSL(format) {
2022
+ return `
2023
+ struct MipmapUniforms {
2024
+ sourceWidth: u32,
2025
+ sourceHeight: u32,
2026
+ sourceDepth: u32,
2027
+ destinationWidth: u32,
2028
+ destinationHeight: u32,
2029
+ destinationDepth: u32,
2030
+ padding: u32,
2031
+ };
2032
+
2033
+ @group(0) @binding(0) var sourceTexture: texture_3d<f32>;
2034
+ @group(0) @binding(1) var destinationTexture: texture_storage_3d<${format}, write>;
2035
+ @group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
2036
+
2037
+ @compute @workgroup_size(${WORKGROUP_SIZE.x}, ${WORKGROUP_SIZE.y}, ${WORKGROUP_SIZE.z})
2038
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
2039
+ if (
2040
+ id.x >= uniforms.destinationWidth ||
2041
+ id.y >= uniforms.destinationHeight ||
2042
+ id.z >= uniforms.destinationDepth
2043
+ ) {
2044
+ return;
1447
2045
  }
1448
- return subresources;
2046
+
2047
+ let sourceBase = id * 2u;
2048
+ let sourceX0 = min(sourceBase.x, uniforms.sourceWidth - 1u);
2049
+ let sourceY0 = min(sourceBase.y, uniforms.sourceHeight - 1u);
2050
+ let sourceZ0 = min(sourceBase.z, uniforms.sourceDepth - 1u);
2051
+
2052
+ let sourceX1 = min(sourceBase.x + 1u, uniforms.sourceWidth - 1u);
2053
+ let sourceY1 = min(sourceBase.y + 1u, uniforms.sourceHeight - 1u);
2054
+ let sourceZ1 = min(sourceBase.z + 1u, uniforms.sourceDepth - 1u);
2055
+
2056
+ var sum = textureLoad(
2057
+ sourceTexture,
2058
+ vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ0)),
2059
+ 0
2060
+ );
2061
+ sum += textureLoad(
2062
+ sourceTexture,
2063
+ vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ0)),
2064
+ 0
2065
+ );
2066
+ sum += textureLoad(
2067
+ sourceTexture,
2068
+ vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ0)),
2069
+ 0
2070
+ );
2071
+ sum += textureLoad(
2072
+ sourceTexture,
2073
+ vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ0)),
2074
+ 0
2075
+ );
2076
+ sum += textureLoad(
2077
+ sourceTexture,
2078
+ vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ1)),
2079
+ 0
2080
+ );
2081
+ sum += textureLoad(
2082
+ sourceTexture,
2083
+ vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ1)),
2084
+ 0
2085
+ );
2086
+ sum += textureLoad(
2087
+ sourceTexture,
2088
+ vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ1)),
2089
+ 0
2090
+ );
2091
+ sum += textureLoad(
2092
+ sourceTexture,
2093
+ vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ1)),
2094
+ 0
2095
+ );
2096
+
2097
+ textureStore(
2098
+ destinationTexture,
2099
+ vec3<i32>(i32(id.x), i32(id.y), i32(id.z)),
2100
+ vec4<f32>(sum.xyz / 8.0, sum.w / 8.0)
2101
+ );
1449
2102
  }
1450
- function getTextureCubeArraySubresources(data) {
1451
- const subresources = [];
1452
- data.forEach((cubeData, cubeIndex) => {
1453
- for (const [face, faceData] of Object.entries(cubeData)) {
1454
- const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
1455
- getTexture2DSubresources(faceDepth, faceData);
1456
- }
1457
- });
1458
- return subresources;
2103
+ `;
1459
2104
  }
1460
2105
 
1461
2106
  // dist/dynamic-texture/dynamic-texture.js
@@ -1535,6 +2180,10 @@ var _DynamicTexture = class {
1535
2180
  // temporary; updated below
1536
2181
  data: void 0
1537
2182
  };
2183
+ if (this.device.type === "webgpu" && this.props.mipmaps) {
2184
+ 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;
2185
+ baseTextureProps.usage |= requiredUsage;
2186
+ }
1538
2187
  const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
1539
2188
  const desired = this.props.mipLevels === "auto" ? maxMips : Math.max(1, Math.min(maxMips, this.props.mipLevels ?? 1));
1540
2189
  const finalTextureProps = { ...baseTextureProps, mipLevels: desired };
@@ -1571,7 +2220,7 @@ var _DynamicTexture = class {
1571
2220
  }
1572
2221
  this.isReady = true;
1573
2222
  this.resolveReady(this.texture);
1574
- import_core9.log.info(0, `${this} created`)();
2223
+ import_core11.log.info(0, `${this} created`)();
1575
2224
  } catch (e) {
1576
2225
  const err = e instanceof Error ? e : new Error(String(e));
1577
2226
  this.rejectReady(err);
@@ -1590,14 +2239,16 @@ var _DynamicTexture = class {
1590
2239
  generateMipmaps() {
1591
2240
  if (this.device.type === "webgl") {
1592
2241
  this.texture.generateMipmapsWebGL();
2242
+ } else if (this.device.type === "webgpu") {
2243
+ generateMipmap(this.device, this.texture);
1593
2244
  } else {
1594
- import_core9.log.warn("Mipmap generation not yet implemented on WebGPU: your texture data will not be correctly initialized");
2245
+ import_core11.log.warn(`${this} mipmaps not supported on ${this.device.type}`);
1595
2246
  }
1596
2247
  }
1597
2248
  /** Set sampler or create one from props */
1598
2249
  setSampler(sampler = {}) {
1599
2250
  this._checkReady();
1600
- const s = sampler instanceof import_core9.Sampler ? sampler : this.device.createSampler(sampler);
2251
+ const s = sampler instanceof import_core11.Sampler ? sampler : this.device.createSampler(sampler);
1601
2252
  this.texture.setSampler(s);
1602
2253
  this._sampler = s;
1603
2254
  }
@@ -1615,7 +2266,7 @@ var _DynamicTexture = class {
1615
2266
  this._sampler = this.texture.sampler;
1616
2267
  this._view = this.texture.view;
1617
2268
  prev.destroy();
1618
- import_core9.log.info(`${this} resized`);
2269
+ import_core11.log.info(`${this} resized`);
1619
2270
  return true;
1620
2271
  }
1621
2272
  /** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
@@ -1690,7 +2341,15 @@ var _DynamicTexture = class {
1690
2341
  break;
1691
2342
  case "texture-data":
1692
2343
  const { data } = subresource;
1693
- this.texture.copyImageData({ data: data.data, z, mipLevel });
2344
+ this.texture.writeData(getAlignedUploadData(this.texture, data), {
2345
+ x: 0,
2346
+ y: 0,
2347
+ z,
2348
+ width: data.width,
2349
+ height: data.height,
2350
+ depthOrArrayLayers: 1,
2351
+ mipLevel
2352
+ });
1694
2353
  break;
1695
2354
  default:
1696
2355
  throw new Error("Unsupported 2D mip-level payload");
@@ -1706,22 +2365,39 @@ var _DynamicTexture = class {
1706
2365
  }
1707
2366
  _checkNotDestroyed() {
1708
2367
  if (this.destroyed) {
1709
- import_core9.log.warn(`${this} already destroyed`);
2368
+ import_core11.log.warn(`${this} already destroyed`);
1710
2369
  }
1711
2370
  }
1712
2371
  _checkReady() {
1713
2372
  if (!this.isReady) {
1714
- import_core9.log.warn(`${this} Cannot perform this operation before ready`);
2373
+ import_core11.log.warn(`${this} Cannot perform this operation before ready`);
1715
2374
  }
1716
2375
  }
1717
2376
  };
1718
2377
  var DynamicTexture = _DynamicTexture;
1719
2378
  __publicField(DynamicTexture, "defaultProps", {
1720
- ...import_core9.Texture.defaultProps,
2379
+ ...import_core11.Texture.defaultProps,
1721
2380
  dimension: "2d",
1722
2381
  data: null,
1723
2382
  mipmaps: false
1724
2383
  });
2384
+ function getAlignedUploadData(texture, data) {
2385
+ const { width, height, data: uploadData } = data;
2386
+ const { bytesPerPixel } = texture.device.getTextureFormatInfo(texture.format);
2387
+ const bytesPerRow = width * bytesPerPixel;
2388
+ const alignedBytesPerRow = Math.ceil(bytesPerRow / texture.byteAlignment) * texture.byteAlignment;
2389
+ if (alignedBytesPerRow === bytesPerRow) {
2390
+ return uploadData;
2391
+ }
2392
+ const sourceBytes = new Uint8Array(uploadData.buffer, uploadData.byteOffset, uploadData.byteLength);
2393
+ const paddedBytes = new Uint8Array(alignedBytesPerRow * height);
2394
+ for (let row = 0; row < height; row++) {
2395
+ const sourceOffset = row * bytesPerRow;
2396
+ const destinationOffset = row * alignedBytesPerRow;
2397
+ paddedBytes.set(sourceBytes.subarray(sourceOffset, sourceOffset + bytesPerRow), destinationOffset);
2398
+ }
2399
+ return paddedBytes;
2400
+ }
1725
2401
  async function awaitAllPromises(x) {
1726
2402
  x = await x;
1727
2403
  if (Array.isArray(x)) {
@@ -1741,8 +2417,8 @@ async function awaitAllPromises(x) {
1741
2417
  }
1742
2418
 
1743
2419
  // dist/model/model.js
1744
- var LOG_DRAW_PRIORITY = 2;
1745
- var LOG_DRAW_TIMEOUT = 1e4;
2420
+ var LOG_DRAW_PRIORITY2 = 2;
2421
+ var LOG_DRAW_TIMEOUT2 = 1e4;
1746
2422
  var _Model = class {
1747
2423
  /** Device that created this model */
1748
2424
  device;
@@ -1824,7 +2500,7 @@ var _Model = class {
1824
2500
  const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
1825
2501
  const shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap, { disableWarnings: this.props.disableWarnings });
1826
2502
  this.setShaderInputs(shaderInputs);
1827
- const platformInfo = getPlatformInfo(device);
2503
+ const platformInfo = getPlatformInfo2(device);
1828
2504
  const modules = (
1829
2505
  // @ts-ignore shaderInputs is assigned in setShaderInputs above.
1830
2506
  (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || []
@@ -1932,7 +2608,7 @@ var _Model = class {
1932
2608
  draw(renderPass) {
1933
2609
  const loadingBinding = this._areBindingsLoading();
1934
2610
  if (loadingBinding) {
1935
- import_core10.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
2611
+ import_core12.log.info(LOG_DRAW_PRIORITY2, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1936
2612
  return false;
1937
2613
  }
1938
2614
  try {
@@ -2060,7 +2736,7 @@ var _Model = class {
2060
2736
  /** Set the shader inputs */
2061
2737
  setShaderInputs(shaderInputs) {
2062
2738
  this.shaderInputs = shaderInputs;
2063
- this._uniformStore = new import_core10.UniformStore(this.shaderInputs.modules);
2739
+ this._uniformStore = new import_core12.UniformStore(this.shaderInputs.modules);
2064
2740
  for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
2065
2741
  if (shaderModuleHasUniforms(module2)) {
2066
2742
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
@@ -2104,7 +2780,7 @@ var _Model = class {
2104
2780
  setAttributes(buffers, options) {
2105
2781
  const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
2106
2782
  if (buffers["indices"]) {
2107
- import_core10.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
2783
+ import_core12.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
2108
2784
  }
2109
2785
  this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(this.pipeline.shaderLayout, this.bufferLayout);
2110
2786
  const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
@@ -2112,7 +2788,7 @@ var _Model = class {
2112
2788
  const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
2113
2789
  if (!bufferLayout) {
2114
2790
  if (!disableWarnings) {
2115
- import_core10.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2791
+ import_core12.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2116
2792
  }
2117
2793
  continue;
2118
2794
  }
@@ -2127,7 +2803,7 @@ var _Model = class {
2127
2803
  }
2128
2804
  }
2129
2805
  if (!set && !disableWarnings) {
2130
- import_core10.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
2806
+ import_core12.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
2131
2807
  }
2132
2808
  }
2133
2809
  this.setNeedsRedraw("attributes");
@@ -2146,7 +2822,7 @@ var _Model = class {
2146
2822
  if (attributeInfo) {
2147
2823
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
2148
2824
  } else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
2149
- import_core10.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
2825
+ import_core12.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
2150
2826
  }
2151
2827
  }
2152
2828
  this.setNeedsRedraw("constants");
@@ -2179,16 +2855,16 @@ var _Model = class {
2179
2855
  _getBindingsUpdateTimestamp() {
2180
2856
  let timestamp = 0;
2181
2857
  for (const binding of Object.values(this.bindings)) {
2182
- if (binding instanceof import_core10.TextureView) {
2858
+ if (binding instanceof import_core12.TextureView) {
2183
2859
  timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
2184
- } else if (binding instanceof import_core10.Buffer || binding instanceof import_core10.Texture) {
2860
+ } else if (binding instanceof import_core12.Buffer || binding instanceof import_core12.Texture) {
2185
2861
  timestamp = Math.max(timestamp, binding.updateTimestamp);
2186
2862
  } else if (binding instanceof DynamicTexture) {
2187
2863
  timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
2188
2864
  // The texture will become available in the future
2189
2865
  Infinity
2190
2866
  );
2191
- } else if (!(binding instanceof import_core10.Sampler)) {
2867
+ } else if (!(binding instanceof import_core12.Sampler)) {
2192
2868
  timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
2193
2869
  }
2194
2870
  }
@@ -2223,7 +2899,7 @@ var _Model = class {
2223
2899
  let prevShaderVs = null;
2224
2900
  let prevShaderFs = null;
2225
2901
  if (this.pipeline) {
2226
- import_core10.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
2902
+ import_core12.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
2227
2903
  prevShaderVs = this.pipeline.vs;
2228
2904
  prevShaderFs = this.pipeline.fs;
2229
2905
  }
@@ -2256,7 +2932,7 @@ var _Model = class {
2256
2932
  vs: vs3,
2257
2933
  fs: fs3
2258
2934
  });
2259
- this._attributeInfos = (0, import_core10.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
2935
+ this._attributeInfos = (0, import_core12.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
2260
2936
  if (prevShaderVs)
2261
2937
  this.shaderFactory.release(prevShaderVs);
2262
2938
  if (prevShaderFs)
@@ -2268,24 +2944,24 @@ var _Model = class {
2268
2944
  _lastLogTime = 0;
2269
2945
  _logOpen = false;
2270
2946
  _logDrawCallStart() {
2271
- const logDrawTimeout = import_core10.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2272
- if (import_core10.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2947
+ const logDrawTimeout = import_core12.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
2948
+ if (import_core12.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2273
2949
  return;
2274
2950
  }
2275
2951
  this._lastLogTime = Date.now();
2276
2952
  this._logOpen = true;
2277
- import_core10.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core10.log.level <= 2 })();
2953
+ import_core12.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core12.log.level <= 2 })();
2278
2954
  }
2279
2955
  _logDrawCallEnd() {
2280
2956
  if (this._logOpen) {
2281
2957
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
2282
- import_core10.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
2958
+ import_core12.log.table(LOG_DRAW_PRIORITY2, shaderLayoutTable)();
2283
2959
  const uniformTable = this.shaderInputs.getDebugTable();
2284
- import_core10.log.table(LOG_DRAW_PRIORITY, uniformTable)();
2960
+ import_core12.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
2285
2961
  const attributeTable = this._getAttributeDebugTable();
2286
- import_core10.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2287
- import_core10.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2288
- import_core10.log.groupEnd(LOG_DRAW_PRIORITY)();
2962
+ import_core12.log.table(LOG_DRAW_PRIORITY2, this._attributeInfos)();
2963
+ import_core12.log.table(LOG_DRAW_PRIORITY2, attributeTable)();
2964
+ import_core12.log.groupEnd(LOG_DRAW_PRIORITY2)();
2289
2965
  this._logOpen = false;
2290
2966
  }
2291
2967
  }
@@ -2324,14 +3000,14 @@ var _Model = class {
2324
3000
  }
2325
3001
  // TODO - fix typing of luma data types
2326
3002
  _getBufferOrConstantValues(attribute, dataType) {
2327
- const TypedArrayConstructor = (0, import_core10.getTypedArrayConstructor)(dataType);
2328
- const typedArray = attribute instanceof import_core10.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
3003
+ const TypedArrayConstructor = (0, import_core12.getTypedArrayConstructor)(dataType);
3004
+ const typedArray = attribute instanceof import_core12.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2329
3005
  return typedArray.toString();
2330
3006
  }
2331
3007
  };
2332
3008
  var Model = _Model;
2333
3009
  __publicField(Model, "defaultProps", {
2334
- ...import_core10.RenderPipeline.defaultProps,
3010
+ ...import_core12.RenderPipeline.defaultProps,
2335
3011
  source: void 0,
2336
3012
  vs: null,
2337
3013
  fs: null,
@@ -2352,14 +3028,14 @@ __publicField(Model, "defaultProps", {
2352
3028
  pipelineFactory: void 0,
2353
3029
  shaderFactory: void 0,
2354
3030
  transformFeedback: void 0,
2355
- shaderAssembler: import_shadertools2.ShaderAssembler.getDefaultShaderAssembler(),
3031
+ shaderAssembler: import_shadertools3.ShaderAssembler.getDefaultShaderAssembler(),
2356
3032
  debugShaders: void 0,
2357
3033
  disableWarnings: void 0
2358
3034
  });
2359
3035
  function shaderModuleHasUniforms(module2) {
2360
3036
  return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
2361
3037
  }
2362
- function getPlatformInfo(device) {
3038
+ function getPlatformInfo2(device) {
2363
3039
  return {
2364
3040
  type: device.type,
2365
3041
  shaderLanguage: device.info.shadingLanguage,
@@ -2377,8 +3053,8 @@ function isObjectEmpty(obj) {
2377
3053
  }
2378
3054
 
2379
3055
  // dist/compute/buffer-transform.js
2380
- var import_core11 = require("@luma.gl/core");
2381
- var import_shadertools3 = require("@luma.gl/shadertools");
3056
+ var import_core13 = require("@luma.gl/core");
3057
+ var import_shadertools4 = require("@luma.gl/shadertools");
2382
3058
  var _BufferTransform = class {
2383
3059
  device;
2384
3060
  model;
@@ -2394,7 +3070,7 @@ var _BufferTransform = class {
2394
3070
  this.device = device;
2395
3071
  this.model = new Model(this.device, {
2396
3072
  id: props.id || "buffer-transform-model",
2397
- fs: props.fs || (0, import_shadertools3.getPassthroughFS)(),
3073
+ fs: props.fs || (0, import_shadertools4.getPassthroughFS)(),
2398
3074
  topology: props.topology || "point-list",
2399
3075
  varyings: props.outputs || props.varyings,
2400
3076
  ...props
@@ -2440,7 +3116,7 @@ var _BufferTransform = class {
2440
3116
  if (!result) {
2441
3117
  throw new Error("BufferTransform#getBuffer");
2442
3118
  }
2443
- if (result instanceof import_core11.Buffer) {
3119
+ if (result instanceof import_core13.Buffer) {
2444
3120
  return result.readAsync();
2445
3121
  }
2446
3122
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
@@ -2455,7 +3131,7 @@ __publicField(BufferTransform, "defaultProps", {
2455
3131
  });
2456
3132
 
2457
3133
  // dist/compute/texture-transform.js
2458
- var import_shadertools4 = require("@luma.gl/shadertools");
3134
+ var import_shadertools5 = require("@luma.gl/shadertools");
2459
3135
  var FS_OUTPUT_VARIABLE = "transform_output";
2460
3136
  var TextureTransform = class {
2461
3137
  device;
@@ -2478,7 +3154,7 @@ var TextureTransform = class {
2478
3154
  });
2479
3155
  this.model = new Model(this.device, {
2480
3156
  id: props.id || uid("texture-transform-model"),
2481
- fs: props.fs || (0, import_shadertools4.getPassthroughFS)({
3157
+ fs: props.fs || (0, import_shadertools5.getPassthroughFS)({
2482
3158
  input: props.targetTextureVarying,
2483
3159
  inputChannels: props.targetTextureChannels,
2484
3160
  output: FS_OUTPUT_VARIABLE
@@ -2838,14 +3514,14 @@ var BackgroundTextureModel = class extends ClipSpace {
2838
3514
  };
2839
3515
 
2840
3516
  // dist/scenegraph/scenegraph-node.js
2841
- var import_core12 = require("@math.gl/core");
3517
+ var import_core14 = require("@math.gl/core");
2842
3518
  var ScenegraphNode = class {
2843
3519
  id;
2844
- matrix = new import_core12.Matrix4();
3520
+ matrix = new import_core14.Matrix4();
2845
3521
  display = true;
2846
- position = new import_core12.Vector3();
2847
- rotation = new import_core12.Vector3();
2848
- scale = new import_core12.Vector3(1, 1, 1);
3522
+ position = new import_core14.Vector3();
3523
+ rotation = new import_core14.Vector3();
3524
+ scale = new import_core14.Vector3(1, 1, 1);
2849
3525
  userData = {};
2850
3526
  props = {};
2851
3527
  constructor(props = {}) {
@@ -2930,7 +3606,7 @@ var ScenegraphNode = class {
2930
3606
  }
2931
3607
  getCoordinateUniforms(viewMatrix, modelMatrix) {
2932
3608
  modelMatrix = modelMatrix || this.matrix;
2933
- const worldMatrix = new import_core12.Matrix4(viewMatrix).multiplyRight(modelMatrix);
3609
+ const worldMatrix = new import_core14.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2934
3610
  const worldInverse = worldMatrix.invert();
2935
3611
  const worldInverseTranspose = worldInverse.transpose();
2936
3612
  return {
@@ -2982,14 +3658,14 @@ var ScenegraphNode = class {
2982
3658
  };
2983
3659
 
2984
3660
  // dist/scenegraph/group-node.js
2985
- var import_core13 = require("@math.gl/core");
2986
- var import_core14 = require("@luma.gl/core");
3661
+ var import_core15 = require("@math.gl/core");
3662
+ var import_core16 = require("@luma.gl/core");
2987
3663
  var GroupNode = class extends ScenegraphNode {
2988
3664
  children;
2989
3665
  constructor(props = {}) {
2990
3666
  props = Array.isArray(props) ? { children: props } : props;
2991
3667
  const { children = [] } = props;
2992
- import_core14.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
3668
+ import_core16.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2993
3669
  super(props);
2994
3670
  this.children = children;
2995
3671
  }
@@ -3004,12 +3680,12 @@ var GroupNode = class extends ScenegraphNode {
3004
3680
  return;
3005
3681
  }
3006
3682
  const [min, max] = bounds;
3007
- const center = new import_core13.Vector3(min).add(max).divide([2, 2, 2]);
3683
+ const center = new import_core15.Vector3(min).add(max).divide([2, 2, 2]);
3008
3684
  worldMatrix.transformAsPoint(center, center);
3009
- const halfSize = new import_core13.Vector3(max).subtract(min).divide([2, 2, 2]);
3685
+ const halfSize = new import_core15.Vector3(max).subtract(min).divide([2, 2, 2]);
3010
3686
  worldMatrix.transformAsVector(halfSize, halfSize);
3011
3687
  for (let v = 0; v < 8; v++) {
3012
- const position = new import_core13.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
3688
+ const position = new import_core15.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
3013
3689
  for (let i = 0; i < 3; i++) {
3014
3690
  result[0][i] = Math.min(result[0][i], position[i]);
3015
3691
  result[1][i] = Math.max(result[1][i], position[i]);
@@ -3049,8 +3725,8 @@ var GroupNode = class extends ScenegraphNode {
3049
3725
  this.children = [];
3050
3726
  return this;
3051
3727
  }
3052
- traverse(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
3053
- const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
3728
+ traverse(visitor, { worldMatrix = new import_core15.Matrix4() } = {}) {
3729
+ const modelMatrix = new import_core15.Matrix4(worldMatrix).multiplyRight(this.matrix);
3054
3730
  for (const child of this.children) {
3055
3731
  if (child instanceof GroupNode) {
3056
3732
  child.traverse(visitor, { worldMatrix: modelMatrix });
@@ -3832,7 +4508,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
3832
4508
  };
3833
4509
 
3834
4510
  // dist/geometries/ico-sphere-geometry.js
3835
- var import_core15 = require("@math.gl/core");
4511
+ var import_core17 = require("@math.gl/core");
3836
4512
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
3837
4513
  var ICO_INDICES = [3, 4, 5, 3, 5, 1, 3, 1, 0, 3, 0, 4, 4, 0, 2, 4, 2, 5, 2, 0, 1, 5, 2, 1];
3838
4514
  var IcoSphereGeometry = class extends Geometry {
@@ -3930,7 +4606,7 @@ function tesselateIcosaHedron(props) {
3930
4606
  const u3 = 1 - phi3 / PI2;
3931
4607
  const vec1 = [x3 - x2, y3 - y2, z3 - z2];
3932
4608
  const vec2 = [x1 - x2, y1 - y2, z1 - z2];
3933
- const normal = new import_core15.Vector3(vec1).cross(vec2).normalize();
4609
+ const normal = new import_core17.Vector3(vec1).cross(vec2).normalize();
3934
4610
  let newIndex;
3935
4611
  if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
3936
4612
  positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
@@ -4217,10 +4893,10 @@ async function loadImage(url, opts) {
4217
4893
  }
4218
4894
 
4219
4895
  // dist/passes/shader-pass-renderer.js
4220
- var import_shadertools5 = require("@luma.gl/shadertools");
4896
+ var import_shadertools6 = require("@luma.gl/shadertools");
4221
4897
 
4222
4898
  // dist/compute/swap.js
4223
- var import_core16 = require("@luma.gl/core");
4899
+ var import_core18 = require("@luma.gl/core");
4224
4900
  var Swap = class {
4225
4901
  id;
4226
4902
  /** The current resource - usually the source for renders or computations */
@@ -4253,7 +4929,7 @@ var SwapFramebuffers = class extends Swap {
4253
4929
  let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
4254
4930
  id: `${props.id}-texture-0`,
4255
4931
  format: colorAttachment,
4256
- usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
4932
+ usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
4257
4933
  width,
4258
4934
  height
4259
4935
  }));
@@ -4261,7 +4937,7 @@ var SwapFramebuffers = class extends Swap {
4261
4937
  colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
4262
4938
  id: `${props.id}-texture-1`,
4263
4939
  format: colorAttachment,
4264
- usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
4940
+ usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
4265
4941
  width,
4266
4942
  height
4267
4943
  }));
@@ -4432,7 +5108,7 @@ var ShaderPassRenderer = class {
4432
5108
  textureModel;
4433
5109
  constructor(device, props) {
4434
5110
  this.device = device;
4435
- props.shaderPasses.map((shaderPass) => (0, import_shadertools5.initializeShaderModule)(shaderPass));
5111
+ props.shaderPasses.map((shaderPass) => (0, import_shadertools6.initializeShaderModule)(shaderPass));
4436
5112
  const modules = props.shaderPasses.reduce((object, shaderPass) => ({ ...object, [shaderPass.name]: shaderPass }), {});
4437
5113
  this.shaderInputs = props.shaderInputs || new ShaderInputs(modules);
4438
5114
  const size = device.getCanvasContext().getDrawingBufferSize();
@@ -4604,218 +5280,6 @@ var SubPassRenderer = class {
4604
5280
  }
4605
5281
  };
4606
5282
 
4607
- // dist/compute/computation.js
4608
- var import_core17 = require("@luma.gl/core");
4609
- var import_shadertools6 = require("@luma.gl/shadertools");
4610
- var import_types2 = require("@math.gl/types");
4611
- var LOG_DRAW_PRIORITY2 = 2;
4612
- var LOG_DRAW_TIMEOUT2 = 1e4;
4613
- var _Computation = class {
4614
- device;
4615
- id;
4616
- pipelineFactory;
4617
- shaderFactory;
4618
- userData = {};
4619
- /** Bindings (textures, samplers, uniform buffers) */
4620
- bindings = {};
4621
- /** The underlying GPU pipeline. */
4622
- pipeline;
4623
- /** Assembled compute shader source */
4624
- source;
4625
- /** the underlying compiled compute shader */
4626
- // @ts-ignore Set in function called from constructor
4627
- shader;
4628
- /** ShaderInputs instance */
4629
- shaderInputs;
4630
- // @ts-ignore Set in function called from constructor
4631
- _uniformStore;
4632
- _pipelineNeedsUpdate = "newly created";
4633
- _getModuleUniforms;
4634
- props;
4635
- _destroyed = false;
4636
- constructor(device, props) {
4637
- var _a, _b, _c;
4638
- if (device.type !== "webgpu") {
4639
- throw new Error("Computation is only supported in WebGPU");
4640
- }
4641
- this.props = { ..._Computation.defaultProps, ...props };
4642
- props = this.props;
4643
- this.id = props.id || uid("model");
4644
- this.device = device;
4645
- Object.assign(this.userData, props.userData);
4646
- const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
4647
- this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
4648
- this.setShaderInputs(this.shaderInputs);
4649
- this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
4650
- const platformInfo = getPlatformInfo2(device);
4651
- const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
4652
- this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
4653
- this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
4654
- const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
4655
- platformInfo,
4656
- ...this.props,
4657
- modules
4658
- });
4659
- this.source = source3;
4660
- this._getModuleUniforms = getUniforms2;
4661
- this.pipeline = this._updatePipeline();
4662
- if (props.bindings) {
4663
- this.setBindings(props.bindings);
4664
- }
4665
- Object.seal(this);
4666
- }
4667
- destroy() {
4668
- if (this._destroyed)
4669
- return;
4670
- this.pipelineFactory.release(this.pipeline);
4671
- this.shaderFactory.release(this.shader);
4672
- this._uniformStore.destroy();
4673
- this._destroyed = true;
4674
- }
4675
- // Draw call
4676
- predraw() {
4677
- this.updateShaderInputs();
4678
- }
4679
- dispatch(computePass, x, y, z) {
4680
- try {
4681
- this._logDrawCallStart();
4682
- this.pipeline = this._updatePipeline();
4683
- this.pipeline.setBindings(this.bindings);
4684
- computePass.setPipeline(this.pipeline);
4685
- computePass.setBindings([]);
4686
- computePass.dispatch(x, y, z);
4687
- } finally {
4688
- this._logDrawCallEnd();
4689
- }
4690
- }
4691
- // Update fixed fields (can trigger pipeline rebuild)
4692
- // Update dynamic fields
4693
- /**
4694
- * Updates the vertex count (used in draw calls)
4695
- * @note Any attributes with stepMode=vertex need to be at least this big
4696
- */
4697
- setVertexCount(vertexCount) {
4698
- }
4699
- /**
4700
- * Updates the instance count (used in draw calls)
4701
- * @note Any attributes with stepMode=instance need to be at least this big
4702
- */
4703
- setInstanceCount(instanceCount) {
4704
- }
4705
- setShaderInputs(shaderInputs) {
4706
- this.shaderInputs = shaderInputs;
4707
- this._uniformStore = new import_core17.UniformStore(this.shaderInputs.modules);
4708
- for (const moduleName of Object.keys(this.shaderInputs.modules)) {
4709
- const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
4710
- this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
4711
- }
4712
- }
4713
- /**
4714
- * Updates shader module settings (which results in uniforms being set)
4715
- */
4716
- setShaderModuleProps(props) {
4717
- const uniforms = this._getModuleUniforms(props);
4718
- const keys = Object.keys(uniforms).filter((k) => {
4719
- const uniform = uniforms[k];
4720
- return !(0, import_types2.isNumericArray)(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
4721
- });
4722
- const bindings = {};
4723
- for (const k of keys) {
4724
- bindings[k] = uniforms[k];
4725
- delete uniforms[k];
4726
- }
4727
- }
4728
- updateShaderInputs() {
4729
- this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
4730
- }
4731
- /**
4732
- * Sets bindings (textures, samplers, uniform buffers)
4733
- */
4734
- setBindings(bindings) {
4735
- Object.assign(this.bindings, bindings);
4736
- }
4737
- _setPipelineNeedsUpdate(reason) {
4738
- this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
4739
- }
4740
- _updatePipeline() {
4741
- if (this._pipelineNeedsUpdate) {
4742
- let prevShader = null;
4743
- if (this.pipeline) {
4744
- import_core17.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
4745
- prevShader = this.shader;
4746
- }
4747
- this._pipelineNeedsUpdate = false;
4748
- this.shader = this.shaderFactory.createShader({
4749
- id: `${this.id}-fragment`,
4750
- stage: "compute",
4751
- source: this.source,
4752
- debugShaders: this.props.debugShaders
4753
- });
4754
- this.pipeline = this.pipelineFactory.createComputePipeline({
4755
- ...this.props,
4756
- shader: this.shader
4757
- });
4758
- if (prevShader) {
4759
- this.shaderFactory.release(prevShader);
4760
- }
4761
- }
4762
- return this.pipeline;
4763
- }
4764
- /** Throttle draw call logging */
4765
- _lastLogTime = 0;
4766
- _logOpen = false;
4767
- _logDrawCallStart() {
4768
- const logDrawTimeout = import_core17.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
4769
- if (import_core17.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
4770
- return;
4771
- }
4772
- this._lastLogTime = Date.now();
4773
- this._logOpen = true;
4774
- import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
4775
- }
4776
- _logDrawCallEnd() {
4777
- if (this._logOpen) {
4778
- const uniformTable = this.shaderInputs.getDebugTable();
4779
- import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
4780
- import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
4781
- this._logOpen = false;
4782
- }
4783
- }
4784
- _drawCount = 0;
4785
- // TODO - fix typing of luma data types
4786
- _getBufferOrConstantValues(attribute, dataType) {
4787
- const TypedArrayConstructor = (0, import_core17.getTypedArrayConstructor)(dataType);
4788
- const typedArray = attribute instanceof import_core17.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
4789
- return typedArray.toString();
4790
- }
4791
- };
4792
- var Computation = _Computation;
4793
- __publicField(Computation, "defaultProps", {
4794
- ...import_core17.ComputePipeline.defaultProps,
4795
- id: "unnamed",
4796
- handle: void 0,
4797
- userData: {},
4798
- source: "",
4799
- modules: [],
4800
- defines: {},
4801
- bindings: void 0,
4802
- shaderInputs: void 0,
4803
- pipelineFactory: void 0,
4804
- shaderFactory: void 0,
4805
- shaderAssembler: import_shadertools6.ShaderAssembler.getDefaultShaderAssembler(),
4806
- debugShaders: void 0
4807
- });
4808
- function getPlatformInfo2(device) {
4809
- return {
4810
- type: device.type,
4811
- shaderLanguage: device.info.shadingLanguage,
4812
- shaderLanguageVersion: device.info.shadingLanguageVersion,
4813
- gpu: device.info.gpu,
4814
- // HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
4815
- features: device.features
4816
- };
4817
- }
4818
-
4819
5283
  // dist/modules/picking/picking-uniforms.js
4820
5284
  var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
4821
5285
  var INVALID_INDEX = -1;