@deck.gl/extensions 9.4.0-alpha.1 → 9.4.0-beta.1
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/clip/clip-extension.d.ts +3 -0
- package/dist/clip/clip-extension.d.ts.map +1 -1
- package/dist/clip/clip-extension.js +7 -0
- package/dist/clip/clip-extension.js.map +1 -1
- package/dist/dist.dev.js +1164 -5
- package/dist/index.cjs +2623 -128
- package/dist/index.cjs.map +3 -4
- package/dist/terrain/shader-module.d.ts +16 -2
- package/dist/terrain/shader-module.d.ts.map +1 -1
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist.min.js +1197 -54
- package/package.json +10 -6
- package/src/clip/clip-extension.ts +15 -1
package/dist/dist.dev.js
CHANGED
|
@@ -13,7 +13,11 @@ var __exports__ = (() => {
|
|
|
13
13
|
var __getProtoOf = Object.getPrototypeOf;
|
|
14
14
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
15
15
|
var __commonJS = (cb, mod) => function __require() {
|
|
16
|
-
|
|
16
|
+
try {
|
|
17
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
throw mod = 0, e;
|
|
20
|
+
}
|
|
17
21
|
};
|
|
18
22
|
var __export = (target, all) => {
|
|
19
23
|
for (var name in all)
|
|
@@ -918,8 +922,7 @@ void main() {
|
|
|
918
922
|
*/
|
|
919
923
|
_updateCategoryBitMask(params, extension) {
|
|
920
924
|
const { categorySize } = extension.opts;
|
|
921
|
-
if (!categorySize)
|
|
922
|
-
return;
|
|
925
|
+
if (!categorySize) return;
|
|
923
926
|
const { filterCategories } = this.props;
|
|
924
927
|
const categoryBitMask = new Uint32Array([0, 0, 0, 0]);
|
|
925
928
|
const categoryFilters = categorySize === 1 ? [filterCategories] : filterCategories;
|
|
@@ -1417,7 +1420,7 @@ void main() {
|
|
|
1417
1420
|
var sqrDist = squaredDistance;
|
|
1418
1421
|
var len = length;
|
|
1419
1422
|
var sqrLen = squaredLength;
|
|
1420
|
-
var forEach = function() {
|
|
1423
|
+
var forEach = (function() {
|
|
1421
1424
|
const vec = create();
|
|
1422
1425
|
return function(a, stride, offset, count, fn, arg) {
|
|
1423
1426
|
let i;
|
|
@@ -1444,7 +1447,7 @@ void main() {
|
|
|
1444
1447
|
}
|
|
1445
1448
|
return a;
|
|
1446
1449
|
};
|
|
1447
|
-
}();
|
|
1450
|
+
})();
|
|
1448
1451
|
|
|
1449
1452
|
// ../../node_modules/@luma.gl/shadertools/dist/modules/math/fp64/fp64-utils.js
|
|
1450
1453
|
function fp64ify(a, out = [], startIndex = 0) {
|
|
@@ -1673,6 +1676,462 @@ vec2 sqrt_fp64(vec2 a) {
|
|
|
1673
1676
|
`
|
|
1674
1677
|
);
|
|
1675
1678
|
|
|
1679
|
+
// ../../node_modules/@luma.gl/shadertools/dist/modules/math/fp64/fp64-arithmetic-wgsl-integer.js
|
|
1680
|
+
var fp64arithmeticWGSLInteger = (
|
|
1681
|
+
/* wgsl */
|
|
1682
|
+
`struct Fp64F32Bits {
|
|
1683
|
+
sign: u32,
|
|
1684
|
+
baseExponent: i32,
|
|
1685
|
+
significand: u32,
|
|
1686
|
+
isZero: bool,
|
|
1687
|
+
isInf: bool,
|
|
1688
|
+
isNan: bool,
|
|
1689
|
+
};
|
|
1690
|
+
|
|
1691
|
+
// Decode an f32 as (-1)^sign * significand * 2^baseExponent.
|
|
1692
|
+
fn fp64_decode_f32_bits(bits: u32) -> Fp64F32Bits {
|
|
1693
|
+
let sign = bits >> 31u;
|
|
1694
|
+
let exponentBits = (bits >> 23u) & 0xffu;
|
|
1695
|
+
let fraction = bits & 0x7fffffu;
|
|
1696
|
+
|
|
1697
|
+
if (exponentBits == 0xffu) {
|
|
1698
|
+
return Fp64F32Bits(sign, 0, 0u, false, fraction == 0u, fraction != 0u);
|
|
1699
|
+
}
|
|
1700
|
+
if (exponentBits == 0u) {
|
|
1701
|
+
return Fp64F32Bits(sign, -149, fraction, fraction == 0u, false, false);
|
|
1702
|
+
}
|
|
1703
|
+
return Fp64F32Bits(sign, i32(exponentBits) - 150, 0x800000u | fraction, false, false, false);
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
fn fp64_f32_magnitude_compare(aBits: u32, bBits: u32) -> i32 {
|
|
1707
|
+
let aMagnitude = aBits & 0x7fffffffu;
|
|
1708
|
+
let bMagnitude = bBits & 0x7fffffffu;
|
|
1709
|
+
if (aMagnitude == bMagnitude) {
|
|
1710
|
+
return 0;
|
|
1711
|
+
}
|
|
1712
|
+
return select(-1, 1, aMagnitude > bMagnitude);
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
fn fp64_make_residual_f32_bits(
|
|
1716
|
+
exactSign: u32,
|
|
1717
|
+
exactMagnitude: vec2u,
|
|
1718
|
+
exactBaseExponent: i32,
|
|
1719
|
+
highBits: u32
|
|
1720
|
+
) -> u32 {
|
|
1721
|
+
if (fp64_u64_is_zero(exactMagnitude)) {
|
|
1722
|
+
return 0u;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
let high = fp64_decode_f32_bits(highBits);
|
|
1726
|
+
if (high.isInf || high.isNan) {
|
|
1727
|
+
return exactSign << 31u;
|
|
1728
|
+
}
|
|
1729
|
+
if (high.isZero) {
|
|
1730
|
+
return fp64_make_f32_bits_from_u64(exactSign, exactMagnitude, exactBaseExponent);
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
let commonBaseExponent = min(exactBaseExponent, high.baseExponent);
|
|
1734
|
+
let exactShift = exactBaseExponent - commonBaseExponent;
|
|
1735
|
+
let highShift = high.baseExponent - commonBaseExponent;
|
|
1736
|
+
|
|
1737
|
+
// A normal two-sum/two-product residual never needs a shift this large.
|
|
1738
|
+
// This guard gives deterministic underflow behavior outside that contract.
|
|
1739
|
+
if (exactShift >= 64 || highShift >= 64) {
|
|
1740
|
+
return exactSign << 31u;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
let exactAligned = fp64_u64_shift_left(exactMagnitude, u32(exactShift));
|
|
1744
|
+
let highAligned = fp64_u64_shift_left(vec2u(0u, high.significand), u32(highShift));
|
|
1745
|
+
let comparison = fp64_u64_compare(exactAligned, highAligned);
|
|
1746
|
+
if (comparison == 0) {
|
|
1747
|
+
return 0u;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
var residualSign = exactSign;
|
|
1751
|
+
var residualMagnitude: vec2u;
|
|
1752
|
+
if (comparison > 0) {
|
|
1753
|
+
residualMagnitude = fp64_u64_sub(exactAligned, highAligned);
|
|
1754
|
+
} else {
|
|
1755
|
+
residualSign = exactSign ^ 1u;
|
|
1756
|
+
residualMagnitude = fp64_u64_sub(highAligned, exactAligned);
|
|
1757
|
+
}
|
|
1758
|
+
return fp64_make_f32_bits_from_u64(
|
|
1759
|
+
residualSign,
|
|
1760
|
+
residualMagnitude,
|
|
1761
|
+
commonBaseExponent
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
fn fp64_split_accumulator_bits(
|
|
1766
|
+
sign: u32,
|
|
1767
|
+
magnitude: vec2u,
|
|
1768
|
+
baseExponent: i32
|
|
1769
|
+
) -> vec2u {
|
|
1770
|
+
let highBits = fp64_make_f32_bits_from_u64(sign, magnitude, baseExponent);
|
|
1771
|
+
let lowBits = fp64_make_residual_f32_bits(sign, magnitude, baseExponent, highBits);
|
|
1772
|
+
return vec2u(highBits, lowBits);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
fn fp64_two_sum_integer_bits(aBits: u32, bBits: u32) -> vec2u {
|
|
1776
|
+
let a = fp64_decode_f32_bits(aBits);
|
|
1777
|
+
let b = fp64_decode_f32_bits(bBits);
|
|
1778
|
+
|
|
1779
|
+
if (a.isNan || b.isNan) {
|
|
1780
|
+
return vec2u(0x7fc00000u, 0u);
|
|
1781
|
+
}
|
|
1782
|
+
if (a.isInf || b.isInf) {
|
|
1783
|
+
if (a.isInf && b.isInf && a.sign != b.sign) {
|
|
1784
|
+
return vec2u(0x7fc00000u, 0u);
|
|
1785
|
+
}
|
|
1786
|
+
return select(vec2u(bBits, 0u), vec2u(aBits, 0u), a.isInf);
|
|
1787
|
+
}
|
|
1788
|
+
if (a.isZero && b.isZero) {
|
|
1789
|
+
return vec2u((a.sign & b.sign) << 31u, 0u);
|
|
1790
|
+
}
|
|
1791
|
+
if (a.isZero) {
|
|
1792
|
+
return vec2u(bBits, 0u);
|
|
1793
|
+
}
|
|
1794
|
+
if (b.isZero) {
|
|
1795
|
+
return vec2u(aBits, 0u);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
let exponentDifference = select(
|
|
1799
|
+
b.baseExponent - a.baseExponent,
|
|
1800
|
+
a.baseExponent - b.baseExponent,
|
|
1801
|
+
a.baseExponent >= b.baseExponent
|
|
1802
|
+
);
|
|
1803
|
+
|
|
1804
|
+
// Beyond half an ulp, rounding cannot change the larger operand. Returning
|
|
1805
|
+
// the smaller operand intact also avoids an unbounded integer alignment.
|
|
1806
|
+
// At a power-of-two boundary the spacing below the larger operand is half
|
|
1807
|
+
// the spacing above it, so an opposite-sign gap-25 operand can still change
|
|
1808
|
+
// the rounded high limb. Gap 26 is the first universally safe early-out.
|
|
1809
|
+
if (exponentDifference > 25) {
|
|
1810
|
+
if (fp64_f32_magnitude_compare(aBits, bBits) >= 0) {
|
|
1811
|
+
return vec2u(aBits, bBits);
|
|
1812
|
+
}
|
|
1813
|
+
return vec2u(bBits, aBits);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
let commonBaseExponent = min(a.baseExponent, b.baseExponent);
|
|
1817
|
+
let aMagnitude = fp64_u64_shift_left(
|
|
1818
|
+
vec2u(0u, a.significand),
|
|
1819
|
+
u32(a.baseExponent - commonBaseExponent)
|
|
1820
|
+
);
|
|
1821
|
+
let bMagnitude = fp64_u64_shift_left(
|
|
1822
|
+
vec2u(0u, b.significand),
|
|
1823
|
+
u32(b.baseExponent - commonBaseExponent)
|
|
1824
|
+
);
|
|
1825
|
+
|
|
1826
|
+
var resultSign = a.sign;
|
|
1827
|
+
var resultMagnitude: vec2u;
|
|
1828
|
+
if (a.sign == b.sign) {
|
|
1829
|
+
resultMagnitude = fp64_u64_add(aMagnitude, bMagnitude);
|
|
1830
|
+
} else {
|
|
1831
|
+
let comparison = fp64_u64_compare(aMagnitude, bMagnitude);
|
|
1832
|
+
if (comparison == 0) {
|
|
1833
|
+
return vec2u(0u, 0u);
|
|
1834
|
+
}
|
|
1835
|
+
if (comparison > 0) {
|
|
1836
|
+
resultMagnitude = fp64_u64_sub(aMagnitude, bMagnitude);
|
|
1837
|
+
} else {
|
|
1838
|
+
resultSign = b.sign;
|
|
1839
|
+
resultMagnitude = fp64_u64_sub(bMagnitude, aMagnitude);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
return fp64_split_accumulator_bits(resultSign, resultMagnitude, commonBaseExponent);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
fn fp64_two_sum_integer(a: f32, b: f32) -> vec2f {
|
|
1847
|
+
let resultBits = fp64_two_sum_integer_bits(bitcast<u32>(a), bitcast<u32>(b));
|
|
1848
|
+
return vec2f(bitcast<f32>(resultBits.x), bitcast<f32>(resultBits.y));
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
fn fp64_multiply_significands(a: u32, b: u32) -> vec2u {
|
|
1852
|
+
let aLow = a & 0xffffu;
|
|
1853
|
+
let aHigh = a >> 16u;
|
|
1854
|
+
let bLow = b & 0xffffu;
|
|
1855
|
+
let bHigh = b >> 16u;
|
|
1856
|
+
let lowProduct = aLow * bLow;
|
|
1857
|
+
let crossProduct = aLow * bHigh + aHigh * bLow;
|
|
1858
|
+
let highProduct = aHigh * bHigh;
|
|
1859
|
+
|
|
1860
|
+
var result = vec2u(0u, lowProduct);
|
|
1861
|
+
result = fp64_u64_add(
|
|
1862
|
+
result,
|
|
1863
|
+
fp64_u64_shift_left(vec2u(0u, crossProduct), 16u)
|
|
1864
|
+
);
|
|
1865
|
+
result = fp64_u64_add(result, vec2u(highProduct, 0u));
|
|
1866
|
+
return result;
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
fn fp64_two_prod_integer_bits(aBits: u32, bBits: u32) -> vec2u {
|
|
1870
|
+
let a = fp64_decode_f32_bits(aBits);
|
|
1871
|
+
let b = fp64_decode_f32_bits(bBits);
|
|
1872
|
+
let resultSign = a.sign ^ b.sign;
|
|
1873
|
+
|
|
1874
|
+
if (a.isNan || b.isNan || ((a.isZero || b.isZero) && (a.isInf || b.isInf))) {
|
|
1875
|
+
return vec2u(0x7fc00000u, 0u);
|
|
1876
|
+
}
|
|
1877
|
+
if (a.isInf || b.isInf) {
|
|
1878
|
+
return vec2u((resultSign << 31u) | 0x7f800000u, resultSign << 31u);
|
|
1879
|
+
}
|
|
1880
|
+
if (a.isZero || b.isZero) {
|
|
1881
|
+
return vec2u(resultSign << 31u, resultSign << 31u);
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
let magnitude = fp64_multiply_significands(a.significand, b.significand);
|
|
1885
|
+
return fp64_split_accumulator_bits(
|
|
1886
|
+
resultSign,
|
|
1887
|
+
magnitude,
|
|
1888
|
+
a.baseExponent + b.baseExponent
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
fn fp64_two_prod_integer(a: f32, b: f32) -> vec2f {
|
|
1893
|
+
let resultBits = fp64_two_prod_integer_bits(bitcast<u32>(a), bitcast<u32>(b));
|
|
1894
|
+
return vec2f(bitcast<f32>(resultBits.x), bitcast<f32>(resultBits.y));
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
fn fp64_round_add_integer(a: f32, b: f32) -> f32 {
|
|
1898
|
+
return fp64_two_sum_integer(a, b).x;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
fn fp64_round_mul_integer(a: f32, b: f32) -> f32 {
|
|
1902
|
+
return fp64_two_prod_integer(a, b).x;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
1906
|
+
fn fp64_f32_finite_exponent(value: Fp64F32Bits) -> i32 {
|
|
1907
|
+
let mostSignificantBit = 31u - countLeadingZeros(value.significand);
|
|
1908
|
+
return value.baseExponent + i32(mostSignificantBit);
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
fn fp64_scale_f32_integer(value: f32, exponent: i32) -> f32 {
|
|
1912
|
+
let decoded = fp64_decode_f32_bits(bitcast<u32>(value));
|
|
1913
|
+
if (decoded.isZero || decoded.isInf || decoded.isNan) {
|
|
1914
|
+
return value;
|
|
1915
|
+
}
|
|
1916
|
+
let resultBits = fp64_make_f32_bits_from_u64(
|
|
1917
|
+
decoded.sign,
|
|
1918
|
+
vec2u(0u, decoded.significand),
|
|
1919
|
+
decoded.baseExponent + exponent
|
|
1920
|
+
);
|
|
1921
|
+
return bitcast<f32>(resultBits);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
// Divide normalized significands so the hardware operation cannot overflow,
|
|
1925
|
+
// underflow, or flush a subnormal result. Reapply the exponent with integer
|
|
1926
|
+
// packing, which also produces subnormal correction limbs without relying on
|
|
1927
|
+
// floating-point arithmetic to preserve them.
|
|
1928
|
+
fn fp64_divide_f32_integer(aValue: f32, bValue: f32) -> f32 {
|
|
1929
|
+
let a = fp64_decode_f32_bits(bitcast<u32>(aValue));
|
|
1930
|
+
let b = fp64_decode_f32_bits(bitcast<u32>(bValue));
|
|
1931
|
+
if (a.isZero || b.isZero || a.isInf || b.isInf || a.isNan || b.isNan) {
|
|
1932
|
+
return aValue / bValue;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
let aMostSignificantBit = 31u - countLeadingZeros(a.significand);
|
|
1936
|
+
let bMostSignificantBit = 31u - countLeadingZeros(b.significand);
|
|
1937
|
+
let normalizedABits = fp64_make_f32_bits_from_u64(
|
|
1938
|
+
a.sign,
|
|
1939
|
+
vec2u(0u, a.significand),
|
|
1940
|
+
-i32(aMostSignificantBit)
|
|
1941
|
+
);
|
|
1942
|
+
let normalizedBBits = fp64_make_f32_bits_from_u64(
|
|
1943
|
+
b.sign,
|
|
1944
|
+
vec2u(0u, b.significand),
|
|
1945
|
+
-i32(bMostSignificantBit)
|
|
1946
|
+
);
|
|
1947
|
+
let normalizedQuotient = bitcast<f32>(normalizedABits) / bitcast<f32>(normalizedBBits);
|
|
1948
|
+
let quotient = fp64_decode_f32_bits(bitcast<u32>(normalizedQuotient));
|
|
1949
|
+
let exponentShift =
|
|
1950
|
+
a.baseExponent + i32(aMostSignificantBit) -
|
|
1951
|
+
b.baseExponent - i32(bMostSignificantBit);
|
|
1952
|
+
let quotientBits = fp64_make_f32_bits_from_u64(
|
|
1953
|
+
quotient.sign,
|
|
1954
|
+
vec2u(0u, quotient.significand),
|
|
1955
|
+
quotient.baseExponent + exponentShift
|
|
1956
|
+
);
|
|
1957
|
+
return bitcast<f32>(quotientBits);
|
|
1958
|
+
}
|
|
1959
|
+
#endif
|
|
1960
|
+
|
|
1961
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
1962
|
+
fn split(a: f32) -> vec2f {
|
|
1963
|
+
let aBits = bitcast<u32>(a);
|
|
1964
|
+
let decoded = fp64_decode_f32_bits(aBits);
|
|
1965
|
+
if (decoded.isZero || decoded.isInf || decoded.isNan) {
|
|
1966
|
+
return vec2f(a, 0.0);
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
var roundedHigh = decoded.significand >> 12u;
|
|
1970
|
+
let remainder = decoded.significand & 0xfffu;
|
|
1971
|
+
if (remainder > 0x800u || (remainder == 0x800u && (roundedHigh & 1u) == 1u)) {
|
|
1972
|
+
roundedHigh = roundedHigh + 1u;
|
|
1973
|
+
}
|
|
1974
|
+
var highMagnitude = vec2u(0u, roundedHigh << 12u);
|
|
1975
|
+
var highBits = fp64_make_f32_bits_from_u64(
|
|
1976
|
+
decoded.sign,
|
|
1977
|
+
highMagnitude,
|
|
1978
|
+
decoded.baseExponent
|
|
1979
|
+
);
|
|
1980
|
+
// Rounding the high limb of a maximum-exponent value can overflow even
|
|
1981
|
+
// though the original value is finite. Truncate only in that boundary case
|
|
1982
|
+
// so split remains an exact finite decomposition.
|
|
1983
|
+
if (fp64_decode_f32_bits(highBits).isInf) {
|
|
1984
|
+
roundedHigh = decoded.significand >> 12u;
|
|
1985
|
+
highMagnitude = vec2u(0u, roundedHigh << 12u);
|
|
1986
|
+
highBits = fp64_make_f32_bits_from_u64(
|
|
1987
|
+
decoded.sign,
|
|
1988
|
+
highMagnitude,
|
|
1989
|
+
decoded.baseExponent
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
let lowBits = fp64_make_residual_f32_bits(
|
|
1993
|
+
decoded.sign,
|
|
1994
|
+
vec2u(0u, decoded.significand),
|
|
1995
|
+
decoded.baseExponent,
|
|
1996
|
+
highBits
|
|
1997
|
+
);
|
|
1998
|
+
return vec2f(bitcast<f32>(highBits), bitcast<f32>(lowBits));
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
fn split2(a: vec2f) -> vec2f {
|
|
2002
|
+
var result = split(a.x);
|
|
2003
|
+
result.y = fp64_round_add_integer(result.y, a.y);
|
|
2004
|
+
return result;
|
|
2005
|
+
}
|
|
2006
|
+
#endif
|
|
2007
|
+
|
|
2008
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
2009
|
+
fn quickTwoSum(a: f32, b: f32) -> vec2f {
|
|
2010
|
+
return fp64_two_sum_integer(a, b);
|
|
2011
|
+
}
|
|
2012
|
+
#endif
|
|
2013
|
+
|
|
2014
|
+
fn twoSum(a: f32, b: f32) -> vec2f {
|
|
2015
|
+
return fp64_two_sum_integer(a, b);
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
fn twoSub(a: f32, b: f32) -> vec2f {
|
|
2019
|
+
let bBits = bitcast<u32>(b) ^ 0x80000000u;
|
|
2020
|
+
let resultBits = fp64_two_sum_integer_bits(bitcast<u32>(a), bBits);
|
|
2021
|
+
return vec2f(bitcast<f32>(resultBits.x), bitcast<f32>(resultBits.y));
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
2025
|
+
fn twoSqr(a: f32) -> vec2f {
|
|
2026
|
+
return fp64_two_prod_integer(a, a);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
fn twoProd(a: f32, b: f32) -> vec2f {
|
|
2030
|
+
return fp64_two_prod_integer(a, b);
|
|
2031
|
+
}
|
|
2032
|
+
#endif
|
|
2033
|
+
|
|
2034
|
+
fn sum_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
2035
|
+
var sum = fp64_two_sum_integer(a.x, b.x);
|
|
2036
|
+
let lowSum = fp64_two_sum_integer(a.y, b.y);
|
|
2037
|
+
sum.y = fp64_round_add_integer(sum.y, lowSum.x);
|
|
2038
|
+
sum = fp64_two_sum_integer(sum.x, sum.y);
|
|
2039
|
+
sum.y = fp64_round_add_integer(sum.y, lowSum.y);
|
|
2040
|
+
return fp64_two_sum_integer(sum.x, sum.y);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
fn sub_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
2044
|
+
let negatedB = vec2f(
|
|
2045
|
+
bitcast<f32>(bitcast<u32>(b.x) ^ 0x80000000u),
|
|
2046
|
+
bitcast<f32>(bitcast<u32>(b.y) ^ 0x80000000u)
|
|
2047
|
+
);
|
|
2048
|
+
return sum_fp64(a, negatedB);
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
fn mul_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
2052
|
+
var product = fp64_two_prod_integer(a.x, b.x);
|
|
2053
|
+
let crossProduct1 = fp64_round_mul_integer(a.x, b.y);
|
|
2054
|
+
product.y = fp64_round_add_integer(product.y, crossProduct1);
|
|
2055
|
+
product = fp64_two_sum_integer(product.x, product.y);
|
|
2056
|
+
let crossProduct2 = fp64_round_mul_integer(a.y, b.x);
|
|
2057
|
+
product.y = fp64_round_add_integer(product.y, crossProduct2);
|
|
2058
|
+
return fp64_two_sum_integer(product.x, product.y);
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
2062
|
+
fn fp64_scale_fp64_integer(value: vec2f, exponent: i32) -> vec2f {
|
|
2063
|
+
let high = fp64_scale_f32_integer(value.x, exponent);
|
|
2064
|
+
let low = fp64_scale_f32_integer(value.y, exponent);
|
|
2065
|
+
return sum_fp64(vec2f(high, 0.0), vec2f(low, 0.0));
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
fn fp64_div_fp64_normalized(a: vec2f, b: vec2f) -> vec2f {
|
|
2069
|
+
let quotientHigh = fp64_divide_f32_integer(a.x, b.x);
|
|
2070
|
+
var quotient = vec2f(quotientHigh, 0.0);
|
|
2071
|
+
|
|
2072
|
+
let remainder = sub_fp64(a, mul_fp64(b, quotient));
|
|
2073
|
+
let quotientLow = fp64_divide_f32_integer(remainder.x, b.x);
|
|
2074
|
+
quotient = sum_fp64(quotient, vec2f(quotientLow, 0.0));
|
|
2075
|
+
|
|
2076
|
+
let secondRemainder = sub_fp64(a, mul_fp64(b, quotient));
|
|
2077
|
+
let correction = fp64_divide_f32_integer(secondRemainder.x, b.x);
|
|
2078
|
+
return sum_fp64(quotient, vec2f(correction, 0.0));
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
fn div_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
2082
|
+
let decodedA = fp64_decode_f32_bits(bitcast<u32>(a.x));
|
|
2083
|
+
let decodedB = fp64_decode_f32_bits(bitcast<u32>(b.x));
|
|
2084
|
+
if (
|
|
2085
|
+
decodedA.isZero || decodedB.isZero ||
|
|
2086
|
+
decodedA.isInf || decodedB.isInf ||
|
|
2087
|
+
decodedA.isNan || decodedB.isNan
|
|
2088
|
+
) {
|
|
2089
|
+
return fp64_div_fp64_normalized(a, b);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
let exponentA = fp64_f32_finite_exponent(decodedA);
|
|
2093
|
+
let exponentB = fp64_f32_finite_exponent(decodedB);
|
|
2094
|
+
// Correct the quotient near unity so b * q and the remainder stay clear of
|
|
2095
|
+
// both f32 underflow and overflow. The exponent difference is applied once.
|
|
2096
|
+
let normalizedA = fp64_scale_fp64_integer(a, -exponentA);
|
|
2097
|
+
let normalizedB = fp64_scale_fp64_integer(b, -exponentB);
|
|
2098
|
+
let normalizedQuotient = fp64_div_fp64_normalized(normalizedA, normalizedB);
|
|
2099
|
+
return fp64_scale_fp64_integer(normalizedQuotient, exponentA - exponentB);
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
fn fp64_sqrt_fp64_normalized(a: vec2f) -> vec2f {
|
|
2103
|
+
let estimate = sqrt(a.x);
|
|
2104
|
+
let difference = sub_fp64(a, fp64_two_prod_integer(estimate, estimate)).x;
|
|
2105
|
+
let denominator = fp64_round_add_integer(estimate, estimate);
|
|
2106
|
+
let correction = fp64_divide_f32_integer(difference, denominator);
|
|
2107
|
+
return sum_fp64(vec2f(estimate, 0.0), vec2f(correction, 0.0));
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
fn sqrt_fp64(a: vec2f) -> vec2f {
|
|
2111
|
+
let decoded = fp64_decode_f32_bits(bitcast<u32>(a.x));
|
|
2112
|
+
let decodedLow = fp64_decode_f32_bits(bitcast<u32>(a.y));
|
|
2113
|
+
if (decoded.isZero && decodedLow.isZero) {
|
|
2114
|
+
return vec2f(0.0, 0.0);
|
|
2115
|
+
}
|
|
2116
|
+
if (decoded.sign == 1u) {
|
|
2117
|
+
let nanValue = fp64_nan(a.x);
|
|
2118
|
+
return vec2f(nanValue, nanValue);
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
if (decoded.isInf || decoded.isNan) {
|
|
2122
|
+
return fp64_sqrt_fp64_normalized(a);
|
|
2123
|
+
}
|
|
2124
|
+
let exponent = fp64_f32_finite_exponent(decoded);
|
|
2125
|
+
// An even scale lets the final square-root rescale use an integer exponent.
|
|
2126
|
+
let evenExponent = exponent - (exponent & 1);
|
|
2127
|
+
let normalizedA = fp64_scale_fp64_integer(a, -evenExponent);
|
|
2128
|
+
let normalizedRoot = fp64_sqrt_fp64_normalized(normalizedA);
|
|
2129
|
+
return fp64_scale_fp64_integer(normalizedRoot, evenExponent / 2);
|
|
2130
|
+
}
|
|
2131
|
+
#endif
|
|
2132
|
+
`
|
|
2133
|
+
);
|
|
2134
|
+
|
|
1676
2135
|
// ../../node_modules/@luma.gl/shadertools/dist/modules/math/fp64/fp64-arithmetic-wgsl.js
|
|
1677
2136
|
var fp64arithmeticWGSL = (
|
|
1678
2137
|
/* wgsl */
|
|
@@ -1683,11 +2142,608 @@ vec2 sqrt_fp64(vec2 a) {
|
|
|
1683
2142
|
|
|
1684
2143
|
@group(0) @binding(auto) var<uniform> fp64arithmetic : Fp64ArithmeticUniforms;
|
|
1685
2144
|
|
|
2145
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2146
|
+
struct Fp64Bits {
|
|
2147
|
+
sign: u32,
|
|
2148
|
+
exponent: i32,
|
|
2149
|
+
significand: vec2u,
|
|
2150
|
+
isZero: bool,
|
|
2151
|
+
isInf: bool,
|
|
2152
|
+
isNan: bool,
|
|
2153
|
+
};
|
|
2154
|
+
#endif
|
|
2155
|
+
|
|
2156
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
1686
2157
|
fn fp64_nan(seed: f32) -> f32 {
|
|
1687
2158
|
let nanBits = 0x7fc00000u | select(0u, 1u, seed < 0.0);
|
|
1688
2159
|
return bitcast<f32>(nanBits);
|
|
1689
2160
|
}
|
|
2161
|
+
#endif
|
|
2162
|
+
|
|
2163
|
+
fn fp64_u64_is_zero(value: vec2u) -> bool {
|
|
2164
|
+
return value.x == 0u && value.y == 0u;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
fn fp64_u64_compare(a: vec2u, b: vec2u) -> i32 {
|
|
2168
|
+
if (a.x != b.x) {
|
|
2169
|
+
return select(-1, 1, a.x > b.x);
|
|
2170
|
+
}
|
|
2171
|
+
if (a.y != b.y) {
|
|
2172
|
+
return select(-1, 1, a.y > b.y);
|
|
2173
|
+
}
|
|
2174
|
+
return 0;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
fn fp64_u64_add(a: vec2u, b: vec2u) -> vec2u {
|
|
2178
|
+
let low = a.y + b.y;
|
|
2179
|
+
let carry = select(0u, 1u, low < a.y);
|
|
2180
|
+
return vec2u(a.x + b.x + carry, low);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
fn fp64_u64_sub(a: vec2u, b: vec2u) -> vec2u {
|
|
2184
|
+
let borrow = select(0u, 1u, a.y < b.y);
|
|
2185
|
+
return vec2u(a.x - b.x - borrow, a.y - b.y);
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
fn fp64_u64_shift_left(value: vec2u, shift: u32) -> vec2u {
|
|
2189
|
+
if (shift == 0u) {
|
|
2190
|
+
return value;
|
|
2191
|
+
}
|
|
2192
|
+
if (shift < 32u) {
|
|
2193
|
+
return vec2u((value.x << shift) | (value.y >> (32u - shift)), value.y << shift);
|
|
2194
|
+
}
|
|
2195
|
+
if (shift == 32u) {
|
|
2196
|
+
return vec2u(value.y, 0u);
|
|
2197
|
+
}
|
|
2198
|
+
if (shift < 64u) {
|
|
2199
|
+
return vec2u(value.y << (shift - 32u), 0u);
|
|
2200
|
+
}
|
|
2201
|
+
return vec2u(0u);
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
fn fp64_u64_shift_right(value: vec2u, shift: u32) -> vec2u {
|
|
2205
|
+
if (shift == 0u) {
|
|
2206
|
+
return value;
|
|
2207
|
+
}
|
|
2208
|
+
if (shift < 32u) {
|
|
2209
|
+
return vec2u(value.x >> shift, (value.y >> shift) | (value.x << (32u - shift)));
|
|
2210
|
+
}
|
|
2211
|
+
if (shift == 32u) {
|
|
2212
|
+
return vec2u(0u, value.x);
|
|
2213
|
+
}
|
|
2214
|
+
if (shift < 64u) {
|
|
2215
|
+
return vec2u(0u, value.x >> (shift - 32u));
|
|
2216
|
+
}
|
|
2217
|
+
return vec2u(0u);
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
fn fp64_u64_get_bit(value: vec2u, bitIndex: u32) -> bool {
|
|
2221
|
+
if (bitIndex >= 64u) {
|
|
2222
|
+
return false;
|
|
2223
|
+
}
|
|
2224
|
+
if (bitIndex >= 32u) {
|
|
2225
|
+
return ((value.x >> (bitIndex - 32u)) & 1u) != 0u;
|
|
2226
|
+
}
|
|
2227
|
+
return ((value.y >> bitIndex) & 1u) != 0u;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
fn fp64_u64_has_bits_below(value: vec2u, bitCount: u32) -> bool {
|
|
2231
|
+
if (bitCount == 0u) {
|
|
2232
|
+
return false;
|
|
2233
|
+
}
|
|
2234
|
+
if (bitCount >= 64u) {
|
|
2235
|
+
return !fp64_u64_is_zero(value);
|
|
2236
|
+
}
|
|
2237
|
+
if (bitCount > 32u) {
|
|
2238
|
+
let highBitCount = bitCount - 32u;
|
|
2239
|
+
let highMask = (1u << highBitCount) - 1u;
|
|
2240
|
+
return value.y != 0u || (value.x & highMask) != 0u;
|
|
2241
|
+
}
|
|
2242
|
+
if (bitCount == 32u) {
|
|
2243
|
+
return value.y != 0u;
|
|
2244
|
+
}
|
|
2245
|
+
let lowMask = (1u << bitCount) - 1u;
|
|
2246
|
+
return (value.y & lowMask) != 0u;
|
|
2247
|
+
}
|
|
1690
2248
|
|
|
2249
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2250
|
+
fn fp64_u64_shift_right_sticky(value: vec2u, shift: u32) -> vec2u {
|
|
2251
|
+
var shifted = fp64_u64_shift_right(value, shift);
|
|
2252
|
+
if (fp64_u64_has_bits_below(value, shift)) {
|
|
2253
|
+
shifted.y = shifted.y | 1u;
|
|
2254
|
+
}
|
|
2255
|
+
return shifted;
|
|
2256
|
+
}
|
|
2257
|
+
#endif
|
|
2258
|
+
|
|
2259
|
+
fn fp64_u64_count_leading_zeros(value: vec2u) -> u32 {
|
|
2260
|
+
if (value.x != 0u) {
|
|
2261
|
+
return countLeadingZeros(value.x);
|
|
2262
|
+
}
|
|
2263
|
+
return 32u + countLeadingZeros(value.y);
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
fn fp64_round_shift_right_to_u32(value: vec2u, shift: u32) -> u32 {
|
|
2267
|
+
if (shift == 0u) {
|
|
2268
|
+
return value.y;
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
let truncated = fp64_u64_shift_right(value, shift);
|
|
2272
|
+
var rounded = truncated.y;
|
|
2273
|
+
let guard = fp64_u64_get_bit(value, shift - 1u);
|
|
2274
|
+
let hasTrailingBits = fp64_u64_has_bits_below(value, shift - 1u);
|
|
2275
|
+
if (guard && (hasTrailingBits || (rounded & 1u) == 1u)) {
|
|
2276
|
+
rounded = rounded + 1u;
|
|
2277
|
+
}
|
|
2278
|
+
return rounded;
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2282
|
+
fn fp64_round_shift_right(value: vec2u, shift: u32) -> vec2u {
|
|
2283
|
+
if (shift == 0u) {
|
|
2284
|
+
return value;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
var rounded = fp64_u64_shift_right(value, shift);
|
|
2288
|
+
let guard = fp64_u64_get_bit(value, shift - 1u);
|
|
2289
|
+
let hasTrailingBits = fp64_u64_has_bits_below(value, shift - 1u);
|
|
2290
|
+
if (guard && (hasTrailingBits || (rounded.y & 1u) == 1u)) {
|
|
2291
|
+
rounded = fp64_u64_add(rounded, vec2u(0u, 1u));
|
|
2292
|
+
}
|
|
2293
|
+
return rounded;
|
|
2294
|
+
}
|
|
2295
|
+
#endif
|
|
2296
|
+
|
|
2297
|
+
fn fp64_make_f32_bits_from_u64(sign: u32, significand: vec2u, baseExponent: i32) -> u32 {
|
|
2298
|
+
if (fp64_u64_is_zero(significand)) {
|
|
2299
|
+
return sign << 31u;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
let leadingZeros = fp64_u64_count_leading_zeros(significand);
|
|
2303
|
+
let mostSignificantBit = 63u - leadingZeros;
|
|
2304
|
+
var exponent = baseExponent + i32(mostSignificantBit);
|
|
2305
|
+
|
|
2306
|
+
if (exponent > 127) {
|
|
2307
|
+
return (sign << 31u) | 0x7f800000u;
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
if (exponent >= -126) {
|
|
2311
|
+
let shift = i32(mostSignificantBit) - 23;
|
|
2312
|
+
var significand24: u32;
|
|
2313
|
+
if (shift > 0) {
|
|
2314
|
+
significand24 = fp64_round_shift_right_to_u32(significand, u32(shift));
|
|
2315
|
+
} else {
|
|
2316
|
+
significand24 = fp64_u64_shift_left(significand, u32(-shift)).y;
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
if (significand24 >= 0x1000000u) {
|
|
2320
|
+
significand24 = significand24 >> 1u;
|
|
2321
|
+
exponent = exponent + 1;
|
|
2322
|
+
if (exponent > 127) {
|
|
2323
|
+
return (sign << 31u) | 0x7f800000u;
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
return (sign << 31u) | (u32(exponent + 127) << 23u) | (significand24 & 0x7fffffu);
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
let scaleExponent = baseExponent + 149;
|
|
2331
|
+
var mantissa: u32;
|
|
2332
|
+
if (scaleExponent >= 0) {
|
|
2333
|
+
mantissa = fp64_u64_shift_left(significand, u32(scaleExponent)).y;
|
|
2334
|
+
} else {
|
|
2335
|
+
mantissa = fp64_round_shift_right_to_u32(significand, u32(-scaleExponent));
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
if (mantissa >= 0x800000u) {
|
|
2339
|
+
return (sign << 31u) | 0x00800000u;
|
|
2340
|
+
}
|
|
2341
|
+
return (sign << 31u) | mantissa;
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2345
|
+
fn fp64_decode_bits(bits: vec2u) -> Fp64Bits {
|
|
2346
|
+
let sign = bits.x >> 31u;
|
|
2347
|
+
let exponentBits = (bits.x >> 20u) & 0x7ffu;
|
|
2348
|
+
let fractionHigh = bits.x & 0xfffffu;
|
|
2349
|
+
let fractionLow = bits.y;
|
|
2350
|
+
let fraction = vec2u(fractionHigh, fractionLow);
|
|
2351
|
+
|
|
2352
|
+
if (exponentBits == 0x7ffu) {
|
|
2353
|
+
let isInf = fp64_u64_is_zero(fraction);
|
|
2354
|
+
return Fp64Bits(sign, 0, vec2u(0u), false, isInf, !isInf);
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
if (exponentBits == 0u) {
|
|
2358
|
+
let isZero = fp64_u64_is_zero(fraction);
|
|
2359
|
+
return Fp64Bits(sign, -1022, fraction, isZero, false, false);
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
return Fp64Bits(sign, i32(exponentBits) - 1023, vec2u((1u << 20u) | fractionHigh, fractionLow), false, false, false);
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
fn fp64_finite_magnitude_compare(a: Fp64Bits, b: Fp64Bits) -> i32 {
|
|
2366
|
+
if (a.exponent != b.exponent) {
|
|
2367
|
+
return select(-1, 1, a.exponent > b.exponent);
|
|
2368
|
+
}
|
|
2369
|
+
return fp64_u64_compare(a.significand, b.significand);
|
|
2370
|
+
}
|
|
2371
|
+
#endif
|
|
2372
|
+
|
|
2373
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2374
|
+
struct Fp64RawF32Bits {
|
|
2375
|
+
sign: u32,
|
|
2376
|
+
baseExponent: i32,
|
|
2377
|
+
significand: u32,
|
|
2378
|
+
isZero: bool,
|
|
2379
|
+
isInf: bool,
|
|
2380
|
+
isNan: bool,
|
|
2381
|
+
};
|
|
2382
|
+
|
|
2383
|
+
// Decode an f32 as (-1)^sign * significand * 2^baseExponent. This shared
|
|
2384
|
+
// integer representation lets normalization remain independent of the
|
|
2385
|
+
// selected double-single arithmetic implementation.
|
|
2386
|
+
fn fp64_decode_raw_f32_bits(bits: u32) -> Fp64RawF32Bits {
|
|
2387
|
+
let sign = bits >> 31u;
|
|
2388
|
+
let exponentBits = (bits >> 23u) & 0xffu;
|
|
2389
|
+
let fraction = bits & 0x7fffffu;
|
|
2390
|
+
|
|
2391
|
+
if (exponentBits == 0xffu) {
|
|
2392
|
+
return Fp64RawF32Bits(sign, 0, 0u, false, fraction == 0u, fraction != 0u);
|
|
2393
|
+
}
|
|
2394
|
+
if (exponentBits == 0u) {
|
|
2395
|
+
return Fp64RawF32Bits(sign, -149, fraction, fraction == 0u, false, false);
|
|
2396
|
+
}
|
|
2397
|
+
return Fp64RawF32Bits(
|
|
2398
|
+
sign,
|
|
2399
|
+
i32(exponentBits) - 150,
|
|
2400
|
+
0x800000u | fraction,
|
|
2401
|
+
false,
|
|
2402
|
+
false,
|
|
2403
|
+
false
|
|
2404
|
+
);
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
fn fp64_raw_f32_magnitude_compare(aBits: u32, bBits: u32) -> i32 {
|
|
2408
|
+
let aMagnitude = aBits & 0x7fffffffu;
|
|
2409
|
+
let bMagnitude = bBits & 0x7fffffffu;
|
|
2410
|
+
if (aMagnitude == bMagnitude) {
|
|
2411
|
+
return 0;
|
|
2412
|
+
}
|
|
2413
|
+
return select(-1, 1, aMagnitude > bMagnitude);
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
fn fp64_make_raw_residual_f32_bits(
|
|
2417
|
+
exactSign: u32,
|
|
2418
|
+
exactMagnitude: vec2u,
|
|
2419
|
+
exactBaseExponent: i32,
|
|
2420
|
+
highBits: u32
|
|
2421
|
+
) -> u32 {
|
|
2422
|
+
if (fp64_u64_is_zero(exactMagnitude)) {
|
|
2423
|
+
return 0u;
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
let high = fp64_decode_raw_f32_bits(highBits);
|
|
2427
|
+
if (high.isInf || high.isNan) {
|
|
2428
|
+
return 0u;
|
|
2429
|
+
}
|
|
2430
|
+
if (high.isZero) {
|
|
2431
|
+
return fp64_make_f32_bits_from_u64(exactSign, exactMagnitude, exactBaseExponent);
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
let commonBaseExponent = min(exactBaseExponent, high.baseExponent);
|
|
2435
|
+
let exactShift = exactBaseExponent - commonBaseExponent;
|
|
2436
|
+
let highShift = high.baseExponent - commonBaseExponent;
|
|
2437
|
+
if (exactShift >= 64 || highShift >= 64) {
|
|
2438
|
+
return 0u;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
let exactAligned = fp64_u64_shift_left(exactMagnitude, u32(exactShift));
|
|
2442
|
+
let highAligned = fp64_u64_shift_left(vec2u(0u, high.significand), u32(highShift));
|
|
2443
|
+
let comparison = fp64_u64_compare(exactAligned, highAligned);
|
|
2444
|
+
if (comparison == 0) {
|
|
2445
|
+
return 0u;
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
var residualSign = exactSign;
|
|
2449
|
+
var residualMagnitude: vec2u;
|
|
2450
|
+
if (comparison > 0) {
|
|
2451
|
+
residualMagnitude = fp64_u64_sub(exactAligned, highAligned);
|
|
2452
|
+
} else {
|
|
2453
|
+
residualSign = exactSign ^ 1u;
|
|
2454
|
+
residualMagnitude = fp64_u64_sub(highAligned, exactAligned);
|
|
2455
|
+
}
|
|
2456
|
+
return fp64_make_f32_bits_from_u64(
|
|
2457
|
+
residualSign,
|
|
2458
|
+
residualMagnitude,
|
|
2459
|
+
commonBaseExponent
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
fn fp64_split_raw_accumulator_bits(
|
|
2464
|
+
sign: u32,
|
|
2465
|
+
magnitude: vec2u,
|
|
2466
|
+
baseExponent: i32
|
|
2467
|
+
) -> vec2u {
|
|
2468
|
+
if (fp64_u64_is_zero(magnitude)) {
|
|
2469
|
+
return vec2u(0u);
|
|
2470
|
+
}
|
|
2471
|
+
let highBits = fp64_make_f32_bits_from_u64(sign, magnitude, baseExponent);
|
|
2472
|
+
let rawLowBits = fp64_make_raw_residual_f32_bits(sign, magnitude, baseExponent, highBits);
|
|
2473
|
+
let lowBits = select(rawLowBits, 0u, (rawLowBits & 0x7fffffffu) == 0u);
|
|
2474
|
+
if ((highBits & 0x7fffffffu) == 0u && (lowBits & 0x7fffffffu) == 0u) {
|
|
2475
|
+
return vec2u(0u);
|
|
2476
|
+
}
|
|
2477
|
+
return vec2u(highBits, lowBits);
|
|
2478
|
+
}
|
|
2479
|
+
#endif
|
|
2480
|
+
|
|
2481
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2482
|
+
// Round an arithmetic accumulator to binary64 before splitting it. The
|
|
2483
|
+
// aligned add/subtract paths retain three guard bits plus a sticky bit, which
|
|
2484
|
+
// is sufficient for round-to-nearest-even at the binary64 boundary.
|
|
2485
|
+
fn fp64_split_binary64_accumulator_bits(
|
|
2486
|
+
sign: u32,
|
|
2487
|
+
magnitude: vec2u,
|
|
2488
|
+
baseExponent: i32
|
|
2489
|
+
) -> vec2u {
|
|
2490
|
+
if (fp64_u64_is_zero(magnitude)) {
|
|
2491
|
+
return vec2u(0u);
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
let mostSignificantBit = 63u - fp64_u64_count_leading_zeros(magnitude);
|
|
2495
|
+
let exponent = baseExponent + i32(mostSignificantBit);
|
|
2496
|
+
if (exponent > 1023) {
|
|
2497
|
+
return vec2u((sign << 31u) | 0x7f800000u, 0u);
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
var roundedMagnitude = magnitude;
|
|
2501
|
+
var roundedBaseExponent = baseExponent;
|
|
2502
|
+
if (exponent >= -1022) {
|
|
2503
|
+
if (mostSignificantBit > 52u) {
|
|
2504
|
+
let shift = mostSignificantBit - 52u;
|
|
2505
|
+
roundedMagnitude = fp64_round_shift_right(magnitude, shift);
|
|
2506
|
+
roundedBaseExponent = baseExponent + i32(shift);
|
|
2507
|
+
}
|
|
2508
|
+
} else {
|
|
2509
|
+
let shift = -1074 - baseExponent;
|
|
2510
|
+
if (shift > 0) {
|
|
2511
|
+
roundedMagnitude = fp64_round_shift_right(magnitude, u32(shift));
|
|
2512
|
+
roundedBaseExponent = -1074;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
if (fp64_u64_is_zero(roundedMagnitude)) {
|
|
2517
|
+
return vec2u(0u);
|
|
2518
|
+
}
|
|
2519
|
+
return fp64_split_raw_accumulator_bits(sign, roundedMagnitude, roundedBaseExponent);
|
|
2520
|
+
}
|
|
2521
|
+
#endif
|
|
2522
|
+
|
|
2523
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
2524
|
+
fn fp64_add_raw_f32_bits(aBits: u32, bBits: u32) -> vec2u {
|
|
2525
|
+
let a = fp64_decode_raw_f32_bits(aBits);
|
|
2526
|
+
let b = fp64_decode_raw_f32_bits(bBits);
|
|
2527
|
+
|
|
2528
|
+
if (a.isNan || b.isNan) {
|
|
2529
|
+
return vec2u(0x7fc00000u, 0u);
|
|
2530
|
+
}
|
|
2531
|
+
if (a.isInf || b.isInf) {
|
|
2532
|
+
if (a.isInf && b.isInf && a.sign != b.sign) {
|
|
2533
|
+
return vec2u(0x7fc00000u, 0u);
|
|
2534
|
+
}
|
|
2535
|
+
return select(vec2u(bBits, 0u), vec2u(aBits, 0u), a.isInf);
|
|
2536
|
+
}
|
|
2537
|
+
if (a.isZero && b.isZero) {
|
|
2538
|
+
return vec2u(0u);
|
|
2539
|
+
}
|
|
2540
|
+
if (a.isZero) {
|
|
2541
|
+
return vec2u(bBits, 0u);
|
|
2542
|
+
}
|
|
2543
|
+
if (b.isZero) {
|
|
2544
|
+
return vec2u(aBits, 0u);
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
let exponentDifference = abs(a.baseExponent - b.baseExponent);
|
|
2548
|
+
if (exponentDifference > 25) {
|
|
2549
|
+
if (fp64_raw_f32_magnitude_compare(aBits, bBits) >= 0) {
|
|
2550
|
+
return vec2u(aBits, bBits);
|
|
2551
|
+
}
|
|
2552
|
+
return vec2u(bBits, aBits);
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
let commonBaseExponent = min(a.baseExponent, b.baseExponent);
|
|
2556
|
+
let aMagnitude = fp64_u64_shift_left(
|
|
2557
|
+
vec2u(0u, a.significand),
|
|
2558
|
+
u32(a.baseExponent - commonBaseExponent)
|
|
2559
|
+
);
|
|
2560
|
+
let bMagnitude = fp64_u64_shift_left(
|
|
2561
|
+
vec2u(0u, b.significand),
|
|
2562
|
+
u32(b.baseExponent - commonBaseExponent)
|
|
2563
|
+
);
|
|
2564
|
+
|
|
2565
|
+
var resultSign = a.sign;
|
|
2566
|
+
var resultMagnitude: vec2u;
|
|
2567
|
+
if (a.sign == b.sign) {
|
|
2568
|
+
resultMagnitude = fp64_u64_add(aMagnitude, bMagnitude);
|
|
2569
|
+
} else {
|
|
2570
|
+
let comparison = fp64_u64_compare(aMagnitude, bMagnitude);
|
|
2571
|
+
if (comparison == 0) {
|
|
2572
|
+
return vec2u(0u);
|
|
2573
|
+
}
|
|
2574
|
+
if (comparison > 0) {
|
|
2575
|
+
resultMagnitude = fp64_u64_sub(aMagnitude, bMagnitude);
|
|
2576
|
+
} else {
|
|
2577
|
+
resultSign = b.sign;
|
|
2578
|
+
resultMagnitude = fp64_u64_sub(bMagnitude, aMagnitude);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
return fp64_split_raw_accumulator_bits(
|
|
2583
|
+
resultSign,
|
|
2584
|
+
resultMagnitude,
|
|
2585
|
+
commonBaseExponent
|
|
2586
|
+
);
|
|
2587
|
+
}
|
|
2588
|
+
#endif
|
|
2589
|
+
|
|
2590
|
+
#ifndef LUMA_FP64_F32_INPUT_ONLY
|
|
2591
|
+
fn fp64_add_aligned_magnitudes_to_fp64_bits(
|
|
2592
|
+
sign: u32,
|
|
2593
|
+
larger: Fp64Bits,
|
|
2594
|
+
smaller: Fp64Bits
|
|
2595
|
+
) -> vec2u {
|
|
2596
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
2597
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
2598
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
2599
|
+
u32(larger.exponent - smaller.exponent)
|
|
2600
|
+
);
|
|
2601
|
+
let resultSignificand = fp64_u64_add(largeSignificand, smallSignificand);
|
|
2602
|
+
return fp64_split_binary64_accumulator_bits(
|
|
2603
|
+
sign,
|
|
2604
|
+
resultSignificand,
|
|
2605
|
+
larger.exponent - 55
|
|
2606
|
+
);
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
fn fp64_sub_aligned_magnitudes_to_fp64_bits(
|
|
2610
|
+
sign: u32,
|
|
2611
|
+
larger: Fp64Bits,
|
|
2612
|
+
smaller: Fp64Bits
|
|
2613
|
+
) -> vec2u {
|
|
2614
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
2615
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
2616
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
2617
|
+
u32(larger.exponent - smaller.exponent)
|
|
2618
|
+
);
|
|
2619
|
+
let resultSignificand = fp64_u64_sub(largeSignificand, smallSignificand);
|
|
2620
|
+
return fp64_split_binary64_accumulator_bits(
|
|
2621
|
+
sign,
|
|
2622
|
+
resultSignificand,
|
|
2623
|
+
larger.exponent - 55
|
|
2624
|
+
);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
fn fp64_add_aligned_magnitudes_to_f32_bits(sign: u32, larger: Fp64Bits, smaller: Fp64Bits) -> u32 {
|
|
2628
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
2629
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
2630
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
2631
|
+
u32(larger.exponent - smaller.exponent)
|
|
2632
|
+
);
|
|
2633
|
+
let resultSignificand = fp64_u64_add(largeSignificand, smallSignificand);
|
|
2634
|
+
return fp64_make_f32_bits_from_u64(sign, resultSignificand, larger.exponent - 55);
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
fn fp64_sub_aligned_magnitudes_to_f32_bits(sign: u32, larger: Fp64Bits, smaller: Fp64Bits) -> u32 {
|
|
2638
|
+
let largeSignificand = fp64_u64_shift_left(larger.significand, 3u);
|
|
2639
|
+
let smallSignificand = fp64_u64_shift_right_sticky(
|
|
2640
|
+
fp64_u64_shift_left(smaller.significand, 3u),
|
|
2641
|
+
u32(larger.exponent - smaller.exponent)
|
|
2642
|
+
);
|
|
2643
|
+
let resultSignificand = fp64_u64_sub(largeSignificand, smallSignificand);
|
|
2644
|
+
return fp64_make_f32_bits_from_u64(sign, resultSignificand, larger.exponent - 55);
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
// Subtract two raw binary64 values and round the exact result once to f32.
|
|
2648
|
+
// The input words are canonical high/low words: .x contains sign/exponent/high
|
|
2649
|
+
// fraction bits, and .y contains the low 32 fraction bits.
|
|
2650
|
+
fn sub_fp64u32_to_f32_bits(aBits: vec2u, bBits: vec2u) -> u32 {
|
|
2651
|
+
let a = fp64_decode_bits(aBits);
|
|
2652
|
+
let b = fp64_decode_bits(bBits);
|
|
2653
|
+
let bSubtractionSign = b.sign ^ 1u;
|
|
2654
|
+
|
|
2655
|
+
if (a.isNan || b.isNan) {
|
|
2656
|
+
return 0x7fc00000u;
|
|
2657
|
+
}
|
|
2658
|
+
if (a.isInf && b.isInf) {
|
|
2659
|
+
if (a.sign == bSubtractionSign) {
|
|
2660
|
+
return (a.sign << 31u) | 0x7f800000u;
|
|
2661
|
+
}
|
|
2662
|
+
return 0x7fc00000u;
|
|
2663
|
+
}
|
|
2664
|
+
if (a.isInf) {
|
|
2665
|
+
return (a.sign << 31u) | 0x7f800000u;
|
|
2666
|
+
}
|
|
2667
|
+
if (b.isInf) {
|
|
2668
|
+
return (bSubtractionSign << 31u) | 0x7f800000u;
|
|
2669
|
+
}
|
|
2670
|
+
if (a.isZero && b.isZero) {
|
|
2671
|
+
return select(0u, 0x80000000u, a.sign == 1u && b.sign == 0u);
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
let magnitudeComparison = fp64_finite_magnitude_compare(a, b);
|
|
2675
|
+
if (a.sign == bSubtractionSign) {
|
|
2676
|
+
if (magnitudeComparison >= 0) {
|
|
2677
|
+
return fp64_add_aligned_magnitudes_to_f32_bits(a.sign, a, b);
|
|
2678
|
+
}
|
|
2679
|
+
return fp64_add_aligned_magnitudes_to_f32_bits(a.sign, b, a);
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
if (magnitudeComparison == 0) {
|
|
2683
|
+
return 0u;
|
|
2684
|
+
}
|
|
2685
|
+
if (magnitudeComparison > 0) {
|
|
2686
|
+
return fp64_sub_aligned_magnitudes_to_f32_bits(a.sign, a, b);
|
|
2687
|
+
}
|
|
2688
|
+
return fp64_sub_aligned_magnitudes_to_f32_bits(bSubtractionSign, b, a);
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
fn sub_fp64u32_to_f32(aBits: vec2u, bBits: vec2u) -> f32 {
|
|
2692
|
+
return bitcast<f32>(sub_fp64u32_to_f32_bits(aBits, bBits));
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
// Subtract two raw binary64 values, round once to binary64, then split the
|
|
2696
|
+
// result into normalized f32 limbs. Finite results must fit within the f32
|
|
2697
|
+
// exponent range; larger magnitudes map to infinity and smaller magnitudes
|
|
2698
|
+
// map to zero. The input words use canonical high/low word order.
|
|
2699
|
+
fn sub_fp64u32_to_fp64_bits(aBits: vec2u, bBits: vec2u) -> vec2u {
|
|
2700
|
+
let a = fp64_decode_bits(aBits);
|
|
2701
|
+
let b = fp64_decode_bits(bBits);
|
|
2702
|
+
let bSubtractionSign = b.sign ^ 1u;
|
|
2703
|
+
|
|
2704
|
+
if (a.isNan || b.isNan) {
|
|
2705
|
+
return vec2u(0x7fc00000u, 0u);
|
|
2706
|
+
}
|
|
2707
|
+
if (a.isInf && b.isInf) {
|
|
2708
|
+
if (a.sign == bSubtractionSign) {
|
|
2709
|
+
return vec2u((a.sign << 31u) | 0x7f800000u, 0u);
|
|
2710
|
+
}
|
|
2711
|
+
return vec2u(0x7fc00000u, 0u);
|
|
2712
|
+
}
|
|
2713
|
+
if (a.isInf) {
|
|
2714
|
+
return vec2u((a.sign << 31u) | 0x7f800000u, 0u);
|
|
2715
|
+
}
|
|
2716
|
+
if (b.isInf) {
|
|
2717
|
+
return vec2u((bSubtractionSign << 31u) | 0x7f800000u, 0u);
|
|
2718
|
+
}
|
|
2719
|
+
if (a.isZero && b.isZero) {
|
|
2720
|
+
return vec2u(0u);
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
let magnitudeComparison = fp64_finite_magnitude_compare(a, b);
|
|
2724
|
+
if (a.sign == bSubtractionSign) {
|
|
2725
|
+
if (magnitudeComparison >= 0) {
|
|
2726
|
+
return fp64_add_aligned_magnitudes_to_fp64_bits(a.sign, a, b);
|
|
2727
|
+
}
|
|
2728
|
+
return fp64_add_aligned_magnitudes_to_fp64_bits(a.sign, b, a);
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2731
|
+
if (magnitudeComparison == 0) {
|
|
2732
|
+
return vec2u(0u);
|
|
2733
|
+
}
|
|
2734
|
+
if (magnitudeComparison > 0) {
|
|
2735
|
+
return fp64_sub_aligned_magnitudes_to_fp64_bits(a.sign, a, b);
|
|
2736
|
+
}
|
|
2737
|
+
return fp64_sub_aligned_magnitudes_to_fp64_bits(bSubtractionSign, b, a);
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
fn sub_fp64u32_to_fp64(aBits: vec2u, bBits: vec2u) -> vec2f {
|
|
2741
|
+
let resultBits = sub_fp64u32_to_fp64_bits(aBits, bBits);
|
|
2742
|
+
return vec2f(bitcast<f32>(resultBits.x), bitcast<f32>(resultBits.y));
|
|
2743
|
+
}
|
|
2744
|
+
#endif
|
|
2745
|
+
|
|
2746
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
1691
2747
|
fn fp64_runtime_zero() -> f32 {
|
|
1692
2748
|
return fp64arithmetic.ONE * 0.0;
|
|
1693
2749
|
}
|
|
@@ -1699,7 +2755,11 @@ fn prevent_fp64_optimization(value: f32) -> f32 {
|
|
|
1699
2755
|
return value;
|
|
1700
2756
|
#endif
|
|
1701
2757
|
}
|
|
2758
|
+
#endif
|
|
1702
2759
|
|
|
2760
|
+
#ifdef LUMA_FP64_INTEGER_ARITHMETIC
|
|
2761
|
+
${fp64arithmeticWGSLInteger}
|
|
2762
|
+
#else
|
|
1703
2763
|
fn split(a: f32) -> vec2f {
|
|
1704
2764
|
let splitValue = prevent_fp64_optimization(fp64arithmetic.SPLIT + fp64_runtime_zero());
|
|
1705
2765
|
let t = prevent_fp64_optimization(a * splitValue);
|
|
@@ -1850,6 +2910,7 @@ fn mul_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
|
1850
2910
|
return prod;
|
|
1851
2911
|
}
|
|
1852
2912
|
|
|
2913
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
1853
2914
|
fn div_fp64(a: vec2f, b: vec2f) -> vec2f {
|
|
1854
2915
|
let xn = prevent_fp64_optimization(1.0 / b.x);
|
|
1855
2916
|
let yn = mul_fp64(a, vec2f(xn, fp64_runtime_zero()));
|
|
@@ -1882,6 +2943,97 @@ fn sqrt_fp64(a: vec2f) -> vec2f {
|
|
|
1882
2943
|
return sum_fp64(vec2f(yn, 0.0), prod);
|
|
1883
2944
|
#endif
|
|
1884
2945
|
}
|
|
2946
|
+
#endif
|
|
2947
|
+
#endif
|
|
2948
|
+
|
|
2949
|
+
#ifndef LUMA_FP64_PREDICATE_ONLY
|
|
2950
|
+
fn fp64_f32_bits_is_nan(bits: u32) -> bool {
|
|
2951
|
+
return (bits & 0x7fffffffu) > 0x7f800000u;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
fn fp64_f32_bits_is_inf(bits: u32) -> bool {
|
|
2955
|
+
return (bits & 0x7fffffffu) == 0x7f800000u;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
fn fp64_compare_f32_bits(aBits: u32, bBits: u32) -> i32 {
|
|
2959
|
+
let aMagnitude = aBits & 0x7fffffffu;
|
|
2960
|
+
let bMagnitude = bBits & 0x7fffffffu;
|
|
2961
|
+
if (aMagnitude == 0u && bMagnitude == 0u) {
|
|
2962
|
+
return 0;
|
|
2963
|
+
}
|
|
2964
|
+
let aSign = aBits >> 31u;
|
|
2965
|
+
let bSign = bBits >> 31u;
|
|
2966
|
+
if (aSign != bSign) {
|
|
2967
|
+
return select(1, -1, aSign == 1u);
|
|
2968
|
+
}
|
|
2969
|
+
if (aMagnitude == bMagnitude) {
|
|
2970
|
+
return 0;
|
|
2971
|
+
}
|
|
2972
|
+
let magnitudeComparison = select(-1, 1, aMagnitude > bMagnitude);
|
|
2973
|
+
return select(magnitudeComparison, -magnitudeComparison, aSign == 1u);
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
// Normalize an arbitrary pair of finite f32 limbs with integer accumulation.
|
|
2977
|
+
// This is independent of LUMA_FP64_INTEGER_ARITHMETIC and canonicalizes every
|
|
2978
|
+
// representation of zero to vec2f(+0.0, +0.0).
|
|
2979
|
+
fn normalize_fp64(value: vec2f) -> vec2f {
|
|
2980
|
+
let resultBits = fp64_add_raw_f32_bits(bitcast<u32>(value.x), bitcast<u32>(value.y));
|
|
2981
|
+
return vec2f(bitcast<f32>(resultBits.x), bitcast<f32>(resultBits.y));
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
fn is_nan_fp64(value: vec2f) -> bool {
|
|
2985
|
+
let normalized = normalize_fp64(value);
|
|
2986
|
+
return fp64_f32_bits_is_nan(bitcast<u32>(normalized.x)) ||
|
|
2987
|
+
fp64_f32_bits_is_nan(bitcast<u32>(normalized.y));
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
fn is_finite_fp64(value: vec2f) -> bool {
|
|
2991
|
+
let normalized = normalize_fp64(value);
|
|
2992
|
+
let highBits = bitcast<u32>(normalized.x);
|
|
2993
|
+
let lowBits = bitcast<u32>(normalized.y);
|
|
2994
|
+
return !fp64_f32_bits_is_nan(highBits) && !fp64_f32_bits_is_nan(lowBits) &&
|
|
2995
|
+
!fp64_f32_bits_is_inf(highBits) && !fp64_f32_bits_is_inf(lowBits);
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
// Returns -1, 0, or 1. NaN is unordered and returns 0; call is_nan_fp64 or
|
|
2999
|
+
// is_finite_fp64 first when 0 must mean a finite zero.
|
|
3000
|
+
fn sign_fp64(value: vec2f) -> i32 {
|
|
3001
|
+
let normalized = normalize_fp64(value);
|
|
3002
|
+
let highBits = bitcast<u32>(normalized.x);
|
|
3003
|
+
let lowBits = bitcast<u32>(normalized.y);
|
|
3004
|
+
if (fp64_f32_bits_is_nan(highBits) || fp64_f32_bits_is_nan(lowBits)) {
|
|
3005
|
+
return 0;
|
|
3006
|
+
}
|
|
3007
|
+
if ((highBits & 0x7fffffffu) != 0u) {
|
|
3008
|
+
return select(1, -1, (highBits >> 31u) == 1u);
|
|
3009
|
+
}
|
|
3010
|
+
if ((lowBits & 0x7fffffffu) != 0u) {
|
|
3011
|
+
return select(1, -1, (lowBits >> 31u) == 1u);
|
|
3012
|
+
}
|
|
3013
|
+
return 0;
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
// Compares double-single values and returns -1, 0, or 1. NaN is unordered
|
|
3017
|
+
// and returns 0; callers that require equality semantics must first check
|
|
3018
|
+
// is_nan_fp64 or is_finite_fp64.
|
|
3019
|
+
fn compare_fp64(a: vec2f, b: vec2f) -> i32 {
|
|
3020
|
+
let normalizedA = normalize_fp64(a);
|
|
3021
|
+
let normalizedB = normalize_fp64(b);
|
|
3022
|
+
let aHighBits = bitcast<u32>(normalizedA.x);
|
|
3023
|
+
let aLowBits = bitcast<u32>(normalizedA.y);
|
|
3024
|
+
let bHighBits = bitcast<u32>(normalizedB.x);
|
|
3025
|
+
let bLowBits = bitcast<u32>(normalizedB.y);
|
|
3026
|
+
if (fp64_f32_bits_is_nan(aHighBits) || fp64_f32_bits_is_nan(aLowBits) ||
|
|
3027
|
+
fp64_f32_bits_is_nan(bHighBits) || fp64_f32_bits_is_nan(bLowBits)) {
|
|
3028
|
+
return 0;
|
|
3029
|
+
}
|
|
3030
|
+
let highComparison = fp64_compare_f32_bits(aHighBits, bHighBits);
|
|
3031
|
+
if (highComparison != 0) {
|
|
3032
|
+
return highComparison;
|
|
3033
|
+
}
|
|
3034
|
+
return fp64_compare_f32_bits(aLowBits, bLowBits);
|
|
3035
|
+
}
|
|
3036
|
+
#endif
|
|
1885
3037
|
`
|
|
1886
3038
|
);
|
|
1887
3039
|
|
|
@@ -3512,6 +4664,9 @@ in vec2 clip_commonPosition;
|
|
|
3512
4664
|
clipByInstance = Boolean(this.props.clipByInstance);
|
|
3513
4665
|
}
|
|
3514
4666
|
this.state.clipByInstance = clipByInstance;
|
|
4667
|
+
if (this.context.device.type === "webgpu") {
|
|
4668
|
+
return {};
|
|
4669
|
+
}
|
|
3515
4670
|
return clipByInstance ? {
|
|
3516
4671
|
modules: [shaderModuleVs],
|
|
3517
4672
|
inject: injectionVs
|
|
@@ -3536,6 +4691,10 @@ in vec2 clip_commonPosition;
|
|
|
3536
4691
|
Math.max(corner0[1], corner1[1])
|
|
3537
4692
|
];
|
|
3538
4693
|
}
|
|
4694
|
+
if (this.context.device.type === "webgpu") {
|
|
4695
|
+
clipProps.enabled = true;
|
|
4696
|
+
clipProps.mode = this.state.clipByInstance ? "instance" : "geometry";
|
|
4697
|
+
}
|
|
3539
4698
|
this.setShaderModuleProps({ clip: clipProps });
|
|
3540
4699
|
}
|
|
3541
4700
|
};
|