Compare commits
889
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e96a302e79 | ||
|
|
a4dd357781 | ||
|
|
009fb0e121 | ||
|
|
2779c00ec4 | ||
|
|
43d6909939 | ||
|
|
4eb669d59a | ||
|
|
3681fe9657 | ||
|
|
1dcc141e26 | ||
|
|
83d71d0f57 | ||
|
|
cb8b1bfefa | ||
|
|
d8b994bef1 | ||
|
|
8824f59051 | ||
|
|
e057844742 | ||
|
|
6aa20312e5 | ||
|
|
d8af04f08f | ||
|
|
559bc4eb96 | ||
|
|
c16cab239d | ||
|
|
68719f913a | ||
|
|
038ed69a92 | ||
|
|
69822a91cf | ||
|
|
24ff10b5db | ||
|
|
ec2f5b8078 | ||
|
|
082da86ca8 | ||
|
|
dd51e1dd96 | ||
|
|
538aa39127 | ||
|
|
8de56a2bbc | ||
|
|
ea5d7d4f47 | ||
|
|
05cdeccc27 | ||
|
|
ad4f349f00 | ||
|
|
06a2def85f | ||
|
|
a04019937e | ||
|
|
fff7bd2b28 | ||
|
|
3c4591df17 | ||
|
|
4fe852e88a | ||
|
|
864529254e | ||
|
|
93fa55bd29 | ||
|
|
fb9518e915 | ||
|
|
b780cb36d0 | ||
|
|
62cd8f1d35 | ||
|
|
793f2b4eb7 | ||
|
|
9a2ca8ddbb | ||
|
|
67710723d7 | ||
|
|
40851f4b51 | ||
|
|
87bdf96449 | ||
|
|
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 |
+17
-10
@@ -667,10 +667,6 @@ function(list_licenses OUTPUT MODULES)
|
||||
endfunction()
|
||||
|
||||
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/linux/combine-static-libs.sh")
|
||||
if (WIN32)
|
||||
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/windows/combine-static-libs.bat")
|
||||
set(CMAKE_AR "lib.exe")
|
||||
endif()
|
||||
|
||||
# Add a custom command to TARGET that combines the static libraries in DEPS into a single archive.
|
||||
function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
@@ -685,12 +681,22 @@ function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
if (WIN32)
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND lib.exe /nologo /out:temp.lib ${DEPS_FILES}
|
||||
COMMAND "${CMAKE_COMMAND}" -E rename temp.lib ${OUTPUT}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_command(
|
||||
TARGET ${TARGET} POST_BUILD
|
||||
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
|
||||
COMMENT "Combining ${target} dependencies into single shared library"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ==================================================================================================
|
||||
@@ -761,6 +767,7 @@ add_subdirectory(${LIBRARIES}/utils)
|
||||
add_subdirectory(${LIBRARIES}/viewer)
|
||||
add_subdirectory(${FILAMENT}/filament)
|
||||
add_subdirectory(${FILAMENT}/shaders)
|
||||
add_subdirectory(${EXTERNAL}/abseil/tnt)
|
||||
add_subdirectory(${EXTERNAL}/basisu/tnt)
|
||||
add_subdirectory(${EXTERNAL}/civetweb/tnt)
|
||||
add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.56.8'
|
||||
implementation 'com.google.android.filament:filament-android:1.57.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.56.8'
|
||||
pod 'Filament', '~> 1.57.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,6 +7,14 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.57.1
|
||||
|
||||
|
||||
## v1.57.0
|
||||
|
||||
- matdbg: Add support for debugging ESSL 1.0 shaders
|
||||
- backend: New platform API to better handle external textures [⚠️ **New Material Version**]
|
||||
|
||||
## v1.56.8
|
||||
|
||||
|
||||
|
||||
@@ -329,6 +329,18 @@ Java_com_google_android_filament_MaterialInstance_nSetCullingMode(JNIEnv*,
|
||||
instance->setCullingMode((MaterialInstance::CullingMode) cullingMode);
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetCullingModeSeparate(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance,
|
||||
jlong colorPassCullingMode, jlong shadowPassCullingMode) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setCullingMode(
|
||||
(MaterialInstance::CullingMode) colorPassCullingMode,
|
||||
(MaterialInstance::CullingMode) shadowPassCullingMode);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetColorWrite(JNIEnv*,
|
||||
@@ -505,6 +517,14 @@ Java_com_google_android_filament_MaterialInstance_nGetCullingMode(JNIEnv* env, j
|
||||
return (jint)instance->getCullingMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetShadowCullingMode(JNIEnv* env, jclass,
|
||||
jlong nativeMaterialInstance) {
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return (jint)instance->getShadowCullingMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
|
||||
+25
@@ -556,6 +556,20 @@ public class MaterialInstance {
|
||||
nSetCullingMode(getNativeObject(), mode.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material separately for the
|
||||
* color and shadow passes
|
||||
*
|
||||
* @see
|
||||
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
|
||||
* Rasterization: culling</a>
|
||||
*/
|
||||
public void setCullingMode(@NonNull Material.CullingMode colorPassCullingMode,
|
||||
@NonNull Material.CullingMode shadowPassCullingMode) {
|
||||
nSetCullingModeSeparate(getNativeObject(),
|
||||
colorPassCullingMode.ordinal(), shadowPassCullingMode.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the face culling mode.
|
||||
*/
|
||||
@@ -564,6 +578,14 @@ public class MaterialInstance {
|
||||
return sCullingModeValues[nGetCullingMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the face culling mode for the shadow passes.
|
||||
*/
|
||||
@NonNull
|
||||
public Material.CullingMode getShadowCullingMode() {
|
||||
return sCullingModeValues[nGetShadowCullingMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*
|
||||
@@ -920,6 +942,8 @@ public class MaterialInstance {
|
||||
|
||||
private static native void nSetDoubleSided(long nativeMaterialInstance, boolean doubleSided);
|
||||
private static native void nSetCullingMode(long nativeMaterialInstance, long mode);
|
||||
private static native void nSetCullingModeSeparate(long nativeMaterialInstance,
|
||||
long colorPassCullingMode, long shadowPassCullingMode);
|
||||
private static native void nSetColorWrite(long nativeMaterialInstance, boolean enable);
|
||||
private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable);
|
||||
private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable);
|
||||
@@ -952,6 +976,7 @@ public class MaterialInstance {
|
||||
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance);
|
||||
private static native boolean nIsDoubleSided(long nativeMaterialInstance);
|
||||
private static native int nGetCullingMode(long nativeMaterialInstance);
|
||||
private static native int nGetShadowCullingMode(long nativeMaterialInstance);
|
||||
private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.56.8
|
||||
VERSION_NAME=1.57.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
@echo off
|
||||
set selfName=%0
|
||||
|
||||
:: Check that we have at least 3 arguments.
|
||||
set argC=0
|
||||
for %%x in (%*) do Set /A argC+=1
|
||||
if %argC% LSS 3 goto :print_help
|
||||
|
||||
set AR_TOOL=%1
|
||||
shift
|
||||
set OUTPUT_PATH=%1
|
||||
shift
|
||||
|
||||
set ARCHIVES=
|
||||
:loop
|
||||
if [%1]==[] goto :finished
|
||||
set ARCHIVES=%ARCHIVES% %1
|
||||
shift
|
||||
goto :loop
|
||||
|
||||
:finished
|
||||
|
||||
%AR_TOOL% /nologo /out:%OUTPUT_PATH% %ARCHIVES% || goto :error
|
||||
|
||||
exit /B %ERRORLEVEL%
|
||||
|
||||
:print_help
|
||||
echo %selfName%. Combine multiple static libraries using an archiver tool.
|
||||
echo;
|
||||
echo Usage:
|
||||
echo %selfName% ^<path-to-ar^> ^<output-archive^> ^<archives^>...
|
||||
echo;
|
||||
echo Notes:
|
||||
echo ^<archives^> must be a list of absolute paths to static library archives.
|
||||
echo This script creates a temporary working directory inside the current directory.
|
||||
exit /B 1
|
||||
|
||||
:error
|
||||
exit /B %ERRORLEVEL%
|
||||
@@ -385,16 +385,16 @@ endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/colorGrading.filamat"
|
||||
DEPENDS ../shaders/src/dithering.fs
|
||||
DEPENDS ../shaders/src/vignette.fs
|
||||
DEPENDS ../shaders/src/inline_dithering.fs
|
||||
DEPENDS ../shaders/src/inline_vignette.fs
|
||||
DEPENDS src/materials/colorGrading/colorGrading.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/colorGradingAsSubpass.filamat"
|
||||
DEPENDS ../shaders/src/dithering.fs
|
||||
DEPENDS ../shaders/src/vignette.fs
|
||||
DEPENDS ../shaders/src/inline_dithering.fs
|
||||
DEPENDS ../shaders/src/inline_vignette.fs
|
||||
DEPENDS src/materials/colorGrading/colorGrading.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
@@ -185,8 +185,15 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
src/vulkan/platform/VulkanPlatform.cpp
|
||||
src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp
|
||||
src/vulkan/platform/VulkanPlatformSwapChainImpl.h
|
||||
src/vulkan/spirv/VulkanSpirvUtils.cpp
|
||||
src/vulkan/spirv/VulkanSpirvUtils.h
|
||||
src/vulkan/utils/Conversion.cpp
|
||||
src/vulkan/utils/Conversion.h
|
||||
src/vulkan/utils/Definitions.h
|
||||
src/vulkan/utils/Helper.h
|
||||
src/vulkan/utils/Image.h
|
||||
src/vulkan/utils/Image.cpp
|
||||
src/vulkan/utils/Spirv.h
|
||||
src/vulkan/utils/Spirv.cpp
|
||||
src/vulkan/utils/StaticVector.h
|
||||
src/vulkan/VulkanAsyncHandles.cpp
|
||||
src/vulkan/VulkanAsyncHandles.h
|
||||
src/vulkan/VulkanBlitter.cpp
|
||||
@@ -205,8 +212,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
src/vulkan/VulkanFboCache.h
|
||||
src/vulkan/VulkanHandles.cpp
|
||||
src/vulkan/VulkanHandles.h
|
||||
src/vulkan/VulkanImageUtility.cpp
|
||||
src/vulkan/VulkanImageUtility.h
|
||||
src/vulkan/VulkanMemory.h
|
||||
src/vulkan/VulkanMemory.cpp
|
||||
src/vulkan/VulkanPipelineCache.cpp
|
||||
@@ -221,8 +226,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
||||
src/vulkan/VulkanReadPixels.h
|
||||
src/vulkan/VulkanTexture.cpp
|
||||
src/vulkan/VulkanTexture.h
|
||||
src/vulkan/VulkanUtility.cpp
|
||||
src/vulkan/VulkanUtility.h
|
||||
)
|
||||
if (LINUX OR WIN32)
|
||||
list(APPEND SRCS src/vulkan/platform/VulkanPlatformLinuxWindows.cpp)
|
||||
|
||||
@@ -1302,7 +1302,7 @@ enum class Workaround : uint16_t {
|
||||
// for some uniform arrays, it's needed to do an initialization to avoid crash on adreno gpu
|
||||
ADRENO_UNIFORM_ARRAY_CRASH,
|
||||
// Workaround a Metal pipeline compilation error with the message:
|
||||
// "Could not statically determine the target of a texture". See light_indirect.fs
|
||||
// "Could not statically determine the target of a texture". See surface_light_indirect.fs
|
||||
METAL_STATIC_TEXTURE_TARGET_ERROR,
|
||||
// Adreno drivers sometimes aren't able to blit into a layer of a texture array.
|
||||
DISABLE_BLIT_INTO_TEXTURE_ARRAY,
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Driver;
|
||||
@@ -41,6 +43,50 @@ public:
|
||||
struct Fence {};
|
||||
struct Stream {};
|
||||
|
||||
class ExternalImageHandle;
|
||||
|
||||
class ExternalImage {
|
||||
friend class ExternalImageHandle;
|
||||
std::atomic_uint32_t mRefCount{0};
|
||||
protected:
|
||||
virtual ~ExternalImage() noexcept;
|
||||
};
|
||||
|
||||
class ExternalImageHandle {
|
||||
ExternalImage* UTILS_NULLABLE mTarget = nullptr;
|
||||
static void incref(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
static void decref(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
|
||||
public:
|
||||
ExternalImageHandle() noexcept;
|
||||
~ExternalImageHandle() noexcept;
|
||||
explicit ExternalImageHandle(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
ExternalImageHandle(ExternalImageHandle const& rhs) noexcept;
|
||||
ExternalImageHandle(ExternalImageHandle&& rhs) noexcept;
|
||||
ExternalImageHandle& operator=(ExternalImageHandle const& rhs) noexcept;
|
||||
ExternalImageHandle& operator=(ExternalImageHandle&& rhs) noexcept;
|
||||
|
||||
explicit operator bool() const noexcept { return mTarget != nullptr; }
|
||||
|
||||
ExternalImage* UTILS_NULLABLE get() noexcept { return mTarget; }
|
||||
ExternalImage const* UTILS_NULLABLE get() const noexcept { return mTarget; }
|
||||
|
||||
ExternalImage* UTILS_NULLABLE operator->() noexcept { return mTarget; }
|
||||
ExternalImage const* UTILS_NULLABLE operator->() const noexcept { return mTarget; }
|
||||
|
||||
ExternalImage& operator*() noexcept { return *mTarget; }
|
||||
ExternalImage const& operator*() const noexcept { return *mTarget; }
|
||||
|
||||
void clear() noexcept;
|
||||
void reset(ExternalImage* UTILS_NULLABLE p) noexcept;
|
||||
|
||||
private:
|
||||
friend utils::io::ostream& operator<<(utils::io::ostream& out,
|
||||
ExternalImageHandle const& handle);
|
||||
};
|
||||
|
||||
using ExternalImageHandleRef = ExternalImageHandle const&;
|
||||
|
||||
/**
|
||||
* The type of technique for stereoscopic rendering. (Note that the materials used will need to
|
||||
* be compatible with the chosen technique.)
|
||||
@@ -123,7 +169,7 @@ public:
|
||||
*
|
||||
* @return nullptr on failure, or a pointer to the newly created driver.
|
||||
*/
|
||||
virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
|
||||
virtual Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
|
||||
const DriverConfig& driverConfig) noexcept = 0;
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/CString.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -51,12 +52,23 @@ protected:
|
||||
~OpenGLPlatform() noexcept override;
|
||||
|
||||
public:
|
||||
|
||||
struct ExternalTexture {
|
||||
unsigned int target; // GLenum target
|
||||
unsigned int id; // GLuint id
|
||||
unsigned int target; // GLenum target
|
||||
unsigned int id; // GLuint id
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the OpenGL vendor string of the specified Driver instance.
|
||||
* @return The GL_VENDOR string
|
||||
*/
|
||||
static utils::CString getVendorString(Driver const* UTILS_NONNULL driver);
|
||||
|
||||
/**
|
||||
* Return the OpenGL vendor string of the specified Driver instance
|
||||
* @return The GL_RENDERER string
|
||||
*/
|
||||
static utils::CString getRendererString(Driver const* UTILS_NONNULL driver);
|
||||
|
||||
/**
|
||||
* Called by the driver to destroy the OpenGL context. This should clean up any windows
|
||||
* or buffers from initialization. This is for instance where `eglDestroyContext` would be
|
||||
@@ -324,36 +336,45 @@ public:
|
||||
* Destroys an external texture handle and associated data.
|
||||
* @param texture a pointer to the handle to destroy.
|
||||
*/
|
||||
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
virtual void destroyExternalImageTexture(ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
// called on the application thread to allow Filament to take ownership of the image
|
||||
|
||||
/**
|
||||
* Takes ownership of the externalImage. The externalImage parameter depends on the Platform's
|
||||
* concrete implementation. Ownership is released when destroyExternalImage() is called.
|
||||
* concrete implementation. Ownership is released when destroyExternalImageTexture() is called.
|
||||
*
|
||||
* WARNING: This is called synchronously from the application thread (NOT the Driver thread)
|
||||
*
|
||||
* @param externalImage A token representing the platform's external image.
|
||||
* @see destroyExternalImage
|
||||
* @{
|
||||
*/
|
||||
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
|
||||
|
||||
virtual void retainExternalImage(ExternalImageHandleRef externalImage) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* Called to bind the platform-specific externalImage to an ExternalTexture.
|
||||
* ExternalTexture::id is guaranteed to be bound when this method is called and ExternalTexture
|
||||
* is updated with new values for id/target if necessary.
|
||||
*
|
||||
* WARNING: this method is not allowed to change the bound texture, or must restore the previous
|
||||
* binding upon return. This is to avoid problem with a backend doing state caching.
|
||||
* binding upon return. This is to avoid a problem with a backend doing state caching.
|
||||
*
|
||||
* @param externalImage The platform-specific external image.
|
||||
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
|
||||
* @return true on success, false on error.
|
||||
* @{
|
||||
*/
|
||||
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
|
||||
ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
|
||||
virtual bool setExternalImage(ExternalImageHandleRef externalImage,
|
||||
ExternalTexture* UTILS_NONNULL texture) noexcept;
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* The method allows platforms to convert a user-supplied external image object into a new type
|
||||
* (e.g. HardwareBuffer => EGLImage). The default implementation returns source.
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -34,12 +33,14 @@ public:
|
||||
PlatformCocoaGL();
|
||||
~PlatformCocoaGL() noexcept override;
|
||||
|
||||
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
|
||||
|
||||
protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
// Currently returns 0
|
||||
int getOSVersion() const noexcept override;
|
||||
@@ -59,10 +60,12 @@ protected:
|
||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
||||
void commit(SwapChain* swapChain) noexcept override;
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(void* externalImage) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
private:
|
||||
PlatformCocoaGLImpl* pImpl = nullptr;
|
||||
|
||||
@@ -32,11 +32,13 @@ public:
|
||||
PlatformCocoaTouchGL();
|
||||
~PlatformCocoaTouchGL() noexcept override;
|
||||
|
||||
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
int getOSVersion() const noexcept final { return 0; }
|
||||
|
||||
@@ -56,10 +58,12 @@ public:
|
||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
||||
void commit(SwapChain* swapChain) noexcept override;
|
||||
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(void* externalImage) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
private:
|
||||
PlatformCocoaTouchGLImpl* pImpl = nullptr;
|
||||
|
||||
@@ -47,6 +47,11 @@ public:
|
||||
// Return true if we're on an OpenGL platform (as opposed to OpenGL ES). false by default.
|
||||
virtual bool isOpenGL() const noexcept;
|
||||
|
||||
/**
|
||||
* Creates an ExternalImage from a EGLImageKHR
|
||||
*/
|
||||
ExternalImageHandle createExternalImage(EGLImageKHR eglImage) noexcept;
|
||||
|
||||
protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Helper for EGL configs and attributes parameters
|
||||
@@ -75,8 +80,7 @@ protected:
|
||||
* Initializes EGL, creates the OpenGL context and returns a concrete Driver implementation
|
||||
* that supports OpenGL/OpenGL ES.
|
||||
*/
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
Driver* createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
/**
|
||||
* This returns zero. This method can be overridden to return something more useful.
|
||||
@@ -118,9 +122,10 @@ protected:
|
||||
void destroyFence(Fence* fence) noexcept override;
|
||||
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
|
||||
|
||||
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImage(ExternalTexture* texture) noexcept override;
|
||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
/**
|
||||
* Logs glGetError() to slog.e
|
||||
@@ -188,6 +193,12 @@ protected:
|
||||
|
||||
void initializeGlExtensions() noexcept;
|
||||
|
||||
struct ExternalImageEGL : public ExternalImage {
|
||||
EGLImageKHR eglImage = EGL_NO_IMAGE;
|
||||
protected:
|
||||
~ExternalImageEGL() override;
|
||||
};
|
||||
|
||||
protected:
|
||||
EGLConfig findSwapChainConfig(uint64_t flags, bool window, bool pbuffer) const;
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@ protected:
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
|
||||
/**
|
||||
* Creates an ExternalImage from a EGLImageKHR
|
||||
*/
|
||||
ExternalImageHandle createExternalImage(AHardwareBuffer const *buffer, bool sRGB) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// OpenGLPlatform Interface
|
||||
|
||||
@@ -89,6 +94,15 @@ protected:
|
||||
*/
|
||||
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
|
||||
|
||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||
|
||||
struct ExternalImageEGLAndroid : public ExternalImageEGL {
|
||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||
bool sRGB = false;
|
||||
protected:
|
||||
~ExternalImageEGLAndroid() override;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool makeCurrent(ContextType type,
|
||||
SwapChain* drawSwapChain,
|
||||
|
||||
@@ -69,6 +69,16 @@ public:
|
||||
|
||||
virtual ShaderModel getShaderModel() const noexcept = 0;
|
||||
|
||||
// The shader language used for shaders for this driver, used to inform matdbg.
|
||||
//
|
||||
// For OpenGL, this distinguishes whether the driver's shaders are powered by ESSL1 or ESSL3.
|
||||
// This information is used by matdbg to display the correct shader code to the web UI and patch
|
||||
// the correct chunk when rebuilding shaders live.
|
||||
//
|
||||
// Metal shaders can either be MSL or Metal libraries, but at time of writing, matdbg can only
|
||||
// interface with MSL.
|
||||
virtual ShaderLanguage getShaderLanguage() const noexcept = 0;
|
||||
|
||||
// Returns the dispatcher. This is only called once during initialization of the CommandStream,
|
||||
// so it doesn't matter that it's virtual.
|
||||
virtual Dispatcher getDispatcher() const noexcept = 0;
|
||||
|
||||
@@ -126,8 +126,10 @@
|
||||
* Driver API below...
|
||||
*/
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
DECL_DRIVER_API_0(tick)
|
||||
|
||||
@@ -213,6 +215,14 @@ DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
|
||||
backend::TextureSwizzle, b,
|
||||
backend::TextureSwizzle, a)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage2,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
backend::TextureUsage, usage,
|
||||
backend::Platform::ExternalImageHandleRef, image)
|
||||
|
||||
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
|
||||
backend::SamplerType, target,
|
||||
backend::TextureFormat, format,
|
||||
@@ -353,6 +363,7 @@ 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_0(math::float2, getClipSpaceParams)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage2, backend::Platform::ExternalImageHandleRef, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::TimerQueryResult, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)
|
||||
@@ -533,7 +544,9 @@ DECL_DRIVER_API_N(scissor,
|
||||
Viewport, scissor)
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#undef EXPAND
|
||||
|
||||
|
||||
@@ -249,8 +249,8 @@ public:
|
||||
if (UTILS_LIKELY(isPoolHandle(id))) {
|
||||
// Truncate the age to get the debug tag
|
||||
key &= ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK);
|
||||
writeHandleTag(key, std::move(tag));
|
||||
}
|
||||
writeHandleTag(key, std::move(tag));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define TNT_FILAMENT_DRIVER_ANDROID_VIRTUAL_MACHINE_ENV_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Mutex.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
@@ -26,25 +26,17 @@ namespace filament {
|
||||
|
||||
class VirtualMachineEnv {
|
||||
public:
|
||||
// must be called before VirtualMachineEnv::get() from a thread that is attached to the JavaVM
|
||||
static jint JNI_OnLoad(JavaVM* vm) noexcept;
|
||||
|
||||
static VirtualMachineEnv& get() noexcept {
|
||||
// declaring this thread local, will ensure it's destroyed with the calling thread
|
||||
static thread_local VirtualMachineEnv instance;
|
||||
return instance;
|
||||
}
|
||||
// must be called on backend thread
|
||||
static VirtualMachineEnv& get() noexcept;
|
||||
|
||||
static JNIEnv* getThreadEnvironment() noexcept {
|
||||
JNIEnv* env;
|
||||
assert_invariant(sVirtualMachine);
|
||||
if (sVirtualMachine->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return nullptr; // this should not happen
|
||||
}
|
||||
return env;
|
||||
}
|
||||
// can be called from any thread that already has a JniEnv
|
||||
static JNIEnv* getThreadEnvironment() noexcept;
|
||||
|
||||
inline JNIEnv* getEnvironment() noexcept {
|
||||
assert_invariant(mVirtualMachine);
|
||||
// must be called from the backend thread
|
||||
JNIEnv* getEnvironment() noexcept {
|
||||
JNIEnv* env = mJniEnv;
|
||||
if (UTILS_UNLIKELY(!env)) {
|
||||
return getEnvironmentSlow();
|
||||
@@ -55,20 +47,14 @@ public:
|
||||
static void handleException(JNIEnv* env) noexcept;
|
||||
|
||||
private:
|
||||
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
|
||||
// We're not initializing the JVM here -- but we could -- because most of the time
|
||||
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
|
||||
// a nasty slow down the very first time, but we'll live with it for now.
|
||||
}
|
||||
|
||||
~VirtualMachineEnv() {
|
||||
if (mVirtualMachine) {
|
||||
mVirtualMachine->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
explicit VirtualMachineEnv(JavaVM* vm) noexcept;
|
||||
~VirtualMachineEnv() noexcept;
|
||||
JNIEnv* getEnvironmentSlow() noexcept;
|
||||
|
||||
static utils::Mutex sLock;
|
||||
static JavaVM* sVirtualMachine;
|
||||
static JavaVM* getVirtualMachine();
|
||||
|
||||
JNIEnv* mJniEnv = nullptr;
|
||||
JavaVM* mVirtualMachine = nullptr;
|
||||
};
|
||||
|
||||
@@ -16,8 +16,102 @@
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
void Platform::ExternalImageHandle::incref(ExternalImage* p) noexcept {
|
||||
if (p) {
|
||||
// incrementing the ref-count doesn't acquire or release anything
|
||||
p->mRefCount.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::decref(ExternalImage* p) noexcept {
|
||||
if (p) {
|
||||
// When decrementing the ref-count, unless it reaches zero, there is no need to acquire
|
||||
// data; we need to release all previous writes though so they can be visible to the thread
|
||||
// that will actually delete the object.
|
||||
if (p->mRefCount.fetch_sub(1, std::memory_order_release) == 1) {
|
||||
// if we reach zero, we're about to delete the object, we need to acquire all previous
|
||||
// writes from other threads (i.e.: the memory from other threads prior to the decref()
|
||||
// need to be visible now.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle() noexcept = default;
|
||||
|
||||
Platform::ExternalImageHandle::~ExternalImageHandle() noexcept {
|
||||
decref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImage* p) noexcept
|
||||
: mTarget(p) {
|
||||
incref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle const& rhs) noexcept
|
||||
: mTarget(rhs.mTarget) {
|
||||
incref(mTarget);
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle&& rhs) noexcept
|
||||
: mTarget(rhs.mTarget) {
|
||||
rhs.mTarget = nullptr;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(
|
||||
ExternalImageHandle const& rhs) noexcept {
|
||||
if (UTILS_LIKELY(this != &rhs)) {
|
||||
incref(rhs.mTarget);
|
||||
decref(mTarget);
|
||||
mTarget = rhs.mTarget;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(
|
||||
ExternalImageHandle&& rhs) noexcept {
|
||||
if (UTILS_LIKELY(this != &rhs)) {
|
||||
decref(mTarget);
|
||||
mTarget = rhs.mTarget;
|
||||
rhs.mTarget = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::clear() noexcept {
|
||||
decref(mTarget);
|
||||
mTarget = nullptr;
|
||||
}
|
||||
|
||||
void Platform::ExternalImageHandle::reset(ExternalImage* p) noexcept {
|
||||
incref(p);
|
||||
decref(mTarget);
|
||||
mTarget = p;
|
||||
}
|
||||
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out,
|
||||
Platform::ExternalImageHandle const& handle) {
|
||||
out << "ExternalImageHandle{" << handle.mTarget << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Platform::ExternalImage::~ExternalImage() noexcept = default;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Platform::Platform() noexcept = default;
|
||||
|
||||
// this generates the vtable in this translation unit
|
||||
|
||||
@@ -18,12 +18,28 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace filament {
|
||||
|
||||
JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
|
||||
using namespace utils;
|
||||
|
||||
// This Mutex shouldn't be subject to the Static Initialization Order Fiasco because its initial state is
|
||||
// a single int initialized to 0.
|
||||
/* static*/ Mutex VirtualMachineEnv::sLock;
|
||||
/* static*/ JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
|
||||
|
||||
UTILS_NOINLINE
|
||||
JavaVM* VirtualMachineEnv::getVirtualMachine() {
|
||||
std::lock_guard const lock(sLock);
|
||||
assert_invariant(sVirtualMachine);
|
||||
return sVirtualMachine;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is typically called by filament_jni.so when it is loaded. If filament_jni.so is not used,
|
||||
@@ -35,15 +51,75 @@ JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
|
||||
UTILS_PUBLIC
|
||||
UTILS_NOINLINE
|
||||
jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) noexcept {
|
||||
JNIEnv* env = nullptr;
|
||||
if (UTILS_UNLIKELY(vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)) {
|
||||
// this should not happen
|
||||
return -1;
|
||||
std::lock_guard const lock(sLock);
|
||||
if (sVirtualMachine) {
|
||||
// It doesn't make sense for JNI_OnLoad() to be called more than once
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
// Here we check this VM at least has JNI_VERSION_1_6
|
||||
JNIEnv* env = nullptr;
|
||||
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
|
||||
<< "Couldn't get JniEnv* from the VM, error = " << result;
|
||||
|
||||
sVirtualMachine = vm;
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
VirtualMachineEnv& VirtualMachineEnv::get() noexcept {
|
||||
JavaVM* const vm = getVirtualMachine();
|
||||
// declaring this thread local, will ensure it's destroyed with the calling thread
|
||||
thread_local VirtualMachineEnv instance{ vm };
|
||||
return instance;
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* VirtualMachineEnv::getThreadEnvironment() noexcept {
|
||||
JavaVM* const vm = getVirtualMachine();
|
||||
JNIEnv* env = nullptr;
|
||||
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
|
||||
<< "Couldn't get JniEnv* from the VM, error = " << result;
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
VirtualMachineEnv::VirtualMachineEnv(JavaVM* vm) noexcept : mVirtualMachine(vm) {
|
||||
// We're not initializing the JVM here -- but we could -- because most of the time
|
||||
// we don't need the jvm. Instead, we do the initialization on first use. This means we could get
|
||||
// a nasty slow down the very first time, but we'll live with it for now.
|
||||
}
|
||||
|
||||
VirtualMachineEnv::~VirtualMachineEnv() noexcept {
|
||||
if (mVirtualMachine) {
|
||||
mVirtualMachine->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mVirtualMachine)
|
||||
<< "JNI_OnLoad() has not been called";
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
jint const result = mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
|
||||
#else
|
||||
jint const result = mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
|
||||
#endif
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(result == JNI_OK)
|
||||
<< "JavaVM::AttachCurrentThread failed with error " << result;
|
||||
|
||||
FILAMENT_CHECK_POSTCONDITION(mJniEnv)
|
||||
<< "JavaVM::AttachCurrentThread returned a null mJniEnv";
|
||||
|
||||
return mJniEnv;
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
|
||||
if (UTILS_UNLIKELY(env->ExceptionCheck())) {
|
||||
@@ -52,16 +128,5 @@ void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
|
||||
#if defined(__ANDROID__)
|
||||
mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
|
||||
#else
|
||||
mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
|
||||
#endif
|
||||
assert_invariant(mJniEnv);
|
||||
return mJniEnv;
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ private:
|
||||
MetalContext* mContext;
|
||||
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
|
||||
// Overrides the default implementation by wrapping the call to fn in an @autoreleasepool block.
|
||||
void execute(std::function<void(void)> const& fn) noexcept final;
|
||||
|
||||
@@ -513,6 +513,14 @@ void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTextu
|
||||
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
@@ -747,6 +755,10 @@ Handle<HwTexture> MetalDriver::createTextureViewSwizzleS() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> MetalDriver::createTextureExternalImage2S() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> MetalDriver::createTextureExternalImageS() noexcept {
|
||||
return alloc_handle<MetalTexture>();
|
||||
}
|
||||
@@ -947,6 +959,10 @@ ShaderModel MetalDriver::getShaderModel() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
ShaderLanguage MetalDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::MSL;
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream) {
|
||||
return {};
|
||||
}
|
||||
@@ -1135,8 +1151,8 @@ FeatureLevel MetalDriver::getFeatureLevel() {
|
||||
|
||||
math::float2 MetalDriver::getClipSpaceParams() {
|
||||
// virtual and physical z-coordinate of clip-space is in [-w, 0]
|
||||
// Note: this is actually never used (see: main.vs), but it's a backend API so we implement it
|
||||
// properly.
|
||||
// Note: this is actually never used (see: surface_main.vs), but it's a backend API so we
|
||||
// implement it properly.
|
||||
return math::float2{ 1.0f, 0.0f };
|
||||
}
|
||||
|
||||
@@ -1214,6 +1230,10 @@ void MetalDriver::update3DImage(Handle<HwTexture> th, uint32_t level,
|
||||
th.getId(), level, xoffset, yoffset, zoffset, width, height, depth);
|
||||
}
|
||||
|
||||
void MetalDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
// FIXME: implement setupExternalImage2
|
||||
}
|
||||
|
||||
void MetalDriver::setupExternalImage(void* image) {
|
||||
// setupExternalImage is called on the Filament thread when creating a Texture or SwapChain from
|
||||
// a CVPixelBuffer external image. Here we take ownership of the passed in buffer by calling
|
||||
|
||||
@@ -14,9 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include "noop/NoopDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
Driver* NoopDriver::create() {
|
||||
@@ -39,6 +46,10 @@ ShaderModel NoopDriver::getShaderModel() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
ShaderLanguage NoopDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::ESSL3;
|
||||
}
|
||||
|
||||
// explicit instantiation of the Dispatcher
|
||||
template class ConcreteDispatcher<NoopDriver>;
|
||||
|
||||
@@ -258,6 +269,9 @@ void NoopDriver::update3DImage(Handle<HwTexture> th,
|
||||
scheduleDestroy(std::move(data));
|
||||
}
|
||||
|
||||
void NoopDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
}
|
||||
|
||||
void NoopDriver::setupExternalImage(void* image) {
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
|
||||
private:
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
|
||||
uint64_t nextFakeHandle = 1;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -25,6 +26,8 @@
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gl_headers.h"
|
||||
@@ -50,7 +53,7 @@ void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char*
|
||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
|
||||
#endif
|
||||
|
||||
constexpr inline GLuint getComponentCount(ElementType type) noexcept {
|
||||
constexpr GLuint getComponentCount(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
@@ -90,7 +93,7 @@ constexpr inline GLuint getComponentCount(ElementType type) noexcept {
|
||||
// Our enums to GLenum conversions
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
|
||||
constexpr GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
|
||||
GLbitfield mask = 0;
|
||||
if (any(flags & TargetBufferFlags::COLOR_ALL)) {
|
||||
mask |= (GLbitfield)GL_COLOR_BUFFER_BIT;
|
||||
@@ -104,7 +107,7 @@ constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexc
|
||||
return mask;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
constexpr GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
switch (usage) {
|
||||
case BufferUsage::STATIC:
|
||||
return GL_STATIC_DRAW;
|
||||
@@ -113,7 +116,7 @@ constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
|
||||
constexpr GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
|
||||
switch (bindingType) {
|
||||
case BufferObjectBinding::VERTEX:
|
||||
return GL_ARRAY_BUFFER;
|
||||
@@ -134,11 +137,11 @@ constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) no
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLboolean getNormalization(bool normalized) noexcept {
|
||||
constexpr GLboolean getNormalization(bool normalized) noexcept {
|
||||
return GLboolean(normalized ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getComponentType(ElementType type) noexcept {
|
||||
constexpr GLenum getComponentType(ElementType type) noexcept {
|
||||
using ElementType = ElementType;
|
||||
switch (type) {
|
||||
case ElementType::BYTE:
|
||||
@@ -183,12 +186,30 @@ constexpr inline GLenum getComponentType(ElementType type) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getCubemapTarget(uint16_t layer) noexcept {
|
||||
constexpr GLenum getTextureTargetNotExternal(SamplerType target) noexcept {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return GL_TEXTURE_2D;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return GL_TEXTURE_3D;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return GL_TEXTURE_2D_ARRAY;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return GL_TEXTURE_CUBE_MAP;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return GL_TEXTURE_CUBE_MAP_ARRAY;
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
// we should never be here
|
||||
return GL_TEXTURE_2D;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr GLenum getCubemapTarget(uint16_t layer) noexcept {
|
||||
assert_invariant(layer <= 5);
|
||||
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
constexpr GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
using SamplerWrapMode = SamplerWrapMode;
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
@@ -200,7 +221,7 @@ constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
constexpr GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
using SamplerMinFilter = SamplerMinFilter;
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
@@ -215,12 +236,12 @@ constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
|
||||
constexpr GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
|
||||
return GL_NEAREST + GLenum(filter);
|
||||
}
|
||||
|
||||
|
||||
constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
constexpr GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
using BlendEquation = BlendEquation;
|
||||
switch (mode) {
|
||||
case BlendEquation::ADD: return GL_FUNC_ADD;
|
||||
@@ -231,7 +252,7 @@ constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
constexpr GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
using BlendFunction = BlendFunction;
|
||||
switch (mode) {
|
||||
case BlendFunction::ZERO: return GL_ZERO;
|
||||
@@ -248,7 +269,7 @@ constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
switch (func) {
|
||||
case SamplerCompareFunc::LE: return GL_LEQUAL;
|
||||
case SamplerCompareFunc::GE: return GL_GEQUAL;
|
||||
@@ -262,25 +283,25 @@ constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
}
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
constexpr inline GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
|
||||
constexpr GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
|
||||
return mode == SamplerCompareMode::NONE ?
|
||||
GL_NONE : GL_COMPARE_REF_TO_TEXTURE;
|
||||
}
|
||||
|
||||
constexpr inline GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr inline GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
|
||||
constexpr GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
|
||||
return getCompareFunc(func);
|
||||
}
|
||||
|
||||
constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
constexpr GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
switch (op) {
|
||||
case StencilOperation::KEEP: return GL_KEEP;
|
||||
case StencilOperation::ZERO: return GL_ZERO;
|
||||
@@ -293,7 +314,7 @@ constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
constexpr GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
using PixelDataFormat = PixelDataFormat;
|
||||
switch (format) {
|
||||
case PixelDataFormat::RGB: return GL_RGB;
|
||||
@@ -317,7 +338,7 @@ constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline GLenum getType(PixelDataType type) noexcept {
|
||||
constexpr GLenum getType(PixelDataType type) noexcept {
|
||||
using PixelDataType = PixelDataType;
|
||||
switch (type) {
|
||||
case PixelDataType::UBYTE: return GL_UNSIGNED_BYTE;
|
||||
@@ -342,7 +363,7 @@ constexpr inline GLenum getType(PixelDataType type) noexcept {
|
||||
}
|
||||
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||
constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
constexpr GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
using TextureSwizzle = TextureSwizzle;
|
||||
switch (c) {
|
||||
case TextureSwizzle::SUBSTITUTE_ZERO: return GL_ZERO;
|
||||
@@ -355,7 +376,7 @@ constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
constexpr GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
switch (mode) {
|
||||
case CullingMode::NONE:
|
||||
// should never happen
|
||||
@@ -370,7 +391,7 @@ constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
|
||||
}
|
||||
|
||||
// ES2 supported internal formats for texturing and how they map to a format/type
|
||||
constexpr inline std::pair<GLenum, GLenum> textureFormatToFormatAndType(
|
||||
constexpr std::pair<GLenum, GLenum> textureFormatToFormatAndType(
|
||||
TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::R8: return { 0x1909 /*GL_LUMINANCE*/, GL_UNSIGNED_BYTE };
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <backend/Program.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include "private/backend/CommandStream.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/DriverApi.h"
|
||||
|
||||
@@ -46,9 +47,11 @@
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Slice.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
@@ -75,9 +78,11 @@
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
#endif
|
||||
|
||||
// We can only support this feature on OpenGL ES 3.1+
|
||||
// Support is currently disabled as we don't need it
|
||||
@@ -152,8 +157,8 @@ using namespace GLUtils;
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
UTILS_NOINLINE
|
||||
Driver* OpenGLDriver::create(OpenGLPlatform* const platform,
|
||||
void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* const platform,
|
||||
void* const /*sharedGLContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
assert_invariant(platform);
|
||||
OpenGLPlatform* const ec = platform;
|
||||
|
||||
@@ -220,7 +225,7 @@ Driver* OpenGLDriver::create(OpenGLPlatform* const platform,
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t const defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
|
||||
constexpr size_t defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
|
||||
Platform::DriverConfig validConfig{ driverConfig };
|
||||
validConfig.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize);
|
||||
OpenGLDriver* const driver = new(std::nothrow) OpenGLDriver(ec, validConfig);
|
||||
@@ -275,7 +280,6 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
|
||||
driverConfig.disableHandleUseAfterFreeCheck),
|
||||
mDriverConfig(driverConfig),
|
||||
mCurrentPushConstants(new(std::nothrow) PushConstantBundle{}) {
|
||||
|
||||
// set a reasonable default value for our stream array
|
||||
mTexturesWithStreamsAttached.reserve(8);
|
||||
mStreamsWithPendingAcquiredImage.reserve(8);
|
||||
@@ -349,6 +353,10 @@ ShaderModel OpenGLDriver::getShaderModel() const noexcept {
|
||||
return mContext.getShaderModel();
|
||||
}
|
||||
|
||||
ShaderLanguage OpenGLDriver::getShaderLanguage() const noexcept {
|
||||
return mContext.isES2() ? ShaderLanguage::ESSL1 : ShaderLanguage::ESSL3;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Change and track GL state
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -360,8 +368,8 @@ void OpenGLDriver::bindSampler(GLuint unit, GLuint sampler) noexcept {
|
||||
mContext.bindSampler(unit, sampler);
|
||||
}
|
||||
|
||||
void OpenGLDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
backend::PushConstantVariant value) {
|
||||
void OpenGLDriver::setPushConstant(ShaderStage stage, uint8_t index,
|
||||
PushConstantVariant value) {
|
||||
assert_invariant(stage == ShaderStage::VERTEX || stage == ShaderStage::FRAGMENT);
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
@@ -370,7 +378,7 @@ void OpenGLDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
}
|
||||
#endif
|
||||
|
||||
utils::Slice<std::pair<GLint, ConstantType>> constants;
|
||||
Slice<std::pair<GLint, ConstantType>> constants;
|
||||
if (stage == ShaderStage::VERTEX) {
|
||||
constants = mCurrentPushConstants->vertexConstants;
|
||||
} else if (stage == ShaderStage::FRAGMENT) {
|
||||
@@ -576,6 +584,10 @@ Handle<HwTexture> OpenGLDriver::createTextureViewSwizzleS() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> OpenGLDriver::createTextureExternalImage2S() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> OpenGLDriver::createTextureExternalImageS() noexcept {
|
||||
return initHandle<GLTexture>();
|
||||
}
|
||||
@@ -671,7 +683,7 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
|
||||
bo->gl.buffer = malloc(byteCount);
|
||||
memset(bo->gl.buffer, 0, byteCount);
|
||||
} else {
|
||||
bo->gl.binding = GLUtils::getBufferBindingType(bindingType);
|
||||
bo->gl.binding = getBufferBindingType(bindingType);
|
||||
glGenBuffers(1, &bo->gl.id);
|
||||
gl.bindBuffer(bo->gl.binding, bo->gl.id);
|
||||
glBufferData(bo->gl.binding, byteCount, nullptr, getBufferUsage(usage));
|
||||
@@ -748,7 +760,7 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void OpenGLDriver::textureStorage(OpenGLDriver::GLTexture* t,
|
||||
void OpenGLDriver::textureStorage(GLTexture* t,
|
||||
uint32_t width, uint32_t height, uint32_t depth, bool useProtectedMemory) noexcept {
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -884,6 +896,17 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
if (target == SamplerType::SAMPLER_EXTERNAL) {
|
||||
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
|
||||
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// revert to texture 2D if external is not supported; what else can we do?
|
||||
t->externalTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
} else {
|
||||
t->externalTexture->target = getTextureTargetNotExternal(target);
|
||||
}
|
||||
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
@@ -897,25 +920,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
|
||||
t->gl.internalFormat = internalFormat;
|
||||
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
// we can't be here -- doesn't matter what we do
|
||||
case SamplerType::SAMPLER_2D:
|
||||
t->gl.target = GL_TEXTURE_2D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
t->gl.target = GL_TEXTURE_3D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
t->gl.target = GL_TEXTURE_2D_ARRAY;
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
t->gl.target = GL_TEXTURE_CUBE_MAP;
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
t->gl.target = GL_TEXTURE_CUBE_MAP_ARRAY;
|
||||
break;
|
||||
}
|
||||
t->gl.target = getTextureTargetNotExternal(target);
|
||||
|
||||
if (t->samples > 1) {
|
||||
// Note: we can't be here in practice because filament's user API doesn't
|
||||
@@ -989,8 +994,7 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a) {
|
||||
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
|
||||
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
@@ -1052,6 +1056,57 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
usage &= ~TextureUsage::UPLOADABLE;
|
||||
|
||||
auto& gl = mContext;
|
||||
GLenum internalFormat = getInternalFormat(format);
|
||||
if (UTILS_UNLIKELY(gl.isES2())) {
|
||||
// on ES2, format and internal format must match
|
||||
// FIXME: handle compressed texture format
|
||||
internalFormat = textureFormatToFormatAndType(format).first;
|
||||
}
|
||||
assert_invariant(internalFormat);
|
||||
|
||||
GLTexture* const t = construct<GLTexture>(th, target, 1, 1, width, height, 1, format, usage);
|
||||
assert_invariant(t);
|
||||
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
if (target == SamplerType::SAMPLER_EXTERNAL) {
|
||||
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
|
||||
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// revert to texture 2D if external is not supported; what else can we do?
|
||||
t->externalTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
} else {
|
||||
t->externalTexture->target = getTextureTargetNotExternal(target);
|
||||
}
|
||||
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
// because it's not used anywhere for anything important.
|
||||
t->gl.internalFormat = internalFormat;
|
||||
t->gl.baseLevel = 0;
|
||||
t->gl.maxLevel = 0;
|
||||
t->gl.external = true; // forces bindTexture() call (they're never cached)
|
||||
}
|
||||
|
||||
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
|
||||
if (mPlatform.setExternalImage(image, t->externalTexture)) {
|
||||
// the target and id can be reset each time
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
|
||||
DEBUG_MARKER()
|
||||
@@ -1073,6 +1128,16 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
|
||||
|
||||
t->externalTexture = mPlatform.createExternalImageTexture();
|
||||
if (t->externalTexture) {
|
||||
if (target == SamplerType::SAMPLER_EXTERNAL) {
|
||||
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
|
||||
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// revert to texture 2D if external is not supported; what else can we do?
|
||||
t->externalTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
} else {
|
||||
t->externalTexture->target = getTextureTargetNotExternal(target);
|
||||
}
|
||||
t->gl.target = t->externalTexture->target;
|
||||
t->gl.id = t->externalTexture->id;
|
||||
// internalFormat actually depends on the external image, but it doesn't matter
|
||||
@@ -1092,7 +1157,7 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
void* image, uint32_t plane) {
|
||||
// not relevant for the OpenGL backend
|
||||
}
|
||||
@@ -1408,7 +1473,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
||||
&& ((gl.ext.EXT_multisampled_render_to_texture && attachment == GL_COLOR_ATTACHMENT0)
|
||||
|| gl.ext.EXT_multisampled_render_to_texture2)) {
|
||||
assert_invariant(rt->gl.samples > 1);
|
||||
// We have a multi-sample rendertarget and we have EXT_multisampled_render_to_texture,
|
||||
// We have a multi-sample rendertarget, and we have EXT_multisampled_render_to_texture,
|
||||
// so, we can directly use a 1-sample texture as attachment, multi-sample resolve,
|
||||
// will happen automagically and efficiently in the driver.
|
||||
// This extension only exists on OpenGL ES.
|
||||
@@ -1608,9 +1673,9 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
rt->gl.samples = samples;
|
||||
rt->targets = targets;
|
||||
|
||||
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmin = { std::numeric_limits<uint32_t>::max() };
|
||||
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmax = { 0 };
|
||||
auto checkDimensions = [&tmin, &tmax](GLTexture* t, uint8_t level) {
|
||||
UTILS_UNUSED_IN_RELEASE vec2<uint32_t> tmin = { std::numeric_limits<uint32_t>::max() };
|
||||
UTILS_UNUSED_IN_RELEASE vec2<uint32_t> tmax = { 0 };
|
||||
auto checkDimensions = [&tmin, &tmax](GLTexture const* t, uint8_t level) {
|
||||
const auto twidth = std::max(1u, t->width >> level);
|
||||
const auto theight = std::max(1u, t->height >> level);
|
||||
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
|
||||
@@ -1864,7 +1929,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
detachStream(t);
|
||||
}
|
||||
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
|
||||
mPlatform.destroyExternalImage(t->externalTexture);
|
||||
mPlatform.destroyExternalImageTexture(t->externalTexture);
|
||||
} else {
|
||||
glDeleteTextures(1, &t->gl.id);
|
||||
}
|
||||
@@ -2312,11 +2377,11 @@ bool OpenGLDriver::isStereoSupported() {
|
||||
return false;
|
||||
}
|
||||
switch (mDriverConfig.stereoscopicType) {
|
||||
case backend::StereoscopicType::INSTANCED:
|
||||
case StereoscopicType::INSTANCED:
|
||||
return mContext.ext.EXT_clip_cull_distance;
|
||||
case backend::StereoscopicType::MULTIVIEW:
|
||||
case StereoscopicType::MULTIVIEW:
|
||||
return mContext.ext.OVR_multiview2;
|
||||
case backend::StereoscopicType::NONE:
|
||||
case StereoscopicType::NONE:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2329,7 +2394,7 @@ bool OpenGLDriver::isDepthStencilResolveSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isDepthStencilBlitSupported(TextureFormat format) {
|
||||
bool OpenGLDriver::isDepthStencilBlitSupported(TextureFormat) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2363,12 +2428,12 @@ FeatureLevel OpenGLDriver::getFeatureLevel() {
|
||||
return mContext.getFeatureLevel();
|
||||
}
|
||||
|
||||
math::float2 OpenGLDriver::getClipSpaceParams() {
|
||||
float2 OpenGLDriver::getClipSpaceParams() {
|
||||
return mContext.ext.EXT_clip_control ?
|
||||
// z-coordinate of virtual and physical clip-space is in [-w, 0]
|
||||
math::float2{ 1.0f, 0.0f } :
|
||||
float2{ 1.0f, 0.0f } :
|
||||
// z-coordinate of virtual clip-space is in [-w,0], physical is in [-w, w]
|
||||
math::float2{ 2.0f, -1.0f };
|
||||
float2{ 2.0f, -1.0f };
|
||||
}
|
||||
|
||||
uint8_t OpenGLDriver::getMaxDrawBuffers() {
|
||||
@@ -2432,7 +2497,7 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
|
||||
// Updating driver objects
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
|
||||
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, CString tag) {
|
||||
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
|
||||
}
|
||||
|
||||
@@ -2608,7 +2673,7 @@ void OpenGLDriver::generateMipmaps(Handle<HwTexture> th) {
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
|
||||
void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& p) {
|
||||
@@ -2717,7 +2782,7 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::setCompressedTextureData(GLTexture* t, uint32_t level,
|
||||
void OpenGLDriver::setCompressedTextureData(GLTexture const* t, uint32_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& p) {
|
||||
@@ -2803,6 +2868,10 @@ void OpenGLDriver::setCompressedTextureData(GLTexture* t, uint32_t level,
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
mPlatform.retainExternalImage(image);
|
||||
}
|
||||
|
||||
void OpenGLDriver::setupExternalImage(void* image) {
|
||||
mPlatform.retainExternalImage(image);
|
||||
}
|
||||
@@ -3354,8 +3423,8 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::readBufferSubData(backend::BufferObjectHandle boh,
|
||||
uint32_t offset, uint32_t size, backend::BufferDescriptor&& p) {
|
||||
void OpenGLDriver::readBufferSubData(BufferObjectHandle boh,
|
||||
uint32_t offset, uint32_t size, BufferDescriptor&& p) {
|
||||
UTILS_UNUSED_IN_RELEASE auto& gl = mContext;
|
||||
assert_invariant(!gl.isES2());
|
||||
|
||||
@@ -3502,13 +3571,13 @@ void OpenGLDriver::beginFrame(
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
|
||||
FrameScheduledCallback&& callback, uint64_t flags) {
|
||||
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain>, CallbackHandler*,
|
||||
FrameScheduledCallback&& /*callback*/, uint64_t /*flags*/) {
|
||||
DEBUG_MARKER()
|
||||
}
|
||||
|
||||
void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
|
||||
CallbackHandler* handler, utils::Invocable<void(void)>&& callback) {
|
||||
void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain>,
|
||||
CallbackHandler*, Invocable<void()>&& /*callback*/) {
|
||||
DEBUG_MARKER()
|
||||
}
|
||||
|
||||
@@ -3539,9 +3608,9 @@ void OpenGLDriver::endFrame(UTILS_UNUSED uint32_t frameId) {
|
||||
}
|
||||
|
||||
void OpenGLDriver::updateDescriptorSetBuffer(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_binding_t binding,
|
||||
backend::BufferObjectHandle boh,
|
||||
DescriptorSetHandle dsh,
|
||||
descriptor_binding_t binding,
|
||||
BufferObjectHandle boh,
|
||||
uint32_t offset, uint32_t size) {
|
||||
GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh);
|
||||
GLBufferObject* bo = boh ? handle_cast<GLBufferObject*>(boh) : nullptr;
|
||||
@@ -3549,9 +3618,9 @@ void OpenGLDriver::updateDescriptorSetBuffer(
|
||||
}
|
||||
|
||||
void OpenGLDriver::updateDescriptorSetTexture(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_binding_t binding,
|
||||
backend::TextureHandle th,
|
||||
DescriptorSetHandle dsh,
|
||||
descriptor_binding_t binding,
|
||||
TextureHandle th,
|
||||
SamplerParams params) {
|
||||
GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh);
|
||||
GLTexture* t = th ? handle_cast<GLTexture*>(th) : nullptr;
|
||||
@@ -3584,7 +3653,7 @@ void OpenGLDriver::finish(int) {
|
||||
|
||||
UTILS_NOINLINE
|
||||
void OpenGLDriver::clearWithRasterPipe(TargetBufferFlags clearFlags,
|
||||
math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept {
|
||||
float4 const& linearColor, GLfloat depth, GLint stencil) noexcept {
|
||||
|
||||
if (any(clearFlags & TargetBufferFlags::COLOR_ALL)) {
|
||||
mContext.colorMask(GL_TRUE);
|
||||
@@ -3907,9 +3976,9 @@ void OpenGLDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
}
|
||||
|
||||
void OpenGLDriver::bindDescriptorSet(
|
||||
backend::DescriptorSetHandle dsh,
|
||||
backend::descriptor_set_t set,
|
||||
backend::DescriptorSetOffsetArray&& offsets) {
|
||||
DescriptorSetHandle dsh,
|
||||
descriptor_set_t set,
|
||||
DescriptorSetOffsetArray&& offsets) {
|
||||
|
||||
if (UTILS_UNLIKELY(!dsh)) {
|
||||
mBoundDescriptorSets[set].dsh = dsh;
|
||||
@@ -3941,7 +4010,7 @@ void OpenGLDriver::bindDescriptorSet(
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::updateDescriptors(utils::bitset8 invalidDescriptorSets) noexcept {
|
||||
void OpenGLDriver::updateDescriptors(bitset8 invalidDescriptorSets) noexcept {
|
||||
assert_invariant(mBoundProgram);
|
||||
auto const offsetOnly = mInvalidDescriptorSetBindingOffsets & ~mInvalidDescriptorSetBindings;
|
||||
invalidDescriptorSets.forEachSetBit([this, offsetOnly,
|
||||
@@ -4053,7 +4122,7 @@ void OpenGLDriver::draw(PipelineState state, Handle<HwRenderPrimitive> rph,
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGroupCount) {
|
||||
void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, uint3 workGroupCount) {
|
||||
DEBUG_MARKER()
|
||||
getShaderCompilerService().tick();
|
||||
|
||||
@@ -4090,4 +4159,6 @@ template class ConcreteDispatcher<OpenGLDriver>;
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include "OpenGLContext.h"
|
||||
#include "OpenGLDriverBase.h"
|
||||
#include "OpenGLTimerQuery.h"
|
||||
#include "GLBufferObject.h"
|
||||
#include "GLDescriptorSet.h"
|
||||
@@ -26,11 +27,10 @@
|
||||
#include "GLTexture.h"
|
||||
#include "ShaderCompilerService.h"
|
||||
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/Platform.h>
|
||||
#include <backend/Program.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
@@ -74,14 +75,14 @@ class OpenGLProgram;
|
||||
class TimerQueryFactoryInterface;
|
||||
struct PushConstantBundle;
|
||||
|
||||
class OpenGLDriver final : public DriverBase {
|
||||
class OpenGLDriver final : public OpenGLDriverBase {
|
||||
inline explicit OpenGLDriver(OpenGLPlatform* platform,
|
||||
const Platform::DriverConfig& driverConfig) noexcept;
|
||||
~OpenGLDriver() noexcept final;
|
||||
Dispatcher getDispatcher() const noexcept final;
|
||||
~OpenGLDriver() noexcept override;
|
||||
Dispatcher getDispatcher() const noexcept override;
|
||||
|
||||
public:
|
||||
static Driver* create(OpenGLPlatform* platform, void* sharedGLContext,
|
||||
static OpenGLDriver* create(OpenGLPlatform* platform, void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept;
|
||||
|
||||
class DebugMarker {
|
||||
@@ -184,7 +185,7 @@ public:
|
||||
std::condition_variable cond;
|
||||
FenceStatus status{ FenceStatus::TIMEOUT_EXPIRED };
|
||||
};
|
||||
std::shared_ptr<State> state{ std::make_shared<GLFence::State>() };
|
||||
std::shared_ptr<State> state{ std::make_shared<State>() };
|
||||
};
|
||||
|
||||
OpenGLDriver(OpenGLDriver const&) = delete;
|
||||
@@ -203,12 +204,21 @@ private:
|
||||
return mShaderCompilerService;
|
||||
}
|
||||
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderModel getShaderModel() const noexcept override;
|
||||
ShaderLanguage getShaderLanguage() const noexcept override;
|
||||
|
||||
/*
|
||||
* Driver interface
|
||||
* OpenGLDriver interface
|
||||
*/
|
||||
|
||||
utils::CString getVendorString() const noexcept override {
|
||||
return utils::CString{ mContext.state.vendor };
|
||||
}
|
||||
|
||||
utils::CString getRendererString() const noexcept override {
|
||||
return utils::CString{ mContext.state.renderer };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
friend class ConcreteDispatcher;
|
||||
|
||||
@@ -235,21 +245,21 @@ private:
|
||||
}
|
||||
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
typename std::enable_if<std::is_base_of<B, D>::value, D>::type*
|
||||
std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
construct(Handle<B> const& handle, ARGS&& ... args) {
|
||||
return mHandleAllocator.destroyAndConstruct<D, B>(handle, std::forward<ARGS>(args) ...);
|
||||
}
|
||||
|
||||
template<typename B, typename D,
|
||||
typename = typename std::enable_if<std::is_base_of<B, D>::value, D>::type>
|
||||
typename = std::enable_if_t<std::is_base_of_v<B, D>, D>>
|
||||
void destruct(Handle<B>& handle, D const* p) noexcept {
|
||||
return mHandleAllocator.deallocate(handle, p);
|
||||
}
|
||||
|
||||
template<typename Dp, typename B>
|
||||
typename std::enable_if_t<
|
||||
std::enable_if_t<
|
||||
std::is_pointer_v<Dp> &&
|
||||
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
|
||||
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp>
|
||||
handle_cast(Handle<B>& handle) {
|
||||
return mHandleAllocator.handle_cast<Dp, B>(handle);
|
||||
}
|
||||
@@ -260,9 +270,9 @@ private:
|
||||
}
|
||||
|
||||
template<typename Dp, typename B>
|
||||
inline typename std::enable_if_t<
|
||||
std::enable_if_t<
|
||||
std::is_pointer_v<Dp> &&
|
||||
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
|
||||
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp>
|
||||
handle_cast(Handle<B> const& handle) {
|
||||
return mHandleAllocator.handle_cast<Dp, B>(handle);
|
||||
}
|
||||
@@ -287,13 +297,13 @@ private:
|
||||
|
||||
void setStencilState(StencilState ss) noexcept;
|
||||
|
||||
void setTextureData(GLTexture* t,
|
||||
void setTextureData(GLTexture const* t,
|
||||
uint32_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
PixelBufferDescriptor&& p);
|
||||
|
||||
void setCompressedTextureData(GLTexture* t,
|
||||
void setCompressedTextureData(GLTexture const* t,
|
||||
uint32_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
@@ -302,7 +312,7 @@ private:
|
||||
void renderBufferStorage(GLuint rbo, GLenum internalformat, uint32_t width,
|
||||
uint32_t height, uint8_t samples) const noexcept;
|
||||
|
||||
void textureStorage(OpenGLDriver::GLTexture* t, uint32_t width, uint32_t height,
|
||||
void textureStorage(GLTexture* t, uint32_t width, uint32_t height,
|
||||
uint32_t depth, bool useProtectedMemory) noexcept;
|
||||
|
||||
/* State tracking GL wrappers... */
|
||||
@@ -334,9 +344,9 @@ private:
|
||||
void updateDescriptors(utils::bitset8 invalidDescriptorSets) noexcept;
|
||||
|
||||
struct {
|
||||
backend::DescriptorSetHandle dsh;
|
||||
DescriptorSetHandle dsh;
|
||||
std::array<uint32_t, CONFIG_UNIFORM_BINDING_COUNT> offsets;
|
||||
} mBoundDescriptorSets[MAX_DESCRIPTOR_SET_COUNT];
|
||||
} mBoundDescriptorSets[MAX_DESCRIPTOR_SET_COUNT] = {};
|
||||
|
||||
void clearWithRasterPipe(TargetBufferFlags clearFlags,
|
||||
math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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_OPENGL_OPENGLDRIVERBASE_H
|
||||
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGLDRIVERBASE_H
|
||||
|
||||
#include "DriverBase.h"
|
||||
|
||||
#include <utils/CString.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class OpenGLDriverBase : public DriverBase {
|
||||
protected:
|
||||
~OpenGLDriverBase() override;
|
||||
|
||||
public:
|
||||
virtual utils::CString getVendorString() const noexcept = 0;
|
||||
virtual utils::CString getRendererString() const noexcept = 0;
|
||||
};
|
||||
|
||||
} // filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_OPENGL_OPENGLDRIVERBASE_H
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <backend/platforms/OpenGLPlatform.h>
|
||||
|
||||
#include "OpenGLDriverBase.h"
|
||||
#include "OpenGLDriverFactory.h"
|
||||
|
||||
#include <backend/AcquiredImage.h>
|
||||
@@ -23,21 +24,45 @@
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "OpenGLDriver.h"
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
OpenGLDriverBase::~OpenGLDriverBase() = default;
|
||||
|
||||
Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform,
|
||||
void* sharedContext, const Platform::DriverConfig& driverConfig) {
|
||||
void* sharedContext, const DriverConfig& driverConfig) {
|
||||
return OpenGLDriverFactory::create(platform, sharedContext, driverConfig);
|
||||
}
|
||||
|
||||
OpenGLPlatform::~OpenGLPlatform() noexcept = default;
|
||||
|
||||
utils::CString OpenGLPlatform::getVendorString(Driver const* driver) {
|
||||
auto const p = static_cast<OpenGLDriverBase const*>(driver);
|
||||
#if UTILS_HAS_RTTI
|
||||
FILAMENT_CHECK_POSTCONDITION(dynamic_cast<OpenGLDriverBase const*>(driver))
|
||||
<< "Driver* has not been allocated with OpenGLPlatform";
|
||||
#endif
|
||||
return p->getVendorString();
|
||||
}
|
||||
|
||||
utils::CString OpenGLPlatform::getRendererString(Driver const* driver) {
|
||||
auto const p = static_cast<OpenGLDriverBase const*>(driver);
|
||||
#if UTILS_HAS_RTTI
|
||||
FILAMENT_CHECK_POSTCONDITION(dynamic_cast<OpenGLDriverBase const*>(driver))
|
||||
<< "Driver* has not been allocated with OpenGLPlatform";
|
||||
#endif
|
||||
return p->getRendererString();
|
||||
}
|
||||
|
||||
void OpenGLPlatform::makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
|
||||
utils::Invocable<void()>, utils::Invocable<void(size_t)>) noexcept {
|
||||
makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain);
|
||||
@@ -121,14 +146,24 @@ OpenGLPlatform::ExternalTexture* OpenGLPlatform::createExternalImageTexture() no
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OpenGLPlatform::destroyExternalImage(
|
||||
void OpenGLPlatform::destroyExternalImageTexture(
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
}
|
||||
|
||||
void OpenGLPlatform::retainExternalImage(
|
||||
UTILS_UNUSED ExternalImageHandleRef externalImage) noexcept {
|
||||
}
|
||||
|
||||
void OpenGLPlatform::retainExternalImage(
|
||||
UTILS_UNUSED void* externalImage) noexcept {
|
||||
}
|
||||
|
||||
bool OpenGLPlatform::setExternalImage(
|
||||
UTILS_UNUSED ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenGLPlatform::setExternalImage(
|
||||
UTILS_UNUSED void* externalImage,
|
||||
UTILS_UNUSED ExternalTexture* texture) noexcept {
|
||||
|
||||
@@ -16,13 +16,28 @@
|
||||
|
||||
#include "ExternalStreamManagerAndroid.h"
|
||||
|
||||
#include <utils/api_level.h>
|
||||
#include <private/backend/VirtualMachineEnv.h>
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#if __has_include(<android/surface_texture.h>)
|
||||
# include <android/surface_texture.h>
|
||||
# include <android/surface_texture_jni.h>
|
||||
#else
|
||||
struct ASurfaceTexture;
|
||||
typedef struct ASurfaceTexture ASurfaceTexture;
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
#include <jni.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
using namespace utils;
|
||||
|
||||
@@ -32,13 +47,8 @@ using namespace backend;
|
||||
using Stream = Platform::Stream;
|
||||
|
||||
|
||||
template <typename T>
|
||||
static void loadSymbol(T*& pfn, const char *symbol) noexcept {
|
||||
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
|
||||
}
|
||||
|
||||
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::create() noexcept {
|
||||
return *(new ExternalStreamManagerAndroid{});
|
||||
return *(new(std::nothrow) ExternalStreamManagerAndroid{});
|
||||
}
|
||||
|
||||
void ExternalStreamManagerAndroid::destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept {
|
||||
@@ -56,23 +66,13 @@ ExternalStreamManagerAndroid::~ExternalStreamManagerAndroid() noexcept = default
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept {
|
||||
JNIEnv * env = mVm.getEnvironment();
|
||||
JNIEnv* const env = mVm.getEnvironment();
|
||||
mJniEnv = env;
|
||||
|
||||
jclass SurfaceTextureClass = env->FindClass("android/graphics/SurfaceTexture");
|
||||
|
||||
mSurfaceTextureClass_updateTexImage = env->GetMethodID(
|
||||
SurfaceTextureClass, "updateTexImage", "()V");
|
||||
|
||||
mSurfaceTextureClass_attachToGLContext = env->GetMethodID(
|
||||
SurfaceTextureClass, "attachToGLContext", "(I)V");
|
||||
|
||||
mSurfaceTextureClass_detachFromGLContext = env->GetMethodID(
|
||||
SurfaceTextureClass, "detachFromGLContext", "()V");
|
||||
|
||||
mSurfaceTextureClass_getTimestamp = env->GetMethodID(
|
||||
SurfaceTextureClass, "getTimestamp", "()J");
|
||||
|
||||
mSurfaceTextureClass_updateTexImage = env->GetMethodID(SurfaceTextureClass, "updateTexImage", "()V");
|
||||
mSurfaceTextureClass_attachToGLContext = env->GetMethodID(SurfaceTextureClass, "attachToGLContext", "(I)V");
|
||||
mSurfaceTextureClass_detachFromGLContext = env->GetMethodID(SurfaceTextureClass, "detachFromGLContext", "()V");
|
||||
mSurfaceTextureClass_getTimestamp = env->GetMethodID(SurfaceTextureClass, "getTimestamp", "()J");
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ Stream* ExternalStreamManagerAndroid::acquire(jobject surfaceTexture) noexcept {
|
||||
if (!env) {
|
||||
return nullptr; // this should not happen
|
||||
}
|
||||
EGLStream* stream = new EGLStream();
|
||||
EGLStream* stream = new(std::nothrow) EGLStream();
|
||||
stream->jSurfaceTexture = env->NewGlobalRef(surfaceTexture);
|
||||
if (__builtin_available(android 28, *)) {
|
||||
stream->nSurfaceTexture = ASurfaceTexture_fromSurfaceTexture(env, surfaceTexture);
|
||||
@@ -91,29 +91,30 @@ Stream* ExternalStreamManagerAndroid::acquire(jobject surfaceTexture) noexcept {
|
||||
}
|
||||
|
||||
void ExternalStreamManagerAndroid::release(Stream* handle) noexcept {
|
||||
EGLStream* stream = static_cast<EGLStream*>(handle);
|
||||
EGLStream const* stream = static_cast<EGLStream*>(handle);
|
||||
if (__builtin_available(android 28, *)) {
|
||||
ASurfaceTexture_release(stream->nSurfaceTexture);
|
||||
}
|
||||
JNIEnv* const env = getEnvironment();
|
||||
// use VirtualMachineEnv::getEnvironment() directly because we don't need to cache JNI methods here
|
||||
JNIEnv* const env = mVm.getEnvironment();
|
||||
assert_invariant(env); // we should have called attach() by now
|
||||
env->DeleteGlobalRef(stream->jSurfaceTexture);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void ExternalStreamManagerAndroid::attach(Stream* handle, intptr_t tname) noexcept {
|
||||
EGLStream* stream = static_cast<EGLStream*>(handle);
|
||||
EGLStream const* stream = static_cast<EGLStream*>(handle);
|
||||
if (__builtin_available(android 28, *)) {
|
||||
// associate our GL texture to the SurfaceTexture
|
||||
ASurfaceTexture* const aSurfaceTexture = stream->nSurfaceTexture;
|
||||
if (UTILS_UNLIKELY(ASurfaceTexture_attachToGLContext(aSurfaceTexture, (uint32_t)tname))) {
|
||||
if (UTILS_UNLIKELY(ASurfaceTexture_attachToGLContext(aSurfaceTexture, uint32_t(tname)))) {
|
||||
// Unfortunately, before API 26 SurfaceTexture was always created in attached mode,
|
||||
// so attachToGLContext can fail. We consider this the unlikely case, because
|
||||
// this is how it should work.
|
||||
// So now we have to detach the surfacetexture from its texture
|
||||
ASurfaceTexture_detachFromGLContext(aSurfaceTexture);
|
||||
// and finally, try attaching again
|
||||
ASurfaceTexture_attachToGLContext(aSurfaceTexture, (uint32_t)tname);
|
||||
ASurfaceTexture_attachToGLContext(aSurfaceTexture, uint32_t(tname));
|
||||
}
|
||||
} else {
|
||||
JNIEnv* const env = getEnvironment();
|
||||
@@ -121,19 +122,19 @@ void ExternalStreamManagerAndroid::attach(Stream* handle, intptr_t tname) noexce
|
||||
|
||||
// associate our GL texture to the SurfaceTexture
|
||||
jobject jSurfaceTexture = stream->jSurfaceTexture;
|
||||
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, (jint)tname);
|
||||
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, jint(tname));
|
||||
if (UTILS_UNLIKELY(env->ExceptionCheck())) {
|
||||
// Unfortunately, before API 26 SurfaceTexture was always created in attached mode,
|
||||
// so attachToGLContext can fail. We consider this the unlikely case, because
|
||||
// this is how it should work.
|
||||
env->ExceptionClear();
|
||||
|
||||
// so now we have to detach the surfacetexture from its texture
|
||||
// so now we have to detach the SurfaceTexture from its texture
|
||||
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_detachFromGLContext);
|
||||
VirtualMachineEnv::handleException(env);
|
||||
|
||||
// and finally, try attaching again
|
||||
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, (jint)tname);
|
||||
env->CallVoidMethod(jSurfaceTexture, mSurfaceTextureClass_attachToGLContext, jint(tname));
|
||||
VirtualMachineEnv::handleException(env);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +145,7 @@ void ExternalStreamManagerAndroid::detach(Stream* handle) noexcept {
|
||||
if (__builtin_available(android 28, *)) {
|
||||
ASurfaceTexture_detachFromGLContext(stream->nSurfaceTexture);
|
||||
} else {
|
||||
JNIEnv* const env = mVm.getEnvironment();
|
||||
JNIEnv* const env = getEnvironment();
|
||||
assert_invariant(env); // we should have called attach() by now
|
||||
env->CallVoidMethod(stream->jSurfaceTexture, mSurfaceTextureClass_detachFromGLContext);
|
||||
VirtualMachineEnv::handleException(env);
|
||||
@@ -152,12 +153,12 @@ void ExternalStreamManagerAndroid::detach(Stream* handle) noexcept {
|
||||
}
|
||||
|
||||
void ExternalStreamManagerAndroid::updateTexImage(Stream* handle, int64_t* timestamp) noexcept {
|
||||
EGLStream* stream = static_cast<EGLStream*>(handle);
|
||||
EGLStream const* stream = static_cast<EGLStream*>(handle);
|
||||
if (__builtin_available(android 28, *)) {
|
||||
ASurfaceTexture_updateTexImage(stream->nSurfaceTexture);
|
||||
*timestamp = ASurfaceTexture_getTimestamp(stream->nSurfaceTexture);
|
||||
} else {
|
||||
JNIEnv* const env = mVm.getEnvironment();
|
||||
JNIEnv* const env = getEnvironment();
|
||||
assert_invariant(env); // we should have called attach() by now
|
||||
env->CallVoidMethod(stream->jSurfaceTexture, mSurfaceTextureClass_updateTexImage);
|
||||
VirtualMachineEnv::handleException(env);
|
||||
|
||||
@@ -21,14 +21,19 @@
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#if __has_include(<android/surface_texture.h>)
|
||||
# include <android/surface_texture.h>
|
||||
# include <android/surface_texture_jni.h>
|
||||
#else
|
||||
struct ASurfaceTexture;
|
||||
typedef struct ASurfaceTexture ASurfaceTexture;
|
||||
#endif
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/*
|
||||
@@ -70,7 +75,8 @@ private:
|
||||
ASurfaceTexture* nSurfaceTexture = nullptr;
|
||||
};
|
||||
|
||||
inline JNIEnv* getEnvironment() noexcept {
|
||||
// Must only be called from the backend thread
|
||||
JNIEnv* getEnvironment() noexcept {
|
||||
JNIEnv* env = mJniEnv;
|
||||
if (UTILS_UNLIKELY(!env)) {
|
||||
return getEnvironmentSlow();
|
||||
@@ -85,7 +91,6 @@ private:
|
||||
jmethodID mSurfaceTextureClass_attachToGLContext{};
|
||||
jmethodID mSurfaceTextureClass_detachFromGLContext{};
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif //TNT_FILAMENT_BACKEND_OPENGL_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
|
||||
|
||||
@@ -54,8 +54,15 @@ struct PlatformCocoaGLImpl {
|
||||
CVOpenGLTextureCacheRef mTextureCache = nullptr;
|
||||
std::unique_ptr<CocoaExternalImage::SharedGl> mExternalImageSharedGl;
|
||||
void updateOpenGLContext(NSView *nsView, bool resetView, bool clearView);
|
||||
struct ExternalImageCocoaGL : public Platform::ExternalImage {
|
||||
CVPixelBufferRef cvBuffer;
|
||||
protected:
|
||||
~ExternalImageCocoaGL() noexcept final;
|
||||
};
|
||||
};
|
||||
|
||||
PlatformCocoaGLImpl::ExternalImageCocoaGL::~ExternalImageCocoaGL() noexcept = default;
|
||||
|
||||
CocoaGLSwapChain::CocoaGLSwapChain( NSView* inView )
|
||||
: view(inView)
|
||||
, previousBounds(NSZeroRect)
|
||||
@@ -309,17 +316,12 @@ OpenGLPlatform::ExternalTexture* PlatformCocoaGL::createExternalImageTexture() n
|
||||
if (!pImpl->mExternalImageSharedGl) {
|
||||
pImpl->mExternalImageSharedGl = std::make_unique<CocoaExternalImage::SharedGl>();
|
||||
}
|
||||
|
||||
ExternalTexture* outTexture = new CocoaExternalImage(pImpl->mTextureCache,
|
||||
*pImpl->mExternalImageSharedGl);
|
||||
|
||||
// the actual id/target will be set in setExternalImage.
|
||||
outTexture->id = 0;
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformCocoaGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformCocoaGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
auto* p = static_cast<CocoaExternalImage*>(texture);
|
||||
delete p;
|
||||
}
|
||||
@@ -344,6 +346,36 @@ bool PlatformCocoaGL::setExternalImage(void* externalImage, ExternalTexture* tex
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformCocoaGL::createExternalImage(void* cvPixelBuffer) noexcept {
|
||||
auto* p = new(std::nothrow) PlatformCocoaGLImpl::ExternalImageCocoaGL;
|
||||
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
void PlatformCocoaGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
|
||||
auto const* const cocoaGlExternalImage
|
||||
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
|
||||
// Take ownership of the passed in buffer. It will be released the next time
|
||||
// setExternalImage is called, or when the texture is destroyed.
|
||||
CVPixelBufferRef pixelBuffer = cocoaGlExternalImage->cvBuffer;
|
||||
CVPixelBufferRetain(pixelBuffer);
|
||||
}
|
||||
|
||||
bool PlatformCocoaGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
|
||||
auto const* const cocoaGlExternalImage
|
||||
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
|
||||
CVPixelBufferRef cvPixelBuffer = cocoaGlExternalImage->cvBuffer;
|
||||
CocoaExternalImage* cocoaExternalImage = static_cast<CocoaExternalImage*>(texture);
|
||||
if (!cocoaExternalImage->set(cvPixelBuffer)) {
|
||||
return false;
|
||||
}
|
||||
texture->target = cocoaExternalImage->getTarget();
|
||||
texture->id = cocoaExternalImage->getGlTexture();
|
||||
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
|
||||
// cocoaExternalImage->getInternalFormat();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlatformCocoaGLImpl::updateOpenGLContext(NSView *nsView, bool resetView,
|
||||
bool clearView) {
|
||||
NSOpenGLContext* glContext = mGLContext;
|
||||
|
||||
@@ -47,8 +47,15 @@ struct PlatformCocoaTouchGLImpl {
|
||||
GLuint mDefaultDepthbuffer = 0;
|
||||
CVOpenGLESTextureCacheRef mTextureCache = nullptr;
|
||||
CocoaTouchExternalImage::SharedGl* mExternalImageSharedGl = nullptr;
|
||||
struct ExternalImageCocoaTouchGL : public Platform::ExternalImage {
|
||||
CVPixelBufferRef cvBuffer;
|
||||
protected:
|
||||
~ExternalImageCocoaTouchGL() noexcept final;
|
||||
};
|
||||
};
|
||||
|
||||
PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL::~ExternalImageCocoaTouchGL() noexcept = default;
|
||||
|
||||
PlatformCocoaTouchGL::PlatformCocoaTouchGL()
|
||||
: pImpl(new PlatformCocoaTouchGLImpl) {
|
||||
}
|
||||
@@ -198,13 +205,10 @@ void PlatformCocoaTouchGL::commit(Platform::SwapChain* swapChain) noexcept {
|
||||
OpenGLPlatform::ExternalTexture* PlatformCocoaTouchGL::createExternalImageTexture() noexcept {
|
||||
ExternalTexture* outTexture = new CocoaTouchExternalImage(pImpl->mTextureCache,
|
||||
*pImpl->mExternalImageSharedGl);
|
||||
// the actual id/target will be set in setExternalImage*(
|
||||
outTexture->id = 0;
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformCocoaTouchGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformCocoaTouchGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
auto* p = static_cast<CocoaTouchExternalImage*>(texture);
|
||||
delete p;
|
||||
}
|
||||
@@ -229,4 +233,35 @@ bool PlatformCocoaTouchGL::setExternalImage(void* externalImage, ExternalTexture
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformCocoaTouchGL::createExternalImage(void* cvPixelBuffer) noexcept {
|
||||
auto* p = new(std::nothrow) PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL;
|
||||
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
void PlatformCocoaTouchGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
|
||||
auto const* const cocoaTouchGlExternalImage
|
||||
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
|
||||
// Take ownership of the passed in buffer. It will be released the next time
|
||||
// setExternalImage is called, or when the texture is destroyed.
|
||||
CVPixelBufferRef pixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
|
||||
CVPixelBufferRetain(pixelBuffer);
|
||||
}
|
||||
|
||||
bool PlatformCocoaTouchGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
|
||||
auto const* const cocoaTouchGlExternalImage
|
||||
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
|
||||
CVPixelBufferRef cvPixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
|
||||
CocoaTouchExternalImage* cocoaExternalImage = static_cast<CocoaTouchExternalImage*>(texture);
|
||||
if (!cocoaExternalImage->set(cvPixelBuffer)) {
|
||||
return false;
|
||||
}
|
||||
texture->target = cocoaExternalImage->getTarget();
|
||||
texture->id = cocoaExternalImage->getGlTexture();
|
||||
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
|
||||
// cocoaExternalImage->getInternalFormat();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -117,7 +117,9 @@ bool PlatformEGL::isOpenGL() const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
PlatformEGL::ExternalImageEGL::~ExternalImageEGL() = default;
|
||||
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept {
|
||||
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
|
||||
|
||||
@@ -295,7 +297,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
|
||||
clearGlError();
|
||||
|
||||
// success!!
|
||||
return OpenGLPlatform::createDefaultDriver(this, sharedContext, driverConfig);
|
||||
return createDefaultDriver(this, sharedContext, driverConfig);
|
||||
|
||||
error:
|
||||
// if we're here, we've failed
|
||||
@@ -549,7 +551,7 @@ Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
return sc;
|
||||
}
|
||||
|
||||
void PlatformEGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
||||
void PlatformEGL::destroySwapChain(SwapChain* swapChain) noexcept {
|
||||
if (swapChain) {
|
||||
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
|
||||
if (sc->sur != EGL_NO_SURFACE) {
|
||||
@@ -562,7 +564,7 @@ void PlatformEGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
bool PlatformEGL::isSwapChainProtected(Platform::SwapChain* swapChain) noexcept {
|
||||
bool PlatformEGL::isSwapChainProtected(SwapChain* swapChain) noexcept {
|
||||
if (swapChain) {
|
||||
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
|
||||
return bool(sc->flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT);
|
||||
@@ -583,10 +585,10 @@ bool PlatformEGL::makeCurrent(ContextType type,
|
||||
return success == EGL_TRUE ? true : false;
|
||||
}
|
||||
|
||||
void PlatformEGL::makeCurrent(Platform::SwapChain* drawSwapChain,
|
||||
Platform::SwapChain* readSwapChain,
|
||||
utils::Invocable<void()> preContextChange,
|
||||
utils::Invocable<void(size_t index)> postContextChange) noexcept {
|
||||
void PlatformEGL::makeCurrent(SwapChain* drawSwapChain,
|
||||
SwapChain* readSwapChain,
|
||||
Invocable<void()> preContextChange,
|
||||
Invocable<void(size_t index)> postContextChange) noexcept {
|
||||
|
||||
assert_invariant(drawSwapChain);
|
||||
assert_invariant(readSwapChain);
|
||||
@@ -645,7 +647,7 @@ void PlatformEGL::makeCurrent(Platform::SwapChain* drawSwapChain,
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformEGL::commit(Platform::SwapChain* swapChain) noexcept {
|
||||
void PlatformEGL::commit(SwapChain* swapChain) noexcept {
|
||||
if (swapChain) {
|
||||
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
|
||||
if (sc->sur != EGL_NO_SURFACE) {
|
||||
@@ -668,7 +670,7 @@ Platform::Fence* PlatformEGL::createFence() noexcept {
|
||||
return f;
|
||||
}
|
||||
|
||||
void PlatformEGL::destroyFence(Platform::Fence* fence) noexcept {
|
||||
void PlatformEGL::destroyFence(Fence* fence) noexcept {
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
EGLSyncKHR sync = (EGLSyncKHR) fence;
|
||||
if (sync != EGL_NO_SYNC_KHR) {
|
||||
@@ -678,7 +680,7 @@ void PlatformEGL::destroyFence(Platform::Fence* fence) noexcept {
|
||||
}
|
||||
|
||||
FenceStatus PlatformEGL::waitFence(
|
||||
Platform::Fence* fence, uint64_t timeout) noexcept {
|
||||
Fence* fence, uint64_t timeout) noexcept {
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
EGLSyncKHR sync = (EGLSyncKHR) fence;
|
||||
if (sync != EGL_NO_SYNC_KHR) {
|
||||
@@ -699,16 +701,10 @@ FenceStatus PlatformEGL::waitFence(
|
||||
OpenGLPlatform::ExternalTexture* PlatformEGL::createExternalImageTexture() noexcept {
|
||||
ExternalTexture* outTexture = new(std::nothrow) ExternalTexture{};
|
||||
glGenTextures(1, &outTexture->id);
|
||||
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
|
||||
outTexture->target = GL_TEXTURE_EXTERNAL_OES;
|
||||
} else {
|
||||
// if texture external is not supported, revert to texture 2d
|
||||
outTexture->target = GL_TEXTURE_2D;
|
||||
}
|
||||
return outTexture;
|
||||
}
|
||||
|
||||
void PlatformEGL::destroyExternalImage(ExternalTexture* texture) noexcept {
|
||||
void PlatformEGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
|
||||
glDeleteTextures(1, &texture->id);
|
||||
delete texture;
|
||||
}
|
||||
@@ -728,6 +724,18 @@ bool PlatformEGL::setExternalImage(void* externalImage,
|
||||
return true;
|
||||
}
|
||||
|
||||
Platform::ExternalImageHandle PlatformEGL::createExternalImage(EGLImageKHR eglImage) noexcept {
|
||||
auto* const p = new(std::nothrow) ExternalImageEGL;
|
||||
p->eglImage = eglImage;
|
||||
return ExternalImageHandle{p};
|
||||
}
|
||||
|
||||
bool PlatformEGL::setExternalImage(ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
|
||||
auto const* const eglExternalImage = static_cast<ExternalImageEGL const*>(externalImage.get());
|
||||
return setExternalImage(eglExternalImage->eglImage, texture);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
void PlatformEGL::initializeGlExtensions() noexcept {
|
||||
@@ -738,7 +746,7 @@ void PlatformEGL::initializeGlExtensions() noexcept {
|
||||
ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
|
||||
}
|
||||
|
||||
EGLContext PlatformEGL::getContextForType(OpenGLPlatform::ContextType type) const noexcept {
|
||||
EGLContext PlatformEGL::getContextForType(ContextType type) const noexcept {
|
||||
switch (type) {
|
||||
case ContextType::NONE:
|
||||
return EGL_NO_CONTEXT;
|
||||
|
||||
@@ -231,6 +231,26 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
|
||||
return driver;
|
||||
}
|
||||
|
||||
PlatformEGLAndroid::ExternalImageEGLAndroid::~ExternalImageEGLAndroid() = default;
|
||||
|
||||
Platform::ExternalImageHandle PlatformEGLAndroid::createExternalImage(AHardwareBuffer const* buffer, bool sRGB) noexcept {
|
||||
auto* const p = new(std::nothrow) ExternalImageEGLAndroid;
|
||||
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
|
||||
p->sRGB = sRGB;
|
||||
return ExternalImageHandle{ p };
|
||||
}
|
||||
|
||||
bool PlatformEGLAndroid::setExternalImage(ExternalImageHandleRef externalImage,
|
||||
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
|
||||
auto const* const eglExternalImage = static_cast<ExternalImageEGLAndroid const*>(externalImage.get());
|
||||
if (eglExternalImage->aHardwareBuffer) {
|
||||
// TODO: implement PlatformEGLAndroid::setExternalImage w/ AHardwareBuffer
|
||||
return true;
|
||||
}
|
||||
// not a AHardwareBuffer, fallback to the inherited version
|
||||
return PlatformEGL::setExternalImage(externalImage, texture);
|
||||
}
|
||||
|
||||
void PlatformEGLAndroid::setPresentationTime(int64_t presentationTimeInNanosecond) noexcept {
|
||||
EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
|
||||
if (currentDrawSurface != EGL_NO_SURFACE) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanSamplerCache.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Panic.h>
|
||||
@@ -61,8 +62,8 @@ inline void blitFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect, V
|
||||
.dstOffsets = { dstRect[0], dstRect[1] },
|
||||
}};
|
||||
vkCmdBlitImage(cmdbuf,
|
||||
src.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
dst.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_DST),
|
||||
src.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
dst.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST),
|
||||
1, blitRegions, filter);
|
||||
|
||||
if (oldSrcLayout == VulkanLayout::UNDEFINED) {
|
||||
@@ -104,8 +105,8 @@ inline void resolveFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect
|
||||
.extent = { src.getExtent2D().width, src.getExtent2D().height, 1 },
|
||||
}};
|
||||
vkCmdResolveImage(cmdbuffer,
|
||||
src.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
dst.getImage(), imgutil::getVkLayout(VulkanLayout::TRANSFER_DST),
|
||||
src.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
dst.getImage(), fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST),
|
||||
1, resolveRegions);
|
||||
|
||||
if (oldSrcLayout == VulkanLayout::UNDEFINED) {
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "VulkanAsyncHandles.h"
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/StaticVector.h"
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
@@ -79,7 +79,7 @@ struct VulkanCommandBuffer {
|
||||
void reset() noexcept;
|
||||
|
||||
inline void insertWait(VkSemaphore sem) {
|
||||
mWaitSemaphores.insert(sem);
|
||||
mWaitSemaphores.push_back(sem);
|
||||
}
|
||||
|
||||
void pushMarker(char const* marker) noexcept;
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
bool const isProtected;
|
||||
VkDevice mDevice;
|
||||
VkQueue mQueue;
|
||||
CappedArray<VkSemaphore, 2> mWaitSemaphores;
|
||||
fvkutils::StaticVector<VkSemaphore, 2> mWaitSemaphores;
|
||||
VkCommandBuffer mBuffer;
|
||||
VkSemaphore mSubmission;
|
||||
VkFence mFence;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "VulkanUtility.h"
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#define TNT_FILAMENT_BACKEND_VULKANCONTEXT_H
|
||||
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanImageUtility.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/Slice.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
VK_DEFINE_HANDLE(VmaAllocator)
|
||||
@@ -113,11 +115,11 @@ public:
|
||||
return (uint32_t) VK_MAX_MEMORY_TYPES;
|
||||
}
|
||||
|
||||
inline VkFormatList const& getAttachmentDepthStencilFormats() const {
|
||||
inline fvkutils::VkFormatList const& getAttachmentDepthStencilFormats() const {
|
||||
return mDepthStencilFormats;
|
||||
}
|
||||
|
||||
inline VkFormatList const& getBlittableDepthStencilFormats() const {
|
||||
inline fvkutils::VkFormatList const& getBlittableDepthStencilFormats() const {
|
||||
return mBlittableDepthStencilFormats;
|
||||
}
|
||||
|
||||
@@ -186,8 +188,8 @@ private:
|
||||
bool mLazilyAllocatedMemorySupported = false;
|
||||
bool mProtectedMemorySupported = false;
|
||||
|
||||
VkFormatList mDepthStencilFormats;
|
||||
VkFormatList mBlittableDepthStencilFormats;
|
||||
fvkutils::VkFormatList mDepthStencilFormats;
|
||||
fvkutils::VkFormatList mBlittableDepthStencilFormats;
|
||||
|
||||
// For convenience so that VulkanPlatform can initialize the private fields.
|
||||
friend class VulkanPlatform;
|
||||
|
||||
@@ -26,9 +26,12 @@
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "memory/ResourceManager.h"
|
||||
#include "memory/ResourcePointer.h"
|
||||
#include "vulkan/memory/ResourceManager.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include <utils/CString.h>
|
||||
@@ -43,11 +46,13 @@ using namespace bluevk;
|
||||
|
||||
using utils::FixedCapacityVector;
|
||||
|
||||
#if defined(__clang__)
|
||||
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
|
||||
// to a stack-allocated variable.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-stack-address"
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -295,6 +300,10 @@ ShaderModel VulkanDriver::getShaderModel() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
ShaderLanguage VulkanDriver::getShaderLanguage() const noexcept {
|
||||
return ShaderLanguage::SPIRV;
|
||||
}
|
||||
|
||||
void VulkanDriver::terminate() {
|
||||
// Flush and wait here to make sure all queued commands are executed and resources that are tied
|
||||
// to those commands are no longer referenced.
|
||||
@@ -536,16 +545,25 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a) {
|
||||
TextureSwizzle const swizzleArray[] = {r, g, b, a};
|
||||
VkComponentMapping const swizzle = getSwizzleMap(swizzleArray);
|
||||
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle);
|
||||
texture.inc();
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target, backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage, void* externalImage) {
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* externalImage) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
|
||||
@@ -555,7 +573,7 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th,
|
||||
|
||||
assert_invariant(width == metadata.width);
|
||||
assert_invariant(height == metadata.height);
|
||||
assert_invariant(getVkFormat(format) == metadata.format);
|
||||
assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
|
||||
|
||||
const auto& data = mPlatform->createExternalImage(externalImage, metadata);
|
||||
|
||||
@@ -783,6 +801,10 @@ Handle<HwTexture> VulkanDriver::createTextureViewSwizzleS() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> VulkanDriver::createTextureExternalImage2S() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
|
||||
Handle<HwTexture> VulkanDriver::createTextureExternalImageS() noexcept {
|
||||
return mResourceManager.allocHandle<VulkanTexture>();
|
||||
}
|
||||
@@ -930,7 +952,7 @@ FenceStatus VulkanDriver::getFenceStatus(Handle<HwFence> fh) {
|
||||
// We create all textures using VK_IMAGE_TILING_OPTIMAL, so our definition of "supported" is that
|
||||
// the GPU supports the given texture format with non-zero optimal tiling features.
|
||||
bool VulkanDriver::isTextureFormatSupported(TextureFormat format) {
|
||||
VkFormat vkformat = getVkFormat(format);
|
||||
VkFormat vkformat = fvkutils::getVkFormat(format);
|
||||
if (vkformat == VK_FORMAT_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
@@ -957,7 +979,7 @@ bool VulkanDriver::isTextureFormatMipmappable(TextureFormat format) {
|
||||
}
|
||||
|
||||
bool VulkanDriver::isRenderTargetFormatSupported(TextureFormat format) {
|
||||
VkFormat vkformat = getVkFormat(format);
|
||||
VkFormat vkformat = fvkutils::getVkFormat(format);
|
||||
if (vkformat == VK_FORMAT_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
@@ -1015,12 +1037,11 @@ bool VulkanDriver::isDepthStencilResolveSupported() {
|
||||
|
||||
bool VulkanDriver::isDepthStencilBlitSupported(TextureFormat format) {
|
||||
auto const& formats = mContext.getBlittableDepthStencilFormats();
|
||||
return std::find(formats.begin(), formats.end(), getVkFormat(format)) != formats.end();
|
||||
return std::find(formats.begin(), formats.end(), fvkutils::getVkFormat(format)) !=
|
||||
formats.end();
|
||||
}
|
||||
|
||||
bool VulkanDriver::isProtectedTexturesSupported() {
|
||||
return false;
|
||||
}
|
||||
bool VulkanDriver::isProtectedTexturesSupported() { return false; }
|
||||
|
||||
bool VulkanDriver::isDepthClampSupported() {
|
||||
return mContext.isDepthClampSupported();
|
||||
@@ -1091,8 +1112,8 @@ FeatureLevel VulkanDriver::getFeatureLevel() {
|
||||
|
||||
math::float2 VulkanDriver::getClipSpaceParams() {
|
||||
// virtual and physical z-coordinate of clip-space is in [-w, 0]
|
||||
// Note: this is actually never used (see: main.vs), but it's a backend API, so we implement it
|
||||
// properly.
|
||||
// Note: this is actually never used (see: surface_main.vs), but it's a backend API, so we
|
||||
// implement it properly.
|
||||
return math::float2{ 1.0f, 0.0f };
|
||||
}
|
||||
|
||||
@@ -1163,6 +1184,9 @@ void VulkanDriver::update3DImage(Handle<HwTexture> th, uint32_t level, uint32_t
|
||||
scheduleDestroy(std::move(data));
|
||||
}
|
||||
|
||||
void VulkanDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
}
|
||||
|
||||
void VulkanDriver::setupExternalImage(void* image) {
|
||||
}
|
||||
|
||||
@@ -1673,25 +1697,25 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
auto rt = mCurrentRenderPass.renderTarget;
|
||||
|
||||
VulkanPipelineCache::RasterState const vulkanRasterState{
|
||||
.cullMode = getCullMode(rasterState.culling),
|
||||
.frontFace = getFrontFace(rasterState.inverseFrontFaces),
|
||||
.cullMode = fvkutils::getCullMode(rasterState.culling),
|
||||
.frontFace = fvkutils::getFrontFace(rasterState.inverseFrontFaces),
|
||||
.depthBiasEnable = (depthOffset.constant || depthOffset.slope) ? true : false,
|
||||
.blendEnable = rasterState.hasBlending(),
|
||||
.depthWriteEnable = rasterState.depthWrite,
|
||||
.alphaToCoverageEnable = rasterState.alphaToCoverage,
|
||||
.srcColorBlendFactor = getBlendFactor(rasterState.blendFunctionSrcRGB),
|
||||
.dstColorBlendFactor = getBlendFactor(rasterState.blendFunctionDstRGB),
|
||||
.srcAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionSrcAlpha),
|
||||
.dstAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionDstAlpha),
|
||||
.srcColorBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionSrcRGB),
|
||||
.dstColorBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionDstRGB),
|
||||
.srcAlphaBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionSrcAlpha),
|
||||
.dstAlphaBlendFactor = fvkutils::getBlendFactor(rasterState.blendFunctionDstAlpha),
|
||||
.colorWriteMask = (VkColorComponentFlags) (rasterState.colorWrite ? 0xf : 0x0),
|
||||
.rasterizationSamples = rt->getSamples(),
|
||||
.depthClamp = rasterState.depthClamp,
|
||||
.colorTargetCount = rt->getColorTargetCount(mCurrentRenderPass),
|
||||
.colorBlendOp = rasterState.blendEquationRGB,
|
||||
.alphaBlendOp = rasterState.blendEquationAlpha,
|
||||
.alphaBlendOp = rasterState.blendEquationAlpha,
|
||||
.depthCompareOp = rasterState.depthFunc,
|
||||
.depthBiasConstantFactor = depthOffset.constant,
|
||||
.depthBiasSlopeFactor = depthOffset.slope
|
||||
.depthBiasSlopeFactor = depthOffset.slope,
|
||||
};
|
||||
|
||||
// unfortunately in Vulkan the topology is per pipeline
|
||||
@@ -1728,7 +1752,7 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
mBoundPipeline = {
|
||||
.program = program,
|
||||
.pipelineLayout = pipelineLayout,
|
||||
.descriptorSetMask = DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
|
||||
.descriptorSetMask = fvkutils::DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
|
||||
};
|
||||
|
||||
mPipelineCache.bindLayout(pipelineLayout);
|
||||
@@ -1877,4 +1901,6 @@ template class ConcreteDispatcher<VulkanDriver>;
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -26,12 +26,13 @@
|
||||
#include "VulkanReadPixels.h"
|
||||
#include "VulkanSamplerCache.h"
|
||||
#include "VulkanStagePool.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/caching/VulkanDescriptorSetManager.h"
|
||||
#include "vulkan/caching/VulkanPipelineLayoutCache.h"
|
||||
#include "vulkan/memory/ResourceManager.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
|
||||
#include "backend/DriverEnums.h"
|
||||
#include "caching/VulkanDescriptorSetManager.h"
|
||||
#include "caching/VulkanPipelineLayoutCache.h"
|
||||
#include "memory/ResourceManager.h"
|
||||
#include "memory/ResourcePointer.h"
|
||||
|
||||
#include "DriverBase.h"
|
||||
#include "private/backend/Driver.h"
|
||||
@@ -93,6 +94,7 @@ private:
|
||||
Dispatcher getDispatcher() const noexcept final;
|
||||
|
||||
ShaderModel getShaderModel() const noexcept final;
|
||||
ShaderLanguage getShaderLanguage() const noexcept final;
|
||||
|
||||
template<typename T>
|
||||
friend class ConcreteDispatcher;
|
||||
@@ -141,13 +143,14 @@ private:
|
||||
struct {
|
||||
resource_ptr<VulkanProgram> program;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
DescriptorSetMask descriptorSetMask;
|
||||
fvkutils::DescriptorSetMask descriptorSetMask;
|
||||
} mBoundPipeline = {};
|
||||
|
||||
// We need to store information about a render pass to enable better barriers at the end of a
|
||||
// renderpass.
|
||||
struct {
|
||||
using AttachmentArray = CappedArray<VulkanAttachment, MAX_RENDERTARGET_ATTACHMENT_TEXTURES>;
|
||||
using AttachmentArray =
|
||||
fvkutils::StaticVector<VulkanAttachment, MAX_RENDERTARGET_ATTACHMENT_TEXTURES>;
|
||||
AttachmentArray attachments;
|
||||
} mRenderPassFboInfo = {};
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "vulkan/VulkanFboCache.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include "VulkanFboCache.h"
|
||||
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
// If any VkRenderPass or VkFramebuffer is unused for more than TIME_BEFORE_EVICTION frames, it
|
||||
// is evicted from the cache.
|
||||
@@ -214,7 +214,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
if (config.colorFormat[i] == VK_FORMAT_UNDEFINED) {
|
||||
continue;
|
||||
}
|
||||
const VkImageLayout subpassLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT);
|
||||
const VkImageLayout subpassLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT);
|
||||
uint32_t index;
|
||||
|
||||
if (!hasSubpasses) {
|
||||
@@ -259,8 +259,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
.storeOp = (config.usesLazilyAllocatedMemory & (1 << i)) ? kDisableStore : kEnableStore,
|
||||
.stencilLoadOp = kDontCare,
|
||||
.stencilStoreOp = kDisableStore,
|
||||
.initialLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
|
||||
.finalLayout = imgutil::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
|
||||
.initialLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
|
||||
.finalLayout = fvkutils::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
|
||||
pResolveAttachment->attachment = attachmentIndex;
|
||||
pResolveAttachment->layout
|
||||
= imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT_RESOLVE);
|
||||
= fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT_RESOLVE);
|
||||
++pResolveAttachment;
|
||||
|
||||
attachments[attachmentIndex++] = {
|
||||
@@ -297,8 +297,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
.storeOp = kEnableStore,
|
||||
.stencilLoadOp = kDontCare,
|
||||
.stencilStoreOp = kDisableStore,
|
||||
.initialLayout = imgutil::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
|
||||
.finalLayout = imgutil::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
|
||||
.initialLayout = fvkutils::getVkLayout(VulkanLayout::COLOR_ATTACHMENT),
|
||||
.finalLayout = fvkutils::getVkLayout(FINAL_COLOR_ATTACHMENT_LAYOUT),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
const bool clear = any(config.clear & TargetBufferFlags::DEPTH);
|
||||
const bool discardStart = any(config.discardStart & TargetBufferFlags::DEPTH);
|
||||
const bool discardEnd = any(config.discardEnd & TargetBufferFlags::DEPTH);
|
||||
depthAttachmentRef.layout = imgutil::getVkLayout(VulkanLayout::DEPTH_ATTACHMENT);
|
||||
depthAttachmentRef.layout = fvkutils::getVkLayout(VulkanLayout::DEPTH_ATTACHMENT);
|
||||
depthAttachmentRef.attachment = attachmentIndex;
|
||||
attachments[attachmentIndex++] = {
|
||||
.format = config.depthFormat,
|
||||
@@ -316,8 +316,8 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
||||
.storeOp = discardEnd ? kDisableStore : kEnableStore,
|
||||
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.initialLayout = imgutil::getVkLayout(config.initialDepthLayout),
|
||||
.finalLayout = imgutil::getVkLayout(FINAL_DEPTH_ATTACHMENT_LAYOUT),
|
||||
.initialLayout = fvkutils::getVkLayout(config.initialDepthLayout),
|
||||
.finalLayout = fvkutils::getVkLayout(FINAL_DEPTH_ATTACHMENT_LAYOUT),
|
||||
};
|
||||
}
|
||||
renderPassInfo.attachmentCount = attachmentIndex;
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include "VulkanDriver.h"
|
||||
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "spirv/VulkanSpirvUtils.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
#include "vulkan/utils/Spirv.h"
|
||||
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
@@ -56,10 +58,10 @@ template<typename Bitmask>
|
||||
inline void fromStageFlags(backend::ShaderStageFlags stage, descriptor_binding_t binding,
|
||||
Bitmask& mask) {
|
||||
if ((bool) (stage & ShaderStageFlags::VERTEX)) {
|
||||
mask.set(binding + getVertexStageShift<Bitmask>());
|
||||
mask.set(binding + fvkutils::getVertexStageShift<Bitmask>());
|
||||
}
|
||||
if ((bool) (stage & ShaderStageFlags::FRAGMENT)) {
|
||||
mask.set(binding + getFragmentStageShift<Bitmask>());
|
||||
mask.set(binding + fvkutils::getFragmentStageShift<Bitmask>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +208,7 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
|
||||
size_t dataSize = blob.size();
|
||||
|
||||
if (!specializationConstants.empty()) {
|
||||
workaroundSpecConstant(blob, specializationConstants, shader);
|
||||
fvkutils::workaroundSpecConstant(blob, specializationConstants, shader);
|
||||
data = (uint32_t*) shader.data();
|
||||
dataSize = shader.size() * 4;
|
||||
}
|
||||
@@ -314,8 +316,8 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
// Constrain the sample count according to both kinds of sample count masks obtained from
|
||||
// VkPhysicalDeviceProperties. This is consistent with the VulkanTexture constructor.
|
||||
auto const& limits = context.getPhysicalDeviceLimits();
|
||||
samples = reduceSampleCount(samples, limits.framebufferDepthSampleCounts &
|
||||
limits.framebufferColorSampleCounts);
|
||||
samples = samples = fvkutils::reduceSampleCount(samples,
|
||||
limits.framebufferDepthSampleCounts & limits.framebufferColorSampleCounts);
|
||||
|
||||
auto& rpkey = mInfo->rpkey;
|
||||
rpkey.samples = samples;
|
||||
@@ -498,7 +500,7 @@ VulkanVertexBufferInfo::VulkanVertexBufferInfo(
|
||||
Attribute attrib = attributes[attribIndex];
|
||||
bool const isInteger = attrib.flags & Attribute::FLAG_INTEGER_TARGET;
|
||||
bool const isNormalized = attrib.flags & Attribute::FLAG_NORMALIZED;
|
||||
VkFormat vkformat = getVkFormat(attrib.type, isNormalized, isInteger);
|
||||
VkFormat vkformat = fvkutils::getVkFormat(attrib.type, isNormalized, isInteger);
|
||||
|
||||
// HACK: Re-use the positions buffer as a dummy buffer for disabled attributes. Filament's
|
||||
// vertex shaders declare all attributes as either vec4 or uvec4 (the latter for bone
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
#include "VulkanFboCache.h"
|
||||
#include "VulkanSwapChain.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/memory/Resource.h"
|
||||
#include "vulkan/utils/StaticVector.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
|
||||
#include <backend/Program.h>
|
||||
|
||||
@@ -44,11 +45,11 @@ namespace {
|
||||
template<typename Bitmask>
|
||||
inline uint8_t collapsedCount(Bitmask const& mask) {
|
||||
static_assert(sizeof(mask) <= 64);
|
||||
constexpr uint64_t VERTEX_MASK = (1ULL << getFragmentStageShift<Bitmask>()) - 1ULL;
|
||||
constexpr uint64_t FRAGMENT_MASK = (VERTEX_MASK << getFragmentStageShift<Bitmask>());
|
||||
constexpr uint64_t VERTEX_MASK = (1ULL << fvkutils::getFragmentStageShift<Bitmask>()) - 1ULL;
|
||||
constexpr uint64_t FRAGMENT_MASK = (VERTEX_MASK << fvkutils::getFragmentStageShift<Bitmask>());
|
||||
uint64_t val = mask.getValue();
|
||||
val = ((val & VERTEX_MASK) >> getVertexStageShift<Bitmask>()) |
|
||||
((val & FRAGMENT_MASK) >> getFragmentStageShift<Bitmask>());
|
||||
val = ((val & VERTEX_MASK) >> fvkutils::getVertexStageShift<Bitmask>()) |
|
||||
((val & FRAGMENT_MASK) >> fvkutils::getFragmentStageShift<Bitmask>());
|
||||
return (uint8_t) Bitmask(val).count();
|
||||
}
|
||||
|
||||
@@ -67,10 +68,10 @@ struct VulkanDescriptorSetLayout : public HwDescriptorSetLayout, fvkmemory::Reso
|
||||
// The bitmask representation of a set layout.
|
||||
struct Bitmask {
|
||||
// TODO: better utiltize the space below and use bitset instead.
|
||||
UniformBufferBitmask ubo; // 8 bytes
|
||||
UniformBufferBitmask dynamicUbo; // 8 bytes
|
||||
SamplerBitmask sampler; // 8 bytes
|
||||
InputAttachmentBitmask inputAttachment; // 8 bytes
|
||||
fvkutils::UniformBufferBitmask ubo; // 8 bytes
|
||||
fvkutils::UniformBufferBitmask dynamicUbo; // 8 bytes
|
||||
fvkutils::SamplerBitmask sampler; // 8 bytes
|
||||
fvkutils::InputAttachmentBitmask inputAttachment; // 8 bytes
|
||||
|
||||
bool operator==(Bitmask const& right) const {
|
||||
return ubo == right.ubo && dynamicUbo == right.dynamicUbo && sampler == right.sampler &&
|
||||
@@ -138,7 +139,7 @@ public:
|
||||
using OnRecycle = std::function<void(VulkanDescriptorSet*)>;
|
||||
|
||||
VulkanDescriptorSet(VkDescriptorSet rawSet,
|
||||
UniformBufferBitmask const& dynamicUboMask,
|
||||
fvkutils::UniformBufferBitmask const& dynamicUboMask,
|
||||
uint8_t uniqueDynamicUboCount,
|
||||
OnRecycle&& onRecycleFn)
|
||||
: vkSet(rawSet),
|
||||
@@ -164,7 +165,7 @@ public:
|
||||
void acquire(fvkmemory::resource_ptr<VulkanBufferObject> buffer);
|
||||
|
||||
VkDescriptorSet const vkSet;
|
||||
UniformBufferBitmask const dynamicUboMask;
|
||||
fvkutils::UniformBufferBitmask const dynamicUboMask;
|
||||
uint8_t const uniqueDynamicUboCount;
|
||||
|
||||
private:
|
||||
@@ -193,7 +194,7 @@ private:
|
||||
};
|
||||
|
||||
struct VulkanProgram : public HwProgram, fvkmemory::Resource {
|
||||
using BindingList = CappedArray<uint16_t, MAX_SAMPLER_COUNT>;
|
||||
using BindingList = fvkutils::StaticVector<uint16_t, MAX_SAMPLER_COUNT>;
|
||||
|
||||
VulkanProgram(VkDevice device, Program const& builder) noexcept;
|
||||
~VulkanProgram();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <bluevk/BlueVK.h> // must be included before vk_mem_alloc
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
|
||||
// Needed because not all clang versions have the warning -Wdeprecated-copy.
|
||||
@@ -32,6 +33,7 @@
|
||||
#pragma clang diagnostic ignored "-Wextra-semi"
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
|
||||
#pragma clang diagnostic ignored "-Wthread-safety-analysis"
|
||||
#endif
|
||||
|
||||
static const PFN_vkGetInstanceProcAddr& vkGetInstanceProcAddr = bluevk::vkGetInstanceProcAddr;
|
||||
static const PFN_vkGetDeviceProcAddr& vkGetDeviceProcAddr = bluevk::vkGetDeviceProcAddr;
|
||||
@@ -39,4 +41,7 @@ static const PFN_vkGetDeviceProcAddr& vkGetDeviceProcAddr = bluevk::vkGetDeviceP
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_IMPLEMENTATION
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
|
||||
#endif
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
// Vulkan functions often immediately dereference pointers, so it's fine to pass in a pointer
|
||||
// to a stack-allocated variable.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-stack-address"
|
||||
#endif
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
@@ -194,7 +196,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
|
||||
vkDs.depthTestEnable = VK_TRUE;
|
||||
vkDs.depthWriteEnable = raster.depthWriteEnable;
|
||||
vkDs.depthCompareOp = getCompareOp(raster.depthCompareOp);
|
||||
vkDs.depthCompareOp = fvkutils::getCompareOp(raster.depthCompareOp);
|
||||
vkDs.depthBoundsTestEnable = VK_FALSE;
|
||||
vkDs.stencilTestEnable = VK_FALSE;
|
||||
vkDs.minDepthBounds = 0.0f;
|
||||
@@ -323,4 +325,6 @@ bool VulkanPipelineCache::PipelineEqual::operator()(const PipelineKey& k1,
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanUtility.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
@@ -68,8 +67,10 @@ public:
|
||||
VkSpecializationInfo* specializationInfos = nullptr;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic warning "-Wpadded"
|
||||
#endif
|
||||
|
||||
// The RasterState POD contains standard graphics-related state like blending, culling, etc.
|
||||
// The following states are omitted because Filament never changes them:
|
||||
@@ -212,7 +213,9 @@ private:
|
||||
bool operator()(const PipelineKey& k1, const PipelineKey& k2) const;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
// CACHE ENTRY STRUCTS
|
||||
// -------------------
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#include "DataReshaper.h"
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanHandles.h"
|
||||
#include "VulkanImageUtility.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "vulkan/utils/Conversion.h" // getComponentType()
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
@@ -218,7 +219,7 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
||||
};
|
||||
vkBeginCommandBuffer(cmdbuffer, &binfo);
|
||||
|
||||
imgutil::transitionLayout(cmdbuffer, {
|
||||
fvkutils::transitionLayout(cmdbuffer, {
|
||||
.image = stagingImage,
|
||||
.oldLayout = VulkanLayout::UNDEFINED,
|
||||
.newLayout = VulkanLayout::TRANSFER_DST,
|
||||
@@ -265,8 +266,8 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
||||
imageCopyRegion.srcOffset.y + imageCopyRegion.extent.height <= srcExtent.height);
|
||||
|
||||
vkCmdCopyImage(cmdbuffer, srcAttachment.getImage(),
|
||||
imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC), stagingImage,
|
||||
imgutil::getVkLayout(VulkanLayout::TRANSFER_DST), 1, &imageCopyRegion);
|
||||
fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC), stagingImage,
|
||||
fvkutils::getVkLayout(VulkanLayout::TRANSFER_DST), 1, &imageCopyRegion);
|
||||
|
||||
// Restore the source image layout.
|
||||
srcTexture->transitionLayout(cmdbuffer, srcRange, srcTexture->getDefaultLayout());
|
||||
@@ -318,8 +319,8 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
||||
vkMapMemory(device, stagingMemory, 0, VK_WHOLE_SIZE, 0, (void**) &srcPixels);
|
||||
srcPixels += subResourceLayout.offset;
|
||||
|
||||
if (!DataReshaper::reshapeImage(&p, getComponentType(srcFormat),
|
||||
getComponentCount(srcFormat), srcPixels,
|
||||
if (!DataReshaper::reshapeImage(&p, fvkutils::getComponentType(srcFormat),
|
||||
fvkutils::getComponentCount(srcFormat), srcPixels,
|
||||
static_cast<int>(subResourceLayout.rowPitch), static_cast<int>(width),
|
||||
static_cast<int>(height), swizzle)) {
|
||||
FVK_LOGE << "Unsupported PixelDataFormat or PixelDataType" << utils::io::endl;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "vulkan/VulkanSamplerCache.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
@@ -114,7 +115,7 @@ VkSampler VulkanSamplerCache::getSampler(SamplerParams params) noexcept {
|
||||
.anisotropyEnable = params.anisotropyLog2 == 0 ? 0u : 1u,
|
||||
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
|
||||
.compareEnable = getCompareEnable(params.compareMode),
|
||||
.compareOp = getCompareOp(params.compareFunc),
|
||||
.compareOp = fvkutils::getCompareOp(params.compareFunc),
|
||||
.minLod = 0.0f,
|
||||
.maxLod = getMaxLod(params.filterMin),
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
|
||||
|
||||
#include "VulkanContext.h"
|
||||
#include "VulkanUtility.h"
|
||||
|
||||
#include <tsl/robin_map.h>
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanConstants.h"
|
||||
#include "VulkanImageUtility.h"
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
@@ -72,7 +72,7 @@ VulkanStage const* VulkanStagePool::acquireStage(uint32_t numBytes) {
|
||||
|
||||
VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, PixelDataType type,
|
||||
uint32_t width, uint32_t height) {
|
||||
const VkFormat vkformat = getVkFormat(format, type);
|
||||
const VkFormat vkformat = fvkutils::getVkFormat(format, type);
|
||||
for (auto image : mFreeImages) {
|
||||
if (image->format == vkformat && image->width == width && image->height == height) {
|
||||
mFreeImages.erase(image);
|
||||
@@ -113,7 +113,7 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi
|
||||
|
||||
assert_invariant(result == VK_SUCCESS);
|
||||
|
||||
VkImageAspectFlags const aspectFlags = getImageAspect(vkformat);
|
||||
VkImageAspectFlags const aspectFlags = fvkutils::getImageAspect(vkformat);
|
||||
VkCommandBuffer const cmdbuffer = mCommands->get().buffer();
|
||||
|
||||
// We use VK_IMAGE_LAYOUT_GENERAL here because the spec says:
|
||||
@@ -122,7 +122,7 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi
|
||||
// VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL layout. Calling
|
||||
// vkGetImageSubresourceLayout for a linear image returns a subresource layout mapping that is
|
||||
// valid for either of those image layouts."
|
||||
imgutil::transitionLayout(cmdbuffer, {
|
||||
fvkutils::transitionLayout(cmdbuffer, {
|
||||
.image = image->image,
|
||||
.oldLayout = VulkanLayout::UNDEFINED,
|
||||
.newLayout = VulkanLayout::READ_WRITE, // (= VK_IMAGE_LAYOUT_GENERAL)
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include "VulkanCommands.h"
|
||||
#include "VulkanMemory.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
|
||||
#include <DataReshaper.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -152,7 +152,7 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
|
||||
bool isProtected)
|
||||
: mVkFormat(format),
|
||||
mViewType(viewType),
|
||||
mFullViewRange{filament::backend::getImageAspect(format), 0, levels, 0, layerCount},
|
||||
mFullViewRange{fvkutils::getImageAspect(format), 0, levels, 0, layerCount},
|
||||
mDefaultLayout(defaultLayout),
|
||||
mIsProtected(isProtected),
|
||||
mStagePool(stagePool),
|
||||
@@ -169,7 +169,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
|
||||
: HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED,
|
||||
tusage),
|
||||
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
|
||||
allocator, commands, stagePool, format, imgutil::getViewType(SamplerType::SAMPLER_2D),
|
||||
allocator, commands, stagePool, format, fvkutils::getViewType(SamplerType::SAMPLER_2D),
|
||||
1, 1, getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) {
|
||||
mState->mTextureImage = image;
|
||||
mState->mTextureImageMemory = memory;
|
||||
@@ -184,8 +184,8 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool)
|
||||
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage),
|
||||
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
|
||||
allocator, commands, stagePool, backend::getVkFormat(tformat),
|
||||
imgutil::getViewType(target), levels, getLayerCount(target, depth),
|
||||
allocator, commands, stagePool, fvkutils::getVkFormat(tformat),
|
||||
fvkutils::getViewType(target), levels, getLayerCount(target, depth),
|
||||
VulkanLayout::UNDEFINED, any(usage & TextureUsage::PROTECTED))) {
|
||||
// Create an appropriately-sized device-only VkImage, but do not fill it yet.
|
||||
VkImageCreateInfo imageInfo{
|
||||
@@ -290,16 +290,17 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
// any kind of attachment (color or depth).
|
||||
const auto& limits = context.getPhysicalDeviceLimits();
|
||||
if (imageInfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
|
||||
samples = reduceSampleCount(samples, isVkDepthFormat(mState->mVkFormat)
|
||||
? limits.sampledImageDepthSampleCounts
|
||||
: limits.sampledImageColorSampleCounts);
|
||||
samples = fvkutils::reduceSampleCount(samples,
|
||||
fvkutils::isVkDepthFormat(mState->mVkFormat)
|
||||
? limits.sampledImageDepthSampleCounts
|
||||
: limits.sampledImageColorSampleCounts);
|
||||
}
|
||||
if (imageInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
samples = reduceSampleCount(samples, limits.framebufferColorSampleCounts);
|
||||
samples = fvkutils::reduceSampleCount(samples, limits.framebufferColorSampleCounts);
|
||||
}
|
||||
|
||||
if (imageInfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
samples = reduceSampleCount(samples, limits.sampledImageDepthSampleCounts);
|
||||
samples = fvkutils::reduceSampleCount(samples, limits.sampledImageDepthSampleCounts);
|
||||
}
|
||||
this->samples = samples;
|
||||
imageInfo.samples = (VkSampleCountFlagBits) samples;
|
||||
@@ -410,8 +411,8 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
||||
}
|
||||
|
||||
// If format conversion is both required and supported, use vkCmdBlitImage.
|
||||
const VkFormat hostFormat = backend::getVkFormat(hostData->format, hostData->type);
|
||||
const VkFormat deviceFormat = getVkFormatLinear(mState->mVkFormat);
|
||||
const VkFormat hostFormat = fvkutils::getVkFormat(hostData->format, hostData->type);
|
||||
const VkFormat deviceFormat = fvkutils::getVkFormatLinear(mState->mVkFormat);
|
||||
if (hostFormat != deviceFormat && hostFormat != VK_FORMAT_UNDEFINED) {
|
||||
assert_invariant(xoffset == 0 && yoffset == 0 && zoffset == 0 &&
|
||||
"Offsets not yet supported when format conversion is required.");
|
||||
@@ -470,7 +471,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
||||
|
||||
VulkanLayout const newLayout = VulkanLayout::TRANSFER_DST;
|
||||
VulkanLayout nextLayout = getLayout(transitionRange.baseArrayLayer, miplevel);
|
||||
VkImageLayout const newVkLayout = imgutil::getVkLayout(newLayout);
|
||||
VkImageLayout const newVkLayout = fvkutils::getVkLayout(newLayout);
|
||||
|
||||
if (nextLayout == VulkanLayout::UNDEFINED) {
|
||||
nextLayout = getDefaultLayout();
|
||||
@@ -517,8 +518,8 @@ void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, u
|
||||
VulkanLayout const oldLayout = getLayout(layer, miplevel);
|
||||
transitionLayout(&commands, range, newLayout);
|
||||
|
||||
vkCmdBlitImage(cmdbuf, stage->image, imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
mState->mTextureImage, imgutil::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST);
|
||||
vkCmdBlitImage(cmdbuf, stage->image, fvkutils::getVkLayout(VulkanLayout::TRANSFER_SRC),
|
||||
mState->mTextureImage, fvkutils::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST);
|
||||
|
||||
transitionLayout(&commands, range, oldLayout);
|
||||
}
|
||||
@@ -566,7 +567,7 @@ VkImageView VulkanTexture::getImageView(VkImageSubresourceRange range, VkImageVi
|
||||
|
||||
VkImageAspectFlags VulkanTexture::getImageAspect() const {
|
||||
// Helper function in VulkanUtility
|
||||
return filament::backend::getImageAspect(mState->mVkFormat);
|
||||
return fvkutils::getImageAspect(mState->mVkFormat);
|
||||
}
|
||||
|
||||
bool VulkanTexture::transitionLayout(VulkanCommandBuffer* commands,
|
||||
@@ -609,7 +610,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
|
||||
if (layout == newLayout) {
|
||||
continue;
|
||||
}
|
||||
hasTransitions = hasTransitions || imgutil::transitionLayout(cmdbuf, {
|
||||
hasTransitions = hasTransitions || fvkutils::transitionLayout(cmdbuf, {
|
||||
.image = mState->mTextureImage,
|
||||
.oldLayout = layout,
|
||||
.newLayout = newLayout,
|
||||
@@ -624,7 +625,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
|
||||
}
|
||||
}
|
||||
} else if (newLayout != oldLayout) {
|
||||
hasTransitions = imgutil::transitionLayout(cmdbuf, {
|
||||
hasTransitions = fvkutils::transitionLayout(cmdbuf, {
|
||||
.image = mState->mTextureImage,
|
||||
.oldLayout = oldLayout,
|
||||
.newLayout = newLayout,
|
||||
@@ -659,7 +660,7 @@ void VulkanTexture::samplerToAttachmentBarrier(VulkanCommandBuffer* commands,
|
||||
VkImageSubresourceRange const& range) {
|
||||
VkCommandBuffer const cmdbuf = commands->buffer();
|
||||
VkImageLayout const layout =
|
||||
imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
|
||||
fvkutils::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
|
||||
VkImageMemoryBarrier barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||
@@ -682,7 +683,7 @@ void VulkanTexture::attachmentToSamplerBarrier(VulkanCommandBuffer* commands,
|
||||
VkImageSubresourceRange const& range) {
|
||||
VkCommandBuffer const cmdbuf = commands->buffer();
|
||||
VkImageLayout const layout
|
||||
= imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
|
||||
= fvkutils::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel));
|
||||
VkImageMemoryBarrier barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#include "DriverBase.h"
|
||||
|
||||
#include "VulkanBuffer.h"
|
||||
#include "VulkanImageUtility.h"
|
||||
#include "vulkan/memory/Resource.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/RangeMap.h>
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
#include "VulkanDescriptorSetManager.h"
|
||||
|
||||
#include <vulkan/VulkanCommands.h>
|
||||
#include <vulkan/VulkanHandles.h>
|
||||
#include <vulkan/VulkanUtility.h>
|
||||
#include <vulkan/VulkanConstants.h>
|
||||
#include <vulkan/VulkanImageUtility.h>
|
||||
#include "vulkan/VulkanCommands.h"
|
||||
#include "vulkan/VulkanHandles.h"
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
@@ -207,17 +206,17 @@ uint32_t createBindings(VkDescriptorSetLayoutBinding* toBind, uint32_t count, Vk
|
||||
mask.forEachSetBit([&](size_t index) {
|
||||
VkShaderStageFlags stages = 0;
|
||||
uint32_t binding = 0;
|
||||
if (index < getFragmentStageShift<Bitmask>()) {
|
||||
if (index < fvkutils::getFragmentStageShift<Bitmask>()) {
|
||||
binding = (uint32_t) index;
|
||||
stages |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||
auto fragIndex = index + getFragmentStageShift<Bitmask>();
|
||||
auto fragIndex = index + fvkutils::getFragmentStageShift<Bitmask>();
|
||||
if (mask.test(fragIndex)) {
|
||||
stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
alreadySeen.set(fragIndex);
|
||||
}
|
||||
} else if (!alreadySeen.test(index)) {
|
||||
// We are in fragment stage bits
|
||||
binding = (uint32_t) (index - getFragmentStageShift<Bitmask>());
|
||||
binding = (uint32_t) (index - fvkutils::getFragmentStageShift<Bitmask>());
|
||||
stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
}
|
||||
|
||||
@@ -346,7 +345,6 @@ private:
|
||||
mVkLayouts;
|
||||
};
|
||||
|
||||
|
||||
VulkanDescriptorSetManager::VulkanDescriptorSetManager(VkDevice device,
|
||||
fvkmemory::ResourceManager* resourceManager)
|
||||
: mDevice(device),
|
||||
@@ -376,10 +374,10 @@ void VulkanDescriptorSetManager::unbind(uint8_t setIndex) {
|
||||
}
|
||||
|
||||
void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands,
|
||||
VkPipelineLayout pipelineLayout, DescriptorSetMask const& setMask) {
|
||||
VkPipelineLayout pipelineLayout, fvkutils::DescriptorSetMask const& setMask) {
|
||||
// setMask indicates the set of descriptor sets the driver wants to bind, curMask is the
|
||||
// actual set of sets that *needs* to be bound.
|
||||
DescriptorSetMask curMask = setMask;
|
||||
fvkutils::DescriptorSetMask curMask = setMask;
|
||||
|
||||
auto& updateSets = mStashedSets;
|
||||
auto& lastBoundSets = mLastBoundInfo.boundSets;
|
||||
@@ -458,7 +456,7 @@ void VulkanDescriptorSetManager::updateSampler(fvkmemory::resource_ptr<VulkanDes
|
||||
} else {
|
||||
info.imageView = texture->getViewForType(range, expectedType);
|
||||
}
|
||||
info.imageLayout = imgutil::getVkLayout(texture->getDefaultLayout());
|
||||
info.imageLayout = fvkutils::getVkLayout(texture->getDefaultLayout());
|
||||
VkWriteDescriptorSet const descriptorWrite = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = nullptr,
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
#define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H
|
||||
|
||||
#include "vulkan/VulkanHandles.h"
|
||||
#include "vulkan/VulkanTexture.h"
|
||||
#include "vulkan/VulkanUtility.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
#include "vulkan/utils/Definitions.h" // For DescriptorSetMask
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Program.h>
|
||||
@@ -68,7 +67,7 @@ public:
|
||||
void unbind(uint8_t setIndex);
|
||||
|
||||
void commit(VulkanCommandBuffer* commands, VkPipelineLayout pipelineLayout,
|
||||
DescriptorSetMask const& setMask);
|
||||
fvkutils::DescriptorSetMask const& setMask);
|
||||
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSet> createSet(Handle<HwDescriptorSet> handle,
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
|
||||
@@ -93,7 +92,7 @@ private:
|
||||
|
||||
struct {
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
DescriptorSetMask setMask;
|
||||
fvkutils::DescriptorSetMask setMask;
|
||||
DescriptorSetArray boundSets = {};
|
||||
} mLastBoundInfo;
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "vulkan/platform/VulkanPlatformSwapChainImpl.h"
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
#include "vulkan/VulkanDriver.h"
|
||||
#include "vulkan/VulkanUtility.h"
|
||||
#include "vulkan/utils/Helper.h"
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
#include <utils/PrivateImplementation-impl.h>
|
||||
@@ -133,7 +133,7 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
|
||||
const int minor = VK_VERSION_MINOR(deviceProperties.apiVersion);
|
||||
|
||||
const FixedCapacityVector<VkPhysicalDevice> physicalDevices
|
||||
= filament::backend::enumerate(vkEnumeratePhysicalDevices, instance);
|
||||
= fvkutils::enumerate(vkEnumeratePhysicalDevices, instance);
|
||||
|
||||
FVK_LOGI << "Selected physical device '" << deviceProperties.deviceName << "' from "
|
||||
<< physicalDevices.size() << " physical devices. "
|
||||
@@ -179,7 +179,7 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
|
||||
};
|
||||
ExtensionSet exts;
|
||||
FixedCapacityVector<VkExtensionProperties> const availableExts =
|
||||
filament::backend::enumerate(vkEnumerateInstanceExtensionProperties,
|
||||
fvkutils::enumerate(vkEnumerateInstanceExtensionProperties,
|
||||
static_cast<char const*>(nullptr) /* pLayerName */);
|
||||
for (auto const& extProps: availableExts) {
|
||||
utils::CString name { extProps.extensionName };
|
||||
@@ -219,7 +219,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
|
||||
ExtensionSet exts;
|
||||
// Identify supported physical device extensions
|
||||
FixedCapacityVector<VkExtensionProperties> const extensions
|
||||
= filament::backend::enumerate(vkEnumerateDeviceExtensionProperties, device,
|
||||
= fvkutils::enumerate(vkEnumerateDeviceExtensionProperties, device,
|
||||
static_cast<const char*>(nullptr) /* pLayerName */);
|
||||
for (auto const& extension: extensions) {
|
||||
utils::CString name { extension.extensionName };
|
||||
@@ -367,8 +367,8 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
|
||||
.imageViewFormatSwizzle = VK_TRUE,
|
||||
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
|
||||
.mutableComparisonSamplers = VK_TRUE,
|
||||
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
|
||||
};
|
||||
if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
|
||||
chainStruct(&deviceCreateInfo, &portability);
|
||||
@@ -376,7 +376,6 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
|
||||
VkPhysicalDeviceMultiviewFeaturesKHR multiview = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
|
||||
.pNext = nullptr,
|
||||
.multiview = VK_TRUE,
|
||||
.multiviewGeometryShader = VK_FALSE,
|
||||
.multiviewTessellationShader = VK_FALSE,
|
||||
@@ -478,7 +477,7 @@ inline int deviceTypeOrder(VkPhysicalDeviceType deviceType) {
|
||||
VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
||||
VulkanPlatform::Customization::GPUPreference const& gpuPreference) {
|
||||
FixedCapacityVector<VkPhysicalDevice> const physicalDevices =
|
||||
filament::backend::enumerate(vkEnumeratePhysicalDevices, instance);
|
||||
fvkutils::enumerate(vkEnumeratePhysicalDevices, instance);
|
||||
struct DeviceInfo {
|
||||
VkPhysicalDevice device = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceType deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
|
||||
@@ -513,7 +512,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
||||
|
||||
// Does the device support the VK_KHR_swapchain extension?
|
||||
FixedCapacityVector<VkExtensionProperties> const extensions
|
||||
= filament::backend::enumerate(vkEnumerateDeviceExtensionProperties,
|
||||
= fvkutils::enumerate(vkEnumerateDeviceExtensionProperties,
|
||||
candidateDevice, static_cast<char const*>(nullptr) /* pLayerName */);
|
||||
bool supportsSwapchain = false;
|
||||
for (auto const& extension: extensions) {
|
||||
@@ -565,7 +564,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
||||
return device;
|
||||
}
|
||||
|
||||
VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
|
||||
fvkutils::VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
|
||||
VkFormatFeatureFlags const features = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
// The ordering here indicates the preference of choosing depth+stencil format.
|
||||
@@ -584,17 +583,17 @@ VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device) {
|
||||
selectedFormats.push_back(format);
|
||||
}
|
||||
}
|
||||
VkFormatList ret(selectedFormats.size());
|
||||
fvkutils::VkFormatList ret(selectedFormats.size());
|
||||
std::copy(selectedFormats.begin(), selectedFormats.end(), ret.begin());
|
||||
return ret;
|
||||
}
|
||||
|
||||
VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
|
||||
fvkutils::VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
|
||||
std::vector<VkFormat> selectedFormats;
|
||||
VkFormatFeatureFlags const required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
|
||||
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
|
||||
for (VkFormat format : ALL_VK_FORMATS) {
|
||||
if (isVkDepthFormat(format)) {
|
||||
for (VkFormat format : fvkutils::ALL_VK_FORMATS) {
|
||||
if (fvkutils::isVkDepthFormat(format)) {
|
||||
VkFormatProperties props;
|
||||
vkGetPhysicalDeviceFormatProperties(device, format, &props);
|
||||
if ((props.optimalTilingFeatures & required) == required) {
|
||||
@@ -602,7 +601,7 @@ VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
|
||||
}
|
||||
}
|
||||
}
|
||||
VkFormatList ret(selectedFormats.size());
|
||||
fvkutils::VkFormatList ret(selectedFormats.size());
|
||||
std::copy(selectedFormats.begin(), selectedFormats.end(), ret.begin());
|
||||
return ret;
|
||||
}
|
||||
@@ -791,7 +790,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
if (setContains(deviceExts, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
|
||||
// We are on a non-conformant vulkan implementation so we need to ascertain if the features
|
||||
// we need are available.
|
||||
|
||||
chainStruct(&context.mPhysicalDeviceFeatures, &context.mPortabilitySubsetFeatures);
|
||||
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
|
||||
requestPortabilitySubsetImageView2DOn3DImage =
|
||||
|
||||
@@ -199,7 +199,6 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataIm
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||
<< "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;
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include "VulkanPlatformSwapChainImpl.h"
|
||||
|
||||
#include "vulkan/VulkanConstants.h"
|
||||
#include "vulkan/VulkanUtility.h"
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
#include "vulkan/utils/Helper.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
@@ -29,9 +31,8 @@ namespace filament::backend {
|
||||
namespace {
|
||||
|
||||
std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& context,
|
||||
VkDevice device, VkExtent2D extent, VkFormat format,
|
||||
bool isProtected) {
|
||||
bool const isDepth = isVkDepthFormat(format);
|
||||
VkDevice device, VkExtent2D extent, VkFormat format, bool isProtected) {
|
||||
bool const isDepth = fvkutils::isVkDepthFormat(format);
|
||||
// Filament expects blit() to work with any texture, so we almost always set these usage flags
|
||||
// (see copyFrame() and readPixels()).
|
||||
VkImageUsageFlags const blittable =
|
||||
@@ -83,9 +84,9 @@ std::tuple<VkImage, VkDeviceMemory> createImageAndMemory(VulkanContext const& co
|
||||
return std::tuple(image, imageMemory);
|
||||
}
|
||||
|
||||
VkFormat selectDepthFormat(VkFormatList const& depthFormats, bool hasStencil) {
|
||||
VkFormat selectDepthFormat(fvkutils::VkFormatList const& depthFormats, bool hasStencil) {
|
||||
auto const formatItr = std::find_if(depthFormats.begin(), depthFormats.end(),
|
||||
hasStencil ? isVkStencilFormat : isVkDepthFormat);
|
||||
hasStencil ? fvkutils::isVkStencilFormat : fvkutils::isVkDepthFormat);
|
||||
assert_invariant(
|
||||
formatItr != depthFormats.end() && "Cannot find suitable swapchain depth format");
|
||||
return *formatItr;
|
||||
@@ -169,7 +170,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
|
||||
// Find a suitable surface format.
|
||||
FixedCapacityVector<VkSurfaceFormatKHR> const surfaceFormats
|
||||
= enumerate(vkGetPhysicalDeviceSurfaceFormatsKHR, mPhysicalDevice, mSurface);
|
||||
= fvkutils::enumerate(vkGetPhysicalDeviceSurfaceFormatsKHR, mPhysicalDevice, mSurface);
|
||||
std::array<VkFormat, 2> expectedFormats = {
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_FORMAT_B8G8R8A8_UNORM,
|
||||
@@ -193,8 +194,8 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
// Verify that our chosen present mode is supported. In practice all devices support the FIFO
|
||||
// mode, but we check for it anyway for completeness. (and to avoid validation warnings)
|
||||
VkPresentModeKHR const desiredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
FixedCapacityVector<VkPresentModeKHR> presentModes
|
||||
= enumerate(vkGetPhysicalDeviceSurfacePresentModesKHR, mPhysicalDevice, mSurface);
|
||||
FixedCapacityVector<VkPresentModeKHR> presentModes = fvkutils::enumerate(
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR, mPhysicalDevice, mSurface);
|
||||
bool foundSuitablePresentMode = false;
|
||||
for (VkPresentModeKHR mode: presentModes) {
|
||||
if (mode == desiredPresentMode) {
|
||||
@@ -251,7 +252,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() {
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "vkCreateSwapchainKHR failed."
|
||||
<< " error=" << static_cast<int32_t>(result);
|
||||
|
||||
mSwapChainBundle.colors = enumerate(vkGetSwapchainImagesKHR, mDevice, mSwapchain);
|
||||
mSwapChainBundle.colors = fvkutils::enumerate(vkGetSwapchainImagesKHR, mDevice, mSwapchain);
|
||||
mSwapChainBundle.colorFormat = surfaceFormat.format;
|
||||
mSwapChainBundle.depthFormat =
|
||||
selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil);
|
||||
@@ -329,7 +330,7 @@ bool VulkanPlatformSurfaceSwapChain::hasResized() {
|
||||
|| perceivedExtent.height == VULKAN_UNDEFINED_EXTENT) {
|
||||
perceivedExtent = mFallbackExtent;
|
||||
}
|
||||
return !equivalent(mSwapChainBundle.extent, perceivedExtent);
|
||||
return !fvkutils::equivalent(mSwapChainBundle.extent, perceivedExtent);
|
||||
}
|
||||
|
||||
bool VulkanPlatformSurfaceSwapChain::isProtected() {
|
||||
|
||||
+4
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2024 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.
|
||||
@@ -14,17 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VulkanUtility.h"
|
||||
#include "vulkan/utils/Conversion.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include "private/backend/BackendUtils.h"
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
VkFormat getVkFormat(ElementType type, bool normalized, bool integer) {
|
||||
using ElementType = ElementType;
|
||||
@@ -235,12 +231,6 @@ VkFormat getVkFormat(TextureFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
// Converts PixelBufferDescriptor format + type pair into a VkFormat.
|
||||
//
|
||||
// NOTE: This function only returns formats that support VK_FORMAT_FEATURE_BLIT_SRC_BIT as per
|
||||
// "Required Format Support" in the Vulkan specification. These are the only formats that can be
|
||||
// used for format conversion. If the requested format does not support this feature, then
|
||||
// VK_FORMAT_UNDEFINED is returned.
|
||||
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type) {
|
||||
if (type == PixelDataType::USHORT_565) return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
if (type == PixelDataType::UINT_2_10_10_10_REV) return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
@@ -284,10 +274,6 @@ VkFormat getVkFormat(PixelDataFormat format, PixelDataType type) {
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
// Converts an SRGB Vulkan format identifier into its corresponding canonical UNORM format. If the
|
||||
// given format is not an SRGB format, it is returned unmodified. This function is useful when
|
||||
// determining if blit-based conversion is needed, since SRGB is orthogonal to the actual bit layout
|
||||
// of color components.
|
||||
VkFormat getVkFormatLinear(VkFormat format) {
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8_SRGB: return VK_FORMAT_R8_UNORM;
|
||||
@@ -328,8 +314,6 @@ VkFormat getVkFormatLinear(VkFormat format) {
|
||||
return format;
|
||||
}
|
||||
|
||||
// See also FTexture::computeTextureDataSize, which takes a public-facing Texture format rather
|
||||
// than a driver-level Texture format, and can account for a specified byte alignment.
|
||||
uint32_t getBytesPerPixel(TextureFormat format) {
|
||||
return (uint32_t) getFormatSize(format);
|
||||
}
|
||||
@@ -611,48 +595,4 @@ VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool equivalent(const VkRect2D& a, const VkRect2D& b) {
|
||||
// These are all integers so there's no need for an epsilon.
|
||||
return a.extent.width == b.extent.width && a.extent.height == b.extent.height &&
|
||||
a.offset.x == b.offset.x && a.offset.y == b.offset.y;
|
||||
}
|
||||
|
||||
bool equivalent(const VkExtent2D& a, const VkExtent2D& b) {
|
||||
return a.height == b.height && a.width == b.width;
|
||||
}
|
||||
|
||||
VkImageAspectFlags getImageAspect(VkFormat format) {
|
||||
switch (format) {
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
case VK_FORMAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
default:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
bool isVkDepthFormat(VkFormat format) {
|
||||
return (getImageAspect(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isVkStencilFormat(VkFormat format) {
|
||||
return (getImageAspect(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
}
|
||||
|
||||
static uint32_t mostSignificantBit(uint32_t x) { return 1ul << (31ul - utils::clz(x)); }
|
||||
|
||||
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) {
|
||||
if (sampleCount & mask) {
|
||||
return sampleCount;
|
||||
}
|
||||
return mostSignificantBit((sampleCount - 1) & mask);
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace filament::backend::fvkutils
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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_VULKAN_UTILS_CONVERSION_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_CONVERSION_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <private/backend/BackendUtils.h> // for getFormatSize()
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
// Methods for converting Filament types to Vulkan types
|
||||
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
VkFormat getVkFormat(ElementType type, bool normalized, bool integer);
|
||||
VkFormat getVkFormat(TextureFormat format);
|
||||
|
||||
// Converts PixelBufferDescriptor format + type pair into a VkFormat.
|
||||
// NOTE: This function only returns formats that support VK_FORMAT_FEATURE_BLIT_SRC_BIT as per
|
||||
// "Required Format Support" in the Vulkan specification. These are the only formats that can be
|
||||
// used for format conversion. If the requested format does not support this feature, then
|
||||
// VK_FORMAT_UNDEFINED is returned.
|
||||
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type);
|
||||
|
||||
// Converts an SRGB Vulkan format identifier into its corresponding canonical UNORM format. If the
|
||||
// given format is not an SRGB format, it is returned unmodified. This function is useful when
|
||||
// determining if blit-based conversion is needed, since SRGB is orthogonal to the actual bit layout
|
||||
// of color components.
|
||||
VkFormat getVkFormatLinear(VkFormat format);
|
||||
|
||||
// See also FTexture::computeTextureDataSize, which takes a public-facing Texture format rather
|
||||
// than a driver-level Texture format, and can account for a specified byte alignment.
|
||||
uint32_t getBytesPerPixel(TextureFormat format);
|
||||
|
||||
VkCompareOp getCompareOp(SamplerCompareFunc func);
|
||||
VkBlendFactor getBlendFactor(BlendFunction mode);
|
||||
VkCullModeFlags getCullMode(CullingMode mode);
|
||||
VkFrontFace getFrontFace(bool inverseFrontFaces);
|
||||
PixelDataType getComponentType(VkFormat format);
|
||||
uint32_t getComponentCount(VkFormat format);
|
||||
VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]);
|
||||
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags);
|
||||
|
||||
inline VkImageViewType getViewType(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return VK_IMAGE_VIEW_TYPE_3D;
|
||||
default:
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace filament::backend::fvkutils
|
||||
|
||||
#endif// TNT_FILAMENT_BACKEND_VULKAN_UTILS_CONVERSION_H
|
||||
+8
-196
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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
|
||||
*
|
||||
@@ -14,82 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANUTILITY_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANUTILITY_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <utility>
|
||||
// Definitions for common types used across classes.
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
VkFormat getVkFormat(ElementType type, bool normalized, bool integer);
|
||||
VkFormat getVkFormat(TextureFormat format);
|
||||
VkFormat getVkFormat(PixelDataFormat format, PixelDataType type);
|
||||
VkFormat getVkFormatLinear(VkFormat format);
|
||||
uint32_t getBytesPerPixel(TextureFormat format);
|
||||
VkCompareOp getCompareOp(SamplerCompareFunc func);
|
||||
VkBlendFactor getBlendFactor(BlendFunction mode);
|
||||
VkCullModeFlags getCullMode(CullingMode mode);
|
||||
VkFrontFace getFrontFace(bool inverseFrontFaces);
|
||||
PixelDataType getComponentType(VkFormat format);
|
||||
uint32_t getComponentCount(VkFormat format);
|
||||
VkComponentMapping getSwizzleMap(TextureSwizzle const swizzle[4]);
|
||||
VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags);
|
||||
|
||||
bool equivalent(const VkRect2D& a, const VkRect2D& b);
|
||||
bool equivalent(const VkExtent2D& a, const VkExtent2D& b);
|
||||
bool isVkDepthFormat(VkFormat format);
|
||||
bool isVkStencilFormat(VkFormat format);
|
||||
|
||||
VkImageAspectFlags getImageAspect(VkFormat format);
|
||||
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask);
|
||||
|
||||
// Helper function for the vkEnumerateX methods. These methods have the format of
|
||||
// VkResult vkEnumerateX(InputType1 arg1, InputTyp2 arg2, ..., uint32_t* size,
|
||||
// OutputType* output_arg)
|
||||
// Instead of macros and explicitly listing the template params, Variadic Template was also
|
||||
// considered, but because the "variadic" part of the vk methods (i.e. the inputs) are before the
|
||||
// non-variadic parts, this breaks the template type matching logic. Hence, we use a macro approach
|
||||
// here.
|
||||
#define EXPAND_ENUM(...) \
|
||||
uint32_t size = 0; \
|
||||
VkResult result = func(__VA_ARGS__, nullptr); \
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate size error"; \
|
||||
utils::FixedCapacityVector<OutType> ret(size); \
|
||||
result = func(__VA_ARGS__, ret.data()); \
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate error"; \
|
||||
return std::move(ret);
|
||||
|
||||
#define EXPAND_ENUM_NO_ARGS() EXPAND_ENUM(&size)
|
||||
#define EXPAND_ENUM_ARGS(...) EXPAND_ENUM(__VA_ARGS__, &size)
|
||||
|
||||
template <typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(VKAPI_ATTR VkResult (*func)(uint32_t*, OutType*)) {
|
||||
EXPAND_ENUM_NO_ARGS();
|
||||
}
|
||||
|
||||
template <typename InType, typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(
|
||||
VKAPI_ATTR VkResult (*func)(InType, uint32_t*, OutType*), InType inData) {
|
||||
EXPAND_ENUM_ARGS(inData);
|
||||
}
|
||||
|
||||
template <typename InTypeA, typename InTypeB, typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(
|
||||
VKAPI_ATTR VkResult (*func)(InTypeA, InTypeB, uint32_t*, OutType*), InTypeA inDataA,
|
||||
InTypeB inDataB) {
|
||||
EXPAND_ENUM_ARGS(inDataA, inDataB);
|
||||
}
|
||||
|
||||
#undef EXPAND_ENUM
|
||||
#undef EXPAND_ENUM_NO_ARGS
|
||||
#undef EXPAND_ENUM_ARGS
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
// Useful shorthands
|
||||
using VkFormatList = utils::FixedCapacityVector<VkFormat>;
|
||||
@@ -406,128 +341,6 @@ constexpr VkFormat ALL_VK_FORMATS[] = {
|
||||
VK_FORMAT_R16G16_S10_5_NV,
|
||||
};
|
||||
|
||||
// An Array that will be statically fixed in capacity, but the "size" (as in user added elements) is
|
||||
// variable. Note that this class is movable.
|
||||
template<typename T, uint16_t CAPACITY>
|
||||
class CappedArray {
|
||||
private:
|
||||
using FixedSizeArray = std::array<T, CAPACITY>;
|
||||
|
||||
public:
|
||||
using const_iterator = typename FixedSizeArray::const_iterator;
|
||||
using iterator = typename FixedSizeArray::iterator;
|
||||
|
||||
CappedArray() = default;
|
||||
|
||||
// Delete copy constructor/assignment.
|
||||
CappedArray(CappedArray const& rhs) = delete;
|
||||
CappedArray& operator=(CappedArray& rhs) = delete;
|
||||
|
||||
CappedArray(CappedArray&& rhs) noexcept {
|
||||
this->swap(rhs);
|
||||
}
|
||||
|
||||
CappedArray& operator=(CappedArray&& rhs) noexcept {
|
||||
this->swap(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ~CappedArray() {
|
||||
clear();
|
||||
}
|
||||
|
||||
inline const_iterator begin() const {
|
||||
if (mInd == 0) {
|
||||
return mArray.cend();
|
||||
}
|
||||
return mArray.cbegin();
|
||||
}
|
||||
|
||||
inline const_iterator end() const {
|
||||
if (mInd > 0 && mInd < CAPACITY) {
|
||||
return mArray.begin() + mInd;
|
||||
}
|
||||
return mArray.cend();
|
||||
}
|
||||
|
||||
inline iterator begin() {
|
||||
if (mInd == 0) {
|
||||
return mArray.end();
|
||||
}
|
||||
return mArray.begin();
|
||||
}
|
||||
|
||||
inline iterator end() {
|
||||
if (mInd > 0 && mInd < CAPACITY) {
|
||||
return mArray.begin() + mInd;
|
||||
}
|
||||
return mArray.end();
|
||||
}
|
||||
|
||||
inline T back() {
|
||||
assert_invariant(mInd > 0);
|
||||
return *(mArray.begin() + mInd);
|
||||
}
|
||||
|
||||
inline void pop_back() {
|
||||
assert_invariant(mInd > 0);
|
||||
mInd--;
|
||||
}
|
||||
|
||||
inline const_iterator find(T item) {
|
||||
return std::find(begin(), end(), item);
|
||||
}
|
||||
|
||||
inline void insert(T item) {
|
||||
assert_invariant(mInd < CAPACITY);
|
||||
mArray[mInd++] = item;
|
||||
}
|
||||
|
||||
inline void erase(T item) {
|
||||
PANIC_PRECONDITION("CappedArray::erase should not be called");
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
if (mInd == 0) {
|
||||
return;
|
||||
}
|
||||
mInd = 0;
|
||||
}
|
||||
|
||||
inline T& operator[](uint16_t ind) {
|
||||
return mArray[ind];
|
||||
}
|
||||
|
||||
inline T const& operator[](uint16_t ind) const {
|
||||
return mArray[ind];
|
||||
}
|
||||
|
||||
inline uint32_t size() const {
|
||||
return mInd;
|
||||
}
|
||||
|
||||
T* data() {
|
||||
return mArray.data();
|
||||
}
|
||||
|
||||
T const* data() const {
|
||||
return mArray.data();
|
||||
}
|
||||
|
||||
bool operator==(CappedArray const& b) const {
|
||||
return this->mArray == b.mArray;
|
||||
}
|
||||
|
||||
private:
|
||||
void swap(CappedArray& rhs) {
|
||||
std::swap(mArray, rhs.mArray);
|
||||
std::swap(mInd, rhs.mInd);
|
||||
}
|
||||
|
||||
FixedSizeArray mArray;
|
||||
uint32_t mInd = 0;
|
||||
};
|
||||
|
||||
using UniformBufferBitmask = utils::bitset64;
|
||||
using SamplerBitmask = utils::bitset64;
|
||||
|
||||
@@ -550,7 +363,6 @@ static constexpr uint8_t getFragmentStageShift() noexcept {
|
||||
// We have at most 4 descriptor sets. This is to indicate which ones are active.
|
||||
using DescriptorSetMask = utils::bitset8;
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKANUTILITY_H
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_DEFINITIONS_H
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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_VULKAN_UTILS_HELPER_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_HELPER_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <bluevk/BlueVK.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
inline bool equivalent(const VkRect2D& a, const VkRect2D& b) {
|
||||
// These are all integers so there's no need for an epsilon.
|
||||
return a.extent.width == b.extent.width && a.extent.height == b.extent.height &&
|
||||
a.offset.x == b.offset.x && a.offset.y == b.offset.y;
|
||||
}
|
||||
|
||||
inline bool equivalent(const VkExtent2D& a, const VkExtent2D& b) {
|
||||
return a.height == b.height && a.width == b.width;
|
||||
}
|
||||
|
||||
// Helper function for the vkEnumerateX methods. These methods have the format of
|
||||
// VkResult vkEnumerateX(InputType1 arg1, InputTyp2 arg2, ..., uint32_t* size,
|
||||
// OutputType* output_arg)
|
||||
// Instead of macros and explicitly listing the template params, Variadic Template was also
|
||||
// considered, but because the "variadic" part of the vk methods (i.e. the inputs) are before the
|
||||
// non-variadic parts, this breaks the template type matching logic. Hence, we use a macro approach
|
||||
// here.
|
||||
#define EXPAND_ENUM(...) \
|
||||
uint32_t size = 0; \
|
||||
VkResult result = func(__VA_ARGS__, nullptr); \
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate size error"; \
|
||||
utils::FixedCapacityVector<OutType> ret(size); \
|
||||
result = func(__VA_ARGS__, ret.data()); \
|
||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "enumerate error"; \
|
||||
return std::move(ret);
|
||||
|
||||
#define EXPAND_ENUM_NO_ARGS() EXPAND_ENUM(&size)
|
||||
#define EXPAND_ENUM_ARGS(...) EXPAND_ENUM(__VA_ARGS__, &size)
|
||||
|
||||
template <typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(VKAPI_ATTR VkResult (*func)(uint32_t*, OutType*)) {
|
||||
EXPAND_ENUM_NO_ARGS();
|
||||
}
|
||||
|
||||
template <typename InType, typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(
|
||||
VKAPI_ATTR VkResult (*func)(InType, uint32_t*, OutType*), InType inData) {
|
||||
EXPAND_ENUM_ARGS(inData);
|
||||
}
|
||||
|
||||
template <typename InTypeA, typename InTypeB, typename OutType>
|
||||
utils::FixedCapacityVector<OutType> enumerate(
|
||||
VKAPI_ATTR VkResult (*func)(InTypeA, InTypeB, uint32_t*, OutType*), InTypeA inDataA,
|
||||
InTypeB inDataB) {
|
||||
EXPAND_ENUM_ARGS(inDataA, inDataB);
|
||||
}
|
||||
|
||||
#undef EXPAND_ENUM
|
||||
#undef EXPAND_ENUM_NO_ARGS
|
||||
#undef EXPAND_ENUM_ARGS
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_HELPER_H
|
||||
+38
-4
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VulkanImageUtility.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
|
||||
#include "VulkanTexture.h"
|
||||
#include "vulkan/VulkanTexture.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/algorithm.h>
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
using namespace bluevk;
|
||||
|
||||
namespace filament::backend::imgutil {
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -159,7 +159,41 @@ bool transitionLayout(VkCommandBuffer cmdbuffer,
|
||||
return true;
|
||||
}
|
||||
|
||||
}// namespace filament::backend
|
||||
VkImageAspectFlags getImageAspect(VkFormat format) {
|
||||
switch (format) {
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
case VK_FORMAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
default:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
bool isVkDepthFormat(VkFormat format) {
|
||||
return (getImageAspect(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isVkStencilFormat(VkFormat format) {
|
||||
return (getImageAspect(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
|
||||
}
|
||||
|
||||
static uint32_t mostSignificantBit(uint32_t x) { return 1ul << (31ul - utils::clz(x)); }
|
||||
|
||||
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) {
|
||||
if (sampleCount & mask) {
|
||||
return sampleCount;
|
||||
}
|
||||
return mostSignificantBit((sampleCount - 1) & mask);
|
||||
}
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange& b) {
|
||||
if (a.aspectMask < b.aspectMask) return true;
|
||||
+13
-21
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
@@ -59,22 +59,7 @@ struct VulkanLayoutTransition {
|
||||
VkImageSubresourceRange subresources;
|
||||
};
|
||||
|
||||
namespace imgutil {
|
||||
|
||||
inline VkImageViewType getViewType(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return VK_IMAGE_VIEW_TYPE_3D;
|
||||
default:
|
||||
return VK_IMAGE_VIEW_TYPE_2D;
|
||||
}
|
||||
}
|
||||
namespace fvkutils {
|
||||
|
||||
constexpr inline VkImageLayout getVkLayout(VulkanLayout layout) {
|
||||
switch (layout) {
|
||||
@@ -109,7 +94,15 @@ constexpr inline VkImageLayout getVkLayout(VulkanLayout layout) {
|
||||
// no transition necessary).
|
||||
bool transitionLayout(VkCommandBuffer cmdbuffer, VulkanLayoutTransition transition);
|
||||
|
||||
} // namespace imgutil
|
||||
bool isVkDepthFormat(VkFormat format);
|
||||
|
||||
bool isVkStencilFormat(VkFormat format);
|
||||
|
||||
VkImageAspectFlags getImageAspect(VkFormat format);
|
||||
|
||||
uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask);
|
||||
|
||||
} // namespace fvkutils
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -117,5 +110,4 @@ bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange&
|
||||
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::VulkanLayout& layout);
|
||||
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKANIMAGEUTILITY_H
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_IMAGE_H
|
||||
+6
-64
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VulkanSpirvUtils.h"
|
||||
#include "vulkan/utils/Spirv.h"
|
||||
|
||||
#include <utils/compiler.h> // UTILS_UNUSED_IN_RELEASE, UTILS_FALLTHROUGH
|
||||
#include <utils/debug.h> // assert_invariant
|
||||
@@ -22,12 +22,11 @@
|
||||
|
||||
#include <spirv/unified1/spirv.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -99,7 +98,7 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
uint32_t const* data = (uint32_t*) blob.data();
|
||||
uint32_t* outputData = output.data();
|
||||
|
||||
std::memcpy(&outputData[0], &data[0], HEADER_SIZE * 4);
|
||||
memcpy(&outputData[0], &data[0], HEADER_SIZE * 4);
|
||||
size_t outputCursor = HEADER_SIZE;
|
||||
|
||||
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
|
||||
@@ -147,61 +146,4 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
output.resize(outputCursor);
|
||||
}
|
||||
|
||||
std::tuple<uint32_t,uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob) {
|
||||
std::unordered_map<uint32_t, uint32_t> targetToSet, targetToBinding;
|
||||
|
||||
constexpr size_t HEADER_SIZE = 5;
|
||||
|
||||
size_t const dataSize = blob.size() / 4;
|
||||
uint32_t const* data = (uint32_t*) blob.data();
|
||||
|
||||
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;
|
||||
|
||||
switch(op) {
|
||||
case spv::Op::OpDecorate: {
|
||||
if (data[cursor + 2] == spv::Decoration::DecorationDescriptorSet) {
|
||||
uint32_t const targetVar = data[cursor + 1];
|
||||
uint32_t const setId = data[cursor + 3];
|
||||
targetToSet[targetVar] = setId;
|
||||
} else if (data[cursor + 2] == spv::Decoration::DecorationBinding) {
|
||||
uint32_t const targetVar = data[cursor + 1];
|
||||
uint32_t const binding = data[cursor + 3];
|
||||
targetToBinding[targetVar] = binding;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cursor += wordCount;
|
||||
}
|
||||
|
||||
constexpr uint32_t UBO = 0;
|
||||
constexpr uint32_t SAMPLER = 1;
|
||||
constexpr uint32_t IATTACHMENT = 2;
|
||||
uint32_t ubo = 0, sampler = 0, inputAttachment = 0;
|
||||
|
||||
for (auto const& [target, setId]: targetToSet) {
|
||||
uint32_t const binding = targetToBinding[target];
|
||||
assert_invariant(binding < 32);
|
||||
switch(setId) {
|
||||
case UBO:
|
||||
ubo |= (1 << binding);
|
||||
break;
|
||||
case SAMPLER:
|
||||
sampler |= (1 << binding);
|
||||
break;
|
||||
case IATTACHMENT:
|
||||
inputAttachment |= (1 << binding);
|
||||
break;
|
||||
default:
|
||||
PANIC_POSTCONDITION("unexpected %d", (int) setId);
|
||||
}
|
||||
}
|
||||
return {ubo, sampler, inputAttachment};
|
||||
}
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace filament::backend::fvkutils
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
* Copyright (C) 2024 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.
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
|
||||
#ifndef TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
|
||||
|
||||
#include <backend/Program.h>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
using SpecConstantValue = Program::SpecializationConstant::Type;
|
||||
|
||||
@@ -44,8 +44,9 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
std::vector<uint32_t>& output);
|
||||
|
||||
// bindings for UBO, samplers, input attachment
|
||||
std::tuple<uint32_t, uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob);
|
||||
// This is no longer needed after the descriptor set refactor, but the code is good for reference.
|
||||
// std::tuple<uint32_t, uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob);
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKANSPIRVUTILS_H
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_SPIRV_H
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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_VULKAN_UTILS_STATICVECTOR_H
|
||||
#define TNT_FILAMENT_BACKEND_VULKAN_UTILS_STATICVECTOR_H
|
||||
|
||||
// An Array that will be statically fixed in capacity, but the "size" (as in user added elements) is
|
||||
// variable. Note that this class is movable.
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
template<typename T, uint16_t CAPACITY>
|
||||
class StaticVector {
|
||||
private:
|
||||
using FixedSizeArray = std::array<T, CAPACITY>;
|
||||
|
||||
static_assert(CAPACITY <= (1LL << (8 * sizeof(uint16_t))));
|
||||
|
||||
public:
|
||||
using const_iterator = typename FixedSizeArray::const_iterator;
|
||||
using iterator = typename FixedSizeArray::iterator;
|
||||
|
||||
StaticVector() = default;
|
||||
|
||||
// Delete copy constructor/assignment.
|
||||
StaticVector(StaticVector const& rhs) = delete;
|
||||
StaticVector& operator=(StaticVector& rhs) = delete;
|
||||
|
||||
StaticVector(StaticVector&& rhs) noexcept {
|
||||
std::swap(mSize, rhs.mSize);
|
||||
std::swap(mArray, rhs.mArray);
|
||||
}
|
||||
|
||||
StaticVector& operator=(StaticVector&& rhs) noexcept {
|
||||
std::swap(mSize, rhs.mSize);
|
||||
std::swap(mArray, rhs.mArray);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ~StaticVector() {
|
||||
clear();
|
||||
}
|
||||
|
||||
inline const_iterator begin() const {
|
||||
return mArray.cbegin();
|
||||
}
|
||||
|
||||
inline const_iterator end() const {
|
||||
assert_invariant(mSize <= CAPACITY);
|
||||
return mArray.begin() + mSize;
|
||||
}
|
||||
|
||||
inline iterator begin() {
|
||||
return mArray.begin();
|
||||
}
|
||||
|
||||
inline iterator end() {
|
||||
assert_invariant(mSize <= CAPACITY);
|
||||
return mArray.begin() + mSize;
|
||||
}
|
||||
|
||||
inline T back() {
|
||||
assert_invariant(mSize > 0);
|
||||
return *(mArray.begin() + mSize);
|
||||
}
|
||||
|
||||
inline void pop_back() {
|
||||
assert_invariant(mSize > 0);
|
||||
mSize--;
|
||||
}
|
||||
|
||||
inline const_iterator find(T item) {
|
||||
return std::find(begin(), end(), item);
|
||||
}
|
||||
|
||||
inline void push_back(T item) {
|
||||
assert_invariant(mSize < CAPACITY);
|
||||
mArray[mSize++] = item;
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
inline T& operator[](size_t index) {
|
||||
assert_invariant(index < mSize);
|
||||
return mArray[index];
|
||||
}
|
||||
|
||||
inline T const& operator[](size_t index) const {
|
||||
return mArray[index];
|
||||
}
|
||||
|
||||
inline uint16_t size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
T* data() {
|
||||
return mArray.data();
|
||||
}
|
||||
|
||||
T const* data() const {
|
||||
return mArray.data();
|
||||
}
|
||||
|
||||
bool operator==(StaticVector const& b) const {
|
||||
return this->mArray == b.mArray && this->mSize == b.mSize;
|
||||
}
|
||||
|
||||
private:
|
||||
FixedSizeArray mArray;
|
||||
uint16_t mSize = 0;
|
||||
};
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_VULKAN_UTILS_STATICVECTOR_H
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_ENGINE_H
|
||||
#define TNT_FILAMENT_ENGINE_H
|
||||
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -32,6 +33,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
namespace utils {
|
||||
class Entity;
|
||||
class EntityManager;
|
||||
@@ -40,6 +42,10 @@ class JobSystem;
|
||||
|
||||
namespace filament {
|
||||
|
||||
namespace backend {
|
||||
class Driver;
|
||||
} // backend
|
||||
|
||||
class BufferObject;
|
||||
class Camera;
|
||||
class ColorGrading;
|
||||
@@ -183,6 +189,7 @@ public:
|
||||
using DriverConfig = backend::Platform::DriverConfig;
|
||||
using FeatureLevel = backend::FeatureLevel;
|
||||
using StereoscopicType = backend::StereoscopicType;
|
||||
using Driver = backend::Driver;
|
||||
|
||||
/**
|
||||
* Config is used to define the memory footprint used by the engine, such as the
|
||||
@@ -582,6 +589,11 @@ public:
|
||||
static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @return the Driver instance used by this Engine.
|
||||
* @see OpenGLPlatform
|
||||
*/
|
||||
backend::Driver const* UTILS_NONNULL getDriver() const noexcept;
|
||||
|
||||
/**
|
||||
* Destroy the Engine instance and all associated resources.
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(StringLiteral name, T const& value) {
|
||||
void setParameter(StringLiteral const name, T const& value) {
|
||||
setParameter<T>(name.data, name.size, value);
|
||||
}
|
||||
|
||||
@@ -148,14 +148,14 @@ public:
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) {
|
||||
void setParameter(StringLiteral const name, const T* UTILS_NONNULL values, size_t const count) {
|
||||
setParameter<T>(name.data, name.size, values, count);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
void setParameter(const char* UTILS_NONNULL name,
|
||||
const T* UTILS_NONNULL values, size_t count) {
|
||||
const T* UTILS_NONNULL values, size_t const count) {
|
||||
setParameter<T>(name, strlen(name), values, count);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
void setParameter(StringLiteral name,
|
||||
void setParameter(StringLiteral const name,
|
||||
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
|
||||
setParameter(name.data, name.size, texture, sampler);
|
||||
}
|
||||
@@ -202,12 +202,12 @@ public:
|
||||
RgbType type, math::float3 color);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
void setParameter(StringLiteral name, RgbType type, math::float3 color) {
|
||||
void setParameter(StringLiteral const name, RgbType const type, math::float3 const color) {
|
||||
setParameter(name.data, name.size, type, color);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) {
|
||||
void setParameter(const char* UTILS_NONNULL name, RgbType const type, math::float3 const color) {
|
||||
setParameter(name, strlen(name), type, color);
|
||||
}
|
||||
|
||||
@@ -226,12 +226,12 @@ public:
|
||||
RgbaType type, math::float4 color);
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
void setParameter(StringLiteral name, RgbaType type, math::float4 color) {
|
||||
void setParameter(StringLiteral const name, RgbaType const type, math::float4 const color) {
|
||||
setParameter(name.data, name.size, type, color);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) {
|
||||
void setParameter(const char* UTILS_NONNULL name, RgbaType const type, math::float4 const color) {
|
||||
setParameter(name, strlen(name), type, color);
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ public:
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
T getParameter(StringLiteral name) const {
|
||||
T getParameter(StringLiteral const name) const {
|
||||
return getParameter<T>(name.data, name.size);
|
||||
}
|
||||
|
||||
@@ -376,11 +376,22 @@ public:
|
||||
*/
|
||||
void setCullingMode(CullingMode culling) noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material separately for the
|
||||
* color and shadow passes
|
||||
*/
|
||||
void setCullingMode(CullingMode colorPassCullingMode, CullingMode shadowPassCullingMode) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the face culling mode.
|
||||
*/
|
||||
CullingMode getCullingMode() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the face culling mode for the shadow passes.
|
||||
*/
|
||||
CullingMode getShadowCullingMode() const noexcept;
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*/
|
||||
|
||||
@@ -141,6 +141,11 @@ public:
|
||||
*/
|
||||
void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
|
||||
|
||||
/**
|
||||
* Remove all entities to the Scene.
|
||||
*/
|
||||
void removeAllEntities() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the total number of Entities in the Scene, whether alive or not.
|
||||
* @return Total number of Entities in the Scene.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
@@ -70,7 +71,7 @@ class UTILS_PUBLIC Texture : public FilamentAPI {
|
||||
struct BuilderDetails;
|
||||
|
||||
public:
|
||||
static constexpr const size_t BASE_LEVEL = 0;
|
||||
static constexpr size_t BASE_LEVEL = 0;
|
||||
|
||||
//! Face offsets for all faces of a cubemap
|
||||
struct FaceOffsets;
|
||||
@@ -84,14 +85,16 @@ public:
|
||||
using CompressedType = backend::CompressedPixelDataType; //!< Compressed pixel data format
|
||||
using Usage = backend::TextureUsage; //!< Usage affects texel layout
|
||||
using Swizzle = backend::TextureSwizzle; //!< Texture swizzle
|
||||
using ExternalImageHandle = backend::Platform::ExternalImageHandle;
|
||||
using ExternalImageHandleRef = backend::Platform::ExternalImageHandleRef;
|
||||
|
||||
/** @return whether a backend supports a particular format. */
|
||||
/** @return Whether a backend supports a particular format. */
|
||||
static bool isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept;
|
||||
|
||||
/** @return whether this backend supports protected textures. */
|
||||
/** @return Whether this backend supports protected textures. */
|
||||
static bool isProtectedTexturesSupported(Engine& engine) noexcept;
|
||||
|
||||
/** @return whether a backend supports texture swizzling. */
|
||||
/** @return Whether a backend supports texture swizzling. */
|
||||
static bool isTextureSwizzleSupported(Engine& engine) noexcept;
|
||||
|
||||
static size_t computeTextureDataSize(Format format, Type type,
|
||||
@@ -217,6 +220,18 @@ public:
|
||||
*/
|
||||
Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept;
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
*
|
||||
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Builder& external() noexcept;
|
||||
|
||||
/**
|
||||
* Creates the Texture object and returns a pointer to it.
|
||||
*
|
||||
@@ -261,18 +276,6 @@ public:
|
||||
*/
|
||||
Builder& import(intptr_t id) noexcept;
|
||||
|
||||
/**
|
||||
* Creates an external texture. The content must be set using setExternalImage().
|
||||
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
|
||||
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
|
||||
* validated.
|
||||
*
|
||||
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Builder& external() noexcept;
|
||||
|
||||
private:
|
||||
friend class FTexture;
|
||||
};
|
||||
@@ -359,7 +362,7 @@ public:
|
||||
* uint32_t width, uint32_t height, uint32_t depth,
|
||||
* PixelBufferDescriptor&& buffer)
|
||||
*/
|
||||
inline void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
|
||||
void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
|
||||
setImage(engine, level, 0, 0, 0,
|
||||
uint32_t(getWidth(level)), uint32_t(getHeight(level)), 1, std::move(buffer));
|
||||
}
|
||||
@@ -372,7 +375,7 @@ public:
|
||||
* uint32_t width, uint32_t height, uint32_t depth,
|
||||
* PixelBufferDescriptor&& buffer)
|
||||
*/
|
||||
inline void setImage(Engine& engine, size_t level,
|
||||
void setImage(Engine& engine, size_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
PixelBufferDescriptor&& buffer) const {
|
||||
setImage(engine, level, xoffset, yoffset, 0, width, height, 1, std::move(buffer));
|
||||
@@ -406,6 +409,26 @@ public:
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically, the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
* There are many restrictions when using an external image as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
* - only nearest or linear filtering is supported
|
||||
* - the size and format of the texture is defined by the external image
|
||||
* - only the CLAMP_TO_EDGE wrap mode is supported
|
||||
*
|
||||
* @param engine Engine this texture is associated to.
|
||||
* @param image An opaque handle to a platform specific image. It must be created using Platform
|
||||
* specific APIs. For example PlatformEGL::createExternalImage(EGLImageKHR eglImage)
|
||||
*
|
||||
* @see PlatformEGL::createExternalImage
|
||||
* @see PlatformEGLAndroid::createExternalImage
|
||||
* @see PlatformCocoaGL::createExternalImage
|
||||
* @see PlatformCocoaTouchGL::createExternalImage
|
||||
*/
|
||||
void setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external image to associate with this Texture. Typically, the external
|
||||
* image is OS specific, and can be a video or camera frame.
|
||||
@@ -428,7 +451,9 @@ public:
|
||||
*
|
||||
* @see Builder::sampler()
|
||||
*
|
||||
* @deprecated Instead, use setExternalImage(Engine& engine, ExternalImageHandleRef image)
|
||||
*/
|
||||
UTILS_DEPRECATED
|
||||
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
|
||||
|
||||
/**
|
||||
@@ -463,7 +488,7 @@ public:
|
||||
void setExternalImage(Engine& engine, void* UTILS_NONNULL image, size_t plane) noexcept;
|
||||
|
||||
/**
|
||||
* Specify the external stream to associate with this Texture. Typically the external
|
||||
* Specify the external stream to associate with this Texture. Typically, the external
|
||||
* stream is OS specific, and can be a video or camera stream.
|
||||
* There are many restrictions when using an external stream as a texture, such as:
|
||||
* - only the level of detail (lod) 0 can be specified
|
||||
@@ -474,7 +499,7 @@ public:
|
||||
* @param stream A Stream object
|
||||
*
|
||||
* @attention \p engine must be the instance passed to Builder::build()
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL or it has no effect
|
||||
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL, or it has no effect
|
||||
*
|
||||
* @see Builder::sampler(), Stream
|
||||
*
|
||||
@@ -522,9 +547,9 @@ public:
|
||||
* @param buffer Client-side buffer containing the images to set.
|
||||
* @param faceOffsets Offsets in bytes into \p buffer for all six images. The offsets
|
||||
* are specified in the following order: +x, -x, +y, -y, +z, -z
|
||||
* @param options Optional parameter to controlling user-specified quality and options.
|
||||
* @param options Optional parameter controlling user-specified quality and options.
|
||||
*
|
||||
* @exception utils::PreConditionPanic if the source data constraints are not respected.
|
||||
* @exception utils::PreConditionPanic If the source data constraints are not respected.
|
||||
*
|
||||
*/
|
||||
void generatePrefilterMipmap(Engine& engine,
|
||||
|
||||
@@ -40,12 +40,16 @@ void Culler::intersects(
|
||||
float4 const * const UTILS_RESTRICT planes = frustum.mPlanes;
|
||||
|
||||
count = round(count);
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize_width(FILAMENT_CULLER_VECTORIZE_HINT)
|
||||
#endif
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
int visible = ~0;
|
||||
float4 const sphere(b[i]);
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop unroll(full)
|
||||
#endif
|
||||
for (size_t j = 0; j < 6; j++) {
|
||||
// clang doesn't seem to generate vector * scalar instructions, which leads
|
||||
// to increased register pressure and stack spills
|
||||
@@ -69,11 +73,15 @@ void Culler::intersects(
|
||||
float4 const * UTILS_RESTRICT const planes = frustum.mPlanes;
|
||||
|
||||
count = round(count);
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize_width(FILAMENT_CULLER_VECTORIZE_HINT)
|
||||
#endif
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
int visible = ~0;
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop unroll(full)
|
||||
#endif
|
||||
for (size_t j = 0; j < 6; j++) {
|
||||
// clang doesn't seem to generate vector * scalar instructions, which leads
|
||||
// to increased register pressure and stack spills
|
||||
|
||||
@@ -68,6 +68,10 @@ Engine* Engine::getEngine(void* token) {
|
||||
}
|
||||
#endif
|
||||
|
||||
Driver const* Engine::getDriver() const noexcept {
|
||||
return std::addressof(downcast(this)->getDriver());
|
||||
}
|
||||
|
||||
void Engine::destroy(Engine** pEngine) {
|
||||
if (pEngine) {
|
||||
Engine* engine = *pEngine;
|
||||
|
||||
@@ -395,7 +395,9 @@ bool Froxelizer::update() noexcept {
|
||||
const float linearizer = std::log2(zLightFar / zLightNear) / float(std::max(1u, mFroxelCountZ - 1u));
|
||||
// for a strange reason when, vectorizing this loop, clang does some math in double
|
||||
// and generates conversions to float. not worth it for so little iterations.
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize(disable) unroll(disable)
|
||||
#endif
|
||||
for (ssize_t i = 1, n = mFroxelCountZ; i <= n; i++) {
|
||||
mDistancesZ[i] = zLightFar * std::exp2(float(i - n) * linearizer);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,26 @@
|
||||
#include <filament/MaterialInstance.h>
|
||||
|
||||
#include "details/Material.h"
|
||||
#include "details/MaterialInstance.h"
|
||||
|
||||
#include <filament/Color.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/mat3.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -85,7 +105,7 @@ void MaterialInstance::setParameter(const char* name, size_t nameLength, T const
|
||||
template<>
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool const& v) {
|
||||
// this kills tail-call optimization
|
||||
setParameter(name, nameLength, (uint32_t)v);
|
||||
setParameter(name, nameLength, uint32_t(v));
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -125,8 +145,8 @@ template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char*
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename>
|
||||
void MaterialInstance::setParameter(const char* name, size_t nameLength, const T* value, size_t count) {
|
||||
downcast(this)->setParameterImpl({ name, nameLength }, value, count);
|
||||
void MaterialInstance::setParameter(const char* name, size_t nameLength, const T* values, size_t count) {
|
||||
downcast(this)->setParameterImpl({ name, nameLength }, values, count);
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -272,6 +292,11 @@ void MaterialInstance::setCullingMode(CullingMode const culling) noexcept {
|
||||
downcast(this)->setCullingMode(culling);
|
||||
}
|
||||
|
||||
void MaterialInstance::setCullingMode(CullingMode const colorPassCullingMode,
|
||||
CullingMode const shadowPassCullingMode) noexcept {
|
||||
downcast(this)->setCullingMode(colorPassCullingMode, shadowPassCullingMode);
|
||||
}
|
||||
|
||||
void MaterialInstance::setColorWrite(bool const enable) noexcept {
|
||||
downcast(this)->setColorWrite(enable);
|
||||
}
|
||||
@@ -353,6 +378,10 @@ CullingMode MaterialInstance::getCullingMode() const noexcept {
|
||||
return downcast(this)->getCullingMode();
|
||||
}
|
||||
|
||||
CullingMode MaterialInstance::getShadowCullingMode() const noexcept {
|
||||
return downcast(this)->getShadowCullingMode();
|
||||
}
|
||||
|
||||
bool MaterialInstance::isColorWriteEnabled() const noexcept {
|
||||
return downcast(this)->isColorWriteEnabled();
|
||||
}
|
||||
|
||||
@@ -2661,7 +2661,7 @@ void PostProcessManager::TaaJitterCamera(
|
||||
// update projection matrix
|
||||
inoutCameraInfo->projection[2].xy -= jitterInClipSpace;
|
||||
// VERTEX_DOMAIN_DEVICE doesn't apply the projection, but it still needs this
|
||||
// clip transform, so we apply it separately (see main.vs)
|
||||
// clip transform, so we apply it separately (see surface_main.vs)
|
||||
inoutCameraInfo->clipTransform.zw -= jitterInClipSpace;
|
||||
}
|
||||
|
||||
|
||||
@@ -807,7 +807,13 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
|
||||
cmd.key &= ~Z_BUCKET_MASK;
|
||||
cmd.key |= makeField(distanceBits >> 22u, Z_BUCKET_MASK, Z_BUCKET_SHIFT);
|
||||
}
|
||||
|
||||
*curr = cmd;
|
||||
// cancel command if both front and back faces are culled
|
||||
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
|
||||
|
||||
} else if constexpr (isDepthPass) {
|
||||
const CullingMode cullingMode = hasShadowing ? mi->getShadowCullingMode() : mi->getCullingMode();
|
||||
const RasterState rs = ma->getRasterState();
|
||||
const TransparencyMode mode = mi->getTransparencyMode();
|
||||
const BlendingMode blendingMode = ma->getBlendingMode();
|
||||
@@ -816,7 +822,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
|
||||
const bool isPickingVariant = Variant::isPickingVariant(variant);
|
||||
|
||||
cmd.key |= mi->getSortingKey(); // already all set-up for direct or'ing
|
||||
cmd.info.rasterState.culling = mi->getCullingMode();
|
||||
cmd.info.rasterState.culling = cullingMode;
|
||||
|
||||
// FIXME: should writeDepthForShadowCasters take precedence over mi->getDepthWrite()?
|
||||
cmd.info.rasterState.depthWrite = (1 // only keep bit 0
|
||||
@@ -825,11 +831,12 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
|
||||
& !(filterTranslucentObjects & translucent)
|
||||
& !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage))
|
||||
| writeDepthForShadowCasters;
|
||||
|
||||
*curr = cmd;
|
||||
// cancel command if both front and back faces are culled
|
||||
curr->key |= select(cullingMode == CullingMode::FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
*curr = cmd;
|
||||
// cancel command if both front and back faces are culled
|
||||
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
|
||||
++curr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ void Scene::removeEntities(const Entity* entities, size_t const count) {
|
||||
downcast(this)->removeEntities(entities, count);
|
||||
}
|
||||
|
||||
void Scene::removeAllEntities() noexcept {
|
||||
downcast(this)->removeAllEntities();
|
||||
}
|
||||
|
||||
size_t Scene::getEntityCount() const noexcept {
|
||||
return downcast(this)->getEntityCount();
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
|
||||
|
||||
// The model matrix below is in fact inverted to get the view matrix and passed to the
|
||||
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
|
||||
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
// (see surface_depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b)));
|
||||
mCamera->setCustomProjection(mat4(Mn * F * WLMp), znear, zfar);
|
||||
|
||||
@@ -315,7 +315,7 @@ ShadowMap::ShaderParameters ShadowMap::updatePunctual(
|
||||
|
||||
// The model matrix below is in fact inverted to get the view matrix and passed to the
|
||||
// shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric.
|
||||
// (see depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
// (see surface_depth_main.fs). Note that in the case of VSM, 'b' below is identity.
|
||||
mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b)));
|
||||
mCamera->setCustomProjection(highPrecisionMultiplyd(Mn, Mp), nearPlane, farPlane);
|
||||
|
||||
@@ -719,7 +719,7 @@ mat4f ShadowMap::computeVsmLightSpaceMatrix(const mat4f& lightSpacePcf,
|
||||
// For VSM, we want to leave the z coordinate in linear light-space, normalized between [0, 1],
|
||||
// i.e. remapping [near, far] to [0, 1].
|
||||
// When sampling a VSM shadow map, the shader follows suit, and doesn't divide by w for the z
|
||||
// coordinate. See shadowing.fs.
|
||||
// coordinate. See surface_shadowing.fs.
|
||||
// compute z' = -(Mv * position).z / (far - near) - (near / (far - near))
|
||||
const float scale = 1.0f / (zfar - znear);
|
||||
mat4f lightSpaceVsm{ lightSpacePcf };
|
||||
|
||||
@@ -58,6 +58,10 @@ void Texture::setImage(Engine& engine, size_t const level,
|
||||
downcast(this)->setImage(downcast(engine), level, std::move(buffer), faceOffsets);
|
||||
}
|
||||
|
||||
void Texture::setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept {
|
||||
downcast(this)->setExternalImage(downcast(engine), image);
|
||||
}
|
||||
|
||||
void Texture::setExternalImage(Engine& engine, void* image) noexcept {
|
||||
downcast(this)->setExternalImage(downcast(engine), image);
|
||||
}
|
||||
|
||||
@@ -399,8 +399,10 @@ float3 DisplayRangeToneMapper::operator()(float3 const c) const noexcept {
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct GenericToneMapper::Options {
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
void setParameters(
|
||||
float contrast,
|
||||
float midGrayIn,
|
||||
@@ -424,7 +426,9 @@ struct GenericToneMapper::Options {
|
||||
inputScale = (a * b * (midGrayOut - 1.0f)) / c;
|
||||
outputScale = midGrayOut * (a - b) / c;
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
float contrast;
|
||||
float midGrayIn;
|
||||
|
||||
@@ -52,10 +52,14 @@ using namespace backend;
|
||||
struct ColorGrading::BuilderDetails {
|
||||
const ToneMapper* toneMapper = nullptr;
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
ToneMapping toneMapping = ToneMapping::ACES_LEGACY;
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
bool hasAdjustments = false;
|
||||
|
||||
@@ -268,8 +272,10 @@ ColorGrading::Builder& ColorGrading::Builder::outputColorSpace(
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
ColorGrading* ColorGrading::Builder::build(Engine& engine) {
|
||||
// We want to see if any of the default adjustment values have been modified
|
||||
// We skip the tonemapping operator on purpose since we always want to apply it
|
||||
@@ -309,7 +315,9 @@ ColorGrading* ColorGrading::Builder::build(Engine& engine) {
|
||||
return colorGrading;
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exposure
|
||||
@@ -585,8 +593,10 @@ static std::tuple<TextureFormat, PixelDataFormat, PixelDataType>
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
// The following functions exist to preserve backward compatibility with the
|
||||
// `FILMIC` set via the deprecated `ToneMapping` API. Selecting `ToneMapping::FILMIC`
|
||||
// forces post-processing to be performed in sRGB to guarantee that the inverse tone
|
||||
@@ -612,7 +622,9 @@ static float3 selectColorGradingLuminance(ColorGrading::ToneMapping const toneMa
|
||||
}
|
||||
return LUMINANCE_Rec2020;
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
using ColorTransform = float3(*)(float3);
|
||||
|
||||
@@ -792,7 +804,9 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) {
|
||||
// we use a vectorize width of 8 because, on ARMv8 it allows the compiler to write eight
|
||||
// 32-bits results in one go.
|
||||
const size_t count = (config.lutDimension * config.lutDimension) & ~0x7u; // tell the compiler that we're a multiple of 8
|
||||
#if defined(__clang__)
|
||||
#pragma clang loop vectorize_width(8)
|
||||
#endif
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
float4 v{src[i]};
|
||||
uint32_t pr = uint32_t(std::floor(v.x * 1023.0f + 0.5f));
|
||||
|
||||
+110
-78
@@ -25,7 +25,9 @@
|
||||
#include "details/Fence.h"
|
||||
#include "details/IndexBuffer.h"
|
||||
#include "details/IndirectLight.h"
|
||||
#include "details/InstanceBuffer.h"
|
||||
#include "details/Material.h"
|
||||
#include "details/MorphTargetBuffer.h"
|
||||
#include "details/Renderer.h"
|
||||
#include "details/Scene.h"
|
||||
#include "details/SkinningBuffer.h"
|
||||
@@ -36,28 +38,39 @@
|
||||
#include "details/VertexBuffer.h"
|
||||
#include "details/View.h"
|
||||
|
||||
#include <filament/ColorGrading.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <private/filament/DescriptorSets.h>
|
||||
#include <private/filament/EngineEnums.h>
|
||||
#include <private/filament/Variant.h>
|
||||
|
||||
#include <private/backend/PlatformFactory.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/CallStack.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/PrivateImplementation-impl.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/ThreadUtils.h>
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <string_view>
|
||||
@@ -66,6 +79,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "generated/resources/materials.h"
|
||||
@@ -101,7 +115,7 @@ Engine* FEngine::create(Builder const& builder) {
|
||||
|
||||
// Normally we launch a thread and create the context and Driver from there (see FEngine::loop).
|
||||
// In the single-threaded case, we do so in the here and now.
|
||||
if (!UTILS_HAS_THREADING) {
|
||||
if constexpr (!UTILS_HAS_THREADING) {
|
||||
Platform* platform = builder->mPlatform;
|
||||
void* const sharedContext = builder->mSharedContext;
|
||||
|
||||
@@ -144,7 +158,7 @@ Engine* FEngine::create(Builder const& builder) {
|
||||
// now we can initialize the largest part of the engine
|
||||
instance->init();
|
||||
|
||||
if (!UTILS_HAS_THREADING) {
|
||||
if constexpr (!UTILS_HAS_THREADING) {
|
||||
instance->execute();
|
||||
}
|
||||
|
||||
@@ -163,7 +177,7 @@ void FEngine::create(Builder const& builder, Invocable<void(void*)>&& callback)
|
||||
instance->mDriverThread = std::thread(&FEngine::loop, instance);
|
||||
|
||||
// launch a thread to call the callback -- so it can't do any damage.
|
||||
std::thread callbackThread = std::thread([instance, callback = std::move(callback)]() {
|
||||
std::thread callbackThread = std::thread([instance, callback = std::move(callback)] {
|
||||
instance->mDriverBarrier.await();
|
||||
callback(instance);
|
||||
});
|
||||
@@ -196,7 +210,7 @@ FEngine* FEngine::getEngine(void* token) {
|
||||
|
||||
#endif
|
||||
|
||||
// these must be static because only a pointer is copied to the render stream
|
||||
// These must be static because only a pointer is copied to the render stream
|
||||
// Note that these coordinates are specified in OpenGL clip space. Other backends can transform
|
||||
// these in the vertex shader as needed.
|
||||
static constexpr float4 sFullScreenTriangleVertices[3] = {
|
||||
@@ -206,7 +220,7 @@ static constexpr float4 sFullScreenTriangleVertices[3] = {
|
||||
};
|
||||
|
||||
// these must be static because only a pointer is copied to the render stream
|
||||
static const uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 };
|
||||
static constexpr uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 };
|
||||
|
||||
FEngine::FEngine(Builder const& builder) :
|
||||
mBackend(builder->mBackend),
|
||||
@@ -216,7 +230,6 @@ FEngine::FEngine(Builder const& builder) :
|
||||
mPostProcessManager(*this),
|
||||
mEntityManager(EntityManager::get()),
|
||||
mRenderableManager(*this),
|
||||
mTransformManager(),
|
||||
mLightManager(*this),
|
||||
mCameraManager(*this),
|
||||
mCommandBufferQueue(
|
||||
@@ -274,7 +287,7 @@ uint32_t FEngine::getJobSystemThreadPoolSize(Config const& config) noexcept {
|
||||
}
|
||||
|
||||
// 1 thread for the user, 1 thread for the backend
|
||||
int threadCount = (int)std::thread::hardware_concurrency() - 2;
|
||||
int threadCount = int(std::thread::hardware_concurrency()) - 2;
|
||||
// make sure we have at least 1 thread though
|
||||
threadCount = std::max(1, threadCount);
|
||||
return threadCount;
|
||||
@@ -347,8 +360,8 @@ void FEngine::init() {
|
||||
}
|
||||
|
||||
// initialize the dummy textures so that their contents are not undefined
|
||||
static const uint32_t zeroes[6] = {0};
|
||||
static const uint32_t ones = 0xffffffff;
|
||||
static constexpr uint32_t zeroes[6] = {};
|
||||
static constexpr uint32_t ones = 0xffffffff;
|
||||
|
||||
mDefaultIblTexture = downcast(Texture::Builder()
|
||||
.width(1).height(1).levels(1)
|
||||
@@ -360,7 +373,7 @@ void FEngine::init() {
|
||||
{ zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE });
|
||||
|
||||
// 3 bands = 9 float3
|
||||
const float sh[9 * 3] = { 0.0f };
|
||||
constexpr float sh[9 * 3] = { 0.0f };
|
||||
mDefaultIbl = downcast(IndirectLight::Builder()
|
||||
.irradiance(3, reinterpret_cast<const float3*>(sh))
|
||||
.build(*this));
|
||||
@@ -427,10 +440,10 @@ void FEngine::init() {
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*const_cast<FEngine*>(this)));
|
||||
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this));
|
||||
|
||||
float3 dummyPositions[1] = {};
|
||||
short4 dummyTangents[1] = {};
|
||||
constexpr float3 dummyPositions[1] = {};
|
||||
constexpr short4 dummyTangents[1] = {};
|
||||
mDummyMorphTargetBuffer->setPositionsAt(*this, 0, dummyPositions, 1, 0);
|
||||
mDummyMorphTargetBuffer->setTangentsAt(*this, 0, dummyTangents, 1, 0);
|
||||
|
||||
@@ -453,7 +466,7 @@ void FEngine::init() {
|
||||
mPostProcessManager.init();
|
||||
|
||||
mDebugRegistry.registerProperty("d.shadowmap.debug_directional_shadowmap",
|
||||
&debug.shadowmap.debug_directional_shadowmap, [this]() {
|
||||
&debug.shadowmap.debug_directional_shadowmap, [this] {
|
||||
mMaterials.forEach([this](FMaterial* material) {
|
||||
if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
|
||||
|
||||
@@ -469,7 +482,7 @@ void FEngine::init() {
|
||||
});
|
||||
|
||||
mDebugRegistry.registerProperty("d.lighting.debug_froxel_visualization",
|
||||
&debug.lighting.debug_froxel_visualization, [this]() {
|
||||
&debug.lighting.debug_froxel_visualization, [this] {
|
||||
mMaterials.forEach([this](FMaterial* material) {
|
||||
if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
|
||||
|
||||
@@ -607,7 +620,7 @@ void FEngine::shutdown() {
|
||||
|
||||
// now wait for all pending commands to be executed and the thread to exit
|
||||
mCommandBufferQueue.requestExit();
|
||||
if (!UTILS_HAS_THREADING) {
|
||||
if constexpr (!UTILS_HAS_THREADING) {
|
||||
execute();
|
||||
getDriverApi().terminate();
|
||||
} else {
|
||||
@@ -638,13 +651,13 @@ void FEngine::prepare() {
|
||||
DriverApi& driver = getDriverApi();
|
||||
|
||||
for (auto& materialInstanceList: mMaterialInstances) {
|
||||
materialInstanceList.second.forEach([&driver](FMaterialInstance* item) {
|
||||
materialInstanceList.second.forEach([&driver](FMaterialInstance const* item) {
|
||||
item->commit(driver);
|
||||
});
|
||||
}
|
||||
|
||||
mMaterials.forEach([](FMaterial* material) {
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
#if FILAMENT_ENABLE_MATDBG // NOLINT(*-include-cleaner)
|
||||
material->checkProgramEdits();
|
||||
#endif
|
||||
});
|
||||
@@ -668,7 +681,7 @@ void FEngine::flushAndWait() {
|
||||
flushAndWait(FENCE_WAIT_FOR_EVER);
|
||||
}
|
||||
|
||||
bool FEngine::flushAndWait(uint64_t timeout) {
|
||||
bool FEngine::flushAndWait(uint64_t const timeout) {
|
||||
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
|
||||
<< "Cannot call Engine::flushAndWait() when rendering thread is paused!";
|
||||
|
||||
@@ -706,28 +719,6 @@ int FEngine::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
#ifdef __ANDROID__
|
||||
const char* portString = "8081";
|
||||
#else
|
||||
const char* portString = getenv("FILAMENT_MATDBG_PORT");
|
||||
#endif
|
||||
if (portString != nullptr) {
|
||||
const int port = atoi(portString);
|
||||
debug.server = new matdbg::DebugServer(mBackend, port);
|
||||
|
||||
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
|
||||
// When this occurs, carry onward, developers can look at civetweb.txt for details.
|
||||
if (!debug.server->isReady()) {
|
||||
delete debug.server;
|
||||
debug.server = nullptr;
|
||||
} else {
|
||||
debug.server->setEditCallback(FMaterial::onEditCallback);
|
||||
debug.server->setQueryCallback(FMaterial::onQueryCallback);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JobSystem::setThreadName("FEngine::loop");
|
||||
JobSystem::setThreadPriority(JobSystem::Priority::DISPLAY);
|
||||
|
||||
@@ -749,6 +740,47 @@ int FEngine::loop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_MATDBG
|
||||
#ifdef __ANDROID__
|
||||
const char* portString = "8081";
|
||||
#else
|
||||
const char* portString = getenv("FILAMENT_MATDBG_PORT");
|
||||
#endif
|
||||
if (portString != nullptr) {
|
||||
const int port = atoi(portString);
|
||||
debug.server = new matdbg::DebugServer(mBackend, mDriver->getShaderLanguage(), port);
|
||||
|
||||
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
|
||||
// When this occurs, carry onward, developers can look at civetweb.txt for details.
|
||||
if (!debug.server->isReady()) {
|
||||
delete debug.server;
|
||||
debug.server = nullptr;
|
||||
} else {
|
||||
debug.server->setEditCallback(FMaterial::onEditCallback);
|
||||
debug.server->setQueryCallback(FMaterial::onQueryCallback);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER // NOLINT(*-include-cleaner)
|
||||
#ifdef __ANDROID__
|
||||
const char* fgviewerPortString = "8085";
|
||||
#else
|
||||
const char* fgviewerPortString = getenv("FILAMENT_FGVIEWER_PORT");
|
||||
#endif
|
||||
if (fgviewerPortString != nullptr) {
|
||||
const int fgviewerPort = atoi(fgviewerPortString);
|
||||
debug.fgviewerServer = new fgviewer::DebugServer(fgviewerPort);
|
||||
|
||||
// Sometimes the server can fail to spin up (e.g. if the above port is already in use).
|
||||
// When this occurs, carry onward, developers can look at civetweb.txt for details.
|
||||
if (!debug.fgviewerServer->isReady()) {
|
||||
delete debug.fgviewerServer;
|
||||
debug.fgviewerServer = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
if (!execute()) {
|
||||
break;
|
||||
@@ -760,9 +792,9 @@ int FEngine::loop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FEngine::flushCommandBuffer(CommandBufferQueue& commandQueue) {
|
||||
void FEngine::flushCommandBuffer(CommandBufferQueue& commandBufferQueue) const {
|
||||
getDriver().purge();
|
||||
commandQueue.flush();
|
||||
commandBufferQueue.flush();
|
||||
}
|
||||
|
||||
const FMaterial* FEngine::getSkyboxMaterial() const noexcept {
|
||||
@@ -783,7 +815,7 @@ const FMaterial* FEngine::getSkyboxMaterial() const noexcept {
|
||||
*/
|
||||
|
||||
template<typename T, typename ... ARGS>
|
||||
inline T* FEngine::create(ResourceList<T>& list,
|
||||
T* FEngine::create(ResourceList<T>& list,
|
||||
typename T::Builder const& builder, ARGS&& ... args) noexcept {
|
||||
T* p = mHeapAllocator.make<T>(*this, builder, std::forward<ARGS>(args)...);
|
||||
if (UTILS_LIKELY(p)) {
|
||||
@@ -861,7 +893,7 @@ FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material,
|
||||
const FMaterialInstance* other, const char* name) noexcept {
|
||||
FMaterialInstance* p = mHeapAllocator.make<FMaterialInstance>(*this, other, name);
|
||||
if (UTILS_LIKELY(p)) {
|
||||
auto pos = mMaterialInstances.emplace(material, "MaterialInstance");
|
||||
auto const pos = mMaterialInstances.emplace(material, "MaterialInstance");
|
||||
pos.first->second.insert(p);
|
||||
}
|
||||
return p;
|
||||
@@ -939,7 +971,7 @@ FCamera* FEngine::createCamera(Entity const entity) noexcept {
|
||||
}
|
||||
|
||||
FCamera* FEngine::getCameraComponent(Entity const entity) noexcept {
|
||||
auto ci = mCameraManager.getInstance(entity);
|
||||
auto const ci = mCameraManager.getInstance(entity);
|
||||
return ci ? mCameraManager.getCamera(ci) : nullptr;
|
||||
}
|
||||
|
||||
@@ -992,16 +1024,16 @@ void FEngine::cleanupResourceListLocked(Lock& lock, ResourceList<T>&& list) {
|
||||
|
||||
template<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline bool FEngine::isValid(const T* ptr, ResourceList<T> const& list) const {
|
||||
bool FEngine::isValid(const T* ptr, ResourceList<T> const& list) const {
|
||||
auto& l = const_cast<ResourceList<T>&>(list);
|
||||
return l.find(ptr) != l.end();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline bool FEngine::terminateAndDestroy(const T* ptr, ResourceList<T>& list) {
|
||||
if (ptr == nullptr) return true;
|
||||
bool const success = list.remove(ptr);
|
||||
bool FEngine::terminateAndDestroy(const T* p, ResourceList<T>& list) {
|
||||
if (p == nullptr) return true;
|
||||
bool const success = list.remove(p);
|
||||
|
||||
#if UTILS_HAS_RTTI
|
||||
auto typeName = CallStack::typeName<T>();
|
||||
@@ -1011,19 +1043,19 @@ inline bool FEngine::terminateAndDestroy(const T* ptr, ResourceList<T>& list) {
|
||||
#endif
|
||||
|
||||
if (ASSERT_PRECONDITION_NON_FATAL(success,
|
||||
"Object %s at %p doesn't exist (double free?)", typeNameCStr, ptr)) {
|
||||
const_cast<T*>(ptr)->terminate(*this);
|
||||
mHeapAllocator.destroy(const_cast<T*>(ptr));
|
||||
"Object %s at %p doesn't exist (double free?)", typeNameCStr, p)) {
|
||||
const_cast<T*>(p)->terminate(*this);
|
||||
mHeapAllocator.destroy(const_cast<T*>(p));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
template<typename T, typename Lock>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* ptr, ResourceList<T>& list) {
|
||||
if (ptr == nullptr) return true;
|
||||
bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* p, ResourceList<T>& list) {
|
||||
if (p == nullptr) return true;
|
||||
lock.lock();
|
||||
bool const success = list.remove(ptr);
|
||||
bool const success = list.remove(p);
|
||||
lock.unlock();
|
||||
|
||||
#if UTILS_HAS_RTTI
|
||||
@@ -1034,9 +1066,9 @@ inline bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* ptr, Resourc
|
||||
#endif
|
||||
|
||||
if (ASSERT_PRECONDITION_NON_FATAL(success,
|
||||
"Object %s at %p doesn't exist (double free?)", typeNameCStr, ptr)) {
|
||||
const_cast<T*>(ptr)->terminate(*this);
|
||||
mHeapAllocator.destroy(const_cast<T*>(ptr));
|
||||
"Object %s at %p doesn't exist (double free?)", typeNameCStr, p)) {
|
||||
const_cast<T*>(p)->terminate(*this);
|
||||
mHeapAllocator.destroy(const_cast<T*>(p));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -1129,11 +1161,11 @@ bool FEngine::destroy(const FInstanceBuffer* p){
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
bool FEngine::destroy(const FMaterial* ptr) {
|
||||
if (ptr == nullptr) return true;
|
||||
bool const success = terminateAndDestroy(ptr, mMaterials);
|
||||
bool FEngine::destroy(const FMaterial* p) {
|
||||
if (p == nullptr) return true;
|
||||
bool const success = terminateAndDestroy(p, mMaterials);
|
||||
if (UTILS_LIKELY(success)) {
|
||||
auto pos = mMaterialInstances.find(ptr);
|
||||
auto const pos = mMaterialInstances.find(p);
|
||||
if (UTILS_LIKELY(pos != mMaterialInstances.cend())) {
|
||||
mMaterialInstances.erase(pos);
|
||||
}
|
||||
@@ -1142,8 +1174,8 @@ bool FEngine::destroy(const FMaterial* ptr) {
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
bool FEngine::destroy(const FMaterialInstance* ptr) {
|
||||
if (ptr == nullptr) return true;
|
||||
bool FEngine::destroy(const FMaterialInstance* p) {
|
||||
if (p == nullptr) return true;
|
||||
|
||||
// Check that the material instance we're destroying is not in use in the RenderableManager
|
||||
// To do this, we currently need to inspect all render primitives in the RenderableManager
|
||||
@@ -1159,13 +1191,13 @@ bool FEngine::destroy(const FMaterialInstance* ptr) {
|
||||
for (size_t j = 0; j < primitiveCount; j++) {
|
||||
auto const* const mi = rcm.getMaterialInstanceAt(ri, 0, j);
|
||||
if (features.engine.debug.assert_material_instance_in_use) {
|
||||
FILAMENT_CHECK_PRECONDITION(mi != ptr)
|
||||
FILAMENT_CHECK_PRECONDITION(mi != p)
|
||||
<< "destroying MaterialInstance \""
|
||||
<< mi->getName() << "\" which is still in use by Renderable (entity="
|
||||
<< entity.getId() << ", instance="
|
||||
<< ri.asValue() << ", index=" << j << ")";
|
||||
} else {
|
||||
if (UTILS_UNLIKELY(mi == ptr)) {
|
||||
if (UTILS_UNLIKELY(mi == p)) {
|
||||
slog.e << "destroying MaterialInstance \""
|
||||
<< mi->getName() << "\" which is still in use by Renderable (entity="
|
||||
<< entity.getId() << ", instance="
|
||||
@@ -1177,11 +1209,11 @@ bool FEngine::destroy(const FMaterialInstance* ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr->isDefaultInstance()) return false;
|
||||
auto pos = mMaterialInstances.find(ptr->getMaterial());
|
||||
if (p->isDefaultInstance()) return false;
|
||||
auto const pos = mMaterialInstances.find(p->getMaterial());
|
||||
assert_invariant(pos != mMaterialInstances.cend());
|
||||
if (pos != mMaterialInstances.cend()) {
|
||||
return terminateAndDestroy(ptr, pos->second);
|
||||
return terminateAndDestroy(p, pos->second);
|
||||
}
|
||||
// this shouldn't happen, this would be double-free
|
||||
return false;
|
||||
@@ -1234,7 +1266,7 @@ bool FEngine::isValid(const FMaterial* m, const FMaterialInstance* p) const {
|
||||
}
|
||||
|
||||
// then find the material instance list for that material
|
||||
auto it = mMaterialInstances.find(m);
|
||||
auto const it = mMaterialInstances.find(m);
|
||||
if (it == mMaterialInstances.end()) {
|
||||
// this could happen if this material has no material instances at all
|
||||
return false;
|
||||
@@ -1323,7 +1355,7 @@ void* FEngine::streamAlloc(size_t const size, size_t const alignment) noexcept {
|
||||
|
||||
bool FEngine::execute() {
|
||||
// wait until we get command buffers to be executed (or thread exit requested)
|
||||
auto buffers = mCommandBufferQueue.waitForCommands();
|
||||
auto const buffers = mCommandBufferQueue.waitForCommands();
|
||||
if (UTILS_UNLIKELY(buffers.empty())) {
|
||||
return false;
|
||||
}
|
||||
@@ -1362,7 +1394,7 @@ Engine::FeatureLevel FEngine::getSupportedFeatureLevel() const noexcept {
|
||||
|
||||
Engine::FeatureLevel FEngine::setActiveFeatureLevel(FeatureLevel featureLevel) {
|
||||
FILAMENT_CHECK_PRECONDITION(featureLevel <= getSupportedFeatureLevel())
|
||||
<< "Feature level " << (unsigned)featureLevel << " not supported";
|
||||
<< "Feature level " << unsigned(featureLevel) << " not supported";
|
||||
FILAMENT_CHECK_PRECONDITION(mActiveFeatureLevel >= FeatureLevel::FEATURE_LEVEL_1)
|
||||
<< "Cannot adjust feature level beyond 0 at runtime";
|
||||
return (mActiveFeatureLevel = std::max(mActiveFeatureLevel, featureLevel));
|
||||
@@ -1381,7 +1413,7 @@ void FEngine::unprotected() noexcept {
|
||||
mUnprotectedDummySwapchain->makeCurrent(getDriverApi());
|
||||
}
|
||||
|
||||
bool FEngine::setFeatureFlag(char const* name, bool const value) noexcept {
|
||||
bool FEngine::setFeatureFlag(char const* name, bool const value) const noexcept {
|
||||
auto* const p = getFeatureFlagPtr(name);
|
||||
if (p) {
|
||||
*p = value;
|
||||
@@ -1452,7 +1484,7 @@ Engine::Builder& Engine::Builder::feature(char const* name, bool const value) no
|
||||
}
|
||||
|
||||
Engine::Builder& Engine::Builder::features(std::initializer_list<char const *> const list) noexcept {
|
||||
for (auto name : list) {
|
||||
for (auto const name : list) {
|
||||
if (name) {
|
||||
feature(name, true);
|
||||
}
|
||||
@@ -1481,15 +1513,15 @@ Engine::Config Engine::BuilderDetails::validateConfig(Config config) noexcept {
|
||||
// Use at least the defaults set by the build system
|
||||
config.minCommandBufferSizeMB = std::max(
|
||||
config.minCommandBufferSizeMB,
|
||||
(uint32_t)FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB);
|
||||
uint32_t(FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB)); // NOLINT(*-include-cleaner)
|
||||
|
||||
config.perFrameCommandsSizeMB = std::max(
|
||||
config.perFrameCommandsSizeMB,
|
||||
(uint32_t)FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB);
|
||||
uint32_t(FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB)); // NOLINT(*-include-cleaner)
|
||||
|
||||
config.perRenderPassArenaSizeMB = std::max(
|
||||
config.perRenderPassArenaSizeMB,
|
||||
(uint32_t)FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB);
|
||||
uint32_t(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB)); // NOLINT(*-include-cleaner)
|
||||
|
||||
config.commandBufferSizeMB = std::max(
|
||||
config.commandBufferSizeMB,
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CountDownLatch.h>
|
||||
@@ -88,6 +90,14 @@ using MaterialKey = uint32_t;
|
||||
} // namespace filament::matdbg
|
||||
#endif
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
#include <fgviewer/DebugServer.h>
|
||||
#else
|
||||
namespace filament::fgviewer {
|
||||
class DebugServer;
|
||||
} // namespace filament::fgviewer
|
||||
#endif
|
||||
|
||||
namespace filament {
|
||||
|
||||
class Renderer;
|
||||
@@ -114,12 +124,11 @@ class ResourceAllocator;
|
||||
*/
|
||||
class FEngine : public Engine {
|
||||
public:
|
||||
|
||||
inline void* operator new(std::size_t const size) noexcept {
|
||||
void* operator new(std::size_t const size) noexcept {
|
||||
return utils::aligned_alloc(size, alignof(FEngine));
|
||||
}
|
||||
|
||||
inline void operator delete(void* p) noexcept {
|
||||
void operator delete(void* p) noexcept {
|
||||
utils::aligned_free(p);
|
||||
}
|
||||
|
||||
@@ -252,20 +261,12 @@ public:
|
||||
// Return a vector of shader languages, in order of preference.
|
||||
utils::FixedCapacityVector<backend::ShaderLanguage> getShaderLanguage() const noexcept {
|
||||
switch (mBackend) {
|
||||
case Backend::DEFAULT:
|
||||
case Backend::NOOP:
|
||||
default:
|
||||
return { backend::ShaderLanguage::ESSL3 };
|
||||
case Backend::OPENGL:
|
||||
return { getDriver().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0
|
||||
? backend::ShaderLanguage::ESSL1
|
||||
: backend::ShaderLanguage::ESSL3 };
|
||||
case Backend::VULKAN:
|
||||
return { backend::ShaderLanguage::SPIRV };
|
||||
return { getDriver().getShaderLanguage() };
|
||||
case Backend::METAL:
|
||||
const auto& lang = mConfig.preferredShaderLanguage;
|
||||
if (lang == Config::ShaderLanguage::MSL) {
|
||||
return { backend::ShaderLanguage::MSL, backend::ShaderLanguage::METAL_LIBRARY };
|
||||
return { backend::ShaderLanguage::MSL, backend::ShaderLanguage::METAL_LIBRARY};
|
||||
}
|
||||
return { backend::ShaderLanguage::METAL_LIBRARY, backend::ShaderLanguage::MSL };
|
||||
}
|
||||
@@ -490,7 +491,7 @@ public:
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
|
||||
backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; }
|
||||
|
||||
static constexpr const size_t MiB = 1024u * 1024u;
|
||||
static constexpr size_t MiB = 1024u * 1024u;
|
||||
size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; }
|
||||
size_t getCommandBufferSize() const noexcept { return mConfig.commandBufferSizeMB * MiB; }
|
||||
size_t getPerFrameCommandsSize() const noexcept { return mConfig.perFrameCommandsSizeMB * MiB; }
|
||||
@@ -510,15 +511,15 @@ public:
|
||||
void resetBackendState() noexcept;
|
||||
#endif
|
||||
|
||||
backend::Driver& getDriver() const noexcept { return *mDriver; }
|
||||
|
||||
private:
|
||||
explicit FEngine(Builder const& builder);
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
int loop();
|
||||
void flushCommandBuffer(backend::CommandBufferQueue& commandBufferQueue);
|
||||
|
||||
backend::Driver& getDriver() const noexcept { return *mDriver; }
|
||||
void flushCommandBuffer(backend::CommandBufferQueue& commandBufferQueue) const;
|
||||
|
||||
template<typename T>
|
||||
bool isValid(const T* ptr, ResourceList<T> const& list) const;
|
||||
@@ -681,6 +682,7 @@ public:
|
||||
bool combine_multiview_images = false;
|
||||
} stereo;
|
||||
matdbg::DebugServer* server = nullptr;
|
||||
fgviewer::DebugServer* fgviewerServer = nullptr;
|
||||
} debug;
|
||||
|
||||
struct {
|
||||
@@ -728,7 +730,7 @@ public:
|
||||
return { mFeatures.data(), mFeatures.size() };
|
||||
}
|
||||
|
||||
bool setFeatureFlag(char const* name, bool value) noexcept;
|
||||
bool setFeatureFlag(char const* name, bool value) const noexcept;
|
||||
std::optional<bool> getFeatureFlag(char const* name) const noexcept;
|
||||
bool* getFeatureFlagPtr(std::string_view name, bool allowConstant = false) const noexcept;
|
||||
};
|
||||
|
||||
@@ -1103,8 +1103,13 @@ void FMaterial::precacheDepthVariants(FEngine const& engine) {
|
||||
// later, when/if needed by createAndCacheProgram(). Doing it now potentially uses more
|
||||
// memory and increases init time, but reduces hiccups during the first frame.
|
||||
if (UTILS_UNLIKELY(mIsDefaultMaterial)) {
|
||||
const bool stereoSupported = mEngine.getDriverApi().isStereoSupported();
|
||||
auto const allDepthVariants = VariantUtils::getDepthVariants();
|
||||
for (auto const variant: allDepthVariants) {
|
||||
// Don't precache any stereo variants if stereo is not supported.
|
||||
if (!stereoSupported && Variant::isStereoVariant(variant)) {
|
||||
continue;
|
||||
}
|
||||
assert_invariant(Variant::isValidDepthVariant(variant));
|
||||
if (hasVariant(variant)) {
|
||||
prepareProgram(variant);
|
||||
|
||||
@@ -61,6 +61,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
|
||||
: mMaterial(material),
|
||||
mDescriptorSet(material->getDescriptorSetLayout()),
|
||||
mCulling(CullingMode::BACK),
|
||||
mShadowCulling(CullingMode::BACK),
|
||||
mDepthFunc(RasterState::DepthFunc::LE),
|
||||
mColorWrite(false),
|
||||
mDepthWrite(false),
|
||||
@@ -92,6 +93,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
|
||||
// We inherit the resolved culling mode rather than the builder-set culling mode.
|
||||
// This preserves the property whereby double-sidedness automatically disables culling.
|
||||
mCulling = rasterState.culling;
|
||||
mShadowCulling = rasterState.culling;
|
||||
mColorWrite = rasterState.colorWrite;
|
||||
mDepthWrite = rasterState.depthWrite;
|
||||
mDepthFunc = rasterState.depthFunc;
|
||||
@@ -126,6 +128,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
|
||||
mSpecularAntiAliasingVariance(other->mSpecularAntiAliasingVariance),
|
||||
mSpecularAntiAliasingThreshold(other->mSpecularAntiAliasingThreshold),
|
||||
mCulling(other->mCulling),
|
||||
mShadowCulling(other->mShadowCulling),
|
||||
mDepthFunc(other->mDepthFunc),
|
||||
mColorWrite(other->mColorWrite),
|
||||
mDepthWrite(other->mDepthWrite),
|
||||
@@ -196,10 +199,10 @@ void FMaterialInstance::commit(DriverApi& driver) const {
|
||||
for (auto const& [binding, p]: mTextureParameters) {
|
||||
assert_invariant(p.texture);
|
||||
// TODO: figure out a way to do this more efficiently (isValid() is a hashmap lookup)
|
||||
FEngine& engine = mMaterial->getEngine();
|
||||
FEngine const& engine = mMaterial->getEngine();
|
||||
FILAMENT_CHECK_PRECONDITION(engine.isValid(p.texture))
|
||||
<< "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n";
|
||||
Handle<HwTexture> handle = p.texture->getHwHandleForSampling();
|
||||
Handle<HwTexture> const handle = p.texture->getHwHandleForSampling();
|
||||
assert_invariant(handle);
|
||||
mDescriptorSet.setSampler(binding, handle, p.params);
|
||||
}
|
||||
@@ -216,7 +219,7 @@ void FMaterialInstance::commit(DriverApi& driver) const {
|
||||
|
||||
void FMaterialInstance::setParameter(std::string_view const name,
|
||||
Handle<HwTexture> texture, SamplerParams const params) {
|
||||
auto binding = mMaterial->getSamplerBinding(name);
|
||||
auto const binding = mMaterial->getSamplerBinding(name);
|
||||
mDescriptorSet.setSampler(binding, texture, params);
|
||||
}
|
||||
|
||||
@@ -243,7 +246,7 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
|
||||
}
|
||||
#endif
|
||||
|
||||
auto binding = mMaterial->getSamplerBinding(name);
|
||||
auto const binding = mMaterial->getSamplerBinding(name);
|
||||
if (texture && texture->textureHandleCanMutate()) {
|
||||
mTextureParameters[binding] = { texture, sampler.getSamplerParams() };
|
||||
} else {
|
||||
@@ -328,13 +331,13 @@ const char* FMaterialInstance::getName() const noexcept {
|
||||
void FMaterialInstance::use(FEngine::DriverApi& driver) const {
|
||||
|
||||
if (UTILS_UNLIKELY(mMissingSamplerDescriptors.any())) {
|
||||
std::call_once(mMissingSamplersFlag, [this]() {
|
||||
std::call_once(mMissingSamplersFlag, [this] {
|
||||
auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList();
|
||||
slog.w << "sampler parameters not set in MaterialInstance \""
|
||||
<< mName.c_str_safe() << "\" or Material \""
|
||||
<< mMaterial->getName().c_str_safe() << "\":\n";
|
||||
mMissingSamplerDescriptors.forEachSetBit([&list](descriptor_binding_t binding) {
|
||||
auto pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
|
||||
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
|
||||
return item.binding == binding;
|
||||
});
|
||||
// just safety-check, should never fail
|
||||
@@ -368,7 +371,7 @@ void FMaterialInstance::fixMissingSamplers() const {
|
||||
// here we need to set the samplers that are missing
|
||||
auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList();
|
||||
missingSamplerDescriptors.forEachSetBit([this, &list](descriptor_binding_t binding) {
|
||||
auto pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
|
||||
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
|
||||
return item.binding == binding;
|
||||
});
|
||||
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
|
||||
backend::CullingMode getCullingMode() const noexcept { return mCulling; }
|
||||
|
||||
backend::CullingMode getShadowCullingMode() const noexcept { return mShadowCulling; }
|
||||
|
||||
bool isColorWriteEnabled() const noexcept { return mColorWrite; }
|
||||
|
||||
bool isDepthWriteEnabled() const noexcept { return mDepthWrite; }
|
||||
@@ -135,7 +137,15 @@ public:
|
||||
|
||||
void setTransparencyMode(TransparencyMode mode) noexcept;
|
||||
|
||||
void setCullingMode(CullingMode const culling) noexcept { mCulling = culling; }
|
||||
void setCullingMode(CullingMode const culling) noexcept {
|
||||
mCulling = culling;
|
||||
mShadowCulling = culling;
|
||||
}
|
||||
|
||||
void setCullingMode(CullingMode const color, CullingMode const shadow) noexcept {
|
||||
mCulling = color;
|
||||
mShadowCulling = shadow;
|
||||
}
|
||||
|
||||
void setColorWrite(bool const enable) noexcept { mColorWrite = enable; }
|
||||
|
||||
@@ -271,7 +281,9 @@ private:
|
||||
float mSpecularAntiAliasingThreshold = 0.0f;
|
||||
|
||||
backend::CullingMode mCulling : 2;
|
||||
backend::CullingMode mShadowCulling : 2;
|
||||
backend::RasterState::DepthFunc mDepthFunc : 3;
|
||||
|
||||
bool mColorWrite : 1;
|
||||
bool mDepthWrite : 1;
|
||||
bool mHasScissor : 1;
|
||||
@@ -283,8 +295,8 @@ private:
|
||||
|
||||
// Scissor rectangle is specified as: Left Bottom Width Height.
|
||||
backend::Viewport mScissorRect = { 0, 0,
|
||||
(uint32_t)std::numeric_limits<int32_t>::max(),
|
||||
(uint32_t)std::numeric_limits<int32_t>::max()
|
||||
uint32_t(std::numeric_limits<int32_t>::max()),
|
||||
uint32_t(std::numeric_limits<int32_t>::max())
|
||||
};
|
||||
|
||||
utils::CString mName;
|
||||
|
||||
@@ -66,7 +66,7 @@ MorphTargetBuffer* MorphTargetBuffer::Builder::build(Engine& engine) {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// This value is limited by ES3.0, ES3.0 only guarantees 2048.
|
||||
// When you change this value, you must change MAX_MORPH_TARGET_BUFFER_WIDTH at getters.vs
|
||||
// When you change this value, you must change MAX_MORPH_TARGET_BUFFER_WIDTH at surface_getters.vs
|
||||
constexpr size_t MAX_MORPH_TARGET_BUFFER_WIDTH = 2048;
|
||||
|
||||
static inline size_t getWidth(size_t const vertexCount) noexcept {
|
||||
|
||||
@@ -781,7 +781,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
cameraInfo.projection = highPrecisionMultiply(ts, cameraInfo.projection);
|
||||
|
||||
// VERTEX_DOMAIN_DEVICE doesn't apply the projection, but it still needs this
|
||||
// clip transform, so we apply it separately (see main.vs)
|
||||
// clip transform, so we apply it separately (see surface_main.vs)
|
||||
cameraInfo.clipTransform = { ts[0][0], ts[1][1], ts[3].x, ts[3].y };
|
||||
|
||||
// adjust svp to the new, larger, rendering dimensions
|
||||
@@ -1443,6 +1443,13 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
|
||||
fg.compile();
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
|
||||
if (UTILS_LIKELY(fgviewerServer)) {
|
||||
fgviewerServer->update(view.getViewHandle(), fg.getFrameGraphInfo(view.getName()));
|
||||
}
|
||||
#endif
|
||||
|
||||
//fg.export_graphviz(slog.d, view.getName());
|
||||
|
||||
fg.execute(driver);
|
||||
|
||||
@@ -546,6 +546,11 @@ void FScene::removeEntities(const Entity* entities, size_t const count) {
|
||||
}
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void FScene::removeAllEntities() noexcept {
|
||||
mEntities.clear();
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
size_t FScene::getRenderableCount() const noexcept {
|
||||
FEngine& engine = mEngine;
|
||||
|
||||
@@ -199,6 +199,7 @@ private:
|
||||
void addEntities(const utils::Entity* entities, size_t count);
|
||||
void remove(utils::Entity entity);
|
||||
void removeEntities(const utils::Entity* entities, size_t count);
|
||||
void removeAllEntities() noexcept;
|
||||
size_t getEntityCount() const noexcept { return mEntities.size(); }
|
||||
size_t getRenderableCount() const noexcept;
|
||||
size_t getLightCount() const noexcept;
|
||||
|
||||
@@ -174,7 +174,7 @@ void FSkinningBuffer::setBones(FEngine& engine, Handle<HwBufferObject> handle,
|
||||
}
|
||||
|
||||
// This value is limited by ES3.0, ES3.0 only guarantees 2048.
|
||||
// When you change this value, you must change MAX_SKINNING_BUFFER_WIDTH at getters.vs
|
||||
// When you change this value, you must change MAX_SKINNING_BUFFER_WIDTH at surface_getters.vs
|
||||
constexpr size_t MAX_SKINNING_BUFFER_WIDTH = 2048;
|
||||
|
||||
static inline size_t getSkinningBufferWidth(size_t const pairCount) noexcept {
|
||||
|
||||
@@ -469,6 +469,26 @@ void FTexture::setImage(FEngine& engine, size_t const level,
|
||||
const_cast<FTexture*>(this)->updateLodRange(level);
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
// The call to setupExternalImage2 is synchronous, and allows the driver to take ownership of the
|
||||
// external image on this thread, if necessary.
|
||||
auto& api = engine.getDriverApi();
|
||||
api.setupExternalImage2(image);
|
||||
|
||||
auto texture = api.createTextureExternalImage2(mTarget, mFormat, mWidth, mHeight, mUsage, image);
|
||||
|
||||
if (mTextureIsSwizzled) {
|
||||
auto const& s = mSwizzle;
|
||||
auto swizzleView = api.createTextureViewSwizzle(texture, s[0], s[1], s[2], s[3]);
|
||||
api.destroyTexture(texture);
|
||||
texture = swizzleView;
|
||||
}
|
||||
|
||||
setHandles(texture);
|
||||
}
|
||||
|
||||
void FTexture::setExternalImage(FEngine& engine, void* image) noexcept {
|
||||
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
|
||||
PrefilterOptions const* options);
|
||||
|
||||
void setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept;
|
||||
void setExternalImage(FEngine& engine, void* image) noexcept;
|
||||
void setExternalImage(FEngine& engine, void* image, size_t plane) noexcept;
|
||||
void setExternalStream(FEngine& engine, FStream* stream) noexcept;
|
||||
|
||||
@@ -109,6 +109,14 @@ FView::FView(FEngine& engine)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
|
||||
if (UTILS_LIKELY(fgviewerServer)) {
|
||||
mFrameGraphViewerViewHandle =
|
||||
fgviewerServer->createView(utils::CString(getName()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// allocate UBOs
|
||||
mLightUbh = driver.createBufferObject(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib),
|
||||
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
|
||||
@@ -153,6 +161,13 @@ void FView::terminate(FEngine& engine) {
|
||||
engine.getDebugRegistry().unregisterDataSource("d.view.frame_info");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
fgviewer::DebugServer* fgviewerServer = engine.debug.fgviewerServer;
|
||||
if (UTILS_LIKELY(fgviewerServer)) {
|
||||
fgviewerServer->destroyView(mFrameGraphViewerViewHandle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FView::setViewport(filament::Viewport const& viewport) noexcept {
|
||||
|
||||
@@ -60,6 +60,14 @@
|
||||
#include <utils/Range.h>
|
||||
#include <utils/Slice.h>
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
#include <fgviewer/DebugServer.h>
|
||||
#else
|
||||
namespace filament::fgviewer {
|
||||
using ViewHandle = uint32_t;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <math/scalar.h>
|
||||
#include <math/mat4.h>
|
||||
|
||||
@@ -467,6 +475,10 @@ public:
|
||||
return mUniforms;
|
||||
}
|
||||
|
||||
fgviewer::ViewHandle getViewHandle() const noexcept {
|
||||
return mFrameGraphViewerViewHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
struct FPickingQuery : public PickingQuery {
|
||||
private:
|
||||
@@ -600,6 +612,8 @@ private:
|
||||
{ 0, 0, 0, 1 },
|
||||
}};
|
||||
|
||||
fgviewer::ViewHandle mFrameGraphViewerViewHandle;
|
||||
|
||||
#ifndef NDEBUG
|
||||
struct DebugState {
|
||||
std::unique_ptr<std::array<DebugRegistry::FrameHistory, 5*60>> debugFrameHistory{};
|
||||
|
||||
@@ -479,6 +479,61 @@ void FrameGraph::export_graphviz(utils::io::ostream& out, char const* name) {
|
||||
mGraph.export_graphviz(out, name);
|
||||
}
|
||||
|
||||
fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) const {
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
fgviewer::FrameGraphInfo info{utils::CString(viewName)};
|
||||
std::vector<fgviewer::FrameGraphInfo::Pass> passes;
|
||||
|
||||
auto first = mPassNodes.begin();
|
||||
const auto activePassNodesEnd = mActivePassNodesEnd;
|
||||
while (first != activePassNodesEnd) {
|
||||
PassNode *const pass = *first;
|
||||
first++;
|
||||
|
||||
assert_invariant(!pass->isCulled());
|
||||
std::vector<fgviewer::ResourceId> reads;
|
||||
auto const &readEdges = mGraph.getIncomingEdges(pass);
|
||||
for (auto const &edge: readEdges) {
|
||||
// all incoming edges should be valid by construction
|
||||
assert_invariant(mGraph.isEdgeValid(edge));
|
||||
reads.push_back(edge->from);
|
||||
}
|
||||
|
||||
std::vector<fgviewer::ResourceId> writes;
|
||||
auto const &writeEdges = mGraph.getOutgoingEdges(pass);
|
||||
for (auto const &edge: writeEdges) {
|
||||
// It is possible that the node we're writing to has been culled.
|
||||
// In this case we'd like to ignore the edge.
|
||||
if (!mGraph.isEdgeValid(edge)) {
|
||||
continue;
|
||||
}
|
||||
writes.push_back(edge->to);
|
||||
}
|
||||
passes.emplace_back(utils::CString(pass->getName()),
|
||||
std::move(reads), std::move(writes));
|
||||
}
|
||||
|
||||
std::unordered_map<fgviewer::ResourceId, fgviewer::FrameGraphInfo::Resource> resources;
|
||||
for (const auto &resource: mResourceNodes) {
|
||||
std::vector<fgviewer::FrameGraphInfo::Resource::Property> resourceProps;
|
||||
// TODO: Fill in resource properties
|
||||
fgviewer::ResourceId id = resource->getId();
|
||||
resources.emplace(id, fgviewer::FrameGraphInfo::Resource(
|
||||
id, utils::CString(resource->getName()),
|
||||
std::move(resourceProps))
|
||||
);
|
||||
}
|
||||
|
||||
info.setResources(std::move(resources));
|
||||
info.setPasses(std::move(passes));
|
||||
|
||||
return info;
|
||||
#else
|
||||
return fgviewer::FrameGraphInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user