Compare commits
1032 Commits
temp-llvm-
...
blender-v3
Author | SHA1 | Date | |
---|---|---|---|
cc66d1020c | |||
2cfca7d910 | |||
a28d6a7b56 | |||
f88646a1ed | |||
ccecd97c8c | |||
![]() |
b20b672e76 | ||
b486421284 | |||
d91843f3b6 | |||
31dc94461d | |||
067ae9260f | |||
343fc38b8d | |||
9f15ee3c7a | |||
c33870ab14 | |||
bac78e9bbe | |||
4815b9fd16 | |||
f6e2c9bc97 | |||
5eca3278c5 | |||
694e20b141 | |||
fb2cb0324a | |||
b89437c27e | |||
afd2fc313e | |||
c91d39e473 | |||
3bc0e39850 | |||
1f3547fb3e | |||
b85cfddb5d | |||
7cecb81e19 | |||
97de02247a | |||
edb15b8458 | |||
![]() |
960783a21a | ||
![]() |
9747a322b8 | ||
52bc420658 | |||
07dc383f4b | |||
46585a4900 | |||
c9290d23ca | |||
b444ed2b38 | |||
![]() |
1781c6002a | ||
![]() |
9ed566efb6 | ||
![]() |
3a1e6bc1d5 | ||
fc0a07da29 | |||
![]() |
32284f34e3 | ||
e5487a81a4 | |||
6aa4543462 | |||
99ce71dd5b | |||
731f377783 | |||
![]() |
27bef3ee02 | ||
eb605ba788 | |||
233004789e | |||
2fc52fb742 | |||
18db6ed3c9 | |||
188277f951 | |||
45482ac576 | |||
b125046c75 | |||
40cbbe809c | |||
af6b88c629 | |||
5dd747a54c | |||
2b8d778a68 | |||
eff7e9aa45 | |||
dd1112abe6 | |||
c77597cd0e | |||
7add8163e4 | |||
b217eb73f5 | |||
c305b88aac | |||
d5e4cab76c | |||
3a672fe6fb | |||
![]() |
1d902a6367 | ||
![]() |
2ddb53de54 | ||
2b3367cdf8 | |||
![]() |
60481e4d99 | ||
5dca3ee6a2 | |||
![]() |
ea3b2e8736 | ||
e908ebc094 | |||
00f6e4c990 | |||
0e51defcf4 | |||
72e20785e1 | |||
![]() |
073d2390f0 | ||
4681987d92 | |||
45079b169d | |||
769ae5c866 | |||
9c2e385509 | |||
d961adb866 | |||
8506f3d9fe | |||
2fb31f34af | |||
216a215ba5 | |||
7935d3668a | |||
6883c47bb5 | |||
4a95c3466f | |||
![]() |
383a6ee78c | ||
5086913b28 | |||
4932269ec3 | |||
a75e9863fe | |||
9bd586a01e | |||
8e88af9934 | |||
8322a4f6b7 | |||
f085c2bab5 | |||
952a613d38 | |||
d681d82d41 | |||
629f22f161 | |||
cde5e12c0b | |||
9216cf9cb5 | |||
476fe7d164 | |||
eec1c16200 | |||
a5214212cf | |||
d743ef91df | |||
4a4701b43c | |||
34f6a99433 | |||
ead84d2ba6 | |||
5e9c1feb8a | |||
91de337dc5 | |||
59a133b61f | |||
44b0c70919 | |||
37d2c774c1 | |||
413e87b6b7 | |||
6bbf63f251 | |||
cb736d2f03 | |||
540fd10b4f | |||
2a644deaa7 | |||
4ee4b61dd8 | |||
7aa0be4b32 | |||
a911f075d7 | |||
72a286760f | |||
c8b4e0c0b5 | |||
118a219e9d | |||
4896e72a4d | |||
e84b42bfcf | |||
0bac962fe5 | |||
66328db703 | |||
5186a28dec | |||
5fd792c1f6 | |||
60af7a3496 | |||
0781c22cee | |||
6e396e21e6 | |||
7b37d980b9 | |||
f8507ca372 | |||
b7a954218b | |||
17e0634902 | |||
e767a2d98b | |||
f80f7afbf0 | |||
ba274d20b4 | |||
c9582b2752 | |||
88712453f6 | |||
80be63e2a5 | |||
99a6392fb5 | |||
dbef66c32f | |||
398538b914 | |||
867e50b886 | |||
74611e3555 | |||
2746238dde | |||
59343ee162 | |||
ee9949a85f | |||
283a4cd40e | |||
353fe610ed | |||
ca991e3012 | |||
1d4037645f | |||
66f3545a0b | |||
85b39b6be0 | |||
4e78a7360e | |||
0ad4d2694b | |||
c5b66560de | |||
75be58c63d | |||
18d3d283ec | |||
![]() |
c73bacc364 | ||
459d9c1e3d | |||
ec5bbebf3e | |||
bfdbc78466 | |||
c3d36b7127 | |||
284cef473f | |||
49ae0b5b3c | |||
be6bcaa8c1 | |||
b7171d1b82 | |||
a81cc5cbcb | |||
869dd2e699 | |||
82ff0fa586 | |||
38ae311706 | |||
0f242981ec | |||
829812f180 | |||
132f9a2e31 | |||
bce810f057 | |||
1a0a22f95a | |||
de886884c0 | |||
93cc892470 | |||
32660382f5 | |||
3cebfadb27 | |||
eba3ffc31a | |||
7f7c614ecd | |||
ef0e21f0ae | |||
969c4a45ce | |||
eaa4aa8644 | |||
b04d42022f | |||
![]() |
82fc68ed90 | ||
![]() |
ddc52f2e1d | ||
af6a1b08e3 | |||
82c3bef765 | |||
1b47d07d76 | |||
e4b7d52fe4 | |||
02f4d63dcc | |||
8b4da9a191 | |||
fe26d18889 | |||
400e57b64a | |||
6efdfeb886 | |||
![]() |
1d0d810331 | ||
3cdbeb32d3 | |||
da6b534274 | |||
a04300c436 | |||
9281ba5812 | |||
e5100ca3ad | |||
2c9931699e | |||
cd7550cfe7 | |||
4541249360 | |||
c5dcfb63d9 | |||
be3047c500 | |||
401383f245 | |||
dd6fd06c15 | |||
05697470ab | |||
0622d2ec61 | |||
257ba175fa | |||
f059bdc823 | |||
54972123f7 | |||
232d5d3f13 | |||
53fe4f62fe | |||
48b26d9c2e | |||
430ced76d5 | |||
7083ea36e2 | |||
d1c7a252eb | |||
facd9d8268 | |||
1f7f7ca14e | |||
d7d827789b | |||
b744081f83 | |||
19b21563d6 | |||
33d5ecd5b5 | |||
6ae08da5c8 | |||
a5edff4b73 | |||
56407432a6 | |||
0999a01b03 | |||
65d4c58060 | |||
993839ce85 | |||
3a9a37d6dc | |||
e0fd31f083 | |||
1236d2aea8 | |||
d23cf42ba7 | |||
ab71d833c7 | |||
f0e32ef4ff | |||
f663a1dc09 | |||
fe9b3dd5f9 | |||
33dde170ce | |||
517afcc858 | |||
27d3140b13 | |||
40fce61a6a | |||
8fb2926a53 | |||
9ac1735205 | |||
6ec83afb1d | |||
e2728a0056 | |||
6175c569f9 | |||
2496a94384 | |||
675f38aca7 | |||
2cad80cbc4 | |||
4fbd00e04c | |||
b38f40e904 | |||
0263c8238b | |||
f39698de77 | |||
![]() |
39bac58cdf | ||
![]() |
5cac5a1a69 | ||
88ff5e5fb9 | |||
a44366a642 | |||
35dedc11d5 | |||
3d12dd59ce | |||
410e4e7ce1 | |||
25c4000796 | |||
720d653b41 | |||
c0674aa145 | |||
94f0230230 | |||
04d55038ee | |||
87d2de88fd | |||
5312cf50a1 | |||
507a4deef1 | |||
d1202bd641 | |||
c69ee218d7 | |||
7313a84c5a | |||
d74bb7be19 | |||
d82384f7e1 | |||
![]() |
fd6506626b | ||
![]() |
d3d9e2abbf | ||
06ac599261 | |||
de71860555 | |||
1995aae6e3 | |||
b76918717d | |||
![]() |
229d0ace02 | ||
11d785edea | |||
![]() |
880e85fc80 | ||
65d287a14a | |||
eb071e3d3c | |||
2f868e5647 | |||
3cd686cae8 | |||
![]() |
1d59a7aa77 | ||
8be20fcc61 | |||
59a8bdd48c | |||
![]() |
c24b2cdebf | ||
3a90f93507 | |||
f2087dfc69 | |||
edc0e77afe | |||
7bdfce687b | |||
0b4cf2984f | |||
a5be935966 | |||
260e6fd46b | |||
0446c9c875 | |||
b61cb67e6d | |||
edb0e7ca30 | |||
0f40855a09 | |||
b2e43a4a9d | |||
f75449b5f2 | |||
2e766ff762 | |||
080dd18cdf | |||
8e0763827e | |||
cb986446e2 | |||
b8a634cb1d | |||
5088d907e5 | |||
![]() |
f7a6e8db04 | ||
ef2685afea | |||
a0c1306e8c | |||
bda210d74a | |||
e7f74a7d6a | |||
6a2fc3230f | |||
71cd9f9fbb | |||
4be87e97f4 | |||
946c70e6a7 | |||
3bcbbf8992 | |||
e4c179f1d8 | |||
![]() |
01f1b51a2e | ||
e5a110719f | |||
6c6556c5bd | |||
59b777eedd | |||
35aedd87e7 | |||
98cc3c6009 | |||
c8cca88851 | |||
45d5773519 | |||
c80411ce3b | |||
c379223053 | |||
b0847eff2a | |||
43b0ff3054 | |||
40b84ffc50 | |||
fd35aa48d1 | |||
bf8597febe | |||
a985f558a6 | |||
71b451bb62 | |||
4927919613 | |||
95fcb41841 | |||
a12265f048 | |||
83b6c8f2b1 | |||
![]() |
ffb0ecb498 | ||
2bd71b49e7 | |||
![]() |
e9150ac317 | ||
b03fb70eff | |||
f8713aae5e | |||
217e0a2ce6 | |||
84dab8b597 | |||
6f9828289f | |||
396413dedf | |||
146618fb22 | |||
c8814fb610 | |||
9ce1135440 | |||
2e4a1a70da | |||
f420118335 | |||
68c2650b03 | |||
c8c9965df2 | |||
5fabbedb04 | |||
716d8436f0 | |||
![]() |
5edb924e57 | ||
![]() |
8ad5241778 | ||
![]() |
83fa6a1b2a | ||
![]() |
c626301f19 | ||
5257257539 | |||
9578fe3068 | |||
2216699c64 | |||
180a68c1dc | |||
b9718899fa | |||
deb90557ea | |||
869180548c | |||
dfc959eed6 | |||
cfa235b89d | |||
![]() |
07514def19 | ||
2cf3ed13da | |||
c9d35ee07c | |||
544a0f2880 | |||
03b57d3973 | |||
afdc35b636 | |||
0a8fa07735 | |||
cb09485ff2 | |||
391bb6e9ba | |||
b6f640b953 | |||
3b2a1ff716 | |||
75e61e5a6d | |||
430f71fce2 | |||
29a1d8b1d3 | |||
cdcbdf8ce4 | |||
7c48196056 | |||
be921a04f2 | |||
dcb7b3f9f7 | |||
379814a118 | |||
3aa56608f7 | |||
f756dc4812 | |||
5d4583683b | |||
d45098024e | |||
c37b837244 | |||
49b9b0251b | |||
e1be275878 | |||
![]() |
bdd74e1e93 | ||
0a32ac02e9 | |||
1e0758333d | |||
9523b1478e | |||
ebd0e76088 | |||
9f6b19526d | |||
7475012e24 | |||
f2b24272dd | |||
da848b7440 | |||
423bbbbaae | |||
![]() |
3775615aea | ||
a21f1e81e0 | |||
87c13ac68c | |||
4710f3346a | |||
74d68e50d3 | |||
89dbad9085 | |||
834b966b41 | |||
d7ac659e02 | |||
9c341153a2 | |||
279a73e429 | |||
32a96b80a3 | |||
25ac6aa5e4 | |||
658ae5d63f | |||
![]() |
58e0aa36ea | ||
99ffe1153a | |||
6c483479b8 | |||
![]() |
c85c52f2ce | ||
d518550c46 | |||
aa2164da33 | |||
5730668dea | |||
8a20aec403 | |||
5400018106 | |||
6f1ab97c53 | |||
78f29c0467 | |||
0379ddac7d | |||
cf31c4ba18 | |||
a99e43b2b7 | |||
5abab0a41a | |||
a7f7b0b77e | |||
1edf520439 | |||
0e86c60c28 | |||
bb1e2a80e4 | |||
710e46cb2d | |||
cab1f1d9a2 | |||
7b615ca186 | |||
9dc0379dc0 | |||
f6296e502a | |||
fdd84d36ce | |||
b57db4b79e | |||
fc0dd5583c | |||
08e2885796 | |||
da1b6c4c02 | |||
d74c2b5c1f | |||
57dfec79f4 | |||
13f2df3c28 | |||
489b484b7b | |||
b42adab3a2 | |||
e729abb0e2 | |||
![]() |
74afc86d4b | ||
![]() |
ae44070341 | ||
![]() |
a9bb460766 | ||
974981a637 | |||
79927e730e | |||
990ed109f2 | |||
37848d1c8e | |||
12b26d21b0 | |||
6738ecb64e | |||
5b299e5999 | |||
9bce134e56 | |||
1bf6a880ab | |||
![]() |
a21bca0e20 | ||
b3bf46b78d | |||
0cb5eae9d0 | |||
1758dcd423 | |||
9338126ecc | |||
46ae083113 | |||
b06fff4737 | |||
94d2a611ec | |||
37e555d2fe | |||
086f191169 | |||
4c951bfa82 | |||
4530449317 | |||
c4bedeb018 | |||
83094d9a0d | |||
c1b5cea63a | |||
b45e71e22c | |||
597eaeaa11 | |||
52b2769b9c | |||
c847122096 | |||
1687903fb8 | |||
c89d6b0953 | |||
2637f94358 | |||
3e2591c83e | |||
0ec94d5359 | |||
932d8dba52 | |||
ec1b0c2014 | |||
97a023a0d5 | |||
e2a36a6e45 | |||
f26c36c96b | |||
c813a1b358 | |||
eab066cbf2 | |||
![]() |
2ed73fc97e | ||
a18bd403bf | |||
96667e3391 | |||
6c25aabddf | |||
0477ca75f0 | |||
![]() |
14f6afb090 | ||
368bfa80f9 | |||
460e0a1347 | |||
33ba298b5d | |||
![]() |
948211679f | ||
![]() |
3f42417cd4 | ||
196da819ba | |||
31296f6f9d | |||
0f89bcdbeb | |||
c5980ada4f | |||
![]() |
17b0c06946 | ||
a000de7c2a | |||
a54142f3f1 | |||
1b1693d43f | |||
2e9b8689e4 | |||
a2301b1d91 | |||
114b06b3cb | |||
2bf519d211 | |||
4d799db72f | |||
5a0c5912a4 | |||
083de503ce | |||
04c3b08518 | |||
263f862ba5 | |||
e2337b5342 | |||
90d61600fc | |||
![]() |
e673cfc2d7 | ||
25fa5792e6 | |||
a215d7e230 | |||
0928fe8710 | |||
4c617c06e9 | |||
796ef560b4 | |||
578baf95e0 | |||
e774f2c901 | |||
7708a848c9 | |||
4b1f243e4d | |||
f9b6a257bd | |||
95981c9876 | |||
46475b8e11 | |||
43e3a33082 | |||
c69a581c0b | |||
abf30007ab | |||
38c7378949 | |||
807c58aae4 | |||
889712927f | |||
5c4a5fd40d | |||
6cd977b903 | |||
dde997086c | |||
579e8ebe79 | |||
5ae76fae90 | |||
e88d966737 | |||
25c99e72cd | |||
b7878a4d45 | |||
![]() |
9350005d8b | ||
1f026a3db9 | |||
![]() |
45d038181a | ||
d590e223da | |||
68aa35ae74 | |||
294ab84909 | |||
1c23a06706 | |||
e07b217669 | |||
32ceb0b807 | |||
4f9be46526 | |||
54d69a2fd1 | |||
9d274a609c | |||
58f8eb54a3 | |||
![]() |
5b90c046d5 | ||
c20f209b1c | |||
59fc95bf97 | |||
d034b85f33 | |||
![]() |
c39d514a4e | ||
4251455dcd | |||
87c5423c5e | |||
![]() |
d68ce0e475 | ||
5e51a5e8a4 | |||
93065a67c6 | |||
f6888b530a | |||
36c40760a5 | |||
23fa5bb723 | |||
64196a6b29 | |||
872dc1038c | |||
53923f502d | |||
20655128c9 | |||
5fca280c80 | |||
1ac2d2dcb6 | |||
14d261d23a | |||
9ca1052226 | |||
4369c5817a | |||
22a8e934e4 | |||
e1ae95f6b2 | |||
24e00c115c | |||
2559d79d2f | |||
![]() |
cc1a48e395 | ||
6baccc36a0 | |||
d552b3c0c0 | |||
902a103f80 | |||
19622ffc5b | |||
f6c8a78ac6 | |||
9315215b20 | |||
264fe10ddd | |||
969a571e0f | |||
4425e0cd64 | |||
9b4c017031 | |||
ae349eb2d5 | |||
eb3ff1d6f9 | |||
1d536c21dd | |||
e3f9d9b206 | |||
b7fe27314b | |||
b47a1867e8 | |||
e7db1247b1 | |||
293aab2253 | |||
9a2d1cd5b7 | |||
cd0acba330 | |||
17cab47ed1 | |||
596ce11556 | |||
f179637222 | |||
ecf2f5ed01 | |||
eddad4e9a1 | |||
e49bf4019b | |||
1788298804 | |||
8a23d91a50 | |||
952a4fa456 | |||
71386c08f1 | |||
eb63646605 | |||
71879d665d | |||
ee6507f2b1 | |||
7e3b1e2c8f | |||
2e5aecf557 | |||
221ff895d9 | |||
a5610da1d5 | |||
9506dcf675 | |||
977baeaa26 | |||
09ecb089a5 | |||
15657b7ccd | |||
b88a37a490 | |||
4d5c08b938 | |||
796e9d442c | |||
dfe22a53bb | |||
0d7b3ed39c | |||
6952228386 | |||
6a8ad00bcc | |||
08d008a508 | |||
2486346f6f | |||
9f8ae130af | |||
5d7ac749c5 | |||
fce0b824a7 | |||
![]() |
36068487d0 | ||
d7822981b1 | |||
542d15b1cd | |||
1b94631975 | |||
6dd89afa96 | |||
db496a0b7d | |||
20df402adc | |||
7220897280 | |||
75d84b1b64 | |||
0fc9526178 | |||
84f6d86445 | |||
c11c2a4b91 | |||
![]() |
54fb1a75ee | ||
0fa36c81d9 | |||
3bbb39ecc1 | |||
44ca984dc7 | |||
8c1ddee10c | |||
b776c46d2f | |||
![]() |
449db0ab1e | ||
8af22719d0 | |||
fa1fef5081 | |||
194979e929 | |||
aa0ecd1791 | |||
4d10a46e63 | |||
a25cfc5db2 | |||
be8f10a4e2 | |||
e3fd0b1d17 | |||
7abdd82dfd | |||
59fcbdd815 | |||
0a08ac2528 | |||
9d3f35a0bf | |||
edee5a947b | |||
![]() |
8fb2ff458b | ||
08822801ac | |||
04feaa8bd0 | |||
e15449623d | |||
40c8e23d48 | |||
e1e3043a51 | |||
![]() |
a84621347d | ||
![]() |
34d424fd64 | ||
d914cfcb7a | |||
608d51c9c8 | |||
bc66cd9868 | |||
3574f2730d | |||
b87d87b1d3 | |||
e69020ad0f | |||
18c5d4ccb3 | |||
9664cc91f3 | |||
6a16a9e661 | |||
6e926e9b56 | |||
2a095d8bfe | |||
9fe704800e | |||
b7a27efd78 | |||
bba95d1901 | |||
67517c7d5c | |||
41495707d2 | |||
82d5905e4b | |||
ca9a749b21 | |||
e9a43a3b60 | |||
9109ea0b96 | |||
5703efab88 | |||
d723fa3d31 | |||
780633ec4b | |||
301bb5afa5 | |||
eb33ee566e | |||
85df7036f7 | |||
e57365a70b | |||
348631cffe | |||
8ae6995e98 | |||
c0d0e2788b | |||
ba48c1ee58 | |||
6f51cb0ad7 | |||
a5cb7c1e62 | |||
0cf746c1fa | |||
c0432d5edb | |||
86b7746e3c | |||
0a3de0305c | |||
c9a8975de5 | |||
261517e475 | |||
c8e536bac3 | |||
e0ac75cb44 | |||
7c568e7d36 | |||
cea588b9ef | |||
7a0cf2c72f | |||
1bd0a87384 | |||
8b3d798374 | |||
0c5ccae79d | |||
cfa53e0fbe | |||
800fc17367 | |||
1c4a1c13e0 | |||
5ecaa9a838 | |||
3537abe84b | |||
743b9c5e1d | |||
b8157f5bf1 | |||
22dc865a86 | |||
039cc32917 | |||
1a4f8ab389 | |||
f173973ae4 | |||
79e985ea54 | |||
19a6220308 | |||
d53738396f | |||
7bb572f208 | |||
0cf2fafd81 | |||
a3deef6fff | |||
eaa4cdaa42 | |||
![]() |
29450a2af3 | ||
![]() |
75a1a578bd | ||
f1a488d0f2 | |||
a7c9fb59ca | |||
227f0f3582 | |||
97c2c39916 | |||
a311fa96aa | |||
e594f23a27 | |||
fa8c2c7885 | |||
a0dcd0bf2c | |||
a72a9e099c | |||
![]() |
62a0de1673 | ||
![]() |
bab47b60cb | ||
![]() |
a909ab984c | ||
5f7ad4baaa | |||
![]() |
e5858a3ad0 | ||
ec5560db73 | |||
0882069095 | |||
1552b86b55 | |||
d43b5791e0 | |||
fb6bd88644 | |||
![]() |
46e049d0ce | ||
e5766752d0 | |||
![]() |
b2ccd8546c | ||
a2c1c368af | |||
d320f3677e | |||
1e61b759c7 | |||
145f1d1e0a | |||
7a2b181591 | |||
ebad1d8d33 | |||
795cea2cce | |||
7f28084e2a | |||
77616082f4 | |||
0dc309bef6 | |||
f4492629ea | |||
ef5d01d98f | |||
89145341e5 | |||
bbe59c6014 | |||
ab125f466c | |||
947dc21979 | |||
5a6ec0f003 | |||
48ff9b57f8 | |||
bdf99a5119 | |||
e339946515 | |||
ac3d07ad17 | |||
376e425c02 | |||
45bb6b836a | |||
e95b4dc2dd | |||
259a71cd3c | |||
8cff1ecf9f | |||
![]() |
631067e559 | ||
41ce7807a6 | |||
ccac22fec5 | |||
6774cae3f2 | |||
fc0f315106 | |||
![]() |
0c94e5d166 | ||
9dc9692b09 | |||
255727b752 | |||
![]() |
1949aece21 | ||
4e8a883bcc | |||
bc02ede98b | |||
d608b98145 | |||
9af81c2b74 | |||
c77f837598 | |||
fd922f5940 | |||
f2fb9a0c59 | |||
f134341e03 | |||
922ae55a16 | |||
37b336a8af | |||
f4af21038d | |||
fe82b8d1e8 | |||
4b8cf11fa5 | |||
a4a95c8d36 | |||
ccf06fffbc | |||
![]() |
57bea57f5e | ||
1a27d20df3 | |||
39ba82f25d | |||
af6a30ebf1 | |||
b0a83a6ed4 | |||
292c2cefe3 | |||
20cb2c72a5 | |||
d9dd8c287f | |||
76d69bbb08 | |||
8dd163160e | |||
![]() |
3ec88ae21d | ||
f5e90a943f | |||
8a772645e2 | |||
1b57dcf320 | |||
6669431846 | |||
e12a707692 | |||
f813aab787 | |||
cfb3f5062d | |||
3488339475 | |||
227fd753df | |||
bd8fa07a3d | |||
934db6a820 | |||
5aac794b11 | |||
1b1e947162 | |||
101fadcf6b | |||
62e8d80a61 | |||
6beaa29791 | |||
eb7333e772 | |||
1705587e21 | |||
74c896c081 | |||
c04d36e922 | |||
37d6ae16be | |||
17c7bac405 | |||
6110f3aa1f | |||
ca0c69eaeb | |||
5519a6a520 | |||
c5ee3ac7e0 | |||
e17ac8dc58 | |||
ed1ced2484 | |||
9620fdc986 | |||
45bc4e3209 | |||
d5e73fa13d | |||
937aa8e114 | |||
90e5ce6ab5 | |||
741ed5fcd2 | |||
34e84d0ee8 | |||
09d6846839 | |||
3e11c7016e | |||
5ba5678e00 | |||
![]() |
1152caad32 | ||
![]() |
34d553671d | ||
![]() |
ee0928d4be | ||
ae28d90578 | |||
![]() |
efe3d60a2c | ||
b7ea6e9d0e | |||
![]() |
5560f32447 | ||
5085c622ea | |||
312aa67cc7 | |||
ed52de948c | |||
2cc6b249c3 | |||
![]() |
361702f239 | ||
bef2412ca2 | |||
29e33cfff5 | |||
6c906b7c21 | |||
7c04bc9a01 | |||
f24854005d | |||
1642028310 | |||
82858ca3f4 | |||
b3dc1a17a0 | |||
2cd8238ce3 | |||
f48164b5ea | |||
3d3bc74884 | |||
bb69c19f08 | |||
e6ca0b33e9 | |||
ed9b21098d | |||
3ae664363d | |||
3a4952e7c2 | |||
0c6b29ee43 | |||
c2089ae53c | |||
ddae2d88fa | |||
1785286ecc | |||
7bcf21e66e | |||
08aa7861d6 | |||
45277d804e | |||
d31b8c316f | |||
88e15ff1e6 | |||
ed3fecae8e | |||
f9aa6376f1 | |||
1484fe260b | |||
e766dc9189 | |||
6f389f1bb8 | |||
c12607baa3 | |||
66a4da87f4 | |||
ed68e18c1c | |||
2ee37e9031 | |||
499fec6f79 | |||
aa363ec2ae | |||
61e2384b7a | |||
60757f010a | |||
0e53ea4cb5 | |||
4067367b6c | |||
c0fb8ea8f3 | |||
1d9bac7d92 | |||
0e1da8dd12 | |||
e55a6bf82b | |||
c240ab70ae | |||
7c013f1154 | |||
611da3b7d6 | |||
50f694c7de | |||
a5b4373f95 | |||
cdd61bb6d7 | |||
f7a0f6a0e4 | |||
1dc0bf86bb | |||
a0edee712a | |||
8cd6d0fe68 | |||
3c04b44913 | |||
5e7e571b0d | |||
bfb760e16a | |||
1403f034ff | |||
b63f375775 | |||
3e92b4ed24 | |||
![]() |
5dedb39d44 | ||
1031638c51 | |||
f64d7bfa4a | |||
8393ccd076 | |||
86141a75eb | |||
29ab711efa | |||
4c3f52e7dc | |||
b1bd0f8ffd | |||
13e7065dd2 | |||
924d2b8df6 | |||
d960c78693 | |||
33400ffcc9 | |||
5df916f23f | |||
b7073fa797 | |||
458be2ecc4 | |||
5336fdc6e3 | |||
713d59bcaf | |||
e3748d7fa5 | |||
07de17ded6 | |||
![]() |
25018dc061 | ||
f7c0287278 | |||
55842b4244 | |||
ad8e2d6661 | |||
bbd0c4118b | |||
54e2f851a4 | |||
070948b5f1 | |||
f7018f7b06 | |||
b2867d4365 | |||
![]() |
a2a02e3994 | ||
![]() |
325beef7af | ||
![]() |
7af01de802 | ||
a9e0caa92d | |||
d2cc672b0c | |||
9c85acf61d | |||
![]() |
d3ad04172d | ||
9793bc30ce | |||
675d3cdd69 | |||
4e44cfa3d9 | |||
c6069c439c | |||
a42e972e1b | |||
1b9e103a30 | |||
b7ad58b945 | |||
ca143fafa6 | |||
8f9f65bc29 | |||
8189471912 | |||
a230445cae | |||
a3e634d4d7 | |||
6a4ee3fd56 | |||
e51864a357 | |||
0a4bd32e59 | |||
add4aa7d25 | |||
2e00d90938 | |||
e2fdc6226a | |||
ea8d749587 | |||
180b66ae8a | |||
![]() |
367fc69dc1 | ||
8be217ada5 | |||
4c46203cb5 | |||
![]() |
6844304dda | ||
e79b4523b4 | |||
97ae08c9fc | |||
d09b1d2759 | |||
56344fb30f | |||
018272ee5b | |||
![]() |
71468f475b | ||
0aa7315608 | |||
bf4358ed0c | |||
ee2b72fd29 | |||
e0d1e66732 | |||
![]() |
52da1afbf6 | ||
49a18cc91e | |||
0b73b2c6cf | |||
6d7dbdbb44 | |||
9d3264b4fd | |||
d3a31311b9 | |||
c0fdf16561 | |||
04ead39dae |
@@ -273,11 +273,13 @@ endif()
|
|||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||||
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
|
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||||
|
option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
|
||||||
else()
|
else()
|
||||||
# not an option for other OS's
|
# not an option for other OS's
|
||||||
set(WITH_SYSTEM_GLEW OFF)
|
set(WITH_SYSTEM_GLEW OFF)
|
||||||
set(WITH_SYSTEM_GLES OFF)
|
set(WITH_SYSTEM_GLES OFF)
|
||||||
|
set(WITH_SYSTEM_FREETYPE OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@@ -536,12 +538,14 @@ option(WITH_OPENGL "When off limits visibility of the opengl header
|
|||||||
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
|
option(WITH_GLEW_ES "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
|
||||||
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
|
option(WITH_GL_EGL "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)" OFF)
|
||||||
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
|
option(WITH_GL_PROFILE_ES20 "Support using OpenGL ES 2.0. (through either EGL or the AGL/WGL/XGL 'es20' profile)" OFF)
|
||||||
|
option(WITH_GPU_SHADER_BUILDER "Shader builder is a developer option enabling linting on GLSL during compilation" OFF)
|
||||||
|
|
||||||
mark_as_advanced(
|
mark_as_advanced(
|
||||||
WITH_OPENGL
|
WITH_OPENGL
|
||||||
WITH_GLEW_ES
|
WITH_GLEW_ES
|
||||||
WITH_GL_EGL
|
WITH_GL_EGL
|
||||||
WITH_GL_PROFILE_ES20
|
WITH_GL_PROFILE_ES20
|
||||||
|
WITH_GPU_SHADER_BUILDER
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@@ -559,12 +563,18 @@ if(WIN32)
|
|||||||
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
|
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compiler toolchain
|
# Compiler tool-chain.
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(UNIX AND NOT APPLE)
|
||||||
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
mark_as_advanced(WITH_LINKER_GOLD)
|
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
|
||||||
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
|
mark_as_advanced(WITH_LINKER_GOLD)
|
||||||
mark_as_advanced(WITH_LINKER_LLD)
|
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
|
||||||
|
mark_as_advanced(WITH_LINKER_LLD)
|
||||||
|
endif()
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
option(WITH_LINKER_MOLD "Use ld.mold linker which is usually faster than ld.gold & ld.lld." OFF)
|
||||||
|
mark_as_advanced(WITH_LINKER_MOLD)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
||||||
@@ -675,7 +685,7 @@ if(WIN32 OR XCODE)
|
|||||||
option(IDE_GROUP_PROJECTS_IN_FOLDERS "Organize the projects according to source folder structure." ON)
|
option(IDE_GROUP_PROJECTS_IN_FOLDERS "Organize the projects according to source folder structure." ON)
|
||||||
mark_as_advanced(IDE_GROUP_PROJECTS_IN_FOLDERS)
|
mark_as_advanced(IDE_GROUP_PROJECTS_IN_FOLDERS)
|
||||||
|
|
||||||
if (IDE_GROUP_PROJECTS_IN_FOLDERS)
|
if(IDE_GROUP_PROJECTS_IN_FOLDERS)
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@@ -700,9 +710,12 @@ if(UNIX AND NOT APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Installation process.
|
# Installation process.
|
||||||
option(POSTINSTALL_SCRIPT "Run given CMake script after installation process" OFF)
|
set(POSTINSTALL_SCRIPT "" CACHE FILEPATH "Run given CMake script after installation process")
|
||||||
mark_as_advanced(POSTINSTALL_SCRIPT)
|
mark_as_advanced(POSTINSTALL_SCRIPT)
|
||||||
|
|
||||||
|
set(POSTCONFIGURE_SCRIPT "" CACHE FILEPATH "Run given CMake script as the last step of CMake configuration")
|
||||||
|
mark_as_advanced(POSTCONFIGURE_SCRIPT)
|
||||||
|
|
||||||
# end option(...)
|
# end option(...)
|
||||||
|
|
||||||
|
|
||||||
@@ -893,8 +906,8 @@ if(WITH_PYTHON)
|
|||||||
# Do this before main 'platform_*' checks,
|
# Do this before main 'platform_*' checks,
|
||||||
# because UNIX will search for the old Python paths which may not exist.
|
# because UNIX will search for the old Python paths which may not exist.
|
||||||
# giving errors about missing paths before this case is met.
|
# giving errors about missing paths before this case is met.
|
||||||
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.9")
|
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.10")
|
||||||
message(FATAL_ERROR "At least Python 3.9 is required to build, but found Python ${PYTHON_VERSION}")
|
message(FATAL_ERROR "At least Python 3.10 is required to build, but found Python ${PYTHON_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
|
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
|
||||||
@@ -2066,3 +2079,8 @@ endif()
|
|||||||
if(0)
|
if(0)
|
||||||
print_all_vars()
|
print_all_vars()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Should be the last step of configuration.
|
||||||
|
if(POSTCONFIGURE_SCRIPT)
|
||||||
|
include(${POSTCONFIGURE_SCRIPT})
|
||||||
|
endif()
|
||||||
|
@@ -63,6 +63,7 @@ include(cmake/jpeg.cmake)
|
|||||||
include(cmake/blosc.cmake)
|
include(cmake/blosc.cmake)
|
||||||
include(cmake/pthreads.cmake)
|
include(cmake/pthreads.cmake)
|
||||||
include(cmake/openexr.cmake)
|
include(cmake/openexr.cmake)
|
||||||
|
include(cmake/brotli.cmake)
|
||||||
include(cmake/freetype.cmake)
|
include(cmake/freetype.cmake)
|
||||||
include(cmake/freeglut.cmake)
|
include(cmake/freeglut.cmake)
|
||||||
include(cmake/glew.cmake)
|
include(cmake/glew.cmake)
|
||||||
|
@@ -25,8 +25,13 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(BOOST_TOOLSET toolset=msvc-14.1)
|
if(MSVC_VERSION GREATER_EQUAL 1920) # 2019
|
||||||
set(BOOST_COMPILER_STRING -vc141)
|
set(BOOST_TOOLSET toolset=msvc-14.2)
|
||||||
|
set(BOOST_COMPILER_STRING -vc142)
|
||||||
|
else() # 2017
|
||||||
|
set(BOOST_TOOLSET toolset=msvc-14.1)
|
||||||
|
set(BOOST_COMPILER_STRING -vc141)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(BOOST_CONFIGURE_COMMAND bootstrap.bat)
|
set(BOOST_CONFIGURE_COMMAND bootstrap.bat)
|
||||||
set(BOOST_BUILD_COMMAND b2)
|
set(BOOST_BUILD_COMMAND b2)
|
||||||
|
38
build_files/build_environment/cmake/brotli.cmake
Normal file
38
build_files/build_environment/cmake/brotli.cmake
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
|
set(BROTLI_EXTRA_ARGS
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Add(external_brotli
|
||||||
|
URL file://${PACKAGE_DIR}/${BROTLI_FILE}
|
||||||
|
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||||
|
URL_HASH ${BROTLI_HASH_TYPE}=${BROTLI_HASH}
|
||||||
|
PREFIX ${BUILD_DIR}/brotli
|
||||||
|
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/brotli ${DEFAULT_CMAKE_FLAGS} ${BROTLI_EXTRA_ARGS}
|
||||||
|
INSTALL_DIR ${LIBDIR}/brotli
|
||||||
|
)
|
||||||
|
|
||||||
|
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||||
|
ExternalProject_Add_Step(external_brotli after_install
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/brotli/include ${HARVEST_TARGET}/brotli/include
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/brotli/lib/brotlidec-static${LIBEXT} ${HARVEST_TARGET}/brotli/lib/brotlidec-static${LIBEXT}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/brotli/lib/brotlicommon-static${LIBEXT} ${HARVEST_TARGET}/brotli/lib/brotlicommon-static${LIBEXT}
|
||||||
|
DEPENDEES install
|
||||||
|
)
|
||||||
|
endif()
|
@@ -94,3 +94,4 @@ download_source(POTRACE)
|
|||||||
download_source(HARU)
|
download_source(HARU)
|
||||||
download_source(ZSTD)
|
download_source(ZSTD)
|
||||||
download_source(FLEX)
|
download_source(FLEX)
|
||||||
|
download_source(BROTLI)
|
||||||
|
@@ -19,13 +19,13 @@
|
|||||||
set(FREETYPE_EXTRA_ARGS
|
set(FREETYPE_EXTRA_ARGS
|
||||||
-DCMAKE_RELEASE_POSTFIX:STRING=2ST
|
-DCMAKE_RELEASE_POSTFIX:STRING=2ST
|
||||||
-DCMAKE_DEBUG_POSTFIX:STRING=2ST_d
|
-DCMAKE_DEBUG_POSTFIX:STRING=2ST_d
|
||||||
-DWITH_BZip2=OFF
|
-DFT_DISABLE_BZIP2=ON
|
||||||
-DWITH_HarfBuzz=OFF
|
-DFT_DISABLE_HARFBUZZ=ON
|
||||||
-DFT_WITH_HARFBUZZ=OFF
|
-DFT_DISABLE_PNG=ON
|
||||||
-DFT_WITH_BZIP2=OFF
|
-DFT_REQUIRE_BROTLI=ON
|
||||||
-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
|
-DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include
|
||||||
-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE
|
-DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib
|
||||||
-DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE)
|
)
|
||||||
|
|
||||||
ExternalProject_Add(external_freetype
|
ExternalProject_Add(external_freetype
|
||||||
URL file://${PACKAGE_DIR}/${FREETYPE_FILE}
|
URL file://${PACKAGE_DIR}/${FREETYPE_FILE}
|
||||||
@@ -36,6 +36,11 @@ ExternalProject_Add(external_freetype
|
|||||||
INSTALL_DIR ${LIBDIR}/freetype
|
INSTALL_DIR ${LIBDIR}/freetype
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dependencies(
|
||||||
|
external_freetype
|
||||||
|
external_brotli
|
||||||
|
)
|
||||||
|
|
||||||
if(BUILD_MODE STREQUAL Release AND WIN32)
|
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||||
ExternalProject_Add_Step(external_freetype after_install
|
ExternalProject_Add_Step(external_freetype after_install
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype
|
||||||
|
@@ -38,13 +38,6 @@ elseif(UNIX AND NOT APPLE)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(BLENDER_PLATFORM_ARM)
|
|
||||||
set(GMP_OPTIONS
|
|
||||||
${GMP_OPTIONS}
|
|
||||||
--disable-assembly
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ExternalProject_Add(external_gmp
|
ExternalProject_Add(external_gmp
|
||||||
URL file://${PACKAGE_DIR}/${GMP_FILE}
|
URL file://${PACKAGE_DIR}/${GMP_FILE}
|
||||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||||
|
@@ -79,6 +79,8 @@ endfunction()
|
|||||||
harvest(alembic/include alembic/include "*.h")
|
harvest(alembic/include alembic/include "*.h")
|
||||||
harvest(alembic/lib/libAlembic.a alembic/lib/libAlembic.a)
|
harvest(alembic/lib/libAlembic.a alembic/lib/libAlembic.a)
|
||||||
harvest(alembic/bin alembic/bin "*")
|
harvest(alembic/bin alembic/bin "*")
|
||||||
|
harvest(brotli/include brotli/include "*.h")
|
||||||
|
harvest(brotli/lib brotli/lib "*.a")
|
||||||
harvest(boost/include boost/include "*")
|
harvest(boost/include boost/include "*")
|
||||||
harvest(boost/lib boost/lib "*.a")
|
harvest(boost/lib boost/lib "*.a")
|
||||||
harvest(ffmpeg/include ffmpeg/include "*.h")
|
harvest(ffmpeg/include ffmpeg/include "*.h")
|
||||||
|
@@ -31,7 +31,7 @@ ExternalProject_Add(external_python_site_packages
|
|||||||
CONFIGURE_COMMAND ${PIP_CONFIGURE_COMMAND}
|
CONFIGURE_COMMAND ${PIP_CONFIGURE_COMMAND}
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
PREFIX ${BUILD_DIR}/site_packages
|
PREFIX ${BUILD_DIR}/site_packages
|
||||||
INSTALL_COMMAND ${PYTHON_BINARY} -m pip install ${SITE_PACKAGES_EXTRA} cython==${CYTHON_VERSION} idna==${IDNA_VERSION} charset-normalizer==${CHARSET_NORMALIZER_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} zstandard==${ZSTANDARD_VERSION} --no-binary :all:
|
INSTALL_COMMAND ${PYTHON_BINARY} -m pip install --no-cache-dir ${SITE_PACKAGES_EXTRA} cython==${CYTHON_VERSION} idna==${IDNA_VERSION} charset-normalizer==${CHARSET_NORMALIZER_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} zstandard==${ZSTANDARD_VERSION} --no-binary :all:
|
||||||
)
|
)
|
||||||
|
|
||||||
if(USE_PIP_NUMPY)
|
if(USE_PIP_NUMPY)
|
||||||
|
@@ -83,9 +83,9 @@ else()
|
|||||||
set(OPENEXR_VERSION_POSTFIX)
|
set(OPENEXR_VERSION_POSTFIX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FREETYPE_VERSION 2.10.2)
|
set(FREETYPE_VERSION 2.11.1)
|
||||||
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
|
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
|
||||||
set(FREETYPE_HASH b1cb620e4c875cd4d1bfa04945400945)
|
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
|
||||||
set(FREETYPE_HASH_TYPE MD5)
|
set(FREETYPE_HASH_TYPE MD5)
|
||||||
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
||||||
|
|
||||||
@@ -189,11 +189,11 @@ set(OSL_HASH 1abd7ce40481771a9fa937f19595d2f2)
|
|||||||
set(OSL_HASH_TYPE MD5)
|
set(OSL_HASH_TYPE MD5)
|
||||||
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
|
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(PYTHON_VERSION 3.9.7)
|
set(PYTHON_VERSION 3.10.2)
|
||||||
set(PYTHON_SHORT_VERSION 3.9)
|
set(PYTHON_SHORT_VERSION 3.10)
|
||||||
set(PYTHON_SHORT_VERSION_NO_DOTS 39)
|
set(PYTHON_SHORT_VERSION_NO_DOTS 310)
|
||||||
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
|
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
|
||||||
set(PYTHON_HASH fddb060b483bc01850a3f412eea1d954)
|
set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
|
||||||
set(PYTHON_HASH_TYPE MD5)
|
set(PYTHON_HASH_TYPE MD5)
|
||||||
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
|
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
|
||||||
|
|
||||||
@@ -215,18 +215,20 @@ set(NANOVDB_HASH e7b9e863ec2f3b04ead171dec2322807)
|
|||||||
set(NANOVDB_HASH_TYPE MD5)
|
set(NANOVDB_HASH_TYPE MD5)
|
||||||
set(NANOVDB_FILE nano-vdb-${NANOVDB_GIT_UID}.tar.gz)
|
set(NANOVDB_FILE nano-vdb-${NANOVDB_GIT_UID}.tar.gz)
|
||||||
|
|
||||||
set(IDNA_VERSION 3.2)
|
set(IDNA_VERSION 3.3)
|
||||||
set(CHARSET_NORMALIZER_VERSION 2.0.6)
|
set(CHARSET_NORMALIZER_VERSION 2.0.10)
|
||||||
set(URLLIB3_VERSION 1.26.7)
|
set(URLLIB3_VERSION 1.26.8)
|
||||||
set(CERTIFI_VERSION 2021.10.8)
|
set(CERTIFI_VERSION 2021.10.8)
|
||||||
set(REQUESTS_VERSION 2.26.0)
|
set(REQUESTS_VERSION 2.27.1)
|
||||||
set(CYTHON_VERSION 0.29.24)
|
set(CYTHON_VERSION 0.29.26)
|
||||||
set(ZSTANDARD_VERSION 0.15.2 )
|
# The version of the zstd library used to build the Python package should match ZSTD_VERSION defined below.
|
||||||
|
# At this time of writing, 0.17.0 was already released, but built against zstd 1.5.1, while we use 1.5.0.
|
||||||
|
set(ZSTANDARD_VERSION 0.16.0)
|
||||||
|
|
||||||
set(NUMPY_VERSION 1.21.2)
|
set(NUMPY_VERSION 1.22.0)
|
||||||
set(NUMPY_SHORT_VERSION 1.21)
|
set(NUMPY_SHORT_VERSION 1.22)
|
||||||
set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}/numpy-${NUMPY_VERSION}.zip)
|
set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}/numpy-${NUMPY_VERSION}.zip)
|
||||||
set(NUMPY_HASH 5638d5dae3ca387be562912312db842e)
|
set(NUMPY_HASH 252de134862a27bd66705d29622edbfe)
|
||||||
set(NUMPY_HASH_TYPE MD5)
|
set(NUMPY_HASH_TYPE MD5)
|
||||||
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
|
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
|
||||||
|
|
||||||
@@ -474,9 +476,9 @@ set(ISPC_HASH 2e3abedbc0ea9aaec17d6562c632454d)
|
|||||||
set(ISPC_HASH_TYPE MD5)
|
set(ISPC_HASH_TYPE MD5)
|
||||||
set(ISPC_FILE ispc-${ISPC_VERSION}.tar.gz)
|
set(ISPC_FILE ispc-${ISPC_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(GMP_VERSION 6.2.0)
|
set(GMP_VERSION 6.2.1)
|
||||||
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
|
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
|
||||||
set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1)
|
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
|
||||||
set(GMP_HASH_TYPE MD5)
|
set(GMP_HASH_TYPE MD5)
|
||||||
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
||||||
|
|
||||||
@@ -500,3 +502,9 @@ set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
|
|||||||
|
|
||||||
set(SSE2NEON_GIT https://github.com/DLTcollab/sse2neon.git)
|
set(SSE2NEON_GIT https://github.com/DLTcollab/sse2neon.git)
|
||||||
set(SSE2NEON_GIT_HASH fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
|
set(SSE2NEON_GIT_HASH fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
|
||||||
|
|
||||||
|
set(BROTLI_VERSION v1.0.9)
|
||||||
|
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/${BROTLI_VERSION}.tar.gz)
|
||||||
|
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
|
||||||
|
set(BROTLI_HASH_TYPE SHA256)
|
||||||
|
set(BROTLI_FILE brotli-${BROTLI_VERSION}.tar.gz)
|
||||||
|
@@ -379,27 +379,27 @@ USE_CXX11=true
|
|||||||
CLANG_FORMAT_VERSION_MIN="6.0"
|
CLANG_FORMAT_VERSION_MIN="6.0"
|
||||||
CLANG_FORMAT_VERSION_MEX="10.0"
|
CLANG_FORMAT_VERSION_MEX="10.0"
|
||||||
|
|
||||||
PYTHON_VERSION="3.9.7"
|
PYTHON_VERSION="3.10.2"
|
||||||
PYTHON_VERSION_SHORT="3.9"
|
PYTHON_VERSION_SHORT="3.10"
|
||||||
PYTHON_VERSION_MIN="3.7"
|
PYTHON_VERSION_MIN="3.10"
|
||||||
PYTHON_VERSION_MEX="3.11"
|
PYTHON_VERSION_MEX="3.12"
|
||||||
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT
|
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT
|
||||||
PYTHON_FORCE_BUILD=false
|
PYTHON_FORCE_BUILD=false
|
||||||
PYTHON_FORCE_REBUILD=false
|
PYTHON_FORCE_REBUILD=false
|
||||||
PYTHON_SKIP=false
|
PYTHON_SKIP=false
|
||||||
|
|
||||||
# Additional Python modules.
|
# Additional Python modules.
|
||||||
PYTHON_IDNA_VERSION="3.2"
|
PYTHON_IDNA_VERSION="3.3"
|
||||||
PYTHON_IDNA_VERSION_MIN="2.0"
|
PYTHON_IDNA_VERSION_MIN="2.0"
|
||||||
PYTHON_IDNA_VERSION_MEX="4.0"
|
PYTHON_IDNA_VERSION_MEX="4.0"
|
||||||
PYTHON_IDNA_NAME="idna"
|
PYTHON_IDNA_NAME="idna"
|
||||||
|
|
||||||
PYTHON_CHARSET_NORMALIZER_VERSION="2.0.6"
|
PYTHON_CHARSET_NORMALIZER_VERSION="2.0.10"
|
||||||
PYTHON_CHARSET_NORMALIZER_VERSION_MIN="2.0.6"
|
PYTHON_CHARSET_NORMALIZER_VERSION_MIN="2.0.6"
|
||||||
PYTHON_CHARSET_NORMALIZER_VERSION_MEX="2.1.0" # requests uses `charset_normalizer~=2.0.0`
|
PYTHON_CHARSET_NORMALIZER_VERSION_MEX="2.1.0" # requests uses `charset_normalizer~=2.0.0`
|
||||||
PYTHON_CHARSET_NORMALIZER_NAME="charset-normalizer"
|
PYTHON_CHARSET_NORMALIZER_NAME="charset-normalizer"
|
||||||
|
|
||||||
PYTHON_URLLIB3_VERSION="1.26.7"
|
PYTHON_URLLIB3_VERSION="1.26.8"
|
||||||
PYTHON_URLLIB3_VERSION_MIN="1.0"
|
PYTHON_URLLIB3_VERSION_MIN="1.0"
|
||||||
PYTHON_URLLIB3_VERSION_MEX="2.0"
|
PYTHON_URLLIB3_VERSION_MEX="2.0"
|
||||||
PYTHON_URLLIB3_NAME="urllib3"
|
PYTHON_URLLIB3_NAME="urllib3"
|
||||||
@@ -409,17 +409,17 @@ PYTHON_CERTIFI_VERSION_MIN="2021.0"
|
|||||||
PYTHON_CERTIFI_VERSION_MEX="2023.0"
|
PYTHON_CERTIFI_VERSION_MEX="2023.0"
|
||||||
PYTHON_CERTIFI_NAME="certifi"
|
PYTHON_CERTIFI_NAME="certifi"
|
||||||
|
|
||||||
PYTHON_REQUESTS_VERSION="2.23.0"
|
PYTHON_REQUESTS_VERSION="2.27.1"
|
||||||
PYTHON_REQUESTS_VERSION_MIN="2.0"
|
PYTHON_REQUESTS_VERSION_MIN="2.0"
|
||||||
PYTHON_REQUESTS_VERSION_MEX="3.0"
|
PYTHON_REQUESTS_VERSION_MEX="3.0"
|
||||||
PYTHON_REQUESTS_NAME="requests"
|
PYTHON_REQUESTS_NAME="requests"
|
||||||
|
|
||||||
PYTHON_ZSTANDARD_VERSION="0.15.2"
|
PYTHON_ZSTANDARD_VERSION="0.16.0"
|
||||||
PYTHON_ZSTANDARD_VERSION_MIN="0.15.2"
|
PYTHON_ZSTANDARD_VERSION_MIN="0.15.2"
|
||||||
PYTHON_ZSTANDARD_VERSION_MEX="0.16.0"
|
PYTHON_ZSTANDARD_VERSION_MEX="0.20.0"
|
||||||
PYTHON_ZSTANDARD_NAME="zstandard"
|
PYTHON_ZSTANDARD_NAME="zstandard"
|
||||||
|
|
||||||
PYTHON_NUMPY_VERSION="1.21.2"
|
PYTHON_NUMPY_VERSION="1.22.0"
|
||||||
PYTHON_NUMPY_VERSION_MIN="1.14"
|
PYTHON_NUMPY_VERSION_MIN="1.14"
|
||||||
PYTHON_NUMPY_VERSION_MEX="2.0"
|
PYTHON_NUMPY_VERSION_MEX="2.0"
|
||||||
PYTHON_NUMPY_NAME="numpy"
|
PYTHON_NUMPY_NAME="numpy"
|
||||||
@@ -492,14 +492,14 @@ OIIO_SKIP=false
|
|||||||
LLVM_VERSION="12.0.0"
|
LLVM_VERSION="12.0.0"
|
||||||
LLVM_VERSION_SHORT="12.0"
|
LLVM_VERSION_SHORT="12.0"
|
||||||
LLVM_VERSION_MIN="11.0"
|
LLVM_VERSION_MIN="11.0"
|
||||||
LLVM_VERSION_MEX="13.0"
|
LLVM_VERSION_MEX="14.0"
|
||||||
LLVM_VERSION_FOUND=""
|
LLVM_VERSION_FOUND=""
|
||||||
LLVM_FORCE_BUILD=false
|
LLVM_FORCE_BUILD=false
|
||||||
LLVM_FORCE_REBUILD=false
|
LLVM_FORCE_REBUILD=false
|
||||||
LLVM_SKIP=false
|
LLVM_SKIP=false
|
||||||
|
|
||||||
# OSL needs to be compiled for now!
|
# OSL needs to be compiled for now!
|
||||||
OSL_VERSION="1.11.14.1"
|
OSL_VERSION="1.11.17.0"
|
||||||
OSL_VERSION_SHORT="1.11"
|
OSL_VERSION_SHORT="1.11"
|
||||||
OSL_VERSION_MIN="1.11"
|
OSL_VERSION_MIN="1.11"
|
||||||
OSL_VERSION_MEX="2.0"
|
OSL_VERSION_MEX="2.0"
|
||||||
@@ -3620,8 +3620,8 @@ compile_FFmpeg() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
./configure --cc="gcc -Wl,--as-needed" \
|
./configure --cc="gcc -Wl,--as-needed" \
|
||||||
--extra-ldflags="-pthread -static-libgcc" \
|
--extra-ldflags="-pthread" \
|
||||||
--prefix=$_inst --enable-static \
|
--prefix=$_inst --enable-shared \
|
||||||
--disable-ffplay --disable-doc \
|
--disable-ffplay --disable-doc \
|
||||||
--enable-gray \
|
--enable-gray \
|
||||||
--enable-avfilter --disable-vdpau \
|
--enable-avfilter --disable-vdpau \
|
||||||
@@ -5721,76 +5721,6 @@ install_OTHER() {
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Printing User Info
|
# Printing User Info
|
||||||
|
|
||||||
print_info_ffmpeglink_DEB() {
|
|
||||||
dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
|
|
||||||
}
|
|
||||||
|
|
||||||
print_info_ffmpeglink_RPM() {
|
|
||||||
rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
|
|
||||||
}
|
|
||||||
|
|
||||||
print_info_ffmpeglink_ARCH() {
|
|
||||||
pacman -Ql $_packages | grep -e ".*\/lib[^\/]\+\.so$" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
|
|
||||||
}
|
|
||||||
|
|
||||||
print_info_ffmpeglink() {
|
|
||||||
# This func must only print a ';'-separated list of libs...
|
|
||||||
if [ -z "$DISTRO" ]; then
|
|
||||||
ERROR "Failed to detect distribution type"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create list of packages from which to get libs names...
|
|
||||||
_packages=""
|
|
||||||
|
|
||||||
if [ "$THEORA_USE" = true ]; then
|
|
||||||
_packages="$_packages $THEORA_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$VORBIS_USE" = true ]; then
|
|
||||||
_packages="$_packages $VORBIS_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$OGG_USE" = true ]; then
|
|
||||||
_packages="$_packages $OGG_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$XVID_USE" = true ]; then
|
|
||||||
_packages="$_packages $XVID_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$VPX_USE" = true ]; then
|
|
||||||
_packages="$_packages $VPX_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$OPUS_USE" = true ]; then
|
|
||||||
_packages="$_packages $OPUS_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$MP3LAME_USE" = true ]; then
|
|
||||||
_packages="$_packages $MP3LAME_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$X264_USE" = true ]; then
|
|
||||||
_packages="$_packages $X264_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$OPENJPEG_USE" = true ]; then
|
|
||||||
_packages="$_packages $OPENJPEG_DEV"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$DISTRO" = "DEB" ]; then
|
|
||||||
print_info_ffmpeglink_DEB
|
|
||||||
elif [ "$DISTRO" = "RPM" ]; then
|
|
||||||
print_info_ffmpeglink_RPM
|
|
||||||
elif [ "$DISTRO" = "ARCH" ]; then
|
|
||||||
print_info_ffmpeglink_ARCH
|
|
||||||
# XXX TODO!
|
|
||||||
else
|
|
||||||
PRINT "<Could not determine additional link libraries needed for ffmpeg, replace this by valid list of libs...>"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_info() {
|
print_info() {
|
||||||
PRINT ""
|
PRINT ""
|
||||||
PRINT ""
|
PRINT ""
|
||||||
@@ -5801,7 +5731,7 @@ print_info() {
|
|||||||
PRINT "If you're using CMake add this to your configuration flags:"
|
PRINT "If you're using CMake add this to your configuration flags:"
|
||||||
|
|
||||||
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
|
_buildargs="-U *SNDFILE* -U PYTHON* -U *BOOST* -U *Boost* -U *TBB*"
|
||||||
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
|
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CLANG* -U *CYCLES*"
|
||||||
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
|
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *BLOSC* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC* -U *USD*"
|
||||||
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR*"
|
_buildargs="$_buildargs -U *EMBREE* -U *OPENIMAGEDENOISE* -U *OPENXR*"
|
||||||
|
|
||||||
@@ -6002,12 +5932,10 @@ print_info() {
|
|||||||
|
|
||||||
if [ "$FFMPEG_SKIP" = false ]; then
|
if [ "$FFMPEG_SKIP" = false ]; then
|
||||||
_1="-D WITH_CODEC_FFMPEG=ON"
|
_1="-D WITH_CODEC_FFMPEG=ON"
|
||||||
_2="-D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;swresample;lzma;rt;`print_info_ffmpeglink`'"
|
|
||||||
PRINT " $_1"
|
PRINT " $_1"
|
||||||
PRINT " $_2"
|
_buildargs="$_buildargs $_1"
|
||||||
_buildargs="$_buildargs $_1 $_2"
|
|
||||||
if [ -d $INST/ffmpeg ]; then
|
if [ -d $INST/ffmpeg ]; then
|
||||||
_1="-D FFMPEG=$INST/ffmpeg"
|
_1="-D FFMPEG_ROOT_DIR=$INST/ffmpeg"
|
||||||
PRINT " $_1"
|
PRINT " $_1"
|
||||||
_buildargs="$_buildargs $_1"
|
_buildargs="$_buildargs $_1"
|
||||||
fi
|
fi
|
||||||
|
@@ -1,64 +1,39 @@
|
|||||||
@echo off
|
@echo off
|
||||||
if NOT "%1" == "" (
|
if NOT "%1" == "" (
|
||||||
if "%1" == "2013" (
|
|
||||||
echo "Building for VS2013"
|
|
||||||
set VSVER=12.0
|
|
||||||
set VSVER_SHORT=12
|
|
||||||
set BuildDir=VS12
|
|
||||||
goto par2
|
|
||||||
)
|
|
||||||
if "%1" == "2015" (
|
|
||||||
echo "Building for VS2015"
|
|
||||||
set VSVER=14.0
|
|
||||||
set VSVER_SHORT=14
|
|
||||||
set BuildDir=VS14
|
|
||||||
goto par2
|
|
||||||
)
|
|
||||||
if "%1" == "2017" (
|
if "%1" == "2017" (
|
||||||
echo "Building for VS2017"
|
echo "Building for VS2017"
|
||||||
set VSVER=15.0
|
set VSVER=15.0
|
||||||
set VSVER_SHORT=15
|
set VSVER_SHORT=15
|
||||||
set BuildDir=VS15
|
set BuildDir=VS15
|
||||||
goto par2
|
goto par2
|
||||||
|
)
|
||||||
|
if "%1" == "2019" (
|
||||||
|
echo "Building for VS2019"
|
||||||
|
set VSVER=15.0
|
||||||
|
set VSVER_SHORT=15
|
||||||
|
set BuildDir=VS15
|
||||||
|
goto par2
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
:usage
|
:usage
|
||||||
|
|
||||||
Echo Usage build_deps 2013/2015/2017 x64/x86
|
Echo Usage build_deps 2017/2019 x64
|
||||||
goto exit
|
goto exit
|
||||||
:par2
|
:par2
|
||||||
if NOT "%2" == "" (
|
if NOT "%2" == "" (
|
||||||
if "%2" == "x86" (
|
|
||||||
echo "Building for x86"
|
|
||||||
set HARVESTROOT=Windows_vc
|
|
||||||
set ARCH=86
|
|
||||||
if "%1" == "2013" (
|
|
||||||
set CMAKE_BUILDER=Visual Studio 12 2013
|
|
||||||
)
|
|
||||||
if "%1" == "2015" (
|
|
||||||
set CMAKE_BUILDER=Visual Studio 14 2015
|
|
||||||
)
|
|
||||||
if "%1" == "2017" (
|
|
||||||
set CMAKE_BUILDER=Visual Studio 15 2017
|
|
||||||
)
|
|
||||||
|
|
||||||
goto start
|
|
||||||
)
|
|
||||||
if "%2" == "x64" (
|
if "%2" == "x64" (
|
||||||
echo "Building for x64"
|
echo "Building for x64"
|
||||||
set HARVESTROOT=Win64_vc
|
set HARVESTROOT=Win64_vc
|
||||||
set ARCH=64
|
set ARCH=64
|
||||||
if "%1" == "2013" (
|
if "%1" == "2019" (
|
||||||
set CMAKE_BUILDER=Visual Studio 12 2013 Win64
|
set CMAKE_BUILDER=Visual Studio 16 2019
|
||||||
)
|
set CMAKE_BUILD_ARCH=-A x64
|
||||||
if "%1" == "2015" (
|
|
||||||
set CMAKE_BUILDER=Visual Studio 14 2015 Win64
|
|
||||||
)
|
)
|
||||||
if "%1" == "2017" (
|
if "%1" == "2017" (
|
||||||
set CMAKE_BUILDER=Visual Studio 15 2017 Win64
|
set CMAKE_BUILDER=Visual Studio 15 2017 Win64
|
||||||
|
set CMAKE_BUILD_ARCH=
|
||||||
)
|
)
|
||||||
|
|
||||||
goto start
|
goto start
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -120,7 +95,7 @@ set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads
|
|||||||
mkdir %STAGING%\%BuildDir%%ARCH%R
|
mkdir %STAGING%\%BuildDir%%ARCH%R
|
||||||
cd %Staging%\%BuildDir%%ARCH%R
|
cd %Staging%\%BuildDir%%ARCH%R
|
||||||
echo %DATE% %TIME% : Start > %StatusFile%
|
echo %DATE% %TIME% : Start > %StatusFile%
|
||||||
cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/
|
cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/
|
||||||
echo %DATE% %TIME% : Release Configuration done >> %StatusFile%
|
echo %DATE% %TIME% : Release Configuration done >> %StatusFile%
|
||||||
if "%dobuild%" == "1" (
|
if "%dobuild%" == "1" (
|
||||||
msbuild /m "ll.vcxproj" /p:Configuration=Release /fl /flp:logfile=BlenderDeps_llvm.log;Verbosity=normal
|
msbuild /m "ll.vcxproj" /p:Configuration=Release /fl /flp:logfile=BlenderDeps_llvm.log;Verbosity=normal
|
||||||
@@ -133,7 +108,7 @@ if "%NODEBUG%" == "1" goto exit
|
|||||||
cd %BUILD_DIR%
|
cd %BUILD_DIR%
|
||||||
mkdir %STAGING%\%BuildDir%%ARCH%D
|
mkdir %STAGING%\%BuildDir%%ARCH%D
|
||||||
cd %Staging%\%BuildDir%%ARCH%D
|
cd %Staging%\%BuildDir%%ARCH%D
|
||||||
cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS%
|
cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS%
|
||||||
echo %DATE% %TIME% : Debug Configuration done >> %StatusFile%
|
echo %DATE% %TIME% : Debug Configuration done >> %StatusFile%
|
||||||
if "%dobuild%" == "1" (
|
if "%dobuild%" == "1" (
|
||||||
msbuild /m "ll.vcxproj" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps_llvm.log;;Verbosity=normal
|
msbuild /m "ll.vcxproj" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps_llvm.log;;Verbosity=normal
|
||||||
|
83
build_files/cmake/Modules/FindBrotli.cmake
Normal file
83
build_files/cmake/Modules/FindBrotli.cmake
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# - Find Brotli library (compression for freetype/woff2).
|
||||||
|
# This module defines
|
||||||
|
# BROTLI_INCLUDE_DIRS, where to find Brotli headers, Set when
|
||||||
|
# BROTLI_INCLUDE_DIR is found.
|
||||||
|
# BROTLI_LIBRARIES, libraries to link against to use Brotli.
|
||||||
|
# BROTLI_ROOT_DIR, The base directory to search for Brotli.
|
||||||
|
# This can also be an environment variable.
|
||||||
|
# BROTLI_FOUND, If false, do not try to use Brotli.
|
||||||
|
#
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2022 Blender Foundation.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License,
|
||||||
|
# see accompanying file BSD-3-Clause-license.txt for details.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# If BROTLI_ROOT_DIR was defined in the environment, use it.
|
||||||
|
IF(NOT BROTLI_ROOT_DIR AND NOT $ENV{BROTLI_ROOT_DIR} STREQUAL "")
|
||||||
|
SET(BROTLI_ROOT_DIR $ENV{BROTLI_ROOT_DIR})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET(_BROTLI_SEARCH_DIRS
|
||||||
|
${BROTLI_ROOT_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(BROTLI_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
brotli/decode.h
|
||||||
|
HINTS
|
||||||
|
${_BROTLI_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
DOC "Brotli header files"
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(BROTLI_LIBRARY_COMMON
|
||||||
|
NAMES
|
||||||
|
# Some builds use a special `-static` postfix in their static libraries names.
|
||||||
|
brotlicommon-static
|
||||||
|
brotlicommon
|
||||||
|
HINTS
|
||||||
|
${_BROTLI_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib lib/static
|
||||||
|
DOC "Brotli static common library"
|
||||||
|
)
|
||||||
|
FIND_LIBRARY(BROTLI_LIBRARY_DEC
|
||||||
|
NAMES
|
||||||
|
# Some builds use a special `-static` postfix in their static libraries names.
|
||||||
|
brotlidec-static
|
||||||
|
brotlidec
|
||||||
|
HINTS
|
||||||
|
${_BROTLI_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib lib/static
|
||||||
|
DOC "Brotli static decode library"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
IF(${BROTLI_LIBRARY_COMMON_NOTFOUND} or ${BROTLI_LIBRARY_DEC_NOTFOUND})
|
||||||
|
set(BROTLI_FOUND FALSE)
|
||||||
|
ELSE()
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set BROTLI_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Brotli DEFAULT_MSG BROTLI_LIBRARY_COMMON BROTLI_LIBRARY_DEC BROTLI_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF(BROTLI_FOUND)
|
||||||
|
get_filename_component(BROTLI_LIBRARY_DIR ${BROTLI_LIBRARY_COMMON} DIRECTORY)
|
||||||
|
SET(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
|
||||||
|
SET(BROTLI_LIBRARIES ${BROTLI_LIBRARY_DEC} ${BROTLI_LIBRARY_COMMON})
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
BROTLI_INCLUDE_DIR
|
||||||
|
BROTLI_LIBRARY_COMMON
|
||||||
|
BROTLI_LIBRARY_DEC
|
||||||
|
BROTLI_LIBRARY_DIR
|
||||||
|
)
|
||||||
|
|
||||||
|
UNSET(_BROTLI_SEARCH_DIRS)
|
@@ -33,6 +33,8 @@ if(NOT FFMPEG_FIND_COMPONENTS)
|
|||||||
avfilter
|
avfilter
|
||||||
avformat
|
avformat
|
||||||
avutil
|
avutil
|
||||||
|
swscale
|
||||||
|
swresample
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -50,9 +52,9 @@ foreach(_component ${FFMPEG_FIND_COMPONENTS})
|
|||||||
string(TOUPPER ${_component} _upper_COMPONENT)
|
string(TOUPPER ${_component} _upper_COMPONENT)
|
||||||
find_library(FFMPEG_${_upper_COMPONENT}_LIBRARY
|
find_library(FFMPEG_${_upper_COMPONENT}_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
${_upper_COMPONENT}
|
${_component}
|
||||||
HINTS
|
HINTS
|
||||||
${LIBDIR}/ffmpeg
|
${_ffmpeg_SEARCH_DIRS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
lib64 lib
|
lib64 lib
|
||||||
)
|
)
|
||||||
@@ -80,4 +82,6 @@ mark_as_advanced(
|
|||||||
|
|
||||||
unset(_ffmpeg_SEARCH_DIRS)
|
unset(_ffmpeg_SEARCH_DIRS)
|
||||||
unset(_ffmpeg_LIBRARIES)
|
unset(_ffmpeg_LIBRARIES)
|
||||||
unset(_ffmpeg_INCLUDE_DIR)
|
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||||
|
# find_path so we don't need to clear it from the cache here.
|
||||||
|
unset(_ffmpeg_INCLUDE_DIR CACHE)
|
||||||
|
@@ -76,6 +76,7 @@ FIND_PATH(OSL_SHADER_DIR
|
|||||||
/usr/include/OSL/
|
/usr/include/OSL/
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
share/OSL/shaders
|
share/OSL/shaders
|
||||||
|
shaders
|
||||||
)
|
)
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if
|
# handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if
|
||||||
@@ -99,6 +100,7 @@ ENDIF()
|
|||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
OSL_INCLUDE_DIR
|
OSL_INCLUDE_DIR
|
||||||
|
OSL_SHADER_DIR
|
||||||
)
|
)
|
||||||
FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
|
FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
|
||||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||||
|
@@ -87,12 +87,14 @@ ENDIF()
|
|||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
OPENCOLORIO_INCLUDE_DIR
|
OPENCOLORIO_INCLUDE_DIR
|
||||||
OPENCOLORIO_LIBRARY
|
OPENCOLORIO_LIBRARY
|
||||||
OPENCOLORIO_OPENCOLORIO_LIBRARY
|
|
||||||
OPENCOLORIO_TINYXML_LIBRARY
|
|
||||||
OPENCOLORIO_YAML-CPP_LIBRARY
|
|
||||||
OPENCOLORIO_VERSION
|
OPENCOLORIO_VERSION
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS})
|
||||||
|
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||||
|
MARK_AS_ADVANCED(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY)
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
UNSET(COMPONENT)
|
UNSET(COMPONENT)
|
||||||
UNSET(UPPERCOMPONENT)
|
UNSET(UPPERCOMPONENT)
|
||||||
UNSET(_opencolorio_FIND_COMPONENTS)
|
UNSET(_opencolorio_FIND_COMPONENTS)
|
||||||
|
@@ -33,14 +33,6 @@ ENDIF()
|
|||||||
# Old versions (before 2.0?) do not have any version string, just assuming this should be fine though.
|
# Old versions (before 2.0?) do not have any version string, just assuming this should be fine though.
|
||||||
SET(_openexr_libs_ver_init "2.0")
|
SET(_openexr_libs_ver_init "2.0")
|
||||||
|
|
||||||
SET(_openexr_FIND_COMPONENTS
|
|
||||||
Half
|
|
||||||
Iex
|
|
||||||
IlmImf
|
|
||||||
IlmThread
|
|
||||||
Imath
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(_openexr_SEARCH_DIRS
|
SET(_openexr_SEARCH_DIRS
|
||||||
${OPENEXR_ROOT_DIR}
|
${OPENEXR_ROOT_DIR}
|
||||||
/opt/lib/openexr
|
/opt/lib/openexr
|
||||||
@@ -93,6 +85,24 @@ UNSET(_openexr_libs_ver_init)
|
|||||||
|
|
||||||
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
|
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
|
||||||
|
|
||||||
|
# Different library names in 3.0, and Imath and Half moved out.
|
||||||
|
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||||
|
SET(_openexr_FIND_COMPONENTS
|
||||||
|
Iex
|
||||||
|
IlmThread
|
||||||
|
OpenEXR
|
||||||
|
OpenEXRCore
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
SET(_openexr_FIND_COMPONENTS
|
||||||
|
Half
|
||||||
|
Iex
|
||||||
|
IlmImf
|
||||||
|
IlmThread
|
||||||
|
Imath
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET(_openexr_LIBRARIES)
|
SET(_openexr_LIBRARIES)
|
||||||
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
||||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||||
@@ -111,6 +121,57 @@ ENDFOREACH()
|
|||||||
|
|
||||||
UNSET(_openexr_libs_ver)
|
UNSET(_openexr_libs_ver)
|
||||||
|
|
||||||
|
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||||
|
# For OpenEXR 3.x, we also need to find the now separate Imath library.
|
||||||
|
# For simplicity we add it to the OpenEXR includes and libraries, as we
|
||||||
|
# have no direct dependency on Imath and it's simpler to support both
|
||||||
|
# 2.x and 3.x this way.
|
||||||
|
|
||||||
|
# Find include directory
|
||||||
|
FIND_PATH(IMATH_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
Imath/ImathMath.h
|
||||||
|
HINTS
|
||||||
|
${_openexr_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find version
|
||||||
|
FIND_FILE(_imath_config
|
||||||
|
NAMES
|
||||||
|
ImathConfig.h
|
||||||
|
PATHS
|
||||||
|
${IMATH_INCLUDE_DIR}/Imath
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find line with version, extract string, and format for library suffix.
|
||||||
|
FILE(STRINGS "${_imath_config}" _imath_build_specification
|
||||||
|
REGEX "^[ \t]*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"[.0-9]+\".*$")
|
||||||
|
STRING(REGEX REPLACE ".*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"([.0-9]+)\".*"
|
||||||
|
"\\1" _imath_libs_ver ${_imath_build_specification})
|
||||||
|
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _imath_libs_ver ${_imath_libs_ver})
|
||||||
|
|
||||||
|
# Find library, with or without version number.
|
||||||
|
FIND_LIBRARY(IMATH_LIBRARY
|
||||||
|
NAMES
|
||||||
|
Imath-${_imath_libs_ver} Imath
|
||||||
|
NAMES_PER_DIR
|
||||||
|
HINTS
|
||||||
|
${_openexr_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib
|
||||||
|
)
|
||||||
|
LIST(APPEND _openexr_LIBRARIES "${IMATH_LIBRARY}")
|
||||||
|
|
||||||
|
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||||
|
# FIND_FILE so we don't need to clear it from the cache here.
|
||||||
|
UNSET(_imath_config CACHE)
|
||||||
|
UNSET(_imath_libs_ver)
|
||||||
|
UNSET(_imath_build_specification)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set OPENEXR_FOUND to TRUE if
|
# handle the QUIETLY and REQUIRED arguments and set OPENEXR_FOUND to TRUE if
|
||||||
# all listed variables are TRUE
|
# all listed variables are TRUE
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
@@ -119,13 +180,25 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenEXR DEFAULT_MSG
|
|||||||
|
|
||||||
IF(OPENEXR_FOUND)
|
IF(OPENEXR_FOUND)
|
||||||
SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES})
|
SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES})
|
||||||
# Both include paths are needed because of dummy OSL headers mixing #include <OpenEXR/foo.h> and #include <foo.h> :(
|
# Both include paths are needed because of dummy OSL headers mixing
|
||||||
SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR)
|
# #include <OpenEXR/foo.h> and #include <foo.h>, as well as Alembic
|
||||||
|
# include <half.h> directly.
|
||||||
|
SET(OPENEXR_INCLUDE_DIRS
|
||||||
|
${OPENEXR_INCLUDE_DIR}
|
||||||
|
${OPENEXR_INCLUDE_DIR}/OpenEXR)
|
||||||
|
|
||||||
|
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||||
|
LIST(APPEND OPENEXR_INCLUDE_DIRS
|
||||||
|
${IMATH_INCLUDE_DIR}
|
||||||
|
${IMATH_INCLUDE_DIR}/Imath)
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
OPENEXR_INCLUDE_DIR
|
OPENEXR_INCLUDE_DIR
|
||||||
OPENEXR_VERSION
|
OPENEXR_VERSION
|
||||||
|
IMATH_INCLUDE_DIR
|
||||||
|
IMATH_LIBRARY
|
||||||
)
|
)
|
||||||
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
||||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||||
|
@@ -110,6 +110,7 @@ ENDIF()
|
|||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
OPENIMAGEDENOISE_INCLUDE_DIR
|
OPENIMAGEDENOISE_INCLUDE_DIR
|
||||||
|
OPENIMAGEDENOISE_LIBRARY
|
||||||
)
|
)
|
||||||
|
|
||||||
FOREACH(COMPONENT ${_openimagedenoise_FIND_COMPONENTS})
|
FOREACH(COMPONENT ${_openimagedenoise_FIND_COMPONENTS})
|
||||||
|
@@ -48,6 +48,8 @@ FIND_LIBRARY(OPENIMAGEIO_LIBRARY
|
|||||||
lib64 lib
|
lib64 lib
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(_openimageio_LIBRARIES ${OPENIMAGEIO_LIBRARY})
|
||||||
|
|
||||||
FIND_FILE(OPENIMAGEIO_IDIFF
|
FIND_FILE(OPENIMAGEIO_IDIFF
|
||||||
NAMES
|
NAMES
|
||||||
idiff
|
idiff
|
||||||
@@ -57,14 +59,47 @@ FIND_FILE(OPENIMAGEIO_IDIFF
|
|||||||
bin
|
bin
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Additionally find util library if needed. In old versions this library was
|
||||||
|
# included in libOpenImageIO and linking to both would duplicate symbols. In
|
||||||
|
# new versions we need to link to both.
|
||||||
|
FIND_FILE(_openimageio_export
|
||||||
|
NAMES
|
||||||
|
export.h
|
||||||
|
PATHS
|
||||||
|
${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use existence of OIIO_UTIL_API to check if it's a separate lib.
|
||||||
|
FILE(STRINGS "${_openimageio_export}" _openimageio_util_define
|
||||||
|
REGEX "^[ \t]*#[ \t]*define[ \t]+OIIO_UTIL_API.*$")
|
||||||
|
|
||||||
|
IF(_openimageio_util_define)
|
||||||
|
FIND_LIBRARY(OPENIMAGEIO_UTIL_LIBRARY
|
||||||
|
NAMES
|
||||||
|
OpenImageIO_Util
|
||||||
|
HINTS
|
||||||
|
${_openimageio_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib
|
||||||
|
)
|
||||||
|
|
||||||
|
LIST(APPEND _openimageio_LIBRARIES ${OPENIMAGEIO_UTIL_LIBRARY})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||||
|
# FIND_FILE so we don't need to clear it from the cache here.
|
||||||
|
UNSET(_openimageio_export CACHE)
|
||||||
|
UNSET(_openimageio_util_define)
|
||||||
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set OPENIMAGEIO_FOUND to TRUE if
|
# handle the QUIETLY and REQUIRED arguments and set OPENIMAGEIO_FOUND to TRUE if
|
||||||
# all listed variables are TRUE
|
# all listed variables are TRUE
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG
|
||||||
OPENIMAGEIO_LIBRARY OPENIMAGEIO_INCLUDE_DIR)
|
_openimageio_LIBRARIES OPENIMAGEIO_INCLUDE_DIR)
|
||||||
|
|
||||||
IF(OPENIMAGEIO_FOUND)
|
IF(OPENIMAGEIO_FOUND)
|
||||||
SET(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
|
SET(OPENIMAGEIO_LIBRARIES ${_openimageio_LIBRARIES})
|
||||||
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
|
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
|
||||||
IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
|
IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
|
||||||
SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
|
SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
|
||||||
@@ -78,7 +113,9 @@ ENDIF()
|
|||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
OPENIMAGEIO_INCLUDE_DIR
|
OPENIMAGEIO_INCLUDE_DIR
|
||||||
OPENIMAGEIO_LIBRARY
|
OPENIMAGEIO_LIBRARY
|
||||||
|
OPENIMAGEIO_UTIL_LIBRARY
|
||||||
OPENIMAGEIO_IDIFF
|
OPENIMAGEIO_IDIFF
|
||||||
)
|
)
|
||||||
|
|
||||||
UNSET(_openimageio_SEARCH_DIRS)
|
UNSET(_openimageio_SEARCH_DIRS)
|
||||||
|
UNSET(_openimageio_LIBRARIES)
|
||||||
|
@@ -21,7 +21,7 @@ ENDIF()
|
|||||||
|
|
||||||
SET(_optix_SEARCH_DIRS
|
SET(_optix_SEARCH_DIRS
|
||||||
${OPTIX_ROOT_DIR}
|
${OPTIX_ROOT_DIR}
|
||||||
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.0.0"
|
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_PATH(OPTIX_INCLUDE_DIR
|
FIND_PATH(OPTIX_INCLUDE_DIR
|
||||||
|
@@ -34,7 +34,7 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
|
|||||||
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
|
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
SET(PYTHON_VERSION 3.9 CACHE STRING "Python Version (major and minor only)")
|
SET(PYTHON_VERSION 3.10 CACHE STRING "Python Version (major and minor only)")
|
||||||
MARK_AS_ADVANCED(PYTHON_VERSION)
|
MARK_AS_ADVANCED(PYTHON_VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -114,7 +114,7 @@ def is_c_header(filename: str) -> bool:
|
|||||||
|
|
||||||
def is_c(filename: str) -> bool:
|
def is_c(filename: str) -> bool:
|
||||||
ext = splitext(filename)[1]
|
ext = splitext(filename)[1]
|
||||||
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
|
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".metal"})
|
||||||
|
|
||||||
|
|
||||||
def is_c_any(filename: str) -> bool:
|
def is_c_any(filename: str) -> bool:
|
||||||
|
@@ -488,7 +488,6 @@ function(blender_add_test_executable
|
|||||||
|
|
||||||
include_directories(${includes})
|
include_directories(${includes})
|
||||||
include_directories(${includes_sys})
|
include_directories(${includes_sys})
|
||||||
setup_libdirs()
|
|
||||||
|
|
||||||
BLENDER_SRC_GTEST_EX(
|
BLENDER_SRC_GTEST_EX(
|
||||||
NAME ${name}
|
NAME ${name}
|
||||||
@@ -525,83 +524,6 @@ function(setup_heavy_lib_pool)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(SETUP_LIBDIRS)
|
|
||||||
|
|
||||||
# NOTE: For all new libraries, use absolute library paths.
|
|
||||||
# This should eventually be phased out.
|
|
||||||
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
|
|
||||||
if(NOT MSVC AND NOT APPLE)
|
|
||||||
link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
|
|
||||||
|
|
||||||
if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs
|
|
||||||
link_directories(${PYTHON_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_SDL AND NOT WITH_SDL_DYNLOAD)
|
|
||||||
link_directories(${SDL_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_CODEC_FFMPEG)
|
|
||||||
link_directories(${FFMPEG_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_IMAGE_OPENEXR)
|
|
||||||
link_directories(${OPENEXR_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_IMAGE_TIFF)
|
|
||||||
link_directories(${TIFF_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_BOOST)
|
|
||||||
link_directories(${BOOST_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENIMAGEIO)
|
|
||||||
link_directories(${OPENIMAGEIO_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENIMAGEDENOISE)
|
|
||||||
link_directories(${OPENIMAGEDENOISE_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENCOLORIO)
|
|
||||||
link_directories(${OPENCOLORIO_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENVDB)
|
|
||||||
link_directories(${OPENVDB_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENAL)
|
|
||||||
link_directories(${OPENAL_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_JACK AND NOT WITH_JACK_DYNLOAD)
|
|
||||||
link_directories(${JACK_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_PULSEAUDIO AND NOT WITH_PULSEAUDIO_DYNLOAD)
|
|
||||||
link_directories(${LIBPULSE_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_CODEC_SNDFILE)
|
|
||||||
link_directories(${LIBSNDFILE_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_FFTW3)
|
|
||||||
link_directories(${FFTW3_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENCOLLADA)
|
|
||||||
link_directories(${OPENCOLLADA_LIBPATH})
|
|
||||||
# # Never set
|
|
||||||
# link_directories(${PCRE_LIBPATH})
|
|
||||||
# link_directories(${EXPAT_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_LLVM)
|
|
||||||
link_directories(${LLVM_LIBPATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_ALEMBIC)
|
|
||||||
link_directories(${ALEMBIC_LIBPATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_GMP)
|
|
||||||
link_directories(${GMP_LIBPATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
link_directories(${PTHREADS_LIBPATH})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Platform specific linker flags for targets.
|
# Platform specific linker flags for targets.
|
||||||
function(setup_platform_linker_flags
|
function(setup_platform_linker_flags
|
||||||
target)
|
target)
|
||||||
@@ -1275,43 +1197,20 @@ endfunction()
|
|||||||
macro(openmp_delayload
|
macro(openmp_delayload
|
||||||
projectname
|
projectname
|
||||||
)
|
)
|
||||||
if(MSVC)
|
|
||||||
if(WITH_OPENMP)
|
|
||||||
if(MSVC_CLANG)
|
|
||||||
set(OPENMP_DLL_NAME "libomp")
|
|
||||||
elseif(MSVC_VERSION EQUAL 1800)
|
|
||||||
set(OPENMP_DLL_NAME "vcomp120")
|
|
||||||
else()
|
|
||||||
set(OPENMP_DLL_NAME "vcomp140")
|
|
||||||
endif()
|
|
||||||
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
|
||||||
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /DELAYLOAD:${OPENMP_DLL_NAME}d.dll delayimp.lib")
|
|
||||||
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
|
||||||
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(blender_precompile_headers target cpp header)
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# get the name for the pch output file
|
if(WITH_OPENMP)
|
||||||
get_filename_component(pchbase ${cpp} NAME_WE)
|
if(MSVC_CLANG)
|
||||||
set(pchfinal "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${pchbase}.pch")
|
set(OPENMP_DLL_NAME "libomp")
|
||||||
|
elseif(MSVC_VERSION EQUAL 1800)
|
||||||
# mark the cpp as the one outputting the pch
|
set(OPENMP_DLL_NAME "vcomp120")
|
||||||
set_property(SOURCE ${cpp} APPEND PROPERTY OBJECT_OUTPUTS "${pchfinal}")
|
else()
|
||||||
|
set(OPENMP_DLL_NAME "vcomp140")
|
||||||
# get all sources for the target
|
endif()
|
||||||
get_target_property(sources ${target} SOURCES)
|
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
||||||
|
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /DELAYLOAD:${OPENMP_DLL_NAME}d.dll delayimp.lib")
|
||||||
# make all sources depend on the pch to enforce the build order
|
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
||||||
foreach(src ${sources})
|
set_property(TARGET ${projectname} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL " /DELAYLOAD:${OPENMP_DLL_NAME}.dll delayimp.lib")
|
||||||
set_property(SOURCE ${src} APPEND PROPERTY OBJECT_DEPENDS "${pchfinal}")
|
endif()
|
||||||
endforeach()
|
|
||||||
|
|
||||||
target_sources(${target} PRIVATE ${cpp} ${header})
|
|
||||||
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "/Yu${header} /Fp${pchfinal} /FI${header}")
|
|
||||||
set_source_files_properties(${cpp} PROPERTIES COMPILE_FLAGS "/Yc${header} /Fp${pchfinal}")
|
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
@@ -128,25 +128,20 @@ if(WITH_CODEC_SNDFILE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_PYTHON)
|
if(WITH_PYTHON)
|
||||||
# we use precompiled libraries for py 3.9 and up by default
|
# Use precompiled libraries by default.
|
||||||
set(PYTHON_VERSION 3.9)
|
set(PYTHON_VERSION 3.10)
|
||||||
if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
|
if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
|
||||||
# normally cached but not since we include them with blender
|
# Normally cached but not since we include them with blender.
|
||||||
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}")
|
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}")
|
||||||
set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}")
|
set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}")
|
||||||
set(PYTHON_LIBRARY ${LIBDIR}/python/lib/libpython${PYTHON_VERSION}.a)
|
set(PYTHON_LIBRARY ${LIBDIR}/python/lib/libpython${PYTHON_VERSION}.a)
|
||||||
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
|
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
|
||||||
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
|
|
||||||
else()
|
else()
|
||||||
# module must be compiled against Python framework
|
# Module must be compiled against Python framework.
|
||||||
set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}")
|
set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}")
|
||||||
|
|
||||||
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
|
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
|
||||||
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
|
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
|
||||||
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}")
|
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}")
|
||||||
# set(PYTHON_LIBRARY python${PYTHON_VERSION})
|
|
||||||
# set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
|
|
||||||
|
|
||||||
unset(_py_framework)
|
unset(_py_framework)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -166,13 +161,18 @@ if(WITH_FFTW3)
|
|||||||
find_package(Fftw3)
|
find_package(Fftw3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# FreeType compiled with Brotli compression for woff2.
|
||||||
find_package(Freetype REQUIRED)
|
find_package(Freetype REQUIRED)
|
||||||
|
list(APPEND FREETYPE_LIBRARIES
|
||||||
|
${LIBDIR}/brotli/lib/libbrotlicommon-static.a
|
||||||
|
${LIBDIR}/brotli/lib/libbrotlidec-static.a)
|
||||||
|
|
||||||
if(WITH_IMAGE_OPENEXR)
|
if(WITH_IMAGE_OPENEXR)
|
||||||
find_package(OpenEXR)
|
find_package(OpenEXR)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CODEC_FFMPEG)
|
if(WITH_CODEC_FFMPEG)
|
||||||
|
set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg)
|
||||||
set(FFMPEG_FIND_COMPONENTS
|
set(FFMPEG_FIND_COMPONENTS
|
||||||
avcodec avdevice avformat avutil
|
avcodec avdevice avformat avutil
|
||||||
mp3lame ogg opus swresample swscale
|
mp3lame ogg opus swresample swscale
|
||||||
@@ -479,8 +479,11 @@ string(APPEND PLATFORM_LINKFLAGS " -stdlib=libc++")
|
|||||||
# Suppress ranlib "has no symbols" warnings (workaround for T48250)
|
# Suppress ranlib "has no symbols" warnings (workaround for T48250)
|
||||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||||
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
# llvm-ranlib doesn't support this flag. Xcode's libtool does.
|
||||||
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
if(NOT ${CMAKE_RANLIB} MATCHES ".*llvm-ranlib$")
|
||||||
|
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
||||||
|
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_COMPILER_CCACHE)
|
if(WITH_COMPILER_CCACHE)
|
||||||
if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
|
if(NOT CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
@@ -507,3 +510,6 @@ list(APPEND CMAKE_BUILD_RPATH "${OpenMP_LIBRARY_DIR}")
|
|||||||
|
|
||||||
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
|
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
|
||||||
list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib")
|
list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib")
|
||||||
|
|
||||||
|
# Same as `CFBundleIdentifier` in Info.plist.
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.blenderfoundation.blender")
|
||||||
|
@@ -96,7 +96,7 @@ else()
|
|||||||
# Detect SDK version to use.
|
# Detect SDK version to use.
|
||||||
if(NOT DEFINED OSX_SYSTEM)
|
if(NOT DEFINED OSX_SYSTEM)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND xcrun --show-sdk-version
|
COMMAND xcrun --sdk macosx --show-sdk-version
|
||||||
OUTPUT_VARIABLE OSX_SYSTEM
|
OUTPUT_VARIABLE OSX_SYSTEM
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
# ***** END GPL LICENSE BLOCK *****
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
# Libraries configuration for any *nix system including Linux and Unix.
|
# Libraries configuration for any *nix system including Linux and Unix (excluding APPLE).
|
||||||
|
|
||||||
# Detect precompiled library directory
|
# Detect precompiled library directory
|
||||||
if(NOT DEFINED LIBDIR)
|
if(NOT DEFINED LIBDIR)
|
||||||
@@ -48,6 +48,9 @@ if(NOT DEFINED LIBDIR)
|
|||||||
unset(LIBDIR_CENTOS7_ABI)
|
unset(LIBDIR_CENTOS7_ABI)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Support restoring this value once pre-compiled libraries have been handled.
|
||||||
|
set(WITH_STATIC_LIBS_INIT ${WITH_STATIC_LIBS})
|
||||||
|
|
||||||
if(EXISTS ${LIBDIR})
|
if(EXISTS ${LIBDIR})
|
||||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||||
|
|
||||||
@@ -100,7 +103,22 @@ find_package_wrapper(JPEG REQUIRED)
|
|||||||
find_package_wrapper(PNG REQUIRED)
|
find_package_wrapper(PNG REQUIRED)
|
||||||
find_package_wrapper(ZLIB REQUIRED)
|
find_package_wrapper(ZLIB REQUIRED)
|
||||||
find_package_wrapper(Zstd REQUIRED)
|
find_package_wrapper(Zstd REQUIRED)
|
||||||
find_package_wrapper(Freetype REQUIRED)
|
|
||||||
|
if(NOT WITH_SYSTEM_FREETYPE)
|
||||||
|
# FreeType compiled with Brotli compression for woff2.
|
||||||
|
find_package_wrapper(Freetype REQUIRED)
|
||||||
|
if(EXISTS ${LIBDIR})
|
||||||
|
find_package_wrapper(Brotli REQUIRED)
|
||||||
|
|
||||||
|
# NOTE: This is done on WIN32 & APPLE but fails on some Linux systems.
|
||||||
|
# See: https://devtalk.blender.org/t/22536
|
||||||
|
# So `BROTLI_LIBRARIES` need to be added directly after `FREETYPE_LIBRARIES`.
|
||||||
|
#
|
||||||
|
# list(APPEND FREETYPE_LIBRARIES
|
||||||
|
# ${BROTLI_LIBRARIES}
|
||||||
|
# )
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_PYTHON)
|
if(WITH_PYTHON)
|
||||||
# No way to set py35, remove for now.
|
# No way to set py35, remove for now.
|
||||||
@@ -178,26 +196,30 @@ endif()
|
|||||||
|
|
||||||
if(WITH_CODEC_FFMPEG)
|
if(WITH_CODEC_FFMPEG)
|
||||||
if(EXISTS ${LIBDIR})
|
if(EXISTS ${LIBDIR})
|
||||||
# For precompiled lib directory, all ffmpeg dependencies are in the same folder
|
set(FFMPEG_ROOT_DIR ${LIBDIR}/ffmpeg)
|
||||||
file(GLOB ffmpeg_libs ${LIBDIR}/ffmpeg/lib/*.a ${LIBDIR}/sndfile/lib/*.a)
|
# Override FFMPEG components to also include static library dependencies
|
||||||
set(FFMPEG ${LIBDIR}/ffmpeg CACHE PATH "FFMPEG Directory")
|
# included with precompiled libraries, and to ensure correct link order.
|
||||||
set(FFMPEG_LIBRARIES ${ffmpeg_libs} ${ffmpeg_libs} CACHE STRING "FFMPEG Libraries")
|
set(FFMPEG_FIND_COMPONENTS
|
||||||
else()
|
avformat avcodec avdevice avutil swresample swscale
|
||||||
set(FFMPEG /usr CACHE PATH "FFMPEG Directory")
|
sndfile
|
||||||
set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries")
|
FLAC
|
||||||
|
mp3lame
|
||||||
|
opus
|
||||||
|
theora theoradec theoraenc
|
||||||
|
vorbis vorbisenc vorbisfile ogg
|
||||||
|
vpx
|
||||||
|
x264
|
||||||
|
xvidcore)
|
||||||
|
elseif(FFMPEG)
|
||||||
|
# Old cache variable used for root dir, convert to new standard.
|
||||||
|
set(FFMPEG_ROOT_DIR ${FFMPEG})
|
||||||
endif()
|
endif()
|
||||||
|
find_package(FFmpeg)
|
||||||
|
|
||||||
mark_as_advanced(FFMPEG)
|
if(NOT FFMPEG_FOUND)
|
||||||
|
set(WITH_CODEC_FFMPEG OFF)
|
||||||
# lame, but until we have proper find module for ffmpeg
|
message(STATUS "FFmpeg not found, disabling it")
|
||||||
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
|
|
||||||
if(EXISTS "${FFMPEG}/include/ffmpeg/")
|
|
||||||
list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg")
|
|
||||||
endif()
|
endif()
|
||||||
# end lameness
|
|
||||||
|
|
||||||
mark_as_advanced(FFMPEG_LIBRARIES)
|
|
||||||
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_FFTW3)
|
if(WITH_FFTW3)
|
||||||
@@ -340,6 +362,7 @@ if(WITH_BOOST)
|
|||||||
find_package(IcuLinux)
|
find_package(IcuLinux)
|
||||||
endif()
|
endif()
|
||||||
mark_as_advanced(Boost_DIR) # why doesn't boost do this?
|
mark_as_advanced(Boost_DIR) # why doesn't boost do this?
|
||||||
|
mark_as_advanced(Boost_INCLUDE_DIR) # why doesn't boost do this?
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
|
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
|
||||||
@@ -532,6 +555,21 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
|||||||
#
|
#
|
||||||
# Keep last, so indirectly linked libraries don't override our own pre-compiled libs.
|
# Keep last, so indirectly linked libraries don't override our own pre-compiled libs.
|
||||||
|
|
||||||
|
if(EXISTS ${LIBDIR})
|
||||||
|
# Clear the prefix path as it causes the `LIBDIR` to override system locations.
|
||||||
|
unset(CMAKE_PREFIX_PATH)
|
||||||
|
|
||||||
|
# Since the pre-compiled `LIBDIR` directories have been handled, don't prefer static libraries.
|
||||||
|
set(WITH_STATIC_LIBS ${WITH_STATIC_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_SYSTEM_FREETYPE)
|
||||||
|
find_package_wrapper(Freetype)
|
||||||
|
if(NOT FREETYPE_FOUND)
|
||||||
|
message(FATAL_ERROR "Failed finding system FreeType version!")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_LZO AND WITH_SYSTEM_LZO)
|
if(WITH_LZO AND WITH_SYSTEM_LZO)
|
||||||
find_package_wrapper(LZO)
|
find_package_wrapper(LZO)
|
||||||
if(NOT LZO_FOUND)
|
if(NOT LZO_FOUND)
|
||||||
@@ -644,6 +682,9 @@ endif()
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Compilers
|
# Compilers
|
||||||
|
|
||||||
|
# Only set the linker once.
|
||||||
|
set(_IS_LINKER_DEFAULT ON)
|
||||||
|
|
||||||
# GNU Compiler
|
# GNU Compiler
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
# ffp-contract=off:
|
# ffp-contract=off:
|
||||||
@@ -662,26 +703,89 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
|||||||
string(PREPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GCC_EXTRA_FLAGS_RELEASE} ")
|
string(PREPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GCC_EXTRA_FLAGS_RELEASE} ")
|
||||||
unset(GCC_EXTRA_FLAGS_RELEASE)
|
unset(GCC_EXTRA_FLAGS_RELEASE)
|
||||||
|
|
||||||
if(WITH_LINKER_GOLD)
|
# NOTE(@campbellbarton): Eventually mold will be able to use `-fuse-ld=mold`,
|
||||||
|
# however at the moment this only works for GCC 12.1+ (unreleased at time of writing).
|
||||||
|
# So a workaround is used here "-B" which points to another path to find system commands
|
||||||
|
# such as `ld`.
|
||||||
|
if(WITH_LINKER_MOLD AND _IS_LINKER_DEFAULT)
|
||||||
|
find_program(MOLD_BIN "mold")
|
||||||
|
mark_as_advanced(MOLD_BIN)
|
||||||
|
if(NOT MOLD_BIN)
|
||||||
|
message(STATUS "The \"mold\" binary could not be found, using system linker.")
|
||||||
|
set(WITH_LINKER_MOLD OFF)
|
||||||
|
else()
|
||||||
|
# By default mold installs the binary to:
|
||||||
|
# - `{PREFIX}/bin/mold` as well as a symbolic-link in...
|
||||||
|
# - `{PREFIX}/lib/mold/ld`.
|
||||||
|
# (where `PREFIX` is typically `/usr/`).
|
||||||
|
#
|
||||||
|
# This block of code finds `{PREFIX}/lib/mold` from the `mold` binary.
|
||||||
|
# Other methods of searching for the path could also be made to work,
|
||||||
|
# we could even make our own directory and symbolic-link, however it's more
|
||||||
|
# convenient to use the one provided by mold.
|
||||||
|
#
|
||||||
|
# Use the binary path to "mold", to find the common prefix which contains "lib/mold".
|
||||||
|
# The parent directory: e.g. `/usr/bin/mold` -> `/usr/bin/`.
|
||||||
|
get_filename_component(MOLD_PREFIX "${MOLD_BIN}" DIRECTORY)
|
||||||
|
# The common prefix path: e.g. `/usr/bin/` -> `/usr/` to use as a hint.
|
||||||
|
get_filename_component(MOLD_PREFIX "${MOLD_PREFIX}" DIRECTORY)
|
||||||
|
# Find `{PREFIX}/lib/mold/ld`, store the directory component (without the `ld`).
|
||||||
|
# Then pass `-B {PREFIX}/lib/mold` to GCC so the `ld` located there overrides the default.
|
||||||
|
find_path(
|
||||||
|
MOLD_BIN_DIR "ld"
|
||||||
|
HINTS "${MOLD_PREFIX}"
|
||||||
|
# The default path is `libexec`, Arch Linux for e.g.
|
||||||
|
# replaces this with `lib` so check both.
|
||||||
|
PATH_SUFFIXES "libexec/mold" "lib/mold" "lib64/mold"
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
NO_CACHE
|
||||||
|
)
|
||||||
|
if(NOT MOLD_BIN_DIR)
|
||||||
|
message(STATUS
|
||||||
|
"The mold linker could not find the directory containing the linker command "
|
||||||
|
"(typically "
|
||||||
|
"\"${MOLD_PREFIX}/libexec/mold/ld\") or "
|
||||||
|
"\"${MOLD_PREFIX}/lib/mold/ld\") using system linker.")
|
||||||
|
set(WITH_LINKER_MOLD OFF)
|
||||||
|
endif()
|
||||||
|
unset(MOLD_PREFIX)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_LINKER_MOLD)
|
||||||
|
# GCC will search for `ld` in this directory first.
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
|
||||||
|
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -B \"${MOLD_BIN_DIR}\"")
|
||||||
|
set(_IS_LINKER_DEFAULT OFF)
|
||||||
|
endif()
|
||||||
|
unset(MOLD_BIN)
|
||||||
|
unset(MOLD_BIN_DIR)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_LINKER_GOLD AND _IS_LINKER_DEFAULT)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
|
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
|
||||||
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||||
if("${LD_VERSION}" MATCHES "GNU gold")
|
if("${LD_VERSION}" MATCHES "GNU gold")
|
||||||
string(APPEND CMAKE_C_FLAGS " -fuse-ld=gold")
|
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fuse-ld=gold")
|
||||||
string(APPEND CMAKE_CXX_FLAGS " -fuse-ld=gold")
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -fuse-ld=gold")
|
||||||
|
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -fuse-ld=gold")
|
||||||
|
set(_IS_LINKER_DEFAULT OFF)
|
||||||
else()
|
else()
|
||||||
message(STATUS "GNU gold linker isn't available, using the default system linker.")
|
message(STATUS "GNU gold linker isn't available, using the default system linker.")
|
||||||
endif()
|
endif()
|
||||||
unset(LD_VERSION)
|
unset(LD_VERSION)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LINKER_LLD)
|
if(WITH_LINKER_LLD AND _IS_LINKER_DEFAULT)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=lld -Wl,--version
|
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=lld -Wl,--version
|
||||||
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||||
if("${LD_VERSION}" MATCHES "LLD")
|
if("${LD_VERSION}" MATCHES "LLD")
|
||||||
string(APPEND CMAKE_C_FLAGS " -fuse-ld=lld")
|
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fuse-ld=lld")
|
||||||
string(APPEND CMAKE_CXX_FLAGS " -fuse-ld=lld")
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -fuse-ld=lld")
|
||||||
|
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -fuse-ld=lld")
|
||||||
|
set(_IS_LINKER_DEFAULT OFF)
|
||||||
else()
|
else()
|
||||||
message(STATUS "LLD linker isn't available, using the default system linker.")
|
message(STATUS "LLD linker isn't available, using the default system linker.")
|
||||||
endif()
|
endif()
|
||||||
@@ -691,6 +795,28 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
|||||||
# CLang is the same as GCC for now.
|
# CLang is the same as GCC for now.
|
||||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||||
|
|
||||||
|
if(WITH_LINKER_MOLD AND _IS_LINKER_DEFAULT)
|
||||||
|
find_program(MOLD_BIN "mold")
|
||||||
|
mark_as_advanced(MOLD_BIN)
|
||||||
|
if(NOT MOLD_BIN)
|
||||||
|
message(STATUS "The \"mold\" binary could not be found, using system linker.")
|
||||||
|
set(WITH_LINKER_MOLD OFF)
|
||||||
|
else()
|
||||||
|
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS " --ld-path=\"${MOLD_BIN}\"")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS " --ld-path=\"${MOLD_BIN}\"")
|
||||||
|
string(APPEND CMAKE_MODULE_LINKER_FLAGS " --ld-path=\"${MOLD_BIN}\"")
|
||||||
|
else()
|
||||||
|
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fuse-ld=\"${MOLD_BIN}\"")
|
||||||
|
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -fuse-ld=\"${MOLD_BIN}\"")
|
||||||
|
string(APPEND CMAKE_MODULE_LINKER_FLAGS " -fuse-ld=\"${MOLD_BIN}\"")
|
||||||
|
endif()
|
||||||
|
set(_IS_LINKER_DEFAULT OFF)
|
||||||
|
endif()
|
||||||
|
unset(MOLD_BIN)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Intel C++ Compiler
|
# Intel C++ Compiler
|
||||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||||
# think these next two are broken
|
# think these next two are broken
|
||||||
@@ -714,6 +840,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
|||||||
string(APPEND PLATFORM_LINKFLAGS " -static-intel")
|
string(APPEND PLATFORM_LINKFLAGS " -static-intel")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
unset(_IS_LINKER_DEFAULT)
|
||||||
|
|
||||||
# Avoid conflicts with Mesa llvmpipe, Luxrender, and other plug-ins that may
|
# Avoid conflicts with Mesa llvmpipe, Luxrender, and other plug-ins that may
|
||||||
# use the same libraries as Blender with a different version or build options.
|
# use the same libraries as Blender with a different version or build options.
|
||||||
set(PLATFORM_LINKFLAGS
|
set(PLATFORM_LINKFLAGS
|
||||||
@@ -738,3 +866,45 @@ if(WITH_COMPILER_CCACHE)
|
|||||||
set(WITH_COMPILER_CCACHE OFF)
|
set(WITH_COMPILER_CCACHE OFF)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# On some platforms certain atomic operations are not possible with assembly and/or intrinsics and
|
||||||
|
# they are emulated in software with locks. For example, on armel there is no intrinsics to grant
|
||||||
|
# 64 bit atomic operations and STL library uses libatomic to offload software emulation of atomics
|
||||||
|
# to.
|
||||||
|
# This function will check whether libatomic is required and if so will configure linker flags.
|
||||||
|
# If atomic operations are possible without libatomic then linker flags are left as-is.
|
||||||
|
function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
|
||||||
|
# Source which is used to enforce situation when software emulation of atomics is required.
|
||||||
|
# Assume that using 64bit integer gives a definitive asnwer (as in, if 64bit atomic operations
|
||||||
|
# are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible.
|
||||||
|
set(_source
|
||||||
|
"#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::atomic<uint64_t> uint64; uint64++;
|
||||||
|
return 0;
|
||||||
|
}")
|
||||||
|
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITHOUT_LIBATOMIC)
|
||||||
|
|
||||||
|
if(NOT ATOMIC_OPS_WITHOUT_LIBATOMIC)
|
||||||
|
# Compilation of the test program has failed.
|
||||||
|
# Try it again with -latomic to see if this is what is needed, or whether something else is
|
||||||
|
# going on.
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES atomic)
|
||||||
|
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITH_LIBATOMIC)
|
||||||
|
|
||||||
|
if(ATOMIC_OPS_WITH_LIBATOMIC)
|
||||||
|
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -latomic" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
# Atomic operations are required part of Blender and it is not possible to process forward.
|
||||||
|
# We expect that either standard library or libatomic will make atomics to work. If both
|
||||||
|
# cases has failed something fishy o na bigger scope is going on.
|
||||||
|
message(FATAL_ERROR "Failed to detect required configuration for atomic operations")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
CONFIGURE_ATOMIC_LIB_IF_NEEDED()
|
||||||
|
@@ -55,6 +55,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|||||||
message(WARNING "stripped pdb not supported with clang, disabling..")
|
message(WARNING "stripped pdb not supported with clang, disabling..")
|
||||||
set(WITH_WINDOWS_STRIPPED_PDB OFF)
|
set(WITH_WINDOWS_STRIPPED_PDB OFF)
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.28.29921) # MSVC 2019 16.9.16
|
||||||
|
message(FATAL_ERROR "Compiler is unsupported, MSVC 2019 16.9.16 or newer is required for building blender.")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT WITH_PYTHON_MODULE)
|
if(NOT WITH_PYTHON_MODULE)
|
||||||
@@ -265,12 +269,6 @@ if(NOT DEFINED LIBDIR)
|
|||||||
elseif(MSVC_VERSION GREATER 1919)
|
elseif(MSVC_VERSION GREATER 1919)
|
||||||
message(STATUS "Visual Studio 2019 detected.")
|
message(STATUS "Visual Studio 2019 detected.")
|
||||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||||
elseif(MSVC_VERSION GREATER 1909)
|
|
||||||
message(STATUS "Visual Studio 2017 detected.")
|
|
||||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
|
||||||
elseif(MSVC_VERSION EQUAL 1900)
|
|
||||||
message(STATUS "Visual Studio 2015 detected.")
|
|
||||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||||
@@ -347,7 +345,11 @@ set(FREETYPE_INCLUDE_DIRS
|
|||||||
${LIBDIR}/freetype/include
|
${LIBDIR}/freetype/include
|
||||||
${LIBDIR}/freetype/include/freetype2
|
${LIBDIR}/freetype/include/freetype2
|
||||||
)
|
)
|
||||||
set(FREETYPE_LIBRARY ${LIBDIR}/freetype/lib/freetype2ST.lib)
|
set(FREETYPE_LIBRARIES
|
||||||
|
${LIBDIR}/freetype/lib/freetype2ST.lib
|
||||||
|
${LIBDIR}/brotli/lib/brotlidec-static.lib
|
||||||
|
${LIBDIR}/brotli/lib/brotlicommon-static.lib
|
||||||
|
)
|
||||||
windows_find_package(freetype REQUIRED)
|
windows_find_package(freetype REQUIRED)
|
||||||
|
|
||||||
if(WITH_FFTW3)
|
if(WITH_FFTW3)
|
||||||
@@ -461,7 +463,7 @@ if(WITH_JACK)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_PYTHON)
|
if(WITH_PYTHON)
|
||||||
set(PYTHON_VERSION 3.9) # CACHE STRING)
|
set(PYTHON_VERSION 3.10) # CACHE STRING)
|
||||||
|
|
||||||
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
|
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
|
||||||
set(PYTHON_LIBRARY ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.lib)
|
set(PYTHON_LIBRARY ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.lib)
|
||||||
|
@@ -5,38 +5,38 @@
|
|||||||
update-code:
|
update-code:
|
||||||
git:
|
git:
|
||||||
submodules:
|
submodules:
|
||||||
- branch: master
|
- branch: blender-v3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/scripts/addons
|
path: release/scripts/addons
|
||||||
- branch: master
|
- branch: blender-v3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/scripts/addons_contrib
|
path: release/scripts/addons_contrib
|
||||||
- branch: master
|
- branch: blender-v3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: release/datafiles/locale
|
path: release/datafiles/locale
|
||||||
- branch: master
|
- branch: blender-v3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: source/tools
|
path: source/tools
|
||||||
svn:
|
svn:
|
||||||
libraries:
|
libraries:
|
||||||
darwin-arm64:
|
darwin-arm64:
|
||||||
branch: trunk
|
branch: tags/blender-3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/darwin_arm64
|
path: lib/darwin_arm64
|
||||||
darwin-x86_64:
|
darwin-x86_64:
|
||||||
branch: trunk
|
branch: tags/blender-3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/darwin
|
path: lib/darwin
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
branch: trunk
|
branch: tags/blender-3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/linux_centos7_x86_64
|
path: lib/linux_centos7_x86_64
|
||||||
windows-amd64:
|
windows-amd64:
|
||||||
branch: trunk
|
branch: tags/blender-3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/win64_vc15
|
path: lib/win64_vc15
|
||||||
tests:
|
tests:
|
||||||
branch: trunk
|
branch: tags/blender-3.1-release
|
||||||
commit_id: HEAD
|
commit_id: HEAD
|
||||||
path: lib/tests
|
path: lib/tests
|
||||||
benchmarks:
|
benchmarks:
|
||||||
|
@@ -3,9 +3,6 @@ echo No explicit msvc version requested, autodetecting version.
|
|||||||
call "%~dp0\detect_msvc2019.cmd"
|
call "%~dp0\detect_msvc2019.cmd"
|
||||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||||
|
|
||||||
call "%~dp0\detect_msvc2017.cmd"
|
|
||||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
|
||||||
|
|
||||||
call "%~dp0\detect_msvc2022.cmd"
|
call "%~dp0\detect_msvc2022.cmd"
|
||||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
|
|
||||||
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
|
|
||||||
|
@@ -19,12 +19,6 @@ if "%WITH_PYDEBUG%"=="1" (
|
|||||||
set PYDEBUG_CMAKE_ARGS=-DWINDOWS_PYTHON_DEBUG=On
|
set PYDEBUG_CMAKE_ARGS=-DWINDOWS_PYTHON_DEBUG=On
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%BUILD_VS_YEAR%"=="2017" (
|
|
||||||
set BUILD_GENERATOR_POST=%WINDOWS_ARCH%
|
|
||||||
) else (
|
|
||||||
set BUILD_PLATFORM_SELECT=-A %MSBUILD_PLATFORM%
|
|
||||||
)
|
|
||||||
|
|
||||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%BUILD_GENERATOR_POST%" %BUILD_PLATFORM_SELECT% %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS% %PYDEBUG_CMAKE_ARGS%
|
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%BUILD_GENERATOR_POST%" %BUILD_PLATFORM_SELECT% %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS% %PYDEBUG_CMAKE_ARGS%
|
||||||
|
|
||||||
if NOT EXIST %BUILD_DIR%\nul (
|
if NOT EXIST %BUILD_DIR%\nul (
|
||||||
|
@@ -37,15 +37,9 @@ set LLVM_DIR=
|
|||||||
:DetectionComplete
|
:DetectionComplete
|
||||||
set CC=%LLVM_DIR%\bin\clang-cl
|
set CC=%LLVM_DIR%\bin\clang-cl
|
||||||
set CXX=%LLVM_DIR%\bin\clang-cl
|
set CXX=%LLVM_DIR%\bin\clang-cl
|
||||||
if "%BUILD_VS_YEAR%" == "2019" (
|
rem build and tested against 2019 16.2
|
||||||
rem build and tested against 2019 16.2
|
set CFLAGS=-m64 -fmsc-version=1922
|
||||||
set CFLAGS=-m64 -fmsc-version=1922
|
set CXXFLAGS=-m64 -fmsc-version=1922
|
||||||
set CXXFLAGS=-m64 -fmsc-version=1922
|
|
||||||
) else (
|
|
||||||
rem build and tested against 2017 15.7
|
|
||||||
set CFLAGS=-m64 -fmsc-version=1914
|
|
||||||
set CXXFLAGS=-m64 -fmsc-version=1914
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%WITH_ASAN%"=="1" (
|
if "%WITH_ASAN%"=="1" (
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
set BUILD_VS_VER=15
|
|
||||||
set BUILD_VS_YEAR=2017
|
|
||||||
call "%~dp0\detect_msvc_vswhere.cmd"
|
|
@@ -3,7 +3,32 @@ for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
|
|||||||
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
|
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
|
||||||
for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
|
for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
|
||||||
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
|
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
|
||||||
|
REM For python, default on 39 but if that does not exist also check
|
||||||
|
REM the 310,311 and 312 folders to see if those are there, it checks
|
||||||
|
REM this far ahead to ensure good lib folder compatiblity in the future.
|
||||||
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
||||||
|
if EXIST %PYTHON% (
|
||||||
|
goto detect_python_done
|
||||||
|
)
|
||||||
|
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\310\bin\python.exe
|
||||||
|
if EXIST %PYTHON% (
|
||||||
|
goto detect_python_done
|
||||||
|
)
|
||||||
|
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\311\bin\python.exe
|
||||||
|
if EXIST %PYTHON% (
|
||||||
|
goto detect_python_done
|
||||||
|
)
|
||||||
|
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\312\bin\python.exe
|
||||||
|
if EXIST %PYTHON% (
|
||||||
|
goto detect_python_done
|
||||||
|
)
|
||||||
|
|
||||||
|
if NOT EXIST %PYTHON% (
|
||||||
|
echo Warning: Python not found, there is likely an issue with the library folder
|
||||||
|
set PYTHON=""
|
||||||
|
)
|
||||||
|
|
||||||
|
:detect_python_done
|
||||||
if NOT "%verbose%" == "" (
|
if NOT "%verbose%" == "" (
|
||||||
echo svn : "%SVN%"
|
echo svn : "%SVN%"
|
||||||
echo cmake : "%CMAKE%"
|
echo cmake : "%CMAKE%"
|
||||||
@@ -11,7 +36,3 @@ if NOT "%verbose%" == "" (
|
|||||||
echo git : "%GIT%"
|
echo git : "%GIT%"
|
||||||
echo python : "%PYTHON%"
|
echo python : "%PYTHON%"
|
||||||
)
|
)
|
||||||
if "%CMAKE%" == "" (
|
|
||||||
echo Cmake not found in path, required for building, exiting...
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
@@ -9,17 +9,11 @@ exit /b 1
|
|||||||
:detect_done
|
:detect_done
|
||||||
echo found clang-format in %CF_PATH%
|
echo found clang-format in %CF_PATH%
|
||||||
|
|
||||||
if EXIST %PYTHON% (
|
if NOT EXIST %PYTHON% (
|
||||||
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
echo python not found, required for this operation
|
||||||
goto detect_python_done
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
echo python not found in lib folder
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:detect_python_done
|
|
||||||
echo found python (%PYTHON%)
|
|
||||||
|
|
||||||
set FORMAT_PATHS=%BLENDER_DIR%\source\tools\utils_maintenance\clang_format_paths.py
|
set FORMAT_PATHS=%BLENDER_DIR%\source\tools\utils_maintenance\clang_format_paths.py
|
||||||
|
|
||||||
REM The formatting script expects clang-format to be in the current PATH.
|
REM The formatting script expects clang-format to be in the current PATH.
|
||||||
|
@@ -1,18 +1,8 @@
|
|||||||
if EXIST "%PYTHON%" (
|
if NOT EXIST %PYTHON% (
|
||||||
goto detect_python_done
|
echo python not found, required for this operation
|
||||||
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
|
||||||
if EXIST %PYTHON% (
|
|
||||||
goto detect_python_done
|
|
||||||
)
|
|
||||||
|
|
||||||
echo python not found at %PYTHON%
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:detect_python_done
|
|
||||||
echo found python (%PYTHON%)
|
|
||||||
|
|
||||||
call "%~dp0\find_inkscape.cmd"
|
call "%~dp0\find_inkscape.cmd"
|
||||||
|
|
||||||
if EXIST "%INKSCAPE_BIN%" (
|
if EXIST "%INKSCAPE_BIN%" (
|
||||||
|
@@ -1,18 +1,8 @@
|
|||||||
if EXIST %PYTHON% (
|
if NOT EXIST %PYTHON% (
|
||||||
goto detect_python_done
|
echo python not found, required for this operation
|
||||||
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
|
|
||||||
if EXIST %PYTHON% (
|
|
||||||
goto detect_python_done
|
|
||||||
)
|
|
||||||
|
|
||||||
echo python not found at %PYTHON%
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:detect_python_done
|
|
||||||
echo found python (%PYTHON%)
|
|
||||||
|
|
||||||
call "%~dp0\find_blender.cmd"
|
call "%~dp0\find_blender.cmd"
|
||||||
|
|
||||||
if EXIST "%BLENDER_BIN%" (
|
if EXIST "%BLENDER_BIN%" (
|
||||||
|
@@ -50,14 +50,6 @@ if NOT "%1" == "" (
|
|||||||
goto ERR
|
goto ERR
|
||||||
) else if "%1" == "x64" (
|
) else if "%1" == "x64" (
|
||||||
set BUILD_ARCH=x64
|
set BUILD_ARCH=x64
|
||||||
) else if "%1" == "2017" (
|
|
||||||
set BUILD_VS_YEAR=2017
|
|
||||||
) else if "%1" == "2017pre" (
|
|
||||||
set BUILD_VS_YEAR=2017
|
|
||||||
set VSWHERE_ARGS=-prerelease
|
|
||||||
) else if "%1" == "2017b" (
|
|
||||||
set BUILD_VS_YEAR=2017
|
|
||||||
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
|
|
||||||
) else if "%1" == "2019" (
|
) else if "%1" == "2019" (
|
||||||
set BUILD_VS_YEAR=2019
|
set BUILD_VS_YEAR=2019
|
||||||
) else if "%1" == "2019pre" (
|
) else if "%1" == "2019pre" (
|
||||||
|
@@ -24,12 +24,12 @@ echo - nobuildinfo ^(disable buildinfo^)
|
|||||||
echo - debug ^(Build an unoptimized debuggable build^)
|
echo - debug ^(Build an unoptimized debuggable build^)
|
||||||
echo - packagename [newname] ^(override default cpack package name^)
|
echo - packagename [newname] ^(override default cpack package name^)
|
||||||
echo - builddir [newdir] ^(override default build folder^)
|
echo - builddir [newdir] ^(override default build folder^)
|
||||||
echo - 2017 ^(build with visual studio 2017^)
|
|
||||||
echo - 2017pre ^(build with visual studio 2017 pre-release^)
|
|
||||||
echo - 2017b ^(build with visual studio 2017 Build Tools^)
|
|
||||||
echo - 2019 ^(build with visual studio 2019^)
|
echo - 2019 ^(build with visual studio 2019^)
|
||||||
echo - 2019pre ^(build with visual studio 2019 pre-release^)
|
echo - 2019pre ^(build with visual studio 2019 pre-release^)
|
||||||
echo - 2019b ^(build with visual studio 2019 Build Tools^)
|
echo - 2019b ^(build with visual studio 2019 Build Tools^)
|
||||||
|
echo - 2022 ^(build with visual studio 2022^)
|
||||||
|
echo - 2022pre ^(build with visual studio 2022 pre-release^)
|
||||||
|
echo - 2022b ^(build with visual studio 2022 Build Tools^)
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Documentation Targets ^(Not associated with building^)
|
echo Documentation Targets ^(Not associated with building^)
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
|
|
||||||
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
|
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
if EXIST %PYTHON% (
|
if NOT EXIST %PYTHON% (
|
||||||
goto detect_python_done
|
echo python not found, required for this operation
|
||||||
|
exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
echo python not found in lib folder
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:detect_python_done
|
:detect_python_done
|
||||||
|
|
||||||
REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts.
|
REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts.
|
||||||
|
@@ -51,9 +51,6 @@
|
|||||||
/** \defgroup intern_mikktspace MikktSpace
|
/** \defgroup intern_mikktspace MikktSpace
|
||||||
* \ingroup intern */
|
* \ingroup intern */
|
||||||
|
|
||||||
/** \defgroup intern_numaapi NUMA (Non Uniform Memory Architecture)
|
|
||||||
* \ingroup intern */
|
|
||||||
|
|
||||||
/** \defgroup intern_rigidbody Rigid-Body C-API
|
/** \defgroup intern_rigidbody Rigid-Body C-API
|
||||||
* \ingroup intern */
|
* \ingroup intern */
|
||||||
|
|
||||||
|
@@ -8,27 +8,42 @@ def set_pose_matrices(obj, matrix_map):
|
|||||||
"Assign pose space matrices of all bones at once, ignoring constraints."
|
"Assign pose space matrices of all bones at once, ignoring constraints."
|
||||||
|
|
||||||
def rec(pbone, parent_matrix):
|
def rec(pbone, parent_matrix):
|
||||||
matrix = matrix_map[pbone.name]
|
if pbone.name in matrix_map:
|
||||||
|
matrix = matrix_map[pbone.name]
|
||||||
|
|
||||||
## Instead of:
|
## Instead of:
|
||||||
# pbone.matrix = matrix
|
# pbone.matrix = matrix
|
||||||
# bpy.context.view_layer.update()
|
# bpy.context.view_layer.update()
|
||||||
|
|
||||||
# Compute and assign local matrix, using the new parent matrix
|
# Compute and assign local matrix, using the new parent matrix
|
||||||
if pbone.parent:
|
if pbone.parent:
|
||||||
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
||||||
matrix,
|
matrix,
|
||||||
pbone.bone.matrix_local,
|
pbone.bone.matrix_local,
|
||||||
parent_matrix=parent_matrix,
|
parent_matrix=parent_matrix,
|
||||||
parent_matrix_local=pbone.parent.bone.matrix_local,
|
parent_matrix_local=pbone.parent.bone.matrix_local,
|
||||||
invert=True
|
invert=True
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
||||||
|
matrix,
|
||||||
|
pbone.bone.matrix_local,
|
||||||
|
invert=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
pbone.matrix_basis = pbone.bone.convert_local_to_pose(
|
# Compute the updated pose matrix from local and new parent matrix
|
||||||
matrix,
|
if pbone.parent:
|
||||||
pbone.bone.matrix_local,
|
matrix = pbone.bone.convert_local_to_pose(
|
||||||
invert=True
|
pbone.matrix_basis,
|
||||||
)
|
pbone.bone.matrix_local,
|
||||||
|
parent_matrix=parent_matrix,
|
||||||
|
parent_matrix_local=pbone.parent.bone.matrix_local,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
matrix = pbone.bone.convert_local_to_pose(
|
||||||
|
pbone.matrix_basis,
|
||||||
|
pbone.bone.matrix_local,
|
||||||
|
)
|
||||||
|
|
||||||
# Recursively process children, passing the new matrix through
|
# Recursively process children, passing the new matrix through
|
||||||
for child in pbone.children:
|
for child in pbone.children:
|
||||||
|
@@ -22,7 +22,7 @@ Data Access
|
|||||||
===========
|
===========
|
||||||
|
|
||||||
The most common case for using the reference API is to find out how to access data in the blend-file.
|
The most common case for using the reference API is to find out how to access data in the blend-file.
|
||||||
Before going any further its best to be aware of ID data-blocks in Blender since you will often find properties
|
Before going any further it's best to be aware of ID data-blocks in Blender since you will often find properties
|
||||||
relative to them.
|
relative to them.
|
||||||
|
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@ Start by collecting the information where the data is located.
|
|||||||
First find this setting in the interface ``Properties editor -> Object -> Transform -> Location``.
|
First find this setting in the interface ``Properties editor -> Object -> Transform -> Location``.
|
||||||
From the button context menu select *Online Python Reference*, this will link you to:
|
From the button context menu select *Online Python Reference*, this will link you to:
|
||||||
:class:`bpy.types.Object.location`.
|
:class:`bpy.types.Object.location`.
|
||||||
Being an API reference, this link often gives little more information then the tooltip, though some of the pages
|
Being an API reference, this link often gives little more information than the tooltip, though some of the pages
|
||||||
include examples (normally at the top of the page).
|
include examples (normally at the top of the page).
|
||||||
But you now know that you have to use ``.location`` and that its an array of three floats.
|
But you now know that you have to use ``.location`` and that it's an array of three floats.
|
||||||
|
|
||||||
So the next step is to find out where to access objects, go down to the bottom of the page to the references section,
|
So the next step is to find out where to access objects, go down to the bottom of the page to the references section,
|
||||||
for objects there are many references, but one of the most common places to access objects is via the context.
|
for objects there are many references, but one of the most common places to access objects is via the context.
|
||||||
@@ -154,7 +154,7 @@ The tooltip includes :class:`bpy.types.SubsurfModifier.levels` but you want the
|
|||||||
|
|
||||||
Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that
|
Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that
|
||||||
you won't be doing collection look-ups on every access and typically you'll want to use the context rather
|
you won't be doing collection look-ups on every access and typically you'll want to use the context rather
|
||||||
then access each :class:`bpy.types.ID` instance by name.
|
than access each :class:`bpy.types.ID` instance by name.
|
||||||
|
|
||||||
Type in the ID path into a Python console :mod:`bpy.context.active_object`.
|
Type in the ID path into a Python console :mod:`bpy.context.active_object`.
|
||||||
Include the trailing dot and don't execute the code, yet.
|
Include the trailing dot and don't execute the code, yet.
|
||||||
@@ -252,6 +252,6 @@ Each entry can be selected, then copied :kbd:`Ctrl-C`, usually to paste in the t
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Not all operators get registered for display,
|
Not all operators get registered for display,
|
||||||
zooming the view for example isn't so useful to repeat so its excluded from the output.
|
zooming the view for example isn't so useful to repeat so it's excluded from the output.
|
||||||
|
|
||||||
To display *every* operator that runs see :ref:`Show All Operators <info_show_all_operators>`.
|
To display *every* operator that runs see :ref:`Show All Operators <info_show_all_operators>`.
|
||||||
|
@@ -229,7 +229,7 @@ removing the last items first, which is faster (as explained above):
|
|||||||
|
|
||||||
|
|
||||||
This example shows a fast way of removing items,
|
This example shows a fast way of removing items,
|
||||||
for use in cases where you can alter the list order without breaking the scripts functionality.
|
for use in cases where you can alter the list order without breaking the script's functionality.
|
||||||
This works by swapping two list items, so the item you remove is always last:
|
This works by swapping two list items, so the item you remove is always last:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -278,7 +278,7 @@ Here are three ways of joining multiple strings into one string for writing.
|
|||||||
This also applies to any area of your code that involves a lot of string joining:
|
This also applies to any area of your code that involves a lot of string joining:
|
||||||
|
|
||||||
String concatenation
|
String concatenation
|
||||||
This is the slowest option, do **not** use if you can avoid it, especially when writing data in a loop.
|
This is the slowest option, do **not** use this if you can avoid it, especially when writing data in a loop.
|
||||||
|
|
||||||
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
|
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ String formatting
|
|||||||
>>> file.write("%s %s %s\n" % (str1, str2, str3))
|
>>> file.write("%s %s %s\n" % (str1, str2, str3))
|
||||||
|
|
||||||
String joining
|
String joining
|
||||||
Use to join a list of strings (the list may be temporary). In the following example, the strings are joined with
|
Use this to join a list of strings (the list may be temporary). In the following example, the strings are joined with
|
||||||
a space " " in between, other examples are "" or ", ".
|
a space " " in between, other examples are "" or ", ".
|
||||||
|
|
||||||
>>> file.write(" ".join((str1, str2, str3, "\n")))
|
>>> file.write(" ".join((str1, str2, str3, "\n")))
|
||||||
|
@@ -12,7 +12,7 @@ that can be troublesome and avoid practices that are known to cause instability.
|
|||||||
Using Operators
|
Using Operators
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Blender's operators are tools for users to access, that can access with Python too which is very useful.
|
Blender's operators are tools for users to access, that can be accessed with Python too which is very useful.
|
||||||
Still operators have limitations that can make them cumbersome to script.
|
Still operators have limitations that can make them cumbersome to script.
|
||||||
|
|
||||||
The main limits are:
|
The main limits are:
|
||||||
@@ -20,13 +20,13 @@ The main limits are:
|
|||||||
- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead).
|
- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead).
|
||||||
- The return value from calling an operator is the success (if it finished or was canceled),
|
- The return value from calling an operator is the success (if it finished or was canceled),
|
||||||
in some cases it would be more logical from an API perspective to return the result of the operation.
|
in some cases it would be more logical from an API perspective to return the result of the operation.
|
||||||
- Operators poll function can fail where an API function would raise an exception giving details on exactly why.
|
- Operators' poll function can fail where an API function would raise an exception giving details on exactly why.
|
||||||
|
|
||||||
|
|
||||||
Why does an operator's poll fail?
|
Why does an operator's poll fail?
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
When calling an operator gives an error like this:
|
When calling an operator it gives an error like this:
|
||||||
|
|
||||||
>>> bpy.ops.action.clean(threshold=0.001)
|
>>> bpy.ops.action.clean(threshold=0.001)
|
||||||
RuntimeError: Operator bpy.ops.action.clean.poll() failed, context is incorrect
|
RuntimeError: Operator bpy.ops.action.clean.poll() failed, context is incorrect
|
||||||
@@ -49,9 +49,9 @@ you should be able to find the poll function with no knowledge of C.
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Blender does have the functionality for poll functions to describe why they fail,
|
Blender does have the functionality for poll functions to describe why they fail,
|
||||||
but its currently not used much, if you're interested to help improve the API
|
but it's currently not used much, if you're interested to help improve the API
|
||||||
feel free to add calls to :class:`bpy.types.Operator.poll_message_set` (``CTX_wm_operator_poll_msg_set`` in C)
|
feel free to add calls to :class:`bpy.types.Operator.poll_message_set` (``CTX_wm_operator_poll_msg_set`` in C)
|
||||||
where its not obvious why poll fails, e.g:
|
where it's not obvious why poll fails, e.g:
|
||||||
|
|
||||||
>>> bpy.ops.gpencil.draw()
|
>>> bpy.ops.gpencil.draw()
|
||||||
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
|
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
|
||||||
@@ -107,7 +107,7 @@ In this case you need to call :class:`bpy.types.ViewLayer.update` after modifyin
|
|||||||
|
|
||||||
|
|
||||||
Now all dependent data (child objects, modifiers, drivers, etc.)
|
Now all dependent data (child objects, modifiers, drivers, etc.)
|
||||||
has been recalculated and is available to the script within active view layer.
|
have been recalculated and are available to the script within the active view layer.
|
||||||
|
|
||||||
|
|
||||||
Can I redraw during script execution?
|
Can I redraw during script execution?
|
||||||
@@ -116,13 +116,13 @@ Can I redraw during script execution?
|
|||||||
The official answer to this is no, or... *"You don't want to do that"*.
|
The official answer to this is no, or... *"You don't want to do that"*.
|
||||||
To give some background on the topic:
|
To give some background on the topic:
|
||||||
|
|
||||||
While a script executes Blender waits for it to finish and is effectively locked until its done,
|
While a script executes, Blender waits for it to finish and is effectively locked until it's done;
|
||||||
while in this state Blender won't redraw or respond to user input.
|
while in this state Blender won't redraw or respond to user input.
|
||||||
Normally this is not such a problem because scripts distributed with Blender
|
Normally this is not such a problem because scripts distributed with Blender
|
||||||
tend not to run for an extended period of time,
|
tend not to run for an extended period of time,
|
||||||
nevertheless scripts *can* take a long time to complete and it would be nice to see progress in the viewport.
|
nevertheless scripts *can* take a long time to complete and it would be nice to see progress in the viewport.
|
||||||
|
|
||||||
When tools lock Blender in a loop redraw are highly discouraged
|
Tools that lock Blender in a loop redraw are highly discouraged
|
||||||
since they conflict with Blender's ability to run multiple operators
|
since they conflict with Blender's ability to run multiple operators
|
||||||
at once and update different parts of the interface as the tool runs.
|
at once and update different parts of the interface as the tool runs.
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ So the solution here is to write a **modal** operator, which is an operator that
|
|||||||
See the modal operator template in the text editor.
|
See the modal operator template in the text editor.
|
||||||
Modal operators execute on user input or setup their own timers to run frequently,
|
Modal operators execute on user input or setup their own timers to run frequently,
|
||||||
they can handle the events or pass through to be handled by the keymap or other modal operators.
|
they can handle the events or pass through to be handled by the keymap or other modal operators.
|
||||||
Examples of a modal operators are Transform, Painting, Fly Navigation and File Select.
|
Examples of modal operators are Transform, Painting, Fly Navigation and File Select.
|
||||||
|
|
||||||
Writing modal operators takes more effort than a simple ``for`` loop
|
Writing modal operators takes more effort than a simple ``for`` loop
|
||||||
that contains draw calls but is more flexible and integrates better with Blender's design.
|
that contains draw calls but is more flexible and integrates better with Blender's design.
|
||||||
@@ -240,7 +240,7 @@ Editing
|
|||||||
Editing is where the three data types vary most.
|
Editing is where the three data types vary most.
|
||||||
|
|
||||||
- Polygons are very limited for editing,
|
- Polygons are very limited for editing,
|
||||||
changing materials and options like smooth works but for anything else
|
changing materials and options like smooth works, but for anything else
|
||||||
they are too inflexible and are only intended for storage.
|
they are too inflexible and are only intended for storage.
|
||||||
- Tessfaces should not be used for editing geometry because doing so will cause existing n-gons to be tessellated.
|
- Tessfaces should not be used for editing geometry because doing so will cause existing n-gons to be tessellated.
|
||||||
- BMesh-faces are by far the best way to manipulate geometry.
|
- BMesh-faces are by far the best way to manipulate geometry.
|
||||||
@@ -256,7 +256,7 @@ the choice mostly depends on whether the target format supports n-gons or not.
|
|||||||
- Tessfaces work well for exporting to formats which don't support n-gons,
|
- Tessfaces work well for exporting to formats which don't support n-gons,
|
||||||
in fact this is the only place where their use is encouraged.
|
in fact this is the only place where their use is encouraged.
|
||||||
- BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
|
- BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
|
||||||
since using BMesh gives some overhead because its not the native storage format in Object-Mode.
|
since using BMesh gives some overhead because it's not the native storage format in Object-Mode.
|
||||||
|
|
||||||
|
|
||||||
Edit Bones, Pose Bones, Bone... Bones
|
Edit Bones, Pose Bones, Bone... Bones
|
||||||
@@ -348,7 +348,7 @@ Armature Mode Switching
|
|||||||
While writing scripts that deal with armatures you may find you have to switch between modes,
|
While writing scripts that deal with armatures you may find you have to switch between modes,
|
||||||
when doing so take care when switching out of Edit-Mode not to keep references
|
when doing so take care when switching out of Edit-Mode not to keep references
|
||||||
to the edit bones or their head/tail vectors.
|
to the edit bones or their head/tail vectors.
|
||||||
Further access to these will crash Blender so its important the script
|
Further access to these will crash Blender so it's important that the script
|
||||||
clearly separates sections of the code which operate in different modes.
|
clearly separates sections of the code which operate in different modes.
|
||||||
|
|
||||||
This is mainly an issue with Edit-Mode since pose data can be manipulated without having to be in Pose-Mode,
|
This is mainly an issue with Edit-Mode since pose data can be manipulated without having to be in Pose-Mode,
|
||||||
@@ -386,11 +386,11 @@ Or with name assignment:
|
|||||||
Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
|
Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
|
||||||
|
|
||||||
|
|
||||||
Its better practice not to reference objects by names at all,
|
It's better practice not to reference objects by names at all,
|
||||||
once created you can store the data in a list, dictionary, on a class, etc;
|
once created you can store the data in a list, dictionary, on a class, etc;
|
||||||
there is rarely a reason to have to keep searching for the same data by name.
|
there is rarely a reason to have to keep searching for the same data by name.
|
||||||
|
|
||||||
If you do need to use name references, its best to use a dictionary to maintain
|
If you do need to use name references, it's best to use a dictionary to maintain
|
||||||
a mapping between the names of the imported assets and the newly created data,
|
a mapping between the names of the imported assets and the newly created data,
|
||||||
this way you don't run this risk of referencing existing data from the blend-file, or worse modifying it.
|
this way you don't run this risk of referencing existing data from the blend-file, or worse modifying it.
|
||||||
|
|
||||||
@@ -414,11 +414,11 @@ Library Collisions
|
|||||||
Blender keeps data names unique (:class:`bpy.types.ID.name`) so you can't name two objects,
|
Blender keeps data names unique (:class:`bpy.types.ID.name`) so you can't name two objects,
|
||||||
meshes, scenes, etc., the same by accident.
|
meshes, scenes, etc., the same by accident.
|
||||||
However, when linking in library data from another blend-file naming collisions can occur,
|
However, when linking in library data from another blend-file naming collisions can occur,
|
||||||
so its best to avoid referencing data by name at all.
|
so it's best to avoid referencing data by name at all.
|
||||||
|
|
||||||
This can be tricky at times and not even Blender handles this correctly in some case
|
This can be tricky at times and not even Blender handles this correctly in some cases
|
||||||
(when selecting the modifier object for e.g. you can't select between multiple objects with the same name),
|
(when selecting the modifier object for e.g. you can't select between multiple objects with the same name),
|
||||||
but its still good to try avoiding these problems in this area.
|
but it's still good to try avoiding these problems in this area.
|
||||||
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
|
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -467,11 +467,11 @@ writing a script in ``latin1`` or ``iso-8859-15``.
|
|||||||
See `PEP 263 <https://www.python.org/dev/peps/pep-0263/>`__.
|
See `PEP 263 <https://www.python.org/dev/peps/pep-0263/>`__.
|
||||||
|
|
||||||
However, this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
|
However, this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
|
||||||
To avoid the problem for Python integration and script authors we have decided all strings in blend-files
|
To avoid the problem for Python integration and script authors we have decided that all strings in blend-files
|
||||||
**must** be ``UTF-8``, ``ASCII`` compatible.
|
**must** be ``UTF-8``, ``ASCII`` compatible.
|
||||||
This means assigning strings with different encodings to an object names for instance will raise an error.
|
This means assigning strings with different encodings to an object name, for instance, will raise an error.
|
||||||
|
|
||||||
Paths are an exception to this rule since the existence of non-UTF-8 paths on user's file system cannot be ignored.
|
Paths are an exception to this rule since the existence of non-UTF-8 paths on the user's file system cannot be ignored.
|
||||||
This means seemingly harmless expressions can raise errors, e.g:
|
This means seemingly harmless expressions can raise errors, e.g:
|
||||||
|
|
||||||
>>> print(bpy.data.filepath)
|
>>> print(bpy.data.filepath)
|
||||||
@@ -505,7 +505,7 @@ to keep it short about encoding problems -- here are some suggestions:
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Sometimes it's preferable to avoid string encoding issues by using bytes instead of Python strings,
|
Sometimes it's preferable to avoid string encoding issues by using bytes instead of Python strings,
|
||||||
when reading some input its less trouble to read it as binary data
|
when reading some input it's less trouble to read it as binary data
|
||||||
though you will still need to decide how to treat any strings you want to use with Blender,
|
though you will still need to decide how to treat any strings you want to use with Blender,
|
||||||
some importers do this.
|
some importers do this.
|
||||||
|
|
||||||
@@ -679,7 +679,7 @@ Undo/Redo
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
For safety, you should assume that undo and redo always invalidates all :class:`bpy.types.ID`
|
For safety, you should assume that undo and redo always invalidates all :class:`bpy.types.ID`
|
||||||
instances (Object, Scene, Mesh, Light, etc.), as weel obviously as all of their sub-data.
|
instances (Object, Scene, Mesh, Light, etc.), as well obviously as all of their sub-data.
|
||||||
|
|
||||||
This example shows how you can tell undo changes the memory locations:
|
This example shows how you can tell undo changes the memory locations:
|
||||||
|
|
||||||
@@ -716,7 +716,7 @@ Tools in Blender are not allowed to modify library data.
|
|||||||
But Python does not enforce this restriction.
|
But Python does not enforce this restriction.
|
||||||
|
|
||||||
This can be useful in some cases, using a script to adjust material values for example.
|
This can be useful in some cases, using a script to adjust material values for example.
|
||||||
But its also possible to use a script to make library data point to newly created local data,
|
But it's also possible to use a script to make library data point to newly created local data,
|
||||||
which is not supported since a call to undo will remove the local data
|
which is not supported since a call to undo will remove the local data
|
||||||
but leave the library referencing it and likely crash.
|
but leave the library referencing it and likely crash.
|
||||||
|
|
||||||
@@ -743,7 +743,7 @@ will re-allocate objects data,
|
|||||||
any references to a meshes vertices/polygons/UVs, armatures bones,
|
any references to a meshes vertices/polygons/UVs, armatures bones,
|
||||||
curves points, etc. cannot be accessed after switching mode.
|
curves points, etc. cannot be accessed after switching mode.
|
||||||
|
|
||||||
Only the reference to the data its self can be re-accessed, the following example will crash.
|
Only the reference to the data itself can be re-accessed, the following example will crash.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@@ -81,7 +81,7 @@ but reference an external file rather than including it directly.
|
|||||||
Executing External Scripts
|
Executing External Scripts
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
This is the equivalent to running the script directly, referencing a scripts path from a two line code block.
|
This is the equivalent to running the script directly, referencing a script's path from a two line code block.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ small script which is often useful for testing different settings quickly.
|
|||||||
|
|
||||||
The other issue with this is the script has to be in Python's module search path.
|
The other issue with this is the script has to be in Python's module search path.
|
||||||
While this is not best practice -- for testing purposes you can extend the search path,
|
While this is not best practice -- for testing purposes you can extend the search path,
|
||||||
this following example adds the current blend-files directory to the search path
|
this following example adds the current blend-file's directory to the search path
|
||||||
and then loads the script as a module.
|
and then loads the script as a module.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@@ -302,7 +302,7 @@ Python Safety (Build Option)
|
|||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Since it's possible to access data which has been removed (see :doc:`Gotchas <info_gotcha>`),
|
Since it's possible to access data which has been removed (see :doc:`Gotchas <info_gotcha>`),
|
||||||
can make it hard to track down the cause of crashes.
|
it can be hard to track down the cause of crashes.
|
||||||
To raise Python exceptions on accessing freed data (rather than crashing),
|
To raise Python exceptions on accessing freed data (rather than crashing),
|
||||||
enable the CMake build option ``WITH_PYTHON_SAFETY``.
|
enable the CMake build option ``WITH_PYTHON_SAFETY``.
|
||||||
This enables data tracking which makes data access about two times slower
|
This enables data tracking which makes data access about two times slower
|
||||||
|
@@ -417,7 +417,8 @@ MODULE_GROUPING = {
|
|||||||
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
|
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
|
||||||
|
|
||||||
# '2.83.0 Beta' or '2.83.0' or '2.83.1'
|
# '2.83.0 Beta' or '2.83.0' or '2.83.1'
|
||||||
BLENDER_VERSION_DOTS = bpy.app.version_string
|
BLENDER_VERSION_STRING = bpy.app.version_string
|
||||||
|
BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||||
|
|
||||||
if BLENDER_REVISION != "Unknown":
|
if BLENDER_REVISION != "Unknown":
|
||||||
# SHA1 Git hash
|
# SHA1 Git hash
|
||||||
@@ -1724,11 +1725,11 @@ def write_sphinx_conf_py(basepath):
|
|||||||
fw("import sys, os\n\n")
|
fw("import sys, os\n\n")
|
||||||
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
||||||
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
||||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_DOTS)
|
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
|
||||||
fw("master_doc = 'index'\n")
|
fw("master_doc = 'index'\n")
|
||||||
fw("copyright = u'Blender Foundation'\n")
|
fw("copyright = u'Blender Foundation'\n")
|
||||||
fw("version = '%s'\n" % BLENDER_VERSION_HASH)
|
fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||||
fw("release = '%s'\n" % BLENDER_VERSION_HASH)
|
fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||||
|
|
||||||
# Quiet file not in table-of-contents warnings.
|
# Quiet file not in table-of-contents warnings.
|
||||||
fw("exclude_patterns = [\n")
|
fw("exclude_patterns = [\n")
|
||||||
@@ -1749,6 +1750,7 @@ except ModuleNotFoundError:
|
|||||||
|
|
||||||
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
||||||
fw(" html_theme_options = {\n")
|
fw(" html_theme_options = {\n")
|
||||||
|
fw(" 'display_version': False,\n")
|
||||||
# fw(" 'analytics_id': '',\n")
|
# fw(" 'analytics_id': '',\n")
|
||||||
# fw(" 'collapse_navigation': True,\n")
|
# fw(" 'collapse_navigation': True,\n")
|
||||||
fw(" 'sticky_navigation': False,\n")
|
fw(" 'sticky_navigation': False,\n")
|
||||||
@@ -1762,12 +1764,18 @@ except ModuleNotFoundError:
|
|||||||
fw("html_show_sphinx = False\n")
|
fw("html_show_sphinx = False\n")
|
||||||
fw("html_baseurl = 'https://docs.blender.org/api/current/'\n")
|
fw("html_baseurl = 'https://docs.blender.org/api/current/'\n")
|
||||||
fw("html_use_opensearch = 'https://docs.blender.org/api/current'\n")
|
fw("html_use_opensearch = 'https://docs.blender.org/api/current'\n")
|
||||||
|
fw("html_show_search_summary = True\n")
|
||||||
fw("html_split_index = True\n")
|
fw("html_split_index = True\n")
|
||||||
fw("html_static_path = ['static']\n")
|
fw("html_static_path = ['static']\n")
|
||||||
|
fw("templates_path = ['templates']\n")
|
||||||
|
fw("html_context = {'commit': '%s'}\n" % BLENDER_VERSION_HASH)
|
||||||
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
|
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
|
||||||
fw("html_favicon = 'static/favicon.ico'\n")
|
fw("html_favicon = 'static/favicon.ico'\n")
|
||||||
fw("html_logo = 'static/blender_logo.svg'\n")
|
fw("html_logo = 'static/blender_logo.svg'\n")
|
||||||
fw("html_last_updated_fmt = '%m/%d/%Y'\n\n")
|
fw("html_last_updated_fmt = '%m/%d/%Y'\n\n")
|
||||||
|
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
||||||
|
fw(" html_css_files = ['css/version_switch.css']\n")
|
||||||
|
fw(" html_js_files = ['js/version_switch.js']\n")
|
||||||
|
|
||||||
# needed for latex, pdf gen
|
# needed for latex, pdf gen
|
||||||
fw("latex_elements = {\n")
|
fw("latex_elements = {\n")
|
||||||
@@ -2124,6 +2132,9 @@ def copy_theme_assets(basepath):
|
|||||||
shutil.copytree(os.path.join(SCRIPT_DIR, "static"),
|
shutil.copytree(os.path.join(SCRIPT_DIR, "static"),
|
||||||
os.path.join(basepath, "static"),
|
os.path.join(basepath, "static"),
|
||||||
copy_function=shutil.copy)
|
copy_function=shutil.copy)
|
||||||
|
shutil.copytree(os.path.join(SCRIPT_DIR, "templates"),
|
||||||
|
os.path.join(basepath, "templates"),
|
||||||
|
copy_function=shutil.copy)
|
||||||
|
|
||||||
|
|
||||||
def rna2sphinx(basepath):
|
def rna2sphinx(basepath):
|
||||||
|
128
doc/python_api/static/css/version_switch.css
Normal file
128
doc/python_api/static/css/version_switch.css
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* Override RTD theme */
|
||||||
|
.rst-versions {
|
||||||
|
display: none;
|
||||||
|
border-top: 0px;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
.version-btn.vdeact {
|
||||||
|
cursor: default;
|
||||||
|
color: dimgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-btn.vdeact::after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
#versionwrap {
|
||||||
|
display: flex;
|
||||||
|
padding-top: 2px;
|
||||||
|
font-size: 90%;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.version-btn {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #272525;
|
||||||
|
width: 140px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 3px 10px;
|
||||||
|
margin: 0px 5px 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: #27AE60;
|
||||||
|
border: solid 1px #444444;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 400;
|
||||||
|
transition: border-color 0.4s;
|
||||||
|
}
|
||||||
|
.version-btn::after {
|
||||||
|
content:"\f0d8";
|
||||||
|
display: inline;
|
||||||
|
font: normal normal normal 16px/1 FontAwesome;
|
||||||
|
color: #8d8c8c;
|
||||||
|
vertical-align: top;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
.version-btn-open::after {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
.version-btn:hover, .version-btn:focus {
|
||||||
|
border-color: #525252;
|
||||||
|
}
|
||||||
|
.version-btn-open {
|
||||||
|
color: gray;
|
||||||
|
border: solid 1px gray;
|
||||||
|
}
|
||||||
|
.version-btn.wait {
|
||||||
|
cursor: wait;
|
||||||
|
}
|
||||||
|
.version-btn.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: dimgray;
|
||||||
|
}
|
||||||
|
.version-dialog {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 28px;
|
||||||
|
width: 140px;
|
||||||
|
margin: 0 5px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
background-color: #0003;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 0 6px #000C;
|
||||||
|
z-index: 999;
|
||||||
|
max-height: calc(100vh - 30px);
|
||||||
|
overflow-y: auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.version-title {
|
||||||
|
padding: 5px;
|
||||||
|
color: black;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 102%;
|
||||||
|
background-color: #27ae60;
|
||||||
|
border-bottom: solid 1.5px #444;
|
||||||
|
}
|
||||||
|
.version-list {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #000C;
|
||||||
|
border: solid 1px gray;
|
||||||
|
border-radius: 0px 0px 3px 3px;
|
||||||
|
}
|
||||||
|
.version-list a, .version-list span, .version-list li {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
font-size: 98%;
|
||||||
|
line-height: 1.15;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 0px;
|
||||||
|
color: #404040;
|
||||||
|
}
|
||||||
|
.version-list li {
|
||||||
|
background-color: #ede9e9;
|
||||||
|
color: #404040;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
.version-list li:hover, .version-list li a:focus {
|
||||||
|
background-color: #b9cfda;
|
||||||
|
}
|
||||||
|
.version-list li.selected, .version-list li.selected:hover {
|
||||||
|
background-color: #8d8c8c;
|
||||||
|
}
|
||||||
|
.version-list li.selected span {
|
||||||
|
cursor: default;
|
||||||
|
outline-color: red;
|
||||||
|
}
|
||||||
|
.version-arrow {
|
||||||
|
position: absolute;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 4px;
|
||||||
|
margin-left: -4px;
|
||||||
|
transform: rotate(225deg);
|
||||||
|
background: #ede9e9;
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
}
|
323
doc/python_api/static/js/version_switch.js
Normal file
323
doc/python_api/static/js/version_switch.js
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
(function() { // switch: v1.2
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var versionsFileUrl = "https://docs.blender.org/PROD/versions.json"
|
||||||
|
|
||||||
|
var all_versions;
|
||||||
|
|
||||||
|
var Popover = function() {
|
||||||
|
function Popover(id)
|
||||||
|
{
|
||||||
|
this.isOpen = false;
|
||||||
|
this.type = (id === "version-popover");
|
||||||
|
this.$btn = $('#' + id);
|
||||||
|
this.$dialog = this.$btn.next();
|
||||||
|
this.$list = this.$dialog.children("ul");
|
||||||
|
this.sel = null;
|
||||||
|
this.beforeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Popover.prototype = {
|
||||||
|
beforeInit : function() {
|
||||||
|
var that = this;
|
||||||
|
this.$btn.on("click", function(e) {
|
||||||
|
that.init();
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
this.$btn.on("keydown", function(e) {
|
||||||
|
if (that.btnKeyFilter(e)) {
|
||||||
|
that.init();
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
init : function() {
|
||||||
|
this.$btn.off("click");
|
||||||
|
this.$btn.off("keydown");
|
||||||
|
|
||||||
|
if (all_versions === undefined) {
|
||||||
|
this.$btn.addClass("wait");
|
||||||
|
this.loadVL(this);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.afterLoad();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadVL : function(that) {
|
||||||
|
$.getJSON(versionsFileUrl, function(data) {
|
||||||
|
all_versions = data;
|
||||||
|
that.afterLoad();
|
||||||
|
return true;
|
||||||
|
}).fail(function() {
|
||||||
|
console.log("Version Switch Error: versions.json could not be loaded.");
|
||||||
|
that.$btn.addClass("disabled");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
afterLoad : function() {
|
||||||
|
var release = DOCUMENTATION_OPTIONS.VERSION;
|
||||||
|
const m = release.match(/\d\.\d+/g);
|
||||||
|
if (m) {
|
||||||
|
release = m[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.warnOld(release, all_versions);
|
||||||
|
|
||||||
|
var version = this.getNamed(release);
|
||||||
|
var list = this.buildList(version);
|
||||||
|
|
||||||
|
this.$list.children(":first-child").remove();
|
||||||
|
this.$list.append(list);
|
||||||
|
var that = this;
|
||||||
|
this.$list.on("keydown", function(e) {
|
||||||
|
that.keyMove(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$btn.removeClass("wait");
|
||||||
|
this.btnOpenHandler();
|
||||||
|
this.$btn.on("mousedown", function(e) {
|
||||||
|
that.btnOpenHandler();
|
||||||
|
e.preventDefault()
|
||||||
|
});
|
||||||
|
this.$btn.on("keydown", function(e) {
|
||||||
|
if (that.btnKeyFilter(e)) {
|
||||||
|
that.btnOpenHandler();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
warnOld : function(release, all_versions) {
|
||||||
|
// Note this is effectively disabled now, two issues must fixed:
|
||||||
|
// * versions.js does not contain a current entry, because that leads to
|
||||||
|
// duplicate version numbers in the menu. These need to be deduplicated.
|
||||||
|
// * It only shows the warning after opening the menu to switch version
|
||||||
|
// when versions.js is loaded. This is too late to be useful.
|
||||||
|
var current = all_versions.current
|
||||||
|
if (!current)
|
||||||
|
{
|
||||||
|
// console.log("Version Switch Error: no 'current' in version.json.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const m = current.match(/\d\.\d+/g);
|
||||||
|
if (m) {
|
||||||
|
current = parseFloat(m[0]);
|
||||||
|
}
|
||||||
|
if (release < current) {
|
||||||
|
var currentURL = window.location.pathname.replace(release, current);
|
||||||
|
var warning = $('<div class="admonition warning"> ' +
|
||||||
|
'<p class="first admonition-title">Note</p> ' +
|
||||||
|
'<p class="last"> ' +
|
||||||
|
'You are not using the most up to date version of the documentation. ' +
|
||||||
|
'<a href="#"></a> is the newest version.' +
|
||||||
|
'</p>' +
|
||||||
|
'</div>');
|
||||||
|
|
||||||
|
warning.find('a').attr('href', currentURL).text(current);
|
||||||
|
|
||||||
|
var body = $("div.body");
|
||||||
|
if (!body.length) {
|
||||||
|
body = $("div.document");
|
||||||
|
}
|
||||||
|
body.prepend(warning);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buildList : function(v) {
|
||||||
|
var url = new URL(window.location.href);
|
||||||
|
let pathSplit = [ "", "api", v ];
|
||||||
|
if (url.pathname.startsWith("/api/")) {
|
||||||
|
pathSplit.push(url.pathname.split('/').slice(3).join('/'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pathSplit.push(url.pathname.substring(1));
|
||||||
|
}
|
||||||
|
if (this.type) {
|
||||||
|
var dyn = all_versions;
|
||||||
|
var cur = v;
|
||||||
|
}
|
||||||
|
var buf = [];
|
||||||
|
var that = this;
|
||||||
|
$.each(dyn, function(ix, title) {
|
||||||
|
buf.push("<li");
|
||||||
|
if (ix === cur) {
|
||||||
|
buf.push(
|
||||||
|
' class="selected" tabindex="-1" role="presentation"><span tabindex="-1" role="menuitem" aria-current="page">' +
|
||||||
|
title + '</spanp></li>');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pathSplit[2 + that.type] = ix;
|
||||||
|
var href = new URL(url);
|
||||||
|
href.pathname = pathSplit.join('/');
|
||||||
|
buf.push(' tabindex="-1" role="presentation"><a href ="' + href + '" tabindex="-1">' +
|
||||||
|
title + '</a></li>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return buf.join('');
|
||||||
|
},
|
||||||
|
getNamed : function(v) {
|
||||||
|
$.each(all_versions, function(ix, title) {
|
||||||
|
if (ix === "master" || ix === "latest") {
|
||||||
|
var m = title.match(/\d\.\d[\w\d\.]*/)[0];
|
||||||
|
if (parseFloat(m) == v) {
|
||||||
|
v = ix;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
dialogToggle : function(speed) {
|
||||||
|
var wasClose = !this.isOpen;
|
||||||
|
var that = this;
|
||||||
|
if (!this.isOpen) {
|
||||||
|
this.$btn.addClass("version-btn-open");
|
||||||
|
this.$btn.attr("aria-pressed", true);
|
||||||
|
this.$dialog.attr("aria-hidden", false);
|
||||||
|
this.$dialog.fadeIn(speed, function() {
|
||||||
|
that.$btn.parent().on("focusout", function(e) {
|
||||||
|
that.focusoutHandler();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
})
|
||||||
|
that.$btn.parent().on("mouseleave", function(e) {
|
||||||
|
that.mouseoutHandler();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.isOpen = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$btn.removeClass("version-btn-open");
|
||||||
|
this.$btn.attr("aria-pressed", false);
|
||||||
|
this.$dialog.attr("aria-hidden", true);
|
||||||
|
this.$btn.parent().off("focusout");
|
||||||
|
this.$btn.parent().off("mouseleave");
|
||||||
|
this.$dialog.fadeOut(speed, function() {
|
||||||
|
if (this.$sel) {
|
||||||
|
this.$sel.attr("tabindex", -1);
|
||||||
|
}
|
||||||
|
that.$btn.attr("tabindex", 0);
|
||||||
|
if (document.activeElement !== null && document.activeElement !== document &&
|
||||||
|
document.activeElement !== document.body) {
|
||||||
|
that.$btn.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.isOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasClose) {
|
||||||
|
if (this.$sel) {
|
||||||
|
this.$sel.attr("tabindex", -1);
|
||||||
|
}
|
||||||
|
if (document.activeElement !== null && document.activeElement !== document &&
|
||||||
|
document.activeElement !== document.body) {
|
||||||
|
var $nw = this.listEnter();
|
||||||
|
$nw.attr("tabindex", 0);
|
||||||
|
$nw.focus();
|
||||||
|
this.$sel = $nw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
btnOpenHandler : function() {
|
||||||
|
this.dialogToggle(300);
|
||||||
|
},
|
||||||
|
focusoutHandler : function() {
|
||||||
|
var list = this.$list;
|
||||||
|
var that = this;
|
||||||
|
setTimeout(function() {
|
||||||
|
if (list.find(":focus").length === 0) {
|
||||||
|
that.dialogToggle(200);
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
},
|
||||||
|
mouseoutHandler : function() {
|
||||||
|
this.dialogToggle(200);
|
||||||
|
},
|
||||||
|
btnKeyFilter : function(e) {
|
||||||
|
if (e.ctrlKey || e.shiftKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e.key === " " || e.key === "Enter" || (e.key === "ArrowDown" && e.altKey) ||
|
||||||
|
e.key === "ArrowDown" || e.key === "ArrowUp") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
keyMove : function(e) {
|
||||||
|
if (e.ctrlKey || e.shiftKey) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var p = true;
|
||||||
|
var $nw = $(e.target);
|
||||||
|
switch (e.key) {
|
||||||
|
case "ArrowUp":
|
||||||
|
$nw = this.listPrev($nw);
|
||||||
|
break;
|
||||||
|
case "ArrowDown":
|
||||||
|
$nw = this.listNext($nw);
|
||||||
|
break;
|
||||||
|
case "Home":
|
||||||
|
$nw = this.listFirst();
|
||||||
|
break;
|
||||||
|
case "End":
|
||||||
|
$nw = this.listLast();
|
||||||
|
break;
|
||||||
|
case "Escape":
|
||||||
|
$nw = this.listExit();
|
||||||
|
break;
|
||||||
|
case "ArrowLeft":
|
||||||
|
$nw = this.listExit();
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
$nw = this.listExit();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
p = false;
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
$nw.attr("tabindex", 0);
|
||||||
|
$nw.focus();
|
||||||
|
if (this.$sel) {
|
||||||
|
this.$sel.attr("tabindex", -1);
|
||||||
|
}
|
||||||
|
this.$sel = $nw;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listPrev : function($nw) {
|
||||||
|
if ($nw.parent().prev().length !== 0) {
|
||||||
|
return $nw.parent().prev().children(":first-child");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this.listLast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listNext : function($nw) {
|
||||||
|
if ($nw.parent().next().length !== 0) {
|
||||||
|
return $nw.parent().next().children(":first-child");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return this.listFirst();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listFirst : function() {
|
||||||
|
return this.$list.children(":first-child").children(":first-child");
|
||||||
|
},
|
||||||
|
listLast : function() {
|
||||||
|
return this.$list.children(":last-child").children(":first-child");
|
||||||
|
},
|
||||||
|
listExit : function() {
|
||||||
|
this.mouseoutHandler();
|
||||||
|
return this.$btn;
|
||||||
|
},
|
||||||
|
listEnter : function() {
|
||||||
|
return this.$list.children(":first-child").children(":first-child");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Popover
|
||||||
|
}();
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
var lng_popover = new Popover("version-popover");
|
||||||
|
});
|
||||||
|
})();
|
17
doc/python_api/templates/versions.html
Normal file
17
doc/python_api/templates/versions.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="document versions">
|
||||||
|
<ul id="versionwrap" role="presentation">
|
||||||
|
<li role="presentation">
|
||||||
|
<span id="version-popover" class="version-btn" tabindex="0" role="button" aria-label="versions selector" aria-haspopup="true" aria-controls="version-vsnlist" aria-disabled="true">
|
||||||
|
{{ release }}
|
||||||
|
</span>
|
||||||
|
<div class="version-dialog" aria-hidden="true">
|
||||||
|
<div class="version-arrow" aria-hidden="true"></div>
|
||||||
|
<div class="version-title">Versions</div>
|
||||||
|
<ul id="version-vsnlist" class="version-list" role="menu" aria-labelledby="version-popover" aria-hidden="true">
|
||||||
|
<li role="presentation">Loading...</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
2
extern/CMakeLists.txt
vendored
2
extern/CMakeLists.txt
vendored
@@ -113,6 +113,6 @@ if(WITH_MOD_FLUID)
|
|||||||
add_subdirectory(mantaflow)
|
add_subdirectory(mantaflow)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_COMPOSITOR)
|
if(WITH_COMPOSITOR)
|
||||||
add_subdirectory(smaa_areatex)
|
add_subdirectory(smaa_areatex)
|
||||||
endif()
|
endif()
|
||||||
|
6
extern/audaspace/CMakeLists.txt
vendored
6
extern/audaspace/CMakeLists.txt
vendored
@@ -1092,12 +1092,12 @@ if(WITH_PYTHON)
|
|||||||
configure_file(${PYTHON_SOURCE_DIRECTORY}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py ESCAPE_QUOTES @ONLY)
|
configure_file(${PYTHON_SOURCE_DIRECTORY}/setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py ESCAPE_QUOTES @ONLY)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_custom_command(OUTPUT build COMMAND MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR})
|
add_custom_command(OUTPUT build COMMAND MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR} setup.py)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(ENV{VS100COMNTOOLS} $ENV{VS120COMNTOOLS})
|
set(ENV{VS100COMNTOOLS} $ENV{VS120COMNTOOLS})
|
||||||
add_custom_command(OUTPUT build COMMAND ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR})
|
add_custom_command(OUTPUT build COMMAND ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR} setup.py)
|
||||||
else()
|
else()
|
||||||
add_custom_command(OUTPUT build COMMAND ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR})
|
add_custom_command(OUTPUT build COMMAND ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR} setup.py)
|
||||||
endif()
|
endif()
|
||||||
add_custom_target(pythonmodule ALL DEPENDS build SOURCES ${PYTHON_SOURCE_DIRECTORY}/setup.py.in ${PYTHON_SRC} ${PYTHON_HDR})
|
add_custom_target(pythonmodule ALL DEPENDS build SOURCES ${PYTHON_SOURCE_DIRECTORY}/setup.py.in ${PYTHON_SRC} ${PYTHON_HDR})
|
||||||
add_dependencies(pythonmodule audaspace)
|
add_dependencies(pythonmodule audaspace)
|
||||||
|
27
extern/audaspace/bindings/python/setup.py.in
vendored
27
extern/audaspace/bindings/python/setup.py.in
vendored
@@ -8,20 +8,20 @@ import numpy
|
|||||||
from distutils.core import setup, Extension
|
from distutils.core import setup, Extension
|
||||||
|
|
||||||
if len(sys.argv) > 2 and sys.argv[1] == '--build-docs':
|
if len(sys.argv) > 2 and sys.argv[1] == '--build-docs':
|
||||||
import subprocess
|
import subprocess
|
||||||
from distutils.core import Distribution
|
from distutils.core import Distribution
|
||||||
from distutils.command.build import build
|
from distutils.command.build import build
|
||||||
|
|
||||||
dist = Distribution()
|
dist = Distribution()
|
||||||
cmd = build(dist)
|
cmd = build(dist)
|
||||||
cmd.finalize_options()
|
cmd.finalize_options()
|
||||||
#print(cmd.build_platlib)
|
#print(cmd.build_platlib)
|
||||||
|
|
||||||
os.environ['PYTHONPATH'] = os.path.join(os.getcwd(), cmd.build_platlib)
|
os.environ['PYTHONPATH'] = os.path.join(os.getcwd(), cmd.build_platlib)
|
||||||
os.environ['LD_LIBRARY_PATH'] = os.getcwd()
|
os.environ['LD_LIBRARY_PATH'] = os.getcwd()
|
||||||
|
|
||||||
ret = subprocess.call(sys.argv[2:])
|
ret = subprocess.call(sys.argv[2:])
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
# the following line is not working due to https://bugs.python.org/issue9023
|
# the following line is not working due to https://bugs.python.org/issue9023
|
||||||
@@ -43,7 +43,8 @@ audaspace = Extension(
|
|||||||
library_dirs = ['.', 'Release', 'Debug'],
|
library_dirs = ['.', 'Release', 'Debug'],
|
||||||
language = 'c++',
|
language = 'c++',
|
||||||
extra_compile_args = extra_args,
|
extra_compile_args = extra_args,
|
||||||
sources = [os.path.join(source_directory, file) for file in ['PyAPI.cpp', 'PyDevice.cpp', 'PyHandle.cpp', 'PySound.cpp', 'PySequenceEntry.cpp', 'PySequence.cpp', 'PyPlaybackManager.cpp', 'PyDynamicMusic.cpp', 'PyThreadPool.cpp', 'PySource.cpp'] + (['PyImpulseResponse.cpp', 'PyHRTF.cpp'] if '@WITH_FFTW@' == 'ON' else [])]
|
define_macros = [('WITH_CONVOLUTION', None)] if '@WITH_FFTW@' == 'ON' else [],
|
||||||
|
sources = [os.path.join(source_directory, file) for file in ['PyAPI.cpp', 'PyDevice.cpp', 'PyHandle.cpp', 'PySound.cpp', 'PySequenceEntry.cpp', 'PySequence.cpp', 'PyPlaybackManager.cpp', 'PyDynamicMusic.cpp', 'PyThreadPool.cpp', 'PySource.cpp'] + (['PyImpulseResponse.cpp', 'PyHRTF.cpp'] if '@WITH_FFTW@' == 'ON' else [])]
|
||||||
)
|
)
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
@@ -56,6 +57,6 @@ setup(
|
|||||||
license = 'Apache License 2.0',
|
license = 'Apache License 2.0',
|
||||||
long_description = codecs.open(os.path.join(source_directory, '../../README.md'), 'r', 'utf-8').read(),
|
long_description = codecs.open(os.path.join(source_directory, '../../README.md'), 'r', 'utf-8').read(),
|
||||||
ext_modules = [audaspace],
|
ext_modules = [audaspace],
|
||||||
headers = [os.path.join(source_directory, file) for file in ['PyAPI.h', 'PyDevice.h', 'PyHandle.h', 'PySound.h', 'PySequenceEntry.h', 'PySequence.h', 'PyPlaybackManager.h', 'PyDynamicMusic.h', 'PyThreadPool.h', 'PySource.h'] + (['PyImpulseResponse.h', 'PyHRTF.h'] if '@WITH_FFTW@' == 'ON' else [])] + ['Audaspace.h']
|
headers = [os.path.join(source_directory, file) for file in ['PyAPI.h', 'PyDevice.h', 'PyHandle.h', 'PySound.h', 'PySequenceEntry.h', 'PySequence.h', 'PyPlaybackManager.h', 'PyDynamicMusic.h', 'PyThreadPool.h', 'PySource.h'] + (['PyImpulseResponse.h', 'PyHRTF.h'] if '@WITH_FFTW@' == 'ON' else [])] + ['Audaspace.h']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -177,7 +177,7 @@ void FFMPEGReader::init(int stream)
|
|||||||
|
|
||||||
// get a decoder and open it
|
// get a decoder and open it
|
||||||
#ifndef FFMPEG_OLD_CODE
|
#ifndef FFMPEG_OLD_CODE
|
||||||
AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id);
|
const AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id);
|
||||||
|
|
||||||
if(!aCodec)
|
if(!aCodec)
|
||||||
AUD_THROW(FileException, "File couldn't be read, no decoder found with ffmpeg.");
|
AUD_THROW(FileException, "File couldn't be read, no decoder found with ffmpeg.");
|
||||||
|
39
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
vendored
39
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
vendored
@@ -23,6 +23,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavformat/avio.h>
|
#include <libavformat/avio.h>
|
||||||
|
#include <libavutil/channel_layout.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
AUD_NAMESPACE_BEGIN
|
AUD_NAMESPACE_BEGIN
|
||||||
@@ -171,66 +172,66 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
|||||||
if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0)
|
if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0)
|
||||||
AUD_THROW(FileException, "File couldn't be written, format couldn't be found with ffmpeg.");
|
AUD_THROW(FileException, "File couldn't be written, format couldn't be found with ffmpeg.");
|
||||||
|
|
||||||
AVOutputFormat* outputFmt = m_formatCtx->oformat;
|
const AVOutputFormat* outputFmt = m_formatCtx->oformat;
|
||||||
|
|
||||||
if(!outputFmt) {
|
if(!outputFmt) {
|
||||||
avformat_free_context(m_formatCtx);
|
avformat_free_context(m_formatCtx);
|
||||||
AUD_THROW(FileException, "File couldn't be written, output format couldn't be found with ffmpeg.");
|
AUD_THROW(FileException, "File couldn't be written, output format couldn't be found with ffmpeg.");
|
||||||
}
|
}
|
||||||
|
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
AVCodecID audio_codec = AV_CODEC_ID_NONE;
|
||||||
|
|
||||||
switch(codec)
|
switch(codec)
|
||||||
{
|
{
|
||||||
case CODEC_AAC:
|
case CODEC_AAC:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_AAC;
|
audio_codec = AV_CODEC_ID_AAC;
|
||||||
break;
|
break;
|
||||||
case CODEC_AC3:
|
case CODEC_AC3:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_AC3;
|
audio_codec = AV_CODEC_ID_AC3;
|
||||||
break;
|
break;
|
||||||
case CODEC_FLAC:
|
case CODEC_FLAC:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_FLAC;
|
audio_codec = AV_CODEC_ID_FLAC;
|
||||||
break;
|
break;
|
||||||
case CODEC_MP2:
|
case CODEC_MP2:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_MP2;
|
audio_codec = AV_CODEC_ID_MP2;
|
||||||
break;
|
break;
|
||||||
case CODEC_MP3:
|
case CODEC_MP3:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_MP3;
|
audio_codec = AV_CODEC_ID_MP3;
|
||||||
break;
|
break;
|
||||||
case CODEC_OPUS:
|
case CODEC_OPUS:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_OPUS;
|
audio_codec = AV_CODEC_ID_OPUS;
|
||||||
break;
|
break;
|
||||||
case CODEC_PCM:
|
case CODEC_PCM:
|
||||||
switch(specs.format)
|
switch(specs.format)
|
||||||
{
|
{
|
||||||
case FORMAT_U8:
|
case FORMAT_U8:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_U8;
|
audio_codec = AV_CODEC_ID_PCM_U8;
|
||||||
break;
|
break;
|
||||||
case FORMAT_S16:
|
case FORMAT_S16:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
|
audio_codec = AV_CODEC_ID_PCM_S16LE;
|
||||||
break;
|
break;
|
||||||
case FORMAT_S24:
|
case FORMAT_S24:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE;
|
audio_codec = AV_CODEC_ID_PCM_S24LE;
|
||||||
break;
|
break;
|
||||||
case FORMAT_S32:
|
case FORMAT_S32:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE;
|
audio_codec = AV_CODEC_ID_PCM_S32LE;
|
||||||
break;
|
break;
|
||||||
case FORMAT_FLOAT32:
|
case FORMAT_FLOAT32:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE;
|
audio_codec = AV_CODEC_ID_PCM_F32LE;
|
||||||
break;
|
break;
|
||||||
case FORMAT_FLOAT64:
|
case FORMAT_FLOAT64:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE;
|
audio_codec = AV_CODEC_ID_PCM_F64LE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
audio_codec = AV_CODEC_ID_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_VORBIS:
|
case CODEC_VORBIS:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_VORBIS;
|
audio_codec = AV_CODEC_ID_VORBIS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
outputFmt->audio_codec = AV_CODEC_ID_NONE;
|
audio_codec = AV_CODEC_ID_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,10 +269,10 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(outputFmt->audio_codec == AV_CODEC_ID_NONE)
|
if(audio_codec == AV_CODEC_ID_NONE)
|
||||||
AUD_THROW(FileException, "File couldn't be written, audio codec not found with ffmpeg.");
|
AUD_THROW(FileException, "File couldn't be written, audio codec not found with ffmpeg.");
|
||||||
|
|
||||||
AVCodec* codec = avcodec_find_encoder(outputFmt->audio_codec);
|
const AVCodec* codec = avcodec_find_encoder(audio_codec);
|
||||||
if(!codec)
|
if(!codec)
|
||||||
AUD_THROW(FileException, "File couldn't be written, audio encoder couldn't be found with ffmpeg.");
|
AUD_THROW(FileException, "File couldn't be written, audio encoder couldn't be found with ffmpeg.");
|
||||||
|
|
||||||
|
80
extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
vendored
80
extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
vendored
@@ -95,6 +95,13 @@ void WASAPIDevice::runMixingThread()
|
|||||||
sleep_duration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
|
sleep_duration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_default_device_changed)
|
||||||
|
{
|
||||||
|
m_default_device_changed = false;
|
||||||
|
result = AUDCLNT_E_DEVICE_INVALIDATED;
|
||||||
|
goto stop_thread;
|
||||||
|
}
|
||||||
|
|
||||||
if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
|
if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
|
||||||
goto stop_thread;
|
goto stop_thread;
|
||||||
|
|
||||||
@@ -296,13 +303,78 @@ bool WASAPIDevice::setupDevice(DeviceSpecs &specs)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG WASAPIDevice::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&m_reference_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG WASAPIDevice::Release()
|
||||||
|
{
|
||||||
|
ULONG reference_count = InterlockedDecrement(&m_reference_count);
|
||||||
|
|
||||||
|
if(0 == reference_count)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return reference_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::QueryInterface(REFIID riid, void **ppvObject)
|
||||||
|
{
|
||||||
|
if(riid == __uuidof(IMMNotificationClient))
|
||||||
|
{
|
||||||
|
*ppvObject = reinterpret_cast<IMMNotificationClient*>(this);
|
||||||
|
AddRef();
|
||||||
|
}
|
||||||
|
else if(riid == IID_IUnknown)
|
||||||
|
{
|
||||||
|
*ppvObject = reinterpret_cast<IUnknown*>(this);
|
||||||
|
AddRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = nullptr;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::OnDeviceAdded(LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::OnDeviceRemoved(LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
if(flow != EDataFlow::eCapture)
|
||||||
|
m_default_device_changed = true;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WASAPIDevice::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
|
WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
|
||||||
m_buffersize(buffersize),
|
m_buffersize(buffersize),
|
||||||
m_imm_device_enumerator(nullptr),
|
m_imm_device_enumerator(nullptr),
|
||||||
m_imm_device(nullptr),
|
m_imm_device(nullptr),
|
||||||
m_audio_client(nullptr),
|
m_audio_client(nullptr),
|
||||||
|
m_wave_format_extensible({}),
|
||||||
m_wave_format_extensible({})
|
m_default_device_changed(false),
|
||||||
|
m_reference_count(1)
|
||||||
{
|
{
|
||||||
// initialize COM if it hasn't happened yet
|
// initialize COM if it hasn't happened yet
|
||||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||||
@@ -327,6 +399,8 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
|
|||||||
|
|
||||||
create();
|
create();
|
||||||
|
|
||||||
|
m_imm_device_enumerator->RegisterEndpointNotificationCallback(this);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -340,6 +414,8 @@ WASAPIDevice::~WASAPIDevice()
|
|||||||
{
|
{
|
||||||
stopMixingThread();
|
stopMixingThread();
|
||||||
|
|
||||||
|
m_imm_device_enumerator->UnregisterEndpointNotificationCallback(this);
|
||||||
|
|
||||||
SafeRelease(&m_audio_client);
|
SafeRelease(&m_audio_client);
|
||||||
SafeRelease(&m_imm_device);
|
SafeRelease(&m_imm_device);
|
||||||
SafeRelease(&m_imm_device_enumerator);
|
SafeRelease(&m_imm_device_enumerator);
|
||||||
|
15
extern/audaspace/plugins/wasapi/WASAPIDevice.h
vendored
15
extern/audaspace/plugins/wasapi/WASAPIDevice.h
vendored
@@ -40,7 +40,7 @@ AUD_NAMESPACE_BEGIN
|
|||||||
/**
|
/**
|
||||||
* This device plays back through WASAPI, the Windows audio API.
|
* This device plays back through WASAPI, the Windows audio API.
|
||||||
*/
|
*/
|
||||||
class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice
|
class AUD_PLUGIN_API WASAPIDevice : IMMNotificationClient, public ThreadedDevice
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int m_buffersize;
|
int m_buffersize;
|
||||||
@@ -48,6 +48,8 @@ private:
|
|||||||
IMMDevice* m_imm_device;
|
IMMDevice* m_imm_device;
|
||||||
IAudioClient* m_audio_client;
|
IAudioClient* m_audio_client;
|
||||||
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
|
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
|
||||||
|
bool m_default_device_changed;
|
||||||
|
LONG m_reference_count;
|
||||||
|
|
||||||
AUD_LOCAL HRESULT setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size);
|
AUD_LOCAL HRESULT setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size);
|
||||||
|
|
||||||
@@ -58,6 +60,17 @@ private:
|
|||||||
|
|
||||||
AUD_LOCAL bool setupDevice(DeviceSpecs& specs);
|
AUD_LOCAL bool setupDevice(DeviceSpecs& specs);
|
||||||
|
|
||||||
|
// IUnknown implementation
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
ULONG STDMETHODCALLTYPE Release();
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
||||||
|
// IMMNotificationClient implementation
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId);
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId);
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId);
|
||||||
|
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
|
||||||
|
|
||||||
// delete copy constructor and operator=
|
// delete copy constructor and operator=
|
||||||
WASAPIDevice(const WASAPIDevice&) = delete;
|
WASAPIDevice(const WASAPIDevice&) = delete;
|
||||||
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
|
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
|
||||||
|
4
extern/hipew/src/hipew.c
vendored
4
extern/hipew/src/hipew.c
vendored
@@ -257,7 +257,7 @@ static int hipewHipInit(void) {
|
|||||||
#endif
|
#endif
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
static int result = 0;
|
static int result = 0;
|
||||||
int error, driver_version;
|
int error;
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
return result;
|
return result;
|
||||||
@@ -565,8 +565,6 @@ int hipewCompilerVersion(void) {
|
|||||||
const char *path = hipewCompilerPath();
|
const char *path = hipewCompilerPath();
|
||||||
const char *marker = "Hip compilation tools, release ";
|
const char *marker = "Hip compilation tools, release ";
|
||||||
FILE *pipe;
|
FILE *pipe;
|
||||||
int major, minor;
|
|
||||||
char *versionstr;
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
char output[65536] = "\0";
|
char output[65536] = "\0";
|
||||||
char command[65536] = "\0";
|
char command[65536] = "\0";
|
||||||
|
@@ -25,7 +25,6 @@ add_subdirectory(ghost)
|
|||||||
add_subdirectory(guardedalloc)
|
add_subdirectory(guardedalloc)
|
||||||
add_subdirectory(libmv)
|
add_subdirectory(libmv)
|
||||||
add_subdirectory(memutil)
|
add_subdirectory(memutil)
|
||||||
add_subdirectory(numaapi)
|
|
||||||
add_subdirectory(opencolorio)
|
add_subdirectory(opencolorio)
|
||||||
add_subdirectory(opensubdiv)
|
add_subdirectory(opensubdiv)
|
||||||
add_subdirectory(mikktspace)
|
add_subdirectory(mikktspace)
|
||||||
|
@@ -44,17 +44,13 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||||
list(APPEND LIBRARIES ${GLUT_LIBRARIES})
|
add_definitions(${GL_DEFINITIONS})
|
||||||
|
list(APPEND INC_SYS ${GLEW_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS})
|
||||||
|
list(APPEND LIBRARIES ${CYCLES_GL_LIBRARIES} ${SDL2_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND LIBRARIES ${CYCLES_GL_LIBRARIES})
|
|
||||||
|
|
||||||
# Common configuration.
|
# Common configuration.
|
||||||
|
|
||||||
cycles_link_directories()
|
|
||||||
|
|
||||||
add_definitions(${GL_DEFINITIONS})
|
|
||||||
|
|
||||||
include_directories(${INC})
|
include_directories(${INC})
|
||||||
include_directories(SYSTEM ${INC_SYS})
|
include_directories(SYSTEM ${INC_SYS})
|
||||||
|
|
||||||
@@ -68,6 +64,18 @@ if(WITH_CYCLES_STANDALONE)
|
|||||||
oiio_output_driver.cpp
|
oiio_output_driver.cpp
|
||||||
oiio_output_driver.h
|
oiio_output_driver.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WITH_CYCLES_STANDALONE_GUI)
|
||||||
|
list(APPEND SRC
|
||||||
|
opengl/display_driver.cpp
|
||||||
|
opengl/display_driver.h
|
||||||
|
opengl/shader.cpp
|
||||||
|
opengl/shader.h
|
||||||
|
opengl/window.cpp
|
||||||
|
opengl/window.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(cycles ${SRC} ${INC} ${INC_SYS})
|
add_executable(cycles ${SRC} ${INC} ${INC_SYS})
|
||||||
unset(SRC)
|
unset(SRC)
|
||||||
|
|
||||||
@@ -82,6 +90,10 @@ if(WITH_CYCLES_STANDALONE)
|
|||||||
# OpenImageDenoise uses BNNS from the Accelerate framework.
|
# OpenImageDenoise uses BNNS from the Accelerate framework.
|
||||||
set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework Accelerate")
|
set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework Accelerate")
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_CYCLES_STANDALONE_GUI)
|
||||||
|
set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS
|
||||||
|
" -framework Cocoa -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework ForceFeedback -framework CoreVideo")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
@@ -40,11 +40,10 @@
|
|||||||
#include "app/oiio_output_driver.h"
|
#include "app/oiio_output_driver.h"
|
||||||
|
|
||||||
#ifdef WITH_CYCLES_STANDALONE_GUI
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
||||||
# include "util/view.h"
|
# include "opengl/display_driver.h"
|
||||||
|
# include "opengl/window.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "app/cycles_xml.h"
|
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
@@ -82,7 +81,7 @@ static void session_print_status()
|
|||||||
string status, substatus;
|
string status, substatus;
|
||||||
|
|
||||||
/* get status */
|
/* get status */
|
||||||
float progress = options.session->progress.get_progress();
|
double progress = options.session->progress.get_progress();
|
||||||
options.session->progress.get_status(status, substatus);
|
options.session->progress.get_status(status, substatus);
|
||||||
|
|
||||||
if (substatus != "")
|
if (substatus != "")
|
||||||
@@ -130,7 +129,14 @@ static void session_init()
|
|||||||
options.output_pass = "combined";
|
options.output_pass = "combined";
|
||||||
options.session = new Session(options.session_params, options.scene_params);
|
options.session = new Session(options.session_params, options.scene_params);
|
||||||
|
|
||||||
if (!options.output_filepath.empty()) {
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
||||||
|
if (!options.session_params.background) {
|
||||||
|
options.session->set_display_driver(make_unique<OpenGLDisplayDriver>(
|
||||||
|
window_opengl_context_enable, window_opengl_context_disable));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (!options.output_filepath.empty()) {
|
||||||
options.session->set_output_driver(make_unique<OIIOOutputDriver>(
|
options.session->set_output_driver(make_unique<OIIOOutputDriver>(
|
||||||
options.output_filepath, options.output_pass, session_print));
|
options.output_filepath, options.output_pass, session_print));
|
||||||
}
|
}
|
||||||
@@ -139,7 +145,7 @@ static void session_init()
|
|||||||
options.session->progress.set_update_callback(function_bind(&session_print_status));
|
options.session->progress.set_update_callback(function_bind(&session_print_status));
|
||||||
#ifdef WITH_CYCLES_STANDALONE_GUI
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
||||||
else
|
else
|
||||||
options.session->progress.set_update_callback(function_bind(&view_redraw));
|
options.session->progress.set_update_callback(function_bind(&window_redraw));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* load scene */
|
/* load scene */
|
||||||
@@ -183,7 +189,7 @@ static void display_info(Progress &progress)
|
|||||||
|
|
||||||
progress.get_time(total_time, sample_time);
|
progress.get_time(total_time, sample_time);
|
||||||
progress.get_status(status, substatus);
|
progress.get_status(status, substatus);
|
||||||
float progress_val = progress.get_progress();
|
double progress_val = progress.get_progress();
|
||||||
|
|
||||||
if (substatus != "")
|
if (substatus != "")
|
||||||
status += ": " + substatus;
|
status += ": " + substatus;
|
||||||
@@ -204,10 +210,10 @@ static void display_info(Progress &progress)
|
|||||||
sample_time,
|
sample_time,
|
||||||
interactive.c_str());
|
interactive.c_str());
|
||||||
|
|
||||||
view_display_info(str.c_str());
|
window_display_info(str.c_str());
|
||||||
|
|
||||||
if (options.show_help)
|
if (options.show_help)
|
||||||
view_display_help();
|
window_display_help();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display()
|
static void display()
|
||||||
@@ -538,15 +544,15 @@ int main(int argc, const char **argv)
|
|||||||
string title = "Cycles: " + path_filename(options.filepath);
|
string title = "Cycles: " + path_filename(options.filepath);
|
||||||
|
|
||||||
/* init/exit are callback so they run while GL is initialized */
|
/* init/exit are callback so they run while GL is initialized */
|
||||||
view_main_loop(title.c_str(),
|
window_main_loop(title.c_str(),
|
||||||
options.width,
|
options.width,
|
||||||
options.height,
|
options.height,
|
||||||
session_init,
|
session_init,
|
||||||
session_exit,
|
session_exit,
|
||||||
resize,
|
resize,
|
||||||
display,
|
display,
|
||||||
keyboard,
|
keyboard,
|
||||||
motion);
|
motion);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
398
intern/cycles/app/opengl/display_driver.cpp
Normal file
398
intern/cycles/app/opengl/display_driver.cpp
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app/opengl/display_driver.h"
|
||||||
|
#include "app/opengl/shader.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* OpenGLDisplayDriver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OpenGLDisplayDriver::OpenGLDisplayDriver(const function<bool()> &gl_context_enable,
|
||||||
|
const function<void()> &gl_context_disable)
|
||||||
|
: gl_context_enable_(gl_context_enable), gl_context_disable_(gl_context_disable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLDisplayDriver::~OpenGLDisplayDriver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* Update procedure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::next_tile_begin()
|
||||||
|
{
|
||||||
|
/* Assuming no tiles used in interactive display. */
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLDisplayDriver::update_begin(const Params ¶ms, int texture_width, int texture_height)
|
||||||
|
{
|
||||||
|
/* Note that it's the responsibility of OpenGLDisplayDriver to ensure updating and drawing
|
||||||
|
* the texture does not happen at the same time. This is achieved indirectly.
|
||||||
|
*
|
||||||
|
* When enabling the OpenGL context, it uses an internal mutex lock DST.gl_context_lock.
|
||||||
|
* This same lock is also held when do_draw() is called, which together ensure mutual
|
||||||
|
* exclusion.
|
||||||
|
*
|
||||||
|
* This locking is not performed on the Cycles side, because that would cause lock inversion. */
|
||||||
|
if (!gl_context_enable_()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_render_sync_) {
|
||||||
|
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gl_texture_resources_ensure()) {
|
||||||
|
gl_context_disable_();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update texture dimensions if needed. */
|
||||||
|
if (texture_.width != texture_width || texture_.height != texture_height) {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
|
texture_.width = texture_width;
|
||||||
|
texture_.height = texture_height;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
/* Texture did change, and no pixel storage was provided. Tag for an explicit zeroing out to
|
||||||
|
* avoid undefined content. */
|
||||||
|
texture_.need_clear = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update PBO dimensions if needed.
|
||||||
|
*
|
||||||
|
* NOTE: Allocate the PBO for the the size which will fit the final render resolution (as in,
|
||||||
|
* at a resolution divider 1. This was we don't need to recreate graphics interoperability
|
||||||
|
* objects which are costly and which are tied to the specific underlying buffer size.
|
||||||
|
* The downside of this approach is that when graphics interoperability is not used we are
|
||||||
|
* sending too much data to GPU when resolution divider is not 1. */
|
||||||
|
const int buffer_width = params.full_size.x;
|
||||||
|
const int buffer_height = params.full_size.y;
|
||||||
|
if (texture_.buffer_width != buffer_width || texture_.buffer_height != buffer_height) {
|
||||||
|
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
texture_.buffer_width = buffer_width;
|
||||||
|
texture_.buffer_height = buffer_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New content will be provided to the texture in one way or another, so mark this in a
|
||||||
|
* centralized place. */
|
||||||
|
texture_.need_update = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::update_end()
|
||||||
|
{
|
||||||
|
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
glFlush();
|
||||||
|
|
||||||
|
gl_context_disable_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* Texture buffer mapping.
|
||||||
|
*/
|
||||||
|
|
||||||
|
half4 *OpenGLDisplayDriver::map_texture_buffer()
|
||||||
|
{
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
|
|
||||||
|
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
|
||||||
|
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
||||||
|
if (!mapped_rgba_pixels) {
|
||||||
|
LOG(ERROR) << "Error mapping OpenGLDisplayDriver pixel buffer object.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_.need_clear) {
|
||||||
|
const int64_t texture_width = texture_.width;
|
||||||
|
const int64_t texture_height = texture_.height;
|
||||||
|
memset(reinterpret_cast<void *>(mapped_rgba_pixels),
|
||||||
|
0,
|
||||||
|
texture_width * texture_height * sizeof(half4));
|
||||||
|
texture_.need_clear = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapped_rgba_pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::unmap_texture_buffer()
|
||||||
|
{
|
||||||
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* Graphics interoperability.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OpenGLDisplayDriver::GraphicsInterop OpenGLDisplayDriver::graphics_interop_get()
|
||||||
|
{
|
||||||
|
GraphicsInterop interop_dst;
|
||||||
|
|
||||||
|
interop_dst.buffer_width = texture_.buffer_width;
|
||||||
|
interop_dst.buffer_height = texture_.buffer_height;
|
||||||
|
interop_dst.opengl_pbo_id = texture_.gl_pbo_id;
|
||||||
|
|
||||||
|
interop_dst.need_clear = texture_.need_clear;
|
||||||
|
texture_.need_clear = false;
|
||||||
|
|
||||||
|
return interop_dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::graphics_interop_activate()
|
||||||
|
{
|
||||||
|
gl_context_enable_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::graphics_interop_deactivate()
|
||||||
|
{
|
||||||
|
gl_context_disable_();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* Drawing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::clear()
|
||||||
|
{
|
||||||
|
texture_.need_clear = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::draw(const Params ¶ms)
|
||||||
|
{
|
||||||
|
/* See do_update_begin() for why no locking is required here. */
|
||||||
|
if (texture_.need_clear) {
|
||||||
|
/* Texture is requested to be cleared and was not yet cleared.
|
||||||
|
* Do early return which should be equivalent of drawing all-zero texture. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gl_draw_resources_ensure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_upload_sync_) {
|
||||||
|
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
display_shader_.bind(params.full_size.x, params.full_size.y);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
|
|
||||||
|
if (texture_.width != params.size.x || texture_.height != params.size.y) {
|
||||||
|
/* Resolution divider is different from 1, force nearest interpolation. */
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
|
||||||
|
|
||||||
|
texture_update_if_needed();
|
||||||
|
vertex_buffer_update(params);
|
||||||
|
|
||||||
|
GLuint vertex_array_object;
|
||||||
|
glGenVertexArrays(1, &vertex_array_object);
|
||||||
|
glBindVertexArray(vertex_array_object);
|
||||||
|
|
||||||
|
const int texcoord_attribute = display_shader_.get_tex_coord_attrib_location();
|
||||||
|
const int position_attribute = display_shader_.get_position_attrib_location();
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(texcoord_attribute);
|
||||||
|
glEnableVertexAttribArray(position_attribute);
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
|
||||||
|
glVertexAttribPointer(position_attribute,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
4 * sizeof(float),
|
||||||
|
(const GLvoid *)(sizeof(float) * 2));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
glDeleteVertexArrays(1, &vertex_array_object);
|
||||||
|
|
||||||
|
display_shader_.unbind();
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLDisplayDriver::gl_draw_resources_ensure()
|
||||||
|
{
|
||||||
|
if (!texture_.gl_id) {
|
||||||
|
/* If there is no texture allocated, there is nothing to draw. Inform the draw call that it can
|
||||||
|
* can not continue. Note that this is not an unrecoverable error, so once the texture is known
|
||||||
|
* we will come back here and create all the GPU resources needed for draw. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_draw_resource_creation_attempted_) {
|
||||||
|
return gl_draw_resources_created_;
|
||||||
|
}
|
||||||
|
gl_draw_resource_creation_attempted_ = true;
|
||||||
|
|
||||||
|
if (!vertex_buffer_) {
|
||||||
|
glGenBuffers(1, &vertex_buffer_);
|
||||||
|
if (!vertex_buffer_) {
|
||||||
|
LOG(ERROR) << "Error creating vertex buffer.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_draw_resources_created_ = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::gl_resources_destroy()
|
||||||
|
{
|
||||||
|
gl_context_enable_();
|
||||||
|
|
||||||
|
if (vertex_buffer_ != 0) {
|
||||||
|
glDeleteBuffers(1, &vertex_buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_.gl_pbo_id) {
|
||||||
|
glDeleteBuffers(1, &texture_.gl_pbo_id);
|
||||||
|
texture_.gl_pbo_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_.gl_id) {
|
||||||
|
glDeleteTextures(1, &texture_.gl_id);
|
||||||
|
texture_.gl_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_context_disable_();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLDisplayDriver::gl_texture_resources_ensure()
|
||||||
|
{
|
||||||
|
if (texture_.creation_attempted) {
|
||||||
|
return texture_.is_created;
|
||||||
|
}
|
||||||
|
texture_.creation_attempted = true;
|
||||||
|
|
||||||
|
DCHECK(!texture_.gl_id);
|
||||||
|
DCHECK(!texture_.gl_pbo_id);
|
||||||
|
|
||||||
|
/* Create texture. */
|
||||||
|
glGenTextures(1, &texture_.gl_id);
|
||||||
|
if (!texture_.gl_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the texture. */
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
/* Create PBO for the texture. */
|
||||||
|
glGenBuffers(1, &texture_.gl_pbo_id);
|
||||||
|
if (!texture_.gl_pbo_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture pixel buffer object.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creation finished with a success. */
|
||||||
|
texture_.is_created = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::texture_update_if_needed()
|
||||||
|
{
|
||||||
|
if (!texture_.need_update) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
||||||
|
glTexSubImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, 0, 0, texture_.width, texture_.height, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
texture_.need_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayDriver::vertex_buffer_update(const Params ¶ms)
|
||||||
|
{
|
||||||
|
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
|
||||||
|
* rendered. */
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
||||||
|
if (!vpointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpointer[0] = 0.0f;
|
||||||
|
vpointer[1] = 0.0f;
|
||||||
|
vpointer[2] = params.full_offset.x;
|
||||||
|
vpointer[3] = params.full_offset.y;
|
||||||
|
|
||||||
|
vpointer[4] = 1.0f;
|
||||||
|
vpointer[5] = 0.0f;
|
||||||
|
vpointer[6] = (float)params.size.x + params.full_offset.x;
|
||||||
|
vpointer[7] = params.full_offset.y;
|
||||||
|
|
||||||
|
vpointer[8] = 1.0f;
|
||||||
|
vpointer[9] = 1.0f;
|
||||||
|
vpointer[10] = (float)params.size.x + params.full_offset.x;
|
||||||
|
vpointer[11] = (float)params.size.y + params.full_offset.y;
|
||||||
|
|
||||||
|
vpointer[12] = 0.0f;
|
||||||
|
vpointer[13] = 1.0f;
|
||||||
|
vpointer[14] = params.full_offset.x;
|
||||||
|
vpointer[15] = (float)params.size.y + params.full_offset.y;
|
||||||
|
|
||||||
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
130
intern/cycles/app/opengl/display_driver.h
Normal file
130
intern/cycles/app/opengl/display_driver.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "app/opengl/shader.h"
|
||||||
|
|
||||||
|
#include "session/display_driver.h"
|
||||||
|
|
||||||
|
#include "util/function.h"
|
||||||
|
#include "util/unique_ptr.h"
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class OpenGLDisplayDriver : public DisplayDriver {
|
||||||
|
public:
|
||||||
|
/* Callbacks for enabling and disabling the OpenGL context. Must be provided to support enabling
|
||||||
|
* the context on the Cycles render thread independent of the main thread. */
|
||||||
|
OpenGLDisplayDriver(const function<bool()> &gl_context_enable,
|
||||||
|
const function<void()> &gl_context_disable);
|
||||||
|
~OpenGLDisplayDriver();
|
||||||
|
|
||||||
|
virtual void graphics_interop_activate() override;
|
||||||
|
virtual void graphics_interop_deactivate() override;
|
||||||
|
|
||||||
|
virtual void clear() override;
|
||||||
|
|
||||||
|
void set_zoom(float zoom_x, float zoom_y);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void next_tile_begin() override;
|
||||||
|
|
||||||
|
virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||||
|
virtual void update_end() override;
|
||||||
|
|
||||||
|
virtual half4 *map_texture_buffer() override;
|
||||||
|
virtual void unmap_texture_buffer() override;
|
||||||
|
|
||||||
|
virtual GraphicsInterop graphics_interop_get() override;
|
||||||
|
|
||||||
|
virtual void draw(const Params ¶ms) override;
|
||||||
|
|
||||||
|
/* Make sure texture is allocated and its initial configuration is performed. */
|
||||||
|
bool gl_texture_resources_ensure();
|
||||||
|
|
||||||
|
/* Ensure all runtime GPU resources needed for drawing are allocated.
|
||||||
|
* Returns true if all resources needed for drawing are available. */
|
||||||
|
bool gl_draw_resources_ensure();
|
||||||
|
|
||||||
|
/* Destroy all GPU resources which are being used by this object. */
|
||||||
|
void gl_resources_destroy();
|
||||||
|
|
||||||
|
/* Update GPU texture dimensions and content if needed (new pixel data was provided).
|
||||||
|
*
|
||||||
|
* NOTE: The texture needs to be bound. */
|
||||||
|
void texture_update_if_needed();
|
||||||
|
|
||||||
|
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
|
||||||
|
* This buffer is used to render texture in the viewport.
|
||||||
|
*
|
||||||
|
* NOTE: The buffer needs to be bound. */
|
||||||
|
void vertex_buffer_update(const Params ¶ms);
|
||||||
|
|
||||||
|
/* Texture which contains pixels of the render result. */
|
||||||
|
struct {
|
||||||
|
/* Indicates whether texture creation was attempted and succeeded.
|
||||||
|
* Used to avoid multiple attempts of texture creation on GPU issues or GPU context
|
||||||
|
* misconfiguration. */
|
||||||
|
bool creation_attempted = false;
|
||||||
|
bool is_created = false;
|
||||||
|
|
||||||
|
/* OpenGL resource IDs of the texture itself and Pixel Buffer Object (PBO) used to write
|
||||||
|
* pixels to it.
|
||||||
|
*
|
||||||
|
* NOTE: Allocated on the engine's context. */
|
||||||
|
uint gl_id = 0;
|
||||||
|
uint gl_pbo_id = 0;
|
||||||
|
|
||||||
|
/* Is true when new data was written to the PBO, meaning, the texture might need to be resized
|
||||||
|
* and new data is to be uploaded to the GPU. */
|
||||||
|
bool need_update = false;
|
||||||
|
|
||||||
|
/* Content of the texture is to be filled with zeroes. */
|
||||||
|
std::atomic<bool> need_clear = true;
|
||||||
|
|
||||||
|
/* Dimensions of the texture in pixels. */
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
/* Dimensions of the underlying PBO. */
|
||||||
|
int buffer_width = 0;
|
||||||
|
int buffer_height = 0;
|
||||||
|
} texture_;
|
||||||
|
|
||||||
|
OpenGLShader display_shader_;
|
||||||
|
|
||||||
|
/* Special track of whether GPU resources were attempted to be created, to avoid attempts of
|
||||||
|
* their re-creation on failure on every redraw. */
|
||||||
|
bool gl_draw_resource_creation_attempted_ = false;
|
||||||
|
bool gl_draw_resources_created_ = false;
|
||||||
|
|
||||||
|
/* Vertex buffer which hold vertices of a triangle fan which is textures with the texture
|
||||||
|
* holding the render result. */
|
||||||
|
uint vertex_buffer_ = 0;
|
||||||
|
|
||||||
|
void *gl_render_sync_ = nullptr;
|
||||||
|
void *gl_upload_sync_ = nullptr;
|
||||||
|
|
||||||
|
float2 zoom_ = make_float2(1.0f, 1.0f);
|
||||||
|
|
||||||
|
function<bool()> gl_context_enable_ = nullptr;
|
||||||
|
function<void()> gl_context_disable_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
210
intern/cycles/app/opengl/shader.cpp
Normal file
210
intern/cycles/app/opengl/shader.cpp
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app/opengl/shader.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* OpenGLShader.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char *VERTEX_SHADER =
|
||||||
|
"#version 330\n"
|
||||||
|
"uniform vec2 fullscreen;\n"
|
||||||
|
"in vec2 texCoord;\n"
|
||||||
|
"in vec2 pos;\n"
|
||||||
|
"out vec2 texCoord_interp;\n"
|
||||||
|
"\n"
|
||||||
|
"vec2 normalize_coordinates()\n"
|
||||||
|
"{\n"
|
||||||
|
" return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n"
|
||||||
|
" texCoord_interp = texCoord;\n"
|
||||||
|
"}\n\0";
|
||||||
|
|
||||||
|
static const char *FRAGMENT_SHADER =
|
||||||
|
"#version 330\n"
|
||||||
|
"uniform sampler2D image_texture;\n"
|
||||||
|
"in vec2 texCoord_interp;\n"
|
||||||
|
"out vec4 fragColor;\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 rgba = texture(image_texture, texCoord_interp);\n"
|
||||||
|
/* Harcoded Rec.709 gamma, should use OpenColorIO eventually. */
|
||||||
|
" fragColor = pow(rgba, vec4(0.45, 0.45, 0.45, 1.0));\n"
|
||||||
|
"}\n\0";
|
||||||
|
|
||||||
|
static void shader_print_errors(const char *task, const char *log, const char *code)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Shader: " << task << " error:";
|
||||||
|
LOG(ERROR) << "===== shader string ====";
|
||||||
|
|
||||||
|
stringstream stream(code);
|
||||||
|
string partial;
|
||||||
|
|
||||||
|
int line = 1;
|
||||||
|
while (getline(stream, partial, '\n')) {
|
||||||
|
if (line < 10) {
|
||||||
|
LOG(ERROR) << " " << line << " " << partial;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(ERROR) << line << " " << partial;
|
||||||
|
}
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
LOG(ERROR) << log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compile_shader_program(void)
|
||||||
|
{
|
||||||
|
const struct Shader {
|
||||||
|
const char *source;
|
||||||
|
const GLenum type;
|
||||||
|
} shaders[2] = {{VERTEX_SHADER, GL_VERTEX_SHADER}, {FRAGMENT_SHADER, GL_FRAGMENT_SHADER}};
|
||||||
|
|
||||||
|
const GLuint program = glCreateProgram();
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
const GLuint shader = glCreateShader(shaders[i].type);
|
||||||
|
|
||||||
|
string source_str = shaders[i].source;
|
||||||
|
const char *c_str = source_str.c_str();
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, &c_str, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
GLint compile_status;
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
|
||||||
|
|
||||||
|
if (!compile_status) {
|
||||||
|
GLchar log[5000];
|
||||||
|
GLsizei length = 0;
|
||||||
|
glGetShaderInfoLog(shader, sizeof(log), &length, log);
|
||||||
|
shader_print_errors("compile", log, c_str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glAttachShader(program, shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link output. */
|
||||||
|
glBindFragDataLocation(program, 0, "fragColor");
|
||||||
|
|
||||||
|
/* Link and error check. */
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
GLint link_status;
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
|
||||||
|
if (!link_status) {
|
||||||
|
GLchar log[5000];
|
||||||
|
GLsizei length = 0;
|
||||||
|
glGetShaderInfoLog(program, sizeof(log), &length, log);
|
||||||
|
shader_print_errors("linking", log, VERTEX_SHADER);
|
||||||
|
shader_print_errors("linking", log, FRAGMENT_SHADER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenGLShader::get_position_attrib_location()
|
||||||
|
{
|
||||||
|
if (position_attribute_location_ == -1) {
|
||||||
|
const uint shader_program = get_shader_program();
|
||||||
|
position_attribute_location_ = glGetAttribLocation(shader_program, position_attribute_name);
|
||||||
|
}
|
||||||
|
return position_attribute_location_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenGLShader::get_tex_coord_attrib_location()
|
||||||
|
{
|
||||||
|
if (tex_coord_attribute_location_ == -1) {
|
||||||
|
const uint shader_program = get_shader_program();
|
||||||
|
tex_coord_attribute_location_ = glGetAttribLocation(shader_program, tex_coord_attribute_name);
|
||||||
|
}
|
||||||
|
return tex_coord_attribute_location_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::bind(int width, int height)
|
||||||
|
{
|
||||||
|
create_shader_if_needed();
|
||||||
|
|
||||||
|
if (!shader_program_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(shader_program_);
|
||||||
|
glUniform1i(image_texture_location_, 0);
|
||||||
|
glUniform2f(fullscreen_location_, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::unbind()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint OpenGLShader::get_shader_program()
|
||||||
|
{
|
||||||
|
return shader_program_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::create_shader_if_needed()
|
||||||
|
{
|
||||||
|
if (shader_program_ || shader_compile_attempted_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader_compile_attempted_ = true;
|
||||||
|
|
||||||
|
shader_program_ = compile_shader_program();
|
||||||
|
if (!shader_program_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(shader_program_);
|
||||||
|
|
||||||
|
image_texture_location_ = glGetUniformLocation(shader_program_, "image_texture");
|
||||||
|
if (image_texture_location_ < 0) {
|
||||||
|
LOG(ERROR) << "Shader doesn't contain the 'image_texture' uniform.";
|
||||||
|
destroy_shader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullscreen_location_ = glGetUniformLocation(shader_program_, "fullscreen");
|
||||||
|
if (fullscreen_location_ < 0) {
|
||||||
|
LOG(ERROR) << "Shader doesn't contain the 'fullscreen' uniform.";
|
||||||
|
destroy_shader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::destroy_shader()
|
||||||
|
{
|
||||||
|
glDeleteProgram(shader_program_);
|
||||||
|
shader_program_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
58
intern/cycles/app/opengl/shader.h
Normal file
58
intern/cycles/app/opengl/shader.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 OpenGL Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/types.h"
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class OpenGLShader {
|
||||||
|
public:
|
||||||
|
static constexpr const char *position_attribute_name = "pos";
|
||||||
|
static constexpr const char *tex_coord_attribute_name = "texCoord";
|
||||||
|
|
||||||
|
OpenGLShader() = default;
|
||||||
|
virtual ~OpenGLShader() = default;
|
||||||
|
|
||||||
|
/* Get attribute location for position and texture coordinate respectively.
|
||||||
|
* NOTE: The shader needs to be bound to have access to those. */
|
||||||
|
int get_position_attrib_location();
|
||||||
|
int get_tex_coord_attrib_location();
|
||||||
|
|
||||||
|
void bind(int width, int height);
|
||||||
|
void unbind();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint get_shader_program();
|
||||||
|
|
||||||
|
void create_shader_if_needed();
|
||||||
|
void destroy_shader();
|
||||||
|
|
||||||
|
/* Cached values of various OpenGL resources. */
|
||||||
|
int position_attribute_location_ = -1;
|
||||||
|
int tex_coord_attribute_location_ = -1;
|
||||||
|
|
||||||
|
uint shader_program_ = 0;
|
||||||
|
int image_texture_location_ = -1;
|
||||||
|
int fullscreen_location_ = -1;
|
||||||
|
|
||||||
|
/* Shader compilation attempted. Which means, that if the shader program is 0 then compilation or
|
||||||
|
* linking has failed. Do not attempt to re-compile the shader. */
|
||||||
|
bool shader_compile_attempted_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
365
intern/cycles/app/opengl/window.cpp
Normal file
365
intern/cycles/app/opengl/window.cpp
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "app/opengl/window.h"
|
||||||
|
|
||||||
|
#include "util/string.h"
|
||||||
|
#include "util/thread.h"
|
||||||
|
#include "util/time.h"
|
||||||
|
#include "util/version.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/* structs */
|
||||||
|
|
||||||
|
struct Window {
|
||||||
|
WindowInitFunc initf = nullptr;
|
||||||
|
WindowExitFunc exitf = nullptr;
|
||||||
|
WindowResizeFunc resize = nullptr;
|
||||||
|
WindowDisplayFunc display = nullptr;
|
||||||
|
WindowKeyboardFunc keyboard = nullptr;
|
||||||
|
WindowMotionFunc motion = nullptr;
|
||||||
|
|
||||||
|
bool first_display = true;
|
||||||
|
bool redraw = false;
|
||||||
|
|
||||||
|
int mouseX = 0, mouseY = 0;
|
||||||
|
int mouseBut0 = 0, mouseBut2 = 0;
|
||||||
|
|
||||||
|
int width = 0, height = 0;
|
||||||
|
|
||||||
|
SDL_Window *window = nullptr;
|
||||||
|
SDL_GLContext gl_context = nullptr;
|
||||||
|
thread_mutex gl_context_mutex;
|
||||||
|
} V;
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
|
||||||
|
static void window_display_text(int x, int y, const char *text)
|
||||||
|
{
|
||||||
|
/* Not currently supported, need to add text rendering support. */
|
||||||
|
#if 0
|
||||||
|
const char *c;
|
||||||
|
|
||||||
|
glRasterPos3f(x, y, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
printf("display %s\n", text);
|
||||||
|
|
||||||
|
for (c = text; *c != '\0'; c++) {
|
||||||
|
const uint8_t *bitmap = helvetica10_character_map[*c];
|
||||||
|
glBitmap(bitmap[0],
|
||||||
|
helvetica10_height,
|
||||||
|
helvetica10_x_offset,
|
||||||
|
helvetica10_y_offset,
|
||||||
|
bitmap[0],
|
||||||
|
0.0f,
|
||||||
|
bitmap + 1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static string last_text = "";
|
||||||
|
|
||||||
|
if (text != last_text) {
|
||||||
|
printf("%s\n", text);
|
||||||
|
last_text = text;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_display_info(const char *info)
|
||||||
|
{
|
||||||
|
const int height = 20;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glColor4f(0.1f, 0.1f, 0.1f, 0.8f);
|
||||||
|
glRectf(0.0f, V.height - height, V.width, V.height);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
glColor3f(0.5f, 0.5f, 0.5f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
window_display_text(10, 7 + V.height - height, info);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_display_help()
|
||||||
|
{
|
||||||
|
const int w = (int)((float)V.width / 1.15f);
|
||||||
|
const int h = (int)((float)V.height / 1.15f);
|
||||||
|
|
||||||
|
const int x1 = (V.width - w) / 2;
|
||||||
|
#if 0
|
||||||
|
const int x2 = x1 + w;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const int y1 = (V.height - h) / 2;
|
||||||
|
const int y2 = y1 + h;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glColor4f(0.5f, 0.5f, 0.5f, 0.8f);
|
||||||
|
glRectf(x1, y1, x2, y2);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
glColor3f(0.8f, 0.8f, 0.8f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
string info = string("Cycles Renderer ") + CYCLES_VERSION_STRING;
|
||||||
|
|
||||||
|
window_display_text(x1 + 20, y2 - 20, info.c_str());
|
||||||
|
window_display_text(x1 + 20, y2 - 40, "(C) 2011-2016 Blender Foundation");
|
||||||
|
window_display_text(x1 + 20, y2 - 80, "Controls:");
|
||||||
|
window_display_text(x1 + 20, y2 - 100, "h: Info/Help");
|
||||||
|
window_display_text(x1 + 20, y2 - 120, "r: Reset");
|
||||||
|
window_display_text(x1 + 20, y2 - 140, "p: Pause");
|
||||||
|
window_display_text(x1 + 20, y2 - 160, "esc: Cancel");
|
||||||
|
window_display_text(x1 + 20, y2 - 180, "q: Quit program");
|
||||||
|
|
||||||
|
window_display_text(x1 + 20, y2 - 210, "i: Interactive mode");
|
||||||
|
window_display_text(x1 + 20, y2 - 230, "Left mouse: Move camera");
|
||||||
|
window_display_text(x1 + 20, y2 - 250, "Right mouse: Rotate camera");
|
||||||
|
window_display_text(x1 + 20, y2 - 270, "W/A/S/D: Move camera");
|
||||||
|
window_display_text(x1 + 20, y2 - 290, "0/1/2/3: Set max bounces");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_display()
|
||||||
|
{
|
||||||
|
if (V.first_display) {
|
||||||
|
if (V.initf) {
|
||||||
|
V.initf();
|
||||||
|
}
|
||||||
|
if (V.exitf) {
|
||||||
|
atexit(V.exitf);
|
||||||
|
}
|
||||||
|
|
||||||
|
V.first_display = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_opengl_context_enable();
|
||||||
|
|
||||||
|
glViewport(0, 0, V.width, V.height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glClearColor(0.05f, 0.05f, 0.05f, 0.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, V.width, 0, V.height, -1, 1);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glRasterPos3f(0, 0, 0);
|
||||||
|
|
||||||
|
if (V.display)
|
||||||
|
V.display();
|
||||||
|
|
||||||
|
SDL_GL_SwapWindow(V.window);
|
||||||
|
window_opengl_context_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_reshape(int width, int height)
|
||||||
|
{
|
||||||
|
if (V.width != width || V.height != height) {
|
||||||
|
if (V.resize) {
|
||||||
|
V.resize(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
V.width = width;
|
||||||
|
V.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool window_keyboard(unsigned char key)
|
||||||
|
{
|
||||||
|
if (V.keyboard)
|
||||||
|
V.keyboard(key);
|
||||||
|
|
||||||
|
if (key == 'q') {
|
||||||
|
if (V.exitf)
|
||||||
|
V.exitf();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_mouse(int button, int state, int x, int y)
|
||||||
|
{
|
||||||
|
if (button == SDL_BUTTON_LEFT) {
|
||||||
|
if (state == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
V.mouseX = x;
|
||||||
|
V.mouseY = y;
|
||||||
|
V.mouseBut0 = 1;
|
||||||
|
}
|
||||||
|
else if (state == SDL_MOUSEBUTTONUP) {
|
||||||
|
V.mouseBut0 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (button == SDL_BUTTON_RIGHT) {
|
||||||
|
if (state == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
V.mouseX = x;
|
||||||
|
V.mouseY = y;
|
||||||
|
V.mouseBut2 = 1;
|
||||||
|
}
|
||||||
|
else if (state == SDL_MOUSEBUTTONUP) {
|
||||||
|
V.mouseBut2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_motion(int x, int y)
|
||||||
|
{
|
||||||
|
const int but = V.mouseBut0 ? 0 : 2;
|
||||||
|
const int distX = x - V.mouseX;
|
||||||
|
const int distY = y - V.mouseY;
|
||||||
|
|
||||||
|
if (V.motion)
|
||||||
|
V.motion(distX, distY, but);
|
||||||
|
|
||||||
|
V.mouseX = x;
|
||||||
|
V.mouseY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool window_opengl_context_enable()
|
||||||
|
{
|
||||||
|
V.gl_context_mutex.lock();
|
||||||
|
SDL_GL_MakeCurrent(V.window, V.gl_context);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_opengl_context_disable()
|
||||||
|
{
|
||||||
|
SDL_GL_MakeCurrent(V.window, nullptr);
|
||||||
|
V.gl_context_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_main_loop(const char *title,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
WindowInitFunc initf,
|
||||||
|
WindowExitFunc exitf,
|
||||||
|
WindowResizeFunc resize,
|
||||||
|
WindowDisplayFunc display,
|
||||||
|
WindowKeyboardFunc keyboard,
|
||||||
|
WindowMotionFunc motion)
|
||||||
|
{
|
||||||
|
V.width = width;
|
||||||
|
V.height = height;
|
||||||
|
V.first_display = true;
|
||||||
|
V.redraw = false;
|
||||||
|
V.initf = initf;
|
||||||
|
V.exitf = exitf;
|
||||||
|
V.resize = resize;
|
||||||
|
V.display = display;
|
||||||
|
V.keyboard = keyboard;
|
||||||
|
V.motion = motion;
|
||||||
|
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
|
||||||
|
V.window = SDL_CreateWindow(title,
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
|
||||||
|
if (V.window == nullptr) {
|
||||||
|
fprintf(stderr, "Failed to create window: %s\n", SDL_GetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_RaiseWindow(V.window);
|
||||||
|
|
||||||
|
V.gl_context = SDL_GL_CreateContext(V.window);
|
||||||
|
glewInit();
|
||||||
|
SDL_GL_MakeCurrent(V.window, nullptr);
|
||||||
|
|
||||||
|
window_reshape(width, height);
|
||||||
|
window_display();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
bool quit = false;
|
||||||
|
SDL_Event event;
|
||||||
|
while (!quit && SDL_PollEvent(&event)) {
|
||||||
|
if (event.type == SDL_TEXTINPUT) {
|
||||||
|
quit = window_keyboard(event.text.text[0]);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEMOTION) {
|
||||||
|
window_motion(event.motion.x, event.motion.y);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
|
||||||
|
window_mouse(event.button.button, event.button.state, event.button.x, event.button.y);
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_WINDOWEVENT) {
|
||||||
|
if (event.window.event == SDL_WINDOWEVENT_RESIZED ||
|
||||||
|
event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||||
|
window_reshape(event.window.data1, event.window.data2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_QUIT) {
|
||||||
|
if (V.exitf) {
|
||||||
|
V.exitf();
|
||||||
|
}
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (V.redraw) {
|
||||||
|
V.redraw = false;
|
||||||
|
window_display();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_WaitEventTimeout(NULL, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GL_DeleteContext(V.gl_context);
|
||||||
|
SDL_DestroyWindow(V.window);
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_redraw()
|
||||||
|
{
|
||||||
|
V.redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
48
intern/cycles/app/opengl/window.h
Normal file
48
intern/cycles/app/opengl/window.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* Functions to display a simple OpenGL window using SDL, simplified to the
|
||||||
|
* bare minimum we need to reduce boilerplate code in tests apps. */
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
typedef void (*WindowInitFunc)();
|
||||||
|
typedef void (*WindowExitFunc)();
|
||||||
|
typedef void (*WindowResizeFunc)(int width, int height);
|
||||||
|
typedef void (*WindowDisplayFunc)();
|
||||||
|
typedef void (*WindowKeyboardFunc)(unsigned char key);
|
||||||
|
typedef void (*WindowMotionFunc)(int x, int y, int button);
|
||||||
|
|
||||||
|
void window_main_loop(const char *title,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
WindowInitFunc initf,
|
||||||
|
WindowExitFunc exitf,
|
||||||
|
WindowResizeFunc resize,
|
||||||
|
WindowDisplayFunc display,
|
||||||
|
WindowKeyboardFunc keyboard,
|
||||||
|
WindowMotionFunc motion);
|
||||||
|
|
||||||
|
void window_display_info(const char *info);
|
||||||
|
void window_display_help();
|
||||||
|
void window_redraw();
|
||||||
|
|
||||||
|
bool window_opengl_context_enable();
|
||||||
|
void window_opengl_context_disable();
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
@@ -60,9 +60,8 @@ def init():
|
|||||||
|
|
||||||
path = os.path.dirname(__file__)
|
path = os.path.dirname(__file__)
|
||||||
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
|
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
|
||||||
temp_path = bpy.app.tempdir
|
|
||||||
|
|
||||||
_cycles.init(path, user_path, temp_path, bpy.app.background)
|
_cycles.init(path, user_path, bpy.app.background)
|
||||||
_parse_command_line()
|
_parse_command_line()
|
||||||
|
|
||||||
|
|
||||||
|
@@ -74,7 +74,7 @@ enum_panorama_types = (
|
|||||||
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
||||||
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
|
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
|
||||||
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
|
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
|
||||||
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked."),
|
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked"),
|
||||||
)
|
)
|
||||||
|
|
||||||
enum_curve_shape = (
|
enum_curve_shape = (
|
||||||
@@ -667,6 +667,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
description="Use special type BVH optimized for hair (uses more ram but renders faster)",
|
description="Use special type BVH optimized for hair (uses more ram but renders faster)",
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
debug_use_compact_bvh: BoolProperty(
|
||||||
|
name="Use Compact BVH",
|
||||||
|
description="Use compact BVH structure (uses less ram but renders slower)",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
debug_bvh_time_steps: IntProperty(
|
debug_bvh_time_steps: IntProperty(
|
||||||
name="BVH Time Steps",
|
name="BVH Time Steps",
|
||||||
description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
|
description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
|
||||||
@@ -802,7 +807,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
name="Tile Size",
|
name="Tile Size",
|
||||||
default=2048,
|
default=2048,
|
||||||
description="",
|
description="",
|
||||||
min=8, max=16384,
|
min=8, max=8192,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Various fine-tuning debug flags
|
# Various fine-tuning debug flags
|
||||||
@@ -896,27 +901,27 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
|
|||||||
|
|
||||||
fisheye_polynomial_k0: FloatProperty(
|
fisheye_polynomial_k0: FloatProperty(
|
||||||
name="Fisheye Polynomial K0",
|
name="Fisheye Polynomial K0",
|
||||||
description="Coefficient K0 of the lens polinomial",
|
description="Coefficient K0 of the lens polynomial",
|
||||||
default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE',
|
default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE',
|
||||||
)
|
)
|
||||||
fisheye_polynomial_k1: FloatProperty(
|
fisheye_polynomial_k1: FloatProperty(
|
||||||
name="Fisheye Polynomial K1",
|
name="Fisheye Polynomial K1",
|
||||||
description="Coefficient K1 of the lens polinomial",
|
description="Coefficient K1 of the lens polynomial",
|
||||||
default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE',
|
default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE',
|
||||||
)
|
)
|
||||||
fisheye_polynomial_k2: FloatProperty(
|
fisheye_polynomial_k2: FloatProperty(
|
||||||
name="Fisheye Polynomial K2",
|
name="Fisheye Polynomial K2",
|
||||||
description="Coefficient K2 of the lens polinomial",
|
description="Coefficient K2 of the lens polynomial",
|
||||||
default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE',
|
default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE',
|
||||||
)
|
)
|
||||||
fisheye_polynomial_k3: FloatProperty(
|
fisheye_polynomial_k3: FloatProperty(
|
||||||
name="Fisheye Polynomial K3",
|
name="Fisheye Polynomial K3",
|
||||||
description="Coefficient K3 of the lens polinomial",
|
description="Coefficient K3 of the lens polynomial",
|
||||||
default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE',
|
default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE',
|
||||||
)
|
)
|
||||||
fisheye_polynomial_k4: FloatProperty(
|
fisheye_polynomial_k4: FloatProperty(
|
||||||
name="Fisheye Polynomial K4",
|
name="Fisheye Polynomial K4",
|
||||||
description="Coefficient K4 of the lens polinomial",
|
description="Coefficient K4 of the lens polynomial",
|
||||||
default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE',
|
default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE',
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1369,6 +1374,12 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
use_metalrt: BoolProperty(
|
||||||
|
name="MetalRT (Experimental)",
|
||||||
|
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better performance in specific cases. However this support is experimental and some scenes may render incorrectly",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
def find_existing_device_entry(self, device):
|
def find_existing_device_entry(self, device):
|
||||||
for device_entry in self.devices:
|
for device_entry in self.devices:
|
||||||
if device_entry.id == device[2] and device_entry.type == device[1]:
|
if device_entry.id == device[2] and device_entry.type == device[1]:
|
||||||
@@ -1447,6 +1458,19 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
num += 1
|
num += 1
|
||||||
return num
|
return num
|
||||||
|
|
||||||
|
def has_multi_device(self):
|
||||||
|
import _cycles
|
||||||
|
compute_device_type = self.get_compute_device_type()
|
||||||
|
device_list = _cycles.available_devices(compute_device_type)
|
||||||
|
for device in device_list:
|
||||||
|
if device[1] == compute_device_type:
|
||||||
|
continue
|
||||||
|
for dev in self.devices:
|
||||||
|
if dev.use and dev.id == device[2]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def has_active_device(self):
|
def has_active_device(self):
|
||||||
return self.get_num_gpu_devices() > 0
|
return self.get_num_gpu_devices() > 0
|
||||||
|
|
||||||
@@ -1474,7 +1498,8 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
||||||
elif device_type == 'METAL':
|
elif device_type == 'METAL':
|
||||||
col.label(text="Requires Apple Silicon and macOS 12.0 or newer", icon='BLANK1')
|
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
|
||||||
|
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
|
||||||
return
|
return
|
||||||
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
@@ -1501,6 +1526,15 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||||||
row.use_property_split = True
|
row.use_property_split = True
|
||||||
row.prop(self, "peer_memory")
|
row.prop(self, "peer_memory")
|
||||||
|
|
||||||
|
if compute_device_type == 'METAL':
|
||||||
|
import platform
|
||||||
|
# MetalRT only works on Apple Silicon at present, pending argument encoding fixes on AMD
|
||||||
|
if platform.machine() == 'arm64':
|
||||||
|
row = layout.row()
|
||||||
|
row.use_property_split = True
|
||||||
|
row.prop(self, "use_metalrt")
|
||||||
|
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
self.draw_impl(self.layout, context)
|
self.draw_impl(self.layout, context)
|
||||||
|
|
||||||
|
@@ -118,11 +118,11 @@ def use_optix(context):
|
|||||||
|
|
||||||
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU')
|
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU')
|
||||||
|
|
||||||
|
def use_multi_device(context):
|
||||||
def use_sample_all_lights(context):
|
|
||||||
cscene = context.scene.cycles
|
cscene = context.scene.cycles
|
||||||
|
if cscene.device != 'GPU':
|
||||||
return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
|
return False
|
||||||
|
return context.preferences.addons[__package__].preferences.has_multi_device()
|
||||||
|
|
||||||
|
|
||||||
def show_device_active(context):
|
def show_device_active(context):
|
||||||
@@ -667,6 +667,10 @@ class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Pa
|
|||||||
bl_label = "Acceleration Structure"
|
bl_label = "Acceleration Structure"
|
||||||
bl_parent_id = "CYCLES_RENDER_PT_performance"
|
bl_parent_id = "CYCLES_RENDER_PT_performance"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return not use_optix(context) or use_multi_device(context)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
import _cycles
|
import _cycles
|
||||||
|
|
||||||
@@ -679,21 +683,33 @@ class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Pa
|
|||||||
|
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
|
|
||||||
use_embree = False
|
use_embree = _cycles.with_embree
|
||||||
|
|
||||||
if use_cpu(context):
|
if use_cpu(context):
|
||||||
use_embree = _cycles.with_embree
|
col.prop(cscene, "debug_use_spatial_splits")
|
||||||
if not use_embree:
|
if use_embree:
|
||||||
|
col.prop(cscene, "debug_use_compact_bvh")
|
||||||
|
else:
|
||||||
|
sub = col.column()
|
||||||
|
sub.active = not cscene.debug_use_spatial_splits
|
||||||
|
sub.prop(cscene, "debug_bvh_time_steps")
|
||||||
|
|
||||||
|
col.prop(cscene, "debug_use_hair_bvh")
|
||||||
|
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
sub.label(text="Cycles built without Embree support")
|
sub.label(text="Cycles built without Embree support")
|
||||||
sub.label(text="CPU raytracing performance will be poor")
|
sub.label(text="CPU raytracing performance will be poor")
|
||||||
|
else:
|
||||||
|
col.prop(cscene, "debug_use_spatial_splits")
|
||||||
|
sub = col.column()
|
||||||
|
sub.active = not cscene.debug_use_spatial_splits
|
||||||
|
sub.prop(cscene, "debug_bvh_time_steps")
|
||||||
|
|
||||||
col.prop(cscene, "debug_use_spatial_splits")
|
col.prop(cscene, "debug_use_hair_bvh")
|
||||||
sub = col.column()
|
|
||||||
sub.active = not use_embree
|
# CPU is used in addition to a GPU
|
||||||
sub.prop(cscene, "debug_use_hair_bvh")
|
if use_multi_device(context) and use_embree:
|
||||||
sub = col.column()
|
col.prop(cscene, "debug_use_compact_bvh")
|
||||||
sub.active = not cscene.debug_use_spatial_splits and not use_embree
|
|
||||||
sub.prop(cscene, "debug_bvh_time_steps")
|
|
||||||
|
|
||||||
|
|
||||||
class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
|
class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
|
||||||
@@ -1803,18 +1819,45 @@ class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
|
|||||||
rd = scene.render
|
rd = scene.render
|
||||||
|
|
||||||
if rd.use_bake_multires:
|
if rd.use_bake_multires:
|
||||||
layout.prop(rd, "bake_margin")
|
|
||||||
layout.prop(rd, "use_bake_clear", text="Clear Image")
|
layout.prop(rd, "use_bake_clear", text="Clear Image")
|
||||||
|
|
||||||
if rd.bake_type == 'DISPLACEMENT':
|
if rd.bake_type == 'DISPLACEMENT':
|
||||||
layout.prop(rd, "use_bake_lores_mesh")
|
layout.prop(rd, "use_bake_lores_mesh")
|
||||||
else:
|
else:
|
||||||
layout.prop(cbk, "target")
|
layout.prop(cbk, "target")
|
||||||
|
|
||||||
if cbk.target == 'IMAGE_TEXTURES':
|
if cbk.target == 'IMAGE_TEXTURES':
|
||||||
layout.prop(cbk, "margin")
|
|
||||||
layout.prop(cbk, "use_clear", text="Clear Image")
|
layout.prop(cbk, "use_clear", text="Clear Image")
|
||||||
|
|
||||||
|
class CYCLES_RENDER_PT_bake_output_margin(CyclesButtonsPanel, Panel):
|
||||||
|
bl_label = "Margin"
|
||||||
|
bl_context = "render"
|
||||||
|
bl_parent_id = "CYCLES_RENDER_PT_bake_output"
|
||||||
|
COMPAT_ENGINES = {'CYCLES'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
scene = context.scene
|
||||||
|
cbk = scene.render.bake
|
||||||
|
return cbk.target == 'IMAGE_TEXTURES'
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.use_property_split = True
|
||||||
|
layout.use_property_decorate = False # No animation.
|
||||||
|
|
||||||
|
scene = context.scene
|
||||||
|
cscene = scene.cycles
|
||||||
|
cbk = scene.render.bake
|
||||||
|
rd = scene.render
|
||||||
|
|
||||||
|
if rd.use_bake_multires:
|
||||||
|
layout.prop(rd, "bake_margin_type", text="Type")
|
||||||
|
layout.prop(rd, "bake_margin", text="Size")
|
||||||
|
else:
|
||||||
|
if cbk.target == 'IMAGE_TEXTURES':
|
||||||
|
layout.prop(cbk, "margin_type", text="Type")
|
||||||
|
layout.prop(cbk, "margin", text="Size")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
|
class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
|
||||||
bl_label = "Debug"
|
bl_label = "Debug"
|
||||||
@@ -2183,6 +2226,7 @@ classes = (
|
|||||||
CYCLES_RENDER_PT_bake_influence,
|
CYCLES_RENDER_PT_bake_influence,
|
||||||
CYCLES_RENDER_PT_bake_selected_to_active,
|
CYCLES_RENDER_PT_bake_selected_to_active,
|
||||||
CYCLES_RENDER_PT_bake_output,
|
CYCLES_RENDER_PT_bake_output,
|
||||||
|
CYCLES_RENDER_PT_bake_output_margin,
|
||||||
CYCLES_RENDER_PT_debug,
|
CYCLES_RENDER_PT_debug,
|
||||||
node_panel(CYCLES_MATERIAL_PT_settings),
|
node_panel(CYCLES_MATERIAL_PT_settings),
|
||||||
node_panel(CYCLES_MATERIAL_PT_settings_surface),
|
node_panel(CYCLES_MATERIAL_PT_settings_surface),
|
||||||
|
@@ -118,6 +118,10 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
|
|||||||
device.has_peer_memory = false;
|
device.has_peer_memory = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_boolean(cpreferences, "use_metalrt")) {
|
||||||
|
device.use_metalrt = true;
|
||||||
|
}
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -272,12 +272,307 @@ uint BlenderDisplaySpaceShader::get_shader_program()
|
|||||||
return shader_program_;
|
return shader_program_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* DrawTile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Higher level representation of a texture from the graphics library. */
|
||||||
|
class GLTexture {
|
||||||
|
public:
|
||||||
|
/* Global counter for all allocated OpenGL textures used by instances of this class. */
|
||||||
|
static inline std::atomic<int> num_used = 0;
|
||||||
|
|
||||||
|
GLTexture() = default;
|
||||||
|
|
||||||
|
~GLTexture()
|
||||||
|
{
|
||||||
|
assert(gl_id == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture(const GLTexture &other) = delete;
|
||||||
|
GLTexture &operator=(GLTexture &other) = delete;
|
||||||
|
|
||||||
|
GLTexture(GLTexture &&other) noexcept
|
||||||
|
: gl_id(other.gl_id), width(other.width), height(other.height)
|
||||||
|
{
|
||||||
|
other.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTexture &operator=(GLTexture &&other)
|
||||||
|
{
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_id = other.gl_id;
|
||||||
|
width = other.width;
|
||||||
|
height = other.height;
|
||||||
|
|
||||||
|
other.reset();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gl_resources_ensure()
|
||||||
|
{
|
||||||
|
if (gl_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create texture. */
|
||||||
|
glGenTextures(1, &gl_id);
|
||||||
|
if (!gl_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the texture. */
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, gl_id);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
/* Clamp to edge so that precision issues when zoomed out (which forces linear interpolation)
|
||||||
|
* does not cause unwanted repetition. */
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
++num_used;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_resources_destroy()
|
||||||
|
{
|
||||||
|
if (!gl_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteTextures(1, &gl_id);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
--num_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OpenGL resource IDs of the texture.
|
||||||
|
*
|
||||||
|
* NOTE: Allocated on the render engine's context. */
|
||||||
|
uint gl_id = 0;
|
||||||
|
|
||||||
|
/* Dimensions of the texture in pixels. */
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
gl_id = 0;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Higher level representation of a Pixel Buffer Object (PBO) from the graphics library. */
|
||||||
|
class GLPixelBufferObject {
|
||||||
|
public:
|
||||||
|
/* Global counter for all allocated OpenGL PBOs used by instances of this class. */
|
||||||
|
static inline std::atomic<int> num_used = 0;
|
||||||
|
|
||||||
|
GLPixelBufferObject() = default;
|
||||||
|
|
||||||
|
~GLPixelBufferObject()
|
||||||
|
{
|
||||||
|
assert(gl_id == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLPixelBufferObject(const GLPixelBufferObject &other) = delete;
|
||||||
|
GLPixelBufferObject &operator=(GLPixelBufferObject &other) = delete;
|
||||||
|
|
||||||
|
GLPixelBufferObject(GLPixelBufferObject &&other) noexcept
|
||||||
|
: gl_id(other.gl_id), width(other.width), height(other.height)
|
||||||
|
{
|
||||||
|
other.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLPixelBufferObject &operator=(GLPixelBufferObject &&other)
|
||||||
|
{
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_id = other.gl_id;
|
||||||
|
width = other.width;
|
||||||
|
height = other.height;
|
||||||
|
|
||||||
|
other.reset();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gl_resources_ensure()
|
||||||
|
{
|
||||||
|
if (gl_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &gl_id);
|
||||||
|
if (!gl_id) {
|
||||||
|
LOG(ERROR) << "Error creating texture pixel buffer object.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
++num_used;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_resources_destroy()
|
||||||
|
{
|
||||||
|
if (!gl_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &gl_id);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
--num_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OpenGL resource IDs of the PBO.
|
||||||
|
*
|
||||||
|
* NOTE: Allocated on the render engine's context. */
|
||||||
|
uint gl_id = 0;
|
||||||
|
|
||||||
|
/* Dimensions of the PBO. */
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
gl_id = 0;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DrawTile {
|
||||||
|
public:
|
||||||
|
DrawTile() = default;
|
||||||
|
~DrawTile() = default;
|
||||||
|
|
||||||
|
DrawTile(const DrawTile &other) = delete;
|
||||||
|
DrawTile &operator=(const DrawTile &other) = delete;
|
||||||
|
|
||||||
|
DrawTile(DrawTile &&other) noexcept = default;
|
||||||
|
|
||||||
|
DrawTile &operator=(DrawTile &&other) = default;
|
||||||
|
|
||||||
|
bool gl_resources_ensure()
|
||||||
|
{
|
||||||
|
if (!texture.gl_resources_ensure()) {
|
||||||
|
gl_resources_destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_resources_destroy()
|
||||||
|
{
|
||||||
|
texture.gl_resources_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ready_to_draw() const
|
||||||
|
{
|
||||||
|
return texture.gl_id != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Texture which contains pixels of the tile. */
|
||||||
|
GLTexture texture;
|
||||||
|
|
||||||
|
/* Display parameters the texture of this tile has been updated for. */
|
||||||
|
BlenderDisplayDriver::Params params;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DrawTileAndPBO {
|
||||||
|
public:
|
||||||
|
bool gl_resources_ensure()
|
||||||
|
{
|
||||||
|
if (!tile.gl_resources_ensure() || !buffer_object.gl_resources_ensure()) {
|
||||||
|
gl_resources_destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_resources_destroy()
|
||||||
|
{
|
||||||
|
tile.gl_resources_destroy();
|
||||||
|
buffer_object.gl_resources_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawTile tile;
|
||||||
|
GLPixelBufferObject buffer_object;
|
||||||
|
};
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* BlenderDisplayDriver.
|
* BlenderDisplayDriver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct BlenderDisplayDriver::Tiles {
|
||||||
|
/* Resources of a tile which is being currently rendered. */
|
||||||
|
DrawTileAndPBO current_tile;
|
||||||
|
|
||||||
|
/* All tiles which rendering is finished and which content will not be changed. */
|
||||||
|
struct {
|
||||||
|
vector<DrawTile> tiles;
|
||||||
|
|
||||||
|
void gl_resources_destroy_and_clear()
|
||||||
|
{
|
||||||
|
for (DrawTile &tile : tiles) {
|
||||||
|
tile.gl_resources_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
tiles.clear();
|
||||||
|
}
|
||||||
|
} finished_tiles;
|
||||||
|
|
||||||
|
/* OpenGL vertex buffer needed for drawing. */
|
||||||
|
uint gl_vertex_buffer = 0;
|
||||||
|
|
||||||
|
bool gl_resources_ensure()
|
||||||
|
{
|
||||||
|
if (!gl_vertex_buffer) {
|
||||||
|
glGenBuffers(1, &gl_vertex_buffer);
|
||||||
|
if (!gl_vertex_buffer) {
|
||||||
|
LOG(ERROR) << "Error allocating tile VBO.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_resources_destroy()
|
||||||
|
{
|
||||||
|
if (gl_vertex_buffer) {
|
||||||
|
glDeleteBuffers(1, &gl_vertex_buffer);
|
||||||
|
gl_vertex_buffer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene)
|
BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene)
|
||||||
: b_engine_(b_engine), display_shader_(BlenderDisplayShader::create(b_engine, b_scene))
|
: b_engine_(b_engine),
|
||||||
|
display_shader_(BlenderDisplayShader::create(b_engine, b_scene)),
|
||||||
|
tiles_(make_unique<Tiles>())
|
||||||
{
|
{
|
||||||
/* Create context while on the main thread. */
|
/* Create context while on the main thread. */
|
||||||
gl_context_create();
|
gl_context_create();
|
||||||
@@ -292,6 +587,21 @@ BlenderDisplayDriver::~BlenderDisplayDriver()
|
|||||||
* Update procedure.
|
* Update procedure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void BlenderDisplayDriver::next_tile_begin()
|
||||||
|
{
|
||||||
|
if (!tiles_->current_tile.tile.ready_to_draw()) {
|
||||||
|
LOG(ERROR)
|
||||||
|
<< "Unexpectedly moving to the next tile without any data provided for current tile.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Moving to the next tile without giving render data for the current tile is not an expected
|
||||||
|
* situation. */
|
||||||
|
DCHECK(!need_clear_);
|
||||||
|
|
||||||
|
tiles_->finished_tiles.tiles.emplace_back(std::move(tiles_->current_tile.tile));
|
||||||
|
}
|
||||||
|
|
||||||
bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
||||||
int texture_width,
|
int texture_width,
|
||||||
int texture_height)
|
int texture_height)
|
||||||
@@ -312,24 +622,39 @@ bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
|||||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gl_texture_resources_ensure()) {
|
DrawTile ¤t_tile = tiles_->current_tile.tile;
|
||||||
|
GLPixelBufferObject ¤t_tile_buffer_object = tiles_->current_tile.buffer_object;
|
||||||
|
|
||||||
|
/* Clear storage of all finished tiles when display clear is requested.
|
||||||
|
* Do it when new tile data is provided to handle the display clear flag in a single place.
|
||||||
|
* It also makes the logic reliable from the whether drawing did happen or not point of view. */
|
||||||
|
if (need_clear_) {
|
||||||
|
tiles_->finished_tiles.gl_resources_destroy_and_clear();
|
||||||
|
need_clear_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tiles_->gl_resources_ensure()) {
|
||||||
|
tiles_->gl_resources_destroy();
|
||||||
|
gl_context_disable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tiles_->current_tile.gl_resources_ensure()) {
|
||||||
|
tiles_->current_tile.gl_resources_destroy();
|
||||||
gl_context_disable();
|
gl_context_disable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update texture dimensions if needed. */
|
/* Update texture dimensions if needed. */
|
||||||
if (texture_.width != texture_width || texture_.height != texture_height) {
|
if (current_tile.texture.width != texture_width ||
|
||||||
|
current_tile.texture.height != texture_height) {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
glBindTexture(GL_TEXTURE_2D, current_tile.texture.gl_id);
|
||||||
glTexImage2D(
|
glTexImage2D(
|
||||||
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
GL_TEXTURE_2D, 0, GL_RGBA16F, texture_width, texture_height, 0, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
texture_.width = texture_width;
|
current_tile.texture.width = texture_width;
|
||||||
texture_.height = texture_height;
|
current_tile.texture.height = texture_height;
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
/* Texture did change, and no pixel storage was provided. Tag for an explicit zeroing out to
|
|
||||||
* avoid undefined content. */
|
|
||||||
texture_.need_clear = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update PBO dimensions if needed.
|
/* Update PBO dimensions if needed.
|
||||||
@@ -341,29 +666,58 @@ bool BlenderDisplayDriver::update_begin(const Params ¶ms,
|
|||||||
* sending too much data to GPU when resolution divider is not 1. */
|
* sending too much data to GPU when resolution divider is not 1. */
|
||||||
/* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
|
/* TODO(sergey): Investigate whether keeping the PBO exact size of the texture makes non-interop
|
||||||
* mode faster. */
|
* mode faster. */
|
||||||
const int buffer_width = params.full_size.x;
|
const int buffer_width = params.size.x;
|
||||||
const int buffer_height = params.full_size.y;
|
const int buffer_height = params.size.y;
|
||||||
if (texture_.buffer_width != buffer_width || texture_.buffer_height != buffer_height) {
|
if (current_tile_buffer_object.width != buffer_width ||
|
||||||
|
current_tile_buffer_object.height != buffer_height) {
|
||||||
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
|
const size_t size_in_bytes = sizeof(half4) * buffer_width * buffer_height;
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, current_tile_buffer_object.gl_id);
|
||||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, size_in_bytes, 0, GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
texture_.buffer_width = buffer_width;
|
current_tile_buffer_object.width = buffer_width;
|
||||||
texture_.buffer_height = buffer_height;
|
current_tile_buffer_object.height = buffer_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New content will be provided to the texture in one way or another, so mark this in a
|
/* Store an updated parameters of the current tile.
|
||||||
* centralized place. */
|
* In theory it is only needed once per update of the tile, but doing it on every update is
|
||||||
texture_.need_update = true;
|
* the easiest and is not expensive. */
|
||||||
|
tiles_->current_tile.tile.params = params;
|
||||||
texture_.params = params;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_tile_texture_pixels(const DrawTileAndPBO &tile)
|
||||||
|
{
|
||||||
|
const GLTexture &texture = tile.tile.texture;
|
||||||
|
|
||||||
|
DCHECK_NE(tile.buffer_object.gl_id, 0);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tile.buffer_object.gl_id);
|
||||||
|
|
||||||
|
glTexSubImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, 0, 0, texture.width, texture.height, GL_RGBA, GL_HALF_FLOAT, 0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void BlenderDisplayDriver::update_end()
|
void BlenderDisplayDriver::update_end()
|
||||||
{
|
{
|
||||||
|
/* Unpack the PBO into the texture as soon as the new content is provided.
|
||||||
|
*
|
||||||
|
* This allows to ensure that the unpacking happens while resources like graphics interop (which
|
||||||
|
* lifetime is outside of control of the display driver) are still valid, as well as allows to
|
||||||
|
* move the tile from being current to finished immediately after this call.
|
||||||
|
*
|
||||||
|
* One concern with this approach is that if the update happens more often than drawing then
|
||||||
|
* doing the unpack here occupies GPU transfer for no good reason. However, the render scheduler
|
||||||
|
* takes care of ensuring updates don't happen that often. In regular applications redraw will
|
||||||
|
* happen much more often than this update. */
|
||||||
|
update_tile_texture_pixels(tiles_->current_tile);
|
||||||
|
|
||||||
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
@@ -376,7 +730,11 @@ void BlenderDisplayDriver::update_end()
|
|||||||
|
|
||||||
half4 *BlenderDisplayDriver::map_texture_buffer()
|
half4 *BlenderDisplayDriver::map_texture_buffer()
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
const uint pbo_gl_id = tiles_->current_tile.buffer_object.gl_id;
|
||||||
|
|
||||||
|
DCHECK_NE(pbo_gl_id, 0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_gl_id);
|
||||||
|
|
||||||
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
|
half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>(
|
||||||
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
|
||||||
@@ -384,15 +742,6 @@ half4 *BlenderDisplayDriver::map_texture_buffer()
|
|||||||
LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
|
LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture_.need_clear) {
|
|
||||||
const int64_t texture_width = texture_.width;
|
|
||||||
const int64_t texture_height = texture_.height;
|
|
||||||
memset(reinterpret_cast<void *>(mapped_rgba_pixels),
|
|
||||||
0,
|
|
||||||
texture_width * texture_height * sizeof(half4));
|
|
||||||
texture_.need_clear = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapped_rgba_pixels;
|
return mapped_rgba_pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,12 +760,9 @@ BlenderDisplayDriver::GraphicsInterop BlenderDisplayDriver::graphics_interop_get
|
|||||||
{
|
{
|
||||||
GraphicsInterop interop_dst;
|
GraphicsInterop interop_dst;
|
||||||
|
|
||||||
interop_dst.buffer_width = texture_.buffer_width;
|
interop_dst.buffer_width = tiles_->current_tile.buffer_object.width;
|
||||||
interop_dst.buffer_height = texture_.buffer_height;
|
interop_dst.buffer_height = tiles_->current_tile.buffer_object.height;
|
||||||
interop_dst.opengl_pbo_id = texture_.gl_pbo_id;
|
interop_dst.opengl_pbo_id = tiles_->current_tile.buffer_object.gl_id;
|
||||||
|
|
||||||
interop_dst.need_clear = texture_.need_clear;
|
|
||||||
texture_.need_clear = false;
|
|
||||||
|
|
||||||
return interop_dst;
|
return interop_dst;
|
||||||
}
|
}
|
||||||
@@ -437,7 +783,7 @@ void BlenderDisplayDriver::graphics_interop_deactivate()
|
|||||||
|
|
||||||
void BlenderDisplayDriver::clear()
|
void BlenderDisplayDriver::clear()
|
||||||
{
|
{
|
||||||
texture_.need_clear = true;
|
need_clear_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
||||||
@@ -445,26 +791,156 @@ void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y)
|
|||||||
zoom_ = make_float2(zoom_x, zoom_y);
|
zoom_ = make_float2(zoom_x, zoom_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
|
||||||
|
* This buffer is used to render texture in the viewport.
|
||||||
|
*
|
||||||
|
* NOTE: The buffer needs to be bound. */
|
||||||
|
static void vertex_buffer_update(const DisplayDriver::Params ¶ms)
|
||||||
|
{
|
||||||
|
const int x = params.full_offset.x;
|
||||||
|
const int y = params.full_offset.y;
|
||||||
|
|
||||||
|
const int width = params.size.x;
|
||||||
|
const int height = params.size.y;
|
||||||
|
|
||||||
|
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
|
||||||
|
* rendered. */
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
||||||
|
if (!vpointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vpointer[0] = 0.0f;
|
||||||
|
vpointer[1] = 0.0f;
|
||||||
|
vpointer[2] = x;
|
||||||
|
vpointer[3] = y;
|
||||||
|
|
||||||
|
vpointer[4] = 1.0f;
|
||||||
|
vpointer[5] = 0.0f;
|
||||||
|
vpointer[6] = x + width;
|
||||||
|
vpointer[7] = y;
|
||||||
|
|
||||||
|
vpointer[8] = 1.0f;
|
||||||
|
vpointer[9] = 1.0f;
|
||||||
|
vpointer[10] = x + width;
|
||||||
|
vpointer[11] = y + height;
|
||||||
|
|
||||||
|
vpointer[12] = 0.0f;
|
||||||
|
vpointer[13] = 1.0f;
|
||||||
|
vpointer[14] = x;
|
||||||
|
vpointer[15] = y + height;
|
||||||
|
|
||||||
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_tile(const float2 &zoom,
|
||||||
|
const int texcoord_attribute,
|
||||||
|
const int position_attribute,
|
||||||
|
const DrawTile &draw_tile,
|
||||||
|
const uint gl_vertex_buffer)
|
||||||
|
{
|
||||||
|
if (!draw_tile.ready_to_draw()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLTexture &texture = draw_tile.texture;
|
||||||
|
|
||||||
|
DCHECK_NE(texture.gl_id, 0);
|
||||||
|
DCHECK_NE(gl_vertex_buffer, 0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer);
|
||||||
|
|
||||||
|
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
|
||||||
|
* texture during bordered-rendered camera view without flickering. The validness of the display
|
||||||
|
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
|
||||||
|
* have an early output.
|
||||||
|
*
|
||||||
|
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
|
||||||
|
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
|
||||||
|
* the texture draw parameters and the latest updated draw parameters (although, complexity of
|
||||||
|
* doing it might not worth it. */
|
||||||
|
vertex_buffer_update(draw_tile.params);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture.gl_id);
|
||||||
|
|
||||||
|
/* Trick to keep sharp rendering without jagged edges on all GPUs.
|
||||||
|
*
|
||||||
|
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
|
||||||
|
* in.
|
||||||
|
* For the render result with a resolution divider in effect we always use nearest interpolation.
|
||||||
|
*
|
||||||
|
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
|
||||||
|
* the zoom level 1. The MAG filter is always NEAREST. */
|
||||||
|
const float zoomed_width = draw_tile.params.size.x * zoom.x;
|
||||||
|
const float zoomed_height = draw_tile.params.size.y * zoom.y;
|
||||||
|
if (texture.width != draw_tile.params.size.x || texture.height != draw_tile.params.size.y) {
|
||||||
|
/* Resolution divider is different from 1, force nearest interpolation. */
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else if (zoomed_width - draw_tile.params.size.x > 0.5f ||
|
||||||
|
zoomed_height - draw_tile.params.size.y > 0.5f) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
glVertexAttribPointer(
|
||||||
|
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
|
||||||
|
glVertexAttribPointer(position_attribute,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
4 * sizeof(float),
|
||||||
|
(const GLvoid *)(sizeof(float) * 2));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlenderDisplayDriver::flush()
|
||||||
|
{
|
||||||
|
/* This is called from the render thread that also calls update_begin/end, right before ending
|
||||||
|
* the render loop. We wait for any queued PBO and render commands to be done, before destroying
|
||||||
|
* the render thread and activating the context in the main thread to destroy resources.
|
||||||
|
*
|
||||||
|
* If we don't do this, the NVIDIA driver hangs for a few seconds for when ending 3D viewport
|
||||||
|
* rendering, for unknown reasons. This was found with NVIDIA driver version 470.73 and a Quadro
|
||||||
|
* RTX 6000 on Linux. */
|
||||||
|
if (!gl_context_enable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_upload_sync_) {
|
||||||
|
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gl_render_sync_) {
|
||||||
|
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_context_disable();
|
||||||
|
}
|
||||||
|
|
||||||
void BlenderDisplayDriver::draw(const Params ¶ms)
|
void BlenderDisplayDriver::draw(const Params ¶ms)
|
||||||
{
|
{
|
||||||
/* See do_update_begin() for why no locking is required here. */
|
/* See do_update_begin() for why no locking is required here. */
|
||||||
const bool transparent = true; // TODO(sergey): Derive this from Film.
|
const bool transparent = true; // TODO(sergey): Derive this from Film.
|
||||||
|
|
||||||
if (!gl_draw_resources_ensure()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_gl_context_) {
|
if (use_gl_context_) {
|
||||||
gl_context_mutex_.lock();
|
gl_context_mutex_.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture_.need_clear) {
|
if (need_clear_) {
|
||||||
/* Texture is requested to be cleared and was not yet cleared.
|
/* Texture is requested to be cleared and was not yet cleared.
|
||||||
*
|
*
|
||||||
* Do early return which should be equivalent of drawing all-zero texture.
|
* Do early return which should be equivalent of drawing all-zero texture.
|
||||||
* Watch out for the lock though so that the clear happening during update is properly
|
* Watch out for the lock though so that the clear happening during update is properly
|
||||||
* synchronized here. */
|
* synchronized here. */
|
||||||
gl_context_mutex_.unlock();
|
if (use_gl_context_) {
|
||||||
|
gl_context_mutex_.unlock();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,66 +953,41 @@ void BlenderDisplayDriver::draw(const Params ¶ms)
|
|||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
display_shader_->bind(params.full_size.x, params.full_size.y);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
|
||||||
|
|
||||||
/* Trick to keep sharp rendering without jagged edges on all GPUs.
|
/* NOTE: The VAO is to be allocated on the drawing context as it is not shared across contexts.
|
||||||
*
|
* Simplest is to allocate it on every redraw so that it is possible to destroy it from a
|
||||||
* The idea here is to enforce driver to use linear interpolation when the image is not zoomed
|
* correct context. */
|
||||||
* in.
|
|
||||||
* For the render result with a resolution divider in effect we always use nearest interpolation.
|
|
||||||
*
|
|
||||||
* Use explicit MIN assignment to make sure the driver does not have an undefined behavior at
|
|
||||||
* the zoom level 1. The MAG filter is always NEAREST. */
|
|
||||||
const float zoomed_width = params.size.x * zoom_.x;
|
|
||||||
const float zoomed_height = params.size.y * zoom_.y;
|
|
||||||
if (texture_.width != params.size.x || texture_.height != params.size.y) {
|
|
||||||
/* Resolution divider is different from 1, force nearest interpolation. */
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
else if (zoomed_width - params.size.x > 0.5f || zoomed_height - params.size.y > 0.5f) {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
|
|
||||||
|
|
||||||
texture_update_if_needed();
|
|
||||||
vertex_buffer_update(params);
|
|
||||||
|
|
||||||
/* TODO(sergey): Does it make sense/possible to cache/reuse the VAO? */
|
|
||||||
GLuint vertex_array_object;
|
GLuint vertex_array_object;
|
||||||
glGenVertexArrays(1, &vertex_array_object);
|
glGenVertexArrays(1, &vertex_array_object);
|
||||||
glBindVertexArray(vertex_array_object);
|
glBindVertexArray(vertex_array_object);
|
||||||
|
|
||||||
|
display_shader_->bind(params.full_size.x, params.full_size.y);
|
||||||
|
|
||||||
const int texcoord_attribute = display_shader_->get_tex_coord_attrib_location();
|
const int texcoord_attribute = display_shader_->get_tex_coord_attrib_location();
|
||||||
const int position_attribute = display_shader_->get_position_attrib_location();
|
const int position_attribute = display_shader_->get_position_attrib_location();
|
||||||
|
|
||||||
glEnableVertexAttribArray(texcoord_attribute);
|
glEnableVertexAttribArray(texcoord_attribute);
|
||||||
glEnableVertexAttribArray(position_attribute);
|
glEnableVertexAttribArray(position_attribute);
|
||||||
|
|
||||||
glVertexAttribPointer(
|
draw_tile(zoom_,
|
||||||
texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
|
texcoord_attribute,
|
||||||
glVertexAttribPointer(position_attribute,
|
position_attribute,
|
||||||
2,
|
tiles_->current_tile.tile,
|
||||||
GL_FLOAT,
|
tiles_->gl_vertex_buffer);
|
||||||
GL_FALSE,
|
|
||||||
4 * sizeof(float),
|
|
||||||
(const GLvoid *)(sizeof(float) * 2));
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
for (const DrawTile &tile : tiles_->finished_tiles.tiles) {
|
||||||
|
draw_tile(zoom_, texcoord_attribute, position_attribute, tile, tiles_->gl_vertex_buffer);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
glDeleteVertexArrays(1, &vertex_array_object);
|
|
||||||
|
|
||||||
display_shader_->unbind();
|
display_shader_->unbind();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glDeleteVertexArrays(1, &vertex_array_object);
|
||||||
|
|
||||||
if (transparent) {
|
if (transparent) {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
@@ -544,6 +995,11 @@ void BlenderDisplayDriver::draw(const Params ¶ms)
|
|||||||
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
|
if (VLOG_IS_ON(5)) {
|
||||||
|
VLOG(5) << "Number of textures: " << GLTexture::num_used;
|
||||||
|
VLOG(5) << "Number of PBOs: " << GLPixelBufferObject::num_used;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_gl_context_) {
|
if (use_gl_context_) {
|
||||||
gl_context_mutex_.unlock();
|
gl_context_mutex_.unlock();
|
||||||
}
|
}
|
||||||
@@ -618,154 +1074,17 @@ void BlenderDisplayDriver::gl_context_dispose()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlenderDisplayDriver::gl_draw_resources_ensure()
|
|
||||||
{
|
|
||||||
if (!texture_.gl_id) {
|
|
||||||
/* If there is no texture allocated, there is nothing to draw. Inform the draw call that it can
|
|
||||||
* can not continue. Note that this is not an unrecoverable error, so once the texture is known
|
|
||||||
* we will come back here and create all the GPU resources needed for draw. */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gl_draw_resource_creation_attempted_) {
|
|
||||||
return gl_draw_resources_created_;
|
|
||||||
}
|
|
||||||
gl_draw_resource_creation_attempted_ = true;
|
|
||||||
|
|
||||||
if (!vertex_buffer_) {
|
|
||||||
glGenBuffers(1, &vertex_buffer_);
|
|
||||||
if (!vertex_buffer_) {
|
|
||||||
LOG(ERROR) << "Error creating vertex buffer.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_draw_resources_created_ = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::gl_resources_destroy()
|
void BlenderDisplayDriver::gl_resources_destroy()
|
||||||
{
|
{
|
||||||
gl_context_enable();
|
gl_context_enable();
|
||||||
|
|
||||||
if (vertex_buffer_ != 0) {
|
tiles_->current_tile.gl_resources_destroy();
|
||||||
glDeleteBuffers(1, &vertex_buffer_);
|
tiles_->finished_tiles.gl_resources_destroy_and_clear();
|
||||||
}
|
tiles_->gl_resources_destroy();
|
||||||
|
|
||||||
if (texture_.gl_pbo_id) {
|
|
||||||
glDeleteBuffers(1, &texture_.gl_pbo_id);
|
|
||||||
texture_.gl_pbo_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture_.gl_id) {
|
|
||||||
glDeleteTextures(1, &texture_.gl_id);
|
|
||||||
texture_.gl_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_context_disable();
|
gl_context_disable();
|
||||||
|
|
||||||
gl_context_dispose();
|
gl_context_dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlenderDisplayDriver::gl_texture_resources_ensure()
|
|
||||||
{
|
|
||||||
if (texture_.creation_attempted) {
|
|
||||||
return texture_.is_created;
|
|
||||||
}
|
|
||||||
texture_.creation_attempted = true;
|
|
||||||
|
|
||||||
DCHECK(!texture_.gl_id);
|
|
||||||
DCHECK(!texture_.gl_pbo_id);
|
|
||||||
|
|
||||||
/* Create texture. */
|
|
||||||
glGenTextures(1, &texture_.gl_id);
|
|
||||||
if (!texture_.gl_id) {
|
|
||||||
LOG(ERROR) << "Error creating texture.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure the texture. */
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture_.gl_id);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
/* Create PBO for the texture. */
|
|
||||||
glGenBuffers(1, &texture_.gl_pbo_id);
|
|
||||||
if (!texture_.gl_pbo_id) {
|
|
||||||
LOG(ERROR) << "Error creating texture pixel buffer object.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Creation finished with a success. */
|
|
||||||
texture_.is_created = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::texture_update_if_needed()
|
|
||||||
{
|
|
||||||
if (!texture_.need_update) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id);
|
|
||||||
glTexSubImage2D(
|
|
||||||
GL_TEXTURE_2D, 0, 0, 0, texture_.width, texture_.height, GL_RGBA, GL_HALF_FLOAT, 0);
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
|
|
||||||
texture_.need_update = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderDisplayDriver::vertex_buffer_update(const Params & /*params*/)
|
|
||||||
{
|
|
||||||
/* Draw at the parameters for which the texture has been updated for. This allows to always draw
|
|
||||||
* texture during bordered-rendered camera view without flickering. The validness of the display
|
|
||||||
* parameters for a texture is guaranteed by the initial "clear" state which makes drawing to
|
|
||||||
* have an early output.
|
|
||||||
*
|
|
||||||
* Such approach can cause some extra "jelly" effect during panning, but it is not more jelly
|
|
||||||
* than overlay of selected objects. Also, it's possible to redraw texture at an intersection of
|
|
||||||
* the texture draw parameters and the latest updated draw parameters (although, complexity of
|
|
||||||
* doing it might not worth it. */
|
|
||||||
const int x = texture_.params.full_offset.x;
|
|
||||||
const int y = texture_.params.full_offset.y;
|
|
||||||
|
|
||||||
const int width = texture_.params.size.x;
|
|
||||||
const int height = texture_.params.size.y;
|
|
||||||
|
|
||||||
/* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be
|
|
||||||
* rendered. */
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
float *vpointer = reinterpret_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
|
|
||||||
if (!vpointer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpointer[0] = 0.0f;
|
|
||||||
vpointer[1] = 0.0f;
|
|
||||||
vpointer[2] = x;
|
|
||||||
vpointer[3] = y;
|
|
||||||
|
|
||||||
vpointer[4] = 1.0f;
|
|
||||||
vpointer[5] = 0.0f;
|
|
||||||
vpointer[6] = x + width;
|
|
||||||
vpointer[7] = y;
|
|
||||||
|
|
||||||
vpointer[8] = 1.0f;
|
|
||||||
vpointer[9] = 1.0f;
|
|
||||||
vpointer[10] = x + width;
|
|
||||||
vpointer[11] = y + height;
|
|
||||||
|
|
||||||
vpointer[12] = 0.0f;
|
|
||||||
vpointer[13] = 1.0f;
|
|
||||||
vpointer[14] = x;
|
|
||||||
vpointer[15] = y + height;
|
|
||||||
|
|
||||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/unique_ptr.h"
|
#include "util/unique_ptr.h"
|
||||||
|
#include "util/vector.h"
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@@ -112,6 +113,8 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
void set_zoom(float zoom_x, float zoom_y);
|
void set_zoom(float zoom_x, float zoom_y);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void next_tile_begin() override;
|
||||||
|
|
||||||
virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||||
virtual void update_end() override;
|
virtual void update_end() override;
|
||||||
|
|
||||||
@@ -122,33 +125,17 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
|
|
||||||
virtual void draw(const Params ¶ms) override;
|
virtual void draw(const Params ¶ms) override;
|
||||||
|
|
||||||
|
virtual void flush() override;
|
||||||
|
|
||||||
/* Helper function which allocates new GPU context. */
|
/* Helper function which allocates new GPU context. */
|
||||||
void gl_context_create();
|
void gl_context_create();
|
||||||
bool gl_context_enable();
|
bool gl_context_enable();
|
||||||
void gl_context_disable();
|
void gl_context_disable();
|
||||||
void gl_context_dispose();
|
void gl_context_dispose();
|
||||||
|
|
||||||
/* Make sure texture is allocated and its initial configuration is performed. */
|
|
||||||
bool gl_texture_resources_ensure();
|
|
||||||
|
|
||||||
/* Ensure all runtime GPU resources needed for drawing are allocated.
|
|
||||||
* Returns true if all resources needed for drawing are available. */
|
|
||||||
bool gl_draw_resources_ensure();
|
|
||||||
|
|
||||||
/* Destroy all GPU resources which are being used by this object. */
|
/* Destroy all GPU resources which are being used by this object. */
|
||||||
void gl_resources_destroy();
|
void gl_resources_destroy();
|
||||||
|
|
||||||
/* Update GPU texture dimensions and content if needed (new pixel data was provided).
|
|
||||||
*
|
|
||||||
* NOTE: The texture needs to be bound. */
|
|
||||||
void texture_update_if_needed();
|
|
||||||
|
|
||||||
/* Update vertex buffer with new coordinates of vertex positions and texture coordinates.
|
|
||||||
* This buffer is used to render texture in the viewport.
|
|
||||||
*
|
|
||||||
* NOTE: The buffer needs to be bound. */
|
|
||||||
void vertex_buffer_update(const Params ¶ms);
|
|
||||||
|
|
||||||
BL::RenderEngine b_engine_;
|
BL::RenderEngine b_engine_;
|
||||||
|
|
||||||
/* OpenGL context which is used the render engine doesn't have its own. */
|
/* OpenGL context which is used the render engine doesn't have its own. */
|
||||||
@@ -159,50 +146,14 @@ class BlenderDisplayDriver : public DisplayDriver {
|
|||||||
/* Mutex used to guard the `gl_context_`. */
|
/* Mutex used to guard the `gl_context_`. */
|
||||||
thread_mutex gl_context_mutex_;
|
thread_mutex gl_context_mutex_;
|
||||||
|
|
||||||
/* Texture which contains pixels of the render result. */
|
/* Content of the display is to be filled with zeroes. */
|
||||||
struct {
|
std::atomic<bool> need_clear_ = true;
|
||||||
/* Indicates whether texture creation was attempted and succeeded.
|
|
||||||
* Used to avoid multiple attempts of texture creation on GPU issues or GPU context
|
|
||||||
* misconfiguration. */
|
|
||||||
bool creation_attempted = false;
|
|
||||||
bool is_created = false;
|
|
||||||
|
|
||||||
/* OpenGL resource IDs of the texture itself and Pixel Buffer Object (PBO) used to write
|
|
||||||
* pixels to it.
|
|
||||||
*
|
|
||||||
* NOTE: Allocated on the engine's context. */
|
|
||||||
uint gl_id = 0;
|
|
||||||
uint gl_pbo_id = 0;
|
|
||||||
|
|
||||||
/* Is true when new data was written to the PBO, meaning, the texture might need to be resized
|
|
||||||
* and new data is to be uploaded to the GPU. */
|
|
||||||
bool need_update = false;
|
|
||||||
|
|
||||||
/* Content of the texture is to be filled with zeroes. */
|
|
||||||
std::atomic<bool> need_clear = true;
|
|
||||||
|
|
||||||
/* Dimensions of the texture in pixels. */
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
|
|
||||||
/* Dimensions of the underlying PBO. */
|
|
||||||
int buffer_width = 0;
|
|
||||||
int buffer_height = 0;
|
|
||||||
|
|
||||||
/* Display parameters the texture has been updated for. */
|
|
||||||
Params params;
|
|
||||||
} texture_;
|
|
||||||
|
|
||||||
unique_ptr<BlenderDisplayShader> display_shader_;
|
unique_ptr<BlenderDisplayShader> display_shader_;
|
||||||
|
|
||||||
/* Special track of whether GPU resources were attempted to be created, to avoid attempts of
|
/* Opaque storage for an internal state and data for tiles. */
|
||||||
* their re-creation on failure on every redraw. */
|
struct Tiles;
|
||||||
bool gl_draw_resource_creation_attempted_ = false;
|
unique_ptr<Tiles> tiles_;
|
||||||
bool gl_draw_resources_created_ = false;
|
|
||||||
|
|
||||||
/* Vertex buffer which hold vertices of a triangle fan which is textures with the texture
|
|
||||||
* holding the render result. */
|
|
||||||
uint vertex_buffer_ = 0;
|
|
||||||
|
|
||||||
void *gl_render_sync_ = nullptr;
|
void *gl_render_sync_ = nullptr;
|
||||||
void *gl_upload_sync_ = nullptr;
|
void *gl_upload_sync_ = nullptr;
|
||||||
|
@@ -1071,7 +1071,15 @@ static void create_subd_mesh(Scene *scene,
|
|||||||
|
|
||||||
for (BL::MeshEdge &e : b_mesh.edges) {
|
for (BL::MeshEdge &e : b_mesh.edges) {
|
||||||
if (e.crease() != 0.0f) {
|
if (e.crease() != 0.0f) {
|
||||||
mesh->add_crease(e.vertices()[0], e.vertices()[1], e.crease());
|
mesh->add_edge_crease(e.vertices()[0], e.vertices()[1], e.crease());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
|
||||||
|
for (int i = 0; i < c.data.length(); ++i) {
|
||||||
|
if (c.data[i].value() != 0.0f) {
|
||||||
|
mesh->add_vertex_crease(i, c.data[i].value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,40 +1094,6 @@ static void create_subd_mesh(Scene *scene,
|
|||||||
|
|
||||||
/* Sync */
|
/* Sync */
|
||||||
|
|
||||||
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
|
|
||||||
* things like velocity from cache modifier, fluid simulation).
|
|
||||||
*
|
|
||||||
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
|
|
||||||
* set by `sync_object_motion_init()`. */
|
|
||||||
static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
|
|
||||||
{
|
|
||||||
const Scene::MotionType need_motion = scene->need_motion();
|
|
||||||
if (need_motion == Scene::MOTION_NONE) {
|
|
||||||
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
|
|
||||||
* attributes. */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_motion == Scene::MOTION_BLUR) {
|
|
||||||
/* A bit tricky and implicit case:
|
|
||||||
* - Motion blur is enabled in the scene, which implies specific number of time steps for
|
|
||||||
* objects.
|
|
||||||
* - If the object has motion blur disabled on it, it will have 0 time steps.
|
|
||||||
* - Motion attribute expects non-zero time steps.
|
|
||||||
*
|
|
||||||
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
|
|
||||||
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
|
|
||||||
const bool use_motion = get_boolean(cobject, "use_motion_blur");
|
|
||||||
if (!use_motion) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
|
|
||||||
* level. */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
|
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
|
||||||
{
|
{
|
||||||
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
|
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
|
||||||
@@ -1144,7 +1118,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
|
|||||||
|
|
||||||
if (b_mesh) {
|
if (b_mesh) {
|
||||||
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
||||||
const bool need_motion = mesh_need_motion_attribute(b_ob_info, scene);
|
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
||||||
const float motion_scale = (need_motion) ?
|
const float motion_scale = (need_motion) ?
|
||||||
scene->motion_shutter_time() /
|
scene->motion_shutter_time() /
|
||||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||||
|
@@ -529,6 +529,17 @@ void BlenderSync::sync_procedural(BL::Object &b_ob,
|
|||||||
string absolute_path = blender_absolute_path(b_data, b_ob, b_mesh_cache.cache_file().filepath());
|
string absolute_path = blender_absolute_path(b_data, b_ob, b_mesh_cache.cache_file().filepath());
|
||||||
procedural->set_filepath(ustring(absolute_path));
|
procedural->set_filepath(ustring(absolute_path));
|
||||||
|
|
||||||
|
array<ustring> layers;
|
||||||
|
for (BL::CacheFileLayer &layer : cache_file.layers) {
|
||||||
|
if (layer.hide_layer()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
absolute_path = blender_absolute_path(b_data, b_ob, layer.filepath());
|
||||||
|
layers.push_back_slow(ustring(absolute_path));
|
||||||
|
}
|
||||||
|
procedural->set_layers(layers);
|
||||||
|
|
||||||
procedural->set_scale(cache_file.scale());
|
procedural->set_scale(cache_file.scale());
|
||||||
|
|
||||||
procedural->set_use_prefetch(cache_file.use_prefetch());
|
procedural->set_use_prefetch(cache_file.use_prefetch());
|
||||||
|
@@ -51,8 +51,6 @@ bool BlenderOutputDriver::read_render_tile(const Tile &tile)
|
|||||||
|
|
||||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||||
|
|
||||||
vector<float> pixels(tile.size.x * tile.size.y * 4);
|
|
||||||
|
|
||||||
/* Copy each pass.
|
/* Copy each pass.
|
||||||
* TODO:copy only the required ones for better performance? */
|
* TODO:copy only the required ones for better performance? */
|
||||||
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
||||||
@@ -109,7 +107,7 @@ void BlenderOutputDriver::write_render_tile(const Tile &tile)
|
|||||||
|
|
||||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||||
|
|
||||||
vector<float> pixels(tile.size.x * tile.size.y * 4);
|
vector<float> pixels(static_cast<size_t>(tile.size.x) * tile.size.y * 4);
|
||||||
|
|
||||||
/* Copy each pass. */
|
/* Copy each pass. */
|
||||||
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
||||||
@@ -120,7 +118,7 @@ void BlenderOutputDriver::write_render_tile(const Tile &tile)
|
|||||||
b_pass.rect(&pixels[0]);
|
b_pass.rect(&pixels[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
b_engine_.end_result(b_rr, true, false, true);
|
b_engine_.end_result(b_rr, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -37,12 +37,52 @@ static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud)
|
static void attr_create_motion(PointCloud *pointcloud,
|
||||||
|
BL::Attribute &b_attribute,
|
||||||
|
const float motion_scale)
|
||||||
|
{
|
||||||
|
if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
|
||||||
|
(b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
|
||||||
|
const int num_points = pointcloud->get_points().size();
|
||||||
|
|
||||||
|
/* Find or add attribute */
|
||||||
|
float3 *P = &pointcloud->get_points()[0];
|
||||||
|
Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||||
|
|
||||||
|
if (!attr_mP) {
|
||||||
|
attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only export previous and next frame, we don't have any in between data. */
|
||||||
|
float motion_times[2] = {-1.0f, 1.0f};
|
||||||
|
for (int step = 0; step < 2; step++) {
|
||||||
|
const float relative_time = motion_times[step] * 0.5f * motion_scale;
|
||||||
|
float3 *mP = attr_mP->data_float3() + step * num_points;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_points; i++) {
|
||||||
|
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_attributes(PointCloud *pointcloud,
|
||||||
|
BL::PointCloud b_pointcloud,
|
||||||
|
const bool need_motion,
|
||||||
|
const float motion_scale)
|
||||||
{
|
{
|
||||||
AttributeSet &attributes = pointcloud->attributes;
|
AttributeSet &attributes = pointcloud->attributes;
|
||||||
|
static const ustring u_velocity("velocity");
|
||||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||||
const ustring name{b_attribute.name().c_str()};
|
const ustring name{b_attribute.name().c_str()};
|
||||||
|
|
||||||
|
if (need_motion && name == u_velocity) {
|
||||||
|
attr_create_motion(pointcloud, b_attribute, motion_scale);
|
||||||
|
}
|
||||||
|
|
||||||
if (attributes.find(name)) {
|
if (attributes.find(name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -111,7 +151,11 @@ static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud)
|
static void export_pointcloud(Scene *scene,
|
||||||
|
PointCloud *pointcloud,
|
||||||
|
BL::PointCloud b_pointcloud,
|
||||||
|
const bool need_motion,
|
||||||
|
const float motion_scale)
|
||||||
{
|
{
|
||||||
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
||||||
|
|
||||||
@@ -141,7 +185,7 @@ static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointClo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Export attributes */
|
/* Export attributes */
|
||||||
copy_attributes(pointcloud, b_pointcloud);
|
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void export_pointcloud_motion(PointCloud *pointcloud,
|
static void export_pointcloud_motion(PointCloud *pointcloud,
|
||||||
@@ -193,7 +237,7 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Export attributes */
|
/* Export attributes */
|
||||||
copy_attributes(pointcloud, b_pointcloud);
|
copy_attributes(pointcloud, b_pointcloud, false, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info)
|
void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info)
|
||||||
@@ -207,7 +251,13 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
|
|||||||
|
|
||||||
/* TODO: add option to filter out points in the view layer. */
|
/* TODO: add option to filter out points in the view layer. */
|
||||||
BL::PointCloud b_pointcloud(b_ob_info.object_data);
|
BL::PointCloud b_pointcloud(b_ob_info.object_data);
|
||||||
export_pointcloud(scene, &new_pointcloud, b_pointcloud);
|
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
||||||
|
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
||||||
|
const float motion_scale = (need_motion) ?
|
||||||
|
scene->motion_shutter_time() /
|
||||||
|
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||||
|
0.0f;
|
||||||
|
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
|
||||||
|
|
||||||
/* update original sockets */
|
/* update original sockets */
|
||||||
for (const SocketType &socket : new_pointcloud.type->inputs) {
|
for (const SocketType &socket : new_pointcloud.type->inputs) {
|
||||||
|
@@ -138,20 +138,18 @@ static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
|
|||||||
|
|
||||||
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
|
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *path, *user_path, *temp_path;
|
PyObject *path, *user_path;
|
||||||
int headless;
|
int headless;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OOOi", &path, &user_path, &temp_path, &headless)) {
|
if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr, *temp_path_coerce = nullptr;
|
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
|
||||||
path_init(PyC_UnicodeAsByte(path, &path_coerce),
|
path_init(PyC_UnicodeAsByte(path, &path_coerce),
|
||||||
PyC_UnicodeAsByte(user_path, &user_path_coerce),
|
PyC_UnicodeAsByte(user_path, &user_path_coerce));
|
||||||
PyC_UnicodeAsByte(temp_path, &temp_path_coerce));
|
|
||||||
Py_XDECREF(path_coerce);
|
Py_XDECREF(path_coerce);
|
||||||
Py_XDECREF(user_path_coerce);
|
Py_XDECREF(user_path_coerce);
|
||||||
Py_XDECREF(temp_path_coerce);
|
|
||||||
|
|
||||||
BlenderSession::headless = headless;
|
BlenderSession::headless = headless;
|
||||||
|
|
||||||
@@ -735,27 +733,20 @@ static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepat
|
|||||||
|
|
||||||
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
|
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
|
||||||
{
|
{
|
||||||
#if 1
|
|
||||||
(void)args;
|
|
||||||
(void)keywords;
|
|
||||||
#else
|
|
||||||
static const char *keyword_list[] = {
|
static const char *keyword_list[] = {
|
||||||
"preferences", "scene", "view_layer", "input", "output", "tile_size", "samples", NULL};
|
"preferences", "scene", "view_layer", "input", "output", NULL};
|
||||||
PyObject *pypreferences, *pyscene, *pyviewlayer;
|
PyObject *pypreferences, *pyscene, *pyviewlayer;
|
||||||
PyObject *pyinput, *pyoutput = NULL;
|
PyObject *pyinput, *pyoutput = NULL;
|
||||||
int tile_size = 0, samples = 0;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args,
|
if (!PyArg_ParseTupleAndKeywords(args,
|
||||||
keywords,
|
keywords,
|
||||||
"OOOO|Oii",
|
"OOOO|O",
|
||||||
(char **)keyword_list,
|
(char **)keyword_list,
|
||||||
&pypreferences,
|
&pypreferences,
|
||||||
&pyscene,
|
&pyscene,
|
||||||
&pyviewlayer,
|
&pyviewlayer,
|
||||||
&pyinput,
|
&pyinput,
|
||||||
&pyoutput,
|
&pyoutput)) {
|
||||||
&tile_size,
|
|
||||||
&samples)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,14 +768,10 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
|
|||||||
&RNA_ViewLayer,
|
&RNA_ViewLayer,
|
||||||
PyLong_AsVoidPtr(pyviewlayer),
|
PyLong_AsVoidPtr(pyviewlayer),
|
||||||
&viewlayerptr);
|
&viewlayerptr);
|
||||||
PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
|
BL::ViewLayer b_view_layer(viewlayerptr);
|
||||||
|
|
||||||
DenoiseParams params;
|
DenoiseParams params = BlenderSync::get_denoise_params(b_scene, b_view_layer, true);
|
||||||
params.radius = get_int(cviewlayer, "denoising_radius");
|
params.use = true;
|
||||||
params.strength = get_float(cviewlayer, "denoising_strength");
|
|
||||||
params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
|
|
||||||
params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
|
|
||||||
params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
|
|
||||||
|
|
||||||
/* Parse file paths list. */
|
/* Parse file paths list. */
|
||||||
vector<string> input, output;
|
vector<string> input, output;
|
||||||
@@ -812,24 +799,15 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create denoiser. */
|
/* Create denoiser. */
|
||||||
DenoiserPipeline denoiser(device);
|
DenoiserPipeline denoiser(device, params);
|
||||||
denoiser.params = params;
|
|
||||||
denoiser.input = input;
|
denoiser.input = input;
|
||||||
denoiser.output = output;
|
denoiser.output = output;
|
||||||
|
|
||||||
if (tile_size > 0) {
|
|
||||||
denoiser.tile_size = make_int2(tile_size, tile_size);
|
|
||||||
}
|
|
||||||
if (samples > 0) {
|
|
||||||
denoiser.samples_override = samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run denoiser. */
|
/* Run denoiser. */
|
||||||
if (!denoiser.run()) {
|
if (!denoiser.run()) {
|
||||||
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
|
PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
@@ -502,10 +502,20 @@ void BlenderSession::render_frame_finish()
|
|||||||
path_remove(filename);
|
path_remove(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear driver. */
|
/* Clear output driver. */
|
||||||
session->set_output_driver(nullptr);
|
session->set_output_driver(nullptr);
|
||||||
session->full_buffer_written_cb = function_null;
|
session->full_buffer_written_cb = function_null;
|
||||||
|
|
||||||
|
/* The display driver is the source of drawing context for both drawing and possible graphics
|
||||||
|
* interop objects in the path trace. Once the frame is finished the OpenGL context might be
|
||||||
|
* freed form Blender side. Need to ensure that all GPU resources are freed prior to that
|
||||||
|
* point.
|
||||||
|
* Ideally would only do this when OpenGL context is actually destroyed, but there is no way to
|
||||||
|
* know when this happens (at least in the code at the time when this comment was written).
|
||||||
|
* The penalty of re-creating resources on every frame is unlikely to be noticed. */
|
||||||
|
display_driver_ = nullptr;
|
||||||
|
session->set_display_driver(nullptr);
|
||||||
|
|
||||||
/* All the files are handled.
|
/* All the files are handled.
|
||||||
* Clear the list so that this session can be re-used by Persistent Data. */
|
* Clear the list so that this session can be re-used by Persistent Data. */
|
||||||
full_buffer_files_.clear();
|
full_buffer_files_.clear();
|
||||||
|
@@ -45,7 +45,8 @@ typedef map<string, ConvertNode *> ProxyMap;
|
|||||||
|
|
||||||
void BlenderSync::find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader)
|
void BlenderSync::find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader)
|
||||||
{
|
{
|
||||||
Shader *shader = (id) ? shader_map.find(id) : default_shader;
|
Shader *synced_shader = (id) ? shader_map.find(id) : nullptr;
|
||||||
|
Shader *shader = (synced_shader) ? synced_shader : default_shader;
|
||||||
|
|
||||||
used_shaders.push_back_slow(shader);
|
used_shaders.push_back_slow(shader);
|
||||||
shader->tag_used(scene);
|
shader->tag_used(scene);
|
||||||
@@ -689,6 +690,9 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
|
else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
|
||||||
node = graph->create_node<HairInfoNode>();
|
node = graph->create_node<HairInfoNode>();
|
||||||
}
|
}
|
||||||
|
else if (b_node.is_a(&RNA_ShaderNodePointInfo)) {
|
||||||
|
node = graph->create_node<PointInfoNode>();
|
||||||
|
}
|
||||||
else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) {
|
else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) {
|
||||||
node = graph->create_node<VolumeInfoNode>();
|
node = graph->create_node<VolumeInfoNode>();
|
||||||
}
|
}
|
||||||
@@ -776,7 +780,7 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ustring filename = ustring(
|
ustring filename = ustring(
|
||||||
image_user_file_path(b_image_user, b_image, b_scene.frame_current(), true));
|
image_user_file_path(b_image_user, b_image, b_scene.frame_current()));
|
||||||
image->set_filename(filename);
|
image->set_filename(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -813,7 +817,7 @@ static ShaderNode *add_node(Scene *scene,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
env->set_filename(
|
env->set_filename(
|
||||||
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current(), false)));
|
ustring(image_user_file_path(b_image_user, b_image, b_scene.frame_current())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = env;
|
node = env;
|
||||||
@@ -1583,18 +1587,13 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
|
void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all)
|
||||||
{
|
{
|
||||||
/* for auto refresh images */
|
|
||||||
ImageManager *image_manager = scene->image_manager;
|
|
||||||
const int frame = b_scene.frame_current();
|
|
||||||
const bool auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
|
||||||
|
|
||||||
shader_map.pre_sync();
|
shader_map.pre_sync();
|
||||||
|
|
||||||
sync_world(b_depsgraph, b_v3d, auto_refresh_update);
|
sync_world(b_depsgraph, b_v3d, update_all);
|
||||||
sync_lights(b_depsgraph, auto_refresh_update);
|
sync_lights(b_depsgraph, update_all);
|
||||||
sync_materials(b_depsgraph, auto_refresh_update);
|
sync_materials(b_depsgraph, update_all);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -259,7 +259,12 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
|||||||
int height,
|
int height,
|
||||||
void **python_thread_state)
|
void **python_thread_state)
|
||||||
{
|
{
|
||||||
if (!has_updates_) {
|
/* For auto refresh images. */
|
||||||
|
ImageManager *image_manager = scene->image_manager;
|
||||||
|
const int frame = b_scene.frame_current();
|
||||||
|
const bool auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
||||||
|
|
||||||
|
if (!has_updates_ && !auto_refresh_update) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +279,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
|||||||
sync_view_layer(b_view_layer);
|
sync_view_layer(b_view_layer);
|
||||||
sync_integrator(b_view_layer, background);
|
sync_integrator(b_view_layer, background);
|
||||||
sync_film(b_view_layer, b_v3d);
|
sync_film(b_view_layer, b_v3d);
|
||||||
sync_shaders(b_depsgraph, b_v3d);
|
sync_shaders(b_depsgraph, b_v3d, auto_refresh_update);
|
||||||
sync_images();
|
sync_images();
|
||||||
|
|
||||||
geometry_synced.clear(); /* use for objects and motion sync */
|
geometry_synced.clear(); /* use for objects and motion sync */
|
||||||
@@ -787,6 +792,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
|
|||||||
params.bvh_type = BVH_TYPE_DYNAMIC;
|
params.bvh_type = BVH_TYPE_DYNAMIC;
|
||||||
|
|
||||||
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
|
params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
|
||||||
|
params.use_bvh_compact_structure = RNA_boolean_get(&cscene, "debug_use_compact_bvh");
|
||||||
params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
|
params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
|
||||||
params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
|
params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
|
||||||
|
|
||||||
@@ -832,6 +838,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
|||||||
SessionParams params;
|
SessionParams params;
|
||||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||||
|
|
||||||
|
if (background && !b_engine.is_preview()) {
|
||||||
|
/* Viewport and preview renders do not require temp directory and do request session
|
||||||
|
* parameters more often than the background render.
|
||||||
|
* Optimize RNA-C++ usage and memory allocation a bit by saving string access which we know is
|
||||||
|
* not needed for viewport render. */
|
||||||
|
params.temp_dir = b_engine.temporary_directory();
|
||||||
|
}
|
||||||
|
|
||||||
/* feature set */
|
/* feature set */
|
||||||
params.experimental = (get_enum(cscene, "feature_set") != 0);
|
params.experimental = (get_enum(cscene, "feature_set") != 0);
|
||||||
|
|
||||||
|
@@ -105,11 +105,11 @@ class BlenderSync {
|
|||||||
static BufferParams get_buffer_params(
|
static BufferParams get_buffer_params(
|
||||||
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
|
BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height);
|
||||||
|
|
||||||
private:
|
|
||||||
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
|
static DenoiseParams get_denoise_params(BL::Scene &b_scene,
|
||||||
BL::ViewLayer &b_view_layer,
|
BL::ViewLayer &b_view_layer,
|
||||||
bool background);
|
bool background);
|
||||||
|
|
||||||
|
private:
|
||||||
/* sync */
|
/* sync */
|
||||||
void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
|
void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
|
||||||
void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);
|
void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);
|
||||||
@@ -127,7 +127,7 @@ class BlenderSync {
|
|||||||
/* Shader */
|
/* Shader */
|
||||||
array<Node *> find_used_shaders(BL::Object &b_ob);
|
array<Node *> find_used_shaders(BL::Object &b_ob);
|
||||||
void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||||
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
|
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
|
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
|
||||||
|
|
||||||
/* Object */
|
/* Object */
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#define __BLENDER_UTIL_H__
|
#define __BLENDER_UTIL_H__
|
||||||
|
|
||||||
#include "scene/mesh.h"
|
#include "scene/mesh.h"
|
||||||
|
#include "scene/scene.h"
|
||||||
|
|
||||||
#include "util/algorithm.h"
|
#include "util/algorithm.h"
|
||||||
#include "util/array.h"
|
#include "util/array.h"
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
|
void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
|
||||||
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
|
void BKE_image_user_file_path_ex(void *iuser, void *ima, char *path, bool resolve_udim);
|
||||||
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
|
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
|
||||||
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
|
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
|
||||||
}
|
}
|
||||||
@@ -290,25 +291,14 @@ static inline int render_resolution_y(BL::RenderSettings &b_render)
|
|||||||
return b_render.resolution_y() * b_render.resolution_percentage() / 100;
|
return b_render.resolution_y() * b_render.resolution_percentage() / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline string image_user_file_path(BL::ImageUser &iuser,
|
static inline string image_user_file_path(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
||||||
BL::Image &ima,
|
|
||||||
int cfra,
|
|
||||||
bool load_tiled)
|
|
||||||
{
|
{
|
||||||
char filepath[1024];
|
char filepath[1024];
|
||||||
iuser.tile(0);
|
iuser.tile(0);
|
||||||
BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
|
BKE_image_user_frame_calc(ima.ptr.data, iuser.ptr.data, cfra);
|
||||||
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
|
BKE_image_user_file_path_ex(iuser.ptr.data, ima.ptr.data, filepath, false);
|
||||||
|
|
||||||
string filepath_str = string(filepath);
|
return string(filepath);
|
||||||
if (load_tiled && ima.source() == BL::Image::source_TILED) {
|
|
||||||
string udim;
|
|
||||||
if (!ima.tiles.empty()) {
|
|
||||||
udim = to_string(ima.tiles[0].number());
|
|
||||||
}
|
|
||||||
string_replace(filepath_str, udim, "<UDIM>");
|
|
||||||
}
|
|
||||||
return filepath_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
static inline int image_user_frame_number(BL::ImageUser &iuser, BL::Image &ima, int cfra)
|
||||||
@@ -681,6 +671,40 @@ static inline uint object_ray_visibility(BL::Object &b_ob)
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes
|
||||||
|
* things like velocity from cache modifier, fluid simulation).
|
||||||
|
*
|
||||||
|
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
|
||||||
|
* set by `sync_object_motion_init()`. */
|
||||||
|
static inline bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
|
||||||
|
{
|
||||||
|
const Scene::MotionType need_motion = scene->need_motion();
|
||||||
|
if (need_motion == Scene::MOTION_NONE) {
|
||||||
|
/* Simple case: neither motion pass nor motion blur is needed, no need in the motion related
|
||||||
|
* attributes. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_motion == Scene::MOTION_BLUR) {
|
||||||
|
/* A bit tricky and implicit case:
|
||||||
|
* - Motion blur is enabled in the scene, which implies specific number of time steps for
|
||||||
|
* objects.
|
||||||
|
* - If the object has motion blur disabled on it, it will have 0 time steps.
|
||||||
|
* - Motion attribute expects non-zero time steps.
|
||||||
|
*
|
||||||
|
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
|
||||||
|
PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
|
||||||
|
const bool use_motion = get_boolean(cobject, "use_motion_blur");
|
||||||
|
if (!use_motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object
|
||||||
|
* level. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class EdgeMap {
|
class EdgeMap {
|
||||||
public:
|
public:
|
||||||
EdgeMap()
|
EdgeMap()
|
||||||
|
@@ -935,7 +935,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
|
|||||||
|
|
||||||
BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHReference> &references)
|
BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHReference> &references)
|
||||||
{
|
{
|
||||||
/* This is a bit overallocating here (considering leaf size into account),
|
/* This is a bit over-allocating here (considering leaf size into account),
|
||||||
* but chunk-based re-allocation in vector makes it difficult to use small
|
* but chunk-based re-allocation in vector makes it difficult to use small
|
||||||
* size of stack storage here. Some tweaks are possible tho.
|
* size of stack storage here. Some tweaks are possible tho.
|
||||||
*
|
*
|
||||||
|
@@ -61,6 +61,26 @@ static_assert(Object::MAX_MOTION_STEPS == Geometry::MAX_MOTION_STEPS,
|
|||||||
|
|
||||||
# define IS_HAIR(x) (x & 1)
|
# define IS_HAIR(x) (x & 1)
|
||||||
|
|
||||||
|
/* This gets called by Embree at every valid ray/object intersection.
|
||||||
|
* Things like recording subsurface or shadow hits for later evaluation
|
||||||
|
* as well as filtering for volume objects happen here.
|
||||||
|
* Cycles' own BVH does that directly inside the traversal calls.
|
||||||
|
*/
|
||||||
|
static void rtc_filter_intersection_func(const RTCFilterFunctionNArguments *args)
|
||||||
|
{
|
||||||
|
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||||
|
assert(args->N == 1);
|
||||||
|
|
||||||
|
RTCHit *hit = (RTCHit *)args->hit;
|
||||||
|
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||||
|
const KernelGlobalsCPU *kg = ctx->kg;
|
||||||
|
const Ray *cray = ctx->ray;
|
||||||
|
|
||||||
|
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This gets called by Embree at every valid ray/object intersection.
|
/* This gets called by Embree at every valid ray/object intersection.
|
||||||
* Things like recording subsurface or shadow hits for later evaluation
|
* Things like recording subsurface or shadow hits for later evaluation
|
||||||
* as well as filtering for volume objects happen here.
|
* as well as filtering for volume objects happen here.
|
||||||
@@ -75,12 +95,16 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
RTCHit *hit = (RTCHit *)args->hit;
|
RTCHit *hit = (RTCHit *)args->hit;
|
||||||
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||||
const KernelGlobalsCPU *kg = ctx->kg;
|
const KernelGlobalsCPU *kg = ctx->kg;
|
||||||
|
const Ray *cray = ctx->ray;
|
||||||
|
|
||||||
switch (ctx->type) {
|
switch (ctx->type) {
|
||||||
case CCLIntersectContext::RAY_SHADOW_ALL: {
|
case CCLIntersectContext::RAY_SHADOW_ALL: {
|
||||||
Intersection current_isect;
|
Intersection current_isect;
|
||||||
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
||||||
|
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
|
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
|
||||||
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
|
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
|
||||||
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
|
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
|
||||||
@@ -160,6 +184,10 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (intersection_skip_self_local(cray->self, current_isect.prim)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* No intersection information requested, just return a hit. */
|
/* No intersection information requested, just return a hit. */
|
||||||
if (ctx->max_hits == 0) {
|
if (ctx->max_hits == 0) {
|
||||||
@@ -225,6 +253,11 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
if (ctx->num_hits < ctx->max_hits) {
|
if (ctx->num_hits < ctx->max_hits) {
|
||||||
Intersection current_isect;
|
Intersection current_isect;
|
||||||
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
kernel_embree_convert_hit(kg, ray, hit, ¤t_isect);
|
||||||
|
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Intersection *isect = &ctx->isect_s[ctx->num_hits];
|
Intersection *isect = &ctx->isect_s[ctx->num_hits];
|
||||||
++ctx->num_hits;
|
++ctx->num_hits;
|
||||||
*isect = current_isect;
|
*isect = current_isect;
|
||||||
@@ -236,12 +269,15 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
}
|
}
|
||||||
/* This tells Embree to continue tracing. */
|
/* This tells Embree to continue tracing. */
|
||||||
*args->valid = 0;
|
*args->valid = 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case CCLIntersectContext::RAY_REGULAR:
|
case CCLIntersectContext::RAY_REGULAR:
|
||||||
default:
|
default:
|
||||||
/* Nothing to do here. */
|
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,6 +293,14 @@ static void rtc_filter_func_backface_cull(const RTCFilterFunctionNArguments *arg
|
|||||||
*args->valid = 0;
|
*args->valid = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||||
|
const KernelGlobalsCPU *kg = ctx->kg;
|
||||||
|
const Ray *cray = ctx->ray;
|
||||||
|
|
||||||
|
if (kernel_embree_is_self_intersection(kg, hit, cray)) {
|
||||||
|
*args->valid = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtc_filter_occluded_func_backface_cull(const RTCFilterFunctionNArguments *args)
|
static void rtc_filter_occluded_func_backface_cull(const RTCFilterFunctionNArguments *args)
|
||||||
@@ -355,10 +399,12 @@ void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool dynamic = params.bvh_type == BVH_TYPE_DYNAMIC;
|
const bool dynamic = params.bvh_type == BVH_TYPE_DYNAMIC;
|
||||||
|
const bool compact = params.use_compact_structure;
|
||||||
|
|
||||||
scene = rtcNewScene(rtc_device);
|
scene = rtcNewScene(rtc_device);
|
||||||
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
|
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
|
||||||
RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
|
(compact ? RTC_SCENE_FLAG_COMPACT : RTC_SCENE_FLAG_NONE) |
|
||||||
|
RTC_SCENE_FLAG_ROBUST;
|
||||||
rtcSetSceneFlags(scene, scene_flags);
|
rtcSetSceneFlags(scene, scene_flags);
|
||||||
build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
|
build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
|
||||||
(params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
|
(params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
|
||||||
@@ -425,7 +471,7 @@ void BVHEmbree::add_instance(Object *ob, int i)
|
|||||||
assert(instance_bvh != NULL);
|
assert(instance_bvh != NULL);
|
||||||
|
|
||||||
const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1;
|
const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1;
|
||||||
const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
|
const size_t num_motion_steps = min(num_object_motion_steps, (size_t)RTC_MAX_TIME_STEP_COUNT);
|
||||||
assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
||||||
|
|
||||||
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE);
|
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE);
|
||||||
@@ -476,7 +522,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
||||||
num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
|
num_motion_steps = min(num_motion_steps, (size_t)RTC_MAX_TIME_STEP_COUNT);
|
||||||
|
|
||||||
const size_t num_triangles = mesh->num_triangles();
|
const size_t num_triangles = mesh->num_triangles();
|
||||||
|
|
||||||
@@ -503,6 +549,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
|
|||||||
|
|
||||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
||||||
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
||||||
|
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_intersection_func);
|
||||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||||
|
|
||||||
rtcCommitGeometry(geom_id);
|
rtcCommitGeometry(geom_id);
|
||||||
@@ -728,7 +775,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
|
||||||
num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
|
num_motion_steps = min(num_motion_steps, (size_t)RTC_MAX_TIME_STEP_COUNT);
|
||||||
|
|
||||||
const size_t num_curves = hair->num_curves();
|
const size_t num_curves = hair->num_curves();
|
||||||
size_t num_segments = 0;
|
size_t num_segments = 0;
|
||||||
@@ -765,6 +812,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
|||||||
|
|
||||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
||||||
if (hair->curve_shape == CURVE_RIBBON) {
|
if (hair->curve_shape == CURVE_RIBBON) {
|
||||||
|
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_intersection_func);
|
||||||
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -97,6 +97,9 @@ class BVHParams {
|
|||||||
*/
|
*/
|
||||||
bool use_unaligned_nodes;
|
bool use_unaligned_nodes;
|
||||||
|
|
||||||
|
/* Use compact acceleration structure (Embree)*/
|
||||||
|
bool use_compact_structure;
|
||||||
|
|
||||||
/* Split time range to this number of steps and create leaf node for each
|
/* Split time range to this number of steps and create leaf node for each
|
||||||
* of this time steps.
|
* of this time steps.
|
||||||
*
|
*
|
||||||
@@ -139,6 +142,7 @@ class BVHParams {
|
|||||||
|
|
||||||
top_level = false;
|
top_level = false;
|
||||||
bvh_layout = BVH_LAYOUT_BVH2;
|
bvh_layout = BVH_LAYOUT_BVH2;
|
||||||
|
use_compact_structure = true;
|
||||||
use_unaligned_nodes = false;
|
use_unaligned_nodes = false;
|
||||||
|
|
||||||
num_motion_curve_steps = 0;
|
num_motion_curve_steps = 0;
|
||||||
|
@@ -491,26 +491,22 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
# GLUT
|
# SDL
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
# We can't use the version from the Blender precompiled libraries because
|
||||||
add_definitions(-DFREEGLUT_STATIC -DFREEGLUT_LIB_PRAGMAS=0)
|
# it does not include the video subsystem.
|
||||||
set(GLUT_LIBRARIES "${_cycles_lib_dir}/opengl/lib/freeglut_static.lib")
|
find_package(SDL2)
|
||||||
set(GLUT_INCLUDE_DIR "${_cycles_lib_dir}/opengl/include")
|
|
||||||
else()
|
|
||||||
find_package(GLUT)
|
|
||||||
|
|
||||||
if(NOT GLUT_FOUND)
|
if(NOT SDL2_FOUND)
|
||||||
set(WITH_CYCLES_STANDALONE_GUI OFF)
|
set(WITH_CYCLES_STANDALONE_GUI OFF)
|
||||||
message(STATUS "GLUT not found, disabling Cycles standalone GUI")
|
message(STATUS "SDL not found, disabling Cycles standalone GUI")
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
SYSTEM
|
SYSTEM
|
||||||
${GLUT_INCLUDE_DIR}
|
${SDL2_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -559,10 +555,10 @@ if(WITH_CYCLES_DEVICE_METAL)
|
|||||||
find_library(METAL_LIBRARY Metal)
|
find_library(METAL_LIBRARY Metal)
|
||||||
|
|
||||||
# This file was added in the 12.0 SDK, use it as a way to detect the version.
|
# This file was added in the 12.0 SDK, use it as a way to detect the version.
|
||||||
if (METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
|
if(METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
|
||||||
message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL")
|
message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL")
|
||||||
set(WITH_CYCLES_DEVICE_METAL OFF)
|
set(WITH_CYCLES_DEVICE_METAL OFF)
|
||||||
elseif (NOT METAL_LIBRARY)
|
elseif(NOT METAL_LIBRARY)
|
||||||
message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL")
|
message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL")
|
||||||
set(WITH_CYCLES_DEVICE_METAL OFF)
|
set(WITH_CYCLES_DEVICE_METAL OFF)
|
||||||
else()
|
else()
|
||||||
|
@@ -84,39 +84,6 @@ macro(cycles_add_library target library_deps)
|
|||||||
cycles_set_solution_folder(${target})
|
cycles_set_solution_folder(${target})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# Cycles library dependencies common to all executables
|
|
||||||
|
|
||||||
function(cycles_link_directories)
|
|
||||||
if(APPLE)
|
|
||||||
# APPLE platform uses full paths for linking libraries, and avoids link_directories.
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_OPENCOLORIO)
|
|
||||||
link_directories(${OPENCOLORIO_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENVDB)
|
|
||||||
link_directories(${OPENVDB_LIBPATH} ${BLOSC_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENSUBDIV)
|
|
||||||
link_directories(${OPENSUBDIV_LIBPATH})
|
|
||||||
endif()
|
|
||||||
if(WITH_OPENIMAGEDENOISE)
|
|
||||||
link_directories(${OPENIMAGEDENOISE_LIBPATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
link_directories(
|
|
||||||
${OPENIMAGEIO_LIBPATH}
|
|
||||||
${BOOST_LIBPATH}
|
|
||||||
${PNG_LIBPATH}
|
|
||||||
${JPEG_LIBPATH}
|
|
||||||
${ZLIB_LIBPATH}
|
|
||||||
${TIFF_LIBPATH}
|
|
||||||
${OPENEXR_LIBPATH}
|
|
||||||
${OPENJPEG_LIBPATH}
|
|
||||||
)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
macro(cycles_target_link_libraries target)
|
macro(cycles_target_link_libraries target)
|
||||||
if(WITH_CYCLES_LOGGING)
|
if(WITH_CYCLES_LOGGING)
|
||||||
target_link_libraries(${target} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
|
target_link_libraries(${target} ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})
|
||||||
@@ -168,12 +135,6 @@ macro(cycles_target_link_libraries target)
|
|||||||
target_link_libraries(${target} extern_hipew)
|
target_link_libraries(${target} extern_hipew)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CYCLES_STANDALONE_REPOSITORY)
|
|
||||||
target_link_libraries(${target} extern_numaapi)
|
|
||||||
else()
|
|
||||||
target_link_libraries(${target} bf_intern_numaapi)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
if(CYCLES_STANDALONE_REPOSITORY)
|
if(CYCLES_STANDALONE_REPOSITORY)
|
||||||
target_link_libraries(${target} extern_libc_compat)
|
target_link_libraries(${target} extern_libc_compat)
|
||||||
|
@@ -72,7 +72,7 @@ CPUDevice::CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_
|
|||||||
<< " CPU kernels.";
|
<< " CPU kernels.";
|
||||||
|
|
||||||
if (info.cpu_threads == 0) {
|
if (info.cpu_threads == 0) {
|
||||||
info.cpu_threads = TaskScheduler::num_threads();
|
info.cpu_threads = TaskScheduler::max_concurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_OSL
|
#ifdef WITH_OSL
|
||||||
@@ -204,7 +204,7 @@ device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_
|
|||||||
|
|
||||||
void CPUDevice::const_copy_to(const char *name, void *host, size_t size)
|
void CPUDevice::const_copy_to(const char *name, void *host, size_t size)
|
||||||
{
|
{
|
||||||
#if WITH_EMBREE
|
#ifdef WITH_EMBREE
|
||||||
if (strcmp(name, "__data") == 0) {
|
if (strcmp(name, "__data") == 0) {
|
||||||
assert(size <= sizeof(KernelData));
|
assert(size <= sizeof(KernelData));
|
||||||
|
|
||||||
|
@@ -45,8 +45,10 @@ void CUDADeviceGraphicsInterop::set_display_interop(
|
|||||||
|
|
||||||
need_clear_ = display_interop.need_clear;
|
need_clear_ = display_interop.need_clear;
|
||||||
|
|
||||||
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
|
if (!display_interop.need_recreate) {
|
||||||
return;
|
if (opengl_pbo_id_ == display_interop.opengl_pbo_id && buffer_area_ == new_buffer_area) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CUDAContextScope scope(device_);
|
CUDAContextScope scope(device_);
|
||||||
|
@@ -76,6 +76,8 @@ NODE_DEFINE(DenoiseParams)
|
|||||||
SOCKET_BOOLEAN(use_pass_albedo, "Use Pass Albedo", true);
|
SOCKET_BOOLEAN(use_pass_albedo, "Use Pass Albedo", true);
|
||||||
SOCKET_BOOLEAN(use_pass_normal, "Use Pass Normal", false);
|
SOCKET_BOOLEAN(use_pass_normal, "Use Pass Normal", false);
|
||||||
|
|
||||||
|
SOCKET_BOOLEAN(temporally_stable, "Temporally Stable", false);
|
||||||
|
|
||||||
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
|
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
|
@@ -72,6 +72,9 @@ class DenoiseParams : public Node {
|
|||||||
bool use_pass_albedo = true;
|
bool use_pass_albedo = true;
|
||||||
bool use_pass_normal = true;
|
bool use_pass_normal = true;
|
||||||
|
|
||||||
|
/* Configure the denoiser to use motion vectors, previous image and a temporally stable model. */
|
||||||
|
bool temporally_stable = false;
|
||||||
|
|
||||||
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
|
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
|
||||||
|
|
||||||
static const NodeEnum *get_type_enum();
|
static const NodeEnum *get_type_enum();
|
||||||
@@ -83,7 +86,8 @@ class DenoiseParams : public Node {
|
|||||||
{
|
{
|
||||||
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
|
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
|
||||||
use_pass_albedo == other.use_pass_albedo &&
|
use_pass_albedo == other.use_pass_albedo &&
|
||||||
use_pass_normal == other.use_pass_normal && prefilter == other.prefilter);
|
use_pass_normal == other.use_pass_normal &&
|
||||||
|
temporally_stable == other.temporally_stable && prefilter == other.prefilter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/system.h"
|
#include "util/system.h"
|
||||||
|
#include "util/task.h"
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
#include "util/types.h"
|
#include "util/types.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
@@ -327,14 +328,15 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
|||||||
info.has_osl = true;
|
info.has_osl = true;
|
||||||
info.has_profiling = true;
|
info.has_profiling = true;
|
||||||
info.has_peer_memory = false;
|
info.has_peer_memory = false;
|
||||||
|
info.use_metalrt = false;
|
||||||
info.denoisers = DENOISER_ALL;
|
info.denoisers = DENOISER_ALL;
|
||||||
|
|
||||||
foreach (const DeviceInfo &device, subdevices) {
|
foreach (const DeviceInfo &device, subdevices) {
|
||||||
/* Ensure CPU device does not slow down GPU. */
|
/* Ensure CPU device does not slow down GPU. */
|
||||||
if (device.type == DEVICE_CPU && subdevices.size() > 1) {
|
if (device.type == DEVICE_CPU && subdevices.size() > 1) {
|
||||||
if (background) {
|
if (background) {
|
||||||
int orig_cpu_threads = (threads) ? threads : system_cpu_thread_count();
|
int orig_cpu_threads = (threads) ? threads : TaskScheduler::max_concurrency();
|
||||||
int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
|
int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), size_t(0));
|
||||||
|
|
||||||
VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads
|
VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads
|
||||||
<< ", to dedicate to GPU.";
|
<< ", to dedicate to GPU.";
|
||||||
@@ -373,6 +375,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
|||||||
info.has_osl &= device.has_osl;
|
info.has_osl &= device.has_osl;
|
||||||
info.has_profiling &= device.has_profiling;
|
info.has_profiling &= device.has_profiling;
|
||||||
info.has_peer_memory |= device.has_peer_memory;
|
info.has_peer_memory |= device.has_peer_memory;
|
||||||
|
info.use_metalrt |= device.use_metalrt;
|
||||||
info.denoisers &= device.denoisers;
|
info.denoisers &= device.denoisers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,6 +79,7 @@ class DeviceInfo {
|
|||||||
bool has_profiling; /* Supports runtime collection of profiling info. */
|
bool has_profiling; /* Supports runtime collection of profiling info. */
|
||||||
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
|
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
|
||||||
bool has_gpu_queue; /* Device supports GPU queue. */
|
bool has_gpu_queue; /* Device supports GPU queue. */
|
||||||
|
bool use_metalrt; /* Use MetalRT to accelerate ray queries (Metal only). */
|
||||||
DenoiserTypeMask denoisers; /* Supported denoiser types. */
|
DenoiserTypeMask denoisers; /* Supported denoiser types. */
|
||||||
int cpu_threads;
|
int cpu_threads;
|
||||||
vector<DeviceInfo> multi_devices;
|
vector<DeviceInfo> multi_devices;
|
||||||
@@ -96,6 +97,7 @@ class DeviceInfo {
|
|||||||
has_profiling = false;
|
has_profiling = false;
|
||||||
has_peer_memory = false;
|
has_peer_memory = false;
|
||||||
has_gpu_queue = false;
|
has_gpu_queue = false;
|
||||||
|
use_metalrt = false;
|
||||||
denoisers = DENOISER_NONE;
|
denoisers = DENOISER_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
# ifdef WITH_HIP_DYNLOAD
|
# ifdef WITH_HIP_DYNLOAD
|
||||||
# include "hipew.h"
|
# include "hipew.h"
|
||||||
# else
|
|
||||||
# include "util/opengl.h"
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
@@ -311,7 +311,7 @@ template<typename T> class device_only_memory : public device_memory {
|
|||||||
: device_memory(device, name, allow_host_memory_fallback ? MEM_READ_WRITE : MEM_DEVICE_ONLY)
|
: device_memory(device, name, allow_host_memory_fallback ? MEM_READ_WRITE : MEM_DEVICE_ONLY)
|
||||||
{
|
{
|
||||||
data_type = device_type_traits<T>::data_type;
|
data_type = device_type_traits<T>::data_type;
|
||||||
data_elements = max(device_type_traits<T>::num_elements, 1);
|
data_elements = max(device_type_traits<T>::num_elements, size_t(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
|
device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
|
||||||
|
@@ -58,6 +58,11 @@ class BVHMetal : public BVH {
|
|||||||
id<MTLCommandQueue> queue,
|
id<MTLCommandQueue> queue,
|
||||||
Geometry *const geom,
|
Geometry *const geom,
|
||||||
bool refit);
|
bool refit);
|
||||||
|
bool build_BLAS_pointcloud(Progress &progress,
|
||||||
|
id<MTLDevice> device,
|
||||||
|
id<MTLCommandQueue> queue,
|
||||||
|
Geometry *const geom,
|
||||||
|
bool refit);
|
||||||
bool build_TLAS(Progress &progress, id<MTLDevice> device, id<MTLCommandQueue> queue, bool refit);
|
bool build_TLAS(Progress &progress, id<MTLDevice> device, id<MTLCommandQueue> queue, bool refit);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
# include "scene/hair.h"
|
# include "scene/hair.h"
|
||||||
# include "scene/mesh.h"
|
# include "scene/mesh.h"
|
||||||
# include "scene/object.h"
|
# include "scene/object.h"
|
||||||
|
# include "scene/pointcloud.h"
|
||||||
|
|
||||||
# include "util/progress.h"
|
# include "util/progress.h"
|
||||||
|
|
||||||
@@ -475,6 +476,220 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
|
||||||
|
id<MTLDevice> device,
|
||||||
|
id<MTLCommandQueue> queue,
|
||||||
|
Geometry *const geom,
|
||||||
|
bool refit)
|
||||||
|
{
|
||||||
|
if (@available(macos 12.0, *)) {
|
||||||
|
/* Build BLAS for point cloud */
|
||||||
|
PointCloud *pointcloud = static_cast<PointCloud *>(geom);
|
||||||
|
if (pointcloud->num_points() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------*/
|
||||||
|
BVH_status("Building pointcloud BLAS | %7d points | %s",
|
||||||
|
(int)pointcloud->num_points(),
|
||||||
|
geom->name.c_str());
|
||||||
|
/*------------------------------------------------*/
|
||||||
|
|
||||||
|
const size_t num_points = pointcloud->get_points().size();
|
||||||
|
const float3 *points = pointcloud->get_points().data();
|
||||||
|
const float *radius = pointcloud->get_radius().data();
|
||||||
|
|
||||||
|
const bool use_fast_trace_bvh = (params.bvh_type == BVH_TYPE_STATIC);
|
||||||
|
|
||||||
|
size_t num_motion_steps = 1;
|
||||||
|
Attribute *motion_keys = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||||
|
if (motion_blur && pointcloud->get_use_motion_blur() && motion_keys) {
|
||||||
|
num_motion_steps = pointcloud->get_motion_steps();
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t num_aabbs = num_motion_steps;
|
||||||
|
|
||||||
|
MTLResourceOptions storage_mode;
|
||||||
|
if (device.hasUnifiedMemory) {
|
||||||
|
storage_mode = MTLResourceStorageModeShared;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
storage_mode = MTLResourceStorageModeManaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a GPU buffer for the AABB data and populate it */
|
||||||
|
id<MTLBuffer> aabbBuf = [device
|
||||||
|
newBufferWithLength:num_aabbs * sizeof(MTLAxisAlignedBoundingBox)
|
||||||
|
options:storage_mode];
|
||||||
|
MTLAxisAlignedBoundingBox *aabb_data = (MTLAxisAlignedBoundingBox *)[aabbBuf contents];
|
||||||
|
|
||||||
|
/* Get AABBs for each motion step */
|
||||||
|
size_t center_step = (num_motion_steps - 1) / 2;
|
||||||
|
for (size_t step = 0; step < num_motion_steps; ++step) {
|
||||||
|
/* The center step for motion vertices is not stored in the attribute */
|
||||||
|
if (step != center_step) {
|
||||||
|
size_t attr_offset = (step > center_step) ? step - 1 : step;
|
||||||
|
points = motion_keys->data_float3() + attr_offset * num_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < num_points; ++j) {
|
||||||
|
const PointCloud::Point point = pointcloud->get_point(j);
|
||||||
|
BoundBox bounds = BoundBox::empty;
|
||||||
|
point.bounds_grow(points, radius, bounds);
|
||||||
|
|
||||||
|
const size_t index = step * num_points + j;
|
||||||
|
aabb_data[index].min = (MTLPackedFloat3 &)bounds.min;
|
||||||
|
aabb_data[index].max = (MTLPackedFloat3 &)bounds.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storage_mode == MTLResourceStorageModeManaged) {
|
||||||
|
[aabbBuf didModifyRange:NSMakeRange(0, aabbBuf.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
# if 0
|
||||||
|
for (size_t i=0; i<num_aabbs && i < 400; i++) {
|
||||||
|
MTLAxisAlignedBoundingBox& bb = aabb_data[i];
|
||||||
|
printf(" %d: %.1f,%.1f,%.1f -- %.1f,%.1f,%.1f\n", int(i), bb.min.x, bb.min.y, bb.min.z, bb.max.x, bb.max.y, bb.max.z);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
MTLAccelerationStructureGeometryDescriptor *geomDesc;
|
||||||
|
if (motion_blur) {
|
||||||
|
std::vector<MTLMotionKeyframeData *> aabb_ptrs;
|
||||||
|
aabb_ptrs.reserve(num_motion_steps);
|
||||||
|
for (size_t step = 0; step < num_motion_steps; ++step) {
|
||||||
|
MTLMotionKeyframeData *k = [MTLMotionKeyframeData data];
|
||||||
|
k.buffer = aabbBuf;
|
||||||
|
k.offset = step * num_points * sizeof(MTLAxisAlignedBoundingBox);
|
||||||
|
aabb_ptrs.push_back(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor *geomDescMotion =
|
||||||
|
[MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor descriptor];
|
||||||
|
geomDescMotion.boundingBoxBuffers = [NSArray arrayWithObjects:aabb_ptrs.data()
|
||||||
|
count:aabb_ptrs.size()];
|
||||||
|
geomDescMotion.boundingBoxCount = num_points;
|
||||||
|
geomDescMotion.boundingBoxStride = sizeof(aabb_data[0]);
|
||||||
|
geomDescMotion.intersectionFunctionTableOffset = 2;
|
||||||
|
|
||||||
|
/* Force a single any-hit call, so shadow record-all behavior works correctly */
|
||||||
|
/* (Match optix behavior: unsigned int build_flags =
|
||||||
|
* OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;) */
|
||||||
|
geomDescMotion.allowDuplicateIntersectionFunctionInvocation = false;
|
||||||
|
geomDescMotion.opaque = true;
|
||||||
|
geomDesc = geomDescMotion;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MTLAccelerationStructureBoundingBoxGeometryDescriptor *geomDescNoMotion =
|
||||||
|
[MTLAccelerationStructureBoundingBoxGeometryDescriptor descriptor];
|
||||||
|
geomDescNoMotion.boundingBoxBuffer = aabbBuf;
|
||||||
|
geomDescNoMotion.boundingBoxBufferOffset = 0;
|
||||||
|
geomDescNoMotion.boundingBoxCount = int(num_aabbs);
|
||||||
|
geomDescNoMotion.boundingBoxStride = sizeof(aabb_data[0]);
|
||||||
|
geomDescNoMotion.intersectionFunctionTableOffset = 2;
|
||||||
|
|
||||||
|
/* Force a single any-hit call, so shadow record-all behavior works correctly */
|
||||||
|
/* (Match optix behavior: unsigned int build_flags =
|
||||||
|
* OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;) */
|
||||||
|
geomDescNoMotion.allowDuplicateIntersectionFunctionInvocation = false;
|
||||||
|
geomDescNoMotion.opaque = true;
|
||||||
|
geomDesc = geomDescNoMotion;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLPrimitiveAccelerationStructureDescriptor *accelDesc =
|
||||||
|
[MTLPrimitiveAccelerationStructureDescriptor descriptor];
|
||||||
|
accelDesc.geometryDescriptors = @[ geomDesc ];
|
||||||
|
|
||||||
|
if (motion_blur) {
|
||||||
|
accelDesc.motionStartTime = 0.0f;
|
||||||
|
accelDesc.motionEndTime = 1.0f;
|
||||||
|
accelDesc.motionStartBorderMode = MTLMotionBorderModeVanish;
|
||||||
|
accelDesc.motionEndBorderMode = MTLMotionBorderModeVanish;
|
||||||
|
accelDesc.motionKeyframeCount = num_motion_steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_fast_trace_bvh) {
|
||||||
|
accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
|
||||||
|
MTLAccelerationStructureUsagePreferFastBuild);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLAccelerationStructureSizes accelSizes = [device
|
||||||
|
accelerationStructureSizesWithDescriptor:accelDesc];
|
||||||
|
id<MTLAccelerationStructure> accel_uncompressed = [device
|
||||||
|
newAccelerationStructureWithSize:accelSizes.accelerationStructureSize];
|
||||||
|
id<MTLBuffer> scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize
|
||||||
|
options:MTLResourceStorageModePrivate];
|
||||||
|
id<MTLBuffer> sizeBuf = [device newBufferWithLength:8 options:MTLResourceStorageModeShared];
|
||||||
|
id<MTLCommandBuffer> accelCommands = [queue commandBuffer];
|
||||||
|
id<MTLAccelerationStructureCommandEncoder> accelEnc =
|
||||||
|
[accelCommands accelerationStructureCommandEncoder];
|
||||||
|
if (refit) {
|
||||||
|
[accelEnc refitAccelerationStructure:accel_struct
|
||||||
|
descriptor:accelDesc
|
||||||
|
destination:accel_uncompressed
|
||||||
|
scratchBuffer:scratchBuf
|
||||||
|
scratchBufferOffset:0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[accelEnc buildAccelerationStructure:accel_uncompressed
|
||||||
|
descriptor:accelDesc
|
||||||
|
scratchBuffer:scratchBuf
|
||||||
|
scratchBufferOffset:0];
|
||||||
|
}
|
||||||
|
if (use_fast_trace_bvh) {
|
||||||
|
[accelEnc writeCompactedAccelerationStructureSize:accel_uncompressed
|
||||||
|
toBuffer:sizeBuf
|
||||||
|
offset:0
|
||||||
|
sizeDataType:MTLDataTypeULong];
|
||||||
|
}
|
||||||
|
[accelEnc endEncoding];
|
||||||
|
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
|
||||||
|
/* free temp resources */
|
||||||
|
[scratchBuf release];
|
||||||
|
[aabbBuf release];
|
||||||
|
|
||||||
|
if (use_fast_trace_bvh) {
|
||||||
|
/* Compact the accel structure */
|
||||||
|
uint64_t compressed_size = *(uint64_t *)sizeBuf.contents;
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
id<MTLCommandBuffer> accelCommands = [queue commandBuffer];
|
||||||
|
id<MTLAccelerationStructureCommandEncoder> accelEnc =
|
||||||
|
[accelCommands accelerationStructureCommandEncoder];
|
||||||
|
id<MTLAccelerationStructure> accel = [device
|
||||||
|
newAccelerationStructureWithSize:compressed_size];
|
||||||
|
[accelEnc copyAndCompactAccelerationStructure:accel_uncompressed
|
||||||
|
toAccelerationStructure:accel];
|
||||||
|
[accelEnc endEncoding];
|
||||||
|
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
|
||||||
|
uint64_t allocated_size = [accel allocatedSize];
|
||||||
|
stats.mem_alloc(allocated_size);
|
||||||
|
accel_struct = accel;
|
||||||
|
[accel_uncompressed release];
|
||||||
|
accel_struct_building = false;
|
||||||
|
}];
|
||||||
|
[accelCommands commit];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* set our acceleration structure to the uncompressed structure */
|
||||||
|
accel_struct = accel_uncompressed;
|
||||||
|
|
||||||
|
uint64_t allocated_size = [accel_struct allocatedSize];
|
||||||
|
stats.mem_alloc(allocated_size);
|
||||||
|
accel_struct_building = false;
|
||||||
|
}
|
||||||
|
[sizeBuf release];
|
||||||
|
}];
|
||||||
|
|
||||||
|
accel_struct_building = true;
|
||||||
|
[accelCommands commit];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool BVHMetal::build_BLAS(Progress &progress,
|
bool BVHMetal::build_BLAS(Progress &progress,
|
||||||
id<MTLDevice> device,
|
id<MTLDevice> device,
|
||||||
id<MTLCommandQueue> queue,
|
id<MTLCommandQueue> queue,
|
||||||
@@ -491,6 +706,8 @@ bool BVHMetal::build_BLAS(Progress &progress,
|
|||||||
return build_BLAS_mesh(progress, device, queue, geom, refit);
|
return build_BLAS_mesh(progress, device, queue, geom, refit);
|
||||||
case Geometry::HAIR:
|
case Geometry::HAIR:
|
||||||
return build_BLAS_hair(progress, device, queue, geom, refit);
|
return build_BLAS_hair(progress, device, queue, geom, refit);
|
||||||
|
case Geometry::POINTCLOUD:
|
||||||
|
return build_BLAS_pointcloud(progress, device, queue, geom, refit);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -544,7 +761,7 @@ bool BVHMetal::build_TLAS(Progress &progress,
|
|||||||
num_instances++;
|
num_instances++;
|
||||||
|
|
||||||
if (ob->use_motion()) {
|
if (ob->use_motion()) {
|
||||||
num_motion_transforms += max(1, ob->get_motion().size());
|
num_motion_transforms += max((size_t)1, ob->get_motion().size());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
num_motion_transforms++;
|
num_motion_transforms++;
|
||||||
|
@@ -39,33 +39,20 @@ bool device_metal_init()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_metal_get_num_devices_safe(uint32_t *num_devices)
|
|
||||||
{
|
|
||||||
*num_devices = MTLCopyAllDevices().count;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_metal_info(vector<DeviceInfo> &devices)
|
void device_metal_info(vector<DeviceInfo> &devices)
|
||||||
{
|
{
|
||||||
uint32_t num_devices = 0;
|
auto usable_devices = MetalInfo::get_usable_devices();
|
||||||
device_metal_get_num_devices_safe(&num_devices);
|
|
||||||
if (num_devices == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<MetalPlatformDevice> usable_devices;
|
|
||||||
MetalInfo::get_usable_devices(&usable_devices);
|
|
||||||
/* Devices are numbered consecutively across platforms. */
|
/* Devices are numbered consecutively across platforms. */
|
||||||
set<string> unique_ids;
|
set<string> unique_ids;
|
||||||
int device_index = 0;
|
int device_index = 0;
|
||||||
for (MetalPlatformDevice &device : usable_devices) {
|
for (id<MTLDevice> &device : usable_devices) {
|
||||||
/* Compute unique ID for persistent user preferences. */
|
/* Compute unique ID for persistent user preferences. */
|
||||||
const string &device_name = device.device_name;
|
string device_name = [device.name UTF8String];
|
||||||
string id = string("METAL_") + device_name;
|
string id = string("METAL_") + device_name;
|
||||||
|
|
||||||
/* Hardware ID might not be unique, add device number in that case. */
|
/* Hardware ID might not be unique, add device number in that case. */
|
||||||
if (unique_ids.find(id) != unique_ids.end()) {
|
if (unique_ids.find(id) != unique_ids.end()) {
|
||||||
id += string_printf("_ID_%d", num_devices);
|
id += string_printf("_ID_%d", device_index);
|
||||||
}
|
}
|
||||||
unique_ids.insert(id);
|
unique_ids.insert(id);
|
||||||
|
|
||||||
@@ -94,15 +81,13 @@ void device_metal_info(vector<DeviceInfo> &devices)
|
|||||||
string device_metal_capabilities()
|
string device_metal_capabilities()
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string error_msg = "";
|
auto allDevices = MTLCopyAllDevices();
|
||||||
uint32_t num_devices = 0;
|
uint32_t num_devices = allDevices.count;
|
||||||
assert(device_metal_get_num_devices_safe(&num_devices));
|
|
||||||
if (num_devices == 0) {
|
if (num_devices == 0) {
|
||||||
return "No Metal devices found\n";
|
return "No Metal devices found\n";
|
||||||
}
|
}
|
||||||
result += string_printf("Number of devices: %u\n", num_devices);
|
result += string_printf("Number of devices: %u\n", num_devices);
|
||||||
|
|
||||||
NSArray<id<MTLDevice>> *allDevices = MTLCopyAllDevices();
|
|
||||||
for (id<MTLDevice> device in allDevices) {
|
for (id<MTLDevice> device in allDevices) {
|
||||||
result += string_printf("\t\tDevice: %s\n", [device.name UTF8String]);
|
result += string_printf("\t\tDevice: %s\n", [device.name UTF8String]);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user