From b37df1c5df7d53e9b428b8e7cc214d19be60dbae Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Thu, 23 Nov 2023 13:44:22 -0500 Subject: [PATCH] wgsl: Add `sparseMatrixRange` to FPTraits API (#3183) Fixes #3174 --- src/resources/cache/hashes.json | 208 +++++++++--------- .../webgpu/shader/execution/transpose.bin | Bin 9530 -> 9583 bytes .../expression/call/builtin/transpose.spec.ts | 77 ++----- src/webgpu/util/floating_point.ts | 26 ++- src/webgpu/util/math.ts | 8 +- 5 files changed, 148 insertions(+), 171 deletions(-) diff --git a/src/resources/cache/hashes.json b/src/resources/cache/hashes.json index 69ec1a49851c..1148577cce12 100644 --- a/src/resources/cache/hashes.json +++ b/src/resources/cache/hashes.json @@ -1,106 +1,106 @@ { - "webgpu/shader/execution/binary/af_addition.bin": "ca9569aa", - "webgpu/shader/execution/binary/af_logical.bin": "79fb9de7", - "webgpu/shader/execution/binary/af_division.bin": "87cef40b", - "webgpu/shader/execution/binary/af_matrix_addition.bin": "8afe5300", - "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "bd433833", - "webgpu/shader/execution/binary/af_multiplication.bin": "7803251d", - "webgpu/shader/execution/binary/af_remainder.bin": "f5feb53", - "webgpu/shader/execution/binary/af_subtraction.bin": "7cc42f3a", - "webgpu/shader/execution/binary/f16_addition.bin": "e56d4073", - "webgpu/shader/execution/binary/f16_logical.bin": "6dfc24ba", - "webgpu/shader/execution/binary/f16_division.bin": "933c3c35", - "webgpu/shader/execution/binary/f16_matrix_addition.bin": "934c3596", - "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "f2a1e8", - "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "b1ca61be", - "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "e054a92b", - "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "4706075e", - "webgpu/shader/execution/binary/f16_multiplication.bin": "28dbd8b6", - "webgpu/shader/execution/binary/f16_remainder.bin": "986de10c", - "webgpu/shader/execution/binary/f16_subtraction.bin": "d3e7f74f", - "webgpu/shader/execution/binary/f32_addition.bin": "fc66b530", - "webgpu/shader/execution/binary/f32_logical.bin": "6aecdb17", - "webgpu/shader/execution/binary/f32_division.bin": "b0b2294c", - "webgpu/shader/execution/binary/f32_matrix_addition.bin": "4f84f9a4", - "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "cf99f3b9", - "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "ac8e0983", - "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "76301b8", - "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "db0f8c38", - "webgpu/shader/execution/binary/f32_multiplication.bin": "ecbcde06", - "webgpu/shader/execution/binary/f32_remainder.bin": "9d11467e", - "webgpu/shader/execution/binary/f32_subtraction.bin": "7dbddc79", - "webgpu/shader/execution/binary/i32_arithmetic.bin": "43c80b5e", - "webgpu/shader/execution/binary/i32_comparison.bin": "1b9d7888", - "webgpu/shader/execution/binary/u32_arithmetic.bin": "c031871c", - "webgpu/shader/execution/binary/u32_comparison.bin": "9b05600", - "webgpu/shader/execution/abs.bin": "acfe9bb2", - "webgpu/shader/execution/acos.bin": "8ed18869", - "webgpu/shader/execution/acosh.bin": "1cf98804", - "webgpu/shader/execution/asin.bin": "71698297", - "webgpu/shader/execution/asinh.bin": "7256451c", - "webgpu/shader/execution/atan.bin": "96e29c5d", - "webgpu/shader/execution/atan2.bin": "2dd9139", - "webgpu/shader/execution/atanh.bin": "fafe4e6c", - "webgpu/shader/execution/bitcast.bin": "b9fb1fbd", - "webgpu/shader/execution/ceil.bin": "ff230775", - "webgpu/shader/execution/clamp.bin": "ae2f4ac", - "webgpu/shader/execution/cos.bin": "ff432f2b", - "webgpu/shader/execution/cosh.bin": "d7af2ee9", - "webgpu/shader/execution/cross.bin": "11bf35a8", - "webgpu/shader/execution/degrees.bin": "c53959da", - "webgpu/shader/execution/determinant.bin": "da997a93", - "webgpu/shader/execution/distance.bin": "817d1cb", - "webgpu/shader/execution/dot.bin": "96070df0", - "webgpu/shader/execution/exp.bin": "e9728b8a", - "webgpu/shader/execution/exp2.bin": "66d0d5c5", - "webgpu/shader/execution/faceForward.bin": "cac5c81", - "webgpu/shader/execution/floor.bin": "18f58cc", - "webgpu/shader/execution/fma.bin": "6372916b", - "webgpu/shader/execution/fract.bin": "6335e79f", - "webgpu/shader/execution/frexp.bin": "54d2bdb0", - "webgpu/shader/execution/inverseSqrt.bin": "10ba17af", - "webgpu/shader/execution/ldexp.bin": "dba21b3e", - "webgpu/shader/execution/length.bin": "aad9991", - "webgpu/shader/execution/log.bin": "ff19d8a0", - "webgpu/shader/execution/log2.bin": "b3ebf3dd", - "webgpu/shader/execution/max.bin": "61a11c89", - "webgpu/shader/execution/min.bin": "5de15c84", - "webgpu/shader/execution/mix.bin": "a07ec401", - "webgpu/shader/execution/modf.bin": "91cac6b2", - "webgpu/shader/execution/normalize.bin": "6da0731", - "webgpu/shader/execution/pack2x16float.bin": "119a9ab1", - "webgpu/shader/execution/pow.bin": "986f5d89", - "webgpu/shader/execution/quantizeToF16.bin": "77efff6b", - "webgpu/shader/execution/radians.bin": "a035b517", - "webgpu/shader/execution/reflect.bin": "c2763f1a", - "webgpu/shader/execution/refract.bin": "e71dd5de", - "webgpu/shader/execution/round.bin": "36f3ecde", - "webgpu/shader/execution/saturate.bin": "392167ed", - "webgpu/shader/execution/sign.bin": "766ace88", - "webgpu/shader/execution/sin.bin": "c1fd0733", - "webgpu/shader/execution/sinh.bin": "3f78d331", - "webgpu/shader/execution/smoothstep.bin": "9f72a10", - "webgpu/shader/execution/sqrt.bin": "17fe3757", - "webgpu/shader/execution/step.bin": "e20fb42", - "webgpu/shader/execution/tan.bin": "c3c67187", - "webgpu/shader/execution/tanh.bin": "9d06e776", - "webgpu/shader/execution/transpose.bin": "f739a482", - "webgpu/shader/execution/trunc.bin": "16600f63", - "webgpu/shader/execution/unpack2x16float.bin": "4d6c065c", - "webgpu/shader/execution/unpack2x16snorm.bin": "8d8fc5df", - "webgpu/shader/execution/unpack2x16unorm.bin": "1824a555", - "webgpu/shader/execution/unpack4x8snorm.bin": "bad79c86", - "webgpu/shader/execution/unpack4x8unorm.bin": "8a744dfa", - "webgpu/shader/execution/unary/af_arithmetic.bin": "63f22c73", - "webgpu/shader/execution/unary/af_assignment.bin": "fb65d5ff", - "webgpu/shader/execution/unary/bool_conversion.bin": "cae3c1bd", - "webgpu/shader/execution/unary/f16_arithmetic.bin": "f6937f3e", - "webgpu/shader/execution/unary/f16_conversion.bin": "786501ec", - "webgpu/shader/execution/unary/f32_arithmetic.bin": "eef2bb81", - "webgpu/shader/execution/unary/f32_conversion.bin": "983e48bb", - "webgpu/shader/execution/unary/i32_arithmetic.bin": "c93e4e68", - "webgpu/shader/execution/unary/i32_complement.bin": "2505e4e6", - "webgpu/shader/execution/unary/i32_conversion.bin": "8cceff52", - "webgpu/shader/execution/unary/u32_complement.bin": "dada6764", - "webgpu/shader/execution/unary/u32_conversion.bin": "9b89fb5" + "webgpu/shader/execution/binary/af_addition.bin": "a5da1df9", + "webgpu/shader/execution/binary/af_logical.bin": "27d915bd", + "webgpu/shader/execution/binary/af_division.bin": "a5270697", + "webgpu/shader/execution/binary/af_matrix_addition.bin": "62f800a8", + "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "9183d57f", + "webgpu/shader/execution/binary/af_multiplication.bin": "865258e7", + "webgpu/shader/execution/binary/af_remainder.bin": "4c61df7e", + "webgpu/shader/execution/binary/af_subtraction.bin": "43dd47ae", + "webgpu/shader/execution/binary/f16_addition.bin": "513d71c8", + "webgpu/shader/execution/binary/f16_logical.bin": "443f9a98", + "webgpu/shader/execution/binary/f16_division.bin": "f54e29cb", + "webgpu/shader/execution/binary/f16_matrix_addition.bin": "f910cec6", + "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "b70ddbb2", + "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "62afef7a", + "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "29e3722d", + "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "f4a29ad1", + "webgpu/shader/execution/binary/f16_multiplication.bin": "9baf80a1", + "webgpu/shader/execution/binary/f16_remainder.bin": "85c74732", + "webgpu/shader/execution/binary/f16_subtraction.bin": "b06f0345", + "webgpu/shader/execution/binary/f32_addition.bin": "e0f9ce70", + "webgpu/shader/execution/binary/f32_logical.bin": "47cadba6", + "webgpu/shader/execution/binary/f32_division.bin": "7005e989", + "webgpu/shader/execution/binary/f32_matrix_addition.bin": "98e53a9", + "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "b5c60cda", + "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "522a3569", + "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "c19e488c", + "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "9af1d0c3", + "webgpu/shader/execution/binary/f32_multiplication.bin": "e59c1749", + "webgpu/shader/execution/binary/f32_remainder.bin": "f0aa263b", + "webgpu/shader/execution/binary/f32_subtraction.bin": "f4bc3081", + "webgpu/shader/execution/binary/i32_arithmetic.bin": "e92caa13", + "webgpu/shader/execution/binary/i32_comparison.bin": "21f566be", + "webgpu/shader/execution/binary/u32_arithmetic.bin": "4190d758", + "webgpu/shader/execution/binary/u32_comparison.bin": "91fe8844", + "webgpu/shader/execution/abs.bin": "40c39d52", + "webgpu/shader/execution/acos.bin": "9998e303", + "webgpu/shader/execution/acosh.bin": "7636c6b9", + "webgpu/shader/execution/asin.bin": "fd7059cd", + "webgpu/shader/execution/asinh.bin": "58959a2", + "webgpu/shader/execution/atan.bin": "ed0a5fe5", + "webgpu/shader/execution/atan2.bin": "bcfaa17a", + "webgpu/shader/execution/atanh.bin": "fe79d05d", + "webgpu/shader/execution/bitcast.bin": "ab8f3a85", + "webgpu/shader/execution/ceil.bin": "82690ce1", + "webgpu/shader/execution/clamp.bin": "a30a2b8e", + "webgpu/shader/execution/cos.bin": "bf80f288", + "webgpu/shader/execution/cosh.bin": "2add503b", + "webgpu/shader/execution/cross.bin": "ce546995", + "webgpu/shader/execution/degrees.bin": "af783136", + "webgpu/shader/execution/determinant.bin": "16d6108", + "webgpu/shader/execution/distance.bin": "34788cf8", + "webgpu/shader/execution/dot.bin": "5d8d3fff", + "webgpu/shader/execution/exp.bin": "e890f3d", + "webgpu/shader/execution/exp2.bin": "80f0c788", + "webgpu/shader/execution/faceForward.bin": "4cf3e04d", + "webgpu/shader/execution/floor.bin": "4d91b147", + "webgpu/shader/execution/fma.bin": "9579e337", + "webgpu/shader/execution/fract.bin": "a1372b54", + "webgpu/shader/execution/frexp.bin": "7d140601", + "webgpu/shader/execution/inverseSqrt.bin": "515fb6e3", + "webgpu/shader/execution/ldexp.bin": "826a29a8", + "webgpu/shader/execution/length.bin": "124ac33b", + "webgpu/shader/execution/log.bin": "aad3a1a8", + "webgpu/shader/execution/log2.bin": "7ef34360", + "webgpu/shader/execution/max.bin": "69a1807", + "webgpu/shader/execution/min.bin": "8dfa353d", + "webgpu/shader/execution/mix.bin": "96c9d02d", + "webgpu/shader/execution/modf.bin": "26670f53", + "webgpu/shader/execution/normalize.bin": "60571bc4", + "webgpu/shader/execution/pack2x16float.bin": "31601129", + "webgpu/shader/execution/pow.bin": "8f5de92", + "webgpu/shader/execution/quantizeToF16.bin": "9936c450", + "webgpu/shader/execution/radians.bin": "56c3610d", + "webgpu/shader/execution/reflect.bin": "61beb0cf", + "webgpu/shader/execution/refract.bin": "d0180f9b", + "webgpu/shader/execution/round.bin": "3bc78d47", + "webgpu/shader/execution/saturate.bin": "8478071d", + "webgpu/shader/execution/sign.bin": "58d75a88", + "webgpu/shader/execution/sin.bin": "b14cf00a", + "webgpu/shader/execution/sinh.bin": "a8d76c62", + "webgpu/shader/execution/smoothstep.bin": "246c76eb", + "webgpu/shader/execution/sqrt.bin": "f6c4f4c1", + "webgpu/shader/execution/step.bin": "8268c823", + "webgpu/shader/execution/tan.bin": "af3ecb02", + "webgpu/shader/execution/tanh.bin": "c22b8364", + "webgpu/shader/execution/transpose.bin": "f8663cd3", + "webgpu/shader/execution/trunc.bin": "b532e654", + "webgpu/shader/execution/unpack2x16float.bin": "67d0b480", + "webgpu/shader/execution/unpack2x16snorm.bin": "be8c0687", + "webgpu/shader/execution/unpack2x16unorm.bin": "8ef57a36", + "webgpu/shader/execution/unpack4x8snorm.bin": "a807e0f6", + "webgpu/shader/execution/unpack4x8unorm.bin": "b8ed39e8", + "webgpu/shader/execution/unary/af_arithmetic.bin": "f6181e3d", + "webgpu/shader/execution/unary/af_assignment.bin": "1da130e3", + "webgpu/shader/execution/unary/bool_conversion.bin": "166e7b55", + "webgpu/shader/execution/unary/f16_arithmetic.bin": "576d8432", + "webgpu/shader/execution/unary/f16_conversion.bin": "187365c9", + "webgpu/shader/execution/unary/f32_arithmetic.bin": "abfce14d", + "webgpu/shader/execution/unary/f32_conversion.bin": "69c41336", + "webgpu/shader/execution/unary/i32_arithmetic.bin": "cca83969", + "webgpu/shader/execution/unary/i32_complement.bin": "2a173277", + "webgpu/shader/execution/unary/i32_conversion.bin": "11d03e95", + "webgpu/shader/execution/unary/u32_complement.bin": "6fce0665", + "webgpu/shader/execution/unary/u32_conversion.bin": "53c94e7b" } \ No newline at end of file diff --git a/src/resources/cache/webgpu/shader/execution/transpose.bin b/src/resources/cache/webgpu/shader/execution/transpose.bin index e63e0c314b30277a83592d98296c23ea35439f0c..76590b2836a9a2b9ae8156ccf067c24832a03a37 100644 GIT binary patch literal 9583 zcmX|G3pms5`%fx#AXJjWl8Wj@(d#g56{S)ny?M)Fog_ubA%|_>ijw0hr^GC&RAM1U z*qoQs<~-+N80I|e^xgKKe(&{n?Xo@hbKjr)^m(3Z-+Pc4*>!*Zq-R}Q;`fvNC{qu& z?ATiw_FhW0_36K|&$PC$&%HKjeJ@8&G($b@v$t_QvQV!FwtM*G#!CtxY+9war{Ayo zSUP4qxoxIQp3&IY`2FQ??o#%z(7V4|_5^s`y>jKwovRl?_baOgvB!Mkaey&xf;mB( zKs5U_1Mx-Tch|-DMcyFT2L>G$-?m`itF6$0J25;=GzkO}p#?2^OG>5AwmbxlCT{d= zzo;vOICHq?QBYmsVyENnA!yuqT&^}>9uGiidUJ6({SW9+2X#Ao0K>zV_Ex?FxA5yN zv7&qHj>wMrGyj^DV0h{h*RuWh;@ci@|G`mtHVT)qCAwxxLECG0-e=~Gv#q#=gM24;p>a**ROqvsDY1Km(A^i( zahtC^)J&?uu;#Aqq+%@X*vz-V=;rFe8mDO+!N@X11OM3(V^hC zMjpTyS1cXzCW-tAD}fGw>?`e1v9*vkxif+)@ZjHF@E(A7nO~r_LaU+zmFMA;+F>nB zVw@m5v|$Qz+D0+`UrZElzC7<;(@=60j}VOZl5TajZ1Yxx%>(TxrS)>-tA(u4i=Bt; zzJv|h2yiO{!z&pE4q`c1ld~1sojU3;bPn^cmiH>zN*Ku0X}*~3yAQbtI%_;OoHOMG zjq-2-x1xruLz6l1sY>Ox97i>d{mS8vPu66^LA9xyL!=JEsriHa?1GG`>z6(FrqxWL z4C=!9Zz=BL1EHxSulUO^cl(Jeh_H4;KXJ@T@nxKEu=penQej6pFh_F1Ya@r?9UL8c zz0k3O8i4x9dF@>(P*|;On|>sb83aA0iKF9Act`$@ZxuGO?&=&j&+L_Ju{+vgcQ5Ev zq4GQId-BeV#M+(m(G@3HW2KfCkffW%g=*VjN?@7=?QXmAzfQ>Wl zHK_tK1d&1NPsk6FZi&o& zj9ONPegyu$Co;eBcx9t;{|2U{umApt?16rqf%N@zEx261lmwh$kw!$OXNVmr5rMz6qPn%Rm_W6Ih;V42y~FFX z97TYbd7mS9I?t+6l<6ux+zf**2A=H)et6p@C|X5fC!=magRNg^fEiatan4wk_$B=-p;D?*mAvE~)V1;|~vR z27CWCYEm%RUOWUf#nEp_hn5{Ze2nCq8(Y~?I&;96f+s*`8T;8o<9(@P9Cc@9b+gOtL#KjTjaHxykisp^NgxkS|32E4YnX%{eyE-Q3 zrM(R;c5VyLiKfPDpSO?{=yu(V#sl+JbA|IJFQH8~#kYk|OP%{mH`tN0duS%r^`BSN zjuXoYifo6G$k&#zzm9q+IPTV@5B5wP@P!e7qahL7>{(HZ-VX}1M?4WHEpXUd^NzdC zaltV2TZNp1`92MwMkJO%<&eT_<|20*xqd|E&f+Q zw}gmX*~+tRVC~THwS7MK9WK}jeXBf=`_UH?D~%*|5vIb7S8-)G=s%|}4IeP=ILXr% z4aF_Ye>NV)4;dWcte67L2v%}2yX`2@X@5A>KDk?wvVjS11R6(Clz!J|r29ZrX9r1n z@0<@)xYcS1zcO1ZoP8p0SF?1A?`|tnPG=LiW?J^!z=xVle4l}XUwg=-WcXY*ceQH< ze?#<5xNWCRxW8y0Jp3mwY&l(mm$}ZSKH;+%5tiOOs;us5z9@c>TzaU0W$Sy;lsT^` zz@G5r+!o!RU3!$3!6wfvX8r6x26UBr{fu8z!1VR5uKJg$v7NkC68Ot+RReNgQEeXT zFzA*$mUv(K@m-{p?Nw&LYi!u@X`<&F(*3d>!ynNeZA&UMZOR0D*StLwcqnu0aIG%| z@k7VHniz{Fyq2ID-1S=!{jxU{ygzQ9|Nj^9#kE`b-k;lfo{0TI-f6p9WwxV&Zfnbb z_(FrO8lro^bcfqBqpB(H%L-m%Px=pQM%hQKTjFH;Jb(ns=cZiyM#8>Q>J>P6g=H&n#-xI|4iG} z!DMV%4bmMKG>2+NtJ95FAFtP(E~PgNOT^G4`1A_Rszq*q8o0TC=4YPU5lNe+saBF0 z4RV>85?;EC3(J*4y^o=^;JI-@=M!HPD=&3qM8ck|H>k?=jWE*KK_RP*XIhVU1$=F` zdd7B;mM$qB5TkCui2fk%!-Flp z{3&gbxRb7W#(h+bH&*zxA+ma{mk>l^GZ@~d?eCA^L#{=D|yNv46dWlPE{fpu?Ct@2&-geLYfO5PlfX|7>I9!z!c9KaT}k=wAHM}st5 z?Bjslthe4m>gIGg3R7pvDRSck@}$&l<|1gJE-p%j;c&m{8WEU&x!vX%X7&I)w=#3# zJbzqZ9V5n5u9VXarlWW_(ceGy9$ARWxNNi5`@-loE4NZe5Qzg6XbC#0_HiXU{Ar zgp|k}fcYu?(2jHZ%??KEE0S*bK9T0!)Lruv{Xk;U8KzBT@Iqu4F-m;la;7f~?%*=E z|Hh~VJo-x^7Jg>%@x|25>YM55Xg;d06ZTTi?qe0tzkAeL ziNegTi`p-Nh*2&wbzFU4sYGohkox6Cd;UE-7t&LV7XcC%66gKm2=?>-I_(E3Sp5B1J) zchS-ww;W-ohB%SX7J@mhFqP*8qTSuhWXp(Z!dWU8c4>@H2^is5ZI!Ri1E^pKC{QjD zS+a+?mbW72;i>R^miUG!3=D&~h-KK3i($30^!YSS?+Ro9eV=#~@`MFH3W=p7-Wt@G zf}K`9E0A{v_)xZ1iO7mQG8bgw!$Q0>(1>sqzvkf<@iH{v4r~v}CU#*kffF#ZQjh#w zWGPK6n^)9E!i}htE5gDf9Y9w&OW+|aTomLCxtV1=-rg$e7Yc?+@d0wV5gN05MDRSMiVxfznkCIutq5a8 zbzEVfxJZonA;Gj|x0rrTc`r_xaDV&Ur`bflnh*2>9e}?;Zc^+Hck?+0a%Oc1IE!aX z9~z<#>by(8_o%u-ZZJ=`N5+%XZ@+XaDEZ#Q;#qc>T&g0G$0p#$$Yocby`=_({@R-9 zdxqMOP?h{7BjJ$UyA7$QK5fnN7;g&8>fCL6g4*!bA#Z~!WADk;qoMQ8o<`_1rP7me zN@sqn>pWkd-X^F#4-u3KceH97-V+7An(9A);Ji=b--zp}ci>RVgK^I;Y^G~REOOd{ z$+@w6;7{O(vj*6sd!;ComTKd#lCIsBlYkvgzIG+qAvDW^fB((R+h05U4ZV`x685Kk zy8g;LmgJDpVmP~Vm?|_W)9FQ-^L7o#!jI5DDHmg@+{b4IyT>7xz#LEy^8qjUNBPg~~3m zjdV^2@wF$A*7a`JAg97I#F6azQ8?zHmu zl9$@*2T?cRt7&!0yTxa9#zwcwWJA6u66nW=D!G`^ZI^Av7)enUJ)d>nW!ww>FctM# z$L)xvqF^WOIcr$(gXq2$p`EWbuIsn^8{`zWoy~H!khhvTrZGHy#p;J?GweICXu37a z<^a5FOD1Kqg>}~6Le6Woj$&&X7s4GrAlN-J>zJsX56n! zJoV|sjD!}$wFp$zn>=?#_S&<2uFA7bw=yt|xAK(;%6@N!<(eL!4k8k?L5E(ot`POR zkZz_VhD83x;?r~IAXiBchw6;ZGJ6Fu0fAV&bXmb9{mMu@*NIyrWQ3ee$Pb*^(ycL z%u+fJ2|#UcaC4AsubhIUUgEzuG(CcO>>sdi`DFKY*RQLu z6PqrdnV*n7J;|tXcWui(_6@b2m!8sJW_DhYzi@0bXR5{KJ|rKs`~ApC2W7!ljOJyD zfXPP|4jy8NK06lO3A^xfUutfG-@j4f0h=Q(wWp@S8_|2dz8u+qe?;)(S7pS@=P}o7 zQ6E>NVy|8^G3fMbEqVS;dlaflRxf+|H+e_JrFzAwZM&*o4(mTttRG>h zI4)NwPn%v5W_E`YwHOP>Vh=sLX&b2i&8{kx+&vg3_lx5B>+{sR&kx?^{rTV>5I09p z9AnI61zyF6-Ls%Cal*TP>Ev~Y#-U#6g0lidR>~-ph4|hPirvUZWETEeFhWtA_y(Of zKj<$*BztVW@gy#fv#%m0w@_3E{oxZXdODX@^ZRD$j`a5NL6mbW&Ca>ZBvIZRcfa|n^ozoGp zy9^Gr=K(|4DJc$~8P*l54-1y%_db}`B_zd>P9U7>lohnZT^?0uN`H8Py*;G)(p}}H{bW&RW}OR8FRC_7 zo|cOI{{K^&|3)+mzk1~STt?2_gbh6%PyLP3@p_c=hIG+;-S#@S$&Pa6QiHlvkm=yA zJvWxmX>O*{?=Cy&M}O;5MZHO>W)oCVAMvMOG}?{%K>p2$9^gD{wOPEsz3AZbxuNI* zmGD*@=q~H;azcd^i{vBuKASQz%ZFZGRpz^;92VT)&OdAO?Rr8Rj?=#YRc^KU<#8hJ;U1*+|MdSzud3*Ol9+V5;PJo?y&t=J3dOYg^6zfJeENGI@9 zVXZTrreh}?#-li&wS-yenmbaPYqb>4XV{mgY?~rk8?5$enwYN$pN7AY-Z77|;@ccM zvm@{dBl#zgq4se;sc>20Hb!^)ZIqR!_0TIKL0%OeZSq0(V>GoMvJ^ELIbUa0kLzq| z?3K8!TxDfKj-q!&T04;cEIE>;D8TJ9(pWjt;)n3bq)eP~4lif81q`iB6!C3CMMTuE`Nkj;@(=Y2b#pq;b9dm6Dm< zscQYc)2Xgyyq3e&kl*v|s}OB4(*mzl_VuoY^aS83NYMkU)D051U44Sj3$Fx^dW($= zf$^Y}oUHWx0qEvtNXM$ZHv4h0>n?_xJE^Fqfd1~cLB}dWo2}A+bE?@W(LdRltR*N~ z1dY7K#)iN~7F5+%VK^pmFOja+VBfI{XtSLjaB^L3lmvBpya#a_s}@-_y69HuMP4(gsz&q>xhIsWS?gE#noXFridQzE=mac(){%W=a#nOSU3JyI0+G^OU^JCZMU7}I*_nSu$i zlNZ)W9pBs73_fSovaKf*tIQG8U`1~!6ZBzG&sp31s7wSmvzr?O>5x`|Mr<~u@kbG!Rp5f~WW>Jwq7TF(ANq1!Xr zZVIA+g@xmQ=oc=Uw}ob9d1OIa14|+>**??&A$uX{1W-q@8&V6!Vi(E9Gcu4-uw zGuUJ6)o(za&mFZm`(f|9B#97(LbeWRjPaJauY_A>T{g%BECv0P%(C1v`iJ6ODcR)6 z8D^cP{?8mKY&j}VG6g7;zQ-YAHR-oZaGn4sb3>5Xhb)P>N&0?Rn7JkKk-$>gCSYI5 zvh)}?0tM#~dc*~B^@Mhc&4PZS`@#tu5->E!0Z)sp?q$y-a>Y-Ur9UQo!b=bY(kv`j zV-0%L#A_T#oFYAshY`s}6?OKCB3o0OCZaNiyB^)R{roU#ha?*mGKQqxUoCEkRp?D^ zrAqlu8n{of7%||1*3Y5@V`46-b5^GEA0Q^yV2J?jw8Qv>iF3AVPEJZxib^ZE-fON_ zMb26ltu(TXu;OHfJw|~Cv{J2nPw33sOiR@2C<31)WGFIUtShWKMKb)5@KgqB1~^hP zf@~;s1600d>6Clbyh!5>~|~E{Of?aE7#JiKuLv#gN$^ zKj~$Sh_iuQ2&i3rzSSa|lpJ1F91Zt^&|8@@WF6~6BdI(&?or}irXfLeT~=n9y{L#n z`y#Cpv0m9sj~p)fF6;L-J|7(BzLZDwP4P$x2~6KN~(%e7&GA(C?6;XnDwf~ z)wFp;BK@duNizNYAZeN_Rf(sB$u6%fR)H_-`KX{}dT zI4|U!2ay>OlB0y-d`dZ@X<$UWE++ONsO>az+(N?wZlQ@N0*H#lWcmqmB)j2s zYAKM$Ys*<&SsXzIINYswnkB6VS48?Y&yO%+s6By%_v|1YVk6iN1Ay4HX%gV{Vbj`move9_#96~@C56=U^7Uw z!cq1DAsC)Qkw`YJNv1j5*NLv8g`r54sFCh*f;+{_iI?sisl++K<%8~QlM`Vf@cov6bKSW){k&%jE4&!C@pNC0 zNST{f_s`rez-$bRDrrFq8F|Ind_;lYZmIcGyvl_Yra|~k zoBy}unik!$IE*vd*FVK8!<+7`jttqq#?4GnDcxyJm_sp=;yzX}v6A>7U$VcEuJ^Np zP53807YcXR=3hr|#*)0yjRWzc!6TCRi!n{Eo8S`YM+%ye5V@Z^|fzE11lMYKr)#g=nCgWS>$7Ljm9D z1S_tUE@}LKYKS@hvar-;z*HFmOA~!sSP>M8P}Kt~Qv(0TeiKF9R4#72DvaqO|2}S*I6LlUZGZxj zS!Se^_{}2pr%wS?k^T)}&oj<7E48Y!*6T*px2I$ zi!6>W6j_et{*j9xo(NVAo)8TTLMg5z9^Hin%Z{vz_LN{8|J*8Sy5<|_>v#xX^aNE& z86f$XH7*c7)U-~4C0QWKD?~B_4X~ssY{BlU$nQl1z33I*Apqx`=o*UF7okm_(c0xC ztxqH==u5sUxF9Q}Drxh0Jk_2j7?T_nw0?$8{BV(Q6B31Pq}!x0JJ|k<+>m2fKIjXD zn-cY@O~GLjEzNoT&yLX&Gh^a53R~zn$}0^n57CBRhsksx*iwup4JfV+(NuLKt@RFSY;G7Z&)=X`Wz3y=Zm55c{A zheyFTI@kg*)Wa=CYsk z9k(AG!kbfkhN9)G>CtwTDIBr}bDs93Z&D;%?sL&%=2XCXA{wC371kF?NHxl9ac-01 z_A{+m9406{c*z_E=o1w-O6q%(>)a-(vCs^FZ|RiuHioIJ9Smt?^9R!bp(ve%*mOU8 zo>~(XnOBP${^a*hCw>hUBmDZkBo0F?I0-GcUwA7TC@>{I@DEFVVoS!moXg$=9D)8J zKR7XJO!4WSqt>yLOg`M6^MdRWitez}oQiq#T4c#d>6SKTJ(hG4ZBzjtCsAGc|AcSi zb6RG^=d{kSgvV+0@?TgYoKuWxzAAi3A)$c+UQ15@S}fp1?&LafmiBa6kkH~2Pf026 z;CKkY;ZwnS8WE(O*e5t=pX+5fO2P~p8hMB=Y!^(89l}(K_ z*C*iY=R%i}*2|@uu9Lf_X!DfNp66=?;r-4dY=dex11a9YC_e8V%kRHR@k$0H!$wvI zm5i!@Ecnu-&5!~iZ-vQtBsk8v?UJQmQ&`8_0lMNW49u> zQv`O7{;4U|Cdg8w%3LmmHTx$4g1e>Ws8jo~B0+-pn&&&TdBt+u8aAop4H|YGR#^=L&Dk@`AbZG9C*M U3$Y<-LM(OhZ(HdvT&Z>c2cW?ae*gdg literal 9530 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 - ([2, 3, 4] as const).flatMap(rows => - ([true, false] as const).map(nonConst => ({ - [`f32_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f32.generateMatrixToMatrixCases( - sparseMatrixF32Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f32.transposeInterval - ); - }, - })) +// Cases: [f32|f16|abstract]_matCxR_[non_]const +// abstract_matCxR_non_const is empty and not used +const cases = (['f32', 'f16', 'abstract'] as const) + .flatMap(trait => + ([2, 3, 4] as const).flatMap(cols => + ([2, 3, 4] as const).flatMap(rows => + ([true, false] as const).map(nonConst => ({ + [`${trait}_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { + if (trait === 'abstract' && nonConst) { + return []; + } + return FP[trait].generateMatrixToMatrixCases( + FP[trait].sparseMatrixRange(cols, rows), + nonConst ? 'unfiltered' : 'finite', + FP[trait].transposeInterval + ); + }, + })) + ) ) ) .reduce((a, b) => ({ ...a, ...b }), {}); -// Cases: f16_matCxR_[non_]const -const f16_cases = ([2, 3, 4] as const) - .flatMap(cols => - ([2, 3, 4] as const).flatMap(rows => - ([true, false] as const).map(nonConst => ({ - [`f16_mat${cols}x${rows}_${nonConst ? 'non_const' : 'const'}`]: () => { - return FP.f16.generateMatrixToMatrixCases( - sparseMatrixF16Range(cols, rows), - nonConst ? 'unfiltered' : 'finite', - FP.f16.transposeInterval - ); - }, - })) - ) - ) - .reduce((a, b) => ({ ...a, ...b }), {}); - -// Cases: abstract_matCxR -const abstract_cases = ([2, 3, 4] as const) - .flatMap(cols => - ([2, 3, 4] as const).map(rows => ({ - [`abstract_mat${cols}x${rows}`]: () => { - return FP.abstract.generateMatrixToMatrixCases( - sparseMatrixF64Range(cols, rows), - 'finite', - FP.abstract.transposeInterval - ); - }, - })) - ) - .reduce((a, b) => ({ ...a, ...b }), {}); - -export const d = makeCaseCache('transpose', { - ...f32_cases, - ...f16_cases, - ...abstract_cases, -}); +export const d = makeCaseCache('transpose', cases); g.test('abstract_float') .specURL('https://www.w3.org/TR/WGSL/#matrix-builtin-functions') @@ -89,7 +54,7 @@ g.test('abstract_float') .fn(async t => { const cols = t.params.cols; const rows = t.params.rows; - const cases = await d.get(`abstract_mat${cols}x${rows}`); + const cases = await d.get(`abstract_mat${cols}x${rows}_const`); await run( t, abstractBuiltin('transpose'), diff --git a/src/webgpu/util/floating_point.ts b/src/webgpu/util/floating_point.ts index 2cfdb170a0fc..5dcc11e828d2 100644 --- a/src/webgpu/util/floating_point.ts +++ b/src/webgpu/util/floating_point.ts @@ -37,8 +37,17 @@ import { map2DArray, oneULPF16, oneULPF32, - quantizeToF32, quantizeToF16, + quantizeToF32, + scalarF16Range, + scalarF32Range, + scalarF64Range, + sparseMatrixF16Range, + sparseMatrixF32Range, + sparseMatrixF64Range, + sparseScalarF16Range, + sparseScalarF32Range, + sparseScalarF64Range, sparseVectorF16Range, sparseVectorF32Range, sparseVectorF64Range, @@ -46,12 +55,6 @@ import { vectorF16Range, vectorF32Range, vectorF64Range, - scalarF32Range, - sparseScalarF32Range, - scalarF64Range, - sparseScalarF64Range, - scalarF16Range, - sparseScalarF16Range, } from './math.js'; /** Indicate the kind of WGSL floating point numbers being operated on */ @@ -1101,6 +1104,12 @@ export abstract class FPTraits { public abstract vectorRange(dim: number): ROArrayArray; /** @returns a reduced range of dim element vectors for testing */ public abstract sparseVectorRange(dim: number): ROArrayArray; + /** @returns a reduced range of cols x rows matrices for testing + * + * A non-sparse version of this generator is intentionally not provided due to + * runtime issues with more dense ranges. + */ + public abstract sparseMatrixRange(cols: number, rows: number): ROArrayArrayArray; // Framework - Cases @@ -4544,6 +4553,7 @@ class F32Traits extends FPTraits { public readonly sparseScalarRange = sparseScalarF32Range; public readonly vectorRange = vectorF32Range; public readonly sparseVectorRange = sparseVectorF32Range; + public readonly sparseMatrixRange = sparseMatrixF32Range; // Framework - Fundamental Error Intervals - Overrides public readonly absoluteErrorInterval = this.absoluteErrorIntervalImpl.bind(this); @@ -5020,6 +5030,7 @@ class FPAbstractTraits extends FPTraits { public readonly sparseScalarRange = sparseScalarF64Range; public readonly vectorRange = vectorF64Range; public readonly sparseVectorRange = sparseVectorF64Range; + public readonly sparseMatrixRange = sparseMatrixF64Range; // Framework - Fundamental Error Intervals - Overrides public readonly absoluteErrorInterval = this.unboundedAbsoluteErrorInterval.bind(this); @@ -5356,6 +5367,7 @@ class F16Traits extends FPTraits { public readonly sparseScalarRange = sparseScalarF16Range; public readonly vectorRange = vectorF16Range; public readonly sparseVectorRange = sparseVectorF16Range; + public readonly sparseMatrixRange = sparseMatrixF16Range; // Framework - Fundamental Error Intervals - Overrides public readonly absoluteErrorInterval = this.absoluteErrorIntervalImpl.bind(this); diff --git a/src/webgpu/util/math.ts b/src/webgpu/util/math.ts index f063a60eb8b9..139b5552e999 100644 --- a/src/webgpu/util/math.ts +++ b/src/webgpu/util/math.ts @@ -1963,16 +1963,16 @@ const kSparseMatrixF64Values = { * All the interesting floats from sparseScalarF64 are guaranteed to be tested, but * not in every position. */ -export function sparseMatrixF64Range(c: number, r: number): ROArrayArray[] { +export function sparseMatrixF64Range(cols: number, rows: number): ROArrayArrayArray { assert( - c === 2 || c === 3 || c === 4, + cols === 2 || cols === 3 || cols === 4, 'sparseMatrixF64Range only accepts column counts of 2, 3, and 4' ); assert( - r === 2 || r === 3 || r === 4, + rows === 2 || rows === 3 || rows === 4, 'sparseMatrixF64Range only accepts row counts of 2, 3, and 4' ); - return kSparseMatrixF64Values[c][r]; + return kSparseMatrixF64Values[cols][rows]; } /**