Compare commits
880
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3609eba2e | ||
|
|
d53abebbe9 | ||
|
|
cec7150b4c | ||
|
|
dee94b56db | ||
|
|
046d90be1c | ||
|
|
7fda028191 | ||
|
|
00445918ff | ||
|
|
f32ae2c900 | ||
|
|
0be7fa77a6 | ||
|
|
2765269e46 | ||
|
|
4a45db21b4 | ||
|
|
49ad01fa64 | ||
|
|
be0b7373e9 | ||
|
|
d6338fd927 | ||
|
|
6a1e3c54ec | ||
|
|
60132845ed | ||
|
|
e96a302e79 | ||
|
|
a4dd357781 | ||
|
|
009fb0e121 | ||
|
|
2779c00ec4 | ||
|
|
43d6909939 | ||
|
|
4eb669d59a | ||
|
|
3681fe9657 | ||
|
|
1dcc141e26 | ||
|
|
d8b994bef1 | ||
|
|
e057844742 | ||
|
|
6aa20312e5 | ||
|
|
082da86ca8 | ||
|
|
dd51e1dd96 | ||
|
|
b204b92e35 | ||
|
|
0a5b85f740 | ||
|
|
01318588d5 | ||
|
|
71b193a192 | ||
|
|
07324d63b6 | ||
|
|
3387f5bf33 | ||
|
|
18d7cf980b | ||
|
|
031981a72c | ||
|
|
a495d90110 | ||
|
|
9686b3e294 | ||
|
|
69a327c7e7 | ||
|
|
d5bcc31c71 | ||
|
|
95894f9634 | ||
|
|
4695e93633 | ||
|
|
b332bf376f | ||
|
|
aaac6e7662 | ||
|
|
8ef8b345ae | ||
|
|
2cc375e4cc | ||
|
|
592c91f20e | ||
|
|
04b62960de | ||
|
|
e2492dfde8 | ||
|
|
60ce48e327 | ||
|
|
7588189874 | ||
|
|
b6a69fba18 | ||
|
|
a3bfad95ab | ||
|
|
cf7360bf8b | ||
|
|
2a9dcd7c40 | ||
|
|
e726964b85 | ||
|
|
003e500571 | ||
|
|
72ae60fa64 | ||
|
|
06106b7a00 | ||
|
|
c7319ac559 | ||
|
|
66abb75bc4 | ||
|
|
e4b1f0413b | ||
|
|
9e1ee2f290 | ||
|
|
1d0c23a3f7 | ||
|
|
b8f43e4bc8 | ||
|
|
22bb67e0b0 | ||
|
|
9bd994e6a4 | ||
|
|
c3c9fe1b06 | ||
|
|
e9e7911506 | ||
|
|
0689e79441 | ||
|
|
40a6510710 | ||
|
|
d6b1efd5e4 | ||
|
|
6d0ab5a593 | ||
|
|
b2153e0ef6 | ||
|
|
0e4d35b9fd | ||
|
|
6cc4ae0ee8 | ||
|
|
01711f47d9 | ||
|
|
65aed719d7 | ||
|
|
3e556588fc | ||
|
|
429fd7acc6 | ||
|
|
32b0625f36 | ||
|
|
bb1d1c7349 | ||
|
|
c967fb7860 | ||
|
|
422fcea2cf | ||
|
|
b0d3f14243 | ||
|
|
f5f1e56123 | ||
|
|
bce91c56dd | ||
|
|
f743bedef9 | ||
|
|
eb12e06387 | ||
|
|
40ce15cfbd | ||
|
|
aa5f36e1e3 | ||
|
|
c1a3450d9c | ||
|
|
4396a1a776 | ||
|
|
d88ab8d527 | ||
|
|
a109a52f3d | ||
|
|
a7b4b9d3a6 | ||
|
|
e253051867 | ||
|
|
44d082049c | ||
|
|
239b43e34d | ||
|
|
1888c97245 | ||
|
|
c43c58af5d | ||
|
|
6b43762dc7 | ||
|
|
c3f1a4c94d | ||
|
|
1fef82a826 | ||
|
|
bef004e1b0 | ||
|
|
936d0a7b1d | ||
|
|
2b651d4946 | ||
|
|
d6ab9f1c0b | ||
|
|
786b7ec7ae | ||
|
|
55173efc2c | ||
|
|
7fc8e339e7 | ||
|
|
0395df3689 | ||
|
|
64f03b3832 | ||
|
|
982b159b3e | ||
|
|
bbd4177dd0 | ||
|
|
6e3cccf30c | ||
|
|
5d5f53e6e3 | ||
|
|
ec44c4a157 | ||
|
|
74751a0971 | ||
|
|
28069e43dc | ||
|
|
3603202cc5 | ||
|
|
a8596ae9c9 | ||
|
|
3fb9521c10 | ||
|
|
17f32d198a | ||
|
|
11ecaa2fbf | ||
|
|
d56f769d4d | ||
|
|
a46ca78f41 | ||
|
|
7ba437b2c6 | ||
|
|
b4c33d2ab2 | ||
|
|
455025349d | ||
|
|
3fa4aab02a | ||
|
|
5485ef238f | ||
|
|
a5541de84d | ||
|
|
2d184f5077 | ||
|
|
c2e3a97705 | ||
|
|
0d22805342 | ||
|
|
aeb0c14ce1 | ||
|
|
144d99df57 | ||
|
|
268e204a9f | ||
|
|
a13aa728bf | ||
|
|
c0ee1e2874 | ||
|
|
1b9d2c6fa6 | ||
|
|
7489c55532 | ||
|
|
2d157e8fe1 | ||
|
|
3ba082da13 | ||
|
|
7ae2773222 | ||
|
|
b7eb12bd0c | ||
|
|
305bfb36d8 | ||
|
|
880b454702 | ||
|
|
996e2a206e | ||
|
|
b57fbfb128 | ||
|
|
2f36df8d93 | ||
|
|
76a8f18700 | ||
|
|
53af1fd052 | ||
|
|
cb88e7555f | ||
|
|
35fa79ec23 | ||
|
|
d9cba80bcf | ||
|
|
ed4154ee0e | ||
|
|
65f2df7776 | ||
|
|
1b1c03814a | ||
|
|
b89a0173ef | ||
|
|
1fec588fb1 | ||
|
|
de1edbdf25 | ||
|
|
d468303bc9 | ||
|
|
81658541a1 | ||
|
|
d0eb56ff20 | ||
|
|
85589a7d16 | ||
|
|
d476c7fa1b | ||
|
|
3ed008c0b6 | ||
|
|
66ec81187d | ||
|
|
0efd94a769 | ||
|
|
1801def1ee | ||
|
|
61155644d5 | ||
|
|
b3ec8b188e | ||
|
|
dbf0cde330 | ||
|
|
072562c571 | ||
|
|
780799f30b | ||
|
|
cf0c1f74dc | ||
|
|
d3ca32efbe | ||
|
|
de6df6dc0e | ||
|
|
6dd85c6530 | ||
|
|
5ca7f41513 | ||
|
|
4ad07e25d4 | ||
|
|
89a191c2e9 | ||
|
|
f63296fc18 | ||
|
|
ca27bb58bf | ||
|
|
86d2e11801 | ||
|
|
cd528e57ab | ||
|
|
4a465450f1 | ||
|
|
4e648b224f | ||
|
|
04c7f84c6f | ||
|
|
8c31f46683 | ||
|
|
563c32b95b | ||
|
|
ab0063bc6b | ||
|
|
af48bc3c74 | ||
|
|
65dfac9637 | ||
|
|
9e119937af | ||
|
|
3e644b25f0 | ||
|
|
fadd5eb953 | ||
|
|
b48b6136ba | ||
|
|
ca0f98c513 | ||
|
|
70b87510a2 | ||
|
|
31b836282d | ||
|
|
cdd9c4aebe | ||
|
|
f3a61f100c | ||
|
|
0774ce6b5e | ||
|
|
60db518b75 | ||
|
|
3c5316f1e9 | ||
|
|
1f33a6efd2 | ||
|
|
4127f619e1 | ||
|
|
b3cc4d11b8 | ||
|
|
8523f4e970 | ||
|
|
6b7450dc0b | ||
|
|
7b384fb5e8 | ||
|
|
20dc6d479b | ||
|
|
0736f3c3b3 | ||
|
|
6a7767f4e4 | ||
|
|
628d387cbd | ||
|
|
75a1c6d7a8 | ||
|
|
8c76370e2d | ||
|
|
bdc15a5c2d | ||
|
|
acfe9298d9 | ||
|
|
57f6e5371b | ||
|
|
9fa3cbfcde | ||
|
|
c81ece5c3c | ||
|
|
aae48c1121 | ||
|
|
918ce935b8 | ||
|
|
6f37e07dba | ||
|
|
171b3279e0 | ||
|
|
b3a1cfe7c9 | ||
|
|
d273838e07 | ||
|
|
a1de8c924d | ||
|
|
72765a5b0a | ||
|
|
e1beabaa98 | ||
|
|
ebaee14b8b | ||
|
|
d4f08dafbb | ||
|
|
753fb102c4 | ||
|
|
b219113a55 | ||
|
|
9140d44b29 | ||
|
|
8b0d65768a | ||
|
|
349bf7be38 | ||
|
|
a01d282f14 | ||
|
|
3c3296a114 | ||
|
|
61501ba122 | ||
|
|
99ba40e965 | ||
|
|
4116af7971 | ||
|
|
2fab93faff | ||
|
|
b92c5cab07 | ||
|
|
8ed9678cbe | ||
|
|
731e52a3c1 | ||
|
|
687b6da800 | ||
|
|
64f4c097ac | ||
|
|
0191e1fe46 | ||
|
|
21093067db | ||
|
|
1b10e7d4f3 | ||
|
|
5b2d3ac225 | ||
|
|
422dfcc1e6 | ||
|
|
0d304393f4 | ||
|
|
57aa99e964 | ||
|
|
cfc133fcf1 | ||
|
|
8eade6be1f | ||
|
|
2250664e58 | ||
|
|
8a27cc8b7f | ||
|
|
d786d59ea1 | ||
|
|
79116905aa | ||
|
|
763950ec18 | ||
|
|
13571868de | ||
|
|
0f2c89b140 | ||
|
|
f8b70e8ec5 | ||
|
|
7abdea5a2e | ||
|
|
cb3e808e8d | ||
|
|
b2e0b97bad | ||
|
|
9c0cbed214 | ||
|
|
c531a9c077 | ||
|
|
2a1f762e23 | ||
|
|
4dd98e63e4 | ||
|
|
1b7187f427 | ||
|
|
0dddd94eab | ||
|
|
2ef0244266 | ||
|
|
0774bf9501 | ||
|
|
8f5b2fd230 | ||
|
|
274191036f | ||
|
|
13afbc2876 | ||
|
|
a7bb0a60fb | ||
|
|
0650b13358 | ||
|
|
6cd851e77e | ||
|
|
87a8cb3872 | ||
|
|
a4869eaf19 | ||
|
|
1740220f6a | ||
|
|
5deccffdce | ||
|
|
a76eacba67 | ||
|
|
ee31ca6fc0 | ||
|
|
7dd6686087 | ||
|
|
fdffd93949 | ||
|
|
f0a0a9b2e1 | ||
|
|
e743e9243f | ||
|
|
8e13d53b1e | ||
|
|
ff274c8387 | ||
|
|
e08e1c209b | ||
|
|
de310ed9ad | ||
|
|
d01b29fa01 | ||
|
|
8cba3d4366 | ||
|
|
be1e51ad91 | ||
|
|
29ce1cad84 | ||
|
|
6a967ad007 | ||
|
|
fe2bb3d9a4 | ||
|
|
cd7973bdcf | ||
|
|
e6384e0e92 | ||
|
|
e63dc17f54 | ||
|
|
af338cf2ec | ||
|
|
f1d8a04337 | ||
|
|
b13497e2a0 | ||
|
|
175c9f9966 | ||
|
|
1a50420b46 | ||
|
|
bbad75a012 | ||
|
|
25c08f19e3 | ||
|
|
59063fb7b4 | ||
|
|
71f60de0ad | ||
|
|
743661109d | ||
|
|
5014cbb023 | ||
|
|
4142e7a1cf | ||
|
|
a721e648b7 | ||
|
|
358e89ef08 | ||
|
|
e023e90e7a | ||
|
|
a5b5b0c3a7 | ||
|
|
b7b4d3c295 | ||
|
|
a445c4e156 | ||
|
|
1432c59499 | ||
|
|
4c7c10fad0 | ||
|
|
7c8a0d1967 | ||
|
|
11fbacea20 | ||
|
|
8cd70454c3 | ||
|
|
1d988182fc | ||
|
|
dba49f00df | ||
|
|
89c0b44da9 | ||
|
|
4f450fd5c4 | ||
|
|
f0943cfca2 | ||
|
|
9aa52b79d4 | ||
|
|
a82125dbbd | ||
|
|
24fcb299b5 | ||
|
|
753aa9ca61 | ||
|
|
a33eada7ec | ||
|
|
676a2be874 | ||
|
|
c95d466cdd | ||
|
|
3d8ac384ad | ||
|
|
57424cc7e9 | ||
|
|
78fe4ba547 | ||
|
|
a3d25cd22b | ||
|
|
56bf841bac | ||
|
|
dfdf0db794 | ||
|
|
bf6bd4eca8 | ||
|
|
36c69dda9c | ||
|
|
f14fdc11f5 | ||
|
|
0157487b1f | ||
|
|
1716c856c3 | ||
|
|
31521c70c2 | ||
|
|
8cac90d81e | ||
|
|
388b4f5efb | ||
|
|
f9b5a7f301 | ||
|
|
00c78cc225 | ||
|
|
2bdb8b560c | ||
|
|
a974fddd4c | ||
|
|
83a3e243da | ||
|
|
f286e308bf | ||
|
|
29af3be2e3 | ||
|
|
6623dcbebf | ||
|
|
89dc43f361 | ||
|
|
b77aac43ea | ||
|
|
0d63fa02ee | ||
|
|
e187bc442d | ||
|
|
d62268fbfb | ||
|
|
3b73e3de60 | ||
|
|
7685736d6c | ||
|
|
b8a3a7f221 | ||
|
|
732628acf5 | ||
|
|
7bd00d2b30 | ||
|
|
0759797e61 | ||
|
|
fddc5160c7 | ||
|
|
2a579c460f | ||
|
|
efdc801cff | ||
|
|
dd654c575a | ||
|
|
0c2599b6ca | ||
|
|
979d6742e0 | ||
|
|
4a7a033d04 | ||
|
|
5c2bbcb4a1 | ||
|
|
dec903a0ee | ||
|
|
e9475b322b | ||
|
|
d9aead8aac | ||
|
|
ce148ebeb1 | ||
|
|
e1315fbaa7 | ||
|
|
1690549392 | ||
|
|
c73710e343 | ||
|
|
092a0489da | ||
|
|
1c6279366f | ||
|
|
2ac85049a9 | ||
|
|
ea428a27d1 | ||
|
|
3bef718238 | ||
|
|
e9daaa0503 | ||
|
|
6d3ea21993 | ||
|
|
f39127605d | ||
|
|
db476f00f7 | ||
|
|
e54d8ec0a4 | ||
|
|
b95ac854b4 | ||
|
|
96443f6dac | ||
|
|
e5e3dff9fa | ||
|
|
31d9da38fd | ||
|
|
c5a59bb6b1 | ||
|
|
e6854148d7 | ||
|
|
001daf0350 | ||
|
|
d26c48110d | ||
|
|
15a070f0c9 | ||
|
|
93230b06cf | ||
|
|
4c55fc3c48 | ||
|
|
a4797a631e | ||
|
|
5868e857aa | ||
|
|
32ba063bd7 | ||
|
|
02f0839f9b | ||
|
|
e50f3c4c91 | ||
|
|
7ca15bfc16 | ||
|
|
b7b7afb62a | ||
|
|
b8ff6a9ad9 | ||
|
|
a1dcb4f259 | ||
|
|
c3501393fd | ||
|
|
a03de75a4e | ||
|
|
0c3d59aba3 | ||
|
|
ce1987f291 | ||
|
|
7eae926ed7 | ||
|
|
606af52eda | ||
|
|
8ea30aea80 | ||
|
|
72dea695ba | ||
|
|
1c0cf56ed0 | ||
|
|
bcb4eb35cd | ||
|
|
bce2676335 | ||
|
|
510097d722 | ||
|
|
5784118a12 | ||
|
|
b5de0f2d23 | ||
|
|
04df3f4dad | ||
|
|
093ca4d623 | ||
|
|
a3ed1558d3 | ||
|
|
fe379070ae | ||
|
|
ead0a2f597 | ||
|
|
5dbc593f90 | ||
|
|
d47dc12bf0 | ||
|
|
4392f63e57 | ||
|
|
f64b7aca79 | ||
|
|
3762ec5750 | ||
|
|
4591fdd9c0 | ||
|
|
d3068d2a0e | ||
|
|
ca0a4bc23a | ||
|
|
433c163c61 | ||
|
|
c867fda883 | ||
|
|
566540ae6d | ||
|
|
759f490dae | ||
|
|
867d4d44f5 | ||
|
|
65747d5877 | ||
|
|
bd357f6076 | ||
|
|
9e960b7d45 | ||
|
|
0c54d4a6a1 | ||
|
|
526e846a81 | ||
|
|
8bcfa373d4 | ||
|
|
db9a0f2c1f | ||
|
|
646b1e2193 | ||
|
|
41bd30f81d | ||
|
|
bd626aea27 | ||
|
|
8a03f75485 | ||
|
|
dc9594fbdf | ||
|
|
fad0b533c0 | ||
|
|
4d773e9453 | ||
|
|
e0c610b013 | ||
|
|
0da4f36c33 | ||
|
|
11d17e1db3 | ||
|
|
b8c318d923 | ||
|
|
e563cc6f5e | ||
|
|
cb8914ab96 | ||
|
|
2fecda7bdc | ||
|
|
543d8efb25 | ||
|
|
396b1079a7 | ||
|
|
eedcd9f8cb | ||
|
|
ab252b210c | ||
|
|
1071b8ea90 | ||
|
|
a9c5bbf185 | ||
|
|
8dd4bff7a7 | ||
|
|
77c54446af | ||
|
|
4a0bc0af57 | ||
|
|
a171e75e70 | ||
|
|
f5ffa092fe | ||
|
|
8de5fdd551 | ||
|
|
ecca3abe98 | ||
|
|
8570e35224 | ||
|
|
84df9f9a03 | ||
|
|
5f93fb9613 | ||
|
|
75f77fdbdd | ||
|
|
7825d582c2 | ||
|
|
5deb0ba933 | ||
|
|
18e917aaf2 | ||
|
|
a165f3890a | ||
|
|
f88b6d9c97 | ||
|
|
db8ecd9952 | ||
|
|
b5ec06c2d2 | ||
|
|
dfbac8385e | ||
|
|
eaab737b2c | ||
|
|
45991cda0a | ||
|
|
09a016bb6f | ||
|
|
31607d355d | ||
|
|
a67d50b9e2 | ||
|
|
8d42f53c80 | ||
|
|
5e21a55bce | ||
|
|
85930ea2e8 | ||
|
|
4b3cde8b39 | ||
|
|
eedfa85355 | ||
|
|
bb54c6c807 | ||
|
|
c23f905858 | ||
|
|
8c7be0a1d0 | ||
|
|
878497b3d5 | ||
|
|
a155561769 | ||
|
|
8b86a0ed2e | ||
|
|
26f9a9b122 | ||
|
|
6e5f6978fb | ||
|
|
0d31d7b2de | ||
|
|
dd862b7e0a | ||
|
|
52065f2cbd | ||
|
|
77c02d5831 | ||
|
|
f7e4c8d16d | ||
|
|
b7410474ff | ||
|
|
384cc4ebf6 | ||
|
|
7c0643f122 | ||
|
|
58abae3067 | ||
|
|
4742693869 | ||
|
|
6c39e474ea | ||
|
|
5c8977c906 | ||
|
|
6b3cc2e2f3 | ||
|
|
76b2edd6ea | ||
|
|
8ebb37d011 | ||
|
|
3366db83ef | ||
|
|
5415254aac | ||
|
|
caacc61602 | ||
|
|
e902df19b2 | ||
|
|
40b372dda7 | ||
|
|
fd330a98aa | ||
|
|
90c23a7d5d | ||
|
|
5710304114 | ||
|
|
0f684820bc | ||
|
|
e1d2d6ade6 | ||
|
|
e0b6f2ca71 | ||
|
|
2a35ee279b | ||
|
|
5abf780360 | ||
|
|
181f158ea9 | ||
|
|
f4087fc81d | ||
|
|
82793f9b82 | ||
|
|
537576e84a | ||
|
|
375d1f55e3 | ||
|
|
597218963f | ||
|
|
0d29b3ddc8 | ||
|
|
e0e3b42623 | ||
|
|
0995ca6614 | ||
|
|
3d741fc8d4 | ||
|
|
c20772b458 | ||
|
|
4a6b659098 | ||
|
|
2b93f08ca5 | ||
|
|
fca62b8fff | ||
|
|
dee6d9de2c | ||
|
|
574e3e7521 | ||
|
|
29fdf82ac5 | ||
|
|
c8cf2a54e8 | ||
|
|
bfd32e67d4 | ||
|
|
95915367fa | ||
|
|
b769cfda62 | ||
|
|
40ac88dfed | ||
|
|
6d96082f07 | ||
|
|
21f913db1c | ||
|
|
699a578966 | ||
|
|
babbfa1394 | ||
|
|
73f0d58e10 | ||
|
|
9cb4b74bbd | ||
|
|
f2c8456971 | ||
|
|
e571600c30 | ||
|
|
e84c94d3eb | ||
|
|
e791d4818f | ||
|
|
cdadb43e50 | ||
|
|
edaff60fbf | ||
|
|
3f64e46557 | ||
|
|
32dab23bc6 | ||
|
|
362de7dd31 | ||
|
|
6b01fbb903 | ||
|
|
4934d9f7bc | ||
|
|
ed73955b00 | ||
|
|
3f1f2726c4 | ||
|
|
1a7bd7ea8d | ||
|
|
946ea43436 | ||
|
|
7f42385f5f | ||
|
|
8845ac2b75 | ||
|
|
da85001d4d | ||
|
|
8d15079937 | ||
|
|
adc542b5cd | ||
|
|
72feb044a3 | ||
|
|
c0ba260ddf | ||
|
|
2da215e8e7 | ||
|
|
4d0368b5f1 | ||
|
|
d11c78857d | ||
|
|
e829d90c4a | ||
|
|
a8006acd33 | ||
|
|
86ec502040 | ||
|
|
b19a73cc50 | ||
|
|
a99c695932 | ||
|
|
8cd720b53a | ||
|
|
04df79e58f | ||
|
|
a4b3717762 | ||
|
|
1035e442ee | ||
|
|
60d3638f15 | ||
|
|
3e7d3c9035 | ||
|
|
eb360be2ad | ||
|
|
485ac8704d | ||
|
|
dc74540423 | ||
|
|
96219c22db | ||
|
|
f3b7048775 | ||
|
|
aaed6fb376 | ||
|
|
35a5d3310f | ||
|
|
9da79a1d2d | ||
|
|
595b355d1b | ||
|
|
3a67d769f4 | ||
|
|
6fb536a937 | ||
|
|
bb460d78d8 | ||
|
|
838835a715 | ||
|
|
63acd53e23 | ||
|
|
fcd2d0457b | ||
|
|
58fc26461b | ||
|
|
fd82f6b04e | ||
|
|
cef3200533 | ||
|
|
634500c398 | ||
|
|
b3e294ac54 | ||
|
|
2bf7535ad0 | ||
|
|
3315f75de9 | ||
|
|
bbe7dbfa92 | ||
|
|
5697922a65 | ||
|
|
4da83df2b9 | ||
|
|
8f156d6588 | ||
|
|
cec0871c11 | ||
|
|
41a809368b | ||
|
|
ea53eb9290 | ||
|
|
05875057c9 | ||
|
|
44125926d1 | ||
|
|
60734349de | ||
|
|
fbfd5ec0ec | ||
|
|
a74a95cc65 | ||
|
|
bc0ea16ff0 | ||
|
|
b2dc8aa84c | ||
|
|
9987e8b6ab | ||
|
|
0d9bdcc008 | ||
|
|
b5c634045e | ||
|
|
1f05531d53 | ||
|
|
88f382f0e3 | ||
|
|
3e59925900 | ||
|
|
ea404f8d4f | ||
|
|
602a550d93 | ||
|
|
12abbe2d23 | ||
|
|
fb0ee97588 | ||
|
|
56ef48c9c3 | ||
|
|
47c3dd3dd1 | ||
|
|
c181648bfa | ||
|
|
0cf78b3abe | ||
|
|
22889a7ad9 | ||
|
|
a14451d0ac | ||
|
|
5dfdab10b7 | ||
|
|
d6f2e3b8e9 | ||
|
|
df30517743 | ||
|
|
8f80643c1a | ||
|
|
5aea9be2fb | ||
|
|
ad02e483d0 | ||
|
|
f463d53036 | ||
|
|
b8d4408524 | ||
|
|
fef70be848 | ||
|
|
bdb12d9b24 | ||
|
|
43ad283a83 | ||
|
|
2e4936afc4 | ||
|
|
891ffabd11 | ||
|
|
e2c19498b4 | ||
|
|
c32630b265 | ||
|
|
bf21e78d02 | ||
|
|
525d4e08a3 | ||
|
|
2e9bf6d694 | ||
|
|
e845f01d85 | ||
|
|
bef48be7b4 | ||
|
|
b54fdc9e6e | ||
|
|
cedbf2e30b | ||
|
|
592f8d1b0d | ||
|
|
29612a684e | ||
|
|
e6d5807399 | ||
|
|
fa2553251f | ||
|
|
7387718852 | ||
|
|
a503a6209a | ||
|
|
ce3e5f74e8 | ||
|
|
f37112358e | ||
|
|
f368b14621 | ||
|
|
6960b1148a | ||
|
|
3cc23aac25 | ||
|
|
11dc8740f2 | ||
|
|
4b797cff88 | ||
|
|
fe1c1736cd | ||
|
|
4058ef5f09 | ||
|
|
d25ca01624 | ||
|
|
d96f87dbbf | ||
|
|
8a2e31023f | ||
|
|
1ea8e171d9 | ||
|
|
e2be3dd0ac | ||
|
|
1c51164e7b | ||
|
|
f190f03530 | ||
|
|
055fc7cbc1 | ||
|
|
9073fc3dc3 | ||
|
|
2409dc9bc4 | ||
|
|
6586c8d70b | ||
|
|
ac0c94da69 | ||
|
|
d19d6a72b0 | ||
|
|
c81b5d98ef | ||
|
|
756866675f | ||
|
|
ebcd4925f7 | ||
|
|
13bed4fdf9 | ||
|
|
1dae5c6b6c | ||
|
|
8e6663e4b0 | ||
|
|
ba804444b8 | ||
|
|
58cfb85004 | ||
|
|
ab46481b45 | ||
|
|
4296782399 | ||
|
|
ef375a7103 | ||
|
|
fd258b7765 | ||
|
|
147de8d372 | ||
|
|
eb2a1928b6 | ||
|
|
35b033102f | ||
|
|
7bc65421a9 | ||
|
|
736514cf37 | ||
|
|
db0158dae8 | ||
|
|
e706695ed1 | ||
|
|
e8877ffe2d | ||
|
|
1fd5d9dae6 | ||
|
|
cd48089318 | ||
|
|
6379ab22c9 | ||
|
|
0bf02b75d5 | ||
|
|
c4259b5598 | ||
|
|
6b3c1179bc | ||
|
|
c1a0e61e8e | ||
|
|
fc06298ed4 | ||
|
|
4ca87b188c | ||
|
|
f1f60c3e0d | ||
|
|
76d21b56af | ||
|
|
0ab0e50a4f | ||
|
|
34f4c06a5c | ||
|
|
6de36f1e53 | ||
|
|
2a9a3b1ac2 | ||
|
|
84b73a3770 | ||
|
|
662a10e273 | ||
|
|
ecce02502e | ||
|
|
d17875aea1 | ||
|
|
b8897a68f9 | ||
|
|
84efd4871e | ||
|
|
85ea5a6b70 | ||
|
|
77891acb92 | ||
|
|
74fe102035 | ||
|
|
25cc554925 | ||
|
|
d787a521b5 | ||
|
|
46e52c71e1 | ||
|
|
1dad27a172 | ||
|
|
60d230b380 | ||
|
|
d7cb38e706 | ||
|
|
ce00cca6ee | ||
|
|
d627d57bad | ||
|
|
8ffc776f1c | ||
|
|
be032b52c1 | ||
|
|
4388e81e5f | ||
|
|
71a185d139 | ||
|
|
d2cf5985ac | ||
|
|
debcbb8e5c | ||
|
|
b9dd62c7d3 | ||
|
|
dc2b430f34 | ||
|
|
e5ef4e8868 | ||
|
|
c0d6cd3ac3 | ||
|
|
b63ab2dc19 | ||
|
|
5d8dad561c | ||
|
|
8933be1ae2 | ||
|
|
6b66b48b1d | ||
|
|
9c23eb6e33 | ||
|
|
baea54a3fc | ||
|
|
d9f800454c | ||
|
|
f9ee0de07a | ||
|
|
2786d0a9f7 | ||
|
|
491e8032e6 | ||
|
|
ef3f13f5d3 | ||
|
|
bcb5b2d790 | ||
|
|
02de3f2e2a | ||
|
|
0e7bb53c07 | ||
|
|
759109d478 | ||
|
|
54d5af6edf | ||
|
|
38fbe47ced | ||
|
|
f066c925ba | ||
|
|
994fdf4e1d | ||
|
|
50b50d65e3 | ||
|
|
0aaa985649 | ||
|
|
29564f8eae | ||
|
|
c15db68a5b | ||
|
|
3452fb3e56 | ||
|
|
35eb8e7be1 | ||
|
|
834b774128 | ||
|
|
5aa0eb9f9d | ||
|
|
d9a6e2e649 | ||
|
|
cb823b16a1 | ||
|
|
0bd41e877e | ||
|
|
ecc3e73967 | ||
|
|
464b4c24f9 | ||
|
|
32367516e8 | ||
|
|
1709a55606 | ||
|
|
58b4455979 | ||
|
|
ea1dede19c | ||
|
|
20ea3381fa | ||
|
|
7aa6fccd7c | ||
|
|
adbd54f4f8 | ||
|
|
9d54261f18 | ||
|
|
a97757c9ae | ||
|
|
7c79d9f89d | ||
|
|
bf0914f813 | ||
|
|
b96bc30fbd | ||
|
|
62b50eb8ba | ||
|
|
b4932e384a | ||
|
|
5e68dc5f8d | ||
|
|
f222f1b925 | ||
|
|
22e4a54782 | ||
|
|
1289922c5f | ||
|
|
2839c352b8 | ||
|
|
6a01cbc312 | ||
|
|
6193156556 | ||
|
|
fe23aa917d | ||
|
|
eb8a29a332 | ||
|
|
0626902530 | ||
|
|
042bfe2597 | ||
|
|
97133f3591 | ||
|
|
d06cc4390e | ||
|
|
6047d3235f | ||
|
|
2cda6e35bd | ||
|
|
8f8d51e17b | ||
|
|
6919e3b274 | ||
|
|
10bf944410 | ||
|
|
9a2f6fdb53 | ||
|
|
761977d385 | ||
|
|
21248f15b5 | ||
|
|
4f32817f6d | ||
|
|
cc9e05e711 | ||
|
|
419d68d4db | ||
|
|
8450232448 | ||
|
|
cc51726590 | ||
|
|
318e22af51 | ||
|
|
68ac87dc24 | ||
|
|
acb8f00075 | ||
|
|
06d9183aaa | ||
|
|
75af25419d | ||
|
|
f6b90d2a31 | ||
|
|
a3822f4af0 | ||
|
|
bcdad769ff | ||
|
|
be4fb4fdbb | ||
|
|
65394f6301 | ||
|
|
b0beee03bc | ||
|
|
fe1de41b8e | ||
|
|
a37b431e87 | ||
|
|
98107016b9 | ||
|
|
8bccfc2863 | ||
|
|
f54a0a3452 | ||
|
|
6778ab0624 | ||
|
|
269d636785 | ||
|
|
39862c91ce | ||
|
|
523f4026b4 | ||
|
|
a6bf162431 | ||
|
|
826e8d181c | ||
|
|
16dfadbba0 | ||
|
|
5cbb97551f | ||
|
|
defee767c3 | ||
|
|
9560318521 | ||
|
|
ef09feb048 | ||
|
|
39f323fe09 | ||
|
|
11b95304ea | ||
|
|
b7c30a7916 | ||
|
|
4cae48fc77 | ||
|
|
d1a93f0557 | ||
|
|
b93059fad7 |
@@ -1,68 +0,0 @@
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BracedInitializerIndentWidth: 4
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 100
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
PackConstructorInitializers: Never
|
||||
@@ -92,27 +92,15 @@ jobs:
|
||||
|
||||
test-renderdiff:
|
||||
name: test-renderdiff
|
||||
runs-on: ubuntu-22.04-4core
|
||||
runs-on: ubuntu-22.04-16core
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- uses: ./.github/actions/ubuntu-apt-add-src
|
||||
- name: Run script
|
||||
run: |
|
||||
echo "Disabled renderdiff due to Mesa -> Currently planned outage: 2025-03-16 -> 2025-03-22"
|
||||
# source ./build/linux/ci-common.sh && bash test/renderdiff/test.sh
|
||||
source ./build/linux/ci-common.sh && bash test/renderdiff/test.sh
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: presubmit-renderdiff-result
|
||||
path: ./out/renderdiff_tests
|
||||
|
||||
validate-wgsl-pipeline:
|
||||
name: validate-wgsl-pipeline
|
||||
runs-on: ubuntu-22.04-4core
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run build script
|
||||
run: source ./build/linux/ci-common.sh && ./build.sh -W debug test_filamat
|
||||
- name: Run test
|
||||
run: ./out/cmake-debug/libs/filamat/test_filamat --gtest_filter=MaterialCompiler.Wgsl*
|
||||
@@ -601,14 +601,6 @@ if (FILAMENT_SUPPORTS_METAL)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal)
|
||||
endif()
|
||||
|
||||
# With WebGPU, push constants are not supported. Skinning uses them.
|
||||
# WebGPU has a proposal to add push constants at https://github.com/gpuweb/gpuweb/blob/main/proposals/push-constants.md
|
||||
# With WebGPU, Tint does not support ClipDistance which is used in Stereo. Mentioned in comment
|
||||
# https://github.com/google/dawn/blob/855d17b08abdf02f9142bf5a8f14d0ea088810a4/src/tint/lang/spirv/reader/ast_parser/function.cc#L4434
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=skinning,stereo)
|
||||
endif()
|
||||
|
||||
# Disable ESSL 1.0 code generation.
|
||||
if (NOT FILAMENT_ENABLE_FEATURE_LEVEL_0)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -1)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.58.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.58.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.58.0'
|
||||
pod 'Filament', '~> 1.58.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -9,9 +9,6 @@ Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
|
||||
## v1.58.1
|
||||
|
||||
|
||||
## v1.58.0
|
||||
|
||||
- materials: add an optional `transformName` field to sampler material parameters. [⚠️ **New Material Version**]
|
||||
|
||||
## v1.57.3
|
||||
|
||||
@@ -11,13 +11,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
message("Library filamat ignores Vulkan settings")
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
# See third_party/dawn/tnt/CMakeLists.txt and libs/filamat/CMakeLists.txt
|
||||
add_library(tint STATIC IMPORTED)
|
||||
set_target_properties(tint PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libtint_combined.a)
|
||||
endif()
|
||||
|
||||
add_library(${FILAMAT_FLAVOR} STATIC IMPORTED)
|
||||
set_target_properties(${FILAMAT_FLAVOR} PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/lib${FILAMAT_FLAVOR}.a)
|
||||
@@ -57,5 +50,4 @@ target_link_libraries(filamat-jni
|
||||
utils
|
||||
log
|
||||
smol-v
|
||||
$<$<STREQUAL:${FILAMENT_SUPPORTS_WEBGPU},ON>:tint>
|
||||
)
|
||||
|
||||
@@ -29,6 +29,10 @@ add_library(filaflat STATIC IMPORTED)
|
||||
set_target_properties(filaflat PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilaflat.a)
|
||||
|
||||
add_library(filamat STATIC IMPORTED)
|
||||
set_target_properties(filamat PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilamat.a)
|
||||
|
||||
add_library(geometry STATIC IMPORTED)
|
||||
set_target_properties(geometry PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libgeometry.a)
|
||||
@@ -55,11 +59,11 @@ add_library(smol-v STATIC IMPORTED)
|
||||
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
|
||||
|
||||
if (FILAMENT_ENABLE_FGVIEWER)
|
||||
add_library(fgviewer STATIC IMPORTED)
|
||||
set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfgviewer.a)
|
||||
endif()
|
||||
if (FILAMENT_ENABLE_FGVIEWER)
|
||||
add_library(fgviewer STATIC IMPORTED)
|
||||
set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfgviewer.a)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_ENABLE_MATDBG)
|
||||
add_library(matdbg STATIC IMPORTED)
|
||||
|
||||
@@ -68,21 +68,6 @@ Java_com_google_android_filament_Texture_nIsTextureSwizzleSupported(JNIEnv*, jcl
|
||||
return (jboolean) Texture::isTextureSwizzleSupported(*engine);
|
||||
}
|
||||
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nGetMaxTextureSize(JNIEnv *, jclass,
|
||||
jlong nativeEngine, jint sampler) {
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
return Texture::getMaxTextureSize(*engine, (Texture::Sampler)sampler);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nGetMaxArrayTextureLayers(JNIEnv *, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
return Texture::getMaxArrayTextureLayers(*engine);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Texture_nValidatePixelFormatAndType(JNIEnv*, jclass,
|
||||
jint internalFormat, jint pixelDataFormat, jint pixelDataType) {
|
||||
|
||||
@@ -691,24 +691,6 @@ public class Texture {
|
||||
pixelDataType.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param engine {@link Engine}
|
||||
* @param type Texture sampler type
|
||||
* @return The maximum size in texels of a texture of type \p type. At least 2048 for
|
||||
* 2D textures, 256 for 3D textures
|
||||
*/
|
||||
public static int getMaxTextureSize(@NonNull Engine engine, Sampler type) {
|
||||
return nGetMaxTextureSize(engine.getNativeObject(), type.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param engine {@link Engine}
|
||||
* @return The maximum number of layers supported by texture arrays. At least 256.
|
||||
*/
|
||||
public static int getMaxArrayTextureLayers(@NonNull Engine engine) {
|
||||
return nGetMaxArrayTextureLayers(engine.getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Use <code>Builder</code> to construct a <code>Texture</code> object instance.
|
||||
*/
|
||||
@@ -1307,8 +1289,6 @@ public class Texture {
|
||||
private static native boolean nIsTextureFormatSupported(long nativeEngine, int internalFormat);
|
||||
private static native boolean nIsTextureFormatMipmappable(long nativeEngine, int internalFormat);
|
||||
private static native boolean nIsTextureSwizzleSupported(long nativeEngine);
|
||||
private static native int nGetMaxTextureSize(long nativeObject, int ordinal);
|
||||
private static native int nGetMaxArrayTextureLayers(long nativeObject);
|
||||
|
||||
private static native boolean nValidatePixelFormatAndType(int internalFormat, int pixelDataFormat,
|
||||
int pixelDataType);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.58.0
|
||||
VERSION_NAME=1.58.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -541,7 +541,6 @@ function build_android {
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
:filamat-android:assembleDebug
|
||||
|
||||
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
|
||||
@@ -592,7 +591,6 @@ function build_android {
|
||||
./gradlew \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${WEBGPU_ANDROID_GRADLE_OPTION} \
|
||||
:filamat-android:assembleRelease
|
||||
|
||||
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
|
||||
|
||||
@@ -30,9 +30,6 @@ if [[ "$GITHUB_WORKFLOW" ]]; then
|
||||
sudo apt-get install clang-$GITHUB_CLANG_VERSION libc++-$GITHUB_CLANG_VERSION-dev libc++abi-$GITHUB_CLANG_VERSION-dev
|
||||
sudo apt-get install mesa-common-dev libxi-dev libxxf86vm-dev
|
||||
|
||||
# For dawn
|
||||
sudo apt-get install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
|
||||
|
||||
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${GITHUB_CLANG_VERSION} 100
|
||||
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100
|
||||
fi
|
||||
|
||||
@@ -233,40 +233,17 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
elseif (APPLE OR IOS)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformApple.mm)
|
||||
elseif (ANDROID)
|
||||
list(APPEND SRCS
|
||||
include/backend/platforms/VulkanPlatformAndroid.h
|
||||
src/vulkan/platform/VulkanPlatformAndroid.cpp
|
||||
)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformAndroid.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
list(APPEND SRCS
|
||||
include/backend/platforms/WebGPUPlatform.h
|
||||
src/webgpu/platform/WebGPUPlatform.cpp
|
||||
src/webgpu/WebGPUConstants.h
|
||||
src/webgpu/WebGPUDriver.cpp
|
||||
src/webgpu/WebGPUDriver.h
|
||||
src/webgpu/WebGPUPlatform.cpp
|
||||
src/webgpu/WebGPUPlatform.h
|
||||
)
|
||||
if (WIN32)
|
||||
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformWindows.cpp)
|
||||
elseif (LINUX)
|
||||
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformLinux.cpp)
|
||||
elseif (APPLE OR IOS)
|
||||
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformApple.mm)
|
||||
elseif (ANDROID)
|
||||
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformAndroid.cpp)
|
||||
endif()
|
||||
|
||||
if (TNT_DEV)
|
||||
set(FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING_DEFAULT ON)
|
||||
else()
|
||||
set(FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
option(FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING
|
||||
"Enable immediate_error_handling for the WebGPU backend Dawn implementation"
|
||||
${FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING_DEFAULT})
|
||||
endif()
|
||||
|
||||
if (ANDROID)
|
||||
@@ -453,10 +430,6 @@ if (FILAMENT_SUPPORTS_METAL)
|
||||
target_compile_definitions(${TARGET} PRIVATE $<$<BOOL:${FILAMENT_METAL_PROFILING}>:FILAMENT_METAL_PROFILING>)
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
target_compile_definitions(${TARGET} PRIVATE $<$<BOOL:${FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING}>:FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING>)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${TARGET} PRIVATE
|
||||
${OSMESA_LINKER_FLAGS}
|
||||
$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>:${LINUX_LINKER_OPTIMIZATION_FLAGS}>
|
||||
@@ -485,7 +458,6 @@ if (APPLE OR LINUX)
|
||||
test/ShaderGenerator.cpp
|
||||
test/TrianglePrimitive.cpp
|
||||
test/Arguments.cpp
|
||||
test/Lifetimes.cpp
|
||||
test/test_FeedbackLoops.cpp
|
||||
test/test_Blit.cpp
|
||||
test/test_MissingRequiredAttributes.cpp
|
||||
|
||||
@@ -126,10 +126,6 @@ static_assert(MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_ATTRIBUTE_COUNT,
|
||||
static constexpr size_t CONFIG_UNIFORM_BINDING_COUNT = 9; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t CONFIG_SAMPLER_BINDING_COUNT = 4; // This is guaranteed by OpenGL ES.
|
||||
|
||||
static constexpr uint8_t EXTERNAL_SAMPLER_DATA_INDEX_UNUSED =
|
||||
uint8_t(-1);// Case where the descriptor set binding isnt using any external sampler state
|
||||
// and therefore doesn't have a valid entry.
|
||||
|
||||
/**
|
||||
* Defines the backend's feature levels.
|
||||
*/
|
||||
@@ -186,7 +182,6 @@ enum class ShaderLanguage {
|
||||
SPIRV = 2,
|
||||
MSL = 3,
|
||||
METAL_LIBRARY = 4,
|
||||
WGSL = 5,
|
||||
};
|
||||
|
||||
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
|
||||
@@ -201,8 +196,6 @@ static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguag
|
||||
return "MSL";
|
||||
case ShaderLanguage::METAL_LIBRARY:
|
||||
return "Metal precompiled library";
|
||||
case ShaderLanguage::WGSL:
|
||||
return "WGSL";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,19 +249,21 @@ struct DescriptorSetLayoutBinding {
|
||||
DescriptorFlags flags = DescriptorFlags::NONE;
|
||||
uint16_t count = 0;
|
||||
|
||||
uint8_t externalSamplerDataIndex = EXTERNAL_SAMPLER_DATA_INDEX_UNUSED;
|
||||
|
||||
friend inline bool operator==(
|
||||
DescriptorSetLayoutBinding const& lhs,
|
||||
DescriptorSetLayoutBinding const& rhs) noexcept {
|
||||
return lhs.type == rhs.type &&
|
||||
lhs.flags == rhs.flags &&
|
||||
lhs.count == rhs.count &&
|
||||
lhs.stageFlags == rhs.stageFlags &&
|
||||
lhs.externalSamplerDataIndex == rhs.externalSamplerDataIndex;
|
||||
lhs.stageFlags == rhs.stageFlags;
|
||||
}
|
||||
};
|
||||
|
||||
struct DescriptorSetLayout {
|
||||
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Bitmask for selecting render buffers
|
||||
*/
|
||||
@@ -970,28 +965,8 @@ enum class SamplerCompareFunc : uint8_t {
|
||||
N //!< Never. The depth / stencil test always fails.
|
||||
};
|
||||
|
||||
//! this API is copied from (and only applies to) the Vulkan spec.
|
||||
//! These specify YUV to RGB conversions.
|
||||
enum class SamplerYcbcrModelConversion : uint8_t {
|
||||
RGB_IDENTITY = 0,
|
||||
YCBCR_IDENTITY = 1,
|
||||
YCBCR_709 = 2,
|
||||
YCBCR_601 = 3,
|
||||
YCBCR_2020 = 4,
|
||||
};
|
||||
|
||||
enum class SamplerYcbcrRange : uint8_t {
|
||||
ITU_FULL = 0,
|
||||
ITU_NARROW = 1,
|
||||
};
|
||||
|
||||
enum class ChromaLocation : uint8_t {
|
||||
COSITED_EVEN = 0,
|
||||
MIDPOINT = 1,
|
||||
};
|
||||
|
||||
//! Sampler parameters
|
||||
struct SamplerParams { // NOLINT
|
||||
struct SamplerParams { // NOLINT
|
||||
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
|
||||
SamplerMinFilter filterMin : 3; //!< minification filter (NEAREST)
|
||||
SamplerWrapMode wrapS : 2; //!< s-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
@@ -1046,7 +1021,6 @@ private:
|
||||
return SamplerParams::LessThan{}(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(SamplerParams) == 4);
|
||||
|
||||
// The limitation to 64-bits max comes from how we store a SamplerParams in our JNI code
|
||||
@@ -1054,93 +1028,6 @@ static_assert(sizeof(SamplerParams) == 4);
|
||||
static_assert(sizeof(SamplerParams) <= sizeof(uint64_t),
|
||||
"SamplerParams must be no more than 64 bits");
|
||||
|
||||
//! Sampler parameters
|
||||
struct SamplerYcbcrConversion {// NOLINT
|
||||
SamplerYcbcrModelConversion ycbcrModel : 4;
|
||||
TextureSwizzle r : 4;
|
||||
TextureSwizzle g : 4;
|
||||
TextureSwizzle b : 4;
|
||||
TextureSwizzle a : 4;
|
||||
SamplerYcbcrRange ycbcrRange : 1;
|
||||
ChromaLocation xChromaOffset : 1;
|
||||
ChromaLocation yChromaOffset : 1;
|
||||
SamplerMagFilter chromaFilter : 1;
|
||||
uint8_t padding;
|
||||
|
||||
struct Hasher {
|
||||
size_t operator()(const SamplerYcbcrConversion p) const noexcept {
|
||||
// we don't use std::hash<> here, so we don't have to include <functional>
|
||||
return *reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&p));
|
||||
}
|
||||
};
|
||||
|
||||
struct EqualTo {
|
||||
bool operator()(SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs) const noexcept {
|
||||
assert_invariant(lhs.padding == 0);
|
||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
||||
return *pLhs == *pRhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct LessThan {
|
||||
bool operator()(SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs) const noexcept {
|
||||
assert_invariant(lhs.padding == 0);
|
||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
||||
return *pLhs < *pRhs;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
friend inline bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return !SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
||||
}
|
||||
friend inline bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
||||
noexcept {
|
||||
return SamplerYcbcrConversion::LessThan{}(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(SamplerYcbcrConversion) == 4);
|
||||
|
||||
static_assert(sizeof(SamplerYcbcrConversion) <= sizeof(uint64_t),
|
||||
"SamplerYcbcrConversion must be no more than 64 bits");
|
||||
|
||||
struct ExternalSamplerDatum {
|
||||
ExternalSamplerDatum(SamplerYcbcrConversion ycbcr, SamplerParams spm, uint32_t extFmt)
|
||||
: YcbcrConversion(ycbcr),
|
||||
samplerParams(spm),
|
||||
externalFormat(extFmt) {}
|
||||
bool operator==(ExternalSamplerDatum const& rhs) const {
|
||||
return (YcbcrConversion == rhs.YcbcrConversion && samplerParams == rhs.samplerParams &&
|
||||
externalFormat == rhs.externalFormat);
|
||||
}
|
||||
struct EqualTo {
|
||||
bool operator()(const ExternalSamplerDatum& lhs,
|
||||
const ExternalSamplerDatum& rhs) const noexcept {
|
||||
return (lhs.YcbcrConversion == rhs.YcbcrConversion &&
|
||||
lhs.samplerParams == rhs.samplerParams &&
|
||||
lhs.externalFormat == rhs.externalFormat);
|
||||
}
|
||||
};
|
||||
SamplerYcbcrConversion YcbcrConversion;
|
||||
SamplerParams samplerParams;
|
||||
uint32_t externalFormat;
|
||||
};
|
||||
// No implicit padding allowed due to it being a hash key.
|
||||
static_assert(sizeof(ExternalSamplerDatum) == 12);
|
||||
|
||||
struct DescriptorSetLayout {
|
||||
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
|
||||
utils::FixedCapacityVector<ExternalSamplerDatum> externalSamplerData;
|
||||
};
|
||||
|
||||
//! blending equation function
|
||||
enum class BlendEquation : uint8_t {
|
||||
ADD, //!< the fragment is added to the color buffer
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
|
||||
|
||||
#include <backend/Platform.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
@@ -318,11 +317,6 @@ public:
|
||||
*/
|
||||
uint32_t layers;
|
||||
|
||||
/**
|
||||
* The numbers of samples per texel
|
||||
*/
|
||||
VkSampleCountFlagBits samples;
|
||||
|
||||
/**
|
||||
* The format of the external image
|
||||
*/
|
||||
@@ -353,37 +347,18 @@ public:
|
||||
*/
|
||||
uint32_t memoryTypeBits;
|
||||
};
|
||||
virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage);
|
||||
virtual ExternalImageMetadata getExternalImageMetadata(void* externalImage);
|
||||
|
||||
using ImageData = std::pair<VkImage, VkDeviceMemory>;
|
||||
virtual ImageData createExternalImageData(ExternalImageHandleRef externalImage,
|
||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
|
||||
VkImageUsageFlags usage);
|
||||
|
||||
virtual VkSampler createExternalSampler(SamplerYcbcrConversion chroma,
|
||||
SamplerParams sampler,
|
||||
uint32_t internalFormat);
|
||||
|
||||
virtual VkImageView createExternalImageView(SamplerYcbcrConversion chroma,
|
||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
||||
VkImageViewType viewType, VkComponentMapping swizzle);
|
||||
virtual ImageData createExternalImage(void* externalImage,
|
||||
const ExternalImageMetadata& metadata);
|
||||
|
||||
private:
|
||||
static ExtensionSet getSwapchainInstanceExtensions();
|
||||
|
||||
static ExternalImageMetadata getExternalImageMetadataImpl(ExternalImageHandleRef externalImage,
|
||||
static ExternalImageMetadata getExternalImageMetadataImpl(void* externalImage,
|
||||
VkDevice device);
|
||||
|
||||
static ImageData createExternalImageDataImpl(ExternalImageHandleRef externalImage,
|
||||
VkDevice device, const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
|
||||
VkImageUsageFlags usage);
|
||||
static VkSampler createExternalSamplerImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma, SamplerParams sampler,
|
||||
uint32_t internalFormat);
|
||||
static VkImageView createExternalImageViewImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
||||
VkImageSubresourceRange range, VkImageViewType viewType,
|
||||
VkComponentMapping swizzle);
|
||||
static ImageData createExternalImageImpl(void* externalImage, VkDevice device,
|
||||
const VkAllocationCallbacks* allocator, const ExternalImageMetadata& metadata);
|
||||
|
||||
// Platform dependent helper methods
|
||||
using SurfaceBundle = std::tuple<VkSurfaceKHR, VkExtent2D>;
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <android/hardware_buffer.h>
|
||||
|
||||
namespace filament::backend::fvkandroid {
|
||||
|
||||
struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
|
||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||
bool sRGB = false;
|
||||
unsigned int width; // Texture width
|
||||
unsigned int height; // Texture height
|
||||
TextureFormat format; // Texture format
|
||||
TextureUsage usage; // Texture usage flags
|
||||
|
||||
protected:
|
||||
~ExternalImageVulkanAndroid() override;
|
||||
};
|
||||
|
||||
Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer,
|
||||
bool sRGB) noexcept;
|
||||
|
||||
} // namespace filament::backend::fvkandroid
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PLATFORMS_VULKAN_PLATFORM_ANDROID_H
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_WEBGPUPLATFORM_H
|
||||
#define TNT_FILAMENT_BACKEND_PLATFORMS_WEBGPUPLATFORM_H
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* A Platform interface, handling the environment-specific concerns, e.g. OS, for creating a WebGPU
|
||||
* driver (backend).
|
||||
*/
|
||||
class WebGPUPlatform final : public Platform {
|
||||
public:
|
||||
WebGPUPlatform();
|
||||
~WebGPUPlatform() override = default;
|
||||
|
||||
[[nodiscard]] int getOSVersion() const noexcept final { return 0; }
|
||||
|
||||
[[nodiscard]] wgpu::Instance& getInstance() noexcept { return mInstance; }
|
||||
|
||||
// either returns a valid surface or panics
|
||||
[[nodiscard]] wgpu::Surface createSurface(void* nativeWindow, uint64_t flags);
|
||||
// either returns a valid adapter or panics
|
||||
[[nodiscard]] wgpu::Adapter requestAdapter(wgpu::Surface const& surface);
|
||||
// either returns a valid device or panics
|
||||
[[nodiscard]] wgpu::Device requestDevice(wgpu::Adapter const& adapter);
|
||||
|
||||
protected:
|
||||
[[nodiscard]] Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
private:
|
||||
// we may consider having the driver own this in the future
|
||||
wgpu::Instance mInstance;
|
||||
};
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
#endif// TNT_FILAMENT_BACKEND_PLATFORMS_WEBGPUPLATFORM_H
|
||||
@@ -362,8 +362,6 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedTexturesSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(size_t, getMaxTextureSize, backend::SamplerType, target)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxArrayTextureLayers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage2, backend::Platform::ExternalImageHandleRef, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
|
||||
|
||||
@@ -66,7 +66,7 @@ filament::backend::Platform* createDefaultMetalPlatform();
|
||||
|
||||
#include "noop/PlatformNoop.h"
|
||||
#if defined(FILAMENT_SUPPORTS_WEBGPU)
|
||||
#include "backend/platforms/WebGPUPlatform.h"
|
||||
#include "webgpu/WebGPUPlatform.h"
|
||||
#endif
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -1177,16 +1177,6 @@ size_t MetalDriver::getMaxUniformBufferSize() {
|
||||
return 256 * 1024 * 1024; // TODO: return the actual size instead of hardcoding the minspec
|
||||
}
|
||||
|
||||
size_t MetalDriver::getMaxTextureSize(SamplerType) {
|
||||
// TODO: return the actual size instead of hardcoding the minspec
|
||||
return 2048;
|
||||
}
|
||||
|
||||
size_t MetalDriver::getMaxArrayTextureLayers() {
|
||||
// TODO: return the actual size instead of hardcoding the minspec
|
||||
return 256;
|
||||
}
|
||||
|
||||
void MetalDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor&& data,
|
||||
uint32_t byteOffset) {
|
||||
FILAMENT_CHECK_PRECONDITION(data.buffer)
|
||||
|
||||
@@ -138,7 +138,6 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
||||
case ShaderLanguage::ESSL1:
|
||||
case ShaderLanguage::ESSL3:
|
||||
case ShaderLanguage::SPIRV:
|
||||
case ShaderLanguage::WGSL:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,14 +240,6 @@ size_t NoopDriver::getMaxUniformBufferSize() {
|
||||
return 16384u;
|
||||
}
|
||||
|
||||
size_t NoopDriver::getMaxTextureSize(SamplerType target) {
|
||||
return 2048u;
|
||||
}
|
||||
|
||||
size_t NoopDriver::getMaxArrayTextureLayers() {
|
||||
return 256u;
|
||||
}
|
||||
|
||||
void NoopDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor&& p,
|
||||
uint32_t byteOffset) {
|
||||
scheduleDestroy(std::move(p));
|
||||
|
||||
@@ -94,22 +94,18 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
}
|
||||
#endif
|
||||
|
||||
initExtensions(&ext, state.major, state.minor);
|
||||
OpenGLContext::initExtensions(&ext, state.major, state.minor);
|
||||
|
||||
initProcs(&procs, ext, state.major, state.minor);
|
||||
OpenGLContext::initProcs(&procs, ext, state.major, state.minor);
|
||||
|
||||
initBugs(&bugs, ext, state.major, state.minor,
|
||||
OpenGLContext::initBugs(&bugs, ext, state.major, state.minor,
|
||||
state.vendor, state.renderer, state.version, state.shader);
|
||||
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &gets.max_renderbuffer_size);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &gets.max_texture_image_units);
|
||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &gets.max_combined_texture_image_units);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gets.max_texture_size);
|
||||
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &gets.max_cubemap_texture_size);
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &gets.max_3d_texture_size);
|
||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &gets.max_array_texture_layers);
|
||||
|
||||
mFeatureLevel = resolveFeatureLevel(state.major, state.minor, ext, gets, bugs);
|
||||
mFeatureLevel = OpenGLContext::resolveFeatureLevel(state.major, state.minor, ext, gets, bugs);
|
||||
|
||||
#ifdef BACKEND_OPENGL_VERSION_GLES
|
||||
mShaderModel = ShaderModel::MOBILE;
|
||||
@@ -181,14 +177,6 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
||||
<< gets.max_anisotropy << '\n'
|
||||
<< "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = "
|
||||
<< gets.max_combined_texture_image_units << '\n'
|
||||
<< "GL_MAX_TEXTURE_SIZE = "
|
||||
<< gets.max_texture_size << '\n'
|
||||
<< "GL_MAX_CUBE_MAP_TEXTURE_SIZE = "
|
||||
<< gets.max_cubemap_texture_size << '\n'
|
||||
<< "GL_MAX_3D_TEXTURE_SIZE = "
|
||||
<< gets.max_3d_texture_size << '\n'
|
||||
<< "GL_MAX_ARRAY_TEXTURE_LAYERS = "
|
||||
<< gets.max_array_texture_layers << '\n'
|
||||
<< "GL_MAX_DRAW_BUFFERS = "
|
||||
<< gets.max_draw_buffers << '\n'
|
||||
<< "GL_MAX_RENDERBUFFER_SIZE = "
|
||||
|
||||
@@ -203,10 +203,6 @@ public:
|
||||
GLint max_renderbuffer_size;
|
||||
GLint max_samples;
|
||||
GLint max_texture_image_units;
|
||||
GLint max_texture_size;
|
||||
GLint max_cubemap_texture_size;
|
||||
GLint max_3d_texture_size;
|
||||
GLint max_array_texture_layers;
|
||||
GLint max_transform_feedback_separate_attribs;
|
||||
GLint max_uniform_block_size;
|
||||
GLint max_uniform_buffer_bindings;
|
||||
|
||||
@@ -2460,26 +2460,6 @@ size_t OpenGLDriver::getMaxUniformBufferSize() {
|
||||
return mContext.gets.max_uniform_block_size;
|
||||
}
|
||||
|
||||
size_t OpenGLDriver::getMaxTextureSize(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
return mContext.gets.max_texture_size;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return mContext.gets.max_cubemap_texture_size;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return mContext.gets.max_3d_texture_size;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return mContext.gets.max_cubemap_texture_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t OpenGLDriver::getMaxArrayTextureLayers() {
|
||||
return mContext.gets.max_array_texture_layers;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Swap chains
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -22,10 +22,6 @@
|
||||
#include <dlfcn.h>
|
||||
#include <memory>
|
||||
|
||||
// This is to ensure that linking during compilation will not fail even if
|
||||
// OSMesaGetProcAddress is not linked.
|
||||
__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
using namespace backend;
|
||||
@@ -55,10 +51,10 @@ private:
|
||||
using GetProcAddressFunc = OSMESAproc (*)(const char* funcName);
|
||||
|
||||
public:
|
||||
CreateContextFunc fOSMesaCreateContext;
|
||||
DestroyContextFunc fOSMesaDestroyContext;
|
||||
MakeCurrentFunc fOSMesaMakeCurrent;
|
||||
GetProcAddressFunc fOSMesaGetProcAddress;
|
||||
CreateContextFunc OSMesaCreateContext;
|
||||
DestroyContextFunc OSMesaDestroyContext;
|
||||
MakeCurrentFunc OSMesaMakeCurrent;
|
||||
GetProcAddressFunc OSMesaGetProcAddress;
|
||||
|
||||
OSMesaAPI() {
|
||||
constexpr char const* libraryNames[] = {"libOSMesa.so", "libosmesa.so"};
|
||||
@@ -69,25 +65,18 @@ public:
|
||||
}
|
||||
}
|
||||
if (mLib) {
|
||||
// Loading from a libosmesa.os
|
||||
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
|
||||
OSMesaGetProcAddress = (GetProcAddressFunc) dlsym(mLib, "OSMesaGetProcAddress");
|
||||
} else {
|
||||
// Filament is built into a .so
|
||||
fOSMesaGetProcAddress = (GetProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
|
||||
OSMesaGetProcAddress = (GetProcAddressFunc) dlsym(RTLD_LOCAL, "OSMesaGetProcAddress");
|
||||
}
|
||||
|
||||
if (!fOSMesaGetProcAddress) {
|
||||
// Statically linking osmesa
|
||||
fOSMesaGetProcAddress = OSMesaGetProcAddress;
|
||||
}
|
||||
FILAMENT_CHECK_PRECONDITION(OSMesaGetProcAddress)
|
||||
<< "Unable to against libOSMesa to create a software GL context";
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(fOSMesaGetProcAddress)
|
||||
<< "Unable to link against libOSMesa to create a software GL context";
|
||||
|
||||
fOSMesaCreateContext = (CreateContextFunc) fOSMesaGetProcAddress("OSMesaCreateContext");
|
||||
fOSMesaDestroyContext =
|
||||
(DestroyContextFunc) fOSMesaGetProcAddress("OSMesaDestroyContext");
|
||||
fOSMesaMakeCurrent = (MakeCurrentFunc) fOSMesaGetProcAddress("OSMesaMakeCurrent");
|
||||
OSMesaCreateContext = (CreateContextFunc) OSMesaGetProcAddress("OSMesaCreateContext");
|
||||
OSMesaDestroyContext =
|
||||
(DestroyContextFunc) OSMesaGetProcAddress("OSMesaDestroyContext");
|
||||
OSMesaMakeCurrent = (MakeCurrentFunc) OSMesaGetProcAddress("OSMesaMakeCurrent");
|
||||
}
|
||||
|
||||
~OSMesaAPI() {
|
||||
@@ -108,7 +97,7 @@ Driver* PlatformOSMesa::createDriver(void* const sharedGLContext,
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(sharedGLContext == nullptr)
|
||||
<< "shared GL context is not supported with PlatformOSMesa";
|
||||
mContext = api->fOSMesaCreateContext(GL_RGBA, NULL);
|
||||
mContext = api->OSMesaCreateContext(GL_RGBA, NULL);
|
||||
|
||||
// We need to do a no-op makecurrent here so that the context will be in a correct state before
|
||||
// any GL calls.
|
||||
@@ -124,7 +113,7 @@ Driver* PlatformOSMesa::createDriver(void* const sharedGLContext,
|
||||
|
||||
void PlatformOSMesa::terminate() noexcept {
|
||||
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
|
||||
api->fOSMesaDestroyContext(mContext);
|
||||
api->OSMesaDestroyContext(mContext);
|
||||
delete api;
|
||||
mOsMesaApi = nullptr;
|
||||
|
||||
@@ -152,7 +141,7 @@ bool PlatformOSMesa::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
|
||||
OSMesaSwapchain* impl = (OSMesaSwapchain*) drawSwapChain;
|
||||
|
||||
auto result = api->fOSMesaMakeCurrent(mContext, (BackingType*) impl->buffer.get(),
|
||||
auto result = api->OSMesaMakeCurrent(mContext, (BackingType*) impl->buffer.get(),
|
||||
BACKING_GL_TYPE, impl->width, impl->height);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == GL_TRUE) << "OSMesaMakeCurrent failed!";
|
||||
|
||||
|
||||
@@ -554,45 +554,13 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
texture.inc();
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
|
||||
if (metadata.isProtected) {
|
||||
usage |= backend::TextureUsage::PROTECTED;
|
||||
}
|
||||
|
||||
VkImageUsageFlags vkUsage = metadata.usage;
|
||||
if (any(usage & TextureUsage::BLIT_SRC)) {
|
||||
vkUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
|
||||
if (any(usage & (TextureUsage::BLIT_DST & TextureUsage::UPLOADABLE))) {
|
||||
vkUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
|
||||
assert_invariant(width == metadata.width);
|
||||
assert_invariant(height == metadata.height);
|
||||
assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
|
||||
|
||||
VkMemoryPropertyFlags const requiredMemoryFlags = any(usage & TextureUsage::UPLOADABLE)
|
||||
? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||
: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
uint32_t const memoryTypeIndex =
|
||||
mContext.selectMemoryType(metadata.memoryTypeBits, requiredMemoryFlags);
|
||||
FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex != VK_MAX_MEMORY_TYPES)
|
||||
<< "failed to find a valid memory type for external image memory.";
|
||||
|
||||
const auto& data =
|
||||
mPlatform->createExternalImageData(externalImage, metadata, memoryTypeIndex, vkUsage);
|
||||
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format,
|
||||
metadata.samples, metadata.width, metadata.height, metadata.layerCount, usage,
|
||||
mStagePool);
|
||||
|
||||
texture.inc();
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
@@ -600,7 +568,22 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
|
||||
void* externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
// not supported in this backend
|
||||
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
|
||||
if (metadata.isProtected) {
|
||||
usage |= backend::TextureUsage::PROTECTED;
|
||||
}
|
||||
|
||||
assert_invariant(width == metadata.width);
|
||||
assert_invariant(height == metadata.height);
|
||||
assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
|
||||
|
||||
const auto& data = mPlatform->createExternalImage(externalImage, metadata);
|
||||
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format,
|
||||
1, metadata.width, metadata.height, /*depth=*/1, usage, mStagePool);
|
||||
|
||||
texture.inc();
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
@@ -1147,16 +1130,6 @@ size_t VulkanDriver::getMaxUniformBufferSize() {
|
||||
return 32768;
|
||||
}
|
||||
|
||||
size_t VulkanDriver::getMaxTextureSize(SamplerType) {
|
||||
// TODO: return the actual size instead of hardcoded value
|
||||
return 2048;
|
||||
}
|
||||
|
||||
size_t VulkanDriver::getMaxArrayTextureLayers() {
|
||||
// TODO: return the actual size instead of hardcoded value
|
||||
return 256;
|
||||
}
|
||||
|
||||
void VulkanDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh, uint32_t index,
|
||||
Handle<HwBufferObject> boh) {
|
||||
auto vb = resource_ptr<VulkanVertexBuffer>::cast(&mResourceManager, vbh);
|
||||
@@ -1293,9 +1266,10 @@ void VulkanDriver::generateMipmaps(Handle<HwTexture> th) {
|
||||
mBlitter.blit(VK_FILTER_LINEAR, dst, dstOffsets, src, srcOffsets);
|
||||
}
|
||||
|
||||
level++;
|
||||
srcw = dstw;
|
||||
srch = dsth;
|
||||
} while ((srcw > 1 || srch > 1) && ++level < t->levels - 1);
|
||||
} while ((srcw > 1 || srch > 1) && level < t->levels);
|
||||
}
|
||||
|
||||
void VulkanDriver::compilePrograms(CompilerPriorityQueue priority,
|
||||
|
||||
@@ -23,6 +23,79 @@ using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
constexpr inline VkSamplerAddressMode getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case SamplerWrapMode::CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case SamplerWrapMode::MIRRORED_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkFilter getFilter(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkFilter getFilter(SamplerMagFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMagFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMagFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkSamplerMipmapMode getMipmapMode(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline float getMaxLod(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
case SamplerMinFilter::LINEAR:
|
||||
// The Vulkan spec recommends a max LOD of 0.25 to "disable" mipmapping.
|
||||
// See "Mapping of OpenGL to Vulkan filter modes" in the VK Spec.
|
||||
return 0.25f;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_LOD_CLAMP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkBool32 getCompareEnable(SamplerCompareMode mode) noexcept {
|
||||
return mode == SamplerCompareMode::NONE ? VK_FALSE : VK_TRUE;
|
||||
}
|
||||
|
||||
VulkanSamplerCache::VulkanSamplerCache(VkDevice device)
|
||||
: mDevice(device) {}
|
||||
|
||||
@@ -33,18 +106,18 @@ VkSampler VulkanSamplerCache::getSampler(SamplerParams params) noexcept {
|
||||
}
|
||||
VkSamplerCreateInfo samplerInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = fvkutils::getFilter(params.filterMag),
|
||||
.minFilter = fvkutils::getFilter(params.filterMin),
|
||||
.mipmapMode = fvkutils::getMipmapMode(params.filterMin),
|
||||
.addressModeU = fvkutils::getWrapMode(params.wrapS),
|
||||
.addressModeV = fvkutils::getWrapMode(params.wrapT),
|
||||
.addressModeW = fvkutils::getWrapMode(params.wrapR),
|
||||
.anisotropyEnable = params.anisotropyLog2 == 0 ? VK_FALSE : VK_TRUE,
|
||||
.magFilter = getFilter(params.filterMag),
|
||||
.minFilter = getFilter(params.filterMin),
|
||||
.mipmapMode = getMipmapMode(params.filterMin),
|
||||
.addressModeU = getWrapMode(params.wrapS),
|
||||
.addressModeV = getWrapMode(params.wrapT),
|
||||
.addressModeW = getWrapMode(params.wrapR),
|
||||
.anisotropyEnable = params.anisotropyLog2 == 0 ? 0u : 1u,
|
||||
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
|
||||
.compareEnable = fvkutils::getCompareEnable(params.compareMode),
|
||||
.compareEnable = getCompareEnable(params.compareMode),
|
||||
.compareOp = fvkutils::getCompareOp(params.compareFunc),
|
||||
.minLod = 0.0f,
|
||||
.maxLod = fvkutils::getMaxLod(params.filterMin),
|
||||
.maxLod = getMaxLod(params.filterMin),
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE
|
||||
};
|
||||
|
||||
@@ -978,28 +978,15 @@ VkQueue VulkanPlatform::getProtectedGraphicsQueue() const noexcept {
|
||||
}
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadata(
|
||||
ExternalImageHandleRef externalImage) {
|
||||
void* externalImage) {
|
||||
return getExternalImageMetadataImpl(externalImage, mImpl->mDevice);
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageData(
|
||||
ExternalImageHandleRef externalImage, const ExternalImageMetadata& metadata,
|
||||
uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
||||
return createExternalImageDataImpl(externalImage, mImpl->mDevice, metadata, memoryTypeIndex,
|
||||
usage);
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImage(void* externalImage,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return createExternalImageImpl(externalImage, mImpl->mDevice, nullptr, metadata);
|
||||
}
|
||||
|
||||
VkSampler VulkanPlatform::createExternalSampler(SamplerYcbcrConversion chroma,
|
||||
SamplerParams sampler, uint32_t internalFormat) {
|
||||
return createExternalSamplerImpl(mImpl->mDevice, chroma, sampler, internalFormat);
|
||||
}
|
||||
|
||||
VkImageView VulkanPlatform::createExternalImageView(SamplerYcbcrConversion chroma,
|
||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
||||
VkImageViewType viewType, VkComponentMapping swizzle) {
|
||||
return createExternalImageViewImpl(mImpl->mDevice, chroma, internalFormat, image, range,
|
||||
viewType, swizzle);
|
||||
}
|
||||
#undef SWAPCHAIN_RET_FUNC
|
||||
|
||||
}// namespace filament::backend
|
||||
|
||||
@@ -15,59 +15,26 @@
|
||||
*/
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/VulkanPlatformAndroid.h>
|
||||
#include <private/backend/BackendUtilsAndroid.h>
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include "vulkan/utils/Image.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <android/native_window.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
|
||||
VkFormat transformVkFormat(VkFormat format, bool sRGB) {
|
||||
if (!sRGB) {
|
||||
return format;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
break;
|
||||
case VK_FORMAT_R8G8B8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8_SRGB;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
bool isProtectedFromUsage(uint64_t usage) {
|
||||
return (usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? true : false;
|
||||
}
|
||||
|
||||
std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer_Desc& desc,
|
||||
bool sRGB) {
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageUsageFlags usage = 0;
|
||||
void getVKFormatAndUsage(const AHardwareBuffer_Desc& desc, VkFormat& format,
|
||||
VkImageUsageFlags& usage, bool& isProtected) {
|
||||
// Refer to "11.2.17. External Memory Handle Types" in the spec, and
|
||||
// Tables 13/14 for how the following derivation works.
|
||||
bool isDepthFormat = false;
|
||||
isProtected = false;
|
||||
switch (desc.format) {
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
@@ -115,8 +82,6 @@ std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer
|
||||
format = VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
format = transformVkFormat(format, sRGB);
|
||||
|
||||
// The following only concern usage flags derived from Table 14.
|
||||
usage = 0;
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
|
||||
@@ -133,14 +98,16 @@ std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) {
|
||||
usage = VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
}
|
||||
|
||||
return { format, usage };
|
||||
if (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
|
||||
isProtected = true;
|
||||
}
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevice device,
|
||||
VulkanPlatform::ExternalImageMetadata const& metadata, uint32_t memoryTypeIndex,
|
||||
VkImageUsageFlags usage) {
|
||||
VulkanPlatform::ImageData allocateExternalImage(void* externalBuffer,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
VulkanPlatform::ExternalImageMetadata const& metadata) {
|
||||
VulkanPlatform::ImageData data;
|
||||
AHardwareBuffer* buffer = static_cast<AHardwareBuffer*>(externalBuffer);
|
||||
|
||||
// if external format we need to specifiy it in the allocation
|
||||
const bool useExternalFormat = metadata.format == VK_FORMAT_UNDEFINED;
|
||||
@@ -148,8 +115,8 @@ VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevic
|
||||
const VkExternalFormatANDROID externalFormat = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
||||
.pNext = nullptr,
|
||||
// pass down the format (external means we don't have it VK defined)
|
||||
.externalFormat = metadata.externalFormat,
|
||||
.externalFormat = metadata
|
||||
.externalFormat,// pass down the format (external means we don't have it VK defined)
|
||||
};
|
||||
const VkExternalMemoryImageCreateInfo externalCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
@@ -168,10 +135,12 @@ VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevic
|
||||
};
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.arrayLayers = metadata.layers;
|
||||
imageInfo.samples = metadata.samples;
|
||||
imageInfo.usage = usage;
|
||||
imageInfo.usage = metadata.usage;
|
||||
// In the unprotected case add R/W capabilities
|
||||
if (metadata.isProtected == false)
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
VkResult result = vkCreateImage(device, &imageInfo, VKALLOC, &data.first);
|
||||
VkResult result = vkCreateImage(device, &imageInfo, allocator, &data.first);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkCreateImage failed with error=" << static_cast<int32_t>(result);
|
||||
|
||||
@@ -187,66 +156,36 @@ VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevic
|
||||
.image = data.first,
|
||||
.buffer = VK_NULL_HANDLE,
|
||||
};
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
VkMemoryAllocateInfo allocInfo = {.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &memoryDedicatedAllocateInfo,
|
||||
.allocationSize = metadata.allocationSize,
|
||||
.memoryTypeIndex = memoryTypeIndex,
|
||||
};
|
||||
result = vkAllocateMemory(device, &allocInfo, VKALLOC, &data.second);
|
||||
.memoryTypeIndex = metadata.memoryTypeBits};
|
||||
result = vkAllocateMemory(device, &allocInfo, allocator, &data.second);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkAllocateMemory failed with error=" << static_cast<int32_t>(result);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace fvkandroid {
|
||||
|
||||
ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() = default;
|
||||
|
||||
Platform::ExternalImageHandle createExternalImage(AHardwareBuffer const* buffer,
|
||||
bool sRGB) noexcept {
|
||||
if (__builtin_available(android 26, *)) {
|
||||
AHardwareBuffer_Desc hardwareBufferDescription = {};
|
||||
AHardwareBuffer_describe(buffer, &hardwareBufferDescription);
|
||||
|
||||
auto* const p = new (std::nothrow) ExternalImageVulkanAndroid;
|
||||
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
|
||||
p->sRGB = sRGB;
|
||||
p->height = hardwareBufferDescription.height;
|
||||
p->width = hardwareBufferDescription.width;
|
||||
TextureFormat textureFormat = mapToFilamentFormat(hardwareBufferDescription.format, sRGB);
|
||||
p->format = textureFormat;
|
||||
p->usage = mapToFilamentUsage(hardwareBufferDescription.usage, textureFormat);
|
||||
return Platform::ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
return Platform::ExternalImageHandle{};
|
||||
}
|
||||
|
||||
} // namespace fvkandroid
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
||||
auto const* fvkExternalImage =
|
||||
static_cast<fvkandroid::ExternalImageVulkanAndroid const*>(externalImage.get());
|
||||
}// namespace
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(void* externalImage,
|
||||
VkDevice device) {
|
||||
ExternalImageMetadata metadata;
|
||||
AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer;
|
||||
AHardwareBuffer* buffer = static_cast<AHardwareBuffer*>(externalImage);
|
||||
if (__builtin_available(android 26, *)) {
|
||||
AHardwareBuffer_Desc bufferDesc;
|
||||
AHardwareBuffer_describe(buffer, &bufferDesc);
|
||||
metadata.width = bufferDesc.width;
|
||||
metadata.height = bufferDesc.height;
|
||||
metadata.layers = bufferDesc.layers;
|
||||
metadata.isProtected = isProtectedFromUsage(bufferDesc.usage);
|
||||
std::tie(metadata.format, metadata.usage) =
|
||||
getVKFormatAndUsage(bufferDesc, fvkExternalImage->sRGB);
|
||||
|
||||
getVKFormatAndUsage(bufferDesc, metadata.format, metadata.usage, metadata.isProtected);
|
||||
}
|
||||
// In the unprotected case add R/W capabilities
|
||||
if (metadata.isProtected == false) {
|
||||
metadata.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
|
||||
metadata.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
|
||||
@@ -258,145 +197,26 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
|
||||
};
|
||||
VkResult result = vkGetAndroidHardwareBufferPropertiesANDROID(device, buffer, &properties);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkGetAndroidHardwareBufferProperties failed with error="
|
||||
<< static_cast<int32_t>(result);
|
||||
|
||||
VkFormat bufferPropertiesFormat = transformVkFormat(formatInfo.format, fvkExternalImage->sRGB);
|
||||
FILAMENT_CHECK_POSTCONDITION(metadata.format == bufferPropertiesFormat)
|
||||
<< "mismatched image format( " << metadata.format << ") and queried format("
|
||||
<< bufferPropertiesFormat << ") for external image (AHB)";
|
||||
<< "vkGetAndroidHardwareBufferProperties failed with error="
|
||||
<< static_cast<int32_t>(result);
|
||||
FILAMENT_CHECK_POSTCONDITION(metadata.format == formatInfo.format)
|
||||
<< "mismatched image format for external image (AHB)";
|
||||
metadata.externalFormat = formatInfo.externalFormat;
|
||||
metadata.allocationSize = properties.allocationSize;
|
||||
metadata.memoryTypeBits = properties.memoryTypeBits;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device,
|
||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
||||
auto const* fvkExternalImage =
|
||||
static_cast<fvkandroid::ExternalImageVulkanAndroid const*>(externalImage.get());
|
||||
ImageData data = allocateExternalImage(fvkExternalImage->aHardwareBuffer, device, metadata,
|
||||
memoryTypeIndex, usage);
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
ImageData data = allocateExternalImage(externalImage, device, allocator, metadata);
|
||||
VkResult result = vkBindImageMemory(device, data.first, data.second, 0);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "vkBindImageMemory error=" << static_cast<int32_t>(result);
|
||||
<< "vkBindImageMemory error=" << static_cast<int32_t>(result);
|
||||
return data;
|
||||
}
|
||||
|
||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device, SamplerYcbcrConversion chroma,
|
||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
||||
VkImageViewType viewType, VkComponentMapping swizzle){
|
||||
VkExternalFormatANDROID externalFormat = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
||||
.pNext = nullptr,
|
||||
.externalFormat = internalFormat,
|
||||
};
|
||||
|
||||
TextureSwizzle const swizzleArray[] = {chroma.r, chroma.g, chroma.b, chroma.a};
|
||||
VkSamplerYcbcrConversionCreateInfo conversionInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
||||
.pNext = &externalFormat,
|
||||
.format = VK_FORMAT_UNDEFINED,
|
||||
.ycbcrModel = fvkutils::getYcbcrModelConversion(chroma.ycbcrModel),
|
||||
.ycbcrRange = fvkutils::getYcbcrRange(chroma.ycbcrRange),
|
||||
.components = fvkutils::getSwizzleMap(swizzleArray),
|
||||
.xChromaOffset = fvkutils::getChromaLocation(chroma.xChromaOffset),
|
||||
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
|
||||
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
|
||||
};
|
||||
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
|
||||
VkResult result = vkCreateSamplerYcbcrConversion(device, &conversionInfo,
|
||||
nullptr, &conversion);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "Unable to create Ycbcr Conversion."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
|
||||
.pNext = nullptr,
|
||||
.conversion = conversion,
|
||||
};
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = &samplerYcbcrConversionInfo,
|
||||
.flags = 0,
|
||||
.image = image,
|
||||
.viewType = viewType,
|
||||
.format = VK_FORMAT_UNDEFINED,
|
||||
.components = swizzle,
|
||||
.subresourceRange = range,
|
||||
};
|
||||
VkImageView imageView;
|
||||
result = vkCreateImageView(device, &viewInfo, VKALLOC, &imageView);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "Unable to create VkImageView."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
return imageView;
|
||||
}
|
||||
|
||||
VkSampler VulkanPlatform::createExternalSamplerImpl(
|
||||
VkDevice device, SamplerYcbcrConversion chroma, SamplerParams params,
|
||||
uint32_t internalFormat) {
|
||||
VkExternalFormatANDROID externalFormat = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
||||
.pNext = nullptr,
|
||||
.externalFormat = internalFormat,
|
||||
};
|
||||
|
||||
TextureSwizzle const swizzleArray[] = {chroma.r, chroma.g, chroma.b, chroma.a};
|
||||
VkSamplerYcbcrConversionCreateInfo conversionInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
||||
.pNext = &externalFormat,
|
||||
.format = VK_FORMAT_UNDEFINED,
|
||||
.ycbcrModel = fvkutils::getYcbcrModelConversion(chroma.ycbcrModel),
|
||||
.ycbcrRange = fvkutils::getYcbcrRange(chroma.ycbcrRange),
|
||||
.components = fvkutils::getSwizzleMap(swizzleArray),
|
||||
.xChromaOffset = fvkutils::getChromaLocation(chroma.xChromaOffset),
|
||||
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
|
||||
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
|
||||
};
|
||||
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
|
||||
VkResult result = vkCreateSamplerYcbcrConversion(device, &conversionInfo,
|
||||
nullptr, &conversion);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "Unable to create Ycbcr Conversion."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
|
||||
.pNext = nullptr,
|
||||
.conversion = conversion,
|
||||
};
|
||||
|
||||
VkSamplerCreateInfo samplerInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.pNext = &samplerYcbcrConversionInfo,
|
||||
.magFilter = fvkutils::getFilter(params.filterMag),
|
||||
.minFilter = fvkutils::getFilter(params.filterMin),
|
||||
.mipmapMode = fvkutils::getMipmapMode(params.filterMin),
|
||||
.addressModeU = fvkutils::getWrapMode(params.wrapS),
|
||||
.addressModeV = fvkutils::getWrapMode(params.wrapT),
|
||||
.addressModeW = fvkutils::getWrapMode(params.wrapR),
|
||||
.anisotropyEnable = params.anisotropyLog2 == 0 ? VK_FALSE : VK_TRUE,
|
||||
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
|
||||
.compareEnable = fvkutils::getCompareEnable(params.compareMode),
|
||||
.compareOp = fvkutils::getCompareOp(params.compareFunc),
|
||||
.minLod = 0.0f,
|
||||
.maxLod = fvkutils::getMaxLod(params.filterMin),
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
};
|
||||
VkSampler sampler;
|
||||
result = vkCreateSampler(device, &samplerInfo, VKALLOC, &sampler);
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "Unable to create sampler."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
return {
|
||||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
|
||||
|
||||
@@ -64,29 +64,16 @@ VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
}
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
||||
void* externalImage, VkDevice device) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device,
|
||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VkSampler VulkanPlatform::createExternalSamplerImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma,
|
||||
SamplerParams sampler,
|
||||
uint32_t internalFormat) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
||||
VkImageSubresourceRange range, VkImageViewType viewType, VkComponentMapping swizzle) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHR(void* nativeWindow,
|
||||
VkInstance instance, uint64_t flags) noexcept {
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
@@ -85,29 +85,16 @@ using namespace bluevk;
|
||||
namespace filament::backend {
|
||||
|
||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
||||
void* externalImage, VkDevice device) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
||||
ExternalImageHandleRef externalImage, VkDevice device,
|
||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageImpl(void* externalImage,
|
||||
VkDevice device, const VkAllocationCallbacks* allocator,
|
||||
const ExternalImageMetadata& metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VkSampler VulkanPlatform::createExternalSamplerImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma,
|
||||
SamplerParams sampler,
|
||||
uint32_t internalFormat) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
|
||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
||||
VkImageSubresourceRange range, VkImageViewType viewType, VkComponentMapping swizzle) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() {
|
||||
VulkanPlatform::ExtensionSet const ret = {
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
|
||||
@@ -588,79 +588,6 @@ VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]) {
|
||||
return map;
|
||||
}
|
||||
|
||||
VkFilter getFilter(SamplerMinFilter filter) {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
VkFilter getFilter(SamplerMagFilter filter) {
|
||||
switch (filter) {
|
||||
case SamplerMagFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMagFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerMipmapMode getMipmapMode(SamplerMinFilter filter) {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerAddressMode getWrapMode(SamplerWrapMode mode) {
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case SamplerWrapMode::CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case SamplerWrapMode::MIRRORED_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
VkBool32 getCompareEnable(SamplerCompareMode mode) {
|
||||
return mode == SamplerCompareMode::NONE ? VK_FALSE : VK_TRUE;
|
||||
}
|
||||
|
||||
float getMaxLod(SamplerMinFilter filter) {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
case SamplerMinFilter::LINEAR:
|
||||
// The Vulkan spec recommends a max LOD of 0.25 to "disable" mipmapping.
|
||||
// See "Mapping of OpenGL to Vulkan filter modes" in the VK Spec.
|
||||
return 0.25f;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_LOD_CLAMP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags) {
|
||||
VkShaderStageFlags flags = 0x0;
|
||||
if (any(stageFlags & ShaderStageFlags::VERTEX)) flags |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
@@ -56,19 +56,6 @@ uint32_t getComponentCount(VkFormat format);
|
||||
VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]);
|
||||
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags);
|
||||
|
||||
// Needed by the Platform for external sampler creation
|
||||
VkFilter getFilter(SamplerMinFilter filter);
|
||||
VkFilter getFilter(SamplerMagFilter filter);
|
||||
VkSamplerMipmapMode getMipmapMode(SamplerMinFilter filter);
|
||||
VkSamplerAddressMode getWrapMode(SamplerWrapMode mode);
|
||||
VkBool32 getCompareEnable(SamplerCompareMode mode);
|
||||
float getMaxLod(SamplerMinFilter filter);
|
||||
|
||||
// Ycbcr related functions
|
||||
VkSamplerYcbcrModelConversion getYcbcrModelConversion(SamplerYcbcrModelConversion model);
|
||||
VkSamplerYcbcrRange getYcbcrRange(SamplerYcbcrRange range);
|
||||
VkChromaLocation getChromaLocation(ChromaLocation loc);
|
||||
|
||||
inline VkImageViewType getViewType(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
|
||||
@@ -193,49 +193,6 @@ uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) {
|
||||
return mostSignificantBit((sampleCount - 1) & mask);
|
||||
}
|
||||
|
||||
VkSamplerYcbcrModelConversion getYcbcrModelConversion(
|
||||
SamplerYcbcrModelConversion model) {
|
||||
switch (model) {
|
||||
case SamplerYcbcrModelConversion::RGB_IDENTITY:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
|
||||
case SamplerYcbcrModelConversion::YCBCR_IDENTITY:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY;
|
||||
case SamplerYcbcrModelConversion::YCBCR_709:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
|
||||
case SamplerYcbcrModelConversion::YCBCR_601:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
|
||||
case SamplerYcbcrModelConversion::YCBCR_2020:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020;
|
||||
default:
|
||||
assert_invariant(false &&
|
||||
"Unknown data type, conversion is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerYcbcrRange getYcbcrRange(SamplerYcbcrRange range) {
|
||||
switch (range) {
|
||||
case SamplerYcbcrRange::ITU_FULL:
|
||||
return VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
|
||||
case SamplerYcbcrRange::ITU_NARROW:
|
||||
return VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
|
||||
default:
|
||||
assert_invariant(false &&
|
||||
"Unknown data type, conversion is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
VkChromaLocation getChromaLocation(ChromaLocation loc) {
|
||||
switch (loc) {
|
||||
case ChromaLocation::COSITED_EVEN:
|
||||
return VK_CHROMA_LOCATION_COSITED_EVEN;
|
||||
case ChromaLocation::MIDPOINT:
|
||||
return VK_CHROMA_LOCATION_MIDPOINT;
|
||||
default:
|
||||
assert_invariant(false &&
|
||||
"Unknown data type, conversion is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange& b) {
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUCONSTANTS_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUCONSTANTS_H
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// FWGPU is short for Filament WebGPU
|
||||
|
||||
// turn on runtime validation, namely for debugging, that would normally not run (for release)
|
||||
#define FWGPU_DEBUG_VALIDATION 0x00000001
|
||||
// print/log system component details to the console, e.g. about the
|
||||
// instance, surface, adapter, device, etc.
|
||||
#define FWGPU_PRINT_SYSTEM 0x00000002
|
||||
|
||||
// Set this to enable logging "only" to one output stream. This is useful in the case where we want
|
||||
// to debug with print statements and want ordered logging (e.g slog.i and slog.e will not appear in
|
||||
// order of calls).
|
||||
#define FWGPU_DEBUG_FORCE_LOG_TO_I 0x00000004
|
||||
|
||||
// Useful default combinations
|
||||
#define FWGPU_DEBUG_EVERYTHING 0xFFFFFFFF
|
||||
|
||||
#if defined(FILAMENT_BACKEND_DEBUG_FLAG)
|
||||
#define FWGPU_DEBUG_FORWARDED_FLAG (FILAMENT_BACKEND_DEBUG_FLAG & FWGPU_DEBUG_EVERYTHING)
|
||||
#else
|
||||
#define FWGPU_DEBUG_FORWARDED_FLAG 0
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define FWGPU_DEBUG_FLAGS FWGPU_DEBUG_FORWARDED_FLAG
|
||||
#else
|
||||
#define FWGPU_DEBUG_FLAGS 0
|
||||
#endif
|
||||
|
||||
#define FWGPU_ENABLED(flags) (((FWGPU_DEBUG_FLAGS) & (flags)) == (flags))
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_DEBUG_FORCE_LOG_TO_I)
|
||||
#define FWGPU_LOGI (utils::slog.i)
|
||||
#define FWGPU_LOGD FWGPU_LOGI
|
||||
#define FWGPU_LOGE FWGPU_LOGI
|
||||
#define FWGPU_LOGW FWGPU_LOGI
|
||||
#else
|
||||
#define FWGPU_LOGE (utils::slog.e)
|
||||
#define FWGPU_LOGW (utils::slog.w)
|
||||
#define FWGPU_LOGD (utils::slog.d)
|
||||
#define FWGPU_LOGI (utils::slog.i)
|
||||
#endif
|
||||
|
||||
#endif// TNT_FILAMENT_BACKEND_WEBGPUCONSTANTS_H
|
||||
@@ -14,254 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "webgpu/WebGPUDriver.h"
|
||||
|
||||
#include "webgpu/WebGPUConstants.h"
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include "CommandStreamDispatcher.h"
|
||||
#include "DriverBase.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <math/mat3.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ostream.h>
|
||||
#include "webgpu/WebGPUDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
#include <dawn/webgpu_cpp_print.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printInstanceDetails(wgpu::Instance const& instance) {
|
||||
wgpu::SupportedWGSLLanguageFeatures supportedWGSLLanguageFeatures{};
|
||||
if (!instance.GetWGSLLanguageFeatures(&supportedWGSLLanguageFeatures)) {
|
||||
FWGPU_LOGW << "Failed to get WebGPU instance supported WGSL language features"
|
||||
<< utils::io::endl;
|
||||
} else {
|
||||
FWGPU_LOGI << "WebGPU instance supported WGSL language features ("
|
||||
<< supportedWGSLLanguageFeatures.featureCount << "):" << utils::io::endl;
|
||||
if (supportedWGSLLanguageFeatures.featureCount > 0 &&
|
||||
supportedWGSLLanguageFeatures.features != nullptr) {
|
||||
std::for_each(supportedWGSLLanguageFeatures.features,
|
||||
supportedWGSLLanguageFeatures.features +
|
||||
supportedWGSLLanguageFeatures.featureCount,
|
||||
[](wgpu::WGSLLanguageFeatureName const featureName) {
|
||||
std::stringstream nameStream{};
|
||||
nameStream << featureName;
|
||||
FWGPU_LOGI << " " << nameStream.str() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printLimit(std::string_view name, const std::variant<uint32_t, uint64_t> value) {
|
||||
FWGPU_LOGI << " " << name.data() << ": ";
|
||||
bool undefined = true;
|
||||
if (std::holds_alternative<uint32_t>(value)) {
|
||||
if (std::get<uint32_t>(value) != WGPU_LIMIT_U32_UNDEFINED) {
|
||||
undefined = false;
|
||||
FWGPU_LOGI << std::get<uint32_t>(value);
|
||||
}
|
||||
} else if (std::holds_alternative<uint64_t>(value)) {
|
||||
if (std::get<uint64_t>(value) != WGPU_LIMIT_U64_UNDEFINED) {
|
||||
undefined = false;
|
||||
FWGPU_LOGI << std::get<uint64_t>(value);
|
||||
}
|
||||
}
|
||||
if (undefined) {
|
||||
FWGPU_LOGI << "UNDEFINED";
|
||||
}
|
||||
FWGPU_LOGI << utils::io::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printLimits(wgpu::Limits const& limits) {
|
||||
printLimit("maxTextureDimension1D", limits.maxTextureDimension1D);
|
||||
printLimit("maxTextureDimension2D", limits.maxTextureDimension2D);
|
||||
printLimit("maxTextureDimension3D", limits.maxTextureDimension3D);
|
||||
printLimit("maxTextureArrayLayers", limits.maxTextureArrayLayers);
|
||||
printLimit("maxBindGroups", limits.maxBindGroups);
|
||||
printLimit("maxBindGroupsPlusVertexBuffers", limits.maxBindGroupsPlusVertexBuffers);
|
||||
printLimit("maxBindingsPerBindGroup", limits.maxBindingsPerBindGroup);
|
||||
printLimit("maxDynamicUniformBuffersPerPipelineLayout",
|
||||
limits.maxDynamicUniformBuffersPerPipelineLayout);
|
||||
printLimit("maxDynamicStorageBuffersPerPipelineLayout",
|
||||
limits.maxDynamicStorageBuffersPerPipelineLayout);
|
||||
printLimit("maxSampledTexturesPerShaderStage", limits.maxSampledTexturesPerShaderStage);
|
||||
printLimit("maxSamplersPerShaderStage", limits.maxSamplersPerShaderStage);
|
||||
printLimit("maxStorageBuffersPerShaderStage", limits.maxStorageBuffersPerShaderStage);
|
||||
printLimit("maxStorageTexturesPerShaderStage", limits.maxStorageTexturesPerShaderStage);
|
||||
printLimit("maxUniformBuffersPerShaderStage", limits.maxUniformBuffersPerShaderStage);
|
||||
printLimit("maxUniformBufferBindingSize", limits.maxUniformBufferBindingSize);
|
||||
printLimit("maxStorageBufferBindingSize", limits.maxStorageBufferBindingSize);
|
||||
printLimit("minUniformBufferOffsetAlignment", limits.minUniformBufferOffsetAlignment);
|
||||
printLimit("minStorageBufferOffsetAlignment", limits.minStorageBufferOffsetAlignment);
|
||||
printLimit("maxVertexBuffers", limits.maxVertexBuffers);
|
||||
printLimit("maxBufferSize", limits.maxBufferSize);
|
||||
printLimit("maxVertexAttributes", limits.maxVertexAttributes);
|
||||
printLimit("maxVertexBufferArrayStride", limits.maxVertexBufferArrayStride);
|
||||
printLimit("maxInterStageShaderComponents", limits.maxInterStageShaderComponents);
|
||||
printLimit("maxInterStageShaderVariables", limits.maxInterStageShaderVariables);
|
||||
printLimit("maxColorAttachments", limits.maxColorAttachments);
|
||||
printLimit("maxColorAttachmentBytesPerSample", limits.maxColorAttachmentBytesPerSample);
|
||||
printLimit("maxComputeWorkgroupStorageSize", limits.maxComputeWorkgroupStorageSize);
|
||||
printLimit("maxComputeInvocationsPerWorkgroup", limits.maxComputeInvocationsPerWorkgroup);
|
||||
printLimit("maxComputeWorkgroupSizeX", limits.maxComputeWorkgroupSizeX);
|
||||
printLimit("maxComputeWorkgroupSizeY", limits.maxComputeWorkgroupSizeY);
|
||||
printLimit("maxComputeWorkgroupSizeZ", limits.maxComputeWorkgroupSizeZ);
|
||||
printLimit("maxComputeWorkgroupsPerDimension", limits.maxComputeWorkgroupsPerDimension);
|
||||
printLimit("maxStorageBuffersInVertexStage", limits.maxStorageBuffersInVertexStage);
|
||||
printLimit("maxStorageTexturesInVertexStage", limits.maxStorageTexturesInVertexStage);
|
||||
printLimit("maxStorageBuffersInFragmentStage", limits.maxStorageBuffersInFragmentStage);
|
||||
printLimit("maxStorageTexturesInFragmentStage", limits.maxStorageTexturesInFragmentStage);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printAdapterDetails(wgpu::Adapter const& adapter) {
|
||||
wgpu::DawnAdapterPropertiesPowerPreference powerPreferenceProperties{};
|
||||
wgpu::AdapterInfo adapterInfo{};
|
||||
adapterInfo.nextInChain = &powerPreferenceProperties;
|
||||
if (!adapter.GetInfo(&adapterInfo)) {
|
||||
FWGPU_LOGW << "Failed to get WebGPU adapter info" << utils::io::endl;
|
||||
} else {
|
||||
std::stringstream backendTypeStream{};
|
||||
backendTypeStream << adapterInfo.backendType;
|
||||
std::stringstream adapterTypeStream{};
|
||||
adapterTypeStream << adapterInfo.adapterType;
|
||||
std::stringstream powerPreferenceStream{};
|
||||
powerPreferenceStream << powerPreferenceProperties.powerPreference;
|
||||
FWGPU_LOGI << "WebGPU adapter info:" << utils::io::endl;
|
||||
FWGPU_LOGI << " vendor: " << adapterInfo.vendor.data << utils::io::endl;
|
||||
FWGPU_LOGI << " architecture: " << adapterInfo.architecture.data << utils::io::endl;
|
||||
FWGPU_LOGI << " device: " << adapterInfo.device.data << utils::io::endl;
|
||||
FWGPU_LOGI << " description: " << adapterInfo.description.data << utils::io::endl;
|
||||
FWGPU_LOGI << " backend type: " << backendTypeStream.str().data() << utils::io::endl;
|
||||
FWGPU_LOGI << " adapter type: " << adapterTypeStream.str().data() << utils::io::endl;
|
||||
FWGPU_LOGI << " device ID: " << adapterInfo.deviceID << utils::io::endl;
|
||||
FWGPU_LOGI << " vendor ID: " << adapterInfo.vendorID << utils::io::endl;
|
||||
FWGPU_LOGI << " subgroup min size: " << adapterInfo.subgroupMinSize << utils::io::endl;
|
||||
FWGPU_LOGI << " subgroup max size: " << adapterInfo.subgroupMaxSize << utils::io::endl;
|
||||
FWGPU_LOGI << " compatibility mode: " << bool(adapterInfo.compatibilityMode)
|
||||
<< utils::io::endl;
|
||||
FWGPU_LOGI << " power preference: " << powerPreferenceStream.str() << utils::io::endl;
|
||||
}
|
||||
wgpu::SupportedFeatures supportedFeatures{};
|
||||
adapter.GetFeatures(&supportedFeatures);
|
||||
FWGPU_LOGI << "WebGPU adapter supported features (" << supportedFeatures.featureCount
|
||||
<< "):" << utils::io::endl;
|
||||
if (supportedFeatures.featureCount > 0 && supportedFeatures.features != nullptr) {
|
||||
std::for_each(supportedFeatures.features,
|
||||
supportedFeatures.features + supportedFeatures.featureCount,
|
||||
[](wgpu::FeatureName const name) {
|
||||
std::stringstream nameStream{};
|
||||
nameStream << name;
|
||||
FWGPU_LOGI << " " << nameStream.str().data() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
wgpu::SupportedLimits supportedLimits{};
|
||||
if (!adapter.GetLimits(&supportedLimits)) {
|
||||
FWGPU_LOGW << "Failed to get WebGPU adapter supported limits" << utils::io::endl;
|
||||
} else {
|
||||
FWGPU_LOGI << "WebGPU adapter supported limits:" << utils::io::endl;
|
||||
printLimits(supportedLimits.limits);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printSurfaceCapabilitiesDetails(wgpu::SurfaceCapabilities const& capabilities) {
|
||||
std::stringstream usages_stream{};
|
||||
usages_stream << capabilities.usages;
|
||||
FWGPU_LOGI << "WebGPU surface capabilities:" << utils::io::endl;
|
||||
FWGPU_LOGI << " surface usages: " << usages_stream.str().data() << utils::io::endl;
|
||||
FWGPU_LOGI << " surface formats (" << capabilities.formatCount << "):" << utils::io::endl;
|
||||
if (capabilities.formatCount > 0 && capabilities.formats != nullptr) {
|
||||
std::for_each(capabilities.formats, capabilities.formats + capabilities.formatCount,
|
||||
[](wgpu::TextureFormat const format) {
|
||||
std::stringstream format_stream{};
|
||||
format_stream << format;
|
||||
FWGPU_LOGI << " " << format_stream.str().data() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
FWGPU_LOGI << " surface present modes (" << capabilities.presentModeCount
|
||||
<< "):" << utils::io::endl;
|
||||
if (capabilities.presentModeCount > 0 && capabilities.presentModes != nullptr) {
|
||||
std::for_each(capabilities.presentModes,
|
||||
capabilities.presentModes + capabilities.presentModeCount,
|
||||
[](wgpu::PresentMode const presentMode) {
|
||||
std::stringstream present_mode_stream{};
|
||||
present_mode_stream << presentMode;
|
||||
FWGPU_LOGI << " " << present_mode_stream.str().data() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
FWGPU_LOGI << " surface alpha modes (" << capabilities.alphaModeCount
|
||||
<< "):" << utils::io::endl;
|
||||
if (capabilities.alphaModeCount > 0 && capabilities.alphaModes != nullptr) {
|
||||
std::for_each(capabilities.alphaModes,
|
||||
capabilities.alphaModes + capabilities.alphaModeCount,
|
||||
[](wgpu::CompositeAlphaMode const alphaMode) {
|
||||
std::stringstream alpha_mode_stream{};
|
||||
alpha_mode_stream << alphaMode;
|
||||
FWGPU_LOGI << " " << alpha_mode_stream.str().data() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
void printDeviceDetails(wgpu::Device const& device) {
|
||||
wgpu::SupportedFeatures supportedFeatures{};
|
||||
device.GetFeatures(&supportedFeatures);
|
||||
FWGPU_LOGI << "WebGPU device supported features (" << supportedFeatures.featureCount
|
||||
<< "):" << utils::io::endl;
|
||||
if (supportedFeatures.featureCount > 0 && supportedFeatures.features != nullptr) {
|
||||
std::for_each(supportedFeatures.features,
|
||||
supportedFeatures.features + supportedFeatures.featureCount,
|
||||
[](wgpu::FeatureName const name) {
|
||||
std::stringstream nameStream{};
|
||||
nameStream << name;
|
||||
FWGPU_LOGI << " " << nameStream.str().data() << utils::io::endl;
|
||||
});
|
||||
}
|
||||
wgpu::SupportedLimits supportedLimits{};
|
||||
if (!device.GetLimits(&supportedLimits)) {
|
||||
FWGPU_LOGW << "Failed to get WebGPU supported device limits" << utils::io::endl;
|
||||
} else {
|
||||
FWGPU_LOGI << "WebGPU device supported limits:" << utils::io::endl;
|
||||
printLimits(supportedLimits.limits);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}// namespace
|
||||
|
||||
Driver* WebGPUDriver::create(WebGPUPlatform& platform) noexcept {
|
||||
return new WebGPUDriver(platform);
|
||||
Driver* WebGPUDriver::create() {
|
||||
return new WebGPUDriver();
|
||||
}
|
||||
|
||||
WebGPUDriver::WebGPUDriver(WebGPUPlatform& platform) noexcept
|
||||
: mPlatform(platform) {
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
printInstanceDetails(mPlatform.getInstance());
|
||||
#endif
|
||||
}
|
||||
WebGPUDriver::WebGPUDriver() noexcept = default;
|
||||
|
||||
WebGPUDriver::~WebGPUDriver() noexcept = default;
|
||||
|
||||
@@ -278,7 +45,7 @@ ShaderModel WebGPUDriver::getShaderModel() const noexcept {
|
||||
}
|
||||
|
||||
ShaderLanguage WebGPUDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::WGSL;
|
||||
return ShaderLanguage::ESSL3;
|
||||
}
|
||||
|
||||
// explicit instantiation of the Dispatcher
|
||||
@@ -356,188 +123,6 @@ void WebGPUDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> tqh)
|
||||
void WebGPUDriver::destroyDescriptorSet(Handle<HwDescriptorSet> tqh) {
|
||||
}
|
||||
|
||||
Handle<HwSwapChain> WebGPUDriver::createSwapChainS() noexcept {
|
||||
return Handle<HwSwapChain>((Handle<HwSwapChain>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwSwapChain> WebGPUDriver::createSwapChainHeadlessS() noexcept {
|
||||
return Handle<HwSwapChain>((Handle<HwSwapChain>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::importTextureS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwProgram> WebGPUDriver::createProgramS() noexcept {
|
||||
return Handle<HwProgram>((Handle<HwProgram>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwFence> WebGPUDriver::createFenceS() noexcept {
|
||||
return Handle<HwFence>((Handle<HwFence>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTimerQuery> WebGPUDriver::createTimerQueryS() noexcept {
|
||||
return Handle<HwTimerQuery>((Handle<HwTimerQuery>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwIndexBuffer> WebGPUDriver::createIndexBufferS() noexcept {
|
||||
return Handle<HwIndexBuffer>((Handle<HwIndexBuffer>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureViewS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwBufferObject> WebGPUDriver::createBufferObjectS() noexcept {
|
||||
return Handle<HwBufferObject>((Handle<HwBufferObject>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwRenderTarget> WebGPUDriver::createRenderTargetS() noexcept {
|
||||
return Handle<HwRenderTarget>((Handle<HwRenderTarget>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwVertexBuffer> WebGPUDriver::createVertexBufferS() noexcept {
|
||||
return Handle<HwVertexBuffer>((Handle<HwVertexBuffer>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwDescriptorSet> WebGPUDriver::createDescriptorSetS() noexcept {
|
||||
return Handle<HwDescriptorSet>((Handle<HwDescriptorSet>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwRenderPrimitive> WebGPUDriver::createRenderPrimitiveS() noexcept {
|
||||
return Handle<HwRenderPrimitive>((Handle<HwRenderPrimitive>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwVertexBufferInfo> WebGPUDriver::createVertexBufferInfoS() noexcept {
|
||||
return Handle<HwVertexBufferInfo>((Handle<HwVertexBufferInfo>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureViewSwizzleS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwRenderTarget> WebGPUDriver::createDefaultRenderTargetS() noexcept {
|
||||
return Handle<HwRenderTarget>((Handle<HwRenderTarget>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwDescriptorSetLayout> WebGPUDriver::createDescriptorSetLayoutS() noexcept {
|
||||
return Handle<HwDescriptorSetLayout>(
|
||||
(Handle<HwDescriptorSetLayout>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureExternalImageS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureExternalImage2S() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
Handle<HwTexture> WebGPUDriver::createTextureExternalImagePlaneS() noexcept {
|
||||
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
mSurface= mPlatform.createSurface(nativeWindow, flags);
|
||||
mAdapter = mPlatform.requestAdapter(mSurface);
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
printAdapterDetails(mAdapter);
|
||||
wgpu::SurfaceCapabilities surfaceCapabilities{};
|
||||
if (!mSurface.GetCapabilities(mAdapter, &surfaceCapabilities)) {
|
||||
FWGPU_LOGW << "Failed to get WebGPU surface capabilities" << utils::io::endl;
|
||||
} else {
|
||||
printSurfaceCapabilitiesDetails(surfaceCapabilities);
|
||||
}
|
||||
#endif
|
||||
mDevice = mPlatform.requestDevice(mAdapter);
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
printDeviceDetails(mDevice);
|
||||
#endif
|
||||
mQueue = mDevice.GetQueue();
|
||||
// TODO configure the surface (maybe before or after creating the swapchain?
|
||||
// how do we get the surface extent?)
|
||||
// TODO actually create the swapchain
|
||||
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
|
||||
"background components have been instantiated/selected, such as surface/screen, "
|
||||
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
|
||||
<< utils::io::endl;
|
||||
#if !FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) && !defined(NDEBUG)
|
||||
FWGPU_LOGI << "If the FILAMENT_BACKEND_DEBUG_FLAG variable were set with the " << utils::io::hex
|
||||
<< FWGPU_PRINT_SYSTEM << utils::io::dec
|
||||
<< " bit flag on during build time the application would print system details "
|
||||
"about the selected graphics device, surface, etc. To see this try "
|
||||
"rebuilding Filament with that flag, e.g. ./build.sh -x "
|
||||
<< FWGPU_PRINT_SYSTEM << " ..." << utils::io::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||
uint32_t height, uint64_t flags) {}
|
||||
|
||||
void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes) {}
|
||||
|
||||
void WebGPUDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh, uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih) {}
|
||||
|
||||
void WebGPUDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage) {}
|
||||
|
||||
void WebGPUDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage) {}
|
||||
|
||||
void WebGPUDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage) {}
|
||||
|
||||
void WebGPUDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
uint8_t baseLevel, uint8_t levelCount) {}
|
||||
|
||||
void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a) {}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage) {}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* externalImage) {}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane) {}
|
||||
|
||||
void WebGPUDriver::importTextureR(Handle<HwTexture> th, intptr_t id, SamplerType target,
|
||||
uint8_t levels, TextureFormat format, uint8_t samples, uint32_t w, uint32_t h,
|
||||
uint32_t depth, TextureUsage usage) {}
|
||||
|
||||
void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph, Handle<HwVertexBuffer> vbh,
|
||||
Handle<HwIndexBuffer> ibh, PrimitiveType pt) {}
|
||||
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {}
|
||||
|
||||
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {}
|
||||
|
||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> rth, TargetBufferFlags targets,
|
||||
uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color,
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil) {}
|
||||
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
backend::DescriptorSetLayout&& info) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh) {}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
|
||||
return {};
|
||||
}
|
||||
@@ -546,11 +131,9 @@ Handle<HwStream> WebGPUDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void WebGPUDriver::setAcquiredImage(Handle<HwStream> sh, void* image, const math::mat3f& transform,
|
||||
CallbackHandler* handler, StreamCallback cb, void* userData) {}
|
||||
|
||||
void WebGPUDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh,
|
||||
BufferObjectStreamDescriptor&& streams) {}
|
||||
void WebGPUDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
|
||||
CallbackHandler* handler, StreamCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) {
|
||||
}
|
||||
@@ -651,18 +234,10 @@ uint8_t WebGPUDriver::getMaxDrawBuffers() {
|
||||
return MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxUniformBufferSize(SamplerType) {
|
||||
size_t WebGPUDriver::getMaxUniformBufferSize() {
|
||||
return 16384u;
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxTextureSize() {
|
||||
return 2048u;
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxArrayTextureLayers() {
|
||||
return 256u;
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor&& p,
|
||||
uint32_t byteOffset) {
|
||||
scheduleDestroy(std::move(p));
|
||||
|
||||
@@ -17,44 +17,26 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
|
||||
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/Driver.h"
|
||||
#include <backend/DriverEnums.h>
|
||||
#include "DriverBase.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* WebGPU backend (driver) implementation
|
||||
*/
|
||||
class WebGPUDriver final : public DriverBase {
|
||||
public:
|
||||
WebGPUDriver() noexcept;
|
||||
~WebGPUDriver() noexcept override;
|
||||
Dispatcher getDispatcher() const noexcept final;
|
||||
|
||||
[[nodiscard]] Dispatcher getDispatcher() const noexcept final;
|
||||
[[nodiscard]] static Driver* create(WebGPUPlatform& platform) noexcept;
|
||||
public:
|
||||
static Driver* create();
|
||||
|
||||
private:
|
||||
explicit WebGPUDriver(WebGPUPlatform& platform) noexcept;
|
||||
[[nodiscard]] ShaderModel getShaderModel() const noexcept final;
|
||||
[[nodiscard]] ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
|
||||
// the platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
|
||||
// handled in the WebGPUPlatform
|
||||
WebGPUPlatform& mPlatform;
|
||||
wgpu::Surface mSurface = nullptr;
|
||||
wgpu::Adapter mAdapter = nullptr;
|
||||
wgpu::Device mDevice = nullptr;
|
||||
wgpu::Queue mQueue = nullptr;
|
||||
uint64_t mNextFakeHandle = 1;
|
||||
uint64_t nextFakeHandle = 1;
|
||||
|
||||
/*
|
||||
* Driver interface
|
||||
@@ -63,19 +45,20 @@ private:
|
||||
template<typename T>
|
||||
friend class ConcreteDispatcher;
|
||||
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
UTILS_ALWAYS_INLINE inline void methodName(paramsDecl);
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params) \
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params) \
|
||||
RetType methodName(paramsDecl) override;
|
||||
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
|
||||
RetType methodName##S() noexcept override; \
|
||||
UTILS_ALWAYS_INLINE inline void methodName##R(RetType, paramsDecl);
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
|
||||
RetType methodName##S() noexcept override { \
|
||||
return RetType((RetType::HandleId)nextFakeHandle++); } \
|
||||
UTILS_ALWAYS_INLINE inline void methodName##R(RetType, paramsDecl) { }
|
||||
|
||||
#include "private/backend/DriverAPI.inc"
|
||||
};
|
||||
|
||||
}// namespace filament::backend
|
||||
} // namespace filament
|
||||
|
||||
#endif// TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
|
||||
#endif // TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "webgpu/WebGPUPlatform.h"
|
||||
#include "webgpu/WebGPUDriver.h"
|
||||
|
||||
#include "utils/Log.h"
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
Driver* WebGPUPlatform::createDriver(void* const sharedContext , const Platform::DriverConfig& driverConfig) noexcept {
|
||||
wgpu::InstanceDescriptor instance_descriptor {};
|
||||
wgpu::Instance instance = wgpu::CreateInstance(&instance_descriptor);
|
||||
if (instance) {
|
||||
utils::slog.i << " WebGPU instance created\n";
|
||||
} else {
|
||||
utils::slog.e << " WebGPU instance failed to create\n";
|
||||
return nullptr;
|
||||
}
|
||||
return WebGPUDriver::create();
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_WEBGPUPLATFORM_H
|
||||
#define TNT_FILAMENT_BACKEND_WEBGPUPLATFORM_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include "webgpu/webgpu_cpp.h"
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class WebGPUPlatform
|
||||
final : public Platform {
|
||||
public:
|
||||
|
||||
int getOSVersion() const noexcept final { return 0; }
|
||||
|
||||
~WebGPUPlatform() noexcept override = default;
|
||||
|
||||
protected:
|
||||
|
||||
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_WEBGPUPLATFORM_H
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include "webgpu/WebGPUConstants.h"
|
||||
#include "webgpu/WebGPUDriver.h"
|
||||
|
||||
#include <backend/Platform.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <dawn/webgpu_cpp_print.h>
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
|
||||
/**
|
||||
* WebGPU Backend implementation common across platforms or operating systems (at least for now).
|
||||
* Some of these functions may likely be refactored to platform/OS-specific implementations
|
||||
* over time as needed. The caller of the WebGPUPlatform doesn't need to care which is the case.
|
||||
*/
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
namespace {
|
||||
|
||||
//either returns a valid instance or panics
|
||||
[[nodiscard]] wgpu::Instance createInstance() {
|
||||
wgpu::DawnTogglesDescriptor dawnTogglesDescriptor{};
|
||||
#if defined(FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING)
|
||||
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
|
||||
FWGPU_LOGI << "setting on toggle enable_immediate_error_handling" << utils::io::endl;
|
||||
#endif
|
||||
/**
|
||||
* Have the un-captured error callback invoked immediately when an error occurs, rather than
|
||||
* waiting for the next Tick. This enables using the stack trace in which the un-captured error
|
||||
* occurred when breaking into the un-captured error callback.
|
||||
* https://crbug.com/dawn/1789
|
||||
*/
|
||||
static const char* toggleName = "enable_immediate_error_handling";
|
||||
dawnTogglesDescriptor.enabledToggleCount = 1;
|
||||
dawnTogglesDescriptor.enabledToggles = &toggleName;
|
||||
#endif
|
||||
wgpu::InstanceDescriptor instanceDescriptor{
|
||||
.nextInChain = &dawnTogglesDescriptor,
|
||||
.capabilities = {
|
||||
.timedWaitAnyEnable = true// TODO consider using pure async instead
|
||||
}
|
||||
};
|
||||
wgpu::Instance instance = wgpu::CreateInstance(&instanceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(instance != nullptr) << "Unable to create webgpu instance.";
|
||||
return instance;
|
||||
}
|
||||
|
||||
}// namespace
|
||||
|
||||
wgpu::Adapter WebGPUPlatform::requestAdapter(wgpu::Surface const& surface) {
|
||||
// TODO consider power preference etc. (can be custom preferences passed to the platform or
|
||||
// based on whether this is a Mobile or Desktop system,
|
||||
// etc...)
|
||||
wgpu::RequestAdapterOptions adaptorOptions{ .compatibleSurface = surface };
|
||||
// note this just gets the first adapter
|
||||
wgpu::Adapter adapter = nullptr;
|
||||
wgpu::WaitStatus status = mInstance.WaitAny(
|
||||
mInstance.RequestAdapter(&adaptorOptions, wgpu::CallbackMode::WaitAnyOnly,
|
||||
[&adapter](wgpu::RequestAdapterStatus const status,
|
||||
wgpu::Adapter const& readyAdapter, wgpu::StringView const message) {
|
||||
// TODO consider more robust error handling
|
||||
FILAMENT_CHECK_POSTCONDITION(status == wgpu::RequestAdapterStatus::Success)
|
||||
<< "Unable to request a WebGPU adapter. Status "
|
||||
<< static_cast<uint32_t>(status)
|
||||
<< " with message: " << message.data;
|
||||
adapter = readyAdapter;
|
||||
}),
|
||||
UINT16_MAX);// TODO define reasonable timeout (or do this asynchronously)
|
||||
FILAMENT_CHECK_POSTCONDITION(status == wgpu::WaitStatus::Success)
|
||||
<< "Non-successful wait status requesting a WebGPU adapter "
|
||||
<< static_cast<uint32_t>(status);
|
||||
FILAMENT_CHECK_POSTCONDITION(adapter != nullptr)
|
||||
<< "Failed to get a WebGPU adapter for the platform";
|
||||
// TODO consider validating adapter has required features and/or limits
|
||||
return adapter;
|
||||
}
|
||||
|
||||
wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
|
||||
// TODO consider passing required features and/or limits
|
||||
wgpu::DeviceDescriptor deviceDescriptor{};
|
||||
deviceDescriptor.label = "graphics_device";
|
||||
deviceDescriptor.defaultQueue.label = "default_queue";
|
||||
deviceDescriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
|
||||
[](wgpu::Device const&, wgpu::DeviceLostReason const& reason,
|
||||
wgpu::StringView message) {
|
||||
if (reason == wgpu::DeviceLostReason::Destroyed) {
|
||||
FWGPU_LOGD << "WebGPU device lost due to being destroyed (expected)"
|
||||
<< utils::io::endl;
|
||||
return;
|
||||
}
|
||||
// TODO try recreating the device instead of just panicking
|
||||
std::stringstream reasonStream{};
|
||||
reasonStream << reason;
|
||||
FILAMENT_CHECK_POSTCONDITION(reason != wgpu::DeviceLostReason::Destroyed)
|
||||
<< "WebGPU device lost: " << reasonStream.str() << " " << message.data;
|
||||
});
|
||||
deviceDescriptor.SetUncapturedErrorCallback(
|
||||
[](wgpu::Device const&, wgpu::ErrorType errorType, wgpu::StringView message) {
|
||||
std::stringstream typeStream{};
|
||||
typeStream << errorType;
|
||||
FWGPU_LOGE << "WebGPU device error: " << typeStream.str() << " " << message.data
|
||||
<< utils::io::endl;
|
||||
});
|
||||
wgpu::Device device = nullptr;
|
||||
wgpu::WaitStatus status = mInstance.WaitAny(
|
||||
adapter.RequestDevice(&deviceDescriptor, wgpu::CallbackMode::WaitAnyOnly,
|
||||
[&device](wgpu::RequestDeviceStatus const status,
|
||||
wgpu::Device const& readyDevice, wgpu::StringView const message) {
|
||||
FILAMENT_CHECK_POSTCONDITION(status == wgpu::RequestDeviceStatus::Success)
|
||||
<< "Unable to request a WebGPU device. Status: "
|
||||
<< static_cast<uint32_t>(status)
|
||||
<< " with message: " << message.data;
|
||||
device = readyDevice;
|
||||
}),
|
||||
UINT64_MAX);// TODO define reasonable timeout (or do this asynchronously)
|
||||
FILAMENT_CHECK_POSTCONDITION(status == wgpu::WaitStatus::Success)
|
||||
<< "Non-successful wait status requesting a WebGPU device "
|
||||
<< static_cast<uint32_t>(status);
|
||||
FILAMENT_CHECK_POSTCONDITION(device != nullptr)
|
||||
<< "Failed to get a WebGPU device for the platform.";
|
||||
return device;
|
||||
}
|
||||
|
||||
Driver* WebGPUPlatform::createDriver(void* const sharedContext,
|
||||
const Platform::DriverConfig& /*driverConfig*/) noexcept {
|
||||
if (sharedContext) {
|
||||
FWGPU_LOGW << "sharedContext is ignored/unused in the WebGPU backend. A non-null "
|
||||
"sharedContext was provided, but it will be ignored."
|
||||
<< utils::io::endl;
|
||||
}
|
||||
return WebGPUDriver::create(*this);
|
||||
}
|
||||
|
||||
WebGPUPlatform::WebGPUPlatform()
|
||||
: mInstance(createInstance()) {}
|
||||
|
||||
}// namespace filament::backend
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* Android OS specific implementation aspects of the WebGPU backend
|
||||
*/
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t /*flags*/) {
|
||||
wgpu::SurfaceSourceAndroidNativeWindow surfaceSourceAndroidWindow{};
|
||||
surfaceSourceAndroidWindow.window = nativeWindow;
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor{
|
||||
.nextInChain = &surfaceSourceAndroidWindow,
|
||||
.label = "android_surface"
|
||||
};
|
||||
wgpu::Surface surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr) << "Unable to create Android-backed surface.";
|
||||
return surface;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Platform specific includes and defines
|
||||
#if defined(__APPLE__)
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#elif defined(FILAMENT_IOS)
|
||||
// Metal is not available when building for the iOS simulator on Desktop.
|
||||
#define METAL_AVAILABLE __has_include(<QuartzCore/CAMetalLayer.h>)
|
||||
#if METAL_AVAILABLE
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#endif
|
||||
// is this needed?
|
||||
#define METALVIEW_TAG 255
|
||||
#else
|
||||
#error Not a supported Apple + WebGPU platform
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Apple (Mac OS and IOS) specific implementation aspects of the WebGPU backend
|
||||
*/
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t /*flags*/) {
|
||||
wgpu::Surface surface = nullptr;
|
||||
#if defined(__APPLE__)
|
||||
auto nsView = (__bridge NSView*) nativeWindow;
|
||||
FILAMENT_CHECK_POSTCONDITION(nsView) << "Unable to obtain Metal-backed NSView.";
|
||||
[nsView setWantsLayer:YES];
|
||||
id metalLayer = [CAMetalLayer layer];
|
||||
[nsView setLayer:metalLayer];
|
||||
wgpu::SurfaceSourceMetalLayer surfaceSourceMetalLayer{};
|
||||
surfaceSourceMetalLayer.layer = (__bridge void*) metalLayer;
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor = {
|
||||
.nextInChain = &surfaceSourceMetalLayer,
|
||||
.label = "metal_surface",
|
||||
};
|
||||
surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr) << "Unable to create Metal-backed surface.";
|
||||
#elif defined(FILAMENT_IOS)
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow;
|
||||
wgpu::SurfaceSourceMetalLayer surfaceSourceMetalLayer{};
|
||||
surfaceSourceMetalLayer.layer = (__bridge void*) metalLayer;
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor = {
|
||||
.nextInChain = &surfaceSourceMetalLayer,
|
||||
.label = "metal_surface",
|
||||
};
|
||||
surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr) << "Unable to create Metal-backed surface.";
|
||||
#else
|
||||
#error Not a supported Apple + WebGPU platform
|
||||
#endif
|
||||
return surface;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#define LINUX_OR_FREEBSD 1
|
||||
#endif
|
||||
|
||||
// Platform specific includes and defines
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#include <dlfcn.h>
|
||||
namespace {
|
||||
typedef struct _wl {
|
||||
struct wl_display* display;
|
||||
struct wl_surface* surface;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} wl;
|
||||
}// namespace
|
||||
#elif defined(LINUX_OR_FREEBSD) && defined(FILAMENT_SUPPORTS_X11)
|
||||
// TODO: we should allow for headless on Linux explicitly. Right now this is the headless path
|
||||
// (with no FILAMENT_SUPPORTS_XCB or FILAMENT_SUPPORTS_XLIB).
|
||||
#include <dlfcn.h>
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
#include <xcb/xcb.h>
|
||||
namespace {
|
||||
typedef xcb_connection_t* (*XCB_CONNECT)(const char* displayname, int* screenp);
|
||||
}// namespace
|
||||
#endif
|
||||
#if defined(FILAMENT_SUPPORTS_XLIB)
|
||||
#include <X11/Xlib.h>
|
||||
namespace {
|
||||
typedef Display* (*X11_OPEN_DISPLAY)(const char*);
|
||||
}// namespace
|
||||
#endif
|
||||
static constexpr const char* LIBRARY_X11 = "libX11.so.6";
|
||||
namespace {
|
||||
struct XEnv {
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
XCB_CONNECT xcbConnect;
|
||||
xcb_connection_t* connection;
|
||||
#endif
|
||||
#if defined(FILAMENT_SUPPORTS_XLIB)
|
||||
X11_OPEN_DISPLAY openDisplay;
|
||||
Display* display;
|
||||
#endif
|
||||
void* library = nullptr;
|
||||
} g_x11;
|
||||
}// namespace
|
||||
#else
|
||||
#error Not a supported Linux or FeeBSD + WebGPU platform
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Linux OS specific implementation aspects of the WebGPU Backend
|
||||
*/
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t flags) {
|
||||
wgpu::Surface surface = nullptr;
|
||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
wl* ptrval = reinterpret_cast<wl*>(nativeWindow);
|
||||
wgpu::SurfaceSourceWaylandSurface surfaceSourceWayland{};
|
||||
surfaceSourceWayland.display = ptrval->display;
|
||||
surfaceSourceWayland.surface = ptrval->surface;
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor{
|
||||
.nextInChain = &surfaceSourceWayland,
|
||||
.label = "linux_wayland_surface"
|
||||
};
|
||||
surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Unable to create Linux Wayland-backed surface.";
|
||||
#elif defined(LINUX_OR_FREEBSD) && defined(FILAMENT_SUPPORTS_X11)
|
||||
if (g_x11.library == nullptr) {
|
||||
g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW);
|
||||
FILAMENT_CHECK_PRECONDITION(g_x11.library) << "Unable to open X11 library.";
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
g_x11.xcbConnect = (XCB_CONNECT) dlsym(g_x11.library, "xcb_connect");
|
||||
int screen = 0;
|
||||
g_x11.connection = g_x11.xcbConnect(nullptr, &screen);
|
||||
#endif
|
||||
#if defined(FILAMENT_SUPPORTS_XLIB)
|
||||
g_x11.openDisplay = (X11_OPEN_DISPLAY) dlsym(g_x11.library, "XOpenDisplay");
|
||||
g_x11.display = g_x11.openDisplay(NULL);
|
||||
FILAMENT_CHECK_PRECONDITION(g_x11.display) << "Unable to open X11 display.";
|
||||
#endif
|
||||
}
|
||||
#if defined(FILAMENT_SUPPORTS_XCB) || defined(FILAMENT_SUPPORTS_XLIB)
|
||||
bool useXcb = false;
|
||||
#endif
|
||||
#if defined(FILAMENT_SUPPORTS_XCB)
|
||||
#if defined(FILAMENT_SUPPORTS_XLIB)
|
||||
useXcb = (flags & SWAP_CHAIN_CONFIG_ENABLE_XCB) != 0;
|
||||
#else
|
||||
useXcb = true;
|
||||
#endif
|
||||
if (useXcb) {
|
||||
wgpu::SurfaceSourceXCBWindow surfaceSourceXcb{};
|
||||
surfaceSourceXcb.connection = g_x11.connection;
|
||||
surfaceSourceXcb.window = reinterpret_cast<uint32_t>(nativeWindow);
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor{
|
||||
.nextInChain = &surfaceSourceXcb,
|
||||
.label = "linux_xcb_surface"
|
||||
};
|
||||
surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Unable to create Linux (or FreeBSD) XCB-backed surface.";
|
||||
}
|
||||
#endif
|
||||
#if defined(FILAMENT_SUPPORTS_XLIB)
|
||||
if (!useXcb) {
|
||||
wgpu::SurfaceSourceXlibWindow surfaceSourceXlib{};
|
||||
surfaceSourceXlib.display = g_x11.display;
|
||||
surfaceSourceXlib.window = reinterpret_cast<uint64_t>(nativeWindow);
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor{
|
||||
.nextInChain = &surfaceSourceXlib,
|
||||
.label = "linux_xlib_surface"
|
||||
};
|
||||
surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Unable to create Linux (or FreeBSD) XLib-backed surface.";
|
||||
}
|
||||
#endif
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Cannot create WebGPU X11 surface for Linux (or FreeBSD) OS "
|
||||
"(not built with support for XCB or XLIB?)";
|
||||
#elif defined(__linux__)
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Cannot create WebGPU surface for Linux (or FreeBSD) OS "
|
||||
"(not built with support for Wayland or X11?)";
|
||||
#else
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr)
|
||||
<< "Not a supported (Linux) OS + WebGPU platform";
|
||||
#endif
|
||||
return surface;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* Windows OS specific implementation aspects of the WebGPU backend
|
||||
*/
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t /*flags*/) {
|
||||
// TODO verify this is necessary for Dawn implementation as well:
|
||||
// On (at least) NVIDIA drivers, the Vulkan implementation (specifically the call to
|
||||
// vkGetPhysicalDeviceSurfaceCapabilitiesKHR()) does not correctly handle the fact that
|
||||
// each native window has its own DPI_AWARENESS_CONTEXT, and erroneously uses the context
|
||||
// of the calling thread. As a workaround, we set the current thread's DPI_AWARENESS_CONTEXT
|
||||
// to that of the native window we've been given. This isn't a perfect solution, because an
|
||||
// application could create swap chains on multiple native windows with varying DPI-awareness,
|
||||
// but even then, at least one of the windows would be guaranteed to work correctly.
|
||||
SetThreadDpiAwarenessContext(GetWindowDpiAwarenessContext((HWND) nativeWindow));
|
||||
wgpu::SurfaceSourceWindowsHWND surfaceSourceWin{};
|
||||
surfaceSourceWin.hinstance = GetModuleHandle(nullptr);
|
||||
surfaceSourceWin.hwnd = nativeWindow;
|
||||
wgpu::SurfaceDescriptor surfaceDescriptor{
|
||||
.nextInChain = &surfaceSourceWin,
|
||||
.label = "windows_surface"
|
||||
};
|
||||
wgpu::Surface surface = mInstance.CreateSurface(&surfaceDescriptor);
|
||||
FILAMENT_CHECK_POSTCONDITION(surface != nullptr) << "Unable to create Windows-backed surface.";
|
||||
return surface;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Lifetimes.h"
|
||||
|
||||
#include "backend/Platform.h"
|
||||
#include "private/backend/DriverApi.h"
|
||||
|
||||
RenderFrame::RenderFrame(filament::backend::DriverApi& api): mApi(api) {
|
||||
mApi.beginFrame(0, 0, 0);
|
||||
}
|
||||
|
||||
RenderFrame::~RenderFrame() {
|
||||
mApi.endFrame(0);
|
||||
}
|
||||
|
||||
Cleanup::Cleanup(filament::backend::DriverApi& driverApi) : mDriverApi(driverApi) {}
|
||||
|
||||
Cleanup::~Cleanup() {
|
||||
for (const auto swapChain: mSwapChains) {
|
||||
mDriverApi.destroySwapChain(swapChain);
|
||||
}
|
||||
for (const auto descriptorSet : mDescriptorSets) {
|
||||
mDriverApi.destroyDescriptorSet(descriptorSet);
|
||||
}
|
||||
for (const auto descriptorSetLayout : mDescriptorSetLayouts) {
|
||||
mDriverApi.destroyDescriptorSetLayout(descriptorSetLayout);
|
||||
}
|
||||
for (const auto bufferObject : mBufferObjects) {
|
||||
mDriverApi.destroyBufferObject(bufferObject);
|
||||
}
|
||||
for (const auto program : mPrograms) {
|
||||
mDriverApi.destroyProgram(program);
|
||||
}
|
||||
for (const auto texture : mTextures) {
|
||||
mDriverApi.destroyTexture(texture);
|
||||
}
|
||||
for (const auto renderTarget : mRenderTargets) {
|
||||
mDriverApi.destroyRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
for (const auto& callback : mCallbacks) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::SwapChainHandle handle) {
|
||||
mSwapChains.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::DescriptorSetHandle handle) {
|
||||
mDescriptorSets.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(
|
||||
filament::backend::DescriptorSetLayoutHandle handle) {
|
||||
mDescriptorSetLayouts.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::BufferObjectHandle handle) {
|
||||
mBufferObjects.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::ProgramHandle handle) {
|
||||
mPrograms.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::TextureHandle handle) {
|
||||
mTextures.push_back(handle);
|
||||
}
|
||||
template <>
|
||||
void Cleanup::addInternal(filament::backend::RenderTargetHandle handle) {
|
||||
mRenderTargets.push_back(handle);
|
||||
}
|
||||
|
||||
void Cleanup::addPostCall(std::function<void()> callback){
|
||||
mCallbacks.emplace_back(std::move(callback));
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_LIFETIMES_H
|
||||
#define TNT_LIFETIMES_H
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
#include "backend/Handle.h"
|
||||
#include "backend/DriverApiForward.h"
|
||||
#include "BackendTest.h"
|
||||
|
||||
class RenderFrame {
|
||||
public:
|
||||
explicit RenderFrame(filament::backend::DriverApi& api);
|
||||
~RenderFrame();
|
||||
|
||||
RenderFrame(RenderFrame const& rhs) noexcept = delete;
|
||||
RenderFrame& operator=(RenderFrame const& rhs) noexcept = delete;
|
||||
RenderFrame(RenderFrame const&& rhs) noexcept = delete;
|
||||
RenderFrame& operator=(RenderFrame const&& rhs) noexcept = delete;
|
||||
|
||||
private:
|
||||
filament::backend::DriverApi& mApi;
|
||||
};
|
||||
|
||||
class Cleanup {
|
||||
public:
|
||||
/**
|
||||
* @param driverApi Must be valid for the entire lifetime of the Cleanup object.
|
||||
*/
|
||||
explicit Cleanup(filament::backend::DriverApi& driverApi);
|
||||
~Cleanup();
|
||||
|
||||
template <typename HandleType>
|
||||
filament::backend::Handle<HandleType> add(filament::backend::Handle<HandleType> handle);
|
||||
|
||||
void addPostCall(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
template <typename HandleType>
|
||||
void addInternal(filament::backend::Handle<HandleType> handle);
|
||||
|
||||
filament::backend::DriverApi & mDriverApi;
|
||||
|
||||
std::vector<filament::backend::SwapChainHandle> mSwapChains;
|
||||
std::vector<filament::backend::DescriptorSetHandle> mDescriptorSets;
|
||||
std::vector<filament::backend::DescriptorSetLayoutHandle> mDescriptorSetLayouts;
|
||||
std::vector<filament::backend::BufferObjectHandle> mBufferObjects;
|
||||
std::vector<filament::backend::ProgramHandle> mPrograms;
|
||||
std::vector<filament::backend::TextureHandle> mTextures;
|
||||
std::vector<filament::backend::RenderTargetHandle> mRenderTargets;
|
||||
|
||||
std::vector<std::function<void()>> mCallbacks;
|
||||
};
|
||||
|
||||
template <typename HandleType>
|
||||
filament::backend::Handle<HandleType> Cleanup::add(filament::backend::Handle<HandleType> handle) {
|
||||
addInternal(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
#endif //TNT_LIFETIMES_H
|
||||
@@ -30,8 +30,7 @@ enum class Backend : uint8_t {
|
||||
OPENGL = 1,
|
||||
VULKAN = 2,
|
||||
METAL = 3,
|
||||
WEBGPU = 4,
|
||||
NOOP = 5,
|
||||
NOOP = 4,
|
||||
};
|
||||
|
||||
struct NativeView {
|
||||
|
||||
@@ -90,9 +90,6 @@ ShaderGenerator::ShaderGenerator(std::string vertex, std::string fragment, Backe
|
||||
case Backend::METAL:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::MSL;
|
||||
break;
|
||||
case Backend::WEBGPU:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::WGSL;
|
||||
break;
|
||||
case Backend::NOOP:
|
||||
mShaderLanguage = filament::backend::ShaderLanguage::ESSL3;
|
||||
break;
|
||||
@@ -118,8 +115,6 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader(ShaderStage stage, std::s
|
||||
shader.insert(pos, "#define TARGET_METAL_ENVIRONMENT\n");
|
||||
} else if (backend == Backend::VULKAN) {
|
||||
shader.insert(pos, "#define TARGET_VULKAN_ENVIRONMENT\n");
|
||||
} else if (backend == Backend::WEBGPU) {
|
||||
shader.insert(pos, "#define TARGET_VULKAN_ENVIRONMENT\n");
|
||||
}
|
||||
|
||||
const char* shaderCString = shader.c_str();
|
||||
@@ -155,8 +150,7 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader(ShaderStage stage, std::s
|
||||
|
||||
assert_invariant(backend == Backend::OPENGL ||
|
||||
backend == Backend::METAL ||
|
||||
backend == Backend::VULKAN ||
|
||||
backend == Backend::WEBGPU);
|
||||
backend == Backend::VULKAN);
|
||||
|
||||
if (backend == Backend::OPENGL) {
|
||||
if (isMobile) {
|
||||
@@ -172,8 +166,6 @@ ShaderGenerator::Blob ShaderGenerator::transpileShader(ShaderStage stage, std::s
|
||||
return { result.c_str(), result.c_str() + result.length() + 1 };
|
||||
} else if (backend == Backend::VULKAN) {
|
||||
return { (uint8_t*)spirv.data(), (uint8_t*)(spirv.data() + spirv.size()) };
|
||||
} else if (backend == Backend::WEBGPU){
|
||||
filamat::GLSLPostProcessor::spirvToWgsl(&spirv, &result);
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
+141
-110
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "BackendTest.h"
|
||||
|
||||
#include "Lifetimes.h"
|
||||
#include "ShaderGenerator.h"
|
||||
#include "TrianglePrimitive.h"
|
||||
|
||||
@@ -196,8 +195,6 @@ static void createFaces(DriverApi& dapi, Handle<HwTexture> texture, int baseWidt
|
||||
|
||||
TEST_F(BackendTest, ColorMagnify) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
cleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
constexpr int kSrcTexWidth = 256;
|
||||
constexpr int kSrcTexHeight = 256;
|
||||
@@ -208,30 +205,30 @@ TEST_F(BackendTest, ColorMagnify) {
|
||||
constexpr int kNumLevels = 3;
|
||||
|
||||
// Create a SwapChain and make it current. We don't really use it so the res doesn't matter.
|
||||
auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0));
|
||||
auto swapChain = api.createSwapChainHeadless(256, 256, 0);
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
|
||||
// Create a source texture.
|
||||
Handle<HwTexture> const srcTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const srcTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool flipY = sBackend == Backend::OPENGL;
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 0, float3(0.5, 0, 0), flipY);
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 1, float3(0, 0, 0.5), flipY);
|
||||
|
||||
// Create a destination texture.
|
||||
Handle<HwTexture> const dstTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const dstTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kDstTexFormat, 1, kDstTexWidth, kDstTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Create a RenderTarget for each texture's miplevel.
|
||||
Handle<HwRenderTarget> srcRenderTargets[kNumLevels];
|
||||
Handle<HwRenderTarget> dstRenderTargets[kNumLevels];
|
||||
for (uint8_t level = 0; level < kNumLevels; level++) {
|
||||
srcRenderTargets[level] = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {}));
|
||||
dstRenderTargets[level] = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, 0 }, {}, {}));
|
||||
srcRenderTargets[level] = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {});
|
||||
dstRenderTargets[level] = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, 0 }, {}, {});
|
||||
}
|
||||
|
||||
// Do a "magnify" blit from level 1 of the source RT to the level 0 of the destination RT.
|
||||
@@ -241,18 +238,16 @@ TEST_F(BackendTest, ColorMagnify) {
|
||||
{0, 0, kSrcTexWidth >> srcLevel, kSrcTexHeight >> srcLevel}, SamplerMagFilter::LINEAR);
|
||||
|
||||
// Push through an empty frame to allow the texture to upload and the blit to execute.
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Grab a screenshot.
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "ColorMagnify.png" };
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
dumpScreenshot(api, dstRenderTargets[0], ¶ms);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
dumpScreenshot(api, dstRenderTargets[0], ¶ms);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Wait for the ReadPixels result to come back.
|
||||
api.finish();
|
||||
@@ -263,12 +258,18 @@ TEST_F(BackendTest, ColorMagnify) {
|
||||
const uint32_t expected = 0x410bdd31;
|
||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
||||
|
||||
// Cleanup.
|
||||
api.destroyTexture(srcTexture);
|
||||
api.destroyTexture(dstTexture);
|
||||
api.destroySwapChain(swapChain);
|
||||
for (auto rt : srcRenderTargets) api.destroyRenderTarget(rt);
|
||||
for (auto rt : dstRenderTargets) api.destroyRenderTarget(rt);
|
||||
executeCommands();
|
||||
}
|
||||
|
||||
TEST_F(BackendTest, ColorMinify) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
cleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
constexpr int kSrcTexWidth = 1024;
|
||||
constexpr int kSrcTexHeight = 1024;
|
||||
@@ -279,30 +280,30 @@ TEST_F(BackendTest, ColorMinify) {
|
||||
constexpr int kNumLevels = 3;
|
||||
|
||||
// Create a SwapChain and make it current. We don't really use it so the res doesn't matter.
|
||||
auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0));
|
||||
auto swapChain = api.createSwapChainHeadless(256, 256, 0);
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
|
||||
// Create a source texture.
|
||||
Handle<HwTexture> const srcTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const srcTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool flipY = sBackend == Backend::OPENGL;
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 0, float3(0.5, 0, 0), flipY);
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 1, float3(0, 0, 0.5), flipY);
|
||||
|
||||
// Create a destination texture.
|
||||
Handle<HwTexture> const dstTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const dstTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kDstTexFormat, 1, kDstTexWidth, kDstTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Create a RenderTarget for each texture's miplevel.
|
||||
Handle<HwRenderTarget> srcRenderTargets[kNumLevels];
|
||||
Handle<HwRenderTarget> dstRenderTargets[kNumLevels];
|
||||
for (uint8_t level = 0; level < kNumLevels; level++) {
|
||||
srcRenderTargets[level] = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {}));
|
||||
dstRenderTargets[level] = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, 0 }, {}, {}));
|
||||
srcRenderTargets[level] = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {});
|
||||
dstRenderTargets[level] = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, 0 }, {}, {});
|
||||
}
|
||||
|
||||
// Do a "minify" blit from level 1 of the source RT to the level 0 of the destination RT.
|
||||
@@ -313,7 +314,6 @@ TEST_F(BackendTest, ColorMinify) {
|
||||
srcRenderTargets[srcLevel], {0, 0, kSrcTexWidth >> srcLevel, kSrcTexHeight >> srcLevel},
|
||||
SamplerMagFilter::LINEAR);
|
||||
|
||||
|
||||
// Grab a screenshot.
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "ColorMinify.png" };
|
||||
dumpScreenshot(api, dstRenderTargets[0], ¶ms);
|
||||
@@ -325,11 +325,18 @@ TEST_F(BackendTest, ColorMinify) {
|
||||
const uint32_t expected = 0xf3d9c53f;
|
||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
||||
|
||||
// Cleanup.
|
||||
api.destroyTexture(srcTexture);
|
||||
api.destroyTexture(dstTexture);
|
||||
api.destroySwapChain(swapChain);
|
||||
for (auto rt : srcRenderTargets) api.destroyRenderTarget(rt);
|
||||
for (auto rt : dstRenderTargets) api.destroyRenderTarget(rt);
|
||||
executeCommands();
|
||||
}
|
||||
|
||||
TEST_F(BackendTest, ColorResolve) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
|
||||
constexpr int kSrcTexWidth = 256;
|
||||
constexpr int kSrcTexHeight = 256;
|
||||
@@ -349,40 +356,40 @@ TEST_F(BackendTest, ColorResolve) {
|
||||
triangleVs, triangleFs, sBackend, sIsMobilePlatform, std::move(descriptors));
|
||||
Program prog = shaderGen.getProgram(api);
|
||||
prog.descriptorBindings(1, {{ "Params", DescriptorType::UNIFORM_BUFFER, 0 }});
|
||||
program = cleanup.add(api.createProgram(std::move(prog)));
|
||||
program = api.createProgram(std::move(prog));
|
||||
}
|
||||
|
||||
DescriptorSetLayoutHandle descriptorSetLayout = cleanup.add(api.createDescriptorSetLayout({
|
||||
DescriptorSetLayoutHandle descriptorSetLayout = api.createDescriptorSetLayout({
|
||||
{{
|
||||
DescriptorType::UNIFORM_BUFFER,
|
||||
ShaderStageFlags::ALL_SHADER_STAGE_FLAGS, 0,
|
||||
DescriptorFlags::NONE, 0
|
||||
}}}));
|
||||
}}});
|
||||
|
||||
DescriptorSetHandle descriptorSet = cleanup.add(api.createDescriptorSet(descriptorSetLayout));
|
||||
DescriptorSetHandle descriptorSet = api.createDescriptorSet(descriptorSetLayout);
|
||||
|
||||
// Create a VertexBuffer, IndexBuffer, and RenderPrimitive.
|
||||
TrianglePrimitive const triangle(api);
|
||||
|
||||
// Create 4-sample texture.
|
||||
Handle<HwTexture> const srcColorTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const srcColorTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, 1, kColorTexFormat, kSampleCount, kSrcTexWidth, kSrcTexHeight, 1,
|
||||
TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Create 1-sample texture.
|
||||
Handle<HwTexture> const dstColorTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> const dstColorTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, 1, kColorTexFormat, 1, kDstTexWidth, kDstTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Create a 4-sample render target with the 4-sample texture.
|
||||
Handle<HwRenderTarget> const srcRenderTarget = cleanup.add(api.createRenderTarget(
|
||||
Handle<HwRenderTarget> const srcRenderTarget = api.createRenderTarget(
|
||||
TargetBufferFlags::COLOR, kSrcTexWidth, kSrcTexHeight, kSampleCount, 0,
|
||||
{{ srcColorTexture }}, {}, {}));
|
||||
{{ srcColorTexture }}, {}, {});
|
||||
|
||||
// Create a 1-sample render target with the 1-sample texture.
|
||||
Handle<HwRenderTarget> const dstRenderTarget = cleanup.add(api.createRenderTarget(
|
||||
Handle<HwRenderTarget> const dstRenderTarget = api.createRenderTarget(
|
||||
TargetBufferFlags::COLOR, kDstTexWidth, kDstTexHeight, 1, 0,
|
||||
{{ dstColorTexture }}, {}, {}));
|
||||
{{ dstColorTexture }}, {}, {});
|
||||
|
||||
// Prep for rendering.
|
||||
RenderPassParams params = {};
|
||||
@@ -401,8 +408,8 @@ TEST_F(BackendTest, ColorResolve) {
|
||||
state.rasterState.depthFunc = RasterState::DepthFunc::A;
|
||||
state.rasterState.culling = CullingMode::NONE;
|
||||
|
||||
auto ubuffer = cleanup.add(api.createBufferObject(sizeof(MaterialParams),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::STATIC));
|
||||
auto ubuffer = api.createBufferObject(sizeof(MaterialParams),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
|
||||
// Draw red triangle into srcRenderTarget.
|
||||
uploadUniforms(api, ubuffer, {
|
||||
.color = float4(1, 0, 0, 1),
|
||||
@@ -413,12 +420,11 @@ TEST_F(BackendTest, ColorResolve) {
|
||||
api.bindDescriptorSet(descriptorSet, 1, {});
|
||||
|
||||
// FIXME: on Metal this triangle is not drawn. Can't understand why.
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
api.beginFrame(0, 0, 0);
|
||||
api.beginRenderPass(srcRenderTarget, params);
|
||||
api.draw(state, triangle.getRenderPrimitive(), 0, 3, 1);
|
||||
api.endRenderPass();
|
||||
}
|
||||
api.endFrame(0);
|
||||
|
||||
// Resolve the MSAA render target into the single-sample render target.
|
||||
api.blitDEPRECATED(TargetBufferFlags::COLOR,
|
||||
@@ -437,15 +443,23 @@ TEST_F(BackendTest, ColorResolve) {
|
||||
const uint32_t expected = 0xebfac2ef;
|
||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", sparams.pixelHashResult, expected);
|
||||
EXPECT_TRUE(sparams.pixelHashResult == expected);
|
||||
|
||||
// Cleanup.
|
||||
api.destroyDescriptorSet(descriptorSet);
|
||||
api.destroyDescriptorSetLayout(descriptorSetLayout);
|
||||
api.destroyBufferObject(ubuffer);
|
||||
api.destroyProgram(program);
|
||||
api.destroyTexture(srcColorTexture);
|
||||
api.destroyTexture(dstColorTexture);
|
||||
api.destroyRenderTarget(srcRenderTarget);
|
||||
api.destroyRenderTarget(dstRenderTarget);
|
||||
flushAndWait();
|
||||
}
|
||||
|
||||
TEST_F(BackendTest, Blit2DTextureArray) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
cleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
api.startCapture(0);
|
||||
cleanup.addPostCall([&]() { api.stopCapture(0); });
|
||||
|
||||
constexpr int kSrcTexWidth = 256;
|
||||
constexpr int kSrcTexHeight = 256;
|
||||
@@ -460,27 +474,27 @@ TEST_F(BackendTest, Blit2DTextureArray) {
|
||||
constexpr int kDstTexLayer = 0;
|
||||
|
||||
// Create a SwapChain and make it current. We don't really use it so the res doesn't matter.
|
||||
auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0));
|
||||
auto swapChain = api.createSwapChainHeadless(256, 256, 0);
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
|
||||
// Create a source texture.
|
||||
Handle<HwTexture> srcTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> srcTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D_ARRAY, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, kSrcTexDepth,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool flipY = sBackend == Backend::OPENGL;
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 0, kSrcTexLayer, float3(0.5, 0, 0), flipY);
|
||||
|
||||
// Create a destination texture.
|
||||
Handle<HwTexture> dstTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> dstTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kDstTexFormat, 1, kDstTexWidth, kDstTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Create two RenderTargets.
|
||||
const int level = 0;
|
||||
Handle<HwRenderTarget> srcRenderTarget = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, kSrcTexLayer }, {}, {}));
|
||||
Handle<HwRenderTarget> dstRenderTarget = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, kDstTexLayer }, {}, {}));
|
||||
Handle<HwRenderTarget> srcRenderTarget = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, kSrcTexLayer }, {}, {});
|
||||
Handle<HwRenderTarget> dstRenderTarget = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kDstTexWidth >> level, kDstTexHeight >> level, 1, 0, { dstTexture, level, kDstTexLayer }, {}, {});
|
||||
|
||||
// Do a blit from kSrcTexLayer of the source RT to kDstTexLayer of the destination RT.
|
||||
const int srcLevel = 0;
|
||||
@@ -489,18 +503,16 @@ TEST_F(BackendTest, Blit2DTextureArray) {
|
||||
{0, 0, kSrcTexWidth >> srcLevel, kSrcTexHeight >> srcLevel}, SamplerMagFilter::LINEAR);
|
||||
|
||||
// Push through an empty frame to allow the texture to upload and the blit to execute.
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Grab a screenshot.
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "Blit2DTextureArray.png" };
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Wait for the ReadPixels result to come back.
|
||||
api.finish();
|
||||
@@ -511,12 +523,20 @@ TEST_F(BackendTest, Blit2DTextureArray) {
|
||||
const uint32_t expected = 0x8de7d55b;
|
||||
printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
||||
EXPECT_TRUE(params.pixelHashResult == expected);
|
||||
|
||||
// Cleanup.
|
||||
api.destroyTexture(srcTexture);
|
||||
api.destroyTexture(dstTexture);
|
||||
api.destroySwapChain(swapChain);
|
||||
api.destroyRenderTarget(srcRenderTarget);
|
||||
api.destroyRenderTarget(dstRenderTarget);
|
||||
executeCommands();
|
||||
|
||||
api.stopCapture(0);
|
||||
}
|
||||
|
||||
TEST_F(BackendTest, BlitRegion) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
cleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
constexpr int kSrcTexWidth = 1024;
|
||||
constexpr int kSrcTexHeight = 1024;
|
||||
@@ -529,21 +549,21 @@ TEST_F(BackendTest, BlitRegion) {
|
||||
constexpr int kDstLevel = 0;
|
||||
|
||||
// Create a SwapChain and make it current. We don't really use it so the res doesn't matter.
|
||||
auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0));
|
||||
auto swapChain = api.createSwapChainHeadless(256, 256, 0);
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
|
||||
// Create a source texture.
|
||||
Handle<HwTexture> srcTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> srcTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool flipY = sBackend == Backend::OPENGL;
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 0, float3(0.5, 0, 0), flipY);
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 1, float3(0, 0, 0.5), flipY);
|
||||
|
||||
// Create a destination texture.
|
||||
Handle<HwTexture> dstTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> dstTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kDstTexFormat, 1, kDstTexWidth, kDstTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
|
||||
// Blit one-quarter of src level 1 to dst level 0.
|
||||
Viewport srcRect = {
|
||||
@@ -563,34 +583,34 @@ TEST_F(BackendTest, BlitRegion) {
|
||||
// We purposely set the render target width and height to smaller than the texture, to check
|
||||
// that this case is handled correctly.
|
||||
Handle<HwRenderTarget> srcRenderTarget =
|
||||
cleanup.add(api.createRenderTarget(TargetBufferFlags::COLOR, srcRect.width,
|
||||
srcRect.height, 1, 0, {srcTexture, kSrcLevel, 0}, {}, {}));
|
||||
api.createRenderTarget(TargetBufferFlags::COLOR, srcRect.width,
|
||||
srcRect.height, 1, 0, {srcTexture, kSrcLevel, 0}, {}, {});
|
||||
Handle<HwRenderTarget> dstRenderTarget =
|
||||
cleanup.add(api.createRenderTarget(TargetBufferFlags::COLOR, kDstTexWidth >> kDstLevel,
|
||||
kDstTexHeight >> kDstLevel, 1, 0, {dstTexture, kDstLevel, 0}, {}, {}));
|
||||
api.createRenderTarget(TargetBufferFlags::COLOR, kDstTexWidth >> kDstLevel,
|
||||
kDstTexHeight >> kDstLevel, 1, 0, {dstTexture, kDstLevel, 0}, {}, {});
|
||||
|
||||
api.blitDEPRECATED(TargetBufferFlags::COLOR0, dstRenderTarget, dstRect, srcRenderTarget, srcRect,
|
||||
SamplerMagFilter::LINEAR);
|
||||
|
||||
// Push through an empty frame to allow the texture to upload and the blit to execute.
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Grab a screenshot.
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "BlitRegion.png" };
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.beginFrame(0, 0, 0);
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
api.commit(swapChain);
|
||||
api.endFrame(0);
|
||||
|
||||
// Wait for the ReadPixels result to come back.
|
||||
api.finish();
|
||||
executeCommands();
|
||||
getDriver().purge();
|
||||
|
||||
// Check if the image matches perfectly to our golden run.
|
||||
//
|
||||
// TODO: for some reason, this test has very, very slight (as in one pixel) differences between
|
||||
// OpenGL and Metal. So disable golden checking for now.
|
||||
// Use the compare tool from ImageMagick to see visual differences:
|
||||
@@ -599,12 +619,18 @@ TEST_F(BackendTest, BlitRegion) {
|
||||
// const uint32_t expected = 0x74fa34ed;
|
||||
// printf("Computed hash is 0x%8.8x, Expected 0x%8.8x\n", params.pixelHashResult, expected);
|
||||
// EXPECT_TRUE(params.pixelHashResult == expected);
|
||||
|
||||
// Cleanup.
|
||||
api.destroyTexture(srcTexture);
|
||||
api.destroyTexture(dstTexture);
|
||||
api.destroySwapChain(swapChain);
|
||||
api.destroyRenderTarget(srcRenderTarget);
|
||||
api.destroyRenderTarget(dstRenderTarget);
|
||||
executeCommands();
|
||||
}
|
||||
|
||||
TEST_F(BackendTest, BlitRegionToSwapChain) {
|
||||
auto& api = getDriverApi();
|
||||
Cleanup cleanup(getDriverApi());
|
||||
cleanup.addPostCall([&]() { executeCommands(); });
|
||||
|
||||
constexpr int kSrcTexWidth = 1024;
|
||||
constexpr int kSrcTexHeight = 1024;
|
||||
@@ -614,15 +640,14 @@ TEST_F(BackendTest, BlitRegionToSwapChain) {
|
||||
constexpr int kNumLevels = 3;
|
||||
|
||||
// Create a SwapChain and make it current.
|
||||
auto swapChain = cleanup.add(createSwapChain());
|
||||
auto swapChain = createSwapChain();
|
||||
Handle<HwRenderTarget> dstRenderTarget = api.createDefaultRenderTarget();
|
||||
api.makeCurrent(swapChain, swapChain);
|
||||
|
||||
Handle<HwRenderTarget> dstRenderTarget = cleanup.add(api.createDefaultRenderTarget());
|
||||
|
||||
// Create a source texture.
|
||||
Handle<HwTexture> srcTexture = cleanup.add(api.createTexture(
|
||||
Handle<HwTexture> srcTexture = api.createTexture(
|
||||
SamplerType::SAMPLER_2D, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1,
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT));
|
||||
TextureUsage::SAMPLEABLE | TextureUsage::UPLOADABLE | TextureUsage::COLOR_ATTACHMENT);
|
||||
const bool flipY = sBackend == Backend::OPENGL;
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 0, float3(0.5, 0, 0), flipY);
|
||||
createBitmap(api, srcTexture, kSrcTexWidth, kSrcTexHeight, 1, float3(0, 0, 0.5), flipY);
|
||||
@@ -630,8 +655,8 @@ TEST_F(BackendTest, BlitRegionToSwapChain) {
|
||||
// Create a RenderTarget for each texture's miplevel.
|
||||
Handle<HwRenderTarget> srcRenderTargets[kNumLevels];
|
||||
for (uint8_t level = 0; level < kNumLevels; level++) {
|
||||
srcRenderTargets[level] = cleanup.add(api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {}));
|
||||
srcRenderTargets[level] = api.createRenderTarget( TargetBufferFlags::COLOR,
|
||||
kSrcTexWidth >> level, kSrcTexHeight >> level, 1, 0, { srcTexture, level, 0 }, {}, {});
|
||||
}
|
||||
|
||||
// Blit one-quarter of src level 1 to dst level 0.
|
||||
@@ -649,23 +674,29 @@ TEST_F(BackendTest, BlitRegionToSwapChain) {
|
||||
.height = kDstTexHeight - 10,
|
||||
};
|
||||
|
||||
{
|
||||
RenderFrame frame(api);
|
||||
api.beginFrame(0, 0, 0);
|
||||
|
||||
api.blitDEPRECATED(TargetBufferFlags::COLOR0, dstRenderTarget,
|
||||
dstRect, srcRenderTargets[srcLevel],
|
||||
srcRect, SamplerMagFilter::LINEAR);
|
||||
api.blitDEPRECATED(TargetBufferFlags::COLOR0, dstRenderTarget,
|
||||
dstRect, srcRenderTargets[srcLevel],
|
||||
srcRect, SamplerMagFilter::LINEAR);
|
||||
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain.png" };
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
ScreenshotParams params { kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain.png" };
|
||||
dumpScreenshot(api, dstRenderTarget, ¶ms);
|
||||
|
||||
api.commit(swapChain);
|
||||
}
|
||||
api.commit(swapChain);
|
||||
|
||||
api.endFrame(0);
|
||||
|
||||
// Wait for the ReadPixels result to come back.
|
||||
api.finish();
|
||||
executeCommands();
|
||||
getDriver().purge();
|
||||
|
||||
// Cleanup.
|
||||
api.destroyTexture(srcTexture);
|
||||
api.destroySwapChain(swapChain);
|
||||
for (auto rt : srcRenderTargets) api.destroyRenderTarget(rt);
|
||||
executeCommands();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
@@ -106,13 +106,6 @@ public:
|
||||
/** @return Whether a combination of texture format, pixel format and type is valid. */
|
||||
static bool validatePixelFormatAndType(InternalFormat internalFormat, Format format, Type type) noexcept;
|
||||
|
||||
/** @return the maximum size in texels of a texture of type \p type. At least 2048 for
|
||||
* 2D textures, 256 for 3D textures. */
|
||||
static size_t getMaxTextureSize(Engine& engine, Sampler type) noexcept;
|
||||
|
||||
/** @return the maximum number of layers supported by texture arrays. At least 256. */
|
||||
static size_t getMaxArrayTextureLayers(Engine& engine) noexcept;
|
||||
|
||||
/**
|
||||
* Options for environment prefiltering into reflection map
|
||||
*
|
||||
|
||||
@@ -62,8 +62,6 @@ constexpr std::pair<ChunkType, ChunkType> shaderLanguageToTags(ShaderLanguage co
|
||||
return { MaterialEssl1, DictionaryText };
|
||||
case ShaderLanguage::MSL:
|
||||
return { MaterialMetal, DictionaryText };
|
||||
case ShaderLanguage::WGSL:
|
||||
return { MaterialWgsl, DictionaryText };
|
||||
case ShaderLanguage::SPIRV:
|
||||
return { MaterialSpirv, DictionarySpirv };
|
||||
case ShaderLanguage::METAL_LIBRARY:
|
||||
|
||||
@@ -108,12 +108,4 @@ bool Texture::validatePixelFormatAndType(InternalFormat internalFormat, Format f
|
||||
return FTexture::validatePixelFormatAndType(internalFormat, format, type);
|
||||
}
|
||||
|
||||
size_t Texture::getMaxTextureSize(Engine& engine, Sampler type) noexcept {
|
||||
return FTexture::getMaxTextureSize(downcast(engine), type);
|
||||
|
||||
}
|
||||
size_t Texture::getMaxArrayTextureLayers(Engine& engine) noexcept {
|
||||
return FTexture::getMaxArrayTextureLayers(downcast(engine));
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -388,13 +388,12 @@ void FMaterial::terminate(FEngine& engine) {
|
||||
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive.";
|
||||
} else {
|
||||
if (UTILS_UNLIKELY(!pos->second.empty())) {
|
||||
slog.e << "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive." << io::endl;
|
||||
}
|
||||
utils::slog.e << "destroying material \"" << this->getName().c_str_safe() << "\" but "
|
||||
<< pos->second.size() << " instances still alive.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
// Unregister the material with matdbg.
|
||||
matdbg::DebugServer* server = engine.debug.server;
|
||||
|
||||
@@ -164,20 +164,6 @@ Texture* Texture::Builder::build(Engine& engine) {
|
||||
(isProtectedTexturesSupported && useProtectedMemory) || !useProtectedMemory)
|
||||
<< "Texture is PROTECTED but protected textures are not supported";
|
||||
|
||||
size_t const maxTextureDimension = getMaxTextureSize(engine, mImpl->mTarget);
|
||||
size_t const maxTextureDepth = (mImpl->mTarget == Sampler::SAMPLER_2D_ARRAY ||
|
||||
mImpl->mTarget == Sampler::SAMPLER_CUBEMAP_ARRAY)
|
||||
? getMaxArrayTextureLayers(engine)
|
||||
: maxTextureDimension;
|
||||
|
||||
FILAMENT_CHECK_PRECONDITION(
|
||||
mImpl->mWidth <= maxTextureDimension &&
|
||||
mImpl->mHeight <= maxTextureDimension &&
|
||||
mImpl->mDepth <= maxTextureDepth) << "Texture dimensions out of range: "
|
||||
<< "width= " << mImpl->mWidth << " (>" << maxTextureDimension << ")"
|
||||
<<", height= " << mImpl->mHeight << " (>" << maxTextureDimension << ")"
|
||||
<< ", depth= " << mImpl->mDepth << " (>" << maxTextureDepth << ")";
|
||||
|
||||
const auto validateSamplerType = [&engine = downcast(engine)](SamplerType const sampler) -> bool {
|
||||
switch (sampler) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
@@ -686,14 +672,6 @@ bool FTexture::isTextureSwizzleSupported(FEngine& engine) noexcept {
|
||||
return engine.getDriverApi().isTextureSwizzleSupported();
|
||||
}
|
||||
|
||||
size_t FTexture::getMaxTextureSize(FEngine& engine, Sampler type) noexcept {
|
||||
return engine.getDriverApi().getMaxTextureSize(type);
|
||||
}
|
||||
|
||||
size_t FTexture::getMaxArrayTextureLayers(FEngine& engine) noexcept {
|
||||
return engine.getDriverApi().getMaxArrayTextureLayers();
|
||||
}
|
||||
|
||||
size_t FTexture::computeTextureDataSize(Format const format, Type const type,
|
||||
size_t const stride, size_t const height, size_t const alignment) noexcept {
|
||||
return PixelBufferDescriptor::computeDataSize(format, type, stride, height, alignment);
|
||||
|
||||
@@ -124,10 +124,6 @@ public:
|
||||
static bool validatePixelFormatAndType(backend::TextureFormat internalFormat,
|
||||
backend::PixelDataFormat format, backend::PixelDataType type) noexcept;
|
||||
|
||||
static size_t getMaxTextureSize(FEngine& engine, Sampler type) noexcept;
|
||||
|
||||
static size_t getMaxArrayTextureLayers(FEngine& engine) noexcept;
|
||||
|
||||
bool textureHandleCanMutate() const noexcept;
|
||||
void updateLodRange(uint8_t level) noexcept;
|
||||
|
||||
|
||||
@@ -78,10 +78,6 @@ fragment {
|
||||
void dummy(){}
|
||||
|
||||
vec4 resolveFragment() {
|
||||
#ifdef TARGET_WEBGPU_ENVIRONMENT
|
||||
//WebGPU Can not handle subpasses.
|
||||
return vec4(0,0,0,1);
|
||||
#else
|
||||
#if POST_PROCESS_OPAQUE
|
||||
return vec4(subpassLoad(materialParams_colorBuffer).rgb, 1.0);
|
||||
#else
|
||||
@@ -89,7 +85,6 @@ vec4 resolveFragment() {
|
||||
color.rgb *= 1.0 / (color.a + FLT_EPS);
|
||||
return color;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void postProcess(inout PostProcessInputs postProcess) {
|
||||
|
||||
@@ -39,16 +39,11 @@ fragment {
|
||||
void dummy(){}
|
||||
|
||||
vec4 resolveFragment() {
|
||||
#ifdef TARGET_WEBGPU_ENVIRONMENT
|
||||
//WebGPU Can not handle subpasses.
|
||||
return vec4(0,0,0,1);
|
||||
#else
|
||||
#if POST_PROCESS_OPAQUE
|
||||
return vec4(subpassLoad(materialParams_colorBuffer).rgb, 1.0);
|
||||
#else
|
||||
return subpassLoad(materialParams_colorBuffer);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void postProcess(inout PostProcessInputs postProcess) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.58.0"
|
||||
spec.version = "1.58.1"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.58.0/filament-v1.58.0-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.58.1/filament-v1.58.1-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -52,10 +52,6 @@ include_directories(${PUBLIC_HDR_DIR})
|
||||
# we're building a library
|
||||
add_library(${TARGET} STATIC ${PUBLIC_HDRS} ${SRCS})
|
||||
|
||||
if(FILAMENT_SUPPORTS_OSMESA)
|
||||
target_compile_options(${TARGET} PRIVATE -I${FILAMENT_OSMESA_PATH}/include/GL)
|
||||
endif()
|
||||
|
||||
# specify where the public headers of this library are
|
||||
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
|
||||
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
|
||||
|
||||
@@ -14,21 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmesa.h>
|
||||
|
||||
namespace bluegl {
|
||||
|
||||
namespace {
|
||||
using ProcAddressFunc = void*(*)(char const* funcName);
|
||||
}
|
||||
|
||||
// This is to ensure that linking during compilation will not fail even if
|
||||
// OSMesaGetProcAddress is not linked.
|
||||
__attribute__((weak)) OSMESAproc OSMesaGetProcAddress(char const*);
|
||||
|
||||
struct Driver {
|
||||
ProcAddressFunc OSMesaGetProcAddress;
|
||||
void* library;
|
||||
@@ -36,7 +31,7 @@ struct Driver {
|
||||
|
||||
bool initBinder() {
|
||||
constexpr char const* libraryNames[] = {"libOSMesa.so", "libosmesa.so"};
|
||||
for (char const* name: libraryNames) {
|
||||
for (char const* name : libraryNames) {
|
||||
g_driver.library = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
|
||||
if (g_driver.library) {
|
||||
break;
|
||||
@@ -50,10 +45,6 @@ bool initBinder() {
|
||||
(ProcAddressFunc) dlsym(g_driver.library, "OSMesaGetProcAddress");
|
||||
}
|
||||
|
||||
if (!g_driver.OSMesaGetProcAddress) {
|
||||
g_driver.OSMesaGetProcAddress = (ProcAddressFunc) OSMesaGetProcAddress;
|
||||
}
|
||||
|
||||
return g_driver.OSMesaGetProcAddress;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ class FrameGraphTable extends LitElement {
|
||||
super();
|
||||
this.frameGraphData = null;
|
||||
this.selectedResourceId = -1;
|
||||
this.expandedResourceSet = new Set();
|
||||
this.collapsedResources = new Set();
|
||||
}
|
||||
|
||||
updated(props) {
|
||||
@@ -365,11 +365,11 @@ class FrameGraphTable extends LitElement {
|
||||
}
|
||||
|
||||
_toggleCollapse(resourceIndex) {
|
||||
if (this.expandedResourceSet.has(resourceIndex)) {
|
||||
this.expandedResourceSet.delete(resourceIndex);
|
||||
if (this.collapsedResources.has(resourceIndex)) {
|
||||
this.collapsedResources.delete(resourceIndex);
|
||||
}
|
||||
else {
|
||||
this.expandedResourceSet.add(resourceIndex);
|
||||
this.collapsedResources.add(resourceIndex);
|
||||
}
|
||||
this.requestUpdate();
|
||||
}
|
||||
@@ -430,9 +430,9 @@ class FrameGraphTable extends LitElement {
|
||||
.map(subresource => subresource.id);
|
||||
|
||||
const hasSubresources = subresourceIds.length > 0;
|
||||
const isExpanded = this.expandedResourceSet.has(resourceIndex);
|
||||
const isCollapsed = this.collapsedResources.has(resourceIndex);
|
||||
// Show the aggregated resource usage when the subresources are collapsed.
|
||||
const resourceIds = isExpanded ? [resource.id]:[resource.id, ...subresourceIds];
|
||||
const resourceIds = isCollapsed ? [resource.id, ...subresourceIds]:[resource.id];
|
||||
|
||||
const onClickResource = () => this._handleResourceClick(resource.id);
|
||||
const selectedStyle = resource.id === this.selectedResourceId ? "selected" : "";
|
||||
@@ -444,15 +444,15 @@ class FrameGraphTable extends LitElement {
|
||||
? html`
|
||||
<span class="toggle-icon"
|
||||
@click="${(e) => { e.stopPropagation(); this._toggleCollapse(resourceIndex); }}">
|
||||
${isExpanded ? '▼' : '▶'}
|
||||
${isCollapsed ? '▶' : '▼'}
|
||||
</span>`
|
||||
: nothing}
|
||||
${resource.name}
|
||||
${hasSubresources && isExpanded ? nothing : html`(${subresourceIds.length})`}
|
||||
${hasSubresources && isCollapsed ? html`(${subresourceIds.length})` : nothing}
|
||||
</th>
|
||||
${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR)}
|
||||
</tr>
|
||||
${isExpanded ? this._renderSubresourceRows(resources, resource, resourceIndex, allPasses) : nothing}
|
||||
${!isCollapsed ? this._renderSubresourceRows(resources, resource, resourceIndex, allPasses) : nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ enum UTILS_PUBLIC ChunkType : uint64_t {
|
||||
MaterialEssl1 = charTo64bitNum("MAT_ESS1"),
|
||||
MaterialSpirv = charTo64bitNum("MAT_SPIR"),
|
||||
MaterialMetal = charTo64bitNum("MAT_METL"),
|
||||
MaterialWgsl = charTo64bitNum("MAT_WGSL"),
|
||||
MaterialMetalLibrary = charTo64bitNum("MAT_MLIB"),
|
||||
MaterialShaderModels = charTo64bitNum("MAT_SMDL"),
|
||||
MaterialBindingUniformInfo = charTo64bitNum("MAT_UFRM"),
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
namespace filament {
|
||||
|
||||
// update this when a new version of filament wouldn't work with older materials
|
||||
static constexpr size_t MATERIAL_VERSION = 57;
|
||||
static constexpr size_t MATERIAL_VERSION = 58;
|
||||
|
||||
/**
|
||||
* Supported shading models
|
||||
|
||||
@@ -183,7 +183,6 @@ bool MaterialChunk::getShader(ShaderContent& shaderContent, BlobDictionary const
|
||||
switch (mMaterialTag) {
|
||||
case filamat::ChunkType::MaterialGlsl:
|
||||
case filamat::ChunkType::MaterialEssl1:
|
||||
case filamat::ChunkType::MaterialWgsl:
|
||||
case filamat::ChunkType::MaterialMetal:
|
||||
return getTextShader(mUnflattener, dictionary, shaderContent, shaderModel, variant, stage);
|
||||
case filamat::ChunkType::MaterialSpirv:
|
||||
|
||||
@@ -144,12 +144,6 @@ set(FILAMAT_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}filamat${CMAKE_STATIC_LIBRARY
|
||||
install(FILES "${FILAMAT_COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR} RENAME ${FILAMAT_LIB_NAME})
|
||||
install(DIRECTORY ${PUBLIC_HDR_DIR}/filamat DESTINATION include)
|
||||
|
||||
# Need to install libtint for filamat on Android.
|
||||
# See libs/filamat/CMakeLists.txt and android/filamat-android/CMakeLists.txt.
|
||||
if (ANDROID)
|
||||
target_link_libraries(${TARGET} libtint_combined)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Tests
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -81,11 +81,7 @@ public:
|
||||
VULKAN = 0x02u,
|
||||
METAL = 0x04u,
|
||||
WEBGPU = 0x08u,
|
||||
#ifdef FILAMENT_SUPPORTS_WEBGPU
|
||||
ALL = OPENGL | VULKAN | METAL | WEBGPU
|
||||
#else
|
||||
ALL = OPENGL | VULKAN | METAL
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -518,13 +518,8 @@ void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
|
||||
}
|
||||
}
|
||||
|
||||
bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
bool GLSLPostProcessor::spirvToWgsl(const SpirvBlob *spirv, std::string *outWsl) {
|
||||
#if FILAMENT_SUPPORTS_WEBGPU
|
||||
// We need to remove dead code for our variant-filter workaround for WebGPU to work
|
||||
// This is especially relevant for removing the push constants that morphing uses when not disabled
|
||||
spv::spirvbin_t remapper(0);
|
||||
remapper.remap(*spirv, spv::spirvbin_base_t::DCE_ALL);
|
||||
|
||||
//Currently no options we want to use
|
||||
const tint::spirv::reader::Options readerOpts{};
|
||||
tint::wgsl::writer::Options writerOpts{};
|
||||
@@ -532,15 +527,11 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
tint::Program tintRead = tint::spirv::reader::Read(*spirv, readerOpts);
|
||||
|
||||
if (tintRead.Diagnostics().ContainsErrors()) {
|
||||
//TODO remove this if block once combined image sampler conversion works.
|
||||
if (tintRead.Diagnostics().Str().rfind("error: WGSL does not support combined image-samplers") != std::string::npos) {
|
||||
slog.w << "This tint reader error is currently ignored during WebGPU bringup: " << tintRead.Diagnostics().Str() << io::endl;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
slog.e << "Tint Reader Error: " << tintRead.Diagnostics().Str() << io::endl;
|
||||
return false;
|
||||
}
|
||||
slog.w << "This tint reader error is currently ignored during WebGPU bringup:" << tintRead.Diagnostics().Str() << io::endl;
|
||||
|
||||
//TODO: We should actually return false here, but for initial debugging
|
||||
// let it slide until combined image sampler is resolved
|
||||
// return false;
|
||||
}
|
||||
|
||||
tint::Result<tint::wgsl::writer::Output> wgslOut = tint::wgsl::writer::Generate(tintRead,writerOpts);
|
||||
@@ -548,8 +539,10 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
|
||||
tint::SuccessType tintSuccess;
|
||||
|
||||
if (wgslOut != tintSuccess) {
|
||||
slog.e << "Tint writer error: " << wgslOut.Failure().reason.Str() << io::endl;
|
||||
return false;
|
||||
slog.w << "This tint writer error is currently ignored during WebGPU bringup:" << wgslOut.Failure().reason.Str() << io::endl;
|
||||
//TODO: We should actually return false here, but for initial debugging
|
||||
// let it slide until combined image sampler is resolved
|
||||
// return false;
|
||||
}
|
||||
*outWsl = wgslOut->wgsl;
|
||||
return true;
|
||||
@@ -920,10 +913,6 @@ std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
|
||||
optimizer->RegisterPass(CreateRedundancyEliminationPass());
|
||||
optimizer->RegisterPass(CreateAggressiveDCEPass());
|
||||
}
|
||||
if (config.targetApi == MaterialBuilder::TargetApi::WEBGPU) {
|
||||
optimizer->RegisterPass(CreateSplitCombinedImageSamplerPass());
|
||||
optimizer->RegisterPass(CreateResolveBindingConflictsPass());
|
||||
}
|
||||
|
||||
return optimizer;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
bool useFramebufferFetch, const DescriptorSets& descriptorSets,
|
||||
const ShaderMinifier* minifier);
|
||||
|
||||
static bool spirvToWgsl(SpirvBlob* spirv, std::string* outWsl);
|
||||
static bool spirvToWgsl(const SpirvBlob* spirv, std::string* outWsl);
|
||||
|
||||
private:
|
||||
struct InternalConfig {
|
||||
|
||||
@@ -179,14 +179,6 @@ void MaterialBuilderBase::prepare(bool vulkanSemantics,
|
||||
effectiveFeatureLevel,
|
||||
});
|
||||
}
|
||||
if (any(mTargetApi & TargetApi::WEBGPU)) {
|
||||
mCodeGenPermutations.push_back({
|
||||
shaderModel,
|
||||
TargetApi::WEBGPU,
|
||||
TargetLanguage::SPIRV,
|
||||
effectiveFeatureLevel,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,7 +836,6 @@ static void showErrorMessage(const char* materialName, filament::Variant variant
|
||||
break;
|
||||
case TargetApi::WEBGPU:
|
||||
targetApiString = "WebGPU.\n";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
assert(0); // Unreachable.
|
||||
break;
|
||||
@@ -888,7 +879,6 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
std::vector<TextEntry> essl1Entries;
|
||||
std::vector<BinaryEntry> spirvEntries;
|
||||
std::vector<TextEntry> metalEntries;
|
||||
std::vector<TextEntry> wgslEntries;
|
||||
LineDictionary textDictionary;
|
||||
BlobDictionary spirvDictionary;
|
||||
// End: must be protected by lock
|
||||
@@ -917,7 +907,7 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
|
||||
// Metal Shading Language is cross-compiled from Vulkan.
|
||||
const bool targetApiNeedsSpirv =
|
||||
(targetApi == TargetApi::VULKAN || targetApi == TargetApi::METAL || targetApi == TargetApi::WEBGPU);
|
||||
(targetApi == TargetApi::VULKAN || targetApi == TargetApi::METAL);
|
||||
const bool targetApiNeedsMsl = targetApi == TargetApi::METAL;
|
||||
const bool targetApiNeedsWgsl = targetApi == TargetApi::WEBGPU;
|
||||
const bool targetApiNeedsGlsl = targetApi == TargetApi::OPENGL;
|
||||
@@ -943,17 +933,14 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
TextEntry glslEntry{};
|
||||
BinaryEntry spirvEntry{};
|
||||
TextEntry metalEntry{};
|
||||
TextEntry wgslEntry{};
|
||||
|
||||
glslEntry.shaderModel = params.shaderModel;
|
||||
spirvEntry.shaderModel = params.shaderModel;
|
||||
metalEntry.shaderModel = params.shaderModel;
|
||||
wgslEntry.shaderModel = params.shaderModel;
|
||||
|
||||
glslEntry.variant = v.variant;
|
||||
spirvEntry.variant = v.variant;
|
||||
metalEntry.variant = v.variant;
|
||||
wgslEntry.variant = v.variant;
|
||||
|
||||
// Generate raw shader code.
|
||||
// The quotes in Google-style line directives cause problems with certain drivers. These
|
||||
@@ -1051,12 +1038,6 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
switch (targetApi) {
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
assert(!spirv.empty());
|
||||
assert(wgsl.length() > 0);
|
||||
wgslEntry.stage = v.stage;
|
||||
wgslEntry.shader = wgsl;
|
||||
wgslEntries.push_back(wgslEntry);
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
// should never happen
|
||||
break;
|
||||
@@ -1118,7 +1099,6 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
std::sort(essl1Entries.begin(), essl1Entries.end(), compare);
|
||||
std::sort(spirvEntries.begin(), spirvEntries.end(), compare);
|
||||
std::sort(metalEntries.begin(), metalEntries.end(), compare);
|
||||
std::sort(wgslEntries.begin(), wgslEntries.end(), compare);
|
||||
|
||||
// Generate the dictionaries.
|
||||
for (const auto& s : glslEntries) {
|
||||
@@ -1134,9 +1114,6 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
for (const auto& s : metalEntries) {
|
||||
textDictionary.addText(s.shader);
|
||||
}
|
||||
for (const auto& s : wgslEntries) {
|
||||
textDictionary.addText(s.shader);
|
||||
}
|
||||
|
||||
// Emit dictionary chunk (TextDictionaryReader and DictionaryTextChunk)
|
||||
const auto& dictionaryChunk = container.push<filamat::DictionaryTextChunk>(
|
||||
@@ -1167,12 +1144,6 @@ bool MaterialBuilder::generateShaders(JobSystem& jobSystem, const std::vector<Va
|
||||
dictionaryChunk.getDictionary(), ChunkType::MaterialMetal);
|
||||
}
|
||||
|
||||
// Emit WGSL chunk (MaterialTextChunk).
|
||||
if (!wgslEntries.empty()) {
|
||||
container.push<MaterialTextChunk>(std::move(wgslEntries),
|
||||
dictionaryChunk.getDictionary(), ChunkType::MaterialWgsl);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -525,11 +525,6 @@ EShMessages GLSLTools::glslangFlagsFromTargetApi(
|
||||
// choke on gl_VertexIndex.
|
||||
msg |= (Type)EShMessages::EShMsgVulkanRules;
|
||||
}
|
||||
if (targetApi == TargetApi::WEBGPU) {
|
||||
// FIXME: We have to use EShMsgVulkanRules for WEBGPU, otherwise compilation will
|
||||
// choke on gl_VertexIndex.
|
||||
msg |= (Type)EShMessages::EShMsgVulkanRules;
|
||||
}
|
||||
return (EShMessages)msg;
|
||||
}
|
||||
}
|
||||
@@ -545,13 +540,13 @@ void GLSLTools::prepareShaderParser(MaterialBuilder::TargetApi targetApi,
|
||||
shader.setEnvInput(EShSourceGlsl, stage, EShClientOpenGL, version);
|
||||
shader.setEnvClient(EShClientOpenGL, EShTargetOpenGL_450);
|
||||
break;
|
||||
case MaterialBuilderBase::TargetApi::WEBGPU:
|
||||
case MaterialBuilderBase::TargetApi::VULKAN:
|
||||
case MaterialBuilderBase::TargetApi::METAL:
|
||||
shader.setEnvInput(EShSourceGlsl, stage, EShClientVulkan, version);
|
||||
shader.setEnvClient(EShClientVulkan, EShTargetVulkan_1_1);
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case MaterialBuilderBase::TargetApi::WEBGPU:
|
||||
case MaterialBuilderBase::TargetApi::ALL:
|
||||
// can't happen
|
||||
break;
|
||||
|
||||
@@ -175,11 +175,6 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out,
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
//For now, no differences so inherit the same changes.
|
||||
// TODO Define a separte environment, OR relevant checks
|
||||
out << "#define TARGET_VULKAN_ENVIRONMENT\n";
|
||||
out << "#define TARGET_WEBGPU_ENVIRONMENT\n";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
// invalid should never happen
|
||||
break;
|
||||
@@ -195,7 +190,6 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out,
|
||||
}
|
||||
|
||||
if (mTargetApi == TargetApi::VULKAN ||
|
||||
mTargetApi == TargetApi::WEBGPU ||
|
||||
mTargetApi == TargetApi::METAL ||
|
||||
(mTargetApi == TargetApi::OPENGL && mShaderModel == ShaderModel::DESKTOP) ||
|
||||
mFeatureLevel >= FeatureLevel::FEATURE_LEVEL_2) {
|
||||
@@ -731,8 +725,6 @@ io::sstream& CodeGenerator::generateBufferInterfaceBlock(io::sstream& out, Shade
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
out << "set = " << +set << ", binding = " << +binding << ", ";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
// nonsensical, shouldn't happen.
|
||||
break;
|
||||
@@ -821,8 +813,6 @@ io::sstream& CodeGenerator::generateCommonSamplers(utils::io::sstream& out,
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
out << "layout(binding = " << +info.binding << ", set = " << +set << ") ";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
// should not happen
|
||||
break;
|
||||
|
||||
@@ -796,10 +796,8 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
|
||||
|
||||
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib);
|
||||
|
||||
// Subpasses are not yet in WebGPU, https://github.com/gpuweb/gpuweb/issues/435
|
||||
CodeGenerator::generatePostProcessSubpass(fs, targetApi == MaterialBuilderBase::TargetApi::WEBGPU
|
||||
? SubpassInfo{}
|
||||
: material.subpass);
|
||||
// subpass
|
||||
CodeGenerator::generatePostProcessSubpass(fs, material.subpass);
|
||||
|
||||
CodeGenerator::generatePostProcessCommon(fs, ShaderStage::FRAGMENT);
|
||||
CodeGenerator::generatePostProcessGetters(fs, ShaderStage::FRAGMENT);
|
||||
|
||||
@@ -891,78 +891,7 @@ TEST_F(MaterialCompiler, FeatureLevel0Ess3CallFails) {
|
||||
EXPECT_FALSE(result.isValid());
|
||||
}
|
||||
|
||||
#if FILAMENT_SUPPORTS_WEBGPU
|
||||
TEST_F(MaterialCompiler, WgslConversionBakedColor) {
|
||||
std::string bakedColorCodeFrag(R"(
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = getColor();
|
||||
}
|
||||
)");
|
||||
filamat::MaterialBuilder builder;
|
||||
builder.targetApi(filamat::MaterialBuilderBase::TargetApi::WEBGPU);
|
||||
builder.material(bakedColorCodeFrag.c_str());
|
||||
builder.shading(filamat::MaterialBuilder::Shading::UNLIT);
|
||||
builder.name("BakedColor");
|
||||
builder.culling(CullingMode::NONE);
|
||||
builder.featureLevel(FeatureLevel::FEATURE_LEVEL_0);
|
||||
builder.require(filament::VertexAttribute::COLOR);
|
||||
builder.variantFilter(static_cast<filament::UserVariantFilterMask>(
|
||||
filament::UserVariantFilterBit::SKINNING | filament::UserVariantFilterBit::STE));
|
||||
filamat::Package result = builder.build(*jobSystem);
|
||||
EXPECT_TRUE(result.isValid());
|
||||
}
|
||||
|
||||
TEST_F(MaterialCompiler, WgslConversionSandboxLitTransparent) {
|
||||
std::string litTransparentCodeFrag(R"(
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor.rgb = materialParams.baseColor * materialParams.alpha;
|
||||
material.baseColor.a = materialParams.alpha;
|
||||
material.roughness = materialParams.roughness;
|
||||
material.metallic = materialParams.metallic;
|
||||
material.reflectance = materialParams.reflectance;
|
||||
material.sheenColor = materialParams.sheenColor;
|
||||
material.sheenRoughness = materialParams.sheenRoughness;
|
||||
material.clearCoat = materialParams.clearCoat;
|
||||
material.clearCoatRoughness = materialParams.clearCoatRoughness;
|
||||
material.anisotropy = materialParams.anisotropy;
|
||||
material.emissive = materialParams.emissive;
|
||||
}
|
||||
)");
|
||||
filamat::MaterialBuilder builder;
|
||||
builder.targetApi(filamat::MaterialBuilderBase::TargetApi::WEBGPU);
|
||||
builder.material(litTransparentCodeFrag.c_str());
|
||||
builder.shading(filamat::MaterialBuilder::Shading::LIT);
|
||||
builder.name("LitTransparent");
|
||||
builder.blending(filament::BlendingMode::TRANSPARENT);
|
||||
builder.specularAntiAliasing(true);
|
||||
|
||||
builder.parameter("alpha", 1, UniformType::FLOAT);
|
||||
builder.parameter("baseColor", 1, UniformType::FLOAT3);
|
||||
builder.parameter("roughness", 1, UniformType::FLOAT);
|
||||
builder.parameter("metallic", 1, UniformType::FLOAT);
|
||||
builder.parameter("reflectance", 1, UniformType::FLOAT);
|
||||
builder.parameter("sheenColor", 1, UniformType::FLOAT3);
|
||||
builder.parameter("sheenRoughness", 1, UniformType::FLOAT);
|
||||
builder.parameter("clearCoat", 1, UniformType::FLOAT);
|
||||
builder.parameter("clearCoatRoughness", 1, UniformType::FLOAT);
|
||||
builder.parameter("anisotropy", 1, UniformType::FLOAT);
|
||||
builder.parameter("emissive", 1, UniformType::FLOAT4);
|
||||
|
||||
builder.variantFilter(static_cast<filament::UserVariantFilterMask>(
|
||||
filament::UserVariantFilterBit::SKINNING | filament::UserVariantFilterBit::STE));
|
||||
filamat::Package result = builder.build(*jobSystem);
|
||||
EXPECT_TRUE(result.isValid());
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
const int rv = RUN_ALL_TESTS();
|
||||
if (testing::UnitTest::GetInstance()->test_to_run_count() == 0) {
|
||||
//If you run a test filter that contains 0 tests that was likely not intentional. Fail in that scenario.
|
||||
return 1;
|
||||
}
|
||||
return rv;
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -254,10 +254,6 @@ bool JsonWriter::writeActiveInfo(const filaflat::ChunkContainer& package,
|
||||
json << "metal";
|
||||
chunkType = ChunkType::MaterialMetal;
|
||||
break;
|
||||
case ShaderLanguage::WGSL:
|
||||
json << "webgpu";
|
||||
chunkType = ChunkType::MaterialWgsl;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,10 +57,6 @@ ShaderExtractor::ShaderExtractor(backend::ShaderLanguage target, const void* dat
|
||||
mMaterialTag = ChunkType::MaterialMetalLibrary;
|
||||
mDictionaryTag = ChunkType::DictionaryMetalLibrary;
|
||||
break;
|
||||
case backend::ShaderLanguage::WGSL:
|
||||
mMaterialTag = ChunkType::MaterialWgsl;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
case backend::ShaderLanguage::SPIRV:
|
||||
mMaterialTag = ChunkType::MaterialSpirv;
|
||||
mDictionaryTag = ChunkType::DictionarySpirv;
|
||||
|
||||
@@ -135,10 +135,6 @@ ShaderReplacer::ShaderReplacer(Backend backend, ShaderLanguage language,
|
||||
mMaterialTag = ChunkType::MaterialMetal;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
case backend::ShaderLanguage::WGSL:
|
||||
mMaterialTag = ChunkType::MaterialWgsl;
|
||||
mDictionaryTag = ChunkType::DictionaryText;
|
||||
break;
|
||||
case backend::ShaderLanguage::SPIRV:
|
||||
mMaterialTag = ChunkType::MaterialSpirv;
|
||||
mDictionaryTag = ChunkType::DictionarySpirv;
|
||||
|
||||
@@ -429,10 +429,7 @@ static bool printShaderInfo(ostream& text, const ChunkContainer& container, Chun
|
||||
break;
|
||||
case ChunkType::MaterialMetalLibrary:
|
||||
text << "Metal precompiled shader libraries:" << endl;
|
||||
break;
|
||||
case ChunkType::MaterialWgsl:
|
||||
text << "WGSL precompiled shader libraries:" << endl;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Invalid shader ChunkType");
|
||||
break;
|
||||
@@ -470,9 +467,6 @@ bool TextWriter::writeMaterialInfo(const filaflat::ChunkContainer& container) {
|
||||
if (!printShaderInfo(text, container, ChunkType::MaterialMetalLibrary)) {
|
||||
return false;
|
||||
}
|
||||
if (!printShaderInfo(text, container, ChunkType::MaterialWgsl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
printChunks(text, container);
|
||||
|
||||
|
||||
+2
-28
@@ -20,6 +20,7 @@ set(MATERIAL_SRCS
|
||||
materials/aiDefaultMat.mat
|
||||
materials/bakedColor.mat
|
||||
materials/bakedTexture.mat
|
||||
materials/pointSprites.mat
|
||||
materials/aoPreview.mat
|
||||
materials/arrayTexture.mat
|
||||
materials/groundShadow.mat
|
||||
@@ -41,12 +42,6 @@ set(MATERIAL_SRCS
|
||||
materials/texturedLit.mat
|
||||
)
|
||||
|
||||
# Tint does not support setting gl_PointSize, disable the relevant sample if using WebGPU
|
||||
# https://github.com/gpuweb/gpuweb/issues/1190
|
||||
if (NOT FILAMENT_SUPPORTS_WEBGPU)
|
||||
set(MATERIAL_SRCS ${MATERIAL_SRCS} materials/pointSprites.mat)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
include(${IMPORT_EXECUTABLES})
|
||||
endif()
|
||||
@@ -245,20 +240,6 @@ function(add_demo NAME)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_demo_plain NAME)
|
||||
include_directories(${GENERATION_ROOT})
|
||||
add_executable(${NAME} ${NAME}.cpp)
|
||||
target_compile_options(${NAME} PRIVATE ${COMPILER_FLAGS})
|
||||
set_target_properties(${NAME} PROPERTIES FOLDER Samples)
|
||||
|
||||
# This is needed after XCode 15.3
|
||||
if (APPLE)
|
||||
set_target_properties(${NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
set_target_properties(${NAME} PROPERTIES INSTALL_RPATH /usr/local/lib)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
if (NOT ANDROID)
|
||||
add_demo(animation)
|
||||
add_demo(depthtesting)
|
||||
@@ -277,11 +258,7 @@ if (NOT ANDROID)
|
||||
add_demo(lightbulb)
|
||||
add_demo(material_sandbox)
|
||||
add_demo(multiple_windows)
|
||||
# Tint does not support setting gl_PointSize, disable the relevant sample if using WebGPU
|
||||
# https://github.com/gpuweb/gpuweb/issues/1190
|
||||
if (NOT FILAMENT_SUPPORTS_WEBGPU)
|
||||
add_demo(point_sprites)
|
||||
endif ()
|
||||
add_demo(point_sprites)
|
||||
add_demo(rendertarget)
|
||||
add_demo(sample_cloth)
|
||||
add_demo(sample_full_pbr)
|
||||
@@ -294,9 +271,6 @@ if (NOT ANDROID)
|
||||
add_demo(vbotest)
|
||||
add_demo(viewtest)
|
||||
|
||||
add_demo_plain(spirv_test)
|
||||
target_link_libraries(spirv_test PRIVATE SPIRV-Headers utils)
|
||||
|
||||
# Sample app specific
|
||||
target_link_libraries(frame_generator PRIVATE imageio)
|
||||
target_link_libraries(gltf_viewer PRIVATE gltf-demo-resources uberarchive gltfio viewer)
|
||||
|
||||
@@ -77,11 +77,7 @@ static void printUsage(char* name) {
|
||||
" --help, -h\n"
|
||||
" Prints this message\n\n"
|
||||
" --api, -a\n"
|
||||
" Specify the backend API: opengl, vulkan, metal, or webgpu\n"
|
||||
" (note: webgpu is a no-op for now, printing backend\n"
|
||||
" component info if FILAMENT_BACKEND_DEBUG_FLAG, \n"
|
||||
" set at build time, includes the \n"
|
||||
" FWGPU_PRINT_SYSTEM bit flag 0x2)\n"
|
||||
" Specify the backend API: opengl, vulkan, or metal\n"
|
||||
);
|
||||
const std::string from("HELLOTRIANGLE");
|
||||
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
|
||||
@@ -113,11 +109,8 @@ static int handleCommandLineArguments(int argc, char* argv[], App* app) {
|
||||
app->config.backend = Engine::Backend::VULKAN;
|
||||
} else if (arg == "metal") {
|
||||
app->config.backend = Engine::Backend::METAL;
|
||||
} else if (arg == "webgpu") {
|
||||
app->config.backend = Engine::Backend::WEBGPU;
|
||||
} else {
|
||||
std::cerr << "Unrecognized backend. Must be "
|
||||
"'opengl'|'vulkan'|'metal'|'webgpu'.\n";
|
||||
std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n";
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
#include "spirv/unified1/spirv.hpp"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <functional>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
size_t getFileSize(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open()) {
|
||||
return -1;
|
||||
}
|
||||
size_t size = file.tellg();
|
||||
file.close();
|
||||
return size;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> transform(std::vector<uint32_t> const& spirv) {
|
||||
constexpr size_t HEADER_SIZE = 5;
|
||||
size_t const dataSize = spirv.size();
|
||||
std::vector<uint32_t> output;
|
||||
output.resize(dataSize);
|
||||
uint32_t const* data = (uint32_t*) spirv.data();
|
||||
uint32_t* outputData = output.data();
|
||||
memcpy(&outputData[0], &data[0], HEADER_SIZE * 4);
|
||||
|
||||
struct Descriptor {
|
||||
uint32_t binding = 0xFFFFFFFF;
|
||||
uint32_t set = 0xFFFFFFFF;
|
||||
bool fixed = false;
|
||||
};
|
||||
|
||||
std::unordered_map<uint32_t, Descriptor> descriptors;
|
||||
auto getDesc = [&](uint32_t var) -> Descriptor& {
|
||||
using itertype = std::unordered_map<uint32_t, Descriptor>::iterator;
|
||||
itertype itr;
|
||||
if (itr = descriptors.find(var); itr == descriptors.end()) {
|
||||
itr = descriptors.insert({var, {}}).first;
|
||||
}
|
||||
return itr->second;
|
||||
};
|
||||
|
||||
auto pass = [&](uint32_t targetOp, std::function<void(uint32_t, uint32_t)> f) {
|
||||
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
|
||||
uint32_t const firstWord = data[cursor];
|
||||
uint32_t const wordCount = firstWord >> 16;
|
||||
uint32_t const op = firstWord & 0x0000FFFF;
|
||||
if (targetOp == op) {
|
||||
f(wordCount-1, cursor+1);
|
||||
}
|
||||
cursor += wordCount;
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t samplerTypeId = 0;
|
||||
uint32_t imageTypeId = 0;
|
||||
|
||||
// First we find the ID used to identify the sampler type and the image type.
|
||||
pass(spv::Op::OpTypeSampler, [&](uint32_t count, uint32_t pos) {
|
||||
samplerTypeId = data[pos];
|
||||
});
|
||||
|
||||
pass(spv::Op::OpTypeImage, [&](uint32_t count, uint32_t pos) {
|
||||
imageTypeId = data[pos];
|
||||
});
|
||||
|
||||
// Next we identify all the descriptors and record their set id and binding.
|
||||
pass(spv::Op::OpDecorate, [&](uint32_t count, uint32_t pos) {
|
||||
uint32_t const type = data[pos + 1];
|
||||
if (type == spv::Decoration::DecorationBinding) {
|
||||
uint32_t const targetVar = data[pos];
|
||||
uint32_t const binding = data[pos + 2];
|
||||
auto& desc = getDesc(targetVar);
|
||||
desc.binding = binding;
|
||||
// Note these decorations do not need to be written to the output.
|
||||
} else if (type == spv::Decoration::DecorationDescriptorSet) {
|
||||
uint32_t const targetVar = data[pos];
|
||||
uint32_t const set = data[pos + 2];
|
||||
auto& desc = getDesc(targetVar);
|
||||
desc.set = set;
|
||||
}
|
||||
});
|
||||
|
||||
// If any descriptor is loaded to be a sampler, we offset it by a fixed amount. Note that it
|
||||
// could be "loaded" multiple times, so we use a boolean to skip if it's already offsetted.
|
||||
constexpr uint32_t SAMPLER_BINDING_OFFSET = 100;
|
||||
pass(spv::Op::OpLoad, [&](uint32_t count, uint32_t pos) {
|
||||
uint32_t const retType = data[pos];
|
||||
uint32_t const targetVar = data[pos + 2];
|
||||
if (retType == samplerTypeId) {
|
||||
auto& desc = getDesc(targetVar);
|
||||
if (!desc.fixed) {
|
||||
desc.binding += SAMPLER_BINDING_OFFSET;
|
||||
desc.fixed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Write out the offsetted bindings and copy the rest.
|
||||
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
|
||||
uint32_t const firstWord = data[cursor];
|
||||
uint32_t const wordCount = firstWord >> 16;
|
||||
uint32_t const op = firstWord & 0x0000FFFF;
|
||||
|
||||
uint32_t* out = &outputData[cursor];
|
||||
std::memcpy(out, &data[cursor], wordCount * 4);
|
||||
|
||||
if (op == spv::Op::OpDecorate && data[cursor + 2] == spv::Decoration::DecorationBinding) {
|
||||
uint32_t const targetVar = data[cursor + 1];
|
||||
auto const& modified = getDesc(targetVar);
|
||||
out[3] = modified.binding;
|
||||
}
|
||||
cursor += wordCount;
|
||||
}
|
||||
|
||||
// Note that you should be able to do this in-place (without making another vector).
|
||||
return output;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 3) {
|
||||
utils::slog.e <<"need input and output spirv filenames" << utils::io::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string infname {argv[1]};
|
||||
size_t const fsize = getFileSize(infname);
|
||||
size_t const wordCount = fsize / 4;
|
||||
|
||||
std::ifstream inputFile(infname, std::ios::binary);
|
||||
|
||||
std::vector<uint32_t> words;
|
||||
words.resize(wordCount);
|
||||
inputFile.read((char*) words.data(), fsize);
|
||||
inputFile.close();
|
||||
|
||||
std::string outfname {argv[2]};
|
||||
std::vector<uint32_t> output = transform(words);
|
||||
std::ofstream outputFile(outfname, std::ios::binary);
|
||||
outputFile.write((char const*) output.data(), output.size() * 4);
|
||||
outputFile.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -35,13 +35,10 @@ if [[ "$GITHUB_WORKFLOW" ]]; then
|
||||
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100
|
||||
else
|
||||
set +e
|
||||
sudo apt-get -y build-dep mesa
|
||||
sudo apt -y remove llvm-18 llvm-18-* llvm-19 llvm-19-*
|
||||
apt-get -y build-dep mesa
|
||||
sudo apt -y remove llvm-18 llvm-18-*
|
||||
set -e
|
||||
|
||||
CURRENT_CLANG_VERSION=$(clang --version | head -n 1 | awk '{ print $4 }' | awk 'BEGIN { FS="\\." } { print $1 }')
|
||||
GITHUB_CLANG_VERSION=${GITHUB_CLANG_VERSION:-${CURRENT_CLANG_VERSION}}
|
||||
|
||||
sudo apt-get -y install clang-${GITHUB_CLANG_VERSION} \
|
||||
libc++-${GITHUB_CLANG_VERSION}-dev \
|
||||
libc++abi-${GITHUB_CLANG_VERSION}-dev \
|
||||
|
||||
Vendored
+2
-54
@@ -12,59 +12,7 @@ set(DAWN_ABSEIL_DIR ${EXTERNAL}/abseil)
|
||||
set(DAWN_SPIRV_TOOLS_DIR ${EXTERNAL}/spirv-tools/)
|
||||
set(DAWN_SPIRV_HEADERS_DIR ${EXTERNAL}/spirv-headers)
|
||||
set(DAWN_GLSLANG_DIR ${EXTERNAL}/glslang/)
|
||||
set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF)
|
||||
|
||||
#set(TINT_BUILD_CMD_TOOLS OFF)
|
||||
|
||||
if (FILAMENT_BUILD_FILAMAT)
|
||||
if(IS_HOST_PLATFORM)
|
||||
set(TINT_BUILD_SPV_READER ON)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(../ ${PROJECT_BINARY_DIR}/third_party/dawn)
|
||||
|
||||
# Need to install libtint for filamat on Android.
|
||||
# See third_party/dawn/tnt/CMakeLists.txt and android/filamat-android/CMakeLists.txt.
|
||||
if (ANDROID AND FILAMENT_BUILD_FILAMAT)
|
||||
set(COMBINED_TARGET libtint_combined)
|
||||
set(COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${COMBINED_TARGET}.a")
|
||||
|
||||
# TODO: maybe use this target in place of libtint in filamat proper. (it's smaller)
|
||||
set(LIBTINT_DEPS
|
||||
tint_lang_core
|
||||
tint_lang_core_constant
|
||||
tint_lang_core_intrinsic
|
||||
tint_lang_core_type
|
||||
tint_lang_spirv_reader
|
||||
tint_lang_spirv_reader_ast_lower
|
||||
tint_lang_spirv_reader_ast_parser
|
||||
tint_lang_spirv_reader_common
|
||||
tint_lang_spirv_writer
|
||||
tint_lang_wgsl
|
||||
tint_lang_wgsl_ast
|
||||
tint_lang_wgsl_ast_transform
|
||||
tint_lang_wgsl_features
|
||||
tint_lang_wgsl_intrinsic
|
||||
tint_lang_wgsl_program
|
||||
tint_lang_wgsl_resolver
|
||||
tint_lang_wgsl_sem
|
||||
tint_lang_wgsl_writer
|
||||
tint_lang_wgsl_writer_ast_printer
|
||||
tint_results
|
||||
tint_utils
|
||||
tint_utils_diagnostic
|
||||
tint_utils_ice
|
||||
tint_utils_result
|
||||
tint_utils_rtti
|
||||
tint_utils_strconv
|
||||
tint_utils_symbol
|
||||
tint_utils_text
|
||||
)
|
||||
|
||||
# Use the following no-op definitions to introduce a library and its dependency.
|
||||
add_library(${COMBINED_TARGET} STATIC dummy.cpp)
|
||||
target_link_libraries(${COMBINED_TARGET} PRIVATE
|
||||
${LIBTINT_DEPS}
|
||||
)
|
||||
combine_static_libs(${COMBINED_TARGET} "${COMBINED_OUTPUT}" "${LIBTINT_DEPS}")
|
||||
install(FILES "${COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR})
|
||||
endif()
|
||||
add_subdirectory(../ ${PROJECT_BINARY_DIR}/third_party/dawn)
|
||||
Vendored
+9
-80
@@ -30,44 +30,15 @@
|
||||
#
|
||||
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
config_setting(
|
||||
name = "qnx",
|
||||
constraint_values = ["@platforms//os:qnx"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@platforms//os:windows"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "freebsd",
|
||||
constraint_values = ["@platforms//os:freebsd"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "openbsd",
|
||||
constraint_values = ["@platforms//os:openbsd"],
|
||||
)
|
||||
|
||||
# NOTE: Fuchsia is not an officially supported platform.
|
||||
config_setting(
|
||||
name = "fuchsia",
|
||||
constraint_values = ["@platforms//os:fuchsia"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "msvc_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
constraint_values = ["@bazel_tools//platforms:windows"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
@@ -83,10 +54,6 @@ cc_library(
|
||||
)
|
||||
|
||||
# Google Test including Google Mock
|
||||
|
||||
# For an actual test, use `gtest` and also `gtest_main` if you depend on gtest's
|
||||
# main(). For a library, use `gtest_for_library` instead if the library can be
|
||||
# testonly.
|
||||
cc_library(
|
||||
name = "gtest",
|
||||
srcs = glob(
|
||||
@@ -109,7 +76,6 @@ cc_library(
|
||||
"googlemock/include/gmock/*.h",
|
||||
]),
|
||||
copts = select({
|
||||
":qnx": [],
|
||||
":windows": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
@@ -128,59 +94,22 @@ cc_library(
|
||||
"googletest/include",
|
||||
],
|
||||
linkopts = select({
|
||||
":qnx": ["-lregex"],
|
||||
":windows": [],
|
||||
":freebsd": [
|
||||
"-lm",
|
||||
"-pthread",
|
||||
],
|
||||
":openbsd": [
|
||||
"-lm",
|
||||
"-pthread",
|
||||
],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
deps = select({
|
||||
":has_absl": [
|
||||
"@abseil-cpp//absl/container:flat_hash_set",
|
||||
"@abseil-cpp//absl/debugging:failure_signal_handler",
|
||||
"@abseil-cpp//absl/debugging:stacktrace",
|
||||
"@abseil-cpp//absl/debugging:symbolize",
|
||||
"@abseil-cpp//absl/flags:flag",
|
||||
"@abseil-cpp//absl/flags:parse",
|
||||
"@abseil-cpp//absl/flags:reflection",
|
||||
"@abseil-cpp//absl/flags:usage",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/types:any",
|
||||
"@abseil-cpp//absl/types:optional",
|
||||
"@abseil-cpp//absl/types:variant",
|
||||
"@re2//:re2",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
# `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process,
|
||||
# expects it to crash and inspects its logs with the given matcher,
|
||||
# so that's why these libraries are needed.
|
||||
# Otherwise, builds targeting Fuchsia would fail to compile.
|
||||
":fuchsia": [
|
||||
"@fuchsia_sdk//pkg/fdio",
|
||||
"@fuchsia_sdk//pkg/syslog",
|
||||
"@fuchsia_sdk//pkg/zx",
|
||||
"@com_google_absl//absl/debugging:failure_signal_handler",
|
||||
"@com_google_absl//absl/debugging:stacktrace",
|
||||
"@com_google_absl//absl/debugging:symbolize",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
# `gtest`, but testonly. See guidance on `gtest` for when to use this.
|
||||
alias(
|
||||
name = "gtest_for_library",
|
||||
actual = ":gtest",
|
||||
testonly = True,
|
||||
)
|
||||
|
||||
# Implements main() for tests using gtest. Prefer to depend on `gtest` as well
|
||||
# to ensure compliance with the layering_check Bazel feature where only the
|
||||
# direct hdrs values are available.
|
||||
cc_library(
|
||||
name = "gtest_main",
|
||||
srcs = ["googlemock/src/gmock_main.cc"],
|
||||
|
||||
Vendored
+15
-15
@@ -1,13 +1,23 @@
|
||||
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||
# internally.
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.16.0)
|
||||
set(GOOGLETEST_VERSION 1.9.0)
|
||||
|
||||
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_definitions(-std=c++11)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CYGWIN)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
@@ -15,19 +25,9 @@ enable_testing()
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Note that googlemock target already builds googletest.
|
||||
#Note that googlemock target already builds googletest
|
||||
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
|
||||
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
|
||||
option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF)
|
||||
|
||||
if(GTEST_HAS_ABSL)
|
||||
if(NOT TARGET absl::base)
|
||||
find_package(absl REQUIRED)
|
||||
endif()
|
||||
if(NOT TARGET re2::re2)
|
||||
find_package(re2 REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_GMOCK)
|
||||
add_subdirectory( googlemock )
|
||||
|
||||
Vendored
+32
-31
@@ -21,14 +21,14 @@ accept your pull requests.
|
||||
|
||||
## Are you a Googler?
|
||||
|
||||
If you are a Googler, please make an attempt to submit an internal contribution
|
||||
rather than a GitHub Pull Request. If you are not able to submit internally, a
|
||||
If you are a Googler, please make an attempt to submit an internal change rather
|
||||
than a GitHub Pull Request. If you are not able to submit an internal change a
|
||||
PR is acceptable as an alternative.
|
||||
|
||||
## Contributing A Patch
|
||||
|
||||
1. Submit an issue describing your proposed change to the
|
||||
[issue tracker](https://github.com/google/googletest/issues).
|
||||
[issue tracker](https://github.com/google/googletest).
|
||||
2. Please don't mix more than one logical change per submittal, because it
|
||||
makes the history hard to follow. If you want to make a change that doesn't
|
||||
have a corresponding issue in the issue tracker, please create one.
|
||||
@@ -36,8 +36,7 @@ PR is acceptable as an alternative.
|
||||
This ensures that work isn't being duplicated and communicating your plan
|
||||
early also generally leads to better patches.
|
||||
4. If your proposed change is accepted, and you haven't already done so, sign a
|
||||
Contributor License Agreement
|
||||
([see details above](#contributor-license-agreements)).
|
||||
Contributor License Agreement (see details above).
|
||||
5. Fork the desired repo, develop and test your code changes.
|
||||
6. Ensure that your code adheres to the existing style in the sample to which
|
||||
you are contributing.
|
||||
@@ -47,11 +46,11 @@ PR is acceptable as an alternative.
|
||||
## The Google Test and Google Mock Communities
|
||||
|
||||
The Google Test community exists primarily through the
|
||||
[discussion group](https://groups.google.com/group/googletestframework) and the
|
||||
[discussion group](http://groups.google.com/group/googletestframework) and the
|
||||
GitHub repository. Likewise, the Google Mock community exists primarily through
|
||||
their own [discussion group](https://groups.google.com/group/googlemock). You
|
||||
are definitely encouraged to contribute to the discussion and you can also help
|
||||
us to keep the effectiveness of the group high by following and promoting the
|
||||
their own [discussion group](http://groups.google.com/group/googlemock). You are
|
||||
definitely encouraged to contribute to the discussion and you can also help us
|
||||
to keep the effectiveness of the group high by following and promoting the
|
||||
guidelines listed here.
|
||||
|
||||
### Please Be Friendly
|
||||
@@ -80,17 +79,17 @@ fairly rigid coding style, as defined by the
|
||||
[google-styleguide](https://github.com/google/styleguide) project. All patches
|
||||
will be expected to conform to the style outlined
|
||||
[here](https://google.github.io/styleguide/cppguide.html). Use
|
||||
[.clang-format](https://github.com/google/googletest/blob/main/.clang-format) to
|
||||
check your formatting.
|
||||
[.clang-format](https://github.com/google/googletest/blob/master/.clang-format)
|
||||
to check your formatting
|
||||
|
||||
## Requirements for Contributors
|
||||
|
||||
If you plan to contribute a patch, you need to build Google Test, Google Mock,
|
||||
and their own tests from a git checkout, which has further requirements:
|
||||
|
||||
* [Python](https://www.python.org/) v3.6 or newer (for running some of the
|
||||
* [Python](https://www.python.org/) v2.3 or newer (for running some of the
|
||||
tests and re-generating certain source files from templates)
|
||||
* [CMake](https://cmake.org/) v2.8.12 or newer
|
||||
* [CMake](https://cmake.org/) v2.6.4 or newer
|
||||
|
||||
## Developing Google Test and Google Mock
|
||||
|
||||
@@ -102,40 +101,42 @@ To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test and GoogleMock's own
|
||||
tests. For that you can use CMake:
|
||||
|
||||
```
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
|
||||
```
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
|
||||
|
||||
To choose between building only Google Test or Google Mock, you may modify your
|
||||
cmake command to be one of each
|
||||
|
||||
```
|
||||
cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
|
||||
cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
|
||||
```
|
||||
cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
|
||||
cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests are written
|
||||
in Python. If the cmake command complains about not being able to find Python
|
||||
(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it
|
||||
explicitly where your Python executable can be found:
|
||||
|
||||
```
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python ...
|
||||
```
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python ...
|
||||
|
||||
Next, you can build Google Test and / or Google Mock and all desired tests. On
|
||||
\*nix, this is usually done by
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
make
|
||||
|
||||
To run the tests, do
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files
|
||||
|
||||
Some of Google Test's source files are generated from templates (not in the C++
|
||||
sense) using a script. For example, the file
|
||||
include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
You don't need to worry about regenerating the source files unless you need to
|
||||
modify them. You would then modify the corresponding `.pump` files and run the
|
||||
'[pump.py](googletest/scripts/pump.py)' generator script. See the
|
||||
[Pump Manual](googletest/docs/pump_manual.md).
|
||||
|
||||
Vendored
+86
-92
@@ -1,110 +1,93 @@
|
||||
# GoogleTest
|
||||
# Google Test
|
||||
|
||||
### Announcements
|
||||
#### Announcement:
|
||||
|
||||
#### Live at Head
|
||||
Please note that Sept 13 - Sept 20 most of the maintainers will be attending
|
||||
CppCon 2019. Our response time for Pull Requests and Issues will increase.
|
||||
|
||||
GoogleTest now follows the
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
|
||||
We recommend
|
||||
[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
|
||||
We do publish occasional semantic versions, tagged with
|
||||
`v${major}.${minor}.${patch}` (e.g. `v1.16.0`).
|
||||
#### OSS Builds Status:
|
||||
|
||||
#### Documentation Updates
|
||||
[](https://travis-ci.org/google/googletest)
|
||||
[](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
|
||||
|
||||
Our documentation is now live on GitHub Pages at
|
||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||
GitHub Pages rather than directly in the repository.
|
||||
### Future Plans
|
||||
|
||||
#### Release 1.16.0
|
||||
#### 1.8.x Release:
|
||||
|
||||
[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is
|
||||
now available.
|
||||
[the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is
|
||||
the last release that works with pre-C++11 compilers. The 1.8.x will not accept
|
||||
any requests for any new features and any bugfix requests will only be accepted
|
||||
if proven "critical"
|
||||
|
||||
The 1.16.x branch requires at least C++14.
|
||||
#### Post 1.8.x:
|
||||
|
||||
The 1.16.x branch will be the last to support C++14. Future development will
|
||||
[require at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
|
||||
On-going work to improve/cleanup/pay technical debt. When this work is completed
|
||||
there will be a 1.9.x tagged release
|
||||
|
||||
#### Continuous Integration
|
||||
#### Post 1.9.x
|
||||
|
||||
We use Google's internal systems for continuous integration.
|
||||
Post 1.9.x googletest will follow
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy)
|
||||
|
||||
#### Coming Soon
|
||||
|
||||
* We are planning to take a dependency on
|
||||
[Abseil](https://github.com/abseil/abseil-cpp).
|
||||
|
||||
## Welcome to **GoogleTest**, Google's C++ test framework!
|
||||
## Welcome to **Google Test**, Google's C++ test framework!
|
||||
|
||||
This repository is a merger of the formerly separate GoogleTest and GoogleMock
|
||||
projects. These were so closely related that it makes sense to maintain and
|
||||
release them together.
|
||||
|
||||
### Getting Started
|
||||
Please subscribe to the mailing list at googletestframework@googlegroups.com for
|
||||
questions, discussions, and development.
|
||||
|
||||
See the [GoogleTest User's Guide](https://google.github.io/googletest/) for
|
||||
documentation. We recommend starting with the
|
||||
[GoogleTest Primer](https://google.github.io/googletest/primer.html).
|
||||
### Getting started:
|
||||
|
||||
More information about building GoogleTest can be found at
|
||||
[googletest/README.md](googletest/README.md).
|
||||
The information for **Google Test** is available in the
|
||||
[Google Test Primer](googletest/docs/primer.md) documentation.
|
||||
|
||||
**Google Mock** is an extension to Google Test for writing and using C++ mock
|
||||
classes. See the separate [Google Mock documentation](googlemock/README.md).
|
||||
|
||||
More detailed documentation for googletest is in its interior
|
||||
[googletest/README.md](googletest/README.md) file.
|
||||
|
||||
## Features
|
||||
|
||||
* xUnit test framework: \
|
||||
Googletest is based on the [xUnit](https://en.wikipedia.org/wiki/XUnit)
|
||||
testing framework, a popular architecture for unit testing
|
||||
* Test discovery: \
|
||||
Googletest automatically discovers and runs your tests, eliminating the need
|
||||
to manually register your tests
|
||||
* Rich set of assertions: \
|
||||
Googletest provides a variety of assertions, such as equality, inequality,
|
||||
exceptions, and more, making it easy to test your code
|
||||
* User-defined assertions: \
|
||||
You can define your own assertions with Googletest, making it simple to
|
||||
write tests that are specific to your code
|
||||
* Death tests: \
|
||||
Googletest supports death tests, which verify that your code exits in a
|
||||
certain way, making it useful for testing error-handling code
|
||||
* Fatal and non-fatal failures: \
|
||||
You can specify whether a test failure should be treated as fatal or
|
||||
non-fatal with Googletest, allowing tests to continue running even if a
|
||||
failure occurs
|
||||
* Value-parameterized tests: \
|
||||
Googletest supports value-parameterized tests, which run multiple times with
|
||||
different input values, making it useful for testing functions that take
|
||||
different inputs
|
||||
* Type-parameterized tests: \
|
||||
Googletest also supports type-parameterized tests, which run with different
|
||||
data types, making it useful for testing functions that work with different
|
||||
data types
|
||||
* Various options for running tests: \
|
||||
Googletest provides many options for running tests including running
|
||||
individual tests, running tests in a specific order and running tests in
|
||||
parallel
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
## Supported Platforms
|
||||
## Platforms
|
||||
|
||||
GoogleTest follows Google's
|
||||
[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
|
||||
See
|
||||
[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)
|
||||
for a list of currently supported versions of compilers, platforms, and build
|
||||
tools.
|
||||
Google test has been used on a variety of platforms:
|
||||
|
||||
## Who Is Using GoogleTest?
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows
|
||||
* Cygwin
|
||||
* MinGW
|
||||
* Windows Mobile
|
||||
* Symbian
|
||||
* PlatformIO
|
||||
|
||||
In addition to many internal projects at Google, GoogleTest is also used by the
|
||||
## Who Is Using Google Test?
|
||||
|
||||
In addition to many internal projects at Google, Google Test is also used by the
|
||||
following notable projects:
|
||||
|
||||
* The [Chromium projects](https://www.chromium.org/) (behind the Chrome
|
||||
browser and Chrome OS).
|
||||
* The [LLVM](https://llvm.org/) compiler.
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
|
||||
and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](https://opencv.org/) computer vision library.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only,
|
||||
dependency-free deep learning framework in C++11.
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
@@ -112,13 +95,13 @@ following notable projects:
|
||||
automated test-runner and Graphical User Interface with powerful features for
|
||||
Windows and Linux platforms.
|
||||
|
||||
[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that
|
||||
[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that
|
||||
runs your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. GoogleTest
|
||||
UI is written in C#.
|
||||
displays a list of test failures. Clicking on one shows failure text. Google
|
||||
Test UI is written in C#.
|
||||
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for GoogleTest that implements the
|
||||
listener for Google Test that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
@@ -126,20 +109,31 @@ result output. If your test runner understands TAP, you may find it useful.
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
|
||||
is a VS Code extension allowing to view GoogleTest in a tree view and run/debug
|
||||
your tests.
|
||||
is a VS Code extension allowing to view Google Tests in a tree view, and
|
||||
run/debug your tests.
|
||||
|
||||
[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS
|
||||
Code extension allowing to view GoogleTest in a tree view and run/debug your
|
||||
tests.
|
||||
## Requirements
|
||||
|
||||
[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser
|
||||
that generates stub code for GoogleTest.
|
||||
Google Test is designed to have fairly minimal requirements to build and use
|
||||
with your projects, but there are some. If you notice any problems on your
|
||||
platform, please notify
|
||||
[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework).
|
||||
Patches for fixing them are welcome!
|
||||
|
||||
## Contributing Changes
|
||||
### Build Requirements
|
||||
|
||||
Please read
|
||||
[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md)
|
||||
for details on how to contribute to this project.
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package:
|
||||
|
||||
* [Bazel](https://bazel.build/) or [CMake](https://cmake.org/). NOTE: Bazel is
|
||||
the build system that googletest is using internally and tests against.
|
||||
CMake is community-supported.
|
||||
|
||||
* a C++11-standard-compliant compiler
|
||||
|
||||
## Contributing change
|
||||
|
||||
Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to
|
||||
contribute to this project.
|
||||
|
||||
Happy testing!
|
||||
|
||||
Vendored
+16
-54
@@ -1,61 +1,23 @@
|
||||
# Copyright 2024 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
workspace(name = "googletest")
|
||||
|
||||
load("//:googletest_deps.bzl", "googletest_deps")
|
||||
googletest_deps()
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Abseil
|
||||
http_archive(
|
||||
name = "com_google_absl",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
|
||||
strip_prefix = "abseil-cpp-master",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
strip_prefix = "rules_cc-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_cc/archive/master.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
|
||||
strip_prefix = "rules_python-1.1.0",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
|
||||
)
|
||||
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
|
||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||
py_repositories()
|
||||
|
||||
http_archive(
|
||||
name = "bazel_skylib",
|
||||
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
|
||||
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
|
||||
strip_prefix = "rules_python-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/master.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "platforms",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
||||
"https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
||||
],
|
||||
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
|
||||
)
|
||||
|
||||
Vendored
+154
@@ -0,0 +1,154 @@
|
||||
version: '{build}'
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
build_system: bazel
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015"
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
|
||||
- compiler: gcc-6.3.0-posix
|
||||
build_system: cmake
|
||||
generator: "MinGW Makefiles"
|
||||
cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
|
||||
enabled_on_pr: yes
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
build:
|
||||
verbosity: minimal
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
Write-Output "Compiler: $env:compiler"
|
||||
Write-Output "Generator: $env:generator"
|
||||
Write-Output "Env:Configuation: $env:configuration"
|
||||
Write-Output "Env: $env"
|
||||
if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) {
|
||||
Write-Output "This is *NOT* a pull request build"
|
||||
} else {
|
||||
Write-Output "This is a pull request build"
|
||||
if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") {
|
||||
Write-Output "PR builds are *NOT* explicitly enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# install Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
appveyor DownloadFile https://github.com/bazelbuild/bazel/releases/download/0.28.1/bazel-0.28.1-windows-x86_64.exe -FileName bazel.exe
|
||||
}
|
||||
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# git bash conflicts with MinGW makefiles
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
$env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "")
|
||||
if ($env:cxx_path -ne "") {
|
||||
$env:path += ";$env:cxx_path"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
$env:root=$env:APPVEYOR_BUILD_FOLDER
|
||||
Write-Output "env:root: $env:root"
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
} else {
|
||||
# special case - build with Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
& $env:root\bazel.exe build -c opt //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
# by default build with CMake
|
||||
md _build -Force | Out-Null
|
||||
cd _build
|
||||
|
||||
$conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"}
|
||||
# Disable test for MinGW (gtest tests fail, gmock tests can not build)
|
||||
$gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"}
|
||||
$gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"}
|
||||
& cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests ..
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
$cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
|
||||
& cmake --build . --config $env:configuration -- $cmake_parallel
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
|
||||
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/*.md'
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
}
|
||||
if ($env:build_system -eq "bazel") {
|
||||
# special case - testing with Bazel
|
||||
& $env:root\bazel.exe test //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# built with CMake - test with CTest
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
return # No test available for MinGW
|
||||
}
|
||||
|
||||
& ctest -C $env:configuration --timeout 600 --output-on-failure
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
- path: '_build/Testing/**/*.xml'
|
||||
name: test_results
|
||||
- path: 'bazel-testlogs/**/test.log'
|
||||
name: test_logs
|
||||
- path: 'bazel-testlogs/**/test.xml'
|
||||
name: test_results
|
||||
Vendored
Regular → Executable
+8
-6
@@ -1,4 +1,5 @@
|
||||
# Copyright 2024 Google Inc.
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
@@ -28,8 +29,9 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# https://bazel.build/external/migration#workspace.bzlmod
|
||||
#
|
||||
# This file is intentionally empty. When bzlmod is enabled and this
|
||||
# file exists, the content of WORKSPACE is ignored. This prevents
|
||||
# bzlmod builds from unintentionally depending on the WORKSPACE file.
|
||||
set -e
|
||||
|
||||
bazel version
|
||||
bazel build --curses=no //...:all
|
||||
bazel test --curses=no //...:all
|
||||
bazel test --curses=no //...:all --define absl=1
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
# run PlatformIO builds
|
||||
platformio run
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# This file should be sourced, and not executed as a standalone script.
|
||||
#
|
||||
|
||||
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||
if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.9" CC="clang-3.9"; fi
|
||||
fi
|
||||
+17
-30
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Copyright 2019 Google LLC. All Rights Reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
@@ -27,34 +28,20 @@
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""Tests Google Test's gtest skip in environment setup behavior.
|
||||
|
||||
This script invokes gtest_skip_in_environment_setup_test_ and verifies its
|
||||
output.
|
||||
"""
|
||||
#
|
||||
# This file should be sourced, and not executed as a standalone script.
|
||||
#
|
||||
|
||||
import re
|
||||
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||
#
|
||||
|
||||
from googletest.test import gtest_test_utils
|
||||
|
||||
# Path to the gtest_skip_in_environment_setup_test binary
|
||||
EXE_PATH = gtest_test_utils.GetTestExecutablePath('gtest_skip_test')
|
||||
|
||||
OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
|
||||
|
||||
|
||||
# Test.
|
||||
class SkipEntireEnvironmentTest(gtest_test_utils.TestCase):
|
||||
|
||||
def testSkipEntireEnvironmentTest(self):
|
||||
self.assertIn('Skipped\nskipping single test\n', OUTPUT)
|
||||
skip_fixture = 'Skipped\nskipping all tests for this fixture\n'
|
||||
self.assertIsNotNone(
|
||||
re.search(skip_fixture + '.*' + skip_fixture, OUTPUT, flags=re.DOTALL),
|
||||
repr(OUTPUT),
|
||||
)
|
||||
self.assertNotIn('FAILED', OUTPUT)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
gtest_test_utils.Main()
|
||||
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||
if [ "$CXX" = "clang++" ]; then
|
||||
# $PATH needs to be adjusted because the llvm tap doesn't install the
|
||||
# package to /usr/local/bin, etc, like the gcc tap does.
|
||||
# See: https://github.com/Homebrew/legacy-homebrew/issues/29733
|
||||
clang_version=3.9
|
||||
export PATH="/usr/local/opt/llvm@${clang_version}/bin:$PATH";
|
||||
fi
|
||||
fi
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# This file is typically sourced by another script.
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ] ; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
||||
Vendored
Regular → Executable
+17
-44
@@ -1,4 +1,5 @@
|
||||
# Copyright 2024 Google Inc.
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
@@ -28,49 +29,21 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# https://bazel.build/external/overview#bzlmod
|
||||
set -eu
|
||||
|
||||
module(
|
||||
name = "googletest",
|
||||
version = "head",
|
||||
compatibility_level = 1,
|
||||
)
|
||||
if [ "${TRAVIS_OS_NAME}" != linux ]; then
|
||||
echo "Not a Linux build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Only direct dependencies need to be listed below.
|
||||
# Please keep the versions in sync with the versions in the WORKSPACE file.
|
||||
|
||||
bazel_dep(
|
||||
name = "abseil-cpp",
|
||||
version = "20250127.0",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "platforms",
|
||||
version = "0.0.10",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "re2",
|
||||
version = "2024-07-02",
|
||||
)
|
||||
|
||||
bazel_dep(
|
||||
name = "rules_python",
|
||||
version = "1.1.0",
|
||||
dev_dependency = True,
|
||||
)
|
||||
|
||||
# https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage
|
||||
python = use_extension(
|
||||
"@rules_python//python/extensions:python.bzl",
|
||||
"python",
|
||||
dev_dependency = True,
|
||||
)
|
||||
python.toolchain(
|
||||
ignore_root_user_error = True,
|
||||
is_default = True,
|
||||
python_version = "3.12",
|
||||
)
|
||||
|
||||
# See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed.
|
||||
fuchsia_sdk = use_extension("//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
|
||||
fuchsia_sdk.create_fake()
|
||||
use_repo(fuchsia_sdk, "fuchsia_sdk")
|
||||
if [ "${TRAVIS_SUDO}" = "true" ]; then
|
||||
echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
|
||||
sudo tee /etc/apt/sources.list.d/bazel.list
|
||||
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
|
||||
sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.9
|
||||
elif [ "${CXX}" = "clang++" ]; then
|
||||
# Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment.
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CXX};
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CC};
|
||||
fi
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" != "osx" ]; then
|
||||
echo "Not a macOS build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
brew update
|
||||
brew install ccache gcc@4.9
|
||||
@@ -0,0 +1,5 @@
|
||||
# install PlatformIO
|
||||
sudo pip install -U platformio
|
||||
|
||||
# update PlatformIO
|
||||
platformio update
|
||||
-157
@@ -1,157 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
|
||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
|
||||
if [[ -z ${STD:-} ]]; then
|
||||
STD="c++17 c++20"
|
||||
fi
|
||||
|
||||
# Test CMake + GCC
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env=CXXFLAGS="-Werror -Wdeprecated" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
|
||||
# Test CMake + Clang
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||
--env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
|
||||
# Do one test with an older version of GCC
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=c++17" \
|
||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--copt="-Wno-error=pragmas" \
|
||||
--enable_bzlmod=false \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
|
||||
# Test GCC
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--define="absl=${absl}" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
||||
|
||||
# Test Clang
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="--gcc-toolchain=/usr/local" \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--define="absl=${absl}" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--linkopt="--gcc-toolchain=/usr/local" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
||||
+18
-25
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Copyright 2019, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
@@ -29,30 +29,23 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Verifies that SetUpTestSuite and TearDownTestSuite errors are noticed."""
|
||||
set -e
|
||||
|
||||
from googletest.test import gtest_test_utils
|
||||
# ccache on OS X needs installation first
|
||||
# reset ccache statistics
|
||||
ccache --zero-stats
|
||||
|
||||
COMMAND = gtest_test_utils.GetTestExecutablePath(
|
||||
'googletest-setuptestsuite-test_'
|
||||
)
|
||||
echo PATH=${PATH}
|
||||
|
||||
echo "Compiler configuration:"
|
||||
echo CXX=${CXX}
|
||||
echo CC=${CC}
|
||||
echo CXXFLAGS=${CXXFLAGS}
|
||||
|
||||
class GTestSetUpTestSuiteTest(gtest_test_utils.TestCase):
|
||||
echo "C++ compiler version:"
|
||||
${CXX} --version || echo "${CXX} does not seem to support the --version flag"
|
||||
${CXX} -v || echo "${CXX} does not seem to support the -v flag"
|
||||
|
||||
def testSetupErrorAndTearDownError(self):
|
||||
p = gtest_test_utils.Subprocess(COMMAND)
|
||||
self.assertNotEqual(p.exit_code, 0, msg=p.output)
|
||||
|
||||
self.assertIn(
|
||||
(
|
||||
'[ FAILED ] SetupFailTest: SetUpTestSuite or TearDownTestSuite\n['
|
||||
' FAILED ] TearDownFailTest: SetUpTestSuite or'
|
||||
' TearDownTestSuite\n\n 2 FAILED TEST SUITES\n'
|
||||
),
|
||||
p.output,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
gtest_test_utils.Main()
|
||||
echo "C compiler version:"
|
||||
${CC} --version || echo "${CXX} does not seem to support the --version flag"
|
||||
${CC} -v || echo "${CXX} does not seem to support the -v flag"
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env sh
|
||||
set -evx
|
||||
|
||||
. ci/get-nprocessors.sh
|
||||
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ] ; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
||||
# Tell make to use the processors. No preceding '-' required.
|
||||
MAKEFLAGS="j${NPROCESSORS}"
|
||||
export MAKEFLAGS
|
||||
|
||||
env | sort
|
||||
|
||||
# Set default values to OFF for these variables if not specified.
|
||||
: "${NO_EXCEPTION:=OFF}"
|
||||
: "${NO_RTTI:=OFF}"
|
||||
: "${COMPILER_IS_GNUCXX:=OFF}"
|
||||
|
||||
mkdir build || true
|
||||
cd build
|
||||
cmake -Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=$NO_EXCEPTION \
|
||||
-Dcxx_no_rtti=$NO_RTTI \
|
||||
-DCMAKE_COMPILER_IS_GNUCXX=$COMPILER_IS_GNUCXX \
|
||||
-DCMAKE_CXX_FLAGS=$CXX_FLAGS \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
..
|
||||
make
|
||||
CTEST_OUTPUT_ON_FAILURE=1 make test
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user