mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
815 Commits
gs_wrchack
...
v1.7.4580
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
683c8d0cc3 | ||
|
|
bca20c9e27 | ||
|
|
1de3e0986e | ||
|
|
8b2fa73b45 | ||
|
|
1b953c1dc7 | ||
|
|
c33960b411 | ||
|
|
8d5728097b | ||
|
|
9706045656 | ||
|
|
3a953eb5df | ||
|
|
35971b29bc | ||
|
|
76cbc64f99 | ||
|
|
8f8c85273c | ||
|
|
25b953b7ec | ||
|
|
c40f205bd3 | ||
|
|
be1b698af1 | ||
|
|
c9ec71eeba | ||
|
|
4df27e6efb | ||
|
|
02f3279dec | ||
|
|
21900555dc | ||
|
|
5a4e21287a | ||
|
|
3e8e5216eb | ||
|
|
c679de8e39 | ||
|
|
a979d2283f | ||
|
|
3254714b70 | ||
|
|
65374f50cf | ||
|
|
1a62cd064c | ||
|
|
40bd19ccbb | ||
|
|
642adffeb8 | ||
|
|
5b942f0508 | ||
|
|
b4b5b58e35 | ||
|
|
bf4672fb2b | ||
|
|
d6e2dcd25b | ||
|
|
3b7d22153f | ||
|
|
490a8d35cb | ||
|
|
260846e9e9 | ||
|
|
d1ed5aadc2 | ||
|
|
1067ed309a | ||
|
|
1ef9bc464d | ||
|
|
ba3a7fc11a | ||
|
|
c44b4c3d35 | ||
|
|
c79c79fe0e | ||
|
|
a7c70a3916 | ||
|
|
325a8cba58 | ||
|
|
35387eeabb | ||
|
|
9d3de8631c | ||
|
|
940e211bb6 | ||
|
|
5eb425bc4c | ||
|
|
bd6b529157 | ||
|
|
0d59e0a2e9 | ||
|
|
1826d122f5 | ||
|
|
ed6dd6f6cd | ||
|
|
81da9fb5a4 | ||
|
|
ec35330593 | ||
|
|
f741953ee4 | ||
|
|
c0343897cd | ||
|
|
d880f8cde5 | ||
|
|
1175bd822c | ||
|
|
63a141abe6 | ||
|
|
abce57ce9c | ||
|
|
c471f7cf6c | ||
|
|
656c2775ac | ||
|
|
a2c6e050d7 | ||
|
|
f3adb05b1c | ||
|
|
bfc3d2e1d4 | ||
|
|
680affd1fe | ||
|
|
ab1d2009a0 | ||
|
|
8196f46721 | ||
|
|
44460365c0 | ||
|
|
38d9aa5e73 | ||
|
|
830db2b326 | ||
|
|
51165f6061 | ||
|
|
2a9d38048e | ||
|
|
bba65b8a82 | ||
|
|
884086ba76 | ||
|
|
1fa6614cd5 | ||
|
|
57581724cd | ||
|
|
0ae6f7efc5 | ||
|
|
d0346436fb | ||
|
|
1b28980454 | ||
|
|
90a6088d61 | ||
|
|
338a2beaf0 | ||
|
|
ff9a910c1a | ||
|
|
d88921bb58 | ||
|
|
c1f3f0a247 | ||
|
|
df847835ad | ||
|
|
8aad1c78af | ||
|
|
7c97cf4799 | ||
|
|
fd11523cf4 | ||
|
|
a293a9bd4b | ||
|
|
8de0eb3c06 | ||
|
|
8bff172f0b | ||
|
|
7f26595804 | ||
|
|
68ec70f24f | ||
|
|
836591a44f | ||
|
|
dd4ded3d4b | ||
|
|
995e294856 | ||
|
|
c4e623eec2 | ||
|
|
61253d8201 | ||
|
|
0f05967190 | ||
|
|
ad0e469f87 | ||
|
|
512d24cea6 | ||
|
|
0850a3fab7 | ||
|
|
16db92526c | ||
|
|
30ad66e8f1 | ||
|
|
77f600a16c | ||
|
|
d96bf7f951 | ||
|
|
15948c2781 | ||
|
|
b0c744bd29 | ||
|
|
5eacfe1afb | ||
|
|
2f985b479e | ||
|
|
e61d8f2f8f | ||
|
|
f4e338f9fb | ||
|
|
9509745be9 | ||
|
|
91b47134ad | ||
|
|
6426f4432e | ||
|
|
191ea50663 | ||
|
|
7f5c0fca8f | ||
|
|
5f8798cf94 | ||
|
|
3aac709682 | ||
|
|
e3962aa794 | ||
|
|
1964bbc03a | ||
|
|
80675399aa | ||
|
|
6fb4c724bd | ||
|
|
b34606c9ce | ||
|
|
4e97381709 | ||
|
|
d4db49f969 | ||
|
|
4b54870da1 | ||
|
|
0ae91cbf64 | ||
|
|
041abd8abc | ||
|
|
43be6883df | ||
|
|
ad4e95cb78 | ||
|
|
38480d3aed | ||
|
|
3436bb3792 | ||
|
|
5bab8af38f | ||
|
|
61f344dd66 | ||
|
|
1811955fce | ||
|
|
449da42108 | ||
|
|
9493d3e9c9 | ||
|
|
e5c1052062 | ||
|
|
7edc4e2cb3 | ||
|
|
7ca28fc796 | ||
|
|
72f9bf83fd | ||
|
|
2695ddc9fc | ||
|
|
fbcc8671ac | ||
|
|
7e76230cf8 | ||
|
|
ba27221bf2 | ||
|
|
6cf1501050 | ||
|
|
a30ca0ce2a | ||
|
|
5e3e988846 | ||
|
|
bb42353c81 | ||
|
|
61740fc9ed | ||
|
|
ea30c90a6c | ||
|
|
3968a82775 | ||
|
|
6e40081dd9 | ||
|
|
2b8b43c94c | ||
|
|
3f0ecc2284 | ||
|
|
828e86bdf4 | ||
|
|
159d0c060f | ||
|
|
4a29fdb3f2 | ||
|
|
29da1bb9ef | ||
|
|
47636bb30f | ||
|
|
5fe64396b4 | ||
|
|
75b782f261 | ||
|
|
4a5cf0efb9 | ||
|
|
cfdae77331 | ||
|
|
ec0aaff8ac | ||
|
|
f651d8e26a | ||
|
|
0526769808 | ||
|
|
1866745936 | ||
|
|
920c5ab266 | ||
|
|
c57d8980a1 | ||
|
|
0ed418834a | ||
|
|
083969a3d2 | ||
|
|
6740fff179 | ||
|
|
25e24d1d09 | ||
|
|
76cc9c8b21 | ||
|
|
7dcf6b70d9 | ||
|
|
f26b26b73e | ||
|
|
055beaa27a | ||
|
|
a4623c3c63 | ||
|
|
4e3a94809d | ||
|
|
5ff64899e6 | ||
|
|
971f172c91 | ||
|
|
4671167a2c | ||
|
|
7aff4ee4cb | ||
|
|
30f7685435 | ||
|
|
341f377e6d | ||
|
|
fe4788ae3f | ||
|
|
e133e89b6b | ||
|
|
bf6a0a035a | ||
|
|
790447ecc9 | ||
|
|
47506d1433 | ||
|
|
933e6aa62e | ||
|
|
6736ef1d44 | ||
|
|
3e631e047f | ||
|
|
dd2d4edffc | ||
|
|
fd2960c9cb | ||
|
|
c2907ea58f | ||
|
|
41f62cf53d | ||
|
|
e462f1ff9c | ||
|
|
5b0b6191d8 | ||
|
|
ab9a1e4307 | ||
|
|
029c11c8d2 | ||
|
|
e221d31b45 | ||
|
|
dfbdaa651c | ||
|
|
9de152b8ee | ||
|
|
360f9afb70 | ||
|
|
1b81825218 | ||
|
|
b3e6e28827 | ||
|
|
eaceb27879 | ||
|
|
cd9b6c7ac3 | ||
|
|
d3e527f2a4 | ||
|
|
b47fdcdfab | ||
|
|
2550ad7fd1 | ||
|
|
1717f584a0 | ||
|
|
0822d3e3e5 | ||
|
|
ec41af760a | ||
|
|
a5ed24ca88 | ||
|
|
b3697579c0 | ||
|
|
388da2058b | ||
|
|
aa9a0dca4b | ||
|
|
2a892da0da | ||
|
|
9237bf9429 | ||
|
|
10533dce02 | ||
|
|
b5ebc19eff | ||
|
|
6535e7e43a | ||
|
|
5f9473ef02 | ||
|
|
fbb1c7cb8e | ||
|
|
2d97d85ca5 | ||
|
|
ecd7d0fc35 | ||
|
|
0c389789f3 | ||
|
|
d8239664a8 | ||
|
|
c06d4f477a | ||
|
|
cdd88a6e5c | ||
|
|
5a73fa2d23 | ||
|
|
0367851b8e | ||
|
|
33b2f6331c | ||
|
|
befbf57191 | ||
|
|
20d040d5d1 | ||
|
|
06fdc75945 | ||
|
|
ded971a3ec | ||
|
|
abc0f99ddd | ||
|
|
b3a88d6ea7 | ||
|
|
76014b7cb9 | ||
|
|
0ab6eb6587 | ||
|
|
a4e99366fb | ||
|
|
a32ab4cc97 | ||
|
|
e7f3c42f9d | ||
|
|
d76a0d7416 | ||
|
|
79f4af8ab5 | ||
|
|
a5f83329cb | ||
|
|
267479f31d | ||
|
|
164462e510 | ||
|
|
6331df306f | ||
|
|
027ceebcbd | ||
|
|
edb2c0080c | ||
|
|
caafc87b29 | ||
|
|
5d37cac4a0 | ||
|
|
8f68e096d4 | ||
|
|
430cad48e3 | ||
|
|
757a9532e6 | ||
|
|
f26f8cafa9 | ||
|
|
128a79e355 | ||
|
|
cc2d99db3a | ||
|
|
30a31d931a | ||
|
|
1c30d449bf | ||
|
|
dc4ce58248 | ||
|
|
dc93e861c7 | ||
|
|
960daf27e2 | ||
|
|
844f21344d | ||
|
|
535ad110e3 | ||
|
|
0e0d7a5441 | ||
|
|
ed63221c7e | ||
|
|
f9c2d7767d | ||
|
|
cb91478590 | ||
|
|
5dec7fe27d | ||
|
|
575d487c65 | ||
|
|
2b9289f402 | ||
|
|
9273683d3c | ||
|
|
88f8465e7e | ||
|
|
f26031cada | ||
|
|
3352d71515 | ||
|
|
999f9532ee | ||
|
|
d1f62ca9bf | ||
|
|
ef9f0cf635 | ||
|
|
d745564451 | ||
|
|
d37ac992fc | ||
|
|
e7fc3de90c | ||
|
|
bde81380c3 | ||
|
|
839b482cb5 | ||
|
|
72f70d4789 | ||
|
|
d646bbf5c1 | ||
|
|
e68aaf6540 | ||
|
|
20ab5ed0fa | ||
|
|
8590e390a2 | ||
|
|
ab1d558420 | ||
|
|
53c9021455 | ||
|
|
8bd00e2433 | ||
|
|
c045feae50 | ||
|
|
7531080e51 | ||
|
|
bf57ab3e39 | ||
|
|
dfcb96a4b6 | ||
|
|
5c4fad6725 | ||
|
|
988b1ad03b | ||
|
|
79705a2514 | ||
|
|
0919b15183 | ||
|
|
8162c87884 | ||
|
|
09394ee4b7 | ||
|
|
7f7dd60587 | ||
|
|
6877abb2ec | ||
|
|
ce5dd88790 | ||
|
|
5bc9d625e7 | ||
|
|
1d7a69ad40 | ||
|
|
f7d87076a3 | ||
|
|
9d20b4d6a6 | ||
|
|
128cf9b57d | ||
|
|
e5b7adb228 | ||
|
|
bd5ae66fbe | ||
|
|
a3af4155f8 | ||
|
|
1ec83dc790 | ||
|
|
f26cc38b80 | ||
|
|
d9f537e9dc | ||
|
|
94c75df0d0 | ||
|
|
423a8884e8 | ||
|
|
1f26502c64 | ||
|
|
f61f7bb711 | ||
|
|
971acd3fdb | ||
|
|
bba070bdbf | ||
|
|
6c4152a7e0 | ||
|
|
f569ad0970 | ||
|
|
f16a291412 | ||
|
|
e0cfa2dff3 | ||
|
|
bf9d087e74 | ||
|
|
b245dd55d6 | ||
|
|
1e3f429169 | ||
|
|
8d429c7e5a | ||
|
|
b9be3ad3b8 | ||
|
|
3099090e6a | ||
|
|
5e27c65615 | ||
|
|
8b32382e1b | ||
|
|
60047e8029 | ||
|
|
e37fff1213 | ||
|
|
64a6d8027b | ||
|
|
cd4434135e | ||
|
|
747e11d7dd | ||
|
|
3cae728aba | ||
|
|
7f24a5cf82 | ||
|
|
1b8f5f232a | ||
|
|
77d37de18c | ||
|
|
5ea3fb8e1e | ||
|
|
d683aa43d8 | ||
|
|
d4c3501bb8 | ||
|
|
f2229a0007 | ||
|
|
2a06bb6e2c | ||
|
|
a06f890ab9 | ||
|
|
bbe22f95d1 | ||
|
|
631f75a79c | ||
|
|
c121aae8f1 | ||
|
|
fed7629632 | ||
|
|
0825ca736f | ||
|
|
660974c9d1 | ||
|
|
4404b06d2a | ||
|
|
daef69099b | ||
|
|
6362994fd8 | ||
|
|
398cf43782 | ||
|
|
77f8a0f5f6 | ||
|
|
d7e54ccbed | ||
|
|
53a8855696 | ||
|
|
bd16ed1340 | ||
|
|
dd365fe334 | ||
|
|
2a6ba739bc | ||
|
|
a863466f70 | ||
|
|
32f07f4aae | ||
|
|
3ed0e010be | ||
|
|
fb3c0c8138 | ||
|
|
58ded2e0d0 | ||
|
|
369b9a4808 | ||
|
|
0bd57986a9 | ||
|
|
559b88438b | ||
|
|
5d140f7db3 | ||
|
|
7b512ce296 | ||
|
|
ada291c0f6 | ||
|
|
857cb36707 | ||
|
|
4a702e0585 | ||
|
|
eac420f205 | ||
|
|
23d4fa9d9e | ||
|
|
f6523f34d8 | ||
|
|
82971d3ef7 | ||
|
|
8d9a5111a1 | ||
|
|
e8dac0051c | ||
|
|
72802aa125 | ||
|
|
f77a5c23fc | ||
|
|
cf772fcdd6 | ||
|
|
4313c64d9d | ||
|
|
38bf916231 | ||
|
|
cf59c0b854 | ||
|
|
10e192deed | ||
|
|
b3fb6e7822 | ||
|
|
3f640ed7eb | ||
|
|
cc814585ee | ||
|
|
b0d26c8242 | ||
|
|
4133be28c6 | ||
|
|
6e81879436 | ||
|
|
5ea670ece4 | ||
|
|
e8e9702d7e | ||
|
|
4cbdbaabdb | ||
|
|
f332d4f880 | ||
|
|
5ce418cdaf | ||
|
|
81ab2b9cd1 | ||
|
|
c441d76b7b | ||
|
|
fcbc027abc | ||
|
|
8989b69ce8 | ||
|
|
e9a624ab54 | ||
|
|
8a9df89bf6 | ||
|
|
e95d75e01f | ||
|
|
bbe58b07a8 | ||
|
|
7886c9ea27 | ||
|
|
1c072f38bb | ||
|
|
6c2bbdef1f | ||
|
|
a5ebb388a0 | ||
|
|
9c91c700ac | ||
|
|
28b111b669 | ||
|
|
1be6e1f374 | ||
|
|
fff8592b4e | ||
|
|
4af3856d15 | ||
|
|
8a06fb1840 | ||
|
|
e2e2ab62f4 | ||
|
|
e7e3f30fce | ||
|
|
affc45e752 | ||
|
|
d70334ee57 | ||
|
|
1c600c7068 | ||
|
|
7a93f1fc23 | ||
|
|
9c2f7aeb6a | ||
|
|
8af2d17d1f | ||
|
|
65d78eff57 | ||
|
|
8be9e2dc71 | ||
|
|
faecc6913b | ||
|
|
ed90c8868f | ||
|
|
71edce43ca | ||
|
|
4e9ef34f58 | ||
|
|
de55596926 | ||
|
|
316bc422bc | ||
|
|
c73ae3dfb3 | ||
|
|
27b45276ae | ||
|
|
b00852fada | ||
|
|
663f61f4e1 | ||
|
|
110bc64ee4 | ||
|
|
3764e773b3 | ||
|
|
682f0c7984 | ||
|
|
93014bfede | ||
|
|
4dd946bc8a | ||
|
|
2222007516 | ||
|
|
b09e3b0613 | ||
|
|
3a193956ff | ||
|
|
786eedf2f2 | ||
|
|
f217519e97 | ||
|
|
4caaa70726 | ||
|
|
02a27a6974 | ||
|
|
6d7eceb4f1 | ||
|
|
f52e72b026 | ||
|
|
ebeb646e4d | ||
|
|
70c1620a87 | ||
|
|
d45964d0c7 | ||
|
|
e67aa73e75 | ||
|
|
cb2fe3792a | ||
|
|
2b94cfe782 | ||
|
|
a1c99f3e7a | ||
|
|
57fa3ac653 | ||
|
|
01b6e1b88d | ||
|
|
294aca82c4 | ||
|
|
d080e7e7bd | ||
|
|
66a13d4c3a | ||
|
|
87c76ad010 | ||
|
|
822d292e2f | ||
|
|
42155dd11b | ||
|
|
9b1a2d9eaf | ||
|
|
8d0307cedd | ||
|
|
72b38ce712 | ||
|
|
caf8eedd76 | ||
|
|
181b05daf0 | ||
|
|
92b21ac9c2 | ||
|
|
ad12a3f735 | ||
|
|
badca7c20b | ||
|
|
7cdcfd4b1a | ||
|
|
b02af117f8 | ||
|
|
87d269512e | ||
|
|
3346349bba | ||
|
|
280a41806f | ||
|
|
134937082d | ||
|
|
1499994143 | ||
|
|
5805142fd7 | ||
|
|
5fc855e519 | ||
|
|
8c8bf22892 | ||
|
|
ec927e5dd9 | ||
|
|
3a042d8c14 | ||
|
|
fc88d1de85 | ||
|
|
6cf48e9e2b | ||
|
|
db22377a0d | ||
|
|
443cc08229 | ||
|
|
6ad222117d | ||
|
|
b26acad721 | ||
|
|
76e8bfe42f | ||
|
|
1f6704dbda | ||
|
|
33ea4e6225 | ||
|
|
d9cecbde7d | ||
|
|
84fab9ccd3 | ||
|
|
137dfc20fa | ||
|
|
f39e856fee | ||
|
|
e91aabc843 | ||
|
|
f85a99b6f0 | ||
|
|
a59f95317a | ||
|
|
6923000b52 | ||
|
|
83471bdacd | ||
|
|
18045c195a | ||
|
|
b1edadfe3a | ||
|
|
ed5984aa3a | ||
|
|
bfca8b8461 | ||
|
|
63cb0f3577 | ||
|
|
2b49614df9 | ||
|
|
fa439a465d | ||
|
|
11a74c2c05 | ||
|
|
a693efad1e | ||
|
|
75357a2f0a | ||
|
|
a70f5ebc08 | ||
|
|
b161df69e1 | ||
|
|
85a0e75e28 | ||
|
|
56022a9af3 | ||
|
|
5cbcf706e9 | ||
|
|
500b449422 | ||
|
|
8b78388834 | ||
|
|
b44d40d919 | ||
|
|
f8310e0a35 | ||
|
|
59dc0e2cbf | ||
|
|
6a4a7b1a3b | ||
|
|
d62a7999fb | ||
|
|
0ba1a42867 | ||
|
|
68ef49aef5 | ||
|
|
d0a65153df | ||
|
|
ac113b48e7 | ||
|
|
6e14680ac7 | ||
|
|
ba03a533d8 | ||
|
|
9abbecb286 | ||
|
|
9a20ea5c21 | ||
|
|
8ac4b125d2 | ||
|
|
f9b682ad10 | ||
|
|
58959b6114 | ||
|
|
b90405a7d2 | ||
|
|
e0a1613ad9 | ||
|
|
11930ed7a2 | ||
|
|
f3ff1cec54 | ||
|
|
435e73d838 | ||
|
|
2fdea258fa | ||
|
|
b453a6a46d | ||
|
|
5b88e637d8 | ||
|
|
ac02bcbe33 | ||
|
|
9efdeae3ac | ||
|
|
54e59e2f7b | ||
|
|
2c4e02ff34 | ||
|
|
2a306cbd91 | ||
|
|
b244136179 | ||
|
|
b897f367ce | ||
|
|
6c46418f68 | ||
|
|
f0d5d21e64 | ||
|
|
93490876c9 | ||
|
|
74763d2156 | ||
|
|
b849d9862d | ||
|
|
cd575e0ed8 | ||
|
|
b5fbd88c34 | ||
|
|
6003673165 | ||
|
|
4555667554 | ||
|
|
c0db6d49f4 | ||
|
|
6630066f0b | ||
|
|
20e6a55dd1 | ||
|
|
d3f82c800f | ||
|
|
e0e525d9ae | ||
|
|
12f4d6f872 | ||
|
|
0668e9bad9 | ||
|
|
06aed8491c | ||
|
|
df2d11e70d | ||
|
|
2dde8a5e90 | ||
|
|
674b13fb3f | ||
|
|
ab17c3693f | ||
|
|
a6c372de46 | ||
|
|
62497b9300 | ||
|
|
1461a3f8d7 | ||
|
|
686b31765d | ||
|
|
05e4e98e64 | ||
|
|
e95b60d527 | ||
|
|
59aba9f757 | ||
|
|
248e94dc4c | ||
|
|
a7d574cff0 | ||
|
|
ad05193916 | ||
|
|
b24b353b2d | ||
|
|
18e4a04dba | ||
|
|
30989761e2 | ||
|
|
b219ee9049 | ||
|
|
98c611e404 | ||
|
|
7a4ef32210 | ||
|
|
c3359cea1f | ||
|
|
f73a2d571f | ||
|
|
6dfb02c826 | ||
|
|
6c093fc81e | ||
|
|
911d35e800 | ||
|
|
084fdc0a65 | ||
|
|
1382fe9c6c | ||
|
|
b33242830e | ||
|
|
8c0ee33c4c | ||
|
|
e8cf4822b1 | ||
|
|
3462f02ce2 | ||
|
|
1a67b2146a | ||
|
|
eb0d18f484 | ||
|
|
c783fc0f59 | ||
|
|
31d02c1278 | ||
|
|
85f96bb248 | ||
|
|
229cf908b7 | ||
|
|
89b18275c0 | ||
|
|
b8a86baec7 | ||
|
|
8505e9203a | ||
|
|
5d95a503bf | ||
|
|
36c7f96a1e | ||
|
|
b40b606608 | ||
|
|
03764a624f | ||
|
|
962cfa9441 | ||
|
|
b2f30ab080 | ||
|
|
24c42ae2d9 | ||
|
|
af9353298c | ||
|
|
a3ecf0b0bd | ||
|
|
58cb6ab728 | ||
|
|
f478b3959c | ||
|
|
35ce680859 | ||
|
|
7df189ced4 | ||
|
|
c35092504c | ||
|
|
0bff6f7ad9 | ||
|
|
805f985144 | ||
|
|
12e578b93c | ||
|
|
1312952305 | ||
|
|
6118b94f9e | ||
|
|
520320535e | ||
|
|
262b5f1dc0 | ||
|
|
ac36162ddc | ||
|
|
9b813f4ae3 | ||
|
|
35d05b8653 | ||
|
|
e4d6b87e5d | ||
|
|
64b38e5a4a | ||
|
|
75957c84e3 | ||
|
|
c33fb2adbd | ||
|
|
97d3baba35 | ||
|
|
e91f9925f8 | ||
|
|
b484f7aef0 | ||
|
|
9a3904103a | ||
|
|
2a2d39b392 | ||
|
|
3005ba629f | ||
|
|
795741a341 | ||
|
|
da98465d4b | ||
|
|
d28e46796f | ||
|
|
43c6e321f5 | ||
|
|
4595c2feec | ||
|
|
8b4402c517 | ||
|
|
e08ae7e8fa | ||
|
|
753efd8c4a | ||
|
|
cb786f0320 | ||
|
|
6ff64cc984 | ||
|
|
475b816280 | ||
|
|
229005942f | ||
|
|
4af25d20fe | ||
|
|
6bf5b9a8e3 | ||
|
|
be769c28fa | ||
|
|
3128c48d5b | ||
|
|
5c7161fd2f | ||
|
|
e85790b84b | ||
|
|
980e2f67fd | ||
|
|
7781907f0e | ||
|
|
1d145dd48a | ||
|
|
1a1eb30e60 | ||
|
|
a7e2b98dc7 | ||
|
|
2bf74622a5 | ||
|
|
6bcaef9325 | ||
|
|
0b3aac3d91 | ||
|
|
9a53f0f853 | ||
|
|
a97df14064 | ||
|
|
9a0cd1157f | ||
|
|
16c41255d0 | ||
|
|
c2d1e5bd18 | ||
|
|
3c85ba3eb8 | ||
|
|
f3b67b158c | ||
|
|
8dac10ae36 | ||
|
|
6b81050283 | ||
|
|
b4beacfc43 | ||
|
|
1b607a8c4d | ||
|
|
4583c64ff7 | ||
|
|
a06a07d961 | ||
|
|
520a369872 | ||
|
|
1eaec773e2 | ||
|
|
3433a42e42 | ||
|
|
e01eac615d | ||
|
|
8116646dee | ||
|
|
7f7950cd6b | ||
|
|
2eb11ded52 | ||
|
|
bd64ad510b | ||
|
|
4e9b7e61a7 | ||
|
|
37b19495a8 | ||
|
|
c12b412e87 | ||
|
|
17f137f8be | ||
|
|
fcc627c65c | ||
|
|
5bb3d8e60d | ||
|
|
264086e0aa | ||
|
|
6013d7172a | ||
|
|
a7714b2725 | ||
|
|
f9dcac8cd0 | ||
|
|
2487322e47 | ||
|
|
c7e9c9542e | ||
|
|
c1bc1af302 | ||
|
|
739f9ec758 | ||
|
|
f70a140f42 | ||
|
|
a716e69dc0 | ||
|
|
0c6e1a4d56 | ||
|
|
faf36ecba6 | ||
|
|
49f2900e1f | ||
|
|
8bd522d283 | ||
|
|
e9034a1ba1 | ||
|
|
03feacd69a | ||
|
|
0c9f44d8a4 | ||
|
|
39fb64cdcd | ||
|
|
d531a7f1af | ||
|
|
bb7ff414ae | ||
|
|
215f112521 | ||
|
|
644766d965 | ||
|
|
1e1a555d3b | ||
|
|
c64ae2684d | ||
|
|
50ed04436d | ||
|
|
2fb9beca52 | ||
|
|
cd4c1e920e | ||
|
|
e846ac367a | ||
|
|
ef31c733ee | ||
|
|
724aa657f3 | ||
|
|
0284c35f4c | ||
|
|
6ce33de287 | ||
|
|
6ccfa011d4 | ||
|
|
c9078af45e | ||
|
|
6745428d0c | ||
|
|
925e874ada | ||
|
|
03f0f2f803 | ||
|
|
857360d6b2 | ||
|
|
2dd76c3f12 | ||
|
|
666de3a874 | ||
|
|
e0e9b64db6 | ||
|
|
2f521348c6 | ||
|
|
8ac2949a1f | ||
|
|
d0d5d991ce | ||
|
|
1fc2d7de3c | ||
|
|
2598e8d9b9 | ||
|
|
01f65e98e6 | ||
|
|
c5330cf166 | ||
|
|
b78796d0c1 | ||
|
|
da1e9db2c0 | ||
|
|
6beb6aa05b | ||
|
|
6ea7777a3a | ||
|
|
f97191e241 | ||
|
|
51420dade4 | ||
|
|
cc55c01197 | ||
|
|
86ce464ee3 | ||
|
|
0fa52a75ad | ||
|
|
c91e7dc3b0 | ||
|
|
88034b176c | ||
|
|
efeaff488c | ||
|
|
5df30f5bdd | ||
|
|
cf179c42b8 | ||
|
|
a615f8bf17 | ||
|
|
b38964e814 | ||
|
|
013c9eec58 | ||
|
|
ddbd6eddf7 | ||
|
|
982fd42683 | ||
|
|
90e28e7957 | ||
|
|
f4201f3947 | ||
|
|
7844b40243 | ||
|
|
d0839a3d55 | ||
|
|
876fd9ba9e | ||
|
|
e12717c108 | ||
|
|
af0b17bb7a | ||
|
|
6f595b7d87 | ||
|
|
59cbdc79f5 | ||
|
|
50ff3649b1 | ||
|
|
9ca9db8770 | ||
|
|
fa70f0e764 | ||
|
|
3eb629f133 | ||
|
|
c9aba6bbe1 | ||
|
|
0a26adae76 | ||
|
|
f0798f6510 | ||
|
|
245b03e208 | ||
|
|
4e31e5fdc2 | ||
|
|
750a74206c | ||
|
|
7e64dc2576 | ||
|
|
8a08e2fd97 | ||
|
|
d0a933cda8 | ||
|
|
d00845f56b | ||
|
|
3350e5ebb1 | ||
|
|
aeb4445cad | ||
|
|
73abae8cb9 | ||
|
|
7ecc7b76ba | ||
|
|
71d0bbbc25 | ||
|
|
26e691ba93 | ||
|
|
c7352d9e10 | ||
|
|
7b8f9a54ec | ||
|
|
28980af858 | ||
|
|
80dce398e0 | ||
|
|
06db8eec48 | ||
|
|
9c720efe46 | ||
|
|
cbf91a8d19 | ||
|
|
f99414708d | ||
|
|
9549a6b16a | ||
|
|
3206094545 | ||
|
|
5cfae80701 | ||
|
|
b4d140c6bb | ||
|
|
c65eb3c3ee | ||
|
|
eec0984dbe |
30
.github/ISSUE_TEMPLATE/app_bug_report.yaml
vendored
30
.github/ISSUE_TEMPLATE/app_bug_report.yaml
vendored
@@ -12,19 +12,22 @@ body:
|
||||
## Important: Read First
|
||||
|
||||
Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only
|
||||
If you need help configuring the emulator please make a request on our forums or contact us on discord
|
||||
If you need help configuring the emulator please make a request on our forums or contact us on discord.
|
||||
|
||||
If you are unsure, start with [discord](https://discord.com/invite/TCz3t9k) or the [forums](https://forums.pcsx2.net/index.php)
|
||||
If you are unsure, start with [discord](https://discord.com/invite/TCz3t9k) or the [forums](https://forums.pcsx2.net/index.php).
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
### Please Avoid Issues Pertaining to the Following:
|
||||
- We are **not** accepting bug reports for **PSX mode** at this time
|
||||
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use a [proper PSX emulator](https://emulation.gametechwiki.com/index.php/PlayStation_emulators)
|
||||
- We do **not** accept issues relating to **upscaling** at this time
|
||||
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling
|
||||
- Please try your game at native resolution before creating an issue
|
||||
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues
|
||||
- We are **not** accepting bug reports for **PSX mode** at this time.
|
||||
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use [Duckstation](https://github.com/stenzek/duckstation/releases/tag/latest).
|
||||
- We do **not** accept issues relating to **upscaling** at this time.
|
||||
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling.
|
||||
- Please try your game at native resolution before creating an issue.
|
||||
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues.
|
||||
- We do **not** accept issues relating to Widescreen/no-interlace patches at this time.
|
||||
- Any issues pertaining to Widescreen/no-interlace patches please forward them to the [patches repository](https://github.com/PCSX2/pcsx2_patches).
|
||||
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
@@ -76,3 +79,12 @@ body:
|
||||
placeholder: "Example: Arch"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logsDumps
|
||||
attributes:
|
||||
label: "Logs & Dumps"
|
||||
description: |
|
||||
Please feel free to attach any logs here.
|
||||
If PCSX2 crashed, please post crash logs and the .dmp file (in a zip file) if appropriate.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
39
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
39
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -12,19 +12,22 @@ body:
|
||||
## Important: Read First
|
||||
|
||||
Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only
|
||||
If you need help configuring the emulator please make a request on our forums or contact us on discord
|
||||
If you need help configuring the emulator please make a request on our forums or contact us on discord.
|
||||
|
||||
If you are unsure, start with [discord](https://discord.com/invite/TCz3t9k) or the [forums](https://forums.pcsx2.net/index.php)
|
||||
If you are unsure, start with [discord](https://discord.com/invite/TCz3t9k) or the [forums](https://forums.pcsx2.net/index.php).
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
### Please Avoid Issues Pertaining to the Following:
|
||||
- We are **not** accepting bug reports for **PSX mode** at this time
|
||||
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use a [proper PSX emulator](https://emulation.gametechwiki.com/index.php/PlayStation_emulators)
|
||||
- We do **not** accept issues relating to **upscaling** at this time
|
||||
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling
|
||||
- Please try your game at native resolution before creating an issue
|
||||
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues
|
||||
- We are **not** accepting bug reports for **PSX mode** at this time.
|
||||
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use [Duckstation](https://github.com/stenzek/duckstation/releases/tag/latest).
|
||||
- We do **not** accept issues relating to **upscaling** at this time.
|
||||
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling.
|
||||
- Please try your game at native resolution before creating an issue.
|
||||
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues.
|
||||
- We do **not** accept issues relating to Widescreen/no-interlace patches at this time.
|
||||
- Any issues pertaining to Widescreen/no-interlace patches please forward them to the [patches repository](https://github.com/PCSX2/pcsx2_patches).
|
||||
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
@@ -52,13 +55,13 @@ body:
|
||||
## System Info
|
||||
|
||||
Please make sure your system meets our requirements for OS version, CPU and GPU
|
||||
- [System Requirements](https://github.com/PCSX2/pcsx2#system-requirements)
|
||||
- [System Requirements](https://github.com/PCSX2/pcsx2#system-requirements).
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid.
|
||||
|
||||
Please read our known issues pages for AMD and Intel drivers.
|
||||
- [Intel Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-Intel-GPUs-All-you-need-to-know)
|
||||
- [AMD Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-AMD-GPUs---All-you-need-to-know)
|
||||
- [Intel Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-Intel-GPUs-All-you-need-to-know).
|
||||
- [AMD Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-AMD-GPUs---All-you-need-to-know).
|
||||
|
||||
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
|
||||
- type: input
|
||||
@@ -117,11 +120,11 @@ body:
|
||||
attributes:
|
||||
label: Emulation Settings
|
||||
description: |
|
||||
Any non-default core settings. If you don't want to list them out, please provide screenshots of your configuration window
|
||||
Any non-default core settings. If you don't want to list them out, please provide screenshots of your configuration window.
|
||||
|
||||
Please note that the safe preset works for most games. MTVU can have some compatibility issues so please disable it before making a report
|
||||
Please note that the safe preset works for most games. MTVU can have some compatibility issues so please disable it before making a report.
|
||||
|
||||
If you need to modify the settings manually because a game requires you to do so to work, please state that explicitly
|
||||
If you need to modify the settings manually because a game requires you to do so to work, please state that explicitly.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
@@ -136,8 +139,8 @@ body:
|
||||
attributes:
|
||||
label: "Logs & Dumps"
|
||||
description: |
|
||||
Please feel free to attach any logs, block dumps, GSdump, etc here
|
||||
|
||||
Please feel free to attach any logs, block dumps, GSdump, etc here.
|
||||
If PCSX2 crashed, please post crash logs and the .dmp file (in a zip file) if appropriate.
|
||||
If your problem is graphical in nature it is highly recommended that you provide a GSdump. [GSdump Guide](https://forums.pcsx2.net/Thread-How-to-create-a-proper-GS-dump)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -39,8 +39,8 @@
|
||||
'Debugger':
|
||||
- 'pcsx2/DebugTools/*'
|
||||
- 'pcsx2/DebugTools/**/*'
|
||||
- 'pcsx2/gui/Debugger/*'
|
||||
- 'pcsx2/gui/Debugger/**/*'
|
||||
- 'pcsx2-qt/Debugger/*'
|
||||
- 'pcsx2-qt/Debugger/**/*'
|
||||
'IPC':
|
||||
- 'pcsx2/IPC*'
|
||||
- 'pcsx2/**/IPC*'
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
title: "PAD: Update to latest controller database"
|
||||
commit-message: "PAD: Update to latest controller database."
|
||||
|
||||
90
.github/workflows/linux_build_flatpak.yml
vendored
Normal file
90
.github/workflows/linux_build_flatpak.yml
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
name: Flatpak Build Steps
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-22.04
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: x64
|
||||
compiler:
|
||||
required: true
|
||||
type: string
|
||||
cmakeflags:
|
||||
required: true
|
||||
type: string
|
||||
publish:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
detail:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
patches_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
GUI_FRAMEWORK: QT
|
||||
BUILD_SYSTEM: flatpak
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
PR_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: ./.github/workflows/scripts/common/name-artifacts.sh
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
run: .github/workflows/scripts/linux/install-packages-flatpak.sh
|
||||
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
./.github/workflows/scripts/linux/generate-metainfo.sh .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
cat .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
appstream-util validate .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6.1
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
manifest-path: .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
# TODO: Push to flathub
|
||||
8
.github/workflows/linux_build_matrix.yml
vendored
8
.github/workflows/linux_build_matrix.yml
vendored
@@ -18,3 +18,11 @@ jobs:
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
name: "Flatpak"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
|
||||
11
.github/workflows/linux_build_qt.yml
vendored
11
.github/workflows/linux_build_qt.yml
vendored
@@ -28,7 +28,7 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
cheats_url:
|
||||
patches_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
@@ -93,16 +93,19 @@ jobs:
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: .github/workflows/scripts/linux/build-dependencies-qt.sh
|
||||
|
||||
- name: Download cheats
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ inputs.cmakeflags }}
|
||||
run: .github/workflows/scripts/linux/generate-cmake-qt.sh
|
||||
CLANG_PATH: /usr/bin/clang-12
|
||||
CLANGXX_PATH: /usr/bin/clang++-12
|
||||
run: |
|
||||
DEPS_PREFIX="$HOME/deps" .github/workflows/scripts/linux/generate-cmake-qt.sh
|
||||
|
||||
- name: Build PCSX2
|
||||
working-directory: build
|
||||
|
||||
12
.github/workflows/macos_build.yml
vendored
12
.github/workflows/macos_build.yml
vendored
@@ -17,7 +17,7 @@ on:
|
||||
gui:
|
||||
required: true
|
||||
type: string
|
||||
cheats_url:
|
||||
patches_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
@@ -82,10 +82,10 @@ jobs:
|
||||
GUI: ${{ inputs.gui }}
|
||||
run: .github/workflows/scripts/macos/build-dependencies.sh
|
||||
|
||||
- name: Download cheats
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
|
||||
# -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
|
||||
- name: Prepare ccache timestamp
|
||||
@@ -144,12 +144,12 @@ jobs:
|
||||
APPNAME="PCSX2-$TAG"
|
||||
fi
|
||||
mv build/pcsx2*/PCSX2.app "$APPNAME.app"
|
||||
tar cvzf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" "$APPNAME.app"
|
||||
tar --options xz:compression-level=9 -cvJf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" "$APPNAME.app"
|
||||
mkdir ci-artifacts
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" ci-artifacts/macOS-${{ inputs.gui }}.tar.gz
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS-${{ inputs.gui }}.tar.xz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: "*.tar.gz"
|
||||
path: "*.tar.xz"
|
||||
|
||||
33
.github/workflows/release_pipeline.yml
vendored
33
.github/workflows/release_pipeline.yml
vendored
@@ -18,6 +18,16 @@ jobs:
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
build_windows_qt:
|
||||
@@ -28,25 +38,7 @@ jobs:
|
||||
jobName: Qt
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
secrets: inherit
|
||||
|
||||
build_qt_sse4:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows - SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
|
||||
build_qt_avx2:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows - AVX2"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release AVX2
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
@@ -63,10 +55,9 @@ jobs:
|
||||
upload_artifacts:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- build_linux_flatpak
|
||||
- build_linux_qt
|
||||
- build_windows_qt
|
||||
- build_qt_sse4
|
||||
- build_qt_avx2
|
||||
- build_macos_qt
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -30,7 +30,7 @@ fi
|
||||
# Add cmake if used to differentate it from msbuild builds
|
||||
# Else the two artifacts will have the same name and the files will be merged
|
||||
if [[ ! -z "${BUILD_SYSTEM}" ]]; then
|
||||
if [ "${BUILD_SYSTEM}" == "cmake" ]; then
|
||||
if [[ "${BUILD_SYSTEM}" == "cmake" ]] || [[ "${BUILD_SYSTEM}" == "flatpak" ]]; then
|
||||
NAME="${NAME}-${BUILD_SYSTEM}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -87,6 +87,7 @@ declare -a SYSLIBS=(
|
||||
"libvorbis.so.0"
|
||||
"libvorbisenc.so.2"
|
||||
"libxcb.so.1"
|
||||
"libxcb-cursor.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-shm.so.0"
|
||||
"libxkbcommon.so.0"
|
||||
@@ -157,6 +158,7 @@ declare -a SYSLIBS=(
|
||||
"libhx509.so.5"
|
||||
"libsqlite3.so.0"
|
||||
"libcrypt.so.1"
|
||||
"libdbus-1.so.3"
|
||||
)
|
||||
|
||||
declare -a DEPLIBS=(
|
||||
@@ -206,6 +208,9 @@ mkdir "$OUTDIR/usr"
|
||||
echo "Copying binary and resources..."
|
||||
cp -a "$BUILDDIR/bin" "$OUTDIR/usr"
|
||||
|
||||
# Get rid of unit tests, we don't want them bloating the squashfs.
|
||||
rm -fv "$OUTDIR"/usr/bin/*_test
|
||||
|
||||
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
|
||||
echo "Patching RPATH in ${BINARY}..."
|
||||
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
@@ -4,23 +4,26 @@ set -e
|
||||
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.26.0
|
||||
QT=6.3.1
|
||||
SDL=SDL2-2.26.5
|
||||
QT=6.5.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
|
||||
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
|
||||
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
|
||||
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
|
||||
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
|
||||
6f14fea2d172a5b4170be3efcb0e58535f6605b61bcd823f6d5c9d165bb8c0f0 qtwayland-everywhere-src-$QT.tar.xz
|
||||
ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7 $SDL.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
fde1aa7b4fbe64ec1b4fc576a57f4688ad1453d2fab59cbadd948a10a6eaf5ef qtbase-everywhere-src-$QT.tar.xz
|
||||
64ca7e61f44d51e28bcbb4e0509299b53a9a7e38879e00a7fe91643196067a4f qtsvg-everywhere-src-$QT.tar.xz
|
||||
49c33d96b0a44988be954269b8ce3d1a495b439726e03a6be7c0d50a686369c4 qttools-everywhere-src-$QT.tar.xz
|
||||
fc85d0fd8393f518653ccada1014177a56df6e73f30f3b64eea0c2e4a0067a3d qttranslations-everywhere-src-$QT.tar.xz
|
||||
ccc57fa277fc5f1c1c2c4733eae80a60996b67a067233c47809e542aa31759a3 qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
@@ -37,6 +40,14 @@ make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
unzip "$LIBBACKTRACE.zip"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$HOME/deps"
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
||||
# Couple notes:
|
||||
# -fontconfig is needed otherwise Qt Widgets render only boxes.
|
||||
# -qt-doubleconversion avoids a dependency on libdouble-conversion.
|
||||
@@ -65,19 +76,6 @@ cd ../../
|
||||
echo "Building Qt Wayland..."
|
||||
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
|
||||
cd "qtwayland-everywhere-src-$QT"
|
||||
# qtwayland does not build without qml/qtdeclarative in 6.3.1. Work around it.
|
||||
patch -u src/compositor/CMakeLists.txt <<EOF
|
||||
--- src/compositor/CMakeLists.txt 2022-06-08 13:44:30.000000000 +1000
|
||||
+++ src/compositor/CMakeLists.txt 2022-07-17 20:05:25.461881785 +1000
|
||||
@@ -46,7 +46,6 @@
|
||||
global/qtwaylandcompositorglobal.h
|
||||
global/qtwaylandqmlinclude.h
|
||||
global/qwaylandcompositorextension.cpp global/qwaylandcompositorextension.h global/qwaylandcompositorextension_p.h
|
||||
- global/qwaylandquickextension.cpp global/qwaylandquickextension.h
|
||||
global/qwaylandutils_p.h
|
||||
hardware_integration/qwlclientbufferintegration.cpp hardware_integration/qwlclientbufferintegration_p.h
|
||||
wayland_wrapper/qwlbuffermanager.cpp wayland_wrapper/qwlbuffermanager_p.h
|
||||
EOF
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
@@ -103,6 +101,30 @@ patch -u src/linguist/CMakeLists.txt <<EOF
|
||||
add_subdirectory(linguist)
|
||||
endif()
|
||||
EOF
|
||||
|
||||
# Also force disable clang scanning, it gets very confused.
|
||||
patch -u configure.cmake <<EOF
|
||||
--- configure.cmake
|
||||
+++ configure.cmake
|
||||
@@ -14,12 +14,12 @@
|
||||
# Presumably because 6.0 ClangConfig.cmake files are not good enough?
|
||||
# In any case explicitly request a minimum version of 8.x for now, otherwise
|
||||
# building with CMake will fail at compilation time.
|
||||
-qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
+#qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
# special case end
|
||||
|
||||
-if(TARGET WrapLibClang::WrapLibClang)
|
||||
- set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
-endif()
|
||||
+#if(TARGET WrapLibClang::WrapLibClang)
|
||||
+# set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
+#endif()
|
||||
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF ..
|
||||
|
||||
24
.github/workflows/scripts/linux/flatpak/modules/10-libpcap.json
vendored
Normal file
24
.github/workflows/scripts/linux/flatpak/modules/10-libpcap.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "libpcap",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/the-tcpdump-group/libpcap.git",
|
||||
"tag": "libpcap-1.10.4",
|
||||
"commit": "104271ba4a14de6743e43bcf87536786d8fddea4"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin",
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la",
|
||||
"/lib/pkgconfig",
|
||||
"/share/man"
|
||||
]
|
||||
}
|
||||
|
||||
24
.github/workflows/scripts/linux/flatpak/modules/11-libaio.json
vendored
Normal file
24
.github/workflows/scripts/linux/flatpak/modules/11-libaio.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "libaio",
|
||||
"no-autogen": true,
|
||||
"make-install-args": [
|
||||
"prefix=/app"
|
||||
],
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://pagure.io/libaio.git",
|
||||
"tag": "libaio-0.3.113",
|
||||
"commit": "1b18bfafc6a2f7b9fa2c6be77a95afed8b7be448"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la"
|
||||
]
|
||||
}
|
||||
|
||||
25
.github/workflows/scripts/linux/flatpak/modules/12-soundtouch.json
vendored
Normal file
25
.github/workflows/scripts/linux/flatpak/modules/12-soundtouch.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "soundtouch",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/soundtouch/soundtouch.git",
|
||||
"tag": "2.3.2",
|
||||
"commit": "29fba832a7920a04eab956b3990c50e13d8c93f9"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin",
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la",
|
||||
"/lib/cmake",
|
||||
"/lib/pkgconfig",
|
||||
"/share/doc"
|
||||
]
|
||||
}
|
||||
|
||||
45
.github/workflows/scripts/linux/flatpak/modules/20-sdl2.json
vendored
Normal file
45
.github/workflows/scripts/linux/flatpak/modules/20-sdl2.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "sdl2",
|
||||
"buildsystem": "autotools",
|
||||
"no-autogen": true,
|
||||
"config-opts": [
|
||||
"--disable-dbus",
|
||||
"--without-x",
|
||||
"--disable-video-opengl",
|
||||
"--disable-video-opengles",
|
||||
"--disable-video-vulkan",
|
||||
"--disable-wayland-shared",
|
||||
"--disable-ime",
|
||||
"--disable-oss",
|
||||
"--disable-alsa",
|
||||
"--disable-jack",
|
||||
"--disable-esd",
|
||||
"--disable-pipewire",
|
||||
"--disable-pulseaudio",
|
||||
"--disable-arts",
|
||||
"--disable-nas",
|
||||
"--disable-sndio",
|
||||
"--disable-fusionsound",
|
||||
"--disable-diskaudio"
|
||||
],
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL2-2.26.5.tar.gz",
|
||||
"sha256": "ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin",
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la",
|
||||
"/lib/cmake",
|
||||
"/lib/pkgconfig",
|
||||
"/share/aclocal"
|
||||
]
|
||||
}
|
||||
|
||||
22
.github/workflows/scripts/linux/flatpak/modules/21-libbacktrace.json
vendored
Normal file
22
.github/workflows/scripts/linux/flatpak/modules/21-libbacktrace.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "libbacktrace",
|
||||
"buildsystem": "autotools",
|
||||
"no-autogen": true,
|
||||
"build-options": {
|
||||
"strip": false,
|
||||
"no-debuginfo": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ianlancetaylor/libbacktrace.git",
|
||||
"commit": "ad106d5fdd5d960bd33fae1c48a351af567fd075"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la"
|
||||
]
|
||||
}
|
||||
|
||||
67
.github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
vendored
Normal file
67
.github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"app-id": "net.pcsx2.PCSX2",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.5",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm16"
|
||||
],
|
||||
"add-build-extensions": {
|
||||
"org.freedesktop.Platform.ffmpeg-full": {
|
||||
"directory": "lib/ffmpeg",
|
||||
"version": "22.08",
|
||||
"add-ld-path": "."
|
||||
}
|
||||
},
|
||||
"command": "pcsx2-qt",
|
||||
"finish-args": [
|
||||
"--device=all",
|
||||
"--share=network",
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--socket=pulseaudio",
|
||||
"--filesystem=host:ro"
|
||||
],
|
||||
"modules": [
|
||||
"modules/10-libpcap.json",
|
||||
"modules/11-libaio.json",
|
||||
"modules/12-soundtouch.json",
|
||||
"modules/20-sdl2.json",
|
||||
"modules/21-libbacktrace.json",
|
||||
{
|
||||
"name": "pcsx2",
|
||||
"buildsystem": "simple",
|
||||
"build-options": {
|
||||
"strip": false,
|
||||
"no-debuginfo": true,
|
||||
"env": {
|
||||
"DEPS_PREFIX": "/app",
|
||||
"COMPILER": "clang",
|
||||
"CLANG_PATH": "/usr/lib/sdk/llvm16/bin/clang",
|
||||
"CLANGXX_PATH": "/usr/lib/sdk/llvm16/bin/clang++",
|
||||
"ADDITIONAL_CMAKE_ARGS": "-DUSE_LINKED_FFMPEG=ON"
|
||||
}
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "../../../../.."
|
||||
}
|
||||
],
|
||||
"build-commands": [
|
||||
".github/workflows/scripts/linux/generate-cmake-qt.sh",
|
||||
"cd build && ../.github/workflows/scripts/linux/compile.sh && cd ..",
|
||||
"cp -a build/bin ${FLATPAK_DEST}",
|
||||
"cd build && ninja unittests && cd .."
|
||||
],
|
||||
"post-install": [
|
||||
"install -Dm644 bin/resources/icons/AppIconLarge.png ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/net.pcsx2.PCSX2.png",
|
||||
"install -Dm644 .github/workflows/scripts/linux/pcsx2-qt.desktop ${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop",
|
||||
"desktop-file-edit --set-key=Icon --set-value=net.pcsx2.PCSX2 ${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop",
|
||||
"install -Dm644 .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml ${FLATPAK_DEST}/share/metainfo/net.pcsx2.PCSX2.metainfo.xml"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,16 +2,28 @@
|
||||
|
||||
set -e
|
||||
|
||||
if [[ -z "${DEPS_PREFIX}" ]]; then
|
||||
echo "DEPS_PREFIX is not set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using build dependencies from: ${DEPS_PREFIX}"
|
||||
|
||||
if [ "${COMPILER}" = "clang" ]; then
|
||||
if [[ -z "${CLANG_PATH}" ]] || [[ -z "${CLANGXX_PATH}" ]]; then
|
||||
echo "CLANG_PATH or CLANGXX_PATH is not set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Using clang toolchain"
|
||||
cat > "$HOME/clang-toolchain.cmake" << EOF
|
||||
set(CMAKE_C_COMPILER /usr/bin/clang-12)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/clang++-12)
|
||||
cat > "clang-toolchain.cmake" << EOF
|
||||
set(CMAKE_C_COMPILER "${CLANG_PATH}")
|
||||
set(CMAKE_CXX_COMPILER "${CLANGXX_PATH}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
EOF
|
||||
ADDITIONAL_CMAKE_ARGS="$ADDITIONAL_CMAKE_ARGS -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_TOOLCHAIN_FILE=$HOME/clang-toolchain.cmake"
|
||||
ADDITIONAL_CMAKE_ARGS="$ADDITIONAL_CMAKE_ARGS -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_TOOLCHAIN_FILE=clang-toolchain.cmake"
|
||||
fi
|
||||
|
||||
echo "Additional CMake Args - ${ADDITIONAL_CMAKE_ARGS}"
|
||||
@@ -31,7 +43,7 @@ cmake \
|
||||
-DX11_API=ON \
|
||||
-DWAYLAND_API=ON \
|
||||
-DENABLE_SETCAP=OFF \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DCMAKE_PREFIX_PATH="${DEPS_PREFIX}" \
|
||||
-DUSE_SYSTEM_SDL2=ON \
|
||||
-DUSE_SYSTEM_ZSTD=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE
|
||||
|
||||
24
.github/workflows/scripts/linux/generate-metainfo.sh
vendored
Executable file
24
.github/workflows/scripts/linux/generate-metainfo.sh
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Output file must be provided as a parameter"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OUTFILE=$1
|
||||
GIT_DATE=$(git log -1 --pretty=%cd --date=short)
|
||||
GIT_VERSION=$(git tag --points-at HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
|
||||
echo "GIT_DATE: ${GIT_DATE}"
|
||||
echo "GIT_VERSION: ${GIT_VERSION}"
|
||||
|
||||
cp "${SCRIPTDIR}"/pcsx2-qt.metainfo.xml.in "${OUTFILE}"
|
||||
|
||||
sed -i -e "s/@GIT_VERSION@/${GIT_VERSION}/" "${OUTFILE}"
|
||||
sed -i -e "s/@GIT_DATE@/${GIT_DATE}/" "${OUTFILE}"
|
||||
38
.github/workflows/scripts/linux/install-packages-flatpak.sh
vendored
Executable file
38
.github/workflows/scripts/linux/install-packages-flatpak.sh
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
source "$SCRIPTDIR/functions.sh"
|
||||
|
||||
set -e
|
||||
|
||||
ARCH=x86_64
|
||||
KDE_BRANCH=6.5
|
||||
BRANCH=22.08
|
||||
|
||||
# Build packages.
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"flatpak"
|
||||
"flatpak-builder"
|
||||
"appstream-util"
|
||||
)
|
||||
|
||||
# Flatpak runtimes and SDKs.
|
||||
declare -a FLATPAK_PACKAGES=(
|
||||
"org.kde.Platform/${ARCH}/${KDE_BRANCH}"
|
||||
"org.kde.Sdk/${ARCH}/${KDE_BRANCH}"
|
||||
"org.freedesktop.Platform.ffmpeg-full/${ARCH}/${BRANCH}"
|
||||
"org.freedesktop.Sdk.Extension.llvm16/${ARCH}/${BRANCH}"
|
||||
)
|
||||
|
||||
retry_command sudo apt-get -qq update
|
||||
|
||||
# Install packages needed for building
|
||||
echo "Will install the following packages for building - ${BUILD_PACKAGES[*]}"
|
||||
retry_command sudo apt-get -y install "${BUILD_PACKAGES[@]}"
|
||||
|
||||
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
# Install packages needed for building
|
||||
echo "Will install the following packages for building - ${FLATPAK_PACKAGES[*]}"
|
||||
retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
|
||||
|
||||
21
.github/workflows/scripts/linux/pcsx2-qt.metainfo.xml.in
vendored
Normal file
21
.github/workflows/scripts/linux/pcsx2-qt.metainfo.xml.in
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>net.pcsx2.PCSX2</id>
|
||||
<launchable type="desktop-id">net.pcsx2.PCSX2.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<name>PCSX2</name>
|
||||
<developer_name>PCSX2</developer_name>
|
||||
<summary>PlayStation 2 Emulator</summary>
|
||||
<description>
|
||||
<p>PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.</p>
|
||||
<p>PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.</p>
|
||||
</description>
|
||||
<url type="homepage">https://pcsx2.net/</url>
|
||||
<url type="bugtracker">https://github.com/PCSX2/pcsx2/issues</url>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<update_contact>pcsx2_AT_pcsx2.net</update_contact>
|
||||
<releases>
|
||||
<release version="@GIT_VERSION@" date="@GIT_DATE@" />
|
||||
</releases>
|
||||
</component>
|
||||
@@ -6,11 +6,11 @@ export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.26.0
|
||||
SDL=SDL2-2.26.5
|
||||
PNG=1.6.37
|
||||
JPG=9e
|
||||
SOUNDTOUCH=soundtouch-2.3.1
|
||||
QT=6.3.1
|
||||
QT=6.4.3
|
||||
|
||||
mkdir deps-build
|
||||
cd deps-build
|
||||
@@ -21,14 +21,14 @@ export CFLAGS="-I$INSTALLDIR/include -Os $CFLAGS"
|
||||
export CXXFLAGS="-I$INSTALLDIR/include -Os $CXXFLAGS"
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
|
||||
ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7 $SDL.tar.gz
|
||||
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
|
||||
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
|
||||
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
|
||||
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
|
||||
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
|
||||
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
|
||||
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
|
||||
5087c9e5b0165e7bc3c1a4ab176b35d0cd8f52636aea903fa377bdba00891a60 qtbase-everywhere-src-$QT.tar.xz
|
||||
88315f886cf81898705e487cedba6e6160724359d23c518c92c333c098879a4a qtsvg-everywhere-src-$QT.tar.xz
|
||||
867df829cd5cd3ae8efe62e825503123542764b13c96953511e567df70c5a091 qttools-everywhere-src-$QT.tar.xz
|
||||
79e56b7800d49649a8a8010818538c367a829e0b7a09d5f60bd3aecf5abe972c qttranslations-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
|
||||
@@ -4,7 +4,7 @@ import shutil
|
||||
tag = os.environ['TAG'].split("refs/tags/")[1]
|
||||
scan_dir = os.environ['SCAN_DIR']
|
||||
output_dir = os.environ['OUT_DIR']
|
||||
accepted_exts = ["AppImage", "tar.gz", "7z"]
|
||||
accepted_exts = ["AppImage", "flatpak", "tar.xz", "7z"]
|
||||
|
||||
|
||||
for dir_name in os.listdir(scan_dir):
|
||||
@@ -12,7 +12,10 @@ for dir_name in os.listdir(scan_dir):
|
||||
if "macos" in dir_name.lower():
|
||||
asset_name += "-macos"
|
||||
elif "linux" in dir_name.lower():
|
||||
asset_name += "-linux-AppImage-64bit"
|
||||
if "flatpak" in dir_name.lower():
|
||||
asset_name += "-linux-Flatpak-64bit"
|
||||
else:
|
||||
asset_name += "-linux-AppImage-64bit"
|
||||
elif "windows" in dir_name.lower():
|
||||
asset_name += "-windows-64bit"
|
||||
else:
|
||||
|
||||
14
.github/workflows/windows_build_matrix.yml
vendored
14
.github/workflows/windows_build_matrix.yml
vendored
@@ -38,8 +38,8 @@ jobs:
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
build_qt_sse4_cmake:
|
||||
name: "CMake SSE4"
|
||||
build_qt_cmake:
|
||||
name: "CMake"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
@@ -65,3 +65,13 @@ jobs:
|
||||
jobName: Qt Clang
|
||||
configuration: Release Clang AVX2
|
||||
secrets: inherit
|
||||
|
||||
build_qt_cmake_clang:
|
||||
name: "CMake"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DPCSX2_EXE_NAME=pcsx2-qt-clang
|
||||
secrets: inherit
|
||||
|
||||
16
.github/workflows/windows_build_qt.yml
vendored
16
.github/workflows/windows_build_qt.yml
vendored
@@ -25,15 +25,19 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: msbuild
|
||||
cmakeFlags:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
qt_binary_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/2022-11-20/qt-6.4.0-x64.7z
|
||||
default: https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/2023-04-25/qt-6.5.0-x64.7z
|
||||
qt_dir:
|
||||
required: false
|
||||
type: string
|
||||
default: 3rdparty\qt\6.4.0\msvc2022_64
|
||||
cheats_url:
|
||||
default: 3rdparty\qt\6.5.0\msvc2022_64
|
||||
patches_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
@@ -80,11 +84,11 @@ jobs:
|
||||
7z x qt-*-x64.7z
|
||||
del qt-*-x64.7z
|
||||
|
||||
- name: Download cheats
|
||||
- name: Download patches
|
||||
shell: cmd
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
if: inputs.configuration == 'CMake'
|
||||
@@ -92,7 +96,7 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake . -B build "-DCMAKE_PREFIX_PATH=%cd%\${{ inputs.qt_dir }}" -DQT_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DDISABLE_ADVANCE_SIMD=ON -G Ninja
|
||||
cmake . -B build ${{ inputs.cmakeFlags }} "-DCMAKE_PREFIX_PATH=%cd%\${{ inputs.qt_dir }}" -DQT_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DDISABLE_ADVANCE_SIMD=ON -G Ninja
|
||||
|
||||
- name: Build PCSX2
|
||||
shell: cmd
|
||||
|
||||
9
3rdparty/imgui/imgui.vcxproj
vendored
9
3rdparty/imgui/imgui.vcxproj
vendored
@@ -33,14 +33,9 @@
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\glad\include;$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)3rdparty\glad\glad.vcxproj">
|
||||
<Project>{c0293b32-5acf-40f0-aa6c-e6da6f3bf33a}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\imconfig.h" />
|
||||
<ClInclude Include="include\imgui.h" />
|
||||
@@ -60,4 +55,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
2
3rdparty/libchdr/libchdr
vendored
2
3rdparty/libchdr/libchdr
vendored
Submodule 3rdparty/libchdr/libchdr updated: 5de1a59019...fec8ab9421
10
3rdparty/rainterface/CMakeLists.txt
vendored
Normal file
10
3rdparty/rainterface/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
add_library(rainterface
|
||||
RA_Consoles.h
|
||||
RA_Emulators.h
|
||||
RA_Interface.cpp
|
||||
RA_Interface.h
|
||||
)
|
||||
|
||||
target_include_directories(rainterface PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_include_directories(rainterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
2
3rdparty/sdl2/CMakeLists.txt
vendored
2
3rdparty/sdl2/CMakeLists.txt
vendored
@@ -18,7 +18,7 @@ set(SDL_X11 OFF CACHE BOOL "")
|
||||
set(SDL_WAYLAND OFF CACHE BOOL "")
|
||||
set(SDL_RPI OFF CACHE BOOL "")
|
||||
set(SDL_COCOA ON CACHE BOOL "")
|
||||
set(SDL_DIRECTX OFF CACHE BOOL "")
|
||||
set(SDL_DIRECTX ON CACHE BOOL "")
|
||||
set(SDL_WASAPI OFF CACHE BOOL "")
|
||||
set(SDL_RENDER_D3D OFF CACHE BOOL "")
|
||||
set(SDL_RENDER_METAL OFF CACHE BOOL "")
|
||||
|
||||
2
3rdparty/sdl2/SDL
vendored
2
3rdparty/sdl2/SDL
vendored
Submodule 3rdparty/sdl2/SDL updated: 0bfeed061b...ac13ca9ab6
@@ -25,7 +25,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpgd", "3rdparty\jpgd\jpgd.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{4639972E-424E-4E13-8B07-CA403C481346}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2core", "pcsx2\pcsx2core.vcxproj", "{6C7986C4-3E4D-4DCC-B3C6-6BB12B238995}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2\pcsx2.vcxproj", "{6C7986C4-3E4D-4DCC-B3C6-6BB12B238995}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glad", "3rdparty\glad\glad.vcxproj", "{C0293B32-5ACF-40F0-AA6C-E6DA6F3BF33A}"
|
||||
EndProject
|
||||
|
||||
@@ -22,7 +22,7 @@ Installers and binaries for both stable and development builds are available fro
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 20.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/singleThread.html) rating near or greater than 1800 <br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750 Radeon RX 560 Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 20.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
|
||||
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
|
||||
|
||||
@@ -30,16 +30,16 @@ _Note: Recommended Single Thread Performance is based on moderately complex game
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/singleThread.html) rating near or greater than 2600 <br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650 Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
_Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
|
||||
|
||||
### Technical Notes
|
||||
|
||||
- You need the [Visual C++ 2019 x64 Redistributables](https://support.microsoft.com/en-us/help/2977003/) to run PCSX2.
|
||||
- You need the [Visual C++ 2019 x64 Redistributables](https://support.microsoft.com/en-us/help/2977003/) to run PCSX2 on Windows.
|
||||
- Windows XP and Direct3D9 support was dropped after stable release 1.4.0.
|
||||
- Windows 7, Windows 8.0, and Windows 8.1 support was dropped after stable release 1.6.0.
|
||||
- 32-bit and wxwidgets support was dropped after stable release 1.6.0, with the wxwidgets code being removed completely on 25th December 2022.
|
||||
- 32-bit and wxWidgets support was dropped after stable release 1.6.0, with the wxWidgets code being removed completely on 25th December 2022.
|
||||
- Make sure to update your operating system and drivers to ensure you have the best experience possible. Having a newer GPU is also recommended so you have the latest supported drivers.
|
||||
- Because of copyright issues, and the complexity of trying to work around it, you need a BIOS dump extracted from a legitimately-owned PS2 console to use the emulator. For more information about the BIOS and how to get it from your console, visit [this page](pcsx2/Docs/PCSX2_FAQ.md#question-13-where-do-i-get-a-ps2-bios).
|
||||
- PCSX2 uses two CPU cores for emulation by default. A third core can be used via the MTVU speed hack, which is compatible with most games. This can be a significant speedup on CPUs with 3+ cores, but it may be a slowdown on GS-limited games (or on CPUs with fewer than 2 cores). Software renderers will then additionally use however many rendering threads it is set to and will need higher core counts to run efficiently.
|
||||
|
||||
189
bin/docs/PCSX2.1
189
bin/docs/PCSX2.1
@@ -1,189 +0,0 @@
|
||||
.\" Copyright 2002-2017 PCSX2 Dev Team
|
||||
.\"
|
||||
.\" This is free documentation; 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 3 of
|
||||
.\" the License, or (at your option) any later version.
|
||||
.\"
|
||||
.\" The GNU General Public License's references to "object code"
|
||||
.\" and "executables" are to be interpreted as the output of any
|
||||
.\" document formatting or typesetting system, including
|
||||
.\" intermediate and printed output.
|
||||
.\"
|
||||
.\" This manual 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 manual; if not, see
|
||||
.\" http://www.gnu.org/licenses.
|
||||
.Dd January 10, 2017
|
||||
.Dt PCSX2 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm PCSX2
|
||||
.Nd PlayStation(R)2 Console Emulator
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl h
|
||||
.Op Fl \-cfg Ns = Ns Ar file
|
||||
.Op Fl \-cfgpath Ns = Ns Ar path
|
||||
.Op Fl \-console
|
||||
.Op Fl \-forcewiz
|
||||
.Op Fl \-portable
|
||||
.Op Fl \-profiling
|
||||
.Op Fl \-elf Ns = Ns Ar file
|
||||
.Op Fl \-irx Ns = Ns Ar file
|
||||
.Op Fl \-nogui
|
||||
.Op Fl \-noguiprompt
|
||||
.Op Fl \-nodisc
|
||||
.Op Fl \-usecd
|
||||
.Op Fl \-fullscreen
|
||||
.Op Fl \-windowed
|
||||
.Op Fl \-nohacks
|
||||
.Op Fl \-fullboot
|
||||
.Op Fl \-gamefixes Ns = Ns Ar string
|
||||
.Op Fl \-gs Ns = Ns Ar file
|
||||
.Op Fl \-pad Ns = Ns Ar file
|
||||
.Op Fl \-spu2 Ns = Ns Ar file
|
||||
.Op Fl \-cdvd Ns = Ns Ar file
|
||||
.Op Fl \-usb Ns = Ns Ar file
|
||||
.Op Fl \-fw Ns = Ns Ar file
|
||||
.Op Fl \-dev9 Ns = Ns Ar file
|
||||
.Op Ar iso
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is an open-source PlayStation 2 (AKA PS2) emulator.
|
||||
Its purpose is to emulate the PS2 hardware, using a combination of MIPS CPU
|
||||
interpreters, recompilers and a virtual machine that manages hardware states and
|
||||
PS2 memory.
|
||||
This allows you to play PS2 games on your PC, with many additional features and
|
||||
benefits.
|
||||
.Sh GENERAL OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl h , Fl \-help
|
||||
Displays the list of available command line options.
|
||||
.It Fl \-cfg Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
instead of PCSX2_vm.ini as the configuration file.
|
||||
It does not affect plugins.
|
||||
.It Fl \-cfgpath Ns = Ns Ar path
|
||||
Specifies
|
||||
.Ar path
|
||||
as the configuration file path.
|
||||
It affects both
|
||||
.Nm
|
||||
and the plugins.
|
||||
.It Fl \-console
|
||||
Forces the program log to be visible.
|
||||
.It Fl \-forcewiz
|
||||
Forces the First-Time Wizard to run.
|
||||
.It Fl \-portable
|
||||
Runs
|
||||
.Nm
|
||||
in portable mode.
|
||||
.It Fl \-profiling
|
||||
Makes it easier to use profiling tools.
|
||||
.El
|
||||
.Sh AUTO-RUN OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Ar iso
|
||||
Loads and runs
|
||||
.Ar iso
|
||||
at startup using the
|
||||
.Nm
|
||||
internal ISO loader.
|
||||
.It Fl \-elf Ns = Ns Ar file
|
||||
Executes
|
||||
.Ar file
|
||||
as an ELF image.
|
||||
.It Fl \-irx Ns = Ns Ar file
|
||||
Executes
|
||||
.Ar file
|
||||
as an IRX image.
|
||||
.It Fl \-nogui
|
||||
Disables display of the GUI while running games.
|
||||
.Nm
|
||||
will terminate when the game window is closed.
|
||||
.It Fl \-noguiprompt
|
||||
Prompt before exiting when
|
||||
.Fl \-nogui
|
||||
is used.
|
||||
.It Fl \-nodisc
|
||||
Boots with an empty DVD tray.
|
||||
Use this to boot into the PS2 system menu.
|
||||
.It Fl \-usecd
|
||||
Boots using the configured CDVD plugin instead of booting
|
||||
.Ar iso .
|
||||
.It Fl \-fullscreen
|
||||
Runs the game in fullscreen mode.
|
||||
.It Fl \-windowed
|
||||
Runs the game in windowed mode.
|
||||
.El
|
||||
.Sh COMPATIBILITY OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl \-nohacks
|
||||
Disables all speedhacks.
|
||||
.It Fl \-fullboot
|
||||
Disables the fast boot feature.
|
||||
.It Fl \-gamefixes= Ns Ar string
|
||||
Enable specific gamefixes for this session.
|
||||
.Ar string
|
||||
is a comma-separated list of gamefixes.
|
||||
.Pp
|
||||
Valid gamefixes: VuAddSub, VuClipFlag, FpuCompare, FpuMul, FpuNegDiv, XGKick,
|
||||
IpuWait, EETiming, SkipMpeg, OPHFlag, DMABusy,VIFFIFO, VIF1Stall, GIFFIFO,
|
||||
FMVinSoftware, GoemonTlb, ScarfaceIbit.
|
||||
.El
|
||||
.Sh PLUGIN OVERRIDES
|
||||
.Bl -tag -width Ds
|
||||
.It Fl \-gs Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the GS plugin.
|
||||
.It Fl \-pad Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the PAD plugin.
|
||||
.It Fl \-spu2 Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the SPU2 plugin.
|
||||
.It Fl \-cdvd Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the CDVD plugin.
|
||||
.It Fl \-usb Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the USB plugin.
|
||||
.It Fl \-fw Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the FW plugin.
|
||||
.It Fl \-dev9 Ns = Ns Ar file
|
||||
Uses
|
||||
.Ar file
|
||||
as the DEV9 plugin.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
.It $XDG_CONFIG_DIR/PCSX2 or $HOME/PCSX2
|
||||
User configuration and data directory.
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.An PCSX2 Dev Team and many other contributors
|
||||
.Sh BUGS
|
||||
Bugs can be reported by submitting an issue at the
|
||||
.Lk https://github.com/PCSX2/pcsx2/issues "PCSX2 GitHub issue tracker" .
|
||||
.Sh PCSX2 RELATED WEBSITES
|
||||
.Bl -bullet
|
||||
.It
|
||||
.Lk http://github.com/PCSX2/pcsx2 "PCSX2 git repository"
|
||||
.It
|
||||
.Lk http://pcsx2.net "PCSX2 website"
|
||||
.It
|
||||
.Lk http://forums.pcsx2.net "PCSX2 forums"
|
||||
.El
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -66,12 +66,12 @@
|
||||
03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001230000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
@@ -105,6 +105,8 @@
|
||||
03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
|
||||
03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
|
||||
@@ -184,13 +186,14 @@
|
||||
03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
|
||||
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
|
||||
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
|
||||
03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows,
|
||||
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
|
||||
03000000b40400001224000000000000,Flydigi Vader 2 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
|
||||
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
|
||||
03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
|
||||
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
|
||||
03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -302,6 +305,7 @@
|
||||
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
|
||||
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
|
||||
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
|
||||
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
|
||||
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
|
||||
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -374,7 +378,7 @@
|
||||
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
|
||||
030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -446,7 +450,7 @@
|
||||
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows,
|
||||
030000006f0e00000901000000000000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
|
||||
03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
@@ -530,9 +534,11 @@
|
||||
030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
|
||||
030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
|
||||
030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows,
|
||||
030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
|
||||
030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
|
||||
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
|
||||
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
|
||||
030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
|
||||
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
|
||||
030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
|
||||
030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
|
||||
@@ -543,8 +549,9 @@
|
||||
030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows,
|
||||
030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
|
||||
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
|
||||
030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,x:b0,y:b5,back:b2,guide:b10,start:b3,leftshoulder:b6,rightshoulder:b7,dpup:b12,dpleft:b14,dpdown:b13,dpright:b15,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,
|
||||
030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
|
||||
03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a2,righty:a5,start:b17,x:b9,y:b10,platform:Windows,
|
||||
03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -657,6 +664,8 @@
|
||||
03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
|
||||
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
|
||||
03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
|
||||
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -812,6 +821,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
@@ -824,8 +835,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X,
|
||||
030000006f0e00008401000003010000,Faceoff Premiere Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X,
|
||||
03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
|
||||
03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -850,13 +862,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X,
|
||||
030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000000d0f0000aa00000072050000,Hori Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X,
|
||||
03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X,
|
||||
03000000830500006020000000000000,iBuffalo Gamepad,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
|
||||
03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
|
||||
03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
|
||||
03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X,
|
||||
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -888,6 +901,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
|
||||
03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
|
||||
030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X,
|
||||
030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -904,7 +919,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000901000002010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
@@ -947,6 +962,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X,
|
||||
03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000006f0e00008701000005010000,Rock Candy Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X,
|
||||
03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X,
|
||||
03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X,
|
||||
03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,
|
||||
@@ -969,6 +985,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
|
||||
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
|
||||
030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
|
||||
@@ -992,6 +1010,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1067,6 +1086,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
@@ -1124,14 +1145,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
|
||||
030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
|
||||
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1176,6 +1200,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1185,9 +1210,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
|
||||
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
|
||||
03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux,
|
||||
03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
|
||||
03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
|
||||
@@ -1249,28 +1275,31 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux,
|
||||
030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000b050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000dd02000003020000,Microsoft Xbox One 2015,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000dd02000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000005e040000ea02000008040000,Microsoft Xbox One S,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008902000021010000,Microsoft Xbox pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
|
||||
05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
|
||||
@@ -1301,14 +1330,18 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux,
|
||||
030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
|
||||
05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500001920000011810000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
|
||||
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
|
||||
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
|
||||
030000007e0500001720000011810000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
|
||||
05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
|
||||
@@ -1330,9 +1363,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e00008501000011010000,PDP Nintendo Switch Fightpad Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00000901000011010000,PDP Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000666600006706000000010000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
|
||||
030000004c050000da0c000011010000,PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000d9040000160f000000010000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1432,6 +1467,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,
|
||||
03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,
|
||||
03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux,
|
||||
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1477,6 +1513,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,leftshoulder:b4,rightshoulder:b5,x:b3,y:b0,start:b7,platform:Linux,
|
||||
030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
@@ -1502,6 +1540,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1525,14 +1564,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
0000000058626f782047616d65706100,Xbox Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000005e040000120b000009050000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000007050000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1540,16 +1577,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000007050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000130b000007050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
in vec2 PSin_t;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
#elif (FXAA_GLSL_VK == 1)
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
#ifndef PS_SCALE_FACTOR
|
||||
#define PS_SCALE_FACTOR 1
|
||||
#endif
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
float4 p : POSITION;
|
||||
@@ -24,7 +20,6 @@ cbuffer cb0 : register(b0)
|
||||
int EMODA;
|
||||
int EMODC;
|
||||
int DOFFSET;
|
||||
int cb0_pad;
|
||||
};
|
||||
|
||||
static const float3x3 rgb2yuv =
|
||||
@@ -274,16 +269,25 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
uint2 subblock = pos & uint2(7u, 1u);
|
||||
uint2 coord = block | subblock;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uint SBW = uint(EMODA);
|
||||
uint DBW = uint(EMODC);
|
||||
uint2 block_xy = coord / uint2(64, 32);
|
||||
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
|
||||
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 32);
|
||||
coord = (coord % uint2(64, 32)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||
coord = uint2(float2(coord) * PS_SCALE_FACTOR);
|
||||
float ScaleFactor = BGColor.x;
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uint2(float2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= PS_SCALE_FACTOR;
|
||||
coord *= uint(ScaleFactor);
|
||||
|
||||
float4 pixel = Texture.Load(int3(int2(coord), 0));
|
||||
float2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
@@ -295,7 +299,7 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
|
||||
{
|
||||
// Borrowing the YUV constant buffer.
|
||||
float2 scale = BGColor.xy;
|
||||
float scale = BGColor.x;
|
||||
uint2 offset = uint2(uint(EMODA), uint(EMODC)) + uint(DOFFSET);
|
||||
|
||||
// CLUT4 is easy, just two rows of 8x8.
|
||||
@@ -310,7 +314,7 @@ PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
|
||||
|
||||
PS_OUTPUT ps_convert_clut_8(PS_INPUT input)
|
||||
{
|
||||
float2 scale = BGColor.xy;
|
||||
float scale = BGColor.x;
|
||||
uint2 offset = uint2(uint(EMODA), uint(EMODC));
|
||||
uint index = min(uint(input.p.x) + uint(DOFFSET), 255u);
|
||||
|
||||
|
||||
36
bin/resources/shaders/dx11/imgui.fx
Normal file
36
bin/resources/shaders/dx11/imgui.fx
Normal file
@@ -0,0 +1,36 @@
|
||||
cbuffer vertexBuffer : register(b0)
|
||||
{
|
||||
float4x4 ProjectionMatrix;
|
||||
};
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
float2 pos : POSITION;
|
||||
float4 col : COLOR0;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PS_INPUT
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float4 col : COLOR0;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
PS_INPUT vs_main(VS_INPUT input)
|
||||
{
|
||||
PS_INPUT output;
|
||||
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
|
||||
output.col = input.col;
|
||||
output.uv = input.uv;
|
||||
return output;
|
||||
}
|
||||
|
||||
sampler sampler0 : register(s0);
|
||||
Texture2D texture0 : register(t0);
|
||||
|
||||
float4 ps_main(PS_INPUT input) : SV_Target
|
||||
{
|
||||
float4 out_col = input.col * texture0.Sample(sampler0, input.uv);
|
||||
return out_col;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
|
||||
const int vpos = int(input.p.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
return Texture.Sample(Sampler, input.t);
|
||||
return Texture.SampleLevel(Sampler, input.t, 0);
|
||||
else
|
||||
discard;
|
||||
|
||||
@@ -34,7 +34,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
|
||||
// Bob shader
|
||||
float4 ps_main1(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
return Texture.Sample(Sampler, input.t);
|
||||
return Texture.SampleLevel(Sampler, input.t, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
|
||||
float4 ps_main2(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
float2 vstep = float2(0.0f, ZrH.y);
|
||||
float4 c0 = Texture.Sample(Sampler, input.t - vstep);
|
||||
float4 c1 = Texture.Sample(Sampler, input.t);
|
||||
float4 c2 = Texture.Sample(Sampler, input.t + vstep);
|
||||
float4 c0 = Texture.SampleLevel(Sampler, input.t - vstep, 0);
|
||||
float4 c1 = Texture.SampleLevel(Sampler, input.t, 0);
|
||||
float4 c2 = Texture.SampleLevel(Sampler, input.t + vstep, 0);
|
||||
|
||||
return (c0 + c1 * 2 + c2) / 4;
|
||||
}
|
||||
@@ -66,15 +66,11 @@ float4 ps_main3(PS_INPUT input) : SV_Target0
|
||||
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
const int vpos = int(input.p.y) + lofs; // vertical position of destination texture
|
||||
const float2 bofs = float2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
|
||||
const float2 vscale = float2(1.0f, 2.0f); // scaling factor from source to destination texture
|
||||
const float2 optr = input.t - bofs; // used to check if the current destination line is within the current bank
|
||||
const float2 iptr = optr * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
|
||||
return Texture.Sample(Sampler, iptr);
|
||||
if ((vpos & 1) == field)
|
||||
return Texture.SampleLevel(Sampler, input.t, 0);
|
||||
else
|
||||
discard;
|
||||
|
||||
@@ -133,13 +129,13 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
|
||||
|
||||
float4 hn = Texture.Sample(Sampler, p_t0 - lofs); // new high pixel
|
||||
float4 cn = Texture.Sample(Sampler, p_t1); // new center pixel
|
||||
float4 ln = Texture.Sample(Sampler, p_t0 + lofs); // new low pixel
|
||||
float4 hn = Texture.SampleLevel(Sampler, p_t0 - lofs, 0); // new high pixel
|
||||
float4 cn = Texture.SampleLevel(Sampler, p_t1, 0); // new center pixel
|
||||
float4 ln = Texture.SampleLevel(Sampler, p_t0 + lofs, 0); // new low pixel
|
||||
|
||||
float4 ho = Texture.Sample(Sampler, p_t2 - lofs); // old high pixel
|
||||
float4 co = Texture.Sample(Sampler, p_t3); // old center pixel
|
||||
float4 lo = Texture.Sample(Sampler, p_t2 + lofs); // old low pixel
|
||||
float4 ho = Texture.SampleLevel(Sampler, p_t2 - lofs, 0); // old high pixel
|
||||
float4 co = Texture.SampleLevel(Sampler, p_t3, 0); // old center pixel
|
||||
float4 lo = Texture.SampleLevel(Sampler, p_t2 + lofs, 0); // old low pixel
|
||||
|
||||
float3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
float3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
@@ -164,7 +160,7 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
|
||||
if ((vpos & 1) == field)
|
||||
{
|
||||
// output coordinate present on current field
|
||||
return Texture.Sample(Sampler, p_t0);
|
||||
return Texture.SampleLevel(Sampler, p_t0, 0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
|
||||
@@ -29,7 +29,6 @@ cbuffer cb0 : register(b0)
|
||||
float2 u_source_resolution;
|
||||
float2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
float u_time;
|
||||
float3 cb0_pad0;
|
||||
};
|
||||
|
||||
Texture2D Texture;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
#define FMT_32 0
|
||||
#define FMT_24 1
|
||||
#define FMT_16 2
|
||||
@@ -30,21 +28,23 @@
|
||||
#define PS_ATST 1
|
||||
#define PS_FOG 0
|
||||
#define PS_IIP 0
|
||||
#define PS_CLR_HW 0
|
||||
#define PS_BLEND_HW 0
|
||||
#define PS_A_MASKED 0
|
||||
#define PS_FBA 0
|
||||
#define PS_FBMASK 0
|
||||
#define PS_LTF 1
|
||||
#define PS_TCOFFSETHACK 0
|
||||
#define PS_POINT_SAMPLER 0
|
||||
#define PS_REGION_RECT 0
|
||||
#define PS_SHUFFLE 0
|
||||
#define PS_READ_BA 0
|
||||
#define PS_READ16_SRC 0
|
||||
#define PS_DFMT 0
|
||||
#define PS_DEPTH_FMT 0
|
||||
#define PS_PAL_FMT 0
|
||||
#define PS_CHANNEL_FETCH 0
|
||||
#define PS_TALES_OF_ABYSS_HLE 0
|
||||
#define PS_URBAN_CHAOS_HLE 0
|
||||
#define PS_SCALE_FACTOR 1.0
|
||||
#define PS_HDR 0
|
||||
#define PS_COLCLIP 0
|
||||
#define PS_BLEND_A 0
|
||||
@@ -52,6 +52,7 @@
|
||||
#define PS_BLEND_C 0
|
||||
#define PS_BLEND_D 0
|
||||
#define PS_BLEND_MIX 0
|
||||
#define PS_ROUND_INV 0
|
||||
#define PS_FIXED_ONE_A 0
|
||||
#define PS_PABE 0
|
||||
#define PS_DITHER 0
|
||||
@@ -69,6 +70,7 @@
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
@@ -109,6 +111,8 @@ struct PS_INPUT
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef PIXEL_SHADER
|
||||
|
||||
struct PS_OUTPUT
|
||||
{
|
||||
#if !PS_NO_COLOR
|
||||
@@ -132,21 +136,6 @@ Texture2D<float4> RtTexture : register(t2);
|
||||
Texture2D<float> PrimMinTexture : register(t3);
|
||||
SamplerState TextureSampler : register(s0);
|
||||
|
||||
#ifdef DX12
|
||||
cbuffer cb0 : register(b0)
|
||||
#else
|
||||
cbuffer cb0
|
||||
#endif
|
||||
{
|
||||
float2 VertexScale;
|
||||
float2 VertexOffset;
|
||||
float2 TextureScale;
|
||||
float2 TextureOffset;
|
||||
float2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint pad_cb0;
|
||||
};
|
||||
|
||||
#ifdef DX12
|
||||
cbuffer cb1 : register(b1)
|
||||
#else
|
||||
@@ -167,12 +156,16 @@ cbuffer cb1
|
||||
float2 TC_OffsetHack;
|
||||
float2 STScale;
|
||||
float4x4 DitherMatrix;
|
||||
float ScaledScaleFactor;
|
||||
float RcpScaleFactor;
|
||||
};
|
||||
|
||||
float4 sample_c(float2 uv, float uv_w)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(int2(uv * WH.zw), 0));
|
||||
#elif PS_REGION_RECT == 1
|
||||
return Texture.Load(int3(int2(uv), 0));
|
||||
#else
|
||||
if (PS_POINT_SAMPLER)
|
||||
{
|
||||
@@ -236,7 +229,15 @@ float4 clamp_wrap_uv(float4 uv)
|
||||
|
||||
if(PS_WMS == PS_WMT)
|
||||
{
|
||||
if(PS_WMS == 2)
|
||||
if(PS_REGION_RECT != 0 && PS_WMS == 0)
|
||||
{
|
||||
uv = frac(uv);
|
||||
}
|
||||
else if(PS_REGION_RECT != 0 && PS_WMS == 1)
|
||||
{
|
||||
uv = saturate(uv);
|
||||
}
|
||||
else if(PS_WMS == 2)
|
||||
{
|
||||
uv = clamp(uv, MinMax.xyxy, MinMax.zwzw);
|
||||
}
|
||||
@@ -252,7 +253,15 @@ float4 clamp_wrap_uv(float4 uv)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(PS_WMS == 2)
|
||||
if(PS_REGION_RECT != 0 && PS_WMS == 0)
|
||||
{
|
||||
uv.xz = frac(uv.xz);
|
||||
}
|
||||
else if(PS_REGION_RECT != 0 && PS_WMS == 1)
|
||||
{
|
||||
uv.xz = saturate(uv.xz);
|
||||
}
|
||||
else if(PS_WMS == 2)
|
||||
{
|
||||
uv.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
|
||||
}
|
||||
@@ -263,7 +272,15 @@ float4 clamp_wrap_uv(float4 uv)
|
||||
#endif
|
||||
uv.xz = (float2)(((uint2)(uv.xz * tex_size.xx) & asuint(MinMax.xx)) | asuint(MinMax.zz)) / tex_size.xx;
|
||||
}
|
||||
if(PS_WMT == 2)
|
||||
if(PS_REGION_RECT != 0 && PS_WMT == 0)
|
||||
{
|
||||
uv.yw = frac(uv.yw);
|
||||
}
|
||||
else if(PS_REGION_RECT != 0 && PS_WMT == 1)
|
||||
{
|
||||
uv.yw = saturate(uv.yw);
|
||||
}
|
||||
else if(PS_WMT == 2)
|
||||
{
|
||||
uv.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
|
||||
}
|
||||
@@ -276,6 +293,12 @@ float4 clamp_wrap_uv(float4 uv)
|
||||
}
|
||||
}
|
||||
|
||||
if(PS_REGION_RECT != 0)
|
||||
{
|
||||
// Normalized -> Integer Coordinates.
|
||||
uv = clamp(uv * WH.zwzw + STRange.xyxy, STRange.xyxy, STRange.zwzw);
|
||||
}
|
||||
|
||||
return uv;
|
||||
}
|
||||
|
||||
@@ -398,9 +421,13 @@ int2 clamp_wrap_uv_depth(int2 uv)
|
||||
|
||||
float4 sample_depth(float2 st, float2 pos)
|
||||
{
|
||||
float2 uv_f = (float2)clamp_wrap_uv_depth(int2(st)) * (float2)PS_SCALE_FACTOR * (float2)(1.0f / 16.0f);
|
||||
int2 uv = (int2)uv_f;
|
||||
float2 uv_f = (float2)clamp_wrap_uv_depth(int2(st)) * (float2)ScaledScaleFactor;
|
||||
|
||||
#if PS_REGION_RECT == 1
|
||||
uv_f = clamp(uv_f + STRange.xy, STRange.xy, STRange.zw);
|
||||
#endif
|
||||
|
||||
int2 uv = (int2)uv_f;
|
||||
float4 t = (float4)(0.0f);
|
||||
|
||||
if (PS_TALES_OF_ABYSS_HLE == 1)
|
||||
@@ -559,7 +586,7 @@ float4 sample_color(float2 st, float uv_w)
|
||||
float4x4 c;
|
||||
float2 dd;
|
||||
|
||||
if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2)
|
||||
if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_REGION_RECT == 0 && PS_WMS < 2 && PS_WMT < 2)
|
||||
{
|
||||
c[0] = sample_c(st, uv_w);
|
||||
}
|
||||
@@ -738,9 +765,13 @@ void ps_dither(inout float3 C, float2 pos_xy)
|
||||
if (PS_DITHER == 2)
|
||||
fpos = int2(pos_xy);
|
||||
else
|
||||
fpos = int2(pos_xy / (float)PS_SCALE_FACTOR);
|
||||
fpos = int2(pos_xy * RcpScaleFactor);
|
||||
|
||||
C += DitherMatrix[fpos.x & 3][fpos.y & 3];
|
||||
float value = DitherMatrix[fpos.x & 3][fpos.y & 3];
|
||||
if (PS_ROUND_INV)
|
||||
C -= value;
|
||||
else
|
||||
C += value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,6 +781,9 @@ void ps_color_clamp_wrap(inout float3 C)
|
||||
// so we need to limit the color depth on dithered items
|
||||
if (SW_BLEND || PS_DITHER || PS_FBMASK)
|
||||
{
|
||||
if (PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV)
|
||||
C += 7.0f; // Need to round up, not down since the shader will invert
|
||||
|
||||
// Standard Clamp
|
||||
if (PS_COLCLIP == 0 && PS_HDR == 0)
|
||||
C = clamp(C, (float3)0.0f, (float3)255.0f);
|
||||
@@ -762,8 +796,10 @@ void ps_color_clamp_wrap(inout float3 C)
|
||||
}
|
||||
}
|
||||
|
||||
void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
|
||||
void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
||||
{
|
||||
float As = As_rgba.a;
|
||||
|
||||
if (SW_BLEND)
|
||||
{
|
||||
// PABE
|
||||
@@ -787,9 +823,9 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
|
||||
float3 D = (PS_BLEND_D == 0) ? Cs : ((PS_BLEND_D == 1) ? Cd : (float3)0.0f);
|
||||
|
||||
// As/Af clamp alpha for Blend mix
|
||||
// We shouldn't clamp blend mix with clr1 as we want alpha higher
|
||||
// We shouldn't clamp blend mix with blend hw 1 as we want alpha higher
|
||||
float C_clamped = C;
|
||||
if (PS_BLEND_MIX > 0 && PS_CLR_HW != 1)
|
||||
if (PS_BLEND_MIX > 0 && PS_BLEND_HW != 1)
|
||||
C_clamped = min(C_clamped, 1.0f);
|
||||
|
||||
if (PS_BLEND_A == PS_BLEND_B)
|
||||
@@ -808,21 +844,19 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
|
||||
else
|
||||
Color.rgb = trunc(((A - B) * C) + D);
|
||||
|
||||
if (PS_CLR_HW == 1)
|
||||
if (PS_BLEND_HW == 1)
|
||||
{
|
||||
// Replace Af with As so we can do proper compensation for Alpha.
|
||||
if (PS_BLEND_C == 2)
|
||||
As = Af;
|
||||
// As or Af
|
||||
As_rgba.rgb = (float3)C;
|
||||
// Subtract 1 for alpha to compensate for the changed equation,
|
||||
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
|
||||
// we pick the lowest overflow from all colors because it's the safest,
|
||||
// we divide by 255 the color because we don't know Cd value,
|
||||
// changed alpha should only be done for hw blend.
|
||||
float min_color = min(min(Color.r, Color.g), Color.b);
|
||||
float alpha_compensate = max(1.0f, min_color / 255.0f);
|
||||
As -= alpha_compensate;
|
||||
float3 alpha_compensate = max((float3)1.0f, Color.rgb / (float3)255.0f);
|
||||
As_rgba.rgb -= alpha_compensate;
|
||||
}
|
||||
else if (PS_CLR_HW == 2)
|
||||
else if (PS_BLEND_HW == 2)
|
||||
{
|
||||
// Compensate slightly for Cd*(As + 1) - Cs*As.
|
||||
// The initial factor we chose is 1 (0.00392)
|
||||
@@ -832,16 +866,26 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
|
||||
float color_compensate = 1.0f * (C + 1.0f);
|
||||
Color.rgb -= (float3)color_compensate;
|
||||
}
|
||||
else if (PS_BLEND_HW == 3)
|
||||
{
|
||||
// As, Ad or Af clamped.
|
||||
As_rgba.rgb = (float3)C_clamped;
|
||||
// Cs*(Alpha + 1) might overflow, if it does then adjust alpha value
|
||||
// that is sent on second output to compensate.
|
||||
float3 overflow_check = (Color.rgb - (float3)255.0f) / 255.0f;
|
||||
float3 alpha_compensate = max((float3)0.0f, overflow_check);
|
||||
As_rgba.rgb -= alpha_compensate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PS_CLR_HW == 1 || PS_CLR_HW == 5)
|
||||
if (PS_BLEND_HW == 1)
|
||||
{
|
||||
// Needed for Cd * (As/Ad/F + 1) blending modes
|
||||
|
||||
Color.rgb = (float3)255.0f;
|
||||
}
|
||||
else if (PS_CLR_HW == 2 || PS_CLR_HW == 4)
|
||||
else if (PS_BLEND_HW == 2)
|
||||
{
|
||||
// Cd*As,Cd*Ad or Cd*F
|
||||
|
||||
@@ -850,12 +894,16 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
|
||||
Color.rgb = max((float3)0.0f, (Alpha - (float3)1.0f));
|
||||
Color.rgb *= (float3)255.0f;
|
||||
}
|
||||
else if (PS_CLR_HW == 3)
|
||||
else if (PS_BLEND_HW == 3)
|
||||
{
|
||||
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
|
||||
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
|
||||
|
||||
Color.rgb *= (255.0f / 128.0f);
|
||||
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value when rgb are below 128.
|
||||
// When any color channel is higher than 128 then adjust the compensation automatically
|
||||
// to give us more accurate colors, otherwise they will be wrong.
|
||||
// The higher the value (>128) the lower the compensation will be.
|
||||
float max_color = max(max(Color.r, Color.g), Color.b);
|
||||
float color_compensate = 255.0f / max(128.0f, max_color);
|
||||
Color.rgb *= (float3)color_compensate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -877,26 +925,37 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
{
|
||||
uint4 denorm_c = uint4(C);
|
||||
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
|
||||
|
||||
// Mask will take care of the correct destination
|
||||
if (PS_READ_BA)
|
||||
C.rb = C.bb;
|
||||
else
|
||||
C.rb = C.rr;
|
||||
|
||||
if (PS_READ_BA)
|
||||
|
||||
if (PS_READ16_SRC)
|
||||
{
|
||||
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
// Mask will take care of the correct destination
|
||||
if (PS_READ_BA)
|
||||
C.rb = C.bb;
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
C.rb = C.rr;
|
||||
|
||||
if (PS_READ_BA)
|
||||
{
|
||||
if (denorm_c.a & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (denorm_c.g & 0x80u)
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||
else
|
||||
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,15 +967,15 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
C.a = 128.0f;
|
||||
}
|
||||
|
||||
float alpha_blend;
|
||||
if (PS_BLEND_C == 1 && PS_CLR_HW > 3)
|
||||
float4 alpha_blend;
|
||||
if (SW_AD_TO_HW)
|
||||
{
|
||||
float4 RT = trunc(RtTexture.Load(int3(input.p.xy, 0)) * 255.0f + 0.1f);
|
||||
alpha_blend = RT.a / 128.0f;
|
||||
alpha_blend = (float4)(RT.a / 128.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha_blend = C.a / 128.0f;
|
||||
alpha_blend = (float4)(C.a / 128.0f);
|
||||
}
|
||||
|
||||
// Alpha correction
|
||||
@@ -966,12 +1025,12 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
#if !PS_NO_COLOR
|
||||
output.c0 = PS_HDR ? float4(C.rgb / 65535.0f, C.a / 255.0f) : C / 255.0f;
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = (float4)(alpha_blend);
|
||||
output.c1 = alpha_blend;
|
||||
#endif
|
||||
|
||||
#if PS_NO_ABLEND
|
||||
// write alpha blend factor into col0
|
||||
output.c0.a = alpha_blend;
|
||||
output.c0.a = alpha_blend.a;
|
||||
#endif
|
||||
#if PS_ONLY_ALPHA
|
||||
// rgb isn't used
|
||||
@@ -988,10 +1047,29 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif // PIXEL_SHADER
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Vertex Shader
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
#ifdef DX12
|
||||
cbuffer cb0 : register(b0)
|
||||
#else
|
||||
cbuffer cb0
|
||||
#endif
|
||||
{
|
||||
float2 VertexScale;
|
||||
float2 VertexOffset;
|
||||
float2 TextureScale;
|
||||
float2 TextureOffset;
|
||||
float2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint BaseVertex; // Only used in DX11.
|
||||
};
|
||||
|
||||
VS_OUTPUT vs_main(VS_INPUT input)
|
||||
{
|
||||
// Clamp to max depth, gs doesn't wrap
|
||||
@@ -1044,156 +1122,101 @@ VS_OUTPUT vs_main(VS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Geometry Shader
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if VS_EXPAND != 0
|
||||
|
||||
#if GS_FORWARD_PRIMID
|
||||
#define PRIMID_IN , uint primid : SV_PrimitiveID
|
||||
#define VS2PS(x) vs2ps_impl(x, primid)
|
||||
PS_INPUT vs2ps_impl(VS_OUTPUT vs, uint primid)
|
||||
struct VS_RAW_INPUT
|
||||
{
|
||||
PS_INPUT o;
|
||||
o.p = vs.p;
|
||||
o.t = vs.t;
|
||||
o.ti = vs.ti;
|
||||
o.c = vs.c;
|
||||
o.primid = primid;
|
||||
return o;
|
||||
}
|
||||
float2 ST;
|
||||
uint RGBA;
|
||||
float Q;
|
||||
uint XY;
|
||||
uint Z;
|
||||
uint UV;
|
||||
uint FOG;
|
||||
};
|
||||
|
||||
StructuredBuffer<VS_RAW_INPUT> vertices : register(t0);
|
||||
|
||||
VS_INPUT load_vertex(uint index)
|
||||
{
|
||||
#ifdef DX12
|
||||
VS_RAW_INPUT raw = vertices.Load(index);
|
||||
#else
|
||||
#define PRIMID_IN
|
||||
#define VS2PS(x) vs2ps_impl(x)
|
||||
PS_INPUT vs2ps_impl(VS_OUTPUT vs)
|
||||
{
|
||||
PS_INPUT o;
|
||||
o.p = vs.p;
|
||||
o.t = vs.t;
|
||||
o.ti = vs.ti;
|
||||
o.c = vs.c;
|
||||
return o;
|
||||
}
|
||||
VS_RAW_INPUT raw = vertices.Load(BaseVertex + index);
|
||||
#endif
|
||||
|
||||
#if GS_PRIM == 0
|
||||
|
||||
[maxvertexcount(6)]
|
||||
void gs_main(point VS_OUTPUT input[1], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
|
||||
{
|
||||
// Transform a point to a NxN sprite
|
||||
PS_INPUT Point = VS2PS(input[0]);
|
||||
|
||||
// Get new position
|
||||
float4 lt_p = input[0].p;
|
||||
float4 rb_p = input[0].p + float4(PointSize.x, PointSize.y, 0.0f, 0.0f);
|
||||
float4 lb_p = rb_p;
|
||||
float4 rt_p = rb_p;
|
||||
lb_p.x = lt_p.x;
|
||||
rt_p.y = lt_p.y;
|
||||
|
||||
// Triangle 1
|
||||
Point.p = lt_p;
|
||||
stream.Append(Point);
|
||||
|
||||
Point.p = lb_p;
|
||||
stream.Append(Point);
|
||||
|
||||
Point.p = rt_p;
|
||||
stream.Append(Point);
|
||||
|
||||
// Triangle 2
|
||||
Point.p = lb_p;
|
||||
stream.Append(Point);
|
||||
|
||||
Point.p = rt_p;
|
||||
stream.Append(Point);
|
||||
|
||||
Point.p = rb_p;
|
||||
stream.Append(Point);
|
||||
VS_INPUT vert;
|
||||
vert.st = raw.ST;
|
||||
vert.c = uint4(raw.RGBA & 0xFFu, (raw.RGBA >> 8) & 0xFFu, (raw.RGBA >> 16) & 0xFFu, raw.RGBA >> 24);
|
||||
vert.q = raw.Q;
|
||||
vert.p = uint2(raw.XY & 0xFFFFu, raw.XY >> 16);
|
||||
vert.z = raw.Z;
|
||||
vert.uv = uint2(raw.UV & 0xFFFFu, raw.UV >> 16);
|
||||
vert.f = float4(float(raw.FOG & 0xFFu), float((raw.FOG >> 8) & 0xFFu), float((raw.FOG >> 16) & 0xFFu), float(raw.FOG >> 24)) / 255.0f;
|
||||
return vert;
|
||||
}
|
||||
|
||||
#elif GS_PRIM == 1
|
||||
|
||||
[maxvertexcount(6)]
|
||||
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
|
||||
VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
{
|
||||
// Transform a line to a thick line-sprite
|
||||
PS_INPUT left = VS2PS(input[0]);
|
||||
PS_INPUT right = VS2PS(input[1]);
|
||||
float2 lt_p = input[0].p.xy;
|
||||
float2 rt_p = input[1].p.xy;
|
||||
#if VS_EXPAND == 1 // Point
|
||||
|
||||
// Potentially there is faster math
|
||||
float2 line_vector = normalize(rt_p.xy - lt_p.xy);
|
||||
VS_OUTPUT vtx = vs_main(load_vertex(vid >> 2));
|
||||
|
||||
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
|
||||
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
|
||||
|
||||
return vtx;
|
||||
|
||||
#elif VS_EXPAND == 2 // Line
|
||||
|
||||
uint vid_base = vid >> 2;
|
||||
bool is_bottom = vid & 2;
|
||||
bool is_right = vid & 1;
|
||||
// All lines will be a pair of vertices next to each other
|
||||
// Since DirectX uses provoking vertex first, the bottom point will be the lower of the two
|
||||
uint vid_other = is_bottom ? vid_base + 1 : vid_base - 1;
|
||||
VS_OUTPUT vtx = vs_main(load_vertex(vid_base));
|
||||
VS_OUTPUT other = vs_main(load_vertex(vid_other));
|
||||
|
||||
float2 line_vector = normalize(vtx.p.xy - other.p.xy);
|
||||
float2 line_normal = float2(line_vector.y, -line_vector.x);
|
||||
float2 line_width = (line_normal * PointSize) / 2;
|
||||
// line_normal is inverted for bottom point
|
||||
float2 offset = (is_bottom ^ is_right) ? line_width : -line_width;
|
||||
vtx.p.xy += offset;
|
||||
|
||||
lt_p -= line_width;
|
||||
rt_p -= line_width;
|
||||
float2 lb_p = input[0].p.xy + line_width;
|
||||
float2 rb_p = input[1].p.xy + line_width;
|
||||
// Lines will be run as (0 1 2) (1 2 3)
|
||||
// This means that both triangles will have a point based off the top line point as their first point
|
||||
// So we don't have to do anything for !IIP
|
||||
|
||||
#if GS_IIP == 0
|
||||
left.c = right.c;
|
||||
#endif
|
||||
return vtx;
|
||||
|
||||
// Triangle 1
|
||||
left.p.xy = lt_p;
|
||||
stream.Append(left);
|
||||
#elif VS_EXPAND == 3 // Sprite
|
||||
|
||||
left.p.xy = lb_p;
|
||||
stream.Append(left);
|
||||
// Sprite points are always in pairs
|
||||
uint vid_base = vid >> 1;
|
||||
uint vid_lt = vid_base & ~1u;
|
||||
uint vid_rb = vid_base | 1u;
|
||||
|
||||
right.p.xy = rt_p;
|
||||
stream.Append(right);
|
||||
stream.RestartStrip();
|
||||
VS_OUTPUT lt = vs_main(load_vertex(vid_lt));
|
||||
VS_OUTPUT rb = vs_main(load_vertex(vid_rb));
|
||||
VS_OUTPUT vtx = rb;
|
||||
|
||||
// Triangle 2
|
||||
left.p.xy = lb_p;
|
||||
stream.Append(left);
|
||||
bool is_right = ((vid & 1u) != 0u);
|
||||
vtx.p.x = is_right ? lt.p.x : vtx.p.x;
|
||||
vtx.t.x = is_right ? lt.t.x : vtx.t.x;
|
||||
vtx.ti.xz = is_right ? lt.ti.xz : vtx.ti.xz;
|
||||
|
||||
right.p.xy = rt_p;
|
||||
stream.Append(right);
|
||||
bool is_bottom = ((vid & 2u) != 0u);
|
||||
vtx.p.y = is_bottom ? lt.p.y : vtx.p.y;
|
||||
vtx.t.y = is_bottom ? lt.t.y : vtx.t.y;
|
||||
vtx.ti.yw = is_bottom ? lt.ti.yw : vtx.ti.yw;
|
||||
|
||||
right.p.xy = rb_p;
|
||||
stream.Append(right);
|
||||
stream.RestartStrip();
|
||||
}
|
||||
|
||||
#elif GS_PRIM == 3
|
||||
|
||||
[maxvertexcount(4)]
|
||||
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
|
||||
{
|
||||
PS_INPUT lt = VS2PS(input[0]);
|
||||
PS_INPUT rb = VS2PS(input[1]);
|
||||
|
||||
// flat depth
|
||||
lt.p.z = rb.p.z;
|
||||
// flat fog and texture perspective
|
||||
lt.t.zw = rb.t.zw;
|
||||
|
||||
// flat color
|
||||
lt.c = rb.c;
|
||||
|
||||
// Swap texture and position coordinate
|
||||
PS_INPUT lb = rb;
|
||||
lb.p.x = lt.p.x;
|
||||
lb.t.x = lt.t.x;
|
||||
lb.ti.x = lt.ti.x;
|
||||
lb.ti.z = lt.ti.z;
|
||||
|
||||
PS_INPUT rt = rb;
|
||||
rt.p.y = lt.p.y;
|
||||
rt.t.y = lt.t.y;
|
||||
rt.ti.y = lt.ti.y;
|
||||
rt.ti.w = lt.ti.w;
|
||||
|
||||
stream.Append(lt);
|
||||
stream.Append(lb);
|
||||
stream.Append(rt);
|
||||
stream.Append(rb);
|
||||
}
|
||||
return vtx;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // VS_EXPAND
|
||||
|
||||
#endif // VERTEX_SHADER
|
||||
|
||||
@@ -30,7 +30,7 @@ layout(binding=0, rgba8) uniform writeonly image2D imgDst;
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
{
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
return texelFetch(imgSrc, srcOffset + ivec2(p), 0).rgb;
|
||||
}
|
||||
|
||||
// Lets you transform input from the load into a linear color space between 0 and 1. See ffx_cas.h
|
||||
@@ -42,23 +42,23 @@ void CasInput(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
layout(local_size_x=64) in;
|
||||
void main()
|
||||
{
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
// Do remapping of local xy in workgroup for a more PS-like swizzle pattern.
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c;
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
// Filter.
|
||||
AF4 c;
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.y += 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x -= 8u;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Common Interface Definition
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
#if !pGL_ES
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
#if !pGL_ES
|
||||
in gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
} gl_in[];
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_PointSize;
|
||||
#if !pGL_ES
|
||||
float gl_ClipDistance[1];
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Constant Buffer Definition
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Performance note, some drivers (nouveau) will validate all Constant Buffers
|
||||
// even if only one was updated.
|
||||
|
||||
#if defined(VERTEX_SHADER) || defined(GEOMETRY_SHADER)
|
||||
layout(std140, binding = 1) uniform cb20
|
||||
{
|
||||
vec2 VertexScale;
|
||||
vec2 VertexOffset;
|
||||
|
||||
vec2 TextureScale;
|
||||
vec2 TextureOffset;
|
||||
|
||||
vec2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint pad_cb20;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(VERTEX_SHADER) || defined(FRAGMENT_SHADER)
|
||||
layout(std140, binding = 0) uniform cb21
|
||||
{
|
||||
vec3 FogColor;
|
||||
float AREF;
|
||||
|
||||
vec4 WH;
|
||||
|
||||
vec2 TA;
|
||||
float MaxDepthPS;
|
||||
float Af;
|
||||
|
||||
uvec4 FbMask;
|
||||
|
||||
vec4 HalfTexel;
|
||||
|
||||
vec4 MinMax;
|
||||
vec4 STRange;
|
||||
|
||||
ivec4 ChannelShuffle;
|
||||
|
||||
vec2 TC_OffsetHack;
|
||||
vec2 STScale;
|
||||
|
||||
mat4 DitherMatrix;
|
||||
};
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Default Sampler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
#endif
|
||||
@@ -21,10 +21,10 @@ out vec4 PSin_c;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||
PSin_t = TEXCOORD0;
|
||||
PSin_c = COLOR;
|
||||
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -35,6 +35,8 @@ in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
@@ -44,13 +46,13 @@ layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
SV_Target0 = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -65,20 +67,20 @@ void ps_depth_copy()
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
{
|
||||
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
#else
|
||||
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
|
||||
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -86,195 +88,205 @@ void ps_convert_float32_32bits()
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
#if HAS_CLIP_CONTROL
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
#else
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
uint d = uint(sample_c().r * exp2(24.0f));
|
||||
#endif
|
||||
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(c.r | (c.g << 8)) * exp2(-24.0f);
|
||||
return float(c.r | (c.g << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
#if HAS_CLIP_CONTROL
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
#else
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c());
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
ivec2 dims = textureSize(TextureSampler, 0); \
|
||||
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
|
||||
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||
vec2 mix_vals = fract(top_left_f); \
|
||||
float depthTL = CONVERT_FN(texelFetch(TextureSampler, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
ivec2 dims = textureSize(TextureSampler, 0); \
|
||||
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
|
||||
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||
vec2 mix_vals = fract(top_left_f); \
|
||||
float depthTL = CONVERT_FN(texelFetch(TextureSampler, coords.xy, 0)); \
|
||||
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_float32_biln
|
||||
void ps_convert_rgba8_float32_biln()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24_biln
|
||||
void ps_convert_rgba8_float24_biln()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16_biln
|
||||
void ps_convert_rgba8_float16_biln()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16_biln
|
||||
void ps_convert_rgb5a1_float16_biln()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// Convert a RGBA texture into a 8 bits packed texture
|
||||
// Input column: 8x2 RGBA pixels
|
||||
// 0: 8 RGBA
|
||||
// 1: 8 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 8 R | 8 B
|
||||
// 1: 8 R | 8 B
|
||||
// 2: 8 G | 8 A
|
||||
// 3: 8 G | 8 A
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
// Convert a RGBA texture into a 8 bits packed texture
|
||||
// Input column: 8x2 RGBA pixels
|
||||
// 0: 8 RGBA
|
||||
// 1: 8 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 8 R | 8 B
|
||||
// 1: 8 R | 8 B
|
||||
// 2: 8 G | 8 A
|
||||
// 3: 8 G | 8 A
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||
else
|
||||
coord *= uvec2(PS_SCALE_FACTOR);
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
SV_Target0 = vec4(sel1);
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
SV_Target0 = vec4(sel1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_filter_transparency
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
SV_Target0 = vec4(c.rgb, 1.0);
|
||||
vec4 c = sample_c();
|
||||
SV_Target0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -283,8 +295,8 @@ void ps_filter_transparency()
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -293,30 +305,30 @@ void ps_datm1()
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_init
|
||||
void ps_hdr_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_resolve
|
||||
void ps_hdr_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
uniform uvec3 offset;
|
||||
uniform vec2 scale;
|
||||
uniform float scale;
|
||||
|
||||
void ps_convert_clut_4()
|
||||
{
|
||||
@@ -324,14 +336,14 @@ void ps_convert_clut_4()
|
||||
uint index = uint(gl_FragCoord.x) + offset.z;
|
||||
uvec2 pos = uvec2(index % 8u, index / 8u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_8
|
||||
uniform uvec3 offset;
|
||||
uniform vec2 scale;
|
||||
uniform float scale;
|
||||
|
||||
void ps_convert_clut_8()
|
||||
{
|
||||
@@ -344,7 +356,7 @@ void ps_convert_clut_8()
|
||||
pos.x = (index % 8u) + ((subgroup >= 2u) ? 8u : 0u);
|
||||
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -354,51 +366,51 @@ uniform ivec2 EMOD;
|
||||
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o;
|
||||
vec4 i = sample_c();
|
||||
vec4 o;
|
||||
|
||||
mat3 rgb2yuv; // Value from GS manual
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||
mat3 rgb2yuv; // Value from GS manual
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||
|
||||
vec3 yuv = rgb2yuv * i.gbr;
|
||||
vec3 yuv = rgb2yuv * i.gbr;
|
||||
|
||||
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
|
||||
switch(EMOD.x) {
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
o.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
o.a = Y/2.0f;
|
||||
break;
|
||||
case 3:
|
||||
o.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
switch(EMOD.x) {
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
o.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
o.a = Y/2.0f;
|
||||
break;
|
||||
case 3:
|
||||
o.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(EMOD.y) {
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
o.rgb = vec3(Y);
|
||||
break;
|
||||
case 2:
|
||||
o.rgb = vec3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
o.rgb = vec3(i.a);
|
||||
break;
|
||||
}
|
||||
switch(EMOD.y) {
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
o.rgb = vec3(Y);
|
||||
break;
|
||||
case 2:
|
||||
o.rgb = vec3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
o.rgb = vec3(i.a);
|
||||
break;
|
||||
}
|
||||
|
||||
SV_Target0 = o;
|
||||
SV_Target0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -406,16 +418,16 @@ void ps_yuv()
|
||||
|
||||
void main()
|
||||
{
|
||||
SV_Target0 = vec4(0x7FFFFFFF);
|
||||
SV_Target0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
35
bin/resources/shaders/opengl/imgui.glsl
Normal file
35
bin/resources/shaders/opengl/imgui.glsl
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
uniform mat4 ProjMtx;
|
||||
|
||||
out vec2 Frag_UV;
|
||||
out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
in vec2 Frag_UV;
|
||||
in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,8 @@ in vec4 PSin_c;
|
||||
|
||||
uniform vec4 ZrH;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
|
||||
@@ -19,7 +21,7 @@ void ps_main0()
|
||||
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
@@ -28,7 +30,7 @@ void ps_main0()
|
||||
// Bob shader
|
||||
void ps_main1()
|
||||
{
|
||||
SV_Target0 = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +38,9 @@ void ps_main1()
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = texture(TextureSampler, PSin_t - vstep);
|
||||
vec4 c1 = texture(TextureSampler, PSin_t);
|
||||
vec4 c2 = texture(TextureSampler, PSin_t + vstep);
|
||||
vec4 c0 = textureLod(TextureSampler, PSin_t - vstep, 0);
|
||||
vec4 c1 = textureLod(TextureSampler, PSin_t, 0);
|
||||
vec4 c2 = textureLod(TextureSampler, PSin_t + vstep, 0);
|
||||
|
||||
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
@@ -60,15 +62,11 @@ void ps_main3()
|
||||
int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
vec2 bofs = vec2(0.0f, 0.5f * float(bank)); // vertical offset of the current bank relative to source texture size
|
||||
vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
|
||||
vec2 optr = PSin_t - bofs; // used to check if the current destination line is within the current bank
|
||||
vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
|
||||
SV_Target0 = texture(TextureSampler, iptr);
|
||||
if ((vpos & 1) == field)
|
||||
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
@@ -126,13 +124,13 @@ void ps_main4()
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed
|
||||
// by p_t1
|
||||
|
||||
vec4 hn = texture(TextureSampler, p_t0 - lofs); // new high pixel
|
||||
vec4 cn = texture(TextureSampler, p_t1); // new center pixel
|
||||
vec4 ln = texture(TextureSampler, p_t0 + lofs); // new low pixel
|
||||
vec4 hn = textureLod(TextureSampler, p_t0 - lofs, 0); // new high pixel
|
||||
vec4 cn = textureLod(TextureSampler, p_t1, 0); // new center pixel
|
||||
vec4 ln = textureLod(TextureSampler, p_t0 + lofs, 0); // new low pixel
|
||||
|
||||
vec4 ho = texture(TextureSampler, p_t2 - lofs); // old high pixel
|
||||
vec4 co = texture(TextureSampler, p_t3); // old center pixel
|
||||
vec4 lo = texture(TextureSampler, p_t2 + lofs); // old low pixel
|
||||
vec4 ho = textureLod(TextureSampler, p_t2 - lofs, 0); // old high pixel
|
||||
vec4 co = textureLod(TextureSampler, p_t3, 0); // old center pixel
|
||||
vec4 lo = textureLod(TextureSampler, p_t2 + lofs, 0); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
@@ -158,7 +156,7 @@ void ps_main4()
|
||||
if ((vpos & 1) == field)
|
||||
{
|
||||
// output coordinate present on current field
|
||||
SV_Target0 = texture(TextureSampler, p_t0);
|
||||
SV_Target0 = textureLod(TextureSampler, p_t0, 0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
|
||||
@@ -8,21 +8,23 @@ in vec4 PSin_c;
|
||||
|
||||
uniform vec4 BGColor;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
void ps_main0()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
SV_Target0 = c;
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
// Note: clamping will be done by fixed unit
|
||||
c.a *= 2.0f;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
void ps_main1()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
c.a = BGColor.a;
|
||||
SV_Target0 = c;
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
c.a = BGColor.a;
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,12 +40,13 @@ uniform vec2 u_rcp_target_resolution; // 1 / u_target_resolution
|
||||
uniform vec2 u_source_resolution;
|
||||
uniform vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
uniform float u_time;
|
||||
uniform vec3 cb0_pad0;
|
||||
|
||||
in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
vec4 sample_c()
|
||||
@@ -117,10 +118,10 @@ void ps_filter_triangular() // triangular
|
||||
#ifdef ps_filter_complex
|
||||
void ps_filter_complex()
|
||||
{
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(TextureSampler, 0));
|
||||
float factor = (0.9f - 0.4f * cos(2.0f * PI * PSin_t.y * texdim.y));
|
||||
vec4 c = factor * texture(TextureSampler, vec2(PSin_t.x, (floor(PSin_t.y * texdim.y) + 0.5f) / texdim.y));
|
||||
const float PI = 3.14159265359f;
|
||||
vec2 texdim = vec2(textureSize(TextureSampler, 0));
|
||||
float factor = (0.9f - 0.4f * cos(2.0f * PI * PSin_t.y * texdim.y));
|
||||
vec4 c = factor * texture(TextureSampler, vec2(PSin_t.x, (floor(PSin_t.y * texdim.y) + 0.5f) / texdim.y));
|
||||
|
||||
SV_Target0 = c;
|
||||
}
|
||||
|
||||
@@ -17,38 +17,40 @@ in vec4 PSin_p;
|
||||
in vec2 PSin_t;
|
||||
in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec4 ContrastSaturationBrightness(vec4 color)
|
||||
{
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color.rgb * brt;
|
||||
float dot_intensity = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(dot_intensity, dot_intensity, dot_intensity);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
return color;
|
||||
color.rgb = conColor;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = ContrastSaturationBrightness(c);
|
||||
vec4 c = texture(TextureSampler, PSin_t);
|
||||
SV_Target0 = ContrastSaturationBrightness(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,35 @@
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
layout(std140, binding = 1) uniform cb20
|
||||
{
|
||||
vec2 VertexScale;
|
||||
vec2 VertexOffset;
|
||||
|
||||
vec2 TextureScale;
|
||||
vec2 TextureOffset;
|
||||
|
||||
vec2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint pad_cb20;
|
||||
};
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
out SHADER
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
#if VS_IIP != 0
|
||||
vec4 c;
|
||||
#else
|
||||
flat vec4 c;
|
||||
#endif
|
||||
} VSout;
|
||||
|
||||
const float exp_min32 = exp2(-32.0f);
|
||||
|
||||
#if VS_EXPAND == 0
|
||||
|
||||
layout(location = 0) in vec2 i_st;
|
||||
layout(location = 2) in vec4 i_c;
|
||||
layout(location = 3) in float i_q;
|
||||
@@ -9,241 +38,202 @@ layout(location = 5) in uint i_z;
|
||||
layout(location = 6) in uvec2 i_uv;
|
||||
layout(location = 7) in vec4 i_f;
|
||||
|
||||
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
|
||||
layout(location = 0)
|
||||
#endif
|
||||
out SHADER
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
#if VS_IIP != 0
|
||||
vec4 c;
|
||||
#else
|
||||
flat vec4 c;
|
||||
#endif
|
||||
} VSout;
|
||||
|
||||
const float exp_min32 = exp2(-32.0f);
|
||||
|
||||
void texture_coord()
|
||||
{
|
||||
vec2 uv = vec2(i_uv) - TextureOffset;
|
||||
vec2 st = i_st - TextureOffset;
|
||||
vec2 uv = vec2(i_uv) - TextureOffset;
|
||||
vec2 st = i_st - TextureOffset;
|
||||
|
||||
// Float coordinate
|
||||
VSout.t_float.xy = st;
|
||||
VSout.t_float.w = i_q;
|
||||
// Float coordinate
|
||||
VSout.t_float.xy = st;
|
||||
VSout.t_float.w = i_q;
|
||||
|
||||
// Integer coordinate => normalized
|
||||
VSout.t_int.xy = uv * TextureScale;
|
||||
#if VS_INT_FST == 1
|
||||
// Some games uses float coordinate for post-processing effect
|
||||
VSout.t_int.zw = st / TextureScale;
|
||||
// Integer coordinate => normalized
|
||||
VSout.t_int.xy = uv * TextureScale;
|
||||
#if VS_FST
|
||||
// Integer coordinate => integral
|
||||
VSout.t_int.zw = uv;
|
||||
#else
|
||||
// Integer coordinate => integral
|
||||
VSout.t_int.zw = uv;
|
||||
// Some games uses float coordinate for post-processing effect
|
||||
VSout.t_int.zw = st / TextureScale;
|
||||
#endif
|
||||
}
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
// Clamp to max depth, gs doesn't wrap
|
||||
highp uint z = min(i_z, MaxDepth);
|
||||
// Clamp to max depth, gs doesn't wrap
|
||||
highp uint z = min(i_z, MaxDepth);
|
||||
|
||||
// pos -= 0.05 (1/320 pixel) helps avoiding rounding problems (integral part of pos is usually 5 digits, 0.05 is about as low as we can go)
|
||||
// example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty
|
||||
// input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel
|
||||
// example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133
|
||||
vec4 p;
|
||||
// pos -= 0.05 (1/320 pixel) helps avoiding rounding problems (integral part of pos is usually 5 digits, 0.05 is about as low as we can go)
|
||||
// example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty
|
||||
// input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel
|
||||
// example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133
|
||||
vec4 p;
|
||||
|
||||
p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
|
||||
p.xy = p.xy * VertexScale - VertexOffset;
|
||||
p.w = 1.0f;
|
||||
p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
|
||||
p.xy = p.xy * VertexScale - VertexOffset;
|
||||
p.w = 1.0f;
|
||||
|
||||
#if HAS_CLIP_CONTROL
|
||||
p.z = float(z) * exp_min32;
|
||||
p.z = float(z) * exp_min32;
|
||||
#else
|
||||
// GLES doesn't support ARB_clip_control, so remap it to -1..1. We also reduce the range from 32 bits
|
||||
// to 24 bits, which means some games with very large depth ranges will not render correctly. But,
|
||||
// for most, it's okay, and really, the best we can do.
|
||||
p.z = min(float(z) * exp2(-23.0f), 2.0f) - 1.0f;
|
||||
// GLES doesn't support ARB_clip_control, so remap it to -1..1. We also reduce the range from 32 bits
|
||||
// to 24 bits, which means some games with very large depth ranges will not render correctly. But,
|
||||
// for most, it's okay, and really, the best we can do.
|
||||
p.z = min(float(z) * exp2(-23.0f), 2.0f) - 1.0f;
|
||||
#endif
|
||||
|
||||
gl_Position = p;
|
||||
gl_Position = p;
|
||||
|
||||
texture_coord();
|
||||
texture_coord();
|
||||
|
||||
VSout.c = i_c;
|
||||
VSout.t_float.z = i_f.x; // pack for with texture
|
||||
VSout.c = i_c;
|
||||
VSout.t_float.z = i_f.x; // pack for with texture
|
||||
|
||||
#if VS_POINT_SIZE
|
||||
gl_PointSize = float(VS_POINT_SIZE_VALUE);
|
||||
#endif
|
||||
#if VS_POINT_SIZE
|
||||
gl_PointSize = PointSize.x;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#else // VS_EXPAND
|
||||
|
||||
#ifdef GEOMETRY_SHADER
|
||||
|
||||
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
|
||||
layout(location = 0)
|
||||
#endif
|
||||
in SHADER
|
||||
struct RawVertex
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
#if GS_IIP != 0
|
||||
vec4 c;
|
||||
#else
|
||||
flat vec4 c;
|
||||
#endif
|
||||
} GSin[];
|
||||
|
||||
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
|
||||
layout(location = 0)
|
||||
#endif
|
||||
out SHADER
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
#if GS_IIP != 0
|
||||
vec4 c;
|
||||
#else
|
||||
flat vec4 c;
|
||||
#endif
|
||||
} GSout;
|
||||
|
||||
struct vertex
|
||||
{
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
vec2 ST;
|
||||
uint RGBA;
|
||||
float Q;
|
||||
uint XY;
|
||||
uint Z;
|
||||
uint UV;
|
||||
uint FOG;
|
||||
};
|
||||
|
||||
void out_vertex(in vec4 position, in vertex v)
|
||||
layout(std140, binding = 2) readonly buffer VertexBuffer {
|
||||
RawVertex vertex_buffer[];
|
||||
};
|
||||
|
||||
struct ProcessedVertex
|
||||
{
|
||||
GSout.t_float = v.t_float;
|
||||
GSout.t_int = v.t_int;
|
||||
// Flat output
|
||||
#if GS_POINT == 1
|
||||
GSout.c = GSin[0].c;
|
||||
vec4 p;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
};
|
||||
|
||||
ProcessedVertex load_vertex(uint index)
|
||||
{
|
||||
#if defined(GL_ARB_shader_draw_parameters) && GL_ARB_shader_draw_parameters
|
||||
RawVertex rvtx = vertex_buffer[index + gl_BaseVertexARB];
|
||||
#else
|
||||
GSout.c = GSin[1].c;
|
||||
RawVertex rvtx = vertex_buffer[index];
|
||||
#endif
|
||||
gl_Position = position;
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
#if GS_POINT == 1
|
||||
layout(points) in;
|
||||
vec2 i_st = rvtx.ST;
|
||||
vec4 i_c = vec4(uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
|
||||
bitfieldExtract(rvtx.RGBA, 16, 8), bitfieldExtract(rvtx.RGBA, 24, 8)));
|
||||
float i_q = rvtx.Q;
|
||||
uvec2 i_p = uvec2(bitfieldExtract(rvtx.XY, 0, 16), bitfieldExtract(rvtx.XY, 16, 16));
|
||||
uint i_z = rvtx.Z;
|
||||
uvec2 i_uv = uvec2(bitfieldExtract(rvtx.UV, 0, 16), bitfieldExtract(rvtx.UV, 16, 16));
|
||||
vec4 i_f = unpackUnorm4x8(rvtx.FOG);
|
||||
|
||||
ProcessedVertex vtx;
|
||||
|
||||
uint z = min(i_z, MaxDepth);
|
||||
vtx.p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
|
||||
vtx.p.xy = vtx.p.xy * VertexScale - VertexOffset;
|
||||
vtx.p.w = 1.0f;
|
||||
|
||||
#if HAS_CLIP_CONTROL
|
||||
vtx.p.z = float(z) * exp_min32;
|
||||
#else
|
||||
layout(lines) in;
|
||||
vtx.p.z = min(float(z) * exp2(-23.0f), 2.0f) - 1.0f;
|
||||
#endif
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#if GS_POINT == 1
|
||||
vec2 uv = vec2(i_uv) - TextureOffset;
|
||||
vec2 st = i_st - TextureOffset;
|
||||
|
||||
void gs_main()
|
||||
{
|
||||
// Transform a point to a NxN sprite
|
||||
vertex point = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
|
||||
|
||||
// Get new position
|
||||
vec4 lt_p = gl_in[0].gl_Position;
|
||||
vec4 rb_p = gl_in[0].gl_Position + vec4(PointSize.x, PointSize.y, 0.0f, 0.0f);
|
||||
vec4 lb_p = rb_p;
|
||||
vec4 rt_p = rb_p;
|
||||
lb_p.x = lt_p.x;
|
||||
rt_p.y = lt_p.y;
|
||||
|
||||
out_vertex(lt_p, point);
|
||||
|
||||
out_vertex(lb_p, point);
|
||||
|
||||
out_vertex(rt_p, point);
|
||||
|
||||
out_vertex(rb_p, point);
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#elif GS_LINE == 1
|
||||
|
||||
void gs_main()
|
||||
{
|
||||
// Transform a line to a thick line-sprite
|
||||
vertex left = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
|
||||
vertex right = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);
|
||||
vec4 lt_p = gl_in[0].gl_Position;
|
||||
vec4 rt_p = gl_in[1].gl_Position;
|
||||
|
||||
// Potentially there is faster math
|
||||
vec2 line_vector = normalize(rt_p.xy - lt_p.xy);
|
||||
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
|
||||
vec2 line_width = (line_normal * PointSize) / 2.0f;
|
||||
|
||||
lt_p.xy -= line_width;
|
||||
rt_p.xy -= line_width;
|
||||
vec4 lb_p = gl_in[0].gl_Position + vec4(line_width, 0.0f, 0.0f);
|
||||
vec4 rb_p = gl_in[1].gl_Position + vec4(line_width, 0.0f, 0.0f);
|
||||
|
||||
out_vertex(lt_p, left);
|
||||
|
||||
out_vertex(lb_p, left);
|
||||
|
||||
out_vertex(rt_p, right);
|
||||
|
||||
out_vertex(rb_p, right);
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
vtx.t_float.xy = st;
|
||||
vtx.t_float.w = i_q;
|
||||
|
||||
vtx.t_int.xy = uv * TextureScale;
|
||||
#if VS_FST
|
||||
vtx.t_int.zw = uv;
|
||||
#else
|
||||
vtx.t_int.zw = st / TextureScale;
|
||||
#endif
|
||||
|
||||
void gs_main()
|
||||
{
|
||||
// left top => GSin[0];
|
||||
// right bottom => GSin[1];
|
||||
vertex rb = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);
|
||||
vertex lt = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
|
||||
vtx.c = i_c;
|
||||
vtx.t_float.z = i_f.x;
|
||||
|
||||
vec4 rb_p = gl_in[1].gl_Position;
|
||||
vec4 lb_p = rb_p;
|
||||
vec4 rt_p = rb_p;
|
||||
vec4 lt_p = gl_in[0].gl_Position;
|
||||
|
||||
// flat depth
|
||||
lt_p.z = rb_p.z;
|
||||
// flat fog and texture perspective
|
||||
lt.t_float.zw = rb.t_float.zw;
|
||||
// flat color
|
||||
lt.c = rb.c;
|
||||
|
||||
// Swap texture and position coordinate
|
||||
vertex lb = rb;
|
||||
lb.t_float.x = lt.t_float.x;
|
||||
lb.t_int.x = lt.t_int.x;
|
||||
lb.t_int.z = lt.t_int.z;
|
||||
lb_p.x = lt_p.x;
|
||||
|
||||
vertex rt = rb;
|
||||
rt_p.y = lt_p.y;
|
||||
rt.t_float.y = lt.t_float.y;
|
||||
rt.t_int.y = lt.t_int.y;
|
||||
rt.t_int.w = lt.t_int.w;
|
||||
|
||||
out_vertex(lt_p, lt);
|
||||
|
||||
out_vertex(lb_p, lb);
|
||||
|
||||
out_vertex(rt_p, rt);
|
||||
|
||||
out_vertex(rb_p, rb);
|
||||
|
||||
EndPrimitive();
|
||||
return vtx;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ProcessedVertex vtx;
|
||||
|
||||
#if defined(GL_ARB_shader_draw_parameters) && GL_ARB_shader_draw_parameters
|
||||
uint vid = uint(gl_VertexID - gl_BaseVertexARB);
|
||||
#else
|
||||
uint vid = uint(gl_VertexID);
|
||||
#endif
|
||||
|
||||
#if VS_EXPAND == 1 // Point
|
||||
|
||||
vtx = load_vertex(vid >> 2);
|
||||
|
||||
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
|
||||
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
|
||||
|
||||
#elif VS_EXPAND == 2 // Line
|
||||
|
||||
uint vid_base = vid >> 2;
|
||||
bool is_bottom = (vid & 2u) != 0u;
|
||||
bool is_right = (vid & 1u) != 0u;
|
||||
uint vid_other = is_bottom ? vid_base - 1 : vid_base + 1;
|
||||
vtx = load_vertex(vid_base);
|
||||
ProcessedVertex other = load_vertex(vid_other);
|
||||
|
||||
vec2 line_vector = normalize(vtx.p.xy - other.p.xy);
|
||||
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
|
||||
vec2 line_width = (line_normal * PointSize) / 2;
|
||||
// line_normal is inverted for bottom point
|
||||
vec2 offset = ((uint(is_bottom) ^ uint(is_right)) != 0u) ? line_width : -line_width;
|
||||
vtx.p.xy += offset;
|
||||
|
||||
// Lines will be run as (0 1 2) (1 2 3)
|
||||
// This means that both triangles will have a point based off the top line point as their first point
|
||||
// So we don't have to do anything for !IIP
|
||||
|
||||
#elif VS_EXPAND == 3 // Sprite
|
||||
|
||||
// Sprite points are always in pairs
|
||||
uint vid_base = vid >> 1;
|
||||
uint vid_lt = vid_base & ~1u;
|
||||
uint vid_rb = vid_base | 1u;
|
||||
|
||||
ProcessedVertex lt = load_vertex(vid_lt);
|
||||
ProcessedVertex rb = load_vertex(vid_rb);
|
||||
vtx = rb;
|
||||
|
||||
bool is_right = ((vid & 1u) != 0u);
|
||||
vtx.p.x = is_right ? lt.p.x : vtx.p.x;
|
||||
vtx.t_float.x = is_right ? lt.t_float.x : vtx.t_float.x;
|
||||
vtx.t_int.xz = is_right ? lt.t_int.xz : vtx.t_int.xz;
|
||||
|
||||
bool is_bottom = ((vid & 2u) != 0u);
|
||||
vtx.p.y = is_bottom ? lt.p.y : vtx.p.y;
|
||||
vtx.t_float.y = is_bottom ? lt.t_float.y : vtx.t_float.y;
|
||||
vtx.t_int.yw = is_bottom ? lt.t_int.yw : vtx.t_int.yw;
|
||||
|
||||
#endif
|
||||
|
||||
gl_Position = vtx.p;
|
||||
VSout.t_float = vtx.t_float;
|
||||
VSout.t_int = vtx.t_int;
|
||||
VSout.c = vtx.c;
|
||||
}
|
||||
|
||||
#endif // VS_EXPAND
|
||||
|
||||
#endif // VERTEX_SHADER
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#ifndef PS_SCALE_FACTOR
|
||||
#define PS_SCALE_FACTOR 1.0
|
||||
#endif
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
@@ -23,7 +19,17 @@ layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint o_col0;
|
||||
#else
|
||||
#elif !defined(ps_datm1) && \
|
||||
!defined(ps_datm0) && \
|
||||
!defined(ps_convert_rgba8_float32) && \
|
||||
!defined(ps_convert_rgba8_float24) && \
|
||||
!defined(ps_convert_rgba8_float16) && \
|
||||
!defined(ps_convert_rgb5a1_float16) && \
|
||||
!defined(ps_convert_rgba8_float32_biln) && \
|
||||
!defined(ps_convert_rgba8_float24_biln) && \
|
||||
!defined(ps_convert_rgba8_float16_biln) && \
|
||||
!defined(ps_convert_rgb5a1_float16_biln) && \
|
||||
!defined(ps_depth_copy)
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#endif
|
||||
|
||||
@@ -69,8 +75,6 @@ void ps_convert_rgba8_16bits()
|
||||
#ifdef ps_datm1
|
||||
void ps_datm1()
|
||||
{
|
||||
o_col0 = vec4(0, 0, 0, 0);
|
||||
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
|
||||
@@ -80,8 +84,6 @@ void ps_datm1()
|
||||
#ifdef ps_datm0
|
||||
void ps_datm0()
|
||||
{
|
||||
o_col0 = vec4(0, 0, 0, 0);
|
||||
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
@@ -238,6 +240,15 @@ void ps_convert_rgb5a1_float16_biln()
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uvec2 cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
{
|
||||
// Convert a RGBA texture into a 8 bits packed texture
|
||||
@@ -249,37 +260,45 @@ void ps_convert_rgba_8i()
|
||||
// 1: 8 R | 8 B
|
||||
// 2: 8 G | 8 A
|
||||
// 3: 8 G | 8 A
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||
uvec2 coord = block | subblock;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 32u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
|
||||
coord = (coord % uvec2(64u, 32u)) + block_offset;
|
||||
|
||||
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||
else
|
||||
coord *= uvec2(PS_SCALE_FACTOR);
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
o_col0 = vec4(sel1); // Divide by something here?
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
o_col0 = vec4(sel1); // Divide by something here?
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_clut_4
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec2 scale;
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_4()
|
||||
@@ -288,7 +307,7 @@ void ps_convert_clut_4()
|
||||
uint index = uint(gl_FragCoord.x) + doffset;
|
||||
uvec2 pos = uvec2(index % 8u, index / 8u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * scale));
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -296,9 +315,11 @@ void ps_convert_clut_4()
|
||||
#ifdef ps_convert_clut_8
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
vec2 scale;
|
||||
uvec2 offset;
|
||||
uint doffset;
|
||||
uint cb_pad1;
|
||||
float scale;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_clut_8()
|
||||
@@ -312,7 +333,7 @@ void ps_convert_clut_8()
|
||||
pos.x = (index % 8u) + ((subgroup >= 2u) ? 8u : 0u);
|
||||
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * scale));
|
||||
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
|
||||
o_col0 = texelFetch(samp0, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
39
bin/resources/shaders/vulkan/imgui.glsl
Normal file
39
bin/resources/shaders/vulkan/imgui.glsl
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 1) in vec2 UV;
|
||||
layout(location = 2) in vec4 Color;
|
||||
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
vec2 uScale;
|
||||
vec2 uTranslate;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 Frag_UV;
|
||||
layout(location = 1) out vec4 Frag_Color;
|
||||
|
||||
void vs_main()
|
||||
{
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = vec4(Position * uScale + uTranslate, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
layout(binding = 0) uniform sampler2D Texture;
|
||||
|
||||
layout(location = 0) in vec2 Frag_UV;
|
||||
layout(location = 1) in vec4 Frag_Color;
|
||||
|
||||
layout(location = 0) out vec4 Out_Color;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -35,7 +35,7 @@ void ps_main0()
|
||||
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
|
||||
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = texture(samp0, v_tex);
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void ps_main0()
|
||||
#ifdef ps_main1
|
||||
void ps_main1()
|
||||
{
|
||||
o_col0 = texture(samp0, v_tex);
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -56,9 +56,9 @@ void ps_main1()
|
||||
void ps_main2()
|
||||
{
|
||||
vec2 vstep = vec2(0.0f, ZrH.y);
|
||||
vec4 c0 = texture(samp0, v_tex - vstep);
|
||||
vec4 c1 = texture(samp0, v_tex);
|
||||
vec4 c2 = texture(samp0, v_tex + vstep);
|
||||
vec4 c0 = textureLod(samp0, v_tex - vstep, 0);
|
||||
vec4 c1 = textureLod(samp0, v_tex, 0);
|
||||
vec4 c2 = textureLod(samp0, v_tex + vstep, 0);
|
||||
|
||||
o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f;
|
||||
}
|
||||
@@ -82,15 +82,11 @@ void ps_main3()
|
||||
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
|
||||
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
|
||||
const int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
|
||||
const vec2 bofs = vec2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
|
||||
const vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
|
||||
const vec2 optr = v_tex - bofs; // used to check if the current destination line is within the current bank
|
||||
const vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
|
||||
|
||||
// if the index of current destination line belongs to the current fiels we update it, otherwise
|
||||
// we leave the old line in the destination buffer
|
||||
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
|
||||
o_col0 = texture(samp0, iptr);
|
||||
if ((vpos & 1) == field)
|
||||
o_col0 = textureLod(samp0, v_tex, 0);
|
||||
else
|
||||
discard;
|
||||
}
|
||||
@@ -150,13 +146,13 @@ void ps_main4()
|
||||
|
||||
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
|
||||
|
||||
vec4 hn = texture(samp0, p_t0 - lofs); // new high pixel
|
||||
vec4 cn = texture(samp0, p_t1); // new center pixel
|
||||
vec4 ln = texture(samp0, p_t0 + lofs); // new low pixel
|
||||
vec4 hn = textureLod(samp0, p_t0 - lofs, 0); // new high pixel
|
||||
vec4 cn = textureLod(samp0, p_t1, 0); // new center pixel
|
||||
vec4 ln = textureLod(samp0, p_t0 + lofs, 0); // new low pixel
|
||||
|
||||
vec4 ho = texture(samp0, p_t2 - lofs); // old high pixel
|
||||
vec4 co = texture(samp0, p_t3); // old center pixel
|
||||
vec4 lo = texture(samp0, p_t2 + lofs); // old low pixel
|
||||
vec4 ho = textureLod(samp0, p_t2 - lofs, 0); // old high pixel
|
||||
vec4 co = textureLod(samp0, p_t3, 0); // old center pixel
|
||||
vec4 lo = textureLod(samp0, p_t2 + lofs, 0); // old low pixel
|
||||
|
||||
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
|
||||
vec3 mc = cn.rgb - co.rgb; // center pixel motion
|
||||
@@ -181,7 +177,7 @@ void ps_main4()
|
||||
if ((vpos & 1) == field) // output coordinate present on current field
|
||||
{
|
||||
// output coordinate present on current field
|
||||
o_col0 = texture(samp0, p_t0);
|
||||
o_col0 = textureLod(samp0, p_t0, 0);
|
||||
}
|
||||
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
|
||||
{
|
||||
|
||||
@@ -26,7 +26,6 @@ layout(push_constant) uniform cb10
|
||||
vec2 u_source_resolution;
|
||||
vec2 u_rcp_source_resolution; // 1 / u_source_resolution
|
||||
float u_time;
|
||||
vec3 cb0_pad0;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,113 +0,0 @@
|
||||
set(wx_sdl_c_code "
|
||||
#include <wx/setup.h>
|
||||
|
||||
#if (wxUSE_LIBSDL == 0)
|
||||
#error cmake_WX_SDL
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
|
||||
set(gcc7_mmx_code "
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
class alignas(16) GSVector4i
|
||||
{
|
||||
public:
|
||||
__m128i m;
|
||||
|
||||
explicit GSVector4i(__m128i m)
|
||||
{
|
||||
this->m = m;
|
||||
}
|
||||
|
||||
static void storel(void* p, const GSVector4i& v)
|
||||
{
|
||||
_mm_storel_epi64((__m128i*)p, v.m);
|
||||
}
|
||||
|
||||
static GSVector4i loadl(const void* p)
|
||||
{
|
||||
return GSVector4i(_mm_loadl_epi64((__m128i*)p));
|
||||
}
|
||||
|
||||
bool eq(const GSVector4i& v) const
|
||||
{
|
||||
return _mm_movemask_epi8(_mm_cmpeq_epi32(m, v.m)) == 0xffff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
union GIFRegTRXPOS
|
||||
{
|
||||
unsigned long long u64;
|
||||
void operator = (const GSVector4i& v) {GSVector4i::storel(this, v);}
|
||||
bool operator != (const union GIFRegTRXPOS& r) const {return !((GSVector4i)r).eq(*this);}
|
||||
operator GSVector4i() const {return GSVector4i::loadl(this);}
|
||||
};
|
||||
|
||||
extern GIFRegTRXPOS TRXPOS;
|
||||
GIFRegTRXPOS TRXPOS = {};
|
||||
|
||||
void GIFRegHandlerTRXPOS(const GIFRegTRXPOS& p)
|
||||
{
|
||||
if(p != TRXPOS)
|
||||
{
|
||||
printf(\"foo\");
|
||||
}
|
||||
|
||||
TRXPOS = (GSVector4i)p;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
GIFRegTRXPOS r = {};
|
||||
GIFRegHandlerTRXPOS(r);
|
||||
|
||||
uint16_t fpu[16] = {0};
|
||||
__asm__ __volatile__(\"fstenv %0\" : \"=m\"(fpu));
|
||||
|
||||
bool ok = fpu[4] == 0xFFFF;
|
||||
|
||||
if (!ok) {
|
||||
printf(\"Wrong MMX state !\");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
|
||||
function(GCC7_BUG)
|
||||
# try_run doesn't work when cross-compiling is enabled. It is completely silly in our case
|
||||
# as i386 binaries are 100% fine on x64.
|
||||
set(OLD_CMAKE_CROSSCOMPILING ${CMAKE_CROSSCOMPILING})
|
||||
set(CMAKE_CROSSCOMPILING 0)
|
||||
|
||||
set(IN "${CMAKE_BINARY_DIR}/gcc7_mmx.cpp")
|
||||
file(WRITE "${IN}" "${gcc7_mmx_code}")
|
||||
|
||||
enable_language(CXX)
|
||||
|
||||
try_run(
|
||||
run_result
|
||||
compile_result_unused
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
"${IN}"
|
||||
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=-msse -msse2 -O2 -m32 -march=i686"
|
||||
)
|
||||
|
||||
if (${run_result})
|
||||
message(FATAL_ERROR "GCC 7.0/7.1 generates invalid code => https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80799\n"
|
||||
"You can either backport the fix or swith to another version of GCC.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CROSSCOMPILING ${OLD_CMAKE_CROSSCOMPILING})
|
||||
|
||||
endfunction()
|
||||
@@ -7,6 +7,7 @@ set(PCSX2_DEFS "")
|
||||
option(DISABLE_BUILD_DATE "Disable including the binary compile date")
|
||||
option(ENABLE_TESTS "Enables building the unit tests" ON)
|
||||
set(USE_SYSTEM_LIBS "AUTO" CACHE STRING "Use system libraries instead of bundled libraries. ON - Always use system and fail if unavailable, OFF - Always use bundled, AUTO - Use system if available, otherwise use bundled. Default is AUTO")
|
||||
set(DEFAULT_USE_SYSTEM_RYML OFF) # System rapidyaml causes a lot of problems
|
||||
optional_system_library(fmt)
|
||||
optional_system_library(ryml)
|
||||
optional_system_library(zstd)
|
||||
@@ -34,6 +35,8 @@ if(UNIX AND NOT APPLE)
|
||||
option(USE_LEGACY_USER_DIRECTORY "Use legacy home/PCSX2 user directory instead of XDG standard" OFF)
|
||||
option(X11_API "Enable X11 support" ON)
|
||||
option(WAYLAND_API "Enable Wayland support" ON)
|
||||
option(DBUS_API "Enable DBus support for screensaver inhibiting" ON)
|
||||
option(USE_LINKED_FFMPEG "Links with ffmpeg instead of using dynamic loading" OFF)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
@@ -46,12 +49,12 @@ endif()
|
||||
#-------------------------------------------------------------------------------
|
||||
option(USE_ASAN "Enable address sanitizer")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
if(MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(USE_CLANG_CL TRUE)
|
||||
message(STATUS "Building with Clang-CL.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set(USE_CLANG TRUE)
|
||||
message(STATUS "Building with Clang/LLVM.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
set(USE_ICC TRUE)
|
||||
message(STATUS "Building with Intel's ICC.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(USE_GCC TRUE)
|
||||
message(STATUS "Building with GNU GCC")
|
||||
@@ -103,33 +106,23 @@ include(TargetArch)
|
||||
target_architecture(PCSX2_TARGET_ARCHITECTURES)
|
||||
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
|
||||
message(STATUS "Compiling a ${PCSX2_TARGET_ARCHITECTURES} build on a ${CMAKE_HOST_SYSTEM_PROCESSOR} host.")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
|
||||
endif()
|
||||
|
||||
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
|
||||
# x86_64 requires -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(NOT DEFINED ARCH_FLAG AND NOT MSVC)
|
||||
if (DISABLE_ADVANCE_SIMD)
|
||||
if (USE_ICC)
|
||||
set(ARCH_FLAG "-msse2 -msse4.1")
|
||||
else()
|
||||
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
|
||||
endif()
|
||||
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
|
||||
else()
|
||||
#set(ARCH_FLAG "-march=native -fabi-version=6")
|
||||
set(ARCH_FLAG "-march=native")
|
||||
endif()
|
||||
elseif(NOT DEFINED ARCH_FLAG AND USE_CLANG_CL)
|
||||
set(ARCH_FLAG "-msse4.1")
|
||||
endif()
|
||||
list(APPEND PCSX2_DEFS _ARCH_64=1 _M_X86=1)
|
||||
set(_ARCH_64 1)
|
||||
list(APPEND PCSX2_DEFS _M_X86=1)
|
||||
set(_M_X86 1)
|
||||
else()
|
||||
# All but i386 requires -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
|
||||
endif()
|
||||
string(REPLACE " " ";" ARCH_FLAG_LIST "${ARCH_FLAG}")
|
||||
@@ -143,13 +136,16 @@ option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
|
||||
|
||||
# Note1: Builtin strcmp/memcmp was proved to be slower on Mesa than stdlib version.
|
||||
# Note2: float operation SSE is impacted by the PCSX2 SSE configuration. In particular, flush to zero denormal.
|
||||
if(MSVC)
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>")
|
||||
else()
|
||||
if(MSVC AND NOT USE_CLANG_CL)
|
||||
add_compile_options(
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>"
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:/Zc:__cplusplus>"
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:/permissive->"
|
||||
"/Zo"
|
||||
"/utf-8"
|
||||
)
|
||||
elseif(NOT MSVC)
|
||||
add_compile_options(-pipe -fvisibility=hidden -pthread -fno-builtin-strcmp -fno-builtin-memcmp -mfpmath=sse)
|
||||
|
||||
# -fno-operator-names should only be for C++ files, not C files.
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-operator-names>)
|
||||
endif()
|
||||
|
||||
set(CONFIG_REL_NO_DEB $<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>>)
|
||||
@@ -164,6 +160,12 @@ if(WIN32)
|
||||
list(APPEND PCSX2_DEFS TIXML_USE_STL _SCL_SECURE_NO_WARNINGS _UNICODE UNICODE)
|
||||
endif()
|
||||
|
||||
# Enable debug information in release builds for Linux.
|
||||
# Makes the backtrace actually meaningful.
|
||||
if(UNIX AND NOT APPLE)
|
||||
add_compile_options($<$<CONFIG:Release>:-g1>)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Enable PDB generation in release builds
|
||||
add_compile_options(
|
||||
@@ -209,24 +211,13 @@ endif()
|
||||
if (MSVC)
|
||||
set(DEFAULT_WARNINGS)
|
||||
else()
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security)
|
||||
if (NOT USE_ICC)
|
||||
list(APPEND DEFAULT_WARNINGS -Wno-unused-value)
|
||||
endif()
|
||||
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security -Wno-unused-value)
|
||||
endif()
|
||||
|
||||
if (USE_GCC)
|
||||
list(APPEND DEFAULT_WARNINGS -Wno-stringop-truncation -Wno-stringop-overflow -Wno-maybe-uninitialized )
|
||||
endif()
|
||||
|
||||
|
||||
# -Wstrict-aliasing=n: to fix one day aliasing issue. n=1/2/3
|
||||
if (USE_ICC)
|
||||
set(AGGRESSIVE_WARNING -Wstrict-aliasing)
|
||||
elseif(NOT MSVC)
|
||||
set(AGGRESSIVE_WARNING -Wstrict-aliasing -Wstrict-overflow=1)
|
||||
endif()
|
||||
|
||||
if (USE_PGO_GENERATE OR USE_PGO_OPTIMIZE)
|
||||
add_compile_options("-fprofile-dir=${CMAKE_SOURCE_DIR}/profile")
|
||||
endif()
|
||||
@@ -253,7 +244,7 @@ if(USE_CLANG AND TIMETRACE)
|
||||
add_compile_options(-ftime-trace)
|
||||
endif()
|
||||
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS} ${AGGRESSIVE_WARNING})
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS})
|
||||
|
||||
if(DISABLE_BUILD_DATE)
|
||||
message(STATUS "Disabling the inclusion of the binary compile date.")
|
||||
|
||||
31
cmake/FindLibbacktrace.cmake
Normal file
31
cmake/FindLibbacktrace.cmake
Normal file
@@ -0,0 +1,31 @@
|
||||
# - Try to find libbacktrace
|
||||
# Once done this will define
|
||||
# LIBBACKTRACE_FOUND - System has libbacktrace
|
||||
# LIBBACKTRACE_INCLUDE_DIRS - The libbacktrace include directories
|
||||
# LIBBACKTRACE_LIBRARIES - The libraries needed to use libbacktrace
|
||||
|
||||
FIND_PATH(
|
||||
LIBBACKTRACE_INCLUDE_DIR backtrace.h
|
||||
HINTS /usr/include /usr/local/include
|
||||
${LIBBACKTRACE_PATH_INCLUDES}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(
|
||||
LIBBACKTRACE_LIBRARY
|
||||
NAMES backtrace
|
||||
PATHS ${ADDITIONAL_LIBRARY_PATHS} ${LIBBACKTRACE_PATH_LIB}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libbacktrace DEFAULT_MSG
|
||||
LIBBACKTRACE_LIBRARY LIBBACKTRACE_INCLUDE_DIR)
|
||||
|
||||
if(LIBBACKTRACE_FOUND)
|
||||
add_library(libbacktrace::libbacktrace UNKNOWN IMPORTED)
|
||||
set_target_properties(libbacktrace::libbacktrace PROPERTIES
|
||||
IMPORTED_LOCATION ${LIBBACKTRACE_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${LIBBACKTRACE_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBBACKTRACE_INCLUDE_DIR LIBBACKTRACE_LIBRARY)
|
||||
@@ -5,28 +5,21 @@
|
||||
# VTUNE_INCLUDE_DIRS include path to jitprofiling.h
|
||||
# VTUNE_LIBRARIES path to vtune libs
|
||||
|
||||
find_path(VTUNE_INCLUDE_DIRS NAMES jitprofiling.h PATHS
|
||||
/opt/intel/oneapi/vtune/latest/include
|
||||
/opt/intel/vtune_amplifier_xe_2018/include
|
||||
/opt/intel/vtune_amplifier_xe_2017/include
|
||||
/opt/intel/vtune_amplifier_xe_2016/include
|
||||
set(VTUNE_PATHS
|
||||
/opt/intel/oneapi/vtune/latest
|
||||
/opt/intel/vtune_amplifier_xe_2018
|
||||
/opt/intel/vtune_amplifier_xe_2017
|
||||
/opt/intel/vtune_amplifier_xe_2016
|
||||
"C:\\Program Files (x86)\\Intel\\oneAPI\\vtune\\latest"
|
||||
)
|
||||
|
||||
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "i386")
|
||||
find_library(VTUNE_LIBRARIES NAMES libjitprofiling.a PATHS
|
||||
/opt/intel/oneapi/vtune/latest/lib32
|
||||
/opt/intel/vtune_amplifier_xe_2018/lib32
|
||||
/opt/intel/vtune_amplifier_xe_2017/lib32
|
||||
/opt/intel/vtune_amplifier_xe_2016/lib32
|
||||
)
|
||||
else()
|
||||
find_library(VTUNE_LIBRARIES NAMES libjitprofiling.a PATHS
|
||||
/opt/intel/oneapi/vtune/latest/lib64
|
||||
/opt/intel/vtune_amplifier_xe_2018/lib64
|
||||
/opt/intel/vtune_amplifier_xe_2017/lib64
|
||||
/opt/intel/vtune_amplifier_xe_2016/lib64
|
||||
)
|
||||
endif()
|
||||
find_path(VTUNE_INCLUDE_DIRS NAMES jitprofiling.h PATHS ${VTUNE_PATHS} PATH_SUFFIXES include)
|
||||
|
||||
find_library(VTUNE_LIBRARIES
|
||||
NAMES ${CMAKE_STATIC_LIBRARY_PREFIX}jitprofiling${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||
PATHS ${VTUNE_PATHS}
|
||||
PATH_SUFFIXES lib64
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set VTUNE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
@@ -41,4 +34,3 @@ if(VTUNE_LIBRARIES AND NOT TARGET Vtune::Vtune)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(VTUNE_FOUND VTUNE_INCLUDE_DIRS VTUNE_LIBRARIES)
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ function(detectOperatingSystem)
|
||||
if(WIN32)
|
||||
set(Windows TRUE PARENT_SCOPE)
|
||||
elseif(UNIX AND APPLE)
|
||||
# No easy way to filter out iOS.
|
||||
message(WARNING "OS X/iOS isn't supported, the build will most likely fail")
|
||||
if(IOS)
|
||||
message(WARNING "iOS isn't supported, the build will most likely fail")
|
||||
endif()
|
||||
set(MacOSX TRUE PARENT_SCOPE)
|
||||
elseif(UNIX)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
@@ -198,9 +199,18 @@ endfunction()
|
||||
|
||||
function(optional_system_library library)
|
||||
string(TOUPPER ${library} upperlib)
|
||||
set(USE_SYSTEM_${upperlib} "" CACHE STRING "Use system ${library} instead of bundled. ON - Always use system and fail if unavailable, OFF - Always use bundled, AUTO - Use system if available, otherwise use bundled, blank - Delegate to USE_SYSTEM_LIBS. Default is blank.")
|
||||
if (DEFINED DEFAULT_USE_SYSTEM_${upperlib})
|
||||
set(extra " with extra override to ${DEFAULT_USE_SYSTEM_${upperlib}} on fully default builds")
|
||||
else()
|
||||
set(extra)
|
||||
endif()
|
||||
set(USE_SYSTEM_${upperlib} "" CACHE STRING "Use system ${library} instead of bundled. ON - Always use system and fail if unavailable, OFF - Always use bundled, AUTO - Use system if available, otherwise use bundled, blank - Delegate to USE_SYSTEM_LIBS${extra}. Default is blank.")
|
||||
if ("${USE_SYSTEM_${upperlib}}" STREQUAL "")
|
||||
set(RESOLVED_USE_SYSTEM_${upperlib} ${USE_SYSTEM_LIBS} PARENT_SCOPE)
|
||||
if(${USE_SYSTEM_LIBS} STREQUAL "AUTO" AND DEFINED DEFAULT_USE_SYSTEM_${upperlib})
|
||||
set(RESOLVED_USE_SYSTEM_${upperlib} ${DEFAULT_USE_SYSTEM_${upperlib}} PARENT_SCOPE)
|
||||
else()
|
||||
set(RESOLVED_USE_SYSTEM_${upperlib} ${USE_SYSTEM_LIBS} PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
set(RESOLVED_USE_SYSTEM_${upperlib} ${USE_SYSTEM_${upperlib}} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
@@ -14,6 +14,7 @@ if (WIN32)
|
||||
add_subdirectory(3rdparty/xz EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/D3D12MemAlloc EXCLUDE_FROM_ALL)
|
||||
set(FFMPEG_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/3rdparty/ffmpeg/include")
|
||||
find_package(Vtune)
|
||||
else()
|
||||
find_package(PCAP REQUIRED)
|
||||
find_package(LibLZMA REQUIRED)
|
||||
@@ -86,6 +87,8 @@ else()
|
||||
if(WAYLAND_API)
|
||||
find_package(Wayland REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Libbacktrace)
|
||||
endif()
|
||||
endif(WIN32)
|
||||
|
||||
@@ -100,18 +103,7 @@ if(ENABLE_TESTS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------
|
||||
# Check correctness of the parameter
|
||||
# Note: wxWidgets_INCLUDE_DIRS must be defined
|
||||
#----------------------------------------
|
||||
include(ApiValidation)
|
||||
|
||||
# Blacklist bad GCC
|
||||
if(GCC_VERSION VERSION_EQUAL "7.0" OR GCC_VERSION VERSION_EQUAL "7.1")
|
||||
GCC7_BUG()
|
||||
endif()
|
||||
|
||||
if((GCC_VERSION VERSION_EQUAL "9.0" OR GCC_VERSION VERSION_GREATER "9.0") AND GCC_VERSION LESS "9.2")
|
||||
if(GCC_VERSION VERSION_GREATER_EQUAL "9.0" AND GCC_VERSION VERSION_LESS "9.2")
|
||||
message(WARNING "
|
||||
It looks like you are compiling with 9.0.x or 9.1.x. Using these versions is not recommended,
|
||||
as there is a bug known to cause the compiler to segfault while compiling. See patch
|
||||
@@ -132,7 +124,7 @@ find_optional_system_library(libzip 3rdparty/libzip 1.8.0)
|
||||
if(QT_BUILD)
|
||||
# Default to bundled Qt6 for Windows.
|
||||
if(WIN32 AND NOT DEFINED Qt6_DIR)
|
||||
set(Qt6_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qt/6.4.0/msvc2022_64/lib/cmake/Qt6)
|
||||
set(Qt6_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qt/6.5.0/msvc2022_64/lib/cmake/Qt6)
|
||||
endif()
|
||||
|
||||
# Find the Qt components that we need.
|
||||
@@ -152,6 +144,9 @@ if(QT_BUILD)
|
||||
# rcheevos backend for RetroAchievements.
|
||||
if(USE_ACHIEVEMENTS)
|
||||
add_subdirectory(3rdparty/rcheevos EXCLUDE_FROM_ALL)
|
||||
if(WIN32)
|
||||
add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Discord-RPC library for rich presence.
|
||||
|
||||
56
common/ByteSwap.h
Normal file
56
common/ByteSwap.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
T ByteSwap(T value)
|
||||
{
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
return static_cast<T>(ByteSwap(std::make_unsigned_t<T>(value)));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::uint16_t>)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ushort(value);
|
||||
#else
|
||||
return __builtin_bswap16(value);
|
||||
#endif
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::uint32_t>)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ulong(value);
|
||||
#else
|
||||
return __builtin_bswap32(value);
|
||||
#endif
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::uint64_t>)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_uint64(value);
|
||||
#else
|
||||
return __builtin_bswap64(value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@ target_sources(common PRIVATE
|
||||
AlignedMalloc.h
|
||||
Assertions.h
|
||||
boost_spsc_queue.hpp
|
||||
ByteSwap.h
|
||||
Console.h
|
||||
CrashHandler.h
|
||||
DynamicLibrary.h
|
||||
@@ -126,52 +127,9 @@ target_sources(common PRIVATE
|
||||
emitter/tools.h
|
||||
emitter/x86emitter.h
|
||||
emitter/x86types.h
|
||||
Darwin/DarwinMisc.h
|
||||
)
|
||||
|
||||
if(USE_OPENGL)
|
||||
target_sources(common PRIVATE
|
||||
GL/Context.cpp
|
||||
GL/Program.cpp
|
||||
GL/ShaderCache.cpp
|
||||
GL/StreamBuffer.cpp
|
||||
)
|
||||
target_sources(common PRIVATE
|
||||
GL/Context.h
|
||||
GL/Program.h
|
||||
GL/ShaderCache.h
|
||||
GL/StreamBuffer.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC glad)
|
||||
endif()
|
||||
|
||||
if(USE_VULKAN)
|
||||
target_link_libraries(common PUBLIC
|
||||
Vulkan-Headers glslang
|
||||
)
|
||||
target_sources(common PRIVATE
|
||||
Vulkan/ShaderCache.cpp
|
||||
Vulkan/Texture.cpp
|
||||
Vulkan/Loader.cpp
|
||||
Vulkan/ShaderCompiler.cpp
|
||||
Vulkan/Util.cpp
|
||||
Vulkan/SwapChain.cpp
|
||||
Vulkan/StreamBuffer.cpp
|
||||
Vulkan/Context.cpp
|
||||
Vulkan/Builders.cpp
|
||||
Vulkan/vk_mem_alloc.cpp
|
||||
Vulkan/Context.h
|
||||
Vulkan/Texture.h
|
||||
Vulkan/ShaderCompiler.h
|
||||
Vulkan/SwapChain.h
|
||||
Vulkan/Builders.h
|
||||
Vulkan/StreamBuffer.h
|
||||
Vulkan/ShaderCache.h
|
||||
Vulkan/EntryPoints.h
|
||||
Vulkan/Loader.h
|
||||
Vulkan/Util.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(USE_VTUNE)
|
||||
target_link_libraries(common PUBLIC Vtune::Vtune)
|
||||
endif()
|
||||
@@ -179,7 +137,7 @@ endif()
|
||||
if(WIN32)
|
||||
enable_language(ASM_MASM)
|
||||
target_sources(common PRIVATE FastJmp.asm)
|
||||
target_link_libraries(common PUBLIC WIL::WIL D3D12MemAlloc winmm)
|
||||
target_link_libraries(common PUBLIC WIL::WIL winmm)
|
||||
target_sources(common PRIVATE
|
||||
CrashHandler.cpp
|
||||
CrashHandler.h
|
||||
@@ -188,24 +146,6 @@ if(WIN32)
|
||||
HTTPDownloaderWinHTTP.h
|
||||
StackWalker.cpp
|
||||
StackWalker.h
|
||||
D3D11/ShaderCache.cpp
|
||||
D3D11/ShaderCache.h
|
||||
D3D11/ShaderCompiler.cpp
|
||||
D3D11/ShaderCompiler.h
|
||||
D3D12/Builders.cpp
|
||||
D3D12/Builders.h
|
||||
D3D12/Context.cpp
|
||||
D3D12/Context.h
|
||||
D3D12/DescriptorHeapManager.cpp
|
||||
D3D12/DescriptorHeapManager.h
|
||||
D3D12/ShaderCache.cpp
|
||||
D3D12/ShaderCache.h
|
||||
D3D12/StreamBuffer.cpp
|
||||
D3D12/StreamBuffer.h
|
||||
D3D12/Texture.cpp
|
||||
D3D12/Texture.h
|
||||
D3D12/Util.cpp
|
||||
D3D12/Util.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -216,62 +156,23 @@ if(APPLE)
|
||||
)
|
||||
target_compile_options(common PRIVATE -fobjc-arc)
|
||||
target_link_options(common PRIVATE -fobjc-link-runtime)
|
||||
target_link_libraries(common PRIVATE
|
||||
"-framework Foundation"
|
||||
"-framework IOKit"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(USE_OPENGL)
|
||||
if(WIN32)
|
||||
target_sources(common PRIVATE
|
||||
GL/ContextWGL.cpp
|
||||
GL/ContextWGL.h
|
||||
)
|
||||
target_link_libraries(common PUBLIC opengl32.lib)
|
||||
elseif(APPLE)
|
||||
target_sources(common PRIVATE
|
||||
GL/ContextAGL.mm
|
||||
GL/ContextAGL.h
|
||||
)
|
||||
else()
|
||||
if(X11_API OR WAYLAND_API)
|
||||
target_sources(common PRIVATE
|
||||
GL/ContextEGL.cpp
|
||||
GL/ContextEGL.h
|
||||
)
|
||||
target_link_libraries(common PRIVATE PkgConfig::EGL)
|
||||
endif()
|
||||
|
||||
if(X11_API)
|
||||
target_sources(common PRIVATE
|
||||
GL/ContextEGLX11.cpp
|
||||
GL/ContextEGLX11.h
|
||||
)
|
||||
if(TARGET PkgConfig::XRANDR)
|
||||
target_link_libraries(common PRIVATE PkgConfig::XRANDR)
|
||||
target_compile_definitions(common PRIVATE "HAS_XRANDR=1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WAYLAND_API)
|
||||
target_sources(common PRIVATE
|
||||
GL/ContextEGLWayland.cpp
|
||||
GL/ContextEGLWayland.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(DBUS_API)
|
||||
target_compile_definitions(common PRIVATE DBUS_API)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||
target_include_directories(common PRIVATE ${DBUS_INCLUDE_DIRS})
|
||||
target_link_libraries(common PRIVATE ${DBUS_LINK_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(USE_VULKAN)
|
||||
if(APPLE)
|
||||
# Needed for Metal surface creation.
|
||||
target_compile_options(common PRIVATE -fobjc-arc)
|
||||
target_link_options(common PRIVATE -fobjc-link-runtime)
|
||||
elseif(NOT WIN32)
|
||||
if(X11_API)
|
||||
target_compile_definitions(common PUBLIC "VULKAN_USE_X11=1")
|
||||
endif()
|
||||
if(WAYLAND_API)
|
||||
target_compile_definitions(common PUBLIC "VULKAN_USE_WAYLAND=1")
|
||||
endif()
|
||||
endif()
|
||||
if(X11_API AND TARGET PkgConfig::XRANDR)
|
||||
target_link_libraries(common PRIVATE PkgConfig::XRANDR)
|
||||
target_compile_definitions(common PRIVATE "HAS_XRANDR=1")
|
||||
endif()
|
||||
|
||||
if (USE_GCC AND CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
@@ -288,6 +189,11 @@ if(NOT WIN32 AND (QT_BUILD OR NOGUI_BUILD))
|
||||
target_link_libraries(common PRIVATE CURL::libcurl)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE AND TARGET libbacktrace::libbacktrace)
|
||||
target_compile_definitions(common PRIVATE "HAS_LIBBACKTRACE=1")
|
||||
target_link_libraries(common PRIVATE libbacktrace::libbacktrace)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common PRIVATE
|
||||
${LIBC_LIBRARIES}
|
||||
PNG::PNG
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
@@ -215,6 +215,199 @@ void CrashHandler::Uninstall()
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HAS_LIBBACKTRACE)
|
||||
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include <backtrace.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
struct BacktraceBuffer
|
||||
{
|
||||
char* buffer;
|
||||
size_t used;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static const char* GetSignalName(int signal_no);
|
||||
static void AllocateBuffer(BacktraceBuffer* buf);
|
||||
static void FreeBuffer(BacktraceBuffer* buf);
|
||||
static void AppendToBuffer(BacktraceBuffer* buf, const char* format, ...);
|
||||
static int BacktraceFullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function);
|
||||
static void CallExistingSignalHandler(int signal, siginfo_t* siginfo, void* ctx);
|
||||
static void CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx);
|
||||
|
||||
static std::recursive_mutex s_crash_mutex;
|
||||
static bool s_in_signal_handler = false;
|
||||
|
||||
static backtrace_state* s_backtrace_state = nullptr;
|
||||
static struct sigaction s_old_sigbus_action;
|
||||
static struct sigaction s_old_sigsegv_action;
|
||||
}
|
||||
|
||||
const char* CrashHandler::GetSignalName(int signal_no)
|
||||
{
|
||||
switch (signal_no)
|
||||
{
|
||||
// Don't need to list all of them, there's only a couple we register.
|
||||
// clang-format off
|
||||
case SIGSEGV: return "SIGSEGV";
|
||||
case SIGBUS: return "SIGBUS";
|
||||
default: return "UNKNOWN";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
void CrashHandler::AllocateBuffer(BacktraceBuffer* buf)
|
||||
{
|
||||
buf->used = 0;
|
||||
buf->size = __pagesize;
|
||||
buf->buffer = static_cast<char*>(mmap(nullptr, buf->size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
||||
if (buf->buffer == static_cast<char*>(MAP_FAILED))
|
||||
{
|
||||
buf->buffer = nullptr;
|
||||
buf->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CrashHandler::FreeBuffer(BacktraceBuffer* buf)
|
||||
{
|
||||
if (buf->buffer)
|
||||
munmap(buf->buffer, buf->size);
|
||||
}
|
||||
|
||||
void CrashHandler::AppendToBuffer(BacktraceBuffer* buf, const char* format, ...)
|
||||
{
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
// Hope this doesn't allocate memory... it *can*, but hopefully unlikely since
|
||||
// it won't be the first call, and we're providing the buffer.
|
||||
if (buf->size > 0 && buf->used < (buf->size - 1))
|
||||
{
|
||||
const int written = std::vsnprintf(buf->buffer + buf->used, buf->size - buf->used, format, ap);
|
||||
if (written > 0)
|
||||
buf->used += static_cast<size_t>(written);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int CrashHandler::BacktraceFullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function)
|
||||
{
|
||||
BacktraceBuffer* buf = static_cast<BacktraceBuffer*>(data);
|
||||
AppendToBuffer(buf, " %016p", pc);
|
||||
if (function)
|
||||
AppendToBuffer(buf, " %s", function);
|
||||
if (filename)
|
||||
AppendToBuffer(buf, " [%s:%d]", filename, lineno);
|
||||
|
||||
AppendToBuffer(buf, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CrashHandler::CallExistingSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
|
||||
{
|
||||
const struct sigaction& sa = (signal == SIGBUS) ? s_old_sigbus_action : s_old_sigsegv_action;
|
||||
if (sa.sa_flags & SA_SIGINFO)
|
||||
{
|
||||
sa.sa_sigaction(signal, siginfo, ctx);
|
||||
}
|
||||
else if (sa.sa_handler == SIG_DFL)
|
||||
{
|
||||
// Re-raising the signal would just queue it, and since we'd restore the handler back to us,
|
||||
// we'd end up right back here again. So just abort, because that's probably what it'd do anyway.
|
||||
abort();
|
||||
}
|
||||
else if (sa.sa_handler != SIG_IGN)
|
||||
{
|
||||
sa.sa_handler(signal);
|
||||
}
|
||||
}
|
||||
|
||||
void CrashHandler::CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
|
||||
{
|
||||
std::unique_lock lock(s_crash_mutex);
|
||||
|
||||
// If we crash somewhere in libbacktrace, don't bother trying again.
|
||||
if (!s_in_signal_handler)
|
||||
{
|
||||
s_in_signal_handler = true;
|
||||
|
||||
#if defined(__APPLE__) && defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext->__ss.__rip);
|
||||
#elif defined(__FreeBSD__) && defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.mc_rip);
|
||||
#elif defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.gregs[REG_RIP]);
|
||||
#else
|
||||
void* const exception_pc = nullptr;
|
||||
#endif
|
||||
|
||||
BacktraceBuffer buf;
|
||||
AllocateBuffer(&buf);
|
||||
AppendToBuffer(&buf, "*************** Unhandled %s at %p ***************\n", GetSignalName(signal), exception_pc);
|
||||
|
||||
const int rc = backtrace_full(s_backtrace_state, 0, BacktraceFullCallback, nullptr, &buf);
|
||||
if (rc != 0)
|
||||
AppendToBuffer(&buf, " backtrace_full() failed: %d\n");
|
||||
|
||||
AppendToBuffer(&buf, "*******************************************************************\n");
|
||||
|
||||
if (buf.used > 0)
|
||||
write(STDERR_FILENO, buf.buffer, buf.used);
|
||||
|
||||
FreeBuffer(&buf);
|
||||
|
||||
s_in_signal_handler = false;
|
||||
}
|
||||
|
||||
// Chances are we're not going to have anything else to call, but just in case.
|
||||
lock.unlock();
|
||||
CallExistingSignalHandler(signal, siginfo, ctx);
|
||||
}
|
||||
|
||||
bool CrashHandler::Install()
|
||||
{
|
||||
const std::string progpath = FileSystem::GetProgramPath();
|
||||
s_backtrace_state = backtrace_create_state(progpath.empty() ? nullptr : progpath.c_str(), 0, nullptr, nullptr);
|
||||
if (!s_backtrace_state)
|
||||
return false;
|
||||
|
||||
struct sigaction sa;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO | SA_NODEFER;
|
||||
sa.sa_sigaction = CrashSignalHandler;
|
||||
if (sigaction(SIGBUS, &sa, &s_old_sigbus_action) != 0)
|
||||
return false;
|
||||
if (sigaction(SIGSEGV, &sa, &s_old_sigsegv_action) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CrashHandler::SetWriteDirectory(const std::string_view& dump_directory)
|
||||
{
|
||||
}
|
||||
|
||||
void CrashHandler::WriteDumpForCaller()
|
||||
{
|
||||
}
|
||||
|
||||
void CrashHandler::Uninstall()
|
||||
{
|
||||
// We can't really unchain the signal handlers... so, YOLO.
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
bool CrashHandler::Install()
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/HashCombine.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
#include "common/D3D11/ShaderCompiler.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <d3d11.h>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace D3D11
|
||||
{
|
||||
class ShaderCache
|
||||
{
|
||||
public:
|
||||
ShaderCache();
|
||||
~ShaderCache();
|
||||
|
||||
D3D_FEATURE_LEVEL GetFeatureLevel() const { return m_feature_level; }
|
||||
bool UsingDebugShaders() const { return m_debug; }
|
||||
|
||||
bool Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> GetShaderBlob(ShaderCompiler::Type type, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> GetVertexShader(ID3D11Device* device, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
bool GetVertexShaderAndInputLayout(ID3D11Device* device,
|
||||
ID3D11VertexShader** vs, ID3D11InputLayout** il,
|
||||
const D3D11_INPUT_ELEMENT_DESC* layout, size_t layout_size,
|
||||
const std::string_view& shader_code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> GetGeometryShader(ID3D11Device* device, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> GetPixelShader(ID3D11Device* device, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> GetComputeShader(ID3D11Device* device, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
private:
|
||||
static constexpr u32 FILE_VERSION = 1;
|
||||
|
||||
struct CacheIndexKey
|
||||
{
|
||||
u64 source_hash_low;
|
||||
u64 source_hash_high;
|
||||
u64 macro_hash_low;
|
||||
u64 macro_hash_high;
|
||||
u64 entry_point_low;
|
||||
u64 entry_point_high;
|
||||
u32 source_length;
|
||||
ShaderCompiler::Type shader_type;
|
||||
|
||||
bool operator==(const CacheIndexKey& key) const;
|
||||
bool operator!=(const CacheIndexKey& key) const;
|
||||
};
|
||||
|
||||
struct CacheIndexEntryHasher
|
||||
{
|
||||
std::size_t operator()(const CacheIndexKey& e) const noexcept
|
||||
{
|
||||
std::size_t h = 0;
|
||||
HashCombine(h, e.entry_point_low, e.entry_point_high, e.macro_hash_low, e.macro_hash_high,
|
||||
e.source_hash_low, e.source_hash_high, e.source_length, e.shader_type);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct CacheIndexData
|
||||
{
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
};
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static std::string GetCacheBaseFileName(const std::string_view& base_path, D3D_FEATURE_LEVEL feature_level,
|
||||
bool debug);
|
||||
static CacheIndexKey GetCacheKey(ShaderCompiler::Type type, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
|
||||
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
|
||||
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
|
||||
void Close();
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
|
||||
std::FILE* m_index_file = nullptr;
|
||||
std::FILE* m_blob_file = nullptr;
|
||||
|
||||
CacheIndex m_index;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
u32 m_version = 0;
|
||||
bool m_debug = false;
|
||||
};
|
||||
} // namespace D3D11
|
||||
@@ -1,215 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
#include "common/D3D11/ShaderCompiler.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include <array>
|
||||
#include <d3dcompiler.h>
|
||||
#include <fstream>
|
||||
|
||||
static unsigned s_next_bad_shader_id = 1;
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> D3D11::ShaderCompiler::CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, bool debug,
|
||||
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
|
||||
{
|
||||
const char* target;
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
default:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob;
|
||||
wil::com_ptr_nothrow<ID3DBlob> error_blob;
|
||||
const HRESULT hr =
|
||||
D3DCompile(code.data(), code.size(), "0", macros, nullptr, entry_point, target, debug ? flags_debug : flags_non_debug,
|
||||
0, blob.put(), error_blob.put());
|
||||
|
||||
std::string error_string;
|
||||
if (error_blob)
|
||||
{
|
||||
error_string.append(static_cast<const char*>(error_blob->GetBufferPointer()), error_blob->GetBufferSize());
|
||||
error_blob.reset();
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.WriteLn("Failed to compile '%s':\n%s", target, error_string.c_str());
|
||||
|
||||
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
|
||||
std::ofstream::out | std::ofstream::binary);
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs << code;
|
||||
ofs << "\n\nCompile as " << target << " failed: " << hr << "\n";
|
||||
ofs.write(error_string.c_str(), error_string.size());
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!error_string.empty())
|
||||
Console.Warning("'%s' compiled with warnings:\n%s", target, error_string.c_str());
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> D3D11::ShaderCompiler::CompileAndCreateVertexShader(ID3D11Device* device, bool debug,
|
||||
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob = CompileShader(Type::Vertex, device->GetFeatureLevel(), debug, code, macros, entry_point);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateVertexShader(device, blob.get());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CompileAndCreateGeometryShader(ID3D11Device* device, bool debug,
|
||||
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob = CompileShader(Type::Geometry, device->GetFeatureLevel(), debug, code, macros, entry_point);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateGeometryShader(device, blob.get());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCompiler::CompileAndCreatePixelShader(ID3D11Device* device, bool debug,
|
||||
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob = CompileShader(Type::Pixel, device->GetFeatureLevel(), debug, code, macros, entry_point);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreatePixelShader(device, blob.get());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> D3D11::ShaderCompiler::CompileAndCreateComputeShader(ID3D11Device* device, bool debug,
|
||||
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob = CompileShader(Type::Compute, device->GetFeatureLevel(), debug, code, macros, entry_point);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateComputeShader(device, blob.get());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> D3D11::ShaderCompiler::CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> shader;
|
||||
const HRESULT hr = device->CreateVertexShader(bytecode, bytecode_length, nullptr, shader.put());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("Failed to create vertex shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> D3D11::ShaderCompiler::CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateVertexShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> shader;
|
||||
const HRESULT hr = device->CreateGeometryShader(bytecode, bytecode_length, nullptr, shader.put());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("Failed to create geometry shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateGeometryShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCompiler::CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> shader;
|
||||
const HRESULT hr = device->CreatePixelShader(bytecode, bytecode_length, nullptr, shader.put());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("Failed to create pixel shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCompiler::CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreatePixelShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> D3D11::ShaderCompiler::CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> shader;
|
||||
const HRESULT hr = device->CreateComputeShader(bytecode, bytecode_length, nullptr, shader.put());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("Failed to create compute shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> D3D11::ShaderCompiler::CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateComputeShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
namespace D3D11::ShaderCompiler
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
Vertex,
|
||||
Geometry,
|
||||
Pixel,
|
||||
Compute
|
||||
};
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, bool debug, const std::string_view& code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, bool debug, const std::string_view& code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, bool debug, const std::string_view& code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, bool debug, const std::string_view& code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, bool debug, const std::string_view& code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
wil::com_ptr_nothrow<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
wil::com_ptr_nothrow<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
wil::com_ptr_nothrow<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
}; // namespace D3D11::ShaderCompiler
|
||||
@@ -1,214 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/D3D12/DescriptorHeapManager.h"
|
||||
#include "common/D3D12/StreamBuffer.h"
|
||||
|
||||
#include <array>
|
||||
#include <d3d12.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <wil/com.h>
|
||||
|
||||
struct IDXGIAdapter;
|
||||
struct IDXGIFactory;
|
||||
namespace D3D12MA
|
||||
{
|
||||
class Allocator;
|
||||
class Allocation;
|
||||
} // namespace D3D12MA
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
using ComPtr = wil::com_ptr_nothrow<T>;
|
||||
|
||||
enum : u32
|
||||
{
|
||||
/// Number of command lists. One is being built while the other(s) are executed.
|
||||
NUM_COMMAND_LISTS = 3,
|
||||
|
||||
/// Textures that don't fit into this buffer will be uploaded with a staging buffer.
|
||||
TEXTURE_UPLOAD_BUFFER_SIZE = 64 * 1024 * 1024,
|
||||
|
||||
/// Maximum number of samples in a single allocation group.
|
||||
SAMPLER_GROUP_SIZE = 2,
|
||||
|
||||
/// Start/End timestamp queries.
|
||||
NUM_TIMESTAMP_QUERIES_PER_CMDLIST = 2,
|
||||
};
|
||||
|
||||
~Context();
|
||||
|
||||
/// Creates new device and context.
|
||||
static bool Create(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer);
|
||||
|
||||
/// Destroys active context.
|
||||
static void Destroy();
|
||||
|
||||
__fi IDXGIAdapter* GetAdapter() const { return m_adapter.get(); }
|
||||
__fi ID3D12Device* GetDevice() const { return m_device.get(); }
|
||||
__fi ID3D12CommandQueue* GetCommandQueue() const { return m_command_queue.get(); }
|
||||
__fi D3D12MA::Allocator* GetAllocator() const { return m_allocator.get(); }
|
||||
|
||||
/// Returns the PCI vendor ID of the device, if known.
|
||||
u32 GetAdapterVendorID() const;
|
||||
|
||||
/// Returns the current command list, commands can be recorded directly.
|
||||
ID3D12GraphicsCommandList4* GetCommandList() const
|
||||
{
|
||||
return m_command_lists[m_current_command_list].command_lists[1].get();
|
||||
}
|
||||
|
||||
/// Returns the init command list for uploading.
|
||||
ID3D12GraphicsCommandList4* GetInitCommandList();
|
||||
|
||||
/// Returns the per-frame SRV/CBV/UAV allocator.
|
||||
DescriptorAllocator& GetDescriptorAllocator()
|
||||
{
|
||||
return m_command_lists[m_current_command_list].descriptor_allocator;
|
||||
}
|
||||
|
||||
/// Returns the per-frame sampler allocator.
|
||||
GroupedSamplerAllocator<SAMPLER_GROUP_SIZE>& GetSamplerAllocator()
|
||||
{
|
||||
return m_command_lists[m_current_command_list].sampler_allocator;
|
||||
}
|
||||
|
||||
/// Invalidates GPU-side sampler caches for all command lists. Call after you've freed samplers,
|
||||
/// and are going to re-use the handles from GetSamplerHeapManager().
|
||||
void InvalidateSamplerGroups();
|
||||
|
||||
// Descriptor manager access.
|
||||
DescriptorHeapManager& GetDescriptorHeapManager() { return m_descriptor_heap_manager; }
|
||||
DescriptorHeapManager& GetRTVHeapManager() { return m_rtv_heap_manager; }
|
||||
DescriptorHeapManager& GetDSVHeapManager() { return m_dsv_heap_manager; }
|
||||
DescriptorHeapManager& GetSamplerHeapManager() { return m_sampler_heap_manager; }
|
||||
const DescriptorHandle& GetNullSRVDescriptor() const { return m_null_srv_descriptor; }
|
||||
StreamBuffer& GetTextureStreamBuffer() { return m_texture_stream_buffer; }
|
||||
|
||||
// Root signature access.
|
||||
ComPtr<ID3DBlob> SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc);
|
||||
ComPtr<ID3D12RootSignature> CreateRootSignature(const D3D12_ROOT_SIGNATURE_DESC* desc);
|
||||
|
||||
/// Fence value for current command list.
|
||||
u64 GetCurrentFenceValue() const { return m_current_fence_value; }
|
||||
|
||||
/// Last "completed" fence.
|
||||
u64 GetCompletedFenceValue() const { return m_completed_fence_value; }
|
||||
|
||||
/// Feature level to use when compiling shaders.
|
||||
D3D_FEATURE_LEVEL GetFeatureLevel() const { return m_feature_level; }
|
||||
|
||||
/// Test for support for the specified texture format.
|
||||
bool SupportsTextureFormat(DXGI_FORMAT format);
|
||||
|
||||
enum class WaitType
|
||||
{
|
||||
None, ///< Don't wait (async)
|
||||
Sleep, ///< Wait normally
|
||||
Spin, ///< Wait by spinning
|
||||
};
|
||||
|
||||
/// Executes the current command list.
|
||||
void ExecuteCommandList(WaitType wait_for_completion);
|
||||
|
||||
/// Waits for a specific fence.
|
||||
void WaitForFence(u64 fence, bool spin);
|
||||
|
||||
/// Waits for any in-flight command buffers to complete.
|
||||
void WaitForGPUIdle();
|
||||
|
||||
/// Defers destruction of a D3D resource (associates it with the current list).
|
||||
void DeferObjectDestruction(ID3D12DeviceChild* resource);
|
||||
|
||||
/// Defers destruction of a D3D resource (associates it with the current list).
|
||||
void DeferResourceDestruction(D3D12MA::Allocation* allocation, ID3D12Resource* resource);
|
||||
|
||||
/// Defers destruction of a descriptor handle (associates it with the current list).
|
||||
void DeferDescriptorDestruction(DescriptorHeapManager& manager, u32 index);
|
||||
void DeferDescriptorDestruction(DescriptorHeapManager& manager, DescriptorHandle* handle);
|
||||
|
||||
float GetAndResetAccumulatedGPUTime();
|
||||
void SetEnableGPUTiming(bool enabled);
|
||||
|
||||
private:
|
||||
struct CommandListResources
|
||||
{
|
||||
std::array<ComPtr<ID3D12CommandAllocator>, 2> command_allocators;
|
||||
std::array<ComPtr<ID3D12GraphicsCommandList4>, 2> command_lists;
|
||||
DescriptorAllocator descriptor_allocator;
|
||||
GroupedSamplerAllocator<SAMPLER_GROUP_SIZE> sampler_allocator;
|
||||
std::vector<std::pair<D3D12MA::Allocation*, ID3D12DeviceChild*>> pending_resources;
|
||||
std::vector<std::pair<DescriptorHeapManager&, u32>> pending_descriptors;
|
||||
u64 ready_fence_value = 0;
|
||||
bool init_command_list_used = false;
|
||||
bool has_timestamp_query = false;
|
||||
};
|
||||
|
||||
Context();
|
||||
|
||||
bool CreateDevice(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer);
|
||||
bool CreateCommandQueue();
|
||||
bool CreateAllocator();
|
||||
bool CreateFence();
|
||||
bool CreateDescriptorHeaps();
|
||||
bool CreateCommandLists();
|
||||
bool CreateTextureStreamBuffer();
|
||||
bool CreateTimestampQuery();
|
||||
void MoveToNextCommandList();
|
||||
void DestroyPendingResources(CommandListResources& cmdlist);
|
||||
void DestroyResources();
|
||||
|
||||
ComPtr<IDXGIAdapter> m_adapter;
|
||||
ComPtr<ID3D12Debug> m_debug_interface;
|
||||
ComPtr<ID3D12Device> m_device;
|
||||
ComPtr<ID3D12CommandQueue> m_command_queue;
|
||||
ComPtr<D3D12MA::Allocator> m_allocator;
|
||||
|
||||
ComPtr<ID3D12Fence> m_fence;
|
||||
HANDLE m_fence_event = {};
|
||||
u32 m_current_fence_value = 0;
|
||||
u64 m_completed_fence_value = 0;
|
||||
|
||||
std::array<CommandListResources, NUM_COMMAND_LISTS> m_command_lists;
|
||||
u32 m_current_command_list = NUM_COMMAND_LISTS - 1;
|
||||
|
||||
ComPtr<ID3D12QueryHeap> m_timestamp_query_heap;
|
||||
ComPtr<ID3D12Resource> m_timestamp_query_buffer;
|
||||
ComPtr<D3D12MA::Allocation> m_timestamp_query_allocation;
|
||||
double m_timestamp_frequency = 0.0;
|
||||
float m_accumulated_gpu_time = 0.0f;
|
||||
bool m_gpu_timing_enabled = false;
|
||||
|
||||
DescriptorHeapManager m_descriptor_heap_manager;
|
||||
DescriptorHeapManager m_rtv_heap_manager;
|
||||
DescriptorHeapManager m_dsv_heap_manager;
|
||||
DescriptorHeapManager m_sampler_heap_manager;
|
||||
DescriptorHandle m_null_srv_descriptor;
|
||||
StreamBuffer m_texture_stream_buffer;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
};
|
||||
} // namespace D3D12
|
||||
|
||||
extern std::unique_ptr<D3D12::Context> g_d3d12_context;
|
||||
@@ -1,269 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/HashCombine.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <cstring>
|
||||
#include <d3d12.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
// This class provides an abstraction for D3D12 descriptor heaps.
|
||||
struct DescriptorHandle final
|
||||
{
|
||||
enum : u32
|
||||
{
|
||||
INVALID_INDEX = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle{};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle{};
|
||||
u32 index = INVALID_INDEX;
|
||||
|
||||
__fi operator bool() const { return index != INVALID_INDEX; }
|
||||
|
||||
__fi operator D3D12_CPU_DESCRIPTOR_HANDLE() const { return cpu_handle; }
|
||||
__fi operator D3D12_GPU_DESCRIPTOR_HANDLE() const { return gpu_handle; }
|
||||
|
||||
__fi bool operator==(const DescriptorHandle& rhs) const { return (index == rhs.index); }
|
||||
__fi bool operator!=(const DescriptorHandle& rhs) const { return (index != rhs.index); }
|
||||
__fi bool operator<(const DescriptorHandle& rhs) const { return (index < rhs.index); }
|
||||
__fi bool operator<=(const DescriptorHandle& rhs) const { return (index <= rhs.index); }
|
||||
__fi bool operator>(const DescriptorHandle& rhs) const { return (index > rhs.index); }
|
||||
__fi bool operator>=(const DescriptorHandle& rhs) const { return (index >= rhs.index); }
|
||||
|
||||
__fi void Clear()
|
||||
{
|
||||
cpu_handle = {};
|
||||
gpu_handle = {};
|
||||
index = INVALID_INDEX;
|
||||
}
|
||||
};
|
||||
|
||||
class DescriptorHeapManager final
|
||||
{
|
||||
public:
|
||||
DescriptorHeapManager();
|
||||
~DescriptorHeapManager();
|
||||
|
||||
ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptor_heap.get(); }
|
||||
u32 GetDescriptorIncrementSize() const { return m_descriptor_increment_size; }
|
||||
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, bool shader_visible);
|
||||
void Destroy();
|
||||
|
||||
bool Allocate(DescriptorHandle* handle);
|
||||
void Free(DescriptorHandle* handle);
|
||||
void Free(u32 index);
|
||||
|
||||
private:
|
||||
wil::com_ptr_nothrow<ID3D12DescriptorHeap> m_descriptor_heap;
|
||||
u32 m_num_descriptors = 0;
|
||||
u32 m_descriptor_increment_size = 0;
|
||||
bool m_shader_visible = false;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_heap_base_cpu = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE m_heap_base_gpu = {};
|
||||
|
||||
static constexpr u32 BITSET_SIZE = 1024;
|
||||
using BitSetType = std::bitset<BITSET_SIZE>;
|
||||
std::vector<BitSetType> m_free_slots = {};
|
||||
};
|
||||
|
||||
class DescriptorAllocator
|
||||
{
|
||||
public:
|
||||
DescriptorAllocator();
|
||||
~DescriptorAllocator();
|
||||
|
||||
__fi ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptor_heap.get(); }
|
||||
__fi u32 GetDescriptorIncrementSize() const { return m_descriptor_increment_size; }
|
||||
|
||||
bool Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors);
|
||||
void Destroy();
|
||||
|
||||
bool Allocate(u32 num_handles, DescriptorHandle* out_base_handle);
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
wil::com_ptr_nothrow<ID3D12DescriptorHeap> m_descriptor_heap;
|
||||
u32 m_descriptor_increment_size = 0;
|
||||
u32 m_num_descriptors = 0;
|
||||
u32 m_current_offset = 0;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_heap_base_cpu = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE m_heap_base_gpu = {};
|
||||
};
|
||||
|
||||
template <u32 NumSamplers>
|
||||
class GroupedSamplerAllocator : private DescriptorAllocator
|
||||
{
|
||||
struct Key
|
||||
{
|
||||
u32 idx[NumSamplers];
|
||||
|
||||
__fi bool operator==(const Key& rhs) const
|
||||
{
|
||||
return (std::memcmp(idx, rhs.idx, sizeof(idx)) == 0);
|
||||
}
|
||||
__fi bool operator!=(const Key& rhs) const
|
||||
{
|
||||
return (std::memcmp(idx, rhs.idx, sizeof(idx)) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyHash
|
||||
{
|
||||
__fi std::size_t operator()(const Key& key) const
|
||||
{
|
||||
size_t seed = 0;
|
||||
for (u32 key : key.idx)
|
||||
HashCombine(seed, key);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
GroupedSamplerAllocator();
|
||||
~GroupedSamplerAllocator();
|
||||
|
||||
using DescriptorAllocator::GetDescriptorHeap;
|
||||
using DescriptorAllocator::GetDescriptorIncrementSize;
|
||||
|
||||
bool Create(ID3D12Device* device, u32 num_descriptors);
|
||||
void Destroy();
|
||||
|
||||
bool LookupSingle(DescriptorHandle* gpu_handle, const DescriptorHandle& cpu_handle);
|
||||
bool LookupGroup(DescriptorHandle* gpu_handle, const DescriptorHandle* cpu_handles);
|
||||
|
||||
// Clears cache but doesn't reset allocator.
|
||||
void InvalidateCache();
|
||||
|
||||
void Reset();
|
||||
bool ShouldReset() const;
|
||||
|
||||
private:
|
||||
wil::com_ptr_nothrow<ID3D12Device> m_device;
|
||||
std::unordered_map<Key, D3D12::DescriptorHandle, KeyHash> m_groups;
|
||||
};
|
||||
|
||||
template <u32 NumSamplers>
|
||||
GroupedSamplerAllocator<NumSamplers>::GroupedSamplerAllocator() = default;
|
||||
|
||||
template <u32 NumSamplers>
|
||||
GroupedSamplerAllocator<NumSamplers>::~GroupedSamplerAllocator() = default;
|
||||
|
||||
template <u32 NumSamplers>
|
||||
bool GroupedSamplerAllocator<NumSamplers>::Create(ID3D12Device* device, u32 num_descriptors)
|
||||
{
|
||||
if (!DescriptorAllocator::Create(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_descriptors))
|
||||
return false;
|
||||
|
||||
m_device = device;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
void GroupedSamplerAllocator<NumSamplers>::Destroy()
|
||||
{
|
||||
DescriptorAllocator::Destroy();
|
||||
m_device.reset();
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
void GroupedSamplerAllocator<NumSamplers>::Reset()
|
||||
{
|
||||
m_groups.clear();
|
||||
DescriptorAllocator::Reset();
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
void GroupedSamplerAllocator<NumSamplers>::InvalidateCache()
|
||||
{
|
||||
m_groups.clear();
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
bool GroupedSamplerAllocator<NumSamplers>::LookupSingle(DescriptorHandle* gpu_handle, const DescriptorHandle& cpu_handle)
|
||||
{
|
||||
Key key;
|
||||
key.idx[0] = cpu_handle.index;
|
||||
for (u32 i = 1; i < NumSamplers; i++)
|
||||
key.idx[i] = 0;
|
||||
|
||||
auto it = m_groups.find(key);
|
||||
if (it != m_groups.end())
|
||||
{
|
||||
*gpu_handle = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Allocate(1, gpu_handle))
|
||||
return false;
|
||||
|
||||
m_device->CopyDescriptorsSimple(1, *gpu_handle, cpu_handle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
m_groups.emplace(key, *gpu_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
bool GroupedSamplerAllocator<NumSamplers>::LookupGroup(DescriptorHandle* gpu_handle, const DescriptorHandle* cpu_handles)
|
||||
{
|
||||
Key key;
|
||||
for (u32 i = 0; i < NumSamplers; i++)
|
||||
key.idx[i] = cpu_handles[i].index;
|
||||
|
||||
auto it = m_groups.find(key);
|
||||
if (it != m_groups.end())
|
||||
{
|
||||
*gpu_handle = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Allocate(NumSamplers, gpu_handle))
|
||||
return false;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dst_handle = *gpu_handle;
|
||||
UINT dst_size = NumSamplers;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE src_handles[NumSamplers];
|
||||
UINT src_sizes[NumSamplers];
|
||||
for (u32 i = 0; i < NumSamplers; i++)
|
||||
{
|
||||
src_handles[i] = cpu_handles[i];
|
||||
src_sizes[i] = 1;
|
||||
}
|
||||
m_device->CopyDescriptors(1, &dst_handle, &dst_size, NumSamplers, src_handles, src_sizes, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
|
||||
m_groups.emplace(key, *gpu_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <u32 NumSamplers>
|
||||
bool GroupedSamplerAllocator<NumSamplers>::ShouldReset() const
|
||||
{
|
||||
// We only reset the sampler heap if more than half of the descriptors are used.
|
||||
// This saves descriptor copying when there isn't a large number of sampler configs per frame.
|
||||
return m_groups.size() >= (D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE / 2);
|
||||
}
|
||||
} // namespace D3D12
|
||||
@@ -1,156 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/HashCombine.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <d3d12.h>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
class ShaderCache
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
using ComPtr = wil::com_ptr_nothrow<T>;
|
||||
|
||||
enum class EntryType
|
||||
{
|
||||
VertexShader,
|
||||
GeometryShader,
|
||||
PixelShader,
|
||||
ComputeShader,
|
||||
GraphicsPipeline,
|
||||
ComputePipeline,
|
||||
};
|
||||
|
||||
ShaderCache();
|
||||
~ShaderCache();
|
||||
|
||||
__fi D3D_FEATURE_LEVEL GetFeatureLevel() const { return m_feature_level; }
|
||||
__fi u32 GetDataVersion() const { return m_data_version; }
|
||||
__fi bool UsingDebugShaders() const { return m_debug; }
|
||||
|
||||
bool Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
|
||||
|
||||
__fi ComPtr<ID3DBlob> GetVertexShader(std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
|
||||
{
|
||||
return GetShaderBlob(EntryType::VertexShader, shader_code, macros, entry_point);
|
||||
}
|
||||
__fi ComPtr<ID3DBlob> GetGeometryShader(std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
|
||||
{
|
||||
return GetShaderBlob(EntryType::GeometryShader, shader_code, macros, entry_point);
|
||||
}
|
||||
__fi ComPtr<ID3DBlob> GetPixelShader(std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
|
||||
{
|
||||
return GetShaderBlob(EntryType::PixelShader, shader_code, macros, entry_point);
|
||||
}
|
||||
__fi ComPtr<ID3DBlob> GetComputeShader(std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
|
||||
{
|
||||
return GetShaderBlob(EntryType::ComputeShader, shader_code, macros, entry_point);
|
||||
}
|
||||
|
||||
ComPtr<ID3DBlob> GetShaderBlob(EntryType type, std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
|
||||
ComPtr<ID3D12PipelineState> GetPipelineState(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC& desc);
|
||||
ComPtr<ID3D12PipelineState> GetPipelineState(ID3D12Device* device, const D3D12_COMPUTE_PIPELINE_STATE_DESC& desc);
|
||||
|
||||
private:
|
||||
static constexpr u32 FILE_VERSION = 1;
|
||||
|
||||
struct CacheIndexKey
|
||||
{
|
||||
u64 source_hash_low;
|
||||
u64 source_hash_high;
|
||||
u64 macro_hash_low;
|
||||
u64 macro_hash_high;
|
||||
u64 entry_point_low;
|
||||
u64 entry_point_high;
|
||||
u32 source_length;
|
||||
EntryType type;
|
||||
|
||||
bool operator==(const CacheIndexKey& key) const;
|
||||
bool operator!=(const CacheIndexKey& key) const;
|
||||
};
|
||||
|
||||
struct CacheIndexEntryHasher
|
||||
{
|
||||
std::size_t operator()(const CacheIndexKey& e) const noexcept
|
||||
{
|
||||
std::size_t h = 0;
|
||||
HashCombine(h, e.entry_point_low, e.entry_point_high, e.macro_hash_low, e.macro_hash_high,
|
||||
e.source_hash_low, e.source_hash_high, e.source_length, e.type);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct CacheIndexData
|
||||
{
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
};
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static std::string GetCacheBaseFileName(const std::string_view& base_path, const std::string_view& type,
|
||||
D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
static CacheIndexKey GetShaderCacheKey(EntryType type, const std::string_view& shader_code,
|
||||
const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
static CacheIndexKey GetPipelineCacheKey(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& gpdesc);
|
||||
static CacheIndexKey GetPipelineCacheKey(const D3D12_COMPUTE_PIPELINE_STATE_DESC& gpdesc);
|
||||
|
||||
bool CreateNew(const std::string& index_filename, const std::string& blob_filename, std::FILE*& index_file,
|
||||
std::FILE*& blob_file);
|
||||
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename, std::FILE*& index_file,
|
||||
std::FILE*& blob_file, CacheIndex& index);
|
||||
void InvalidatePipelineCache();
|
||||
void Close();
|
||||
|
||||
ComPtr<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
ComPtr<ID3D12PipelineState> CompileAndAddPipeline(ID3D12Device* device, const CacheIndexKey& key,
|
||||
const D3D12_GRAPHICS_PIPELINE_STATE_DESC& gpdesc);
|
||||
ComPtr<ID3D12PipelineState> CompileAndAddPipeline(ID3D12Device* device, const CacheIndexKey& key,
|
||||
const D3D12_COMPUTE_PIPELINE_STATE_DESC& gpdesc);
|
||||
bool AddPipelineToBlob(const CacheIndexKey& key, ID3D12PipelineState* pso);
|
||||
|
||||
std::string m_base_path;
|
||||
|
||||
std::FILE* m_shader_index_file = nullptr;
|
||||
std::FILE* m_shader_blob_file = nullptr;
|
||||
CacheIndex m_shader_index;
|
||||
|
||||
std::FILE* m_pipeline_index_file = nullptr;
|
||||
std::FILE* m_pipeline_blob_file = nullptr;
|
||||
CacheIndex m_pipeline_index;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
u32 m_data_version = 0;
|
||||
bool m_debug = false;
|
||||
};
|
||||
} // namespace D3D12
|
||||
@@ -1,77 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/RedtapeWilCom.h"
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
namespace D3D12MA
|
||||
{
|
||||
class Allocation;
|
||||
}
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
class StreamBuffer
|
||||
{
|
||||
public:
|
||||
StreamBuffer();
|
||||
~StreamBuffer();
|
||||
|
||||
bool Create(u32 size);
|
||||
|
||||
__fi bool IsValid() const { return static_cast<bool>(m_buffer); }
|
||||
__fi ID3D12Resource* GetBuffer() const { return m_buffer.get(); }
|
||||
__fi D3D12_GPU_VIRTUAL_ADDRESS GetGPUPointer() const { return m_gpu_pointer; }
|
||||
__fi void* GetHostPointer() const { return m_host_pointer; }
|
||||
__fi void* GetCurrentHostPointer() const { return m_host_pointer + m_current_offset; }
|
||||
__fi D3D12_GPU_VIRTUAL_ADDRESS GetCurrentGPUPointer() const { return m_gpu_pointer + m_current_offset; }
|
||||
__fi u32 GetSize() const { return m_size; }
|
||||
__fi u32 GetCurrentOffset() const { return m_current_offset; }
|
||||
__fi u32 GetCurrentSpace() const { return m_current_space; }
|
||||
|
||||
bool ReserveMemory(u32 num_bytes, u32 alignment);
|
||||
void CommitMemory(u32 final_num_bytes);
|
||||
|
||||
void Destroy(bool defer = true);
|
||||
|
||||
private:
|
||||
void UpdateCurrentFencePosition();
|
||||
void UpdateGPUPosition();
|
||||
|
||||
// Waits for as many fences as needed to allocate num_bytes bytes from the buffer.
|
||||
bool WaitForClearSpace(u32 num_bytes);
|
||||
|
||||
u32 m_size = 0;
|
||||
u32 m_current_offset = 0;
|
||||
u32 m_current_space = 0;
|
||||
u32 m_current_gpu_position = 0;
|
||||
|
||||
wil::com_ptr_nothrow<ID3D12Resource> m_buffer;
|
||||
wil::com_ptr_nothrow<D3D12MA::Allocation> m_allocation;
|
||||
D3D12_GPU_VIRTUAL_ADDRESS m_gpu_pointer = {};
|
||||
u8* m_host_pointer = nullptr;
|
||||
|
||||
// List of fences and the corresponding positions in the buffer
|
||||
std::deque<std::pair<u64, u32>> m_tracked_fences;
|
||||
};
|
||||
|
||||
} // namespace D3D12
|
||||
@@ -1,506 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/D3D12/Texture.h"
|
||||
#include "common/D3D12/Context.h"
|
||||
#include "common/D3D12/Util.h"
|
||||
#include "common/Align.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "D3D12MemAlloc.h"
|
||||
|
||||
using namespace D3D12;
|
||||
|
||||
Texture::Texture() = default;
|
||||
|
||||
Texture::Texture(ID3D12Resource* resource, D3D12_RESOURCE_STATES state)
|
||||
: m_resource(std::move(resource))
|
||||
{
|
||||
const D3D12_RESOURCE_DESC desc = GetDesc();
|
||||
m_width = static_cast<u32>(desc.Width);
|
||||
m_height = desc.Height;
|
||||
m_levels = desc.MipLevels;
|
||||
m_format = desc.Format;
|
||||
}
|
||||
|
||||
Texture::Texture(Texture&& texture)
|
||||
: m_resource(std::move(texture.m_resource))
|
||||
, m_allocation(std::move(texture.m_allocation))
|
||||
, m_srv_descriptor(texture.m_srv_descriptor)
|
||||
, m_write_descriptor(texture.m_write_descriptor)
|
||||
, m_width(texture.m_width)
|
||||
, m_height(texture.m_height)
|
||||
, m_levels(texture.m_levels)
|
||||
, m_format(texture.m_format)
|
||||
, m_state(texture.m_state)
|
||||
, m_write_descriptor_type(texture.m_write_descriptor_type)
|
||||
{
|
||||
texture.m_srv_descriptor = {};
|
||||
texture.m_write_descriptor = {};
|
||||
texture.m_width = 0;
|
||||
texture.m_height = 0;
|
||||
texture.m_levels = 0;
|
||||
texture.m_format = DXGI_FORMAT_UNKNOWN;
|
||||
texture.m_state = D3D12_RESOURCE_STATE_COMMON;
|
||||
texture.m_write_descriptor_type = WriteDescriptorType::None;
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
Texture& Texture::operator=(Texture&& texture)
|
||||
{
|
||||
Destroy();
|
||||
m_resource = std::move(texture.m_resource);
|
||||
m_allocation = std::move(texture.m_allocation);
|
||||
m_srv_descriptor = texture.m_srv_descriptor;
|
||||
m_write_descriptor = texture.m_write_descriptor;
|
||||
m_width = texture.m_width;
|
||||
m_height = texture.m_height;
|
||||
m_levels = texture.m_levels;
|
||||
m_format = texture.m_format;
|
||||
m_state = texture.m_state;
|
||||
m_write_descriptor_type = texture.m_write_descriptor_type;
|
||||
texture.m_srv_descriptor = {};
|
||||
texture.m_write_descriptor = {};
|
||||
texture.m_width = 0;
|
||||
texture.m_height = 0;
|
||||
texture.m_levels = 0;
|
||||
texture.m_format = DXGI_FORMAT_UNKNOWN;
|
||||
texture.m_state = D3D12_RESOURCE_STATE_COMMON;
|
||||
texture.m_write_descriptor_type = WriteDescriptorType::None;
|
||||
return *this;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_DESC Texture::GetDesc() const
|
||||
{
|
||||
return m_resource->GetDesc();
|
||||
}
|
||||
|
||||
bool Texture::Create(u32 width, u32 height, u32 levels, DXGI_FORMAT format, DXGI_FORMAT srv_format,
|
||||
DXGI_FORMAT rtv_format, DXGI_FORMAT dsv_format, D3D12_RESOURCE_FLAGS flags, u32 alloc_flags)
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = levels;
|
||||
desc.Format = format;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = flags;
|
||||
|
||||
D3D12_CLEAR_VALUE optimized_clear_value = {};
|
||||
D3D12_RESOURCE_STATES state;
|
||||
if (rtv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
optimized_clear_value.Format = rtv_format;
|
||||
state = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
}
|
||||
else if (dsv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
optimized_clear_value.Format = dsv_format;
|
||||
state = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
}
|
||||
|
||||
D3D12MA::ALLOCATION_DESC allocationDesc = {};
|
||||
allocationDesc.Flags = static_cast<D3D12MA::ALLOCATION_FLAGS>(alloc_flags) | D3D12MA::ALLOCATION_FLAG_WITHIN_BUDGET;
|
||||
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
ComPtr<ID3D12Resource> resource;
|
||||
ComPtr<D3D12MA::Allocation> allocation;
|
||||
HRESULT hr = g_d3d12_context->GetAllocator()->CreateResource(
|
||||
&allocationDesc, &desc, state,
|
||||
(rtv_format != DXGI_FORMAT_UNKNOWN || dsv_format != DXGI_FORMAT_UNKNOWN) ? &optimized_clear_value : nullptr,
|
||||
allocation.put(), IID_PPV_ARGS(resource.put()));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// OOM isn't fatal.
|
||||
if (hr != E_OUTOFMEMORY)
|
||||
Console.Error("Create texture failed: 0x%08X", hr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DescriptorHandle srv_descriptor, write_descriptor;
|
||||
WriteDescriptorType write_descriptor_type = WriteDescriptorType::None;
|
||||
if (srv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (!CreateSRVDescriptor(resource.get(), levels, srv_format, &srv_descriptor))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
pxAssert(dsv_format == DXGI_FORMAT_UNKNOWN && !(flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS));
|
||||
write_descriptor_type = Texture::WriteDescriptorType::RTV;
|
||||
if (!CreateRTVDescriptor(resource.get(), rtv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetRTVHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else if (dsv_format != DXGI_FORMAT_UNKNOWN && !(flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
|
||||
{
|
||||
write_descriptor_type = Texture::WriteDescriptorType::DSV;
|
||||
if (!CreateDSVDescriptor(resource.get(), dsv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetDSVHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
|
||||
{
|
||||
write_descriptor_type = Texture::WriteDescriptorType::UAV;
|
||||
if (!CreateUAVDescriptor(resource.get(), dsv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetDescriptorHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Destroy(true);
|
||||
|
||||
m_resource = std::move(resource);
|
||||
m_allocation = std::move(allocation);
|
||||
m_srv_descriptor = std::move(srv_descriptor);
|
||||
m_write_descriptor = std::move(write_descriptor);
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_levels = levels;
|
||||
m_format = format;
|
||||
m_state = state;
|
||||
m_write_descriptor_type = write_descriptor_type;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::Adopt(ComPtr<ID3D12Resource> texture, DXGI_FORMAT srv_format, DXGI_FORMAT rtv_format,
|
||||
DXGI_FORMAT dsv_format, D3D12_RESOURCE_STATES state)
|
||||
{
|
||||
const D3D12_RESOURCE_DESC desc(texture->GetDesc());
|
||||
|
||||
DescriptorHandle srv_descriptor, write_descriptor;
|
||||
WriteDescriptorType write_descriptor_type = WriteDescriptorType::None;
|
||||
if (srv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (!CreateSRVDescriptor(texture.get(), desc.MipLevels, srv_format, &srv_descriptor))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rtv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
pxAssert(dsv_format == DXGI_FORMAT_UNKNOWN);
|
||||
write_descriptor_type = Texture::WriteDescriptorType::RTV;
|
||||
if (!CreateRTVDescriptor(texture.get(), rtv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetRTVHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (dsv_format != DXGI_FORMAT_UNKNOWN)
|
||||
{
|
||||
write_descriptor_type = Texture::WriteDescriptorType::DSV;
|
||||
if (!CreateDSVDescriptor(texture.get(), dsv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetDSVHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
|
||||
{
|
||||
write_descriptor_type = Texture::WriteDescriptorType::UAV;
|
||||
if (!CreateUAVDescriptor(texture.get(), srv_format, &write_descriptor))
|
||||
{
|
||||
g_d3d12_context->GetDescriptorHeapManager().Free(&srv_descriptor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_resource = std::move(texture);
|
||||
m_allocation.reset();
|
||||
m_srv_descriptor = std::move(srv_descriptor);
|
||||
m_write_descriptor = std::move(write_descriptor);
|
||||
m_write_descriptor_type = write_descriptor_type;
|
||||
m_width = static_cast<u32>(desc.Width);
|
||||
m_height = desc.Height;
|
||||
m_levels = desc.MipLevels;
|
||||
m_format = desc.Format;
|
||||
m_state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Texture::Destroy(bool defer /* = true */)
|
||||
{
|
||||
if (defer)
|
||||
{
|
||||
g_d3d12_context->DeferDescriptorDestruction(g_d3d12_context->GetDescriptorHeapManager(), &m_srv_descriptor);
|
||||
|
||||
switch (m_write_descriptor_type)
|
||||
{
|
||||
case Texture::WriteDescriptorType::RTV:
|
||||
g_d3d12_context->DeferDescriptorDestruction(g_d3d12_context->GetRTVHeapManager(), &m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::DSV:
|
||||
g_d3d12_context->DeferDescriptorDestruction(g_d3d12_context->GetDSVHeapManager(), &m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::UAV:
|
||||
g_d3d12_context->DeferDescriptorDestruction(g_d3d12_context->GetDescriptorHeapManager(), &m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_d3d12_context->DeferResourceDestruction(m_allocation.get(), m_resource.get());
|
||||
m_resource.reset();
|
||||
m_allocation.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_d3d12_context->GetDescriptorHeapManager().Free(&m_srv_descriptor);
|
||||
|
||||
switch (m_write_descriptor_type)
|
||||
{
|
||||
case Texture::WriteDescriptorType::RTV:
|
||||
g_d3d12_context->GetRTVHeapManager().Free(&m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::DSV:
|
||||
g_d3d12_context->GetDSVHeapManager().Free(&m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::UAV:
|
||||
g_d3d12_context->GetDescriptorHeapManager().Free(&m_write_descriptor);
|
||||
break;
|
||||
case Texture::WriteDescriptorType::None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_resource.reset();
|
||||
m_allocation.reset();
|
||||
}
|
||||
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_levels = 0;
|
||||
m_format = DXGI_FORMAT_UNKNOWN;
|
||||
m_write_descriptor_type = WriteDescriptorType::None;
|
||||
}
|
||||
|
||||
void Texture::TransitionToState(ID3D12GraphicsCommandList* cmdlist, D3D12_RESOURCE_STATES state)
|
||||
{
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
ResourceBarrier(cmdlist, m_resource.get(), m_state, state);
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
void Texture::TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, u32 level,
|
||||
D3D12_RESOURCE_STATES before_state, D3D12_RESOURCE_STATES after_state) const
|
||||
{
|
||||
const D3D12_RESOURCE_BARRIER barrier = {D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
{{m_resource.get(), level, before_state, after_state}}};
|
||||
cmdlist->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* Texture::BeginStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch)
|
||||
{
|
||||
const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
||||
const u32 upload_size = copy_pitch * height;
|
||||
|
||||
if (!g_d3d12_context->GetTextureStreamBuffer().ReserveMemory(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT))
|
||||
{
|
||||
DevCon.WriteLn("Executing command buffer while waiting for %u bytes (%ux%u) in upload buffer", upload_size, width,
|
||||
height);
|
||||
g_d3d12_context->ExecuteCommandList(Context::WaitType::None);
|
||||
if (!g_d3d12_context->GetTextureStreamBuffer().ReserveMemory(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT))
|
||||
{
|
||||
Console.Error("Failed to reserve %u bytes for %ux%u upload", upload_size, width, height);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// cmdlist change
|
||||
cmdlist = g_d3d12_context->GetInitCommandList();
|
||||
}
|
||||
|
||||
*out_data = g_d3d12_context->GetTextureStreamBuffer().GetCurrentHostPointer();
|
||||
*out_data_pitch = copy_pitch;
|
||||
return cmdlist;
|
||||
}
|
||||
|
||||
void Texture::EndStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
||||
const u32 upload_size = copy_pitch * height;
|
||||
|
||||
StreamBuffer& sb = g_d3d12_context->GetTextureStreamBuffer();
|
||||
const u32 sb_offset = sb.GetCurrentOffset();
|
||||
sb.CommitMemory(upload_size);
|
||||
|
||||
CopyFromBuffer(cmdlist, level, x, y, width, height, copy_pitch, sb.GetBuffer(), sb_offset);
|
||||
}
|
||||
|
||||
void Texture::CopyFromBuffer(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset)
|
||||
{
|
||||
D3D12_TEXTURE_COPY_LOCATION src;
|
||||
src.pResource = buffer;
|
||||
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
src.PlacedFootprint.Offset = buffer_offset;
|
||||
src.PlacedFootprint.Footprint.Width = width;
|
||||
src.PlacedFootprint.Footprint.Height = height;
|
||||
src.PlacedFootprint.Footprint.Depth = 1;
|
||||
src.PlacedFootprint.Footprint.RowPitch = pitch;
|
||||
src.PlacedFootprint.Footprint.Format = m_format;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst;
|
||||
dst.pResource = m_resource.get();
|
||||
dst.SubresourceIndex = level;
|
||||
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
|
||||
const D3D12_BOX src_box{0u, 0u, 0u, width, height, 1u};
|
||||
const D3D12_RESOURCE_STATES old_state = m_state;
|
||||
TransitionToState(cmdlist, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
cmdlist->CopyTextureRegion(&dst, x, y, 0, &src, &src_box);
|
||||
TransitionToState(cmdlist, old_state);
|
||||
}
|
||||
|
||||
static ID3D12Resource* CreateStagingBuffer(u32 height, const void* data, u32 pitch, u32 upload_pitch, u32 upload_size)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3D12Resource> resource;
|
||||
wil::com_ptr_nothrow<D3D12MA::Allocation> allocation;
|
||||
|
||||
const D3D12MA::ALLOCATION_DESC allocation_desc = {D3D12MA::ALLOCATION_FLAG_NONE, D3D12_HEAP_TYPE_UPLOAD};
|
||||
const D3D12_RESOURCE_DESC resource_desc = {
|
||||
D3D12_RESOURCE_DIMENSION_BUFFER, 0, upload_size, 1, 1, 1, DXGI_FORMAT_UNKNOWN, {1, 0}, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
D3D12_RESOURCE_FLAG_NONE};
|
||||
HRESULT hr = g_d3d12_context->GetAllocator()->CreateResource(&allocation_desc, &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr, allocation.put(), IID_PPV_ARGS(resource.put()));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("CreateResource() for upload staging buffer failed: %08X", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* map;
|
||||
const D3D12_RANGE read_range = {};
|
||||
hr = resource->Map(0, &read_range, &map);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("Map() for upload staging buffer failed: %08X", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StringUtil::StrideMemCpy(map, upload_pitch, data, pitch, std::min(pitch, upload_pitch), height);
|
||||
|
||||
const D3D12_RANGE write_range = {0u, upload_size};
|
||||
resource->Unmap(0, &write_range);
|
||||
|
||||
// queue them for destruction, since the upload happens in this cmdlist
|
||||
g_d3d12_context->DeferResourceDestruction(allocation.get(), resource.get());
|
||||
|
||||
// AddRef()'ed by the defer above.
|
||||
return resource.get();
|
||||
}
|
||||
|
||||
bool Texture::LoadData(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch)
|
||||
{
|
||||
const u32 texel_size = GetTexelSize(m_format);
|
||||
const u32 upload_pitch = Common::AlignUpPow2(width * texel_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
||||
const u32 upload_size = upload_pitch * height;
|
||||
if (upload_size >= g_d3d12_context->GetTextureStreamBuffer().GetSize())
|
||||
{
|
||||
ID3D12Resource* staging_buffer = CreateStagingBuffer(height, data, pitch, upload_pitch, upload_size);
|
||||
if (!staging_buffer)
|
||||
return false;
|
||||
|
||||
CopyFromBuffer(cmdlist, level, x, y, width, height, upload_pitch, staging_buffer, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void* write_ptr;
|
||||
u32 write_pitch;
|
||||
if (!(cmdlist = BeginStreamUpdate(cmdlist, level, x, y, width, height, &write_ptr, &write_pitch)))
|
||||
return false;
|
||||
|
||||
StringUtil::StrideMemCpy(write_ptr, write_pitch, data, pitch, std::min(pitch, upload_pitch), height);
|
||||
EndStreamUpdate(cmdlist, level, x, y, width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::CreateSRVDescriptor(ID3D12Resource* resource, u32 levels, DXGI_FORMAT format, DescriptorHandle* dh)
|
||||
{
|
||||
if (!g_d3d12_context->GetDescriptorHeapManager().Allocate(dh))
|
||||
{
|
||||
Console.Error("Failed to allocate SRV descriptor");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC desc = {format, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING};
|
||||
desc.Texture2D.MipLevels = levels;
|
||||
|
||||
g_d3d12_context->GetDevice()->CreateShaderResourceView(resource, &desc, dh->cpu_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::CreateRTVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh)
|
||||
{
|
||||
if (!g_d3d12_context->GetRTVHeapManager().Allocate(dh))
|
||||
{
|
||||
Console.Error("Failed to allocate SRV descriptor");
|
||||
return false;
|
||||
}
|
||||
|
||||
const D3D12_RENDER_TARGET_VIEW_DESC desc = {format, D3D12_RTV_DIMENSION_TEXTURE2D};
|
||||
g_d3d12_context->GetDevice()->CreateRenderTargetView(resource, &desc, dh->cpu_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::CreateDSVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh)
|
||||
{
|
||||
if (!g_d3d12_context->GetDSVHeapManager().Allocate(dh))
|
||||
{
|
||||
Console.Error("Failed to allocate SRV descriptor");
|
||||
return false;
|
||||
}
|
||||
|
||||
const D3D12_DEPTH_STENCIL_VIEW_DESC desc = {format, D3D12_DSV_DIMENSION_TEXTURE2D, D3D12_DSV_FLAG_NONE};
|
||||
g_d3d12_context->GetDevice()->CreateDepthStencilView(resource, &desc, dh->cpu_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::CreateUAVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh)
|
||||
{
|
||||
if (!g_d3d12_context->GetDescriptorHeapManager().Allocate(dh))
|
||||
{
|
||||
Console.Error("Failed to allocate UAV descriptor");
|
||||
return false;
|
||||
}
|
||||
|
||||
const D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {format, D3D12_UAV_DIMENSION_TEXTURE2D};
|
||||
g_d3d12_context->GetDevice()->CreateUnorderedAccessView(resource, nullptr, &desc, dh->cpu_handle);
|
||||
return true;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/D3D12/DescriptorHeapManager.h"
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <wil/com.h>
|
||||
|
||||
namespace D3D12MA
|
||||
{
|
||||
class Allocation;
|
||||
}
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
class StreamBuffer;
|
||||
|
||||
class Texture final
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
using ComPtr = wil::com_ptr_nothrow<T>;
|
||||
|
||||
Texture();
|
||||
Texture(ID3D12Resource* resource, D3D12_RESOURCE_STATES state);
|
||||
Texture(Texture&& texture);
|
||||
Texture(const Texture&) = delete;
|
||||
~Texture();
|
||||
|
||||
__fi ID3D12Resource* GetResource() const { return m_resource.get(); }
|
||||
__fi D3D12MA::Allocation* GetAllocation() const { return m_allocation.get(); }
|
||||
__fi const DescriptorHandle& GetSRVDescriptor() const { return m_srv_descriptor; }
|
||||
__fi const DescriptorHandle& GetWriteDescriptor() const { return m_write_descriptor; }
|
||||
__fi D3D12_RESOURCE_STATES GetState() const { return m_state; }
|
||||
|
||||
__fi u32 GetWidth() const { return m_width; }
|
||||
__fi u32 GetHeight() const { return m_height; }
|
||||
__fi u32 GetLevels() const { return m_levels; }
|
||||
__fi DXGI_FORMAT GetFormat() const { return m_format; }
|
||||
|
||||
__fi operator ID3D12Resource*() const { return m_resource.get(); }
|
||||
__fi operator bool() const { return static_cast<bool>(m_resource); }
|
||||
|
||||
bool Create(u32 width, u32 height, u32 levels, DXGI_FORMAT format, DXGI_FORMAT srv_format,
|
||||
DXGI_FORMAT rtv_format, DXGI_FORMAT dsv_format, D3D12_RESOURCE_FLAGS flags, u32 alloc_flags = 0);
|
||||
bool Adopt(ComPtr<ID3D12Resource> texture, DXGI_FORMAT srv_format, DXGI_FORMAT rtv_format, DXGI_FORMAT dsv_format,
|
||||
D3D12_RESOURCE_STATES state);
|
||||
|
||||
D3D12_RESOURCE_DESC GetDesc() const;
|
||||
|
||||
void Destroy(bool defer = true);
|
||||
|
||||
void TransitionToState(ID3D12GraphicsCommandList* cmdlist, D3D12_RESOURCE_STATES state);
|
||||
void TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, u32 level,
|
||||
D3D12_RESOURCE_STATES before_state, D3D12_RESOURCE_STATES after_state) const;
|
||||
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
Texture& operator=(Texture&& texture);
|
||||
|
||||
// NOTE: Does not handle compressed formats.
|
||||
ID3D12GraphicsCommandList* BeginStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch);
|
||||
void EndStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height);
|
||||
bool LoadData(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch);
|
||||
void CopyFromBuffer(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset);
|
||||
|
||||
private:
|
||||
static bool CreateSRVDescriptor(ID3D12Resource* resource, u32 levels, DXGI_FORMAT format, DescriptorHandle* dh);
|
||||
static bool CreateRTVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh);
|
||||
static bool CreateDSVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh);
|
||||
static bool CreateUAVDescriptor(ID3D12Resource* resource, DXGI_FORMAT format, DescriptorHandle* dh);
|
||||
|
||||
enum class WriteDescriptorType : u8
|
||||
{
|
||||
None,
|
||||
RTV,
|
||||
DSV,
|
||||
UAV
|
||||
};
|
||||
|
||||
ComPtr<ID3D12Resource> m_resource;
|
||||
ComPtr<D3D12MA::Allocation> m_allocation;
|
||||
DescriptorHandle m_srv_descriptor = {};
|
||||
DescriptorHandle m_write_descriptor = {};
|
||||
u32 m_width = 0;
|
||||
u32 m_height = 0;
|
||||
u32 m_levels = 0;
|
||||
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_STATES m_state = D3D12_RESOURCE_STATE_COMMON;
|
||||
|
||||
WriteDescriptorType m_write_descriptor_type = WriteDescriptorType::None;
|
||||
};
|
||||
} // namespace D3D12
|
||||
@@ -1,93 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/D3D12/Util.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
u32 D3D12::GetTexelSize(DXGI_FORMAT format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
case DXGI_FORMAT_BC2_UNORM:
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
return 16;
|
||||
|
||||
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||
return 4;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
||||
case DXGI_FORMAT_R32_UINT:
|
||||
case DXGI_FORMAT_R32_SINT:
|
||||
return 4;
|
||||
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
case DXGI_FORMAT_R16_UINT:
|
||||
case DXGI_FORMAT_R16_SINT:
|
||||
return 2;
|
||||
|
||||
case DXGI_FORMAT_A8_UNORM:
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
pxFailRel("Unknown format");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12::SetDefaultSampler(D3D12_SAMPLER_DESC* desc)
|
||||
{
|
||||
desc->Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
desc->AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
desc->AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
desc->AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
desc->MipLODBias = 0;
|
||||
desc->MaxAnisotropy = 1;
|
||||
desc->ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||
desc->BorderColor[0] = 1.0f;
|
||||
desc->BorderColor[1] = 1.0f;
|
||||
desc->BorderColor[2] = 1.0f;
|
||||
desc->BorderColor[3] = 1.0f;
|
||||
desc->MinLOD = -3.402823466e+38F; // -FLT_MAX
|
||||
desc->MaxLOD = 3.402823466e+38F; // FLT_MAX
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void D3D12::SetObjectName(ID3D12Object* object, const char* name)
|
||||
{
|
||||
object->SetName(StringUtil::UTF8StringToWideString(name).c_str());
|
||||
}
|
||||
|
||||
void D3D12::SetObjectNameFormatted(ID3D12Object* object, const char* format, ...)
|
||||
{
|
||||
std::va_list ap;
|
||||
va_start(ap, format);
|
||||
SetObjectName(object, StringUtil::StdStringFromFormatV(format, ap).c_str());
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,77 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
|
||||
#include <array>
|
||||
#include <d3d12.h>
|
||||
|
||||
namespace D3D12
|
||||
{
|
||||
static inline void ResourceBarrier(ID3D12GraphicsCommandList* cmdlist, ID3D12Resource* resource,
|
||||
D3D12_RESOURCE_STATES from_state, D3D12_RESOURCE_STATES to_state)
|
||||
{
|
||||
const D3D12_RESOURCE_BARRIER barrier = {D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
|
||||
D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||
{{resource, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, from_state, to_state}}};
|
||||
cmdlist->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
static inline void SetViewport(ID3D12GraphicsCommandList* cmdlist, int x, int y, int width, int height,
|
||||
float min_depth = 0.0f, float max_depth = 1.0f)
|
||||
{
|
||||
const D3D12_VIEWPORT vp{static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
static_cast<float>(width),
|
||||
static_cast<float>(height),
|
||||
min_depth,
|
||||
max_depth};
|
||||
cmdlist->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
static inline void SetScissor(ID3D12GraphicsCommandList* cmdlist, int x, int y, int width, int height)
|
||||
{
|
||||
const D3D12_RECT r{x, y, x + width, y + height};
|
||||
cmdlist->RSSetScissorRects(1, &r);
|
||||
}
|
||||
|
||||
static inline void SetViewportAndScissor(ID3D12GraphicsCommandList* cmdlist, int x, int y, int width, int height,
|
||||
float min_depth = 0.0f, float max_depth = 1.0f)
|
||||
{
|
||||
SetViewport(cmdlist, x, y, width, height, min_depth, max_depth);
|
||||
SetScissor(cmdlist, x, y, width, height);
|
||||
}
|
||||
|
||||
u32 GetTexelSize(DXGI_FORMAT format);
|
||||
|
||||
void SetDefaultSampler(D3D12_SAMPLER_DESC* desc);
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
void SetObjectName(ID3D12Object* object, const char* name);
|
||||
void SetObjectNameFormatted(ID3D12Object* object, const char* format, ...);
|
||||
|
||||
#else
|
||||
|
||||
static inline void SetObjectName(ID3D12Object* object, const char* name)
|
||||
{
|
||||
}
|
||||
static inline void SetObjectNameFormatted(ID3D12Object* object, const char* format, ...) {}
|
||||
|
||||
#endif
|
||||
} // namespace D3D12
|
||||
@@ -15,8 +15,11 @@
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#include "common/Darwin/DarwinMisc.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <optional>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <time.h>
|
||||
@@ -24,6 +27,7 @@
|
||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
||||
|
||||
#include "common/Pcsx2Types.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
#include "common/Threading.h"
|
||||
#include "common/WindowInfo.h"
|
||||
@@ -89,6 +93,20 @@ static std::string sysctl_str(int category, int name)
|
||||
return std::string(buf, len > 0 ? len - 1 : 0);
|
||||
}
|
||||
|
||||
static std::optional<u32> sysctlbyname_u32(const char* name)
|
||||
{
|
||||
u32 output;
|
||||
size_t output_size = sizeof(output);
|
||||
if (0 != sysctlbyname(name, &output, &output_size, nullptr, 0))
|
||||
return std::nullopt;
|
||||
if (output_size != sizeof(output))
|
||||
{
|
||||
DevCon.WriteLn("(DarwinMisc) sysctl %s gave unexpected size %zd", name, output_size);
|
||||
return std::nullopt;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string GetOSVersionString()
|
||||
{
|
||||
std::string type = sysctl_str(CTL_KERN, KERN_OSTYPE);
|
||||
@@ -135,4 +153,46 @@ void Threading::SleepUntil(u64 ticks)
|
||||
nanosleep(&ts, nullptr);
|
||||
}
|
||||
|
||||
std::vector<DarwinMisc::CPUClass> DarwinMisc::GetCPUClasses()
|
||||
{
|
||||
std::vector<CPUClass> out;
|
||||
|
||||
if (std::optional<u32> nperflevels = sysctlbyname_u32("hw.nperflevels"))
|
||||
{
|
||||
char name[64];
|
||||
for (u32 i = 0; i < *nperflevels; i++)
|
||||
{
|
||||
snprintf(name, sizeof(name), "hw.perflevel%u.physicalcpu", i);
|
||||
std::optional<u32> physicalcpu = sysctlbyname_u32(name);
|
||||
snprintf(name, sizeof(name), "hw.perflevel%u.logicalcpu", i);
|
||||
std::optional<u32> logicalcpu = sysctlbyname_u32(name);
|
||||
|
||||
char levelname[64];
|
||||
size_t levelname_size = sizeof(levelname);
|
||||
snprintf(name, sizeof(name), "hw.perflevel%u.name", i);
|
||||
if (0 != sysctlbyname(name, levelname, &levelname_size, nullptr, 0))
|
||||
strcpy(levelname, "???");
|
||||
|
||||
if (!physicalcpu.has_value() || !logicalcpu.has_value())
|
||||
{
|
||||
Console.Warning("(DarwinMisc) Perf level %u is missing data on %s cpus!",
|
||||
i, !physicalcpu.has_value() ? "physical" : "logical");
|
||||
continue;
|
||||
}
|
||||
|
||||
out.push_back({levelname, *physicalcpu, *logicalcpu});
|
||||
}
|
||||
}
|
||||
else if (std::optional<u32> physcpu = sysctlbyname_u32("hw.physicalcpu"))
|
||||
{
|
||||
out.push_back({"Default", *physcpu, sysctlbyname_u32("hw.logicalcpu").value_or(0)});
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("(DarwinMisc) Couldn't get cpu core count!");
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
* Copyright (C) 2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
@@ -13,10 +13,24 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "GSDeviceNull.h"
|
||||
#pragma once
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/Pcsx2Types.h"
|
||||
|
||||
namespace DarwinMisc {
|
||||
|
||||
struct CPUClass {
|
||||
std::string name;
|
||||
u32 num_physical;
|
||||
u32 num_logical;
|
||||
};
|
||||
|
||||
std::vector<CPUClass> GetCPUClasses();
|
||||
|
||||
GSTexture* GSDeviceNull::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
|
||||
{
|
||||
return new GSTextureNull(type, width, height, levels, format);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,184 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/Console.h"
|
||||
#include "common/GL/Context.h"
|
||||
#include "glad.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#ifdef __APPLE__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_M_ARM64)
|
||||
#include "common/GL/ContextWGL.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include "common/GL/ContextAGL.h"
|
||||
#else
|
||||
#ifdef X11_API
|
||||
#include "common/GL/ContextEGLX11.h"
|
||||
#endif
|
||||
#ifdef WAYLAND_API
|
||||
#include "common/GL/ContextEGLWayland.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace GL
|
||||
{
|
||||
static bool ShouldPreferESContext()
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
const char* value = std::getenv("PREFER_GLES_CONTEXT");
|
||||
return (value && std::strcmp(value, "1") == 0);
|
||||
#else
|
||||
char buffer[2] = {};
|
||||
size_t buffer_size = sizeof(buffer);
|
||||
getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT");
|
||||
return (std::strcmp(buffer, "1") == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DisableBrokenExtensions(const char* gl_vendor, const char* gl_renderer)
|
||||
{
|
||||
if (std::strstr(gl_vendor, "ARM"))
|
||||
{
|
||||
// GL_{EXT,OES}_copy_image seem to be implemented on the CPU in the Mali drivers...
|
||||
Console.Warning("Mali driver detected, disabling GL_{EXT,OES}_copy_image");
|
||||
GLAD_GL_EXT_copy_image = 0;
|
||||
GLAD_GL_OES_copy_image = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Context::Context(const WindowInfo& wi)
|
||||
: m_wi(wi)
|
||||
{
|
||||
}
|
||||
|
||||
Context::~Context() = default;
|
||||
|
||||
std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
if (ShouldPreferESContext())
|
||||
{
|
||||
// move ES versions to the front
|
||||
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * versions_to_try.size()));
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < versions_to_try.size(); i++)
|
||||
{
|
||||
if (versions_to_try[i].profile == Profile::ES)
|
||||
new_versions_to_try[count++] = versions_to_try[i];
|
||||
}
|
||||
for (size_t i = 0; i < versions_to_try.size(); i++)
|
||||
{
|
||||
if (versions_to_try[i].profile != Profile::ES)
|
||||
new_versions_to_try[count++] = versions_to_try[i];
|
||||
}
|
||||
versions_to_try = gsl::span<const Version>(new_versions_to_try, versions_to_try.size());
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> context;
|
||||
#if defined(_WIN32) && !defined(_M_ARM64)
|
||||
context = ContextWGL::Create(wi, versions_to_try);
|
||||
#elif defined(__APPLE__)
|
||||
context = ContextAGL::Create(wi, versions_to_try);
|
||||
#endif
|
||||
|
||||
#if defined(X11_API)
|
||||
if (wi.type == WindowInfo::Type::X11)
|
||||
context = ContextEGLX11::Create(wi, versions_to_try);
|
||||
#endif
|
||||
|
||||
#if defined(WAYLAND_API)
|
||||
if (wi.type == WindowInfo::Type::Wayland)
|
||||
context = ContextEGLWayland::Create(wi, versions_to_try);
|
||||
#endif
|
||||
|
||||
if (!context)
|
||||
return nullptr;
|
||||
|
||||
Console.WriteLn("Created a %s context", context->IsGLES() ? "OpenGL ES" : "OpenGL");
|
||||
|
||||
// NOTE: Not thread-safe. But this is okay, since we're not going to be creating more than one context at a time.
|
||||
static Context* context_being_created;
|
||||
context_being_created = context.get();
|
||||
|
||||
// load up glad
|
||||
if (!context->IsGLES())
|
||||
{
|
||||
if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
||||
{
|
||||
Console.Error("Failed to load GL functions for GLAD");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gladLoadGLES2Loader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
||||
{
|
||||
Console.Error("Failed to load GLES functions for GLAD");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
context_being_created = nullptr;
|
||||
|
||||
const char* gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
||||
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
const char* gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
DevCon.WriteLn(Color_Magenta, "GL_VENDOR: %s", gl_vendor);
|
||||
DevCon.WriteLn(Color_Magenta, "GL_RENDERER: %s", gl_renderer);
|
||||
DevCon.WriteLn(Color_Magenta, "GL_VERSION: %s", gl_version);
|
||||
DevCon.WriteLn(Color_Magenta, "GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
|
||||
|
||||
DisableBrokenExtensions(gl_vendor, gl_renderer);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
gsl::span<const Context::Version> Context::GetAllVersionsList()
|
||||
{
|
||||
static constexpr Version vlist[] = {
|
||||
{Profile::Core, 4, 6},
|
||||
{Profile::Core, 4, 5},
|
||||
{Profile::Core, 4, 4},
|
||||
{Profile::Core, 4, 3},
|
||||
{Profile::Core, 4, 2},
|
||||
{Profile::Core, 4, 1},
|
||||
{Profile::Core, 4, 0},
|
||||
{Profile::Core, 3, 3},
|
||||
{Profile::Core, 3, 2},
|
||||
{Profile::Core, 3, 1},
|
||||
{Profile::Core, 3, 0},
|
||||
{Profile::ES, 3, 2},
|
||||
{Profile::ES, 3, 1},
|
||||
{Profile::ES, 3, 0},
|
||||
{Profile::ES, 2, 0},
|
||||
{Profile::NoProfile, 0, 0}
|
||||
};
|
||||
return vlist;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,80 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/WindowInfo.h"
|
||||
|
||||
#include <gsl/span>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace GL {
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
Context(const WindowInfo& wi);
|
||||
virtual ~Context();
|
||||
|
||||
enum class Profile
|
||||
{
|
||||
NoProfile,
|
||||
Core,
|
||||
ES
|
||||
};
|
||||
|
||||
struct Version
|
||||
{
|
||||
Profile profile;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
};
|
||||
|
||||
struct FullscreenModeInfo
|
||||
{
|
||||
u32 width;
|
||||
u32 height;
|
||||
float refresh_rate;
|
||||
};
|
||||
|
||||
__fi const WindowInfo& GetWindowInfo() const { return m_wi; }
|
||||
__fi bool IsGLES() const { return (m_version.profile == Profile::ES); }
|
||||
__fi u32 GetSurfaceWidth() const { return m_wi.surface_width; }
|
||||
__fi u32 GetSurfaceHeight() const { return m_wi.surface_height; }
|
||||
|
||||
virtual void* GetProcAddress(const char* name) = 0;
|
||||
virtual bool ChangeSurface(const WindowInfo& new_wi) = 0;
|
||||
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) = 0;
|
||||
virtual bool SwapBuffers() = 0;
|
||||
virtual bool MakeCurrent() = 0;
|
||||
virtual bool DoneCurrent() = 0;
|
||||
virtual bool SetSwapInterval(s32 interval) = 0;
|
||||
virtual std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) = 0;
|
||||
|
||||
virtual std::vector<FullscreenModeInfo> EnumerateFullscreenModes();
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try);
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi) { return Create(wi, GetAllVersionsList()); }
|
||||
|
||||
static gsl::span<const Version> GetAllVersionsList();
|
||||
|
||||
protected:
|
||||
WindowInfo m_wi;
|
||||
Version m_version = {};
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -1,62 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "common/GL/Context.h"
|
||||
#include "glad.h"
|
||||
|
||||
#if defined(__APPLE__) && defined(__OBJC__)
|
||||
#import <AppKit/AppKit.h>
|
||||
#else
|
||||
struct NSView;
|
||||
struct NSOpenGLContext;
|
||||
struct NSOpenGLPixelFormat;
|
||||
#endif
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class ContextAGL final : public Context
|
||||
{
|
||||
public:
|
||||
ContextAGL(const WindowInfo& wi);
|
||||
~ContextAGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
bool SwapBuffers() override;
|
||||
bool MakeCurrent() override;
|
||||
bool DoneCurrent() override;
|
||||
bool SetSwapInterval(s32 interval) override;
|
||||
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
|
||||
private:
|
||||
bool Initialize(gsl::span<const Version> versions_to_try);
|
||||
bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current);
|
||||
void BindContextToView();
|
||||
void CleanupView();
|
||||
|
||||
// returns true if dimensions have changed
|
||||
bool UpdateDimensions();
|
||||
|
||||
NSView* m_view = nullptr;
|
||||
NSOpenGLContext* m_context = nullptr;
|
||||
NSOpenGLPixelFormat* m_pixel_format = nullptr;
|
||||
void* m_opengl_module_handle = nullptr;
|
||||
};
|
||||
|
||||
} // namespace GL
|
||||
@@ -1,243 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/GL/ContextAGL.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "glad.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#error "Compile this with -fobjc-arc"
|
||||
#endif
|
||||
|
||||
namespace GL
|
||||
{
|
||||
ContextAGL::ContextAGL(const WindowInfo& wi)
|
||||
: Context(wi)
|
||||
{
|
||||
m_opengl_module_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_NOW);
|
||||
if (!m_opengl_module_handle)
|
||||
Console.Error("Could not open OpenGL.framework, function lookups will probably fail");
|
||||
}
|
||||
|
||||
ContextAGL::~ContextAGL()
|
||||
{
|
||||
if ([NSOpenGLContext currentContext] == m_context)
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
CleanupView();
|
||||
|
||||
if (m_opengl_module_handle)
|
||||
dlclose(m_opengl_module_handle);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
|
||||
if (!context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextAGL::Initialize(gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (cv.profile == Profile::NoProfile && CreateContext(nullptr, NSOpenGLProfileVersionLegacy, true))
|
||||
{
|
||||
// we already have the dummy context, so just use that
|
||||
m_version = cv;
|
||||
return true;
|
||||
}
|
||||
else if (cv.profile == Profile::Core)
|
||||
{
|
||||
if (cv.major_version > 4 || cv.minor_version > 1)
|
||||
continue;
|
||||
|
||||
const NSOpenGLPixelFormatAttribute profile = (cv.major_version > 3 || cv.minor_version > 2) ? NSOpenGLProfileVersion4_1Core : NSOpenGLProfileVersion3_2Core;
|
||||
if (CreateContext(nullptr, static_cast<int>(profile), true))
|
||||
{
|
||||
m_version = cv;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void* ContextAGL::GetProcAddress(const char* name)
|
||||
{
|
||||
void* addr = m_opengl_module_handle ? dlsym(m_opengl_module_handle, name) : nullptr;
|
||||
if (addr)
|
||||
return addr;
|
||||
|
||||
return dlsym(RTLD_NEXT, name);
|
||||
}
|
||||
|
||||
bool ContextAGL::ChangeSurface(const WindowInfo& new_wi)
|
||||
{
|
||||
m_wi = new_wi;
|
||||
BindContextToView();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContextAGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/)
|
||||
{
|
||||
UpdateDimensions();
|
||||
}
|
||||
|
||||
bool ContextAGL::UpdateDimensions()
|
||||
{
|
||||
if (![NSThread isMainThread])
|
||||
{
|
||||
bool ret;
|
||||
dispatch_sync(dispatch_get_main_queue(), [this, &ret]{ ret = UpdateDimensions(); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
const NSSize window_size = [m_view frame].size;
|
||||
const CGFloat window_scale = [[m_view window] backingScaleFactor];
|
||||
const u32 new_width = static_cast<u32>(window_size.width * window_scale);
|
||||
const u32 new_height = static_cast<u32>(window_size.height * window_scale);
|
||||
|
||||
if (m_wi.surface_width == new_width && m_wi.surface_height == new_height)
|
||||
return false;
|
||||
|
||||
m_wi.surface_width = new_width;
|
||||
m_wi.surface_height = new_height;
|
||||
|
||||
[m_context update];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextAGL::SwapBuffers()
|
||||
{
|
||||
[m_context flushBuffer];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextAGL::MakeCurrent()
|
||||
{
|
||||
[m_context makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextAGL::DoneCurrent()
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextAGL::SetSwapInterval(s32 interval)
|
||||
{
|
||||
GLint gl_interval = static_cast<GLint>(interval);
|
||||
[m_context setValues:&gl_interval forParameter:NSOpenGLCPSwapInterval];
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextAGL::CreateSharedContext(const WindowInfo& wi)
|
||||
{
|
||||
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
|
||||
|
||||
context->m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:m_context];
|
||||
if (context->m_context == nil)
|
||||
return nullptr;
|
||||
|
||||
context->m_version = m_version;
|
||||
context->m_pixel_format = m_pixel_format;
|
||||
|
||||
if (wi.type == WindowInfo::Type::MacOS)
|
||||
context->BindContextToView();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextAGL::CreateContext(NSOpenGLContext* share_context, int profile, bool make_current)
|
||||
{
|
||||
if (m_context)
|
||||
m_context = nullptr;
|
||||
|
||||
const NSOpenGLPixelFormatAttribute attribs[] = {
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAOpenGLProfile, static_cast<NSOpenGLPixelFormatAttribute>(profile),
|
||||
NSOpenGLPFAAccelerated,
|
||||
0
|
||||
};
|
||||
|
||||
m_pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
if (m_pixel_format == nil)
|
||||
{
|
||||
Console.Error("(ContextAGL) Failed to initialize pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:nil];
|
||||
if (m_context == nil)
|
||||
return false;
|
||||
|
||||
if (m_wi.type == WindowInfo::Type::MacOS)
|
||||
BindContextToView();
|
||||
|
||||
if (make_current)
|
||||
[m_context makeCurrentContext];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContextAGL::BindContextToView()
|
||||
{
|
||||
if (![NSThread isMainThread])
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), [this]{ BindContextToView(); });
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PCSX2_CORE
|
||||
m_view = (__bridge NSView*)m_wi.window_handle;
|
||||
#else
|
||||
// Drawing to wx's wxView somehow causes fighting between us and wx, resulting in massive CPU usage on the main thread and no image
|
||||
// Avoid that by adding our own subview
|
||||
CleanupView();
|
||||
NSView* const superview = (__bridge NSView*)m_wi.window_handle;
|
||||
m_view = [[NSView alloc] initWithFrame:[superview frame]];
|
||||
[superview addSubview:m_view];
|
||||
[m_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
|
||||
#endif
|
||||
[m_view setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
UpdateDimensions();
|
||||
|
||||
[m_context setView:m_view];
|
||||
}
|
||||
|
||||
void ContextAGL::CleanupView()
|
||||
{
|
||||
#ifndef PCSX2_CORE
|
||||
if (![NSThread isMainThread])
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), [this]{ CleanupView(); });
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_view)
|
||||
[m_view removeFromSuperview];
|
||||
#endif
|
||||
m_view = nullptr;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,391 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/Console.h"
|
||||
#include "ContextEGL.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
ContextEGL::ContextEGL(const WindowInfo& wi)
|
||||
: Context(wi)
|
||||
{
|
||||
}
|
||||
|
||||
ContextEGL::~ContextEGL()
|
||||
{
|
||||
DestroySurface();
|
||||
DestroyContext();
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi);
|
||||
if (!context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextEGL::Initialize(gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
if (!gladLoadEGL())
|
||||
{
|
||||
Console.Error("Loading GLAD EGL functions failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetDisplay())
|
||||
return false;
|
||||
|
||||
int egl_major, egl_minor;
|
||||
if (!eglInitialize(m_display, &egl_major, &egl_minor))
|
||||
{
|
||||
Console.Error("eglInitialize() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
Console.WriteLn("EGL Version: %d.%d", egl_major, egl_minor);
|
||||
|
||||
const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS);
|
||||
if (extensions)
|
||||
{
|
||||
Console.WriteLn("EGL Extensions: %s", extensions);
|
||||
m_supports_surfaceless = std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr;
|
||||
}
|
||||
if (!m_supports_surfaceless)
|
||||
Console.Warning("EGL implementation does not support surfaceless contexts, emulating with pbuffers");
|
||||
|
||||
for (const Version& version : versions_to_try)
|
||||
{
|
||||
if (CreateContextAndSurface(version, nullptr, true))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContextEGL::SetDisplay()
|
||||
{
|
||||
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
|
||||
if (!m_display)
|
||||
{
|
||||
Console.Error("eglGetDisplay() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* ContextEGL::GetProcAddress(const char* name)
|
||||
{
|
||||
return reinterpret_cast<void*>(eglGetProcAddress(name));
|
||||
}
|
||||
|
||||
bool ContextEGL::ChangeSurface(const WindowInfo& new_wi)
|
||||
{
|
||||
const bool was_current = (eglGetCurrentContext() == m_context);
|
||||
if (was_current)
|
||||
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
if (m_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface(m_display, m_surface);
|
||||
m_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
m_wi = new_wi;
|
||||
if (!CreateSurface())
|
||||
return false;
|
||||
|
||||
if (was_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context))
|
||||
{
|
||||
Console.Error("Failed to make context current again after surface change");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/)
|
||||
{
|
||||
if (new_surface_width == 0 && new_surface_height == 0)
|
||||
{
|
||||
EGLint surface_width, surface_height;
|
||||
if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) &&
|
||||
eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height))
|
||||
{
|
||||
m_wi.surface_width = static_cast<u32>(surface_width);
|
||||
m_wi.surface_height = static_cast<u32>(surface_height);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("eglQuerySurface() failed: %d", eglGetError());
|
||||
}
|
||||
}
|
||||
|
||||
m_wi.surface_width = new_surface_width;
|
||||
m_wi.surface_height = new_surface_height;
|
||||
}
|
||||
|
||||
bool ContextEGL::SwapBuffers()
|
||||
{
|
||||
return eglSwapBuffers(m_display, m_surface);
|
||||
}
|
||||
|
||||
bool ContextEGL::MakeCurrent()
|
||||
{
|
||||
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
|
||||
{
|
||||
Console.Error("eglMakeCurrent() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextEGL::DoneCurrent()
|
||||
{
|
||||
return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
bool ContextEGL::SetSwapInterval(s32 interval)
|
||||
{
|
||||
return eglSwapInterval(m_display, interval);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGL::CreateSharedContext(const WindowInfo& wi)
|
||||
{
|
||||
std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi);
|
||||
context->m_display = m_display;
|
||||
context->m_supports_surfaceless = m_supports_surfaceless;
|
||||
|
||||
if (!context->CreateContextAndSurface(m_version, m_context, false))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ContextEGL::CreateSurface()
|
||||
{
|
||||
if (m_wi.type == WindowInfo::Type::Surfaceless)
|
||||
{
|
||||
if (m_supports_surfaceless)
|
||||
return true;
|
||||
else
|
||||
return CreatePBufferSurface();
|
||||
}
|
||||
|
||||
EGLNativeWindowType native_window = GetNativeWindow(m_config);
|
||||
m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr);
|
||||
if (!m_surface)
|
||||
{
|
||||
Console.Error("eglCreateWindowSurface() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some implementations may require the size to be queried at runtime.
|
||||
EGLint surface_width, surface_height;
|
||||
if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) &&
|
||||
eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height))
|
||||
{
|
||||
m_wi.surface_width = static_cast<u32>(surface_width);
|
||||
m_wi.surface_height = static_cast<u32>(surface_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("eglQuerySurface() failed: %d", eglGetError());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextEGL::CreatePBufferSurface()
|
||||
{
|
||||
const u32 width = std::max<u32>(m_wi.surface_width, 1);
|
||||
const u32 height = std::max<u32>(m_wi.surface_height, 1);
|
||||
|
||||
EGLint attrib_list[] = {
|
||||
EGL_WIDTH, static_cast<EGLint>(width),
|
||||
EGL_HEIGHT, static_cast<EGLint>(height),
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list);
|
||||
if (!m_surface)
|
||||
{
|
||||
Console.Error("eglCreatePbufferSurface() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLn("Created %ux%u pbuffer surface", width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config) const
|
||||
{
|
||||
int red_size, green_size, blue_size;
|
||||
if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) ||
|
||||
!eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) ||
|
||||
!eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (red_size == 8 && green_size == 8 && blue_size == 8);
|
||||
}
|
||||
|
||||
void ContextEGL::DestroyContext()
|
||||
{
|
||||
if (eglGetCurrentContext() == m_context)
|
||||
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
if (m_context != EGL_NO_CONTEXT)
|
||||
{
|
||||
eglDestroyContext(m_display, m_context);
|
||||
m_context = EGL_NO_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
void ContextEGL::DestroySurface()
|
||||
{
|
||||
if (eglGetCurrentSurface(EGL_DRAW) == m_surface)
|
||||
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
if (m_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface(m_display, m_surface);
|
||||
m_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
|
||||
{
|
||||
Console.WriteLn(
|
||||
"Trying version %u.%u (%s)", version.major_version, version.minor_version,
|
||||
version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None"));
|
||||
|
||||
const int renderable_type = version.profile == Profile::ES
|
||||
? ((version.major_version >= 3) ? EGL_OPENGL_ES3_BIT : ((version.major_version == 2) ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT))
|
||||
: EGL_OPENGL_BIT;
|
||||
const int surface_attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, renderable_type,
|
||||
EGL_SURFACE_TYPE, (m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint num_configs;
|
||||
if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) || num_configs == 0)
|
||||
{
|
||||
Console.Error("eglChooseConfig() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<EGLConfig> configs(static_cast<u32>(num_configs));
|
||||
if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs))
|
||||
{
|
||||
Console.Error("eglChooseConfig() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
configs.resize(static_cast<u32>(num_configs));
|
||||
|
||||
m_config = [this, &configs]() {
|
||||
const auto found_config = std::find_if(std::begin(configs), std::end(configs), [&](const auto& check_config) {
|
||||
return CheckConfigSurfaceFormat(check_config);
|
||||
});
|
||||
if (found_config == std::end(configs))
|
||||
{
|
||||
Console.Warning("No EGL configs matched exactly, using first.");
|
||||
return configs.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
return *found_config;
|
||||
}
|
||||
}();
|
||||
|
||||
const auto attribs = [version]() -> std::array<int, 8> {
|
||||
if (version.profile != Profile::NoProfile)
|
||||
return {
|
||||
EGL_CONTEXT_MAJOR_VERSION, version.major_version,
|
||||
EGL_CONTEXT_MINOR_VERSION, version.minor_version,
|
||||
EGL_NONE
|
||||
};
|
||||
return {EGL_NONE};
|
||||
}();
|
||||
|
||||
if (!eglBindAPI((version.profile == Profile::ES) ? EGL_OPENGL_ES_API : EGL_OPENGL_API))
|
||||
{
|
||||
Console.Error("eglBindAPI(%s) failed", (version.profile == Profile::ES) ? "EGL_OPENGL_ES_API" : "EGL_OPENGL_API");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_context = eglCreateContext(m_display, m_config, share_context, attribs.data());
|
||||
if (!m_context)
|
||||
{
|
||||
Console.Error("eglCreateContext() failed: %d", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLn(
|
||||
"Got version %u.%u (%s)", version.major_version, version.minor_version,
|
||||
version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None"));
|
||||
|
||||
m_version = version;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current)
|
||||
{
|
||||
if (!CreateContext(version, share_context))
|
||||
return false;
|
||||
|
||||
if (!CreateSurface())
|
||||
{
|
||||
Console.Error("Failed to create surface for context");
|
||||
eglDestroyContext(m_display, m_context);
|
||||
m_context = EGL_NO_CONTEXT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (make_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context))
|
||||
{
|
||||
Console.Error("eglMakeCurrent() failed: %d", eglGetError());
|
||||
if (m_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface(m_display, m_surface);
|
||||
m_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
eglDestroyContext(m_display, m_context);
|
||||
m_context = EGL_NO_CONTEXT;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,63 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/GL/Context.h"
|
||||
#include "glad_egl.h"
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class ContextEGL : public Context
|
||||
{
|
||||
public:
|
||||
ContextEGL(const WindowInfo& wi);
|
||||
~ContextEGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
virtual bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
bool SwapBuffers() override;
|
||||
bool MakeCurrent() override;
|
||||
bool DoneCurrent() override;
|
||||
bool SetSwapInterval(s32 interval) override;
|
||||
virtual std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
|
||||
protected:
|
||||
virtual bool SetDisplay();
|
||||
virtual EGLNativeWindowType GetNativeWindow(EGLConfig config);
|
||||
|
||||
bool Initialize(gsl::span<const Version> versions_to_try);
|
||||
bool CreateDisplay();
|
||||
bool CreateContext(const Version& version, EGLContext share_context);
|
||||
bool CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current);
|
||||
bool CreateSurface();
|
||||
bool CreatePBufferSurface();
|
||||
bool CheckConfigSurfaceFormat(EGLConfig config) const;
|
||||
void DestroyContext();
|
||||
void DestroySurface();
|
||||
|
||||
EGLDisplay m_display = EGL_NO_DISPLAY;
|
||||
EGLSurface m_surface = EGL_NO_SURFACE;
|
||||
EGLContext m_context = EGL_NO_CONTEXT;
|
||||
|
||||
EGLConfig m_config = {};
|
||||
|
||||
bool m_supports_surfaceless = false;
|
||||
};
|
||||
|
||||
} // namespace GL
|
||||
@@ -1,104 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
#include "common/Console.h"
|
||||
|
||||
#include "ContextEGLWayland.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1";
|
||||
|
||||
ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi)
|
||||
: ContextEGL(wi)
|
||||
{
|
||||
}
|
||||
|
||||
ContextEGLWayland::~ContextEGLWayland()
|
||||
{
|
||||
if (m_wl_window)
|
||||
m_wl_egl_window_destroy(m_wl_window);
|
||||
if (m_wl_module)
|
||||
dlclose(m_wl_module);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
|
||||
if (!context->LoadModule() || !context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo& wi)
|
||||
{
|
||||
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
|
||||
context->m_display = m_display;
|
||||
|
||||
if (!context->LoadModule() || !context->CreateContextAndSurface(m_version, m_context, false))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void ContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height)
|
||||
{
|
||||
if (m_wl_window)
|
||||
m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0);
|
||||
|
||||
ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
|
||||
}
|
||||
|
||||
EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config)
|
||||
{
|
||||
if (m_wl_window)
|
||||
{
|
||||
m_wl_egl_window_destroy(m_wl_window);
|
||||
m_wl_window = nullptr;
|
||||
}
|
||||
|
||||
m_wl_window =
|
||||
m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height);
|
||||
if (!m_wl_window)
|
||||
return {};
|
||||
|
||||
return reinterpret_cast<EGLNativeWindowType>(m_wl_window);
|
||||
}
|
||||
|
||||
bool ContextEGLWayland::LoadModule()
|
||||
{
|
||||
m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!m_wl_module)
|
||||
{
|
||||
Console.Error("Failed to load %s.", WAYLAND_EGL_MODNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_wl_egl_window_create = reinterpret_cast<decltype(m_wl_egl_window_create)>(dlsym(m_wl_module, "wl_egl_window_create"));
|
||||
m_wl_egl_window_destroy = reinterpret_cast<decltype(m_wl_egl_window_destroy)>(dlsym(m_wl_module, "wl_egl_window_destroy"));
|
||||
m_wl_egl_window_resize = reinterpret_cast<decltype(m_wl_egl_window_resize)>(dlsym(m_wl_module, "wl_egl_window_resize"));
|
||||
if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize)
|
||||
{
|
||||
Console.Error("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,49 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/GL/ContextEGL.h"
|
||||
|
||||
struct wl_egl_window;
|
||||
struct wl_surface;
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class ContextEGLWayland final : public ContextEGL
|
||||
{
|
||||
public:
|
||||
ContextEGLWayland(const WindowInfo& wi);
|
||||
~ContextEGLWayland() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try);
|
||||
|
||||
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
|
||||
protected:
|
||||
EGLNativeWindowType GetNativeWindow(EGLConfig config) override;
|
||||
|
||||
private:
|
||||
bool LoadModule();
|
||||
|
||||
wl_egl_window* m_wl_window = nullptr;
|
||||
|
||||
void* m_wl_module = nullptr;
|
||||
wl_egl_window* (*m_wl_egl_window_create)(struct wl_surface* surface, int width, int height);
|
||||
void (*m_wl_egl_window_destroy)(struct wl_egl_window* egl_window);
|
||||
void (*m_wl_egl_window_resize)(struct wl_egl_window* egl_window, int width, int height, int dx, int dy);
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -1,59 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/GL/ContextEGLX11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
ContextEGLX11::ContextEGLX11(const WindowInfo& wi)
|
||||
: ContextEGL(wi)
|
||||
{
|
||||
}
|
||||
ContextEGLX11::~ContextEGLX11() = default;
|
||||
|
||||
std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
|
||||
if (!context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi)
|
||||
{
|
||||
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
|
||||
context->m_display = m_display;
|
||||
|
||||
if (!context->CreateContextAndSurface(m_version, m_context, false))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void ContextEGLX11::ResizeSurface(u32 new_surface_width, u32 new_surface_height)
|
||||
{
|
||||
ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
|
||||
}
|
||||
|
||||
EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config)
|
||||
{
|
||||
return (EGLNativeWindowType)reinterpret_cast<Window>(m_wi.window_handle);
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,487 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/GL/ContextWGL.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/ScopedGuard.h"
|
||||
|
||||
static void* GetProcAddressCallback(const char* name)
|
||||
{
|
||||
void* addr = reinterpret_cast<void*>(wglGetProcAddress(name));
|
||||
if (addr)
|
||||
return addr;
|
||||
|
||||
// try opengl32.dll
|
||||
return reinterpret_cast<void*>(::GetProcAddress(GetModuleHandleA("opengl32.dll"), name));
|
||||
}
|
||||
|
||||
static bool ReloadWGL(HDC dc)
|
||||
{
|
||||
if (!gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast<void*>(wglGetProcAddress(name)); }, dc))
|
||||
{
|
||||
Console.Error("Loading GLAD WGL functions failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace GL
|
||||
{
|
||||
ContextWGL::ContextWGL(const WindowInfo& wi)
|
||||
: Context(wi)
|
||||
{
|
||||
}
|
||||
|
||||
ContextWGL::~ContextWGL()
|
||||
{
|
||||
if (wglGetCurrentContext() == m_rc)
|
||||
wglMakeCurrent(m_dc, nullptr);
|
||||
|
||||
if (m_rc)
|
||||
wglDeleteContext(m_rc);
|
||||
|
||||
ReleaseDC();
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi);
|
||||
if (!context->Initialize(versions_to_try))
|
||||
return nullptr;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
bool ContextWGL::Initialize(gsl::span<const Version> versions_to_try)
|
||||
{
|
||||
if (m_wi.type == WindowInfo::Type::Win32)
|
||||
{
|
||||
if (!InitializeDC())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CreatePBuffer())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything including core/ES requires a dummy profile to load the WGL extensions.
|
||||
if (!CreateAnyContext(nullptr, true))
|
||||
return false;
|
||||
|
||||
for (const Version& cv : versions_to_try)
|
||||
{
|
||||
if (cv.profile == Profile::NoProfile)
|
||||
{
|
||||
// we already have the dummy context, so just use that
|
||||
m_version = cv;
|
||||
return true;
|
||||
}
|
||||
else if (CreateVersionContext(cv, nullptr, true))
|
||||
{
|
||||
m_version = cv;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void* ContextWGL::GetProcAddress(const char* name)
|
||||
{
|
||||
return GetProcAddressCallback(name);
|
||||
}
|
||||
|
||||
bool ContextWGL::ChangeSurface(const WindowInfo& new_wi)
|
||||
{
|
||||
const bool was_current = (wglGetCurrentContext() == m_rc);
|
||||
|
||||
ReleaseDC();
|
||||
|
||||
m_wi = new_wi;
|
||||
if (!InitializeDC())
|
||||
return false;
|
||||
|
||||
if (was_current && !wglMakeCurrent(m_dc, m_rc))
|
||||
{
|
||||
Console.Error("Failed to make context current again after surface change: 0x%08X", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContextWGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/)
|
||||
{
|
||||
RECT client_rc = {};
|
||||
GetClientRect(GetHWND(), &client_rc);
|
||||
m_wi.surface_width = static_cast<u32>(client_rc.right - client_rc.left);
|
||||
m_wi.surface_height = static_cast<u32>(client_rc.bottom - client_rc.top);
|
||||
}
|
||||
|
||||
bool ContextWGL::SwapBuffers()
|
||||
{
|
||||
return ::SwapBuffers(m_dc);
|
||||
}
|
||||
|
||||
bool ContextWGL::MakeCurrent()
|
||||
{
|
||||
if (!wglMakeCurrent(m_dc, m_rc))
|
||||
{
|
||||
Console.Error("wglMakeCurrent() failed: 0x%08X", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextWGL::DoneCurrent()
|
||||
{
|
||||
return wglMakeCurrent(m_dc, nullptr);
|
||||
}
|
||||
|
||||
bool ContextWGL::SetSwapInterval(s32 interval)
|
||||
{
|
||||
if (!GLAD_WGL_EXT_swap_control)
|
||||
return false;
|
||||
|
||||
return wglSwapIntervalEXT(interval);
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> ContextWGL::CreateSharedContext(const WindowInfo& wi)
|
||||
{
|
||||
std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi);
|
||||
if (wi.type == WindowInfo::Type::Win32)
|
||||
{
|
||||
if (!context->InitializeDC())
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!context->CreatePBuffer())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (m_version.profile == Profile::NoProfile)
|
||||
{
|
||||
if (!context->CreateAnyContext(m_rc, false))
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!context->CreateVersionContext(m_version, m_rc, false))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
context->m_version = m_version;
|
||||
return context;
|
||||
}
|
||||
|
||||
HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd = {};
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.dwLayerMask = PFD_MAIN_PLANE;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cColorBits = 24;
|
||||
|
||||
HDC hDC = ::GetDC(hwnd);
|
||||
if (!hDC)
|
||||
{
|
||||
Console.Error("GetDC() failed: 0x%08X", GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!m_pixel_format.has_value())
|
||||
{
|
||||
const int pf = ChoosePixelFormat(hDC, &pfd);
|
||||
if (pf == 0)
|
||||
{
|
||||
Console.Error("ChoosePixelFormat() failed: 0x%08X", GetLastError());
|
||||
::ReleaseDC(hwnd, hDC);
|
||||
return {};
|
||||
}
|
||||
|
||||
m_pixel_format = pf;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd))
|
||||
{
|
||||
Console.Error("SetPixelFormat() failed: 0x%08X", GetLastError());
|
||||
::ReleaseDC(hwnd, hDC);
|
||||
return {};
|
||||
}
|
||||
|
||||
return hDC;
|
||||
}
|
||||
|
||||
bool ContextWGL::InitializeDC()
|
||||
{
|
||||
if (m_wi.type == WindowInfo::Type::Win32)
|
||||
{
|
||||
m_dc = GetDCAndSetPixelFormat(GetHWND());
|
||||
if (!m_dc)
|
||||
{
|
||||
Console.Error("Failed to get DC for window");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (m_wi.type == WindowInfo::Type::Surfaceless)
|
||||
{
|
||||
return CreatePBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Unknown window info type %u", static_cast<unsigned>(m_wi.type));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ContextWGL::ReleaseDC()
|
||||
{
|
||||
if (m_pbuffer)
|
||||
{
|
||||
wglReleasePbufferDCARB(m_pbuffer, m_dc);
|
||||
m_dc = {};
|
||||
|
||||
wglDestroyPbufferARB(m_pbuffer);
|
||||
m_pbuffer = {};
|
||||
|
||||
::ReleaseDC(m_dummy_window, m_dummy_dc);
|
||||
m_dummy_dc = {};
|
||||
|
||||
DestroyWindow(m_dummy_window);
|
||||
m_dummy_window = {};
|
||||
}
|
||||
else if (m_dc)
|
||||
{
|
||||
::ReleaseDC(GetHWND(), m_dc);
|
||||
m_dc = {};
|
||||
}
|
||||
}
|
||||
|
||||
bool ContextWGL::CreatePBuffer()
|
||||
{
|
||||
static bool window_class_registered = false;
|
||||
static const wchar_t* window_class_name = L"ContextWGLPBuffer";
|
||||
|
||||
if (!window_class_registered)
|
||||
{
|
||||
WNDCLASSEXW wc = {};
|
||||
wc.cbSize = sizeof(WNDCLASSEXW);
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = DefWindowProcW;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(nullptr);
|
||||
wc.hIcon = NULL;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = window_class_name;
|
||||
wc.hIconSm = NULL;
|
||||
|
||||
if (!RegisterClassExW(&wc))
|
||||
{
|
||||
Console.Error("(ContextWGL::CreatePBuffer) RegisterClassExW() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
window_class_registered = true;
|
||||
}
|
||||
|
||||
HWND hwnd = CreateWindowExW(0, window_class_name, window_class_name, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
|
||||
if (!hwnd)
|
||||
{
|
||||
Console.Error("(ContextWGL::CreatePBuffer) CreateWindowEx() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedGuard hwnd_guard([hwnd]() { DestroyWindow(hwnd); });
|
||||
|
||||
HDC hdc = GetDCAndSetPixelFormat(hwnd);
|
||||
if (!hdc)
|
||||
return false;
|
||||
|
||||
ScopedGuard hdc_guard([hdc, hwnd]() { ::ReleaseDC(hwnd, hdc); });
|
||||
|
||||
static constexpr const int pb_attribs[] = {0, 0};
|
||||
|
||||
HGLRC temp_rc = nullptr;
|
||||
ScopedGuard temp_rc_guard([&temp_rc, hdc]() { if (temp_rc) {
|
||||
wglMakeCurrent(hdc, nullptr);
|
||||
wglDeleteContext(temp_rc);
|
||||
} });
|
||||
|
||||
if (!GLAD_WGL_ARB_pbuffer)
|
||||
{
|
||||
// we're probably running completely surfaceless... need a temporary context.
|
||||
temp_rc = wglCreateContext(hdc);
|
||||
if (!temp_rc || !wglMakeCurrent(hdc, temp_rc))
|
||||
{
|
||||
Console.Error("Failed to create temporary context to load WGL for pbuffer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReloadWGL(hdc) || !GLAD_WGL_ARB_pbuffer)
|
||||
{
|
||||
Console.Error("Missing WGL_ARB_pbuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pxAssertRel(m_pixel_format.has_value(), "Has pixel format for pbuffer");
|
||||
HPBUFFERARB pbuffer = wglCreatePbufferARB(hdc, m_pixel_format.value(), 1, 1, pb_attribs);
|
||||
if (!pbuffer)
|
||||
{
|
||||
Console.Error("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); });
|
||||
|
||||
m_dc = wglGetPbufferDCARB(pbuffer);
|
||||
if (!m_dc)
|
||||
{
|
||||
Console.Error("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dummy_window = hwnd;
|
||||
m_dummy_dc = hdc;
|
||||
m_pbuffer = pbuffer;
|
||||
|
||||
temp_rc_guard.Run();
|
||||
pbuffer_guard.Cancel();
|
||||
hdc_guard.Cancel();
|
||||
hwnd_guard.Cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current)
|
||||
{
|
||||
m_rc = wglCreateContext(m_dc);
|
||||
if (!m_rc)
|
||||
{
|
||||
Console.Error("wglCreateContext() failed: 0x%08X", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (make_current)
|
||||
{
|
||||
if (!wglMakeCurrent(m_dc, m_rc))
|
||||
{
|
||||
Console.Error("wglMakeCurrent() failed: 0x%08X", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// re-init glad-wgl
|
||||
if (!gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast<void*>(wglGetProcAddress(name)); }, m_dc))
|
||||
{
|
||||
Console.Error("Loading GLAD WGL functions failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (share_context && !wglShareLists(share_context, m_rc))
|
||||
{
|
||||
Console.Error("wglShareLists() failed: 0x%08X", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context, bool make_current)
|
||||
{
|
||||
// we need create context attribs
|
||||
if (!GLAD_WGL_ARB_create_context)
|
||||
{
|
||||
Console.Error("Missing GLAD_WGL_ARB_create_context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
HGLRC new_rc;
|
||||
if (version.profile == Profile::Core)
|
||||
{
|
||||
const int attribs[] = {
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major_version,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor_version,
|
||||
#ifdef _DEBUG
|
||||
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB,
|
||||
#else
|
||||
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
#endif
|
||||
0, 0};
|
||||
|
||||
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
|
||||
}
|
||||
else if (version.profile == Profile::ES)
|
||||
{
|
||||
if ((version.major_version >= 2 && !GLAD_WGL_EXT_create_context_es2_profile) ||
|
||||
(version.major_version < 2 && !GLAD_WGL_EXT_create_context_es_profile))
|
||||
{
|
||||
Console.Error("WGL_EXT_create_context_es_profile not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
const int attribs[] = {
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, ((version.major_version >= 2) ? WGL_CONTEXT_ES2_PROFILE_BIT_EXT : WGL_CONTEXT_ES_PROFILE_BIT_EXT),
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major_version,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor_version,
|
||||
0, 0};
|
||||
|
||||
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Unknown profile");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new_rc)
|
||||
return false;
|
||||
|
||||
// destroy and swap contexts
|
||||
if (m_rc)
|
||||
{
|
||||
if (!wglMakeCurrent(m_dc, make_current ? new_rc : nullptr))
|
||||
{
|
||||
Console.Error("wglMakeCurrent() failed: 0x%08X", GetLastError());
|
||||
wglDeleteContext(new_rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// re-init glad-wgl
|
||||
if (make_current && !ReloadWGL(m_dc))
|
||||
return false;
|
||||
|
||||
wglDeleteContext(m_rc);
|
||||
}
|
||||
|
||||
m_rc = new_rc;
|
||||
return true;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,71 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/GL/Context.h"
|
||||
|
||||
#include "glad_wgl.h"
|
||||
#include "glad.h"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <optional>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class ContextWGL final : public Context
|
||||
{
|
||||
public:
|
||||
ContextWGL(const WindowInfo& wi);
|
||||
~ContextWGL() override;
|
||||
|
||||
static std::unique_ptr<Context> Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try);
|
||||
|
||||
void* GetProcAddress(const char* name) override;
|
||||
bool ChangeSurface(const WindowInfo& new_wi) override;
|
||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||
bool SwapBuffers() override;
|
||||
bool MakeCurrent() override;
|
||||
bool DoneCurrent() override;
|
||||
bool SetSwapInterval(s32 interval) override;
|
||||
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
|
||||
|
||||
private:
|
||||
__fi HWND GetHWND() const { return static_cast<HWND>(m_wi.window_handle); }
|
||||
|
||||
HDC GetDCAndSetPixelFormat(HWND hwnd);
|
||||
|
||||
bool Initialize(gsl::span<const Version> versions_to_try);
|
||||
bool InitializeDC();
|
||||
void ReleaseDC();
|
||||
bool CreatePBuffer();
|
||||
bool CreateAnyContext(HGLRC share_context, bool make_current);
|
||||
bool CreateVersionContext(const Version& version, HGLRC share_context, bool make_current);
|
||||
|
||||
HDC m_dc = {};
|
||||
HGLRC m_rc = {};
|
||||
|
||||
// Can't change pixel format once it's set for a RC.
|
||||
std::optional<int> m_pixel_format;
|
||||
|
||||
// Dummy window for creating a PBuffer off when we're surfaceless.
|
||||
HWND m_dummy_window = {};
|
||||
HDC m_dummy_dc = {};
|
||||
HPBUFFERARB m_pbuffer = {};
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -1,673 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/PrecompiledHeader.h"
|
||||
|
||||
#include "common/GL/Program.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
GLuint Program::s_last_program_id = 0;
|
||||
static GLuint s_next_bad_shader_id = 1;
|
||||
|
||||
Program::Program() = default;
|
||||
|
||||
Program::Program(Program&& prog)
|
||||
{
|
||||
m_program_id = prog.m_program_id;
|
||||
prog.m_program_id = 0;
|
||||
m_vertex_shader_id = prog.m_vertex_shader_id;
|
||||
prog.m_vertex_shader_id = 0;
|
||||
m_fragment_shader_id = prog.m_fragment_shader_id;
|
||||
prog.m_fragment_shader_id = 0;
|
||||
m_uniform_locations = std::move(prog.m_uniform_locations);
|
||||
}
|
||||
|
||||
Program::~Program()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
GLuint Program::CompileShader(GLenum type, const std::string_view source)
|
||||
{
|
||||
GLuint id = glCreateShader(type);
|
||||
|
||||
std::array<const GLchar*, 1> sources = {{source.data()}};
|
||||
std::array<GLint, 1> source_lengths = {{static_cast<GLint>(source.size())}};
|
||||
glShaderSource(id, static_cast<GLsizei>(sources.size()), sources.data(), source_lengths.data());
|
||||
glCompileShader(id);
|
||||
|
||||
GLint status = GL_FALSE;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||
|
||||
GLint info_log_length = 0;
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
|
||||
// Log will create a new line when there are no warnings so let's set a minimum log length of 1.
|
||||
constexpr int info_log_min_length = 1;
|
||||
|
||||
if (status == GL_FALSE || info_log_length > info_log_min_length)
|
||||
{
|
||||
std::string info_log;
|
||||
info_log.resize(info_log_length + 1);
|
||||
glGetShaderInfoLog(id, info_log_length, &info_log_length, &info_log[0]);
|
||||
|
||||
if (status == GL_TRUE)
|
||||
{
|
||||
Console.Warning("Shader compiled with warnings:\n%s", info_log.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Shader failed to compile:\n%s", info_log.c_str());
|
||||
|
||||
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
|
||||
std::ofstream::out | std::ofstream::binary);
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs.write(sources[0], source_lengths[0]);
|
||||
ofs << "\n\nCompile failed, info log:\n";
|
||||
ofs << info_log;
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
glDeleteShader(id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void Program::ResetLastProgram()
|
||||
{
|
||||
s_last_program_id = 0;
|
||||
}
|
||||
|
||||
bool Program::Compile(const std::string_view vertex_shader, const std::string_view geometry_shader,
|
||||
const std::string_view fragment_shader)
|
||||
{
|
||||
GLuint vertex_shader_id = 0;
|
||||
if (!vertex_shader.empty())
|
||||
{
|
||||
vertex_shader_id = CompileShader(GL_VERTEX_SHADER, vertex_shader);
|
||||
if (vertex_shader_id == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint geometry_shader_id = 0;
|
||||
if (!geometry_shader.empty())
|
||||
{
|
||||
geometry_shader_id = CompileShader(GL_GEOMETRY_SHADER, geometry_shader);
|
||||
if (geometry_shader_id == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint fragment_shader_id = 0;
|
||||
if (!fragment_shader.empty())
|
||||
{
|
||||
fragment_shader_id = CompileShader(GL_FRAGMENT_SHADER, fragment_shader);
|
||||
if (fragment_shader_id == 0)
|
||||
{
|
||||
glDeleteShader(vertex_shader_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_program_id = glCreateProgram();
|
||||
if (vertex_shader_id != 0)
|
||||
glAttachShader(m_program_id, vertex_shader_id);
|
||||
if (geometry_shader_id != 0)
|
||||
glAttachShader(m_program_id, geometry_shader_id);
|
||||
if (fragment_shader_id != 0)
|
||||
glAttachShader(m_program_id, fragment_shader_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Program::CompileCompute(const std::string_view glsl)
|
||||
{
|
||||
GLuint id = CompileShader(GL_COMPUTE_SHADER, glsl);
|
||||
if (id == 0)
|
||||
return false;
|
||||
|
||||
m_program_id = glCreateProgram();
|
||||
glAttachShader(m_program_id, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Program::CreateFromBinary(const void* data, u32 data_length, u32 data_format)
|
||||
{
|
||||
GLuint prog = glCreateProgram();
|
||||
glProgramBinary(prog, static_cast<GLenum>(data_format), data, data_length);
|
||||
|
||||
GLint link_status;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &link_status);
|
||||
if (link_status != GL_TRUE)
|
||||
{
|
||||
Console.Error("Failed to create GL program from binary: status %d", link_status);
|
||||
glDeleteProgram(prog);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_program_id = prog;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Program::GetBinary(std::vector<u8>* out_data, u32* out_data_format)
|
||||
{
|
||||
GLint binary_size = 0;
|
||||
glGetProgramiv(m_program_id, GL_PROGRAM_BINARY_LENGTH, &binary_size);
|
||||
if (binary_size == 0)
|
||||
{
|
||||
Console.Warning("glGetProgramiv(GL_PROGRAM_BINARY_LENGTH) returned 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum format = 0;
|
||||
out_data->resize(static_cast<size_t>(binary_size));
|
||||
glGetProgramBinary(m_program_id, binary_size, &binary_size, &format, out_data->data());
|
||||
if (binary_size == 0)
|
||||
{
|
||||
Console.Warning("glGetProgramBinary() failed");
|
||||
return false;
|
||||
}
|
||||
else if (static_cast<size_t>(binary_size) != out_data->size())
|
||||
{
|
||||
Console.Warning("Size changed from %zu to %d after glGetProgramBinary()", out_data->size(), binary_size);
|
||||
out_data->resize(static_cast<size_t>(binary_size));
|
||||
}
|
||||
|
||||
*out_data_format = static_cast<u32>(format);
|
||||
DevCon.WriteLn("Program binary retrieved, %zu bytes, format %u", out_data->size(), *out_data_format);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Program::SetBinaryRetrievableHint()
|
||||
{
|
||||
glProgramParameteri(m_program_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
}
|
||||
|
||||
void Program::BindAttribute(GLuint index, const char* name)
|
||||
{
|
||||
glBindAttribLocation(m_program_id, index, name);
|
||||
}
|
||||
|
||||
void Program::BindDefaultAttributes()
|
||||
{
|
||||
BindAttribute(0, "a_position");
|
||||
BindAttribute(1, "a_texcoord");
|
||||
BindAttribute(2, "a_color");
|
||||
}
|
||||
|
||||
void Program::BindFragData(GLuint index /*= 0*/, const char* name /*= "o_col0"*/)
|
||||
{
|
||||
glBindFragDataLocation(m_program_id, index, name);
|
||||
}
|
||||
|
||||
void Program::BindFragDataIndexed(GLuint color_number /*= 0*/, const char* name /*= "o_col0"*/)
|
||||
{
|
||||
if (GLAD_GL_VERSION_3_3 || GLAD_GL_ARB_blend_func_extended)
|
||||
{
|
||||
glBindFragDataLocationIndexed(m_program_id, color_number, 0, name);
|
||||
return;
|
||||
}
|
||||
else if (GLAD_GL_EXT_blend_func_extended)
|
||||
{
|
||||
glBindFragDataLocationIndexedEXT(m_program_id, color_number, 0, name);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Error("BindFragDataIndexed() called without ARB or EXT extension, we'll probably crash.");
|
||||
glBindFragDataLocationIndexed(m_program_id, color_number, 0, name);
|
||||
}
|
||||
|
||||
bool Program::Link()
|
||||
{
|
||||
glLinkProgram(m_program_id);
|
||||
|
||||
if (m_vertex_shader_id != 0)
|
||||
glDeleteShader(m_vertex_shader_id);
|
||||
m_vertex_shader_id = 0;
|
||||
if (m_fragment_shader_id != 0)
|
||||
glDeleteShader(m_fragment_shader_id);
|
||||
m_fragment_shader_id = 0;
|
||||
|
||||
GLint status = GL_FALSE;
|
||||
glGetProgramiv(m_program_id, GL_LINK_STATUS, &status);
|
||||
|
||||
GLint info_log_length = 0;
|
||||
|
||||
// Log will create a new line when there are no warnings so let's set a minimum log length of 1.
|
||||
constexpr int info_log_min_length = 1;
|
||||
|
||||
glGetProgramiv(m_program_id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
|
||||
if (status == GL_FALSE || info_log_length > info_log_min_length)
|
||||
{
|
||||
std::string info_log;
|
||||
info_log.resize(info_log_length + 1);
|
||||
glGetProgramInfoLog(m_program_id, info_log_length, &info_log_length, &info_log[0]);
|
||||
|
||||
if (status == GL_TRUE)
|
||||
{
|
||||
Console.Error("Program linked with warnings:\n%s", info_log.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Program failed to link:\n%s", info_log.c_str());
|
||||
glDeleteProgram(m_program_id);
|
||||
m_program_id = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Program::Bind() const
|
||||
{
|
||||
if (s_last_program_id == m_program_id)
|
||||
return;
|
||||
|
||||
glUseProgram(m_program_id);
|
||||
s_last_program_id = m_program_id;
|
||||
}
|
||||
|
||||
void Program::Destroy()
|
||||
{
|
||||
if (m_vertex_shader_id != 0)
|
||||
{
|
||||
glDeleteShader(m_vertex_shader_id);
|
||||
m_vertex_shader_id = 0;
|
||||
}
|
||||
if (m_fragment_shader_id != 0)
|
||||
{
|
||||
glDeleteShader(m_fragment_shader_id);
|
||||
m_fragment_shader_id = 0;
|
||||
}
|
||||
if (m_program_id != 0)
|
||||
{
|
||||
glDeleteProgram(m_program_id);
|
||||
m_program_id = 0;
|
||||
}
|
||||
|
||||
m_uniform_locations.clear();
|
||||
}
|
||||
|
||||
int Program::RegisterUniform(const char* name)
|
||||
{
|
||||
int id = static_cast<int>(m_uniform_locations.size());
|
||||
m_uniform_locations.push_back(glGetUniformLocation(m_program_id, name));
|
||||
return id;
|
||||
}
|
||||
|
||||
void Program::Uniform1ui(int index, u32 x) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform1ui(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2ui(int index, u32 x, u32 y) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2ui(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3ui(int index, u32 x, u32 y, u32 z) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3ui(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4ui(int index, u32 x, u32 y, u32 z, u32 w) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4ui(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform1i(int index, s32 x) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform1i(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2i(int index, s32 x, s32 y) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2i(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3i(int index, s32 x, s32 y, s32 z) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3i(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4i(int index, s32 x, s32 y, s32 z, s32 w) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4i(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform1f(int index, float x) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform1f(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2f(int index, float x, float y) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2f(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3f(int index, float x, float y, float z) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3f(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4f(int index, float x, float y, float z, float w) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4f(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform2uiv(int index, const u32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3uiv(int index, const u32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4uiv(int index, const u32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform2iv(int index, const s32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3iv(int index, const s32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4iv(int index, const s32* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform2fv(int index, const float* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform2fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3fv(int index, const float* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform3fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4fv(int index, const float* v) const
|
||||
{
|
||||
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
|
||||
const GLint location = m_uniform_locations[index];
|
||||
if (location >= 0)
|
||||
glUniform4fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform1ui(const char* name, u32 x) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform1ui(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2ui(const char* name, u32 x, u32 y) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2ui(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3ui(const char* name, u32 x, u32 y, u32 z) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3ui(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4ui(const char* name, u32 x, u32 y, u32 z, u32 w) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4ui(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform1i(const char* name, s32 x) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform1i(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2i(const char* name, s32 x, s32 y) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2i(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3i(const char* name, s32 x, s32 y, s32 z) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3i(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4i(const char* name, s32 x, s32 y, s32 z, s32 w) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4i(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform1f(const char* name, float x) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform1f(location, x);
|
||||
}
|
||||
|
||||
void Program::Uniform2f(const char* name, float x, float y) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2f(location, x, y);
|
||||
}
|
||||
|
||||
void Program::Uniform3f(const char* name, float x, float y, float z) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3f(location, x, y, z);
|
||||
}
|
||||
|
||||
void Program::Uniform4f(const char* name, float x, float y, float z, float w) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4f(location, x, y, z, w);
|
||||
}
|
||||
|
||||
void Program::Uniform2uiv(const char* name, const u32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3uiv(const char* name, const u32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4uiv(const char* name, const u32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4uiv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform2iv(const char* name, const s32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3iv(const char* name, const s32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4iv(const char* name, const s32* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4iv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform2fv(const char* name, const float* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform2fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform3fv(const char* name, const float* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform3fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::Uniform4fv(const char* name, const float* v) const
|
||||
{
|
||||
const GLint location = glGetUniformLocation(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniform4fv(location, 1, v);
|
||||
}
|
||||
|
||||
void Program::BindUniformBlock(const char* name, u32 index)
|
||||
{
|
||||
const GLint location = glGetUniformBlockIndex(m_program_id, name);
|
||||
if (location >= 0)
|
||||
glUniformBlockBinding(m_program_id, location, index);
|
||||
}
|
||||
|
||||
void Program::SetName(const std::string_view& name)
|
||||
{
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
glObjectLabel(GL_PROGRAM, m_program_id, name.length(), name.data());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Program::SetFormattedName(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string n = StringUtil::StdStringFromFormatV(format, ap);
|
||||
va_end(ap);
|
||||
SetName(n);
|
||||
}
|
||||
|
||||
Program& Program::operator=(Program&& prog)
|
||||
{
|
||||
Destroy();
|
||||
m_program_id = prog.m_program_id;
|
||||
prog.m_program_id = 0;
|
||||
m_vertex_shader_id = prog.m_vertex_shader_id;
|
||||
prog.m_vertex_shader_id = 0;
|
||||
m_fragment_shader_id = prog.m_fragment_shader_id;
|
||||
prog.m_fragment_shader_id = 0;
|
||||
m_uniform_locations = std::move(prog.m_uniform_locations);
|
||||
return *this;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,124 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../Pcsx2Defs.h"
|
||||
#include "glad.h"
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public:
|
||||
Program();
|
||||
Program(const Program&) = delete;
|
||||
Program(Program&& prog);
|
||||
~Program();
|
||||
|
||||
static GLuint CompileShader(GLenum type, const std::string_view source);
|
||||
static void ResetLastProgram();
|
||||
|
||||
bool IsValid() const { return m_program_id != 0; }
|
||||
|
||||
bool Compile(const std::string_view vertex_shader, const std::string_view geometry_shader,
|
||||
const std::string_view fragment_shader);
|
||||
|
||||
bool CompileCompute(const std::string_view glsl);
|
||||
|
||||
bool CreateFromBinary(const void* data, u32 data_length, u32 data_format);
|
||||
|
||||
bool GetBinary(std::vector<u8>* out_data, u32* out_data_format);
|
||||
void SetBinaryRetrievableHint();
|
||||
|
||||
void BindAttribute(GLuint index, const char* name);
|
||||
void BindDefaultAttributes();
|
||||
|
||||
void BindFragData(GLuint index = 0, const char* name = "o_col0");
|
||||
void BindFragDataIndexed(GLuint color_number = 0, const char* name = "o_col0");
|
||||
|
||||
bool Link();
|
||||
|
||||
void Bind() const;
|
||||
|
||||
void Destroy();
|
||||
|
||||
int RegisterUniform(const char* name);
|
||||
void Uniform1ui(int index, u32 x) const;
|
||||
void Uniform2ui(int index, u32 x, u32 y) const;
|
||||
void Uniform3ui(int index, u32 x, u32 y, u32 z) const;
|
||||
void Uniform4ui(int index, u32 x, u32 y, u32 z, u32 w) const;
|
||||
void Uniform1i(int index, s32 x) const;
|
||||
void Uniform2i(int index, s32 x, s32 y) const;
|
||||
void Uniform3i(int index, s32 x, s32 y, s32 z) const;
|
||||
void Uniform4i(int index, s32 x, s32 y, s32 z, s32 w) const;
|
||||
void Uniform1f(int index, float x) const;
|
||||
void Uniform2f(int index, float x, float y) const;
|
||||
void Uniform3f(int index, float x, float y, float z) const;
|
||||
void Uniform4f(int index, float x, float y, float z, float w) const;
|
||||
void Uniform2uiv(int index, const u32* v) const;
|
||||
void Uniform3uiv(int index, const u32* v) const;
|
||||
void Uniform4uiv(int index, const u32* v) const;
|
||||
void Uniform2iv(int index, const s32* v) const;
|
||||
void Uniform3iv(int index, const s32* v) const;
|
||||
void Uniform4iv(int index, const s32* v) const;
|
||||
void Uniform2fv(int index, const float* v) const;
|
||||
void Uniform3fv(int index, const float* v) const;
|
||||
void Uniform4fv(int index, const float* v) const;
|
||||
|
||||
void Uniform1ui(const char* name, u32 x) const;
|
||||
void Uniform2ui(const char* name, u32 x, u32 y) const;
|
||||
void Uniform3ui(const char* name, u32 x, u32 y, u32 z) const;
|
||||
void Uniform4ui(const char* name, u32 x, u32 y, u32 z, u32 w) const;
|
||||
void Uniform1i(const char* name, s32 x) const;
|
||||
void Uniform2i(const char* name, s32 x, s32 y) const;
|
||||
void Uniform3i(const char* name, s32 x, s32 y, s32 z) const;
|
||||
void Uniform4i(const char* name, s32 x, s32 y, s32 z, s32 w) const;
|
||||
void Uniform1f(const char* name, float x) const;
|
||||
void Uniform2f(const char* name, float x, float y) const;
|
||||
void Uniform3f(const char* name, float x, float y, float z) const;
|
||||
void Uniform4f(const char* name, float x, float y, float z, float w) const;
|
||||
void Uniform2uiv(const char* name, const u32* v) const;
|
||||
void Uniform3uiv(const char* name, const u32* v) const;
|
||||
void Uniform4uiv(const char* name, const u32* v) const;
|
||||
void Uniform2iv(const char* name, const s32* v) const;
|
||||
void Uniform3iv(const char* name, const s32* v) const;
|
||||
void Uniform4iv(const char* name, const s32* v) const;
|
||||
void Uniform2fv(const char* name, const float* v) const;
|
||||
void Uniform3fv(const char* name, const float* v) const;
|
||||
void Uniform4fv(const char* name, const float* v) const;
|
||||
|
||||
void BindUniformBlock(const char* name, u32 index);
|
||||
|
||||
void SetName(const std::string_view& name);
|
||||
void SetFormattedName(const char* format, ...);
|
||||
|
||||
Program& operator=(const Program&) = delete;
|
||||
Program& operator=(Program&& prog);
|
||||
|
||||
__fi bool operator==(const Program& rhs) const { return m_program_id == rhs.m_program_id; }
|
||||
__fi bool operator!=(const Program& rhs) const { return m_program_id != rhs.m_program_id; }
|
||||
|
||||
private:
|
||||
static u32 s_last_program_id;
|
||||
|
||||
GLuint m_program_id = 0;
|
||||
GLuint m_vertex_shader_id = 0;
|
||||
GLuint m_fragment_shader_id = 0;
|
||||
|
||||
std::vector<GLint> m_uniform_locations;
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -1,566 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/GL/ShaderCache.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/MD5Digest.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/Timer.h"
|
||||
|
||||
namespace GL
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct CacheIndexEntry
|
||||
{
|
||||
u64 vertex_source_hash_low;
|
||||
u64 vertex_source_hash_high;
|
||||
u32 vertex_source_length;
|
||||
u64 geometry_source_hash_low;
|
||||
u64 geometry_source_hash_high;
|
||||
u32 geometry_source_length;
|
||||
u64 fragment_source_hash_low;
|
||||
u64 fragment_source_hash_high;
|
||||
u32 fragment_source_length;
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
u32 blob_format;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
ShaderCache::ShaderCache() = default;
|
||||
|
||||
ShaderCache::~ShaderCache()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool ShaderCache::CacheIndexKey::operator==(const CacheIndexKey& key) const
|
||||
{
|
||||
return (
|
||||
vertex_source_hash_low == key.vertex_source_hash_low && vertex_source_hash_high == key.vertex_source_hash_high &&
|
||||
vertex_source_length == key.vertex_source_length && geometry_source_hash_low == key.geometry_source_hash_low &&
|
||||
geometry_source_hash_high == key.geometry_source_hash_high &&
|
||||
geometry_source_length == key.geometry_source_length && fragment_source_hash_low == key.fragment_source_hash_low &&
|
||||
fragment_source_hash_high == key.fragment_source_hash_high && fragment_source_length == key.fragment_source_length);
|
||||
}
|
||||
|
||||
bool ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
|
||||
{
|
||||
return (
|
||||
vertex_source_hash_low != key.vertex_source_hash_low || vertex_source_hash_high != key.vertex_source_hash_high ||
|
||||
vertex_source_length != key.vertex_source_length || geometry_source_hash_low != key.geometry_source_hash_low ||
|
||||
geometry_source_hash_high != key.geometry_source_hash_high ||
|
||||
geometry_source_length != key.geometry_source_length || fragment_source_hash_low != key.fragment_source_hash_low ||
|
||||
fragment_source_hash_high != key.fragment_source_hash_high || fragment_source_length != key.fragment_source_length);
|
||||
}
|
||||
|
||||
bool ShaderCache::Open(bool is_gles, std::string_view base_path, u32 version)
|
||||
{
|
||||
m_base_path = base_path;
|
||||
m_version = version;
|
||||
m_program_binary_supported = is_gles || GLAD_GL_ARB_get_program_binary;
|
||||
if (m_program_binary_supported)
|
||||
{
|
||||
// check that there's at least one format and the extension isn't being "faked"
|
||||
GLint num_formats = 0;
|
||||
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num_formats);
|
||||
Console.WriteLn("%u program binary formats supported by driver", num_formats);
|
||||
m_program_binary_supported = (num_formats > 0);
|
||||
}
|
||||
|
||||
if (!m_program_binary_supported)
|
||||
{
|
||||
Console.Warning("Your GL driver does not support program binaries. Hopefully it has a built-in cache.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!base_path.empty())
|
||||
{
|
||||
const std::string index_filename = GetIndexFileName();
|
||||
const std::string blob_filename = GetBlobFileName();
|
||||
|
||||
if (ReadExisting(index_filename, blob_filename))
|
||||
return true;
|
||||
|
||||
return CreateNew(index_filename, blob_filename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderCache::CreateNew(const std::string& index_filename, const std::string& blob_filename)
|
||||
{
|
||||
if (FileSystem::FileExists(index_filename.c_str()))
|
||||
{
|
||||
Console.Warning("Removing existing index file '%s'", index_filename.c_str());
|
||||
FileSystem::DeleteFilePath(index_filename.c_str());
|
||||
}
|
||||
if (FileSystem::FileExists(blob_filename.c_str()))
|
||||
{
|
||||
Console.Warning("Removing existing blob file '%s'", blob_filename.c_str());
|
||||
FileSystem::DeleteFilePath(blob_filename.c_str());
|
||||
}
|
||||
|
||||
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "wb");
|
||||
if (!m_index_file)
|
||||
{
|
||||
Console.Error("Failed to open index file '%s' for writing", index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 index_version = FILE_VERSION;
|
||||
if (std::fwrite(&index_version, sizeof(index_version), 1, m_index_file) != 1 ||
|
||||
std::fwrite(&m_version, sizeof(m_version), 1, m_index_file) != 1)
|
||||
{
|
||||
Console.Error("Failed to write version to index file '%s'", index_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
FileSystem::DeleteFilePath(index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "w+b");
|
||||
if (!m_blob_file)
|
||||
{
|
||||
Console.Error("Failed to open blob file '%s' for writing", blob_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
FileSystem::DeleteFilePath(index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderCache::ReadExisting(const std::string& index_filename, const std::string& blob_filename)
|
||||
{
|
||||
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "r+b");
|
||||
if (!m_index_file)
|
||||
{
|
||||
// special case here: when there's a sharing violation (i.e. two instances running),
|
||||
// we don't want to blow away the cache. so just continue without a cache.
|
||||
if (errno == EACCES)
|
||||
{
|
||||
Console.WriteLn("Failed to open shader cache index with EACCES, are you running two instances?");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 file_version = 0;
|
||||
u32 data_version = 0;
|
||||
if (std::fread(&file_version, sizeof(file_version), 1, m_index_file) != 1 || file_version != FILE_VERSION ||
|
||||
std::fread(&data_version, sizeof(data_version), 1, m_index_file) != 1 || data_version != m_version)
|
||||
{
|
||||
Console.Error("Bad file/data version in '%s'", index_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "a+b");
|
||||
if (!m_blob_file)
|
||||
{
|
||||
Console.Error("Blob file '%s' is missing", blob_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::fseek(m_blob_file, 0, SEEK_END);
|
||||
const u32 blob_file_size = static_cast<u32>(std::ftell(m_blob_file));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CacheIndexEntry entry;
|
||||
if (std::fread(&entry, sizeof(entry), 1, m_index_file) != 1 ||
|
||||
(entry.file_offset + entry.blob_size) > blob_file_size)
|
||||
{
|
||||
if (std::feof(m_index_file))
|
||||
break;
|
||||
|
||||
Console.Error("Failed to read entry from '%s', corrupt file?", index_filename.c_str());
|
||||
m_index.clear();
|
||||
std::fclose(m_blob_file);
|
||||
m_blob_file = nullptr;
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
const CacheIndexKey key{
|
||||
entry.vertex_source_hash_low, entry.vertex_source_hash_high, entry.vertex_source_length,
|
||||
entry.geometry_source_hash_low, entry.geometry_source_hash_high, entry.geometry_source_length,
|
||||
entry.fragment_source_hash_low, entry.fragment_source_hash_high, entry.fragment_source_length};
|
||||
const CacheIndexData data{entry.file_offset, entry.blob_size, entry.blob_format};
|
||||
m_index.emplace(key, data);
|
||||
}
|
||||
|
||||
Console.WriteLn("Read %zu entries from '%s'", m_index.size(), index_filename.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderCache::Close()
|
||||
{
|
||||
m_index.clear();
|
||||
if (m_index_file)
|
||||
std::fclose(m_index_file);
|
||||
if (m_blob_file)
|
||||
std::fclose(m_blob_file);
|
||||
}
|
||||
|
||||
bool ShaderCache::Recreate()
|
||||
{
|
||||
Close();
|
||||
|
||||
const std::string index_filename = GetIndexFileName();
|
||||
const std::string blob_filename = GetBlobFileName();
|
||||
|
||||
return CreateNew(index_filename, blob_filename);
|
||||
}
|
||||
|
||||
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vertex_shader,
|
||||
const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader)
|
||||
{
|
||||
union ShaderHash
|
||||
{
|
||||
struct
|
||||
{
|
||||
u64 low;
|
||||
u64 high;
|
||||
};
|
||||
u8 bytes[16];
|
||||
};
|
||||
|
||||
ShaderHash vertex_hash = {};
|
||||
ShaderHash geometry_hash = {};
|
||||
ShaderHash fragment_hash = {};
|
||||
|
||||
MD5Digest digest;
|
||||
if (!vertex_shader.empty())
|
||||
{
|
||||
digest.Update(vertex_shader.data(), static_cast<u32>(vertex_shader.length()));
|
||||
digest.Final(vertex_hash.bytes);
|
||||
}
|
||||
|
||||
if (!geometry_shader.empty())
|
||||
{
|
||||
digest.Reset();
|
||||
digest.Update(geometry_shader.data(), static_cast<u32>(geometry_shader.length()));
|
||||
digest.Final(geometry_hash.bytes);
|
||||
}
|
||||
|
||||
if (!fragment_shader.empty())
|
||||
{
|
||||
digest.Reset();
|
||||
digest.Update(fragment_shader.data(), static_cast<u32>(fragment_shader.length()));
|
||||
digest.Final(fragment_hash.bytes);
|
||||
}
|
||||
|
||||
return CacheIndexKey{vertex_hash.low, vertex_hash.high, static_cast<u32>(vertex_shader.length()),
|
||||
geometry_hash.low, geometry_hash.high, static_cast<u32>(geometry_shader.length()),
|
||||
fragment_hash.low, fragment_hash.high, static_cast<u32>(fragment_shader.length())};
|
||||
}
|
||||
|
||||
std::string ShaderCache::GetIndexFileName() const
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("%s/gl_programs.idx", m_base_path.c_str());
|
||||
}
|
||||
|
||||
std::string ShaderCache::GetBlobFileName() const
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("%s/gl_programs.bin", m_base_path.c_str());
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
|
||||
const std::string_view geometry_shader,
|
||||
const std::string_view fragment_shader, const PreLinkCallback& callback)
|
||||
{
|
||||
if (!m_program_binary_supported || !m_blob_file)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
std::optional<Program> res = CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, false);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Console.WriteLn("Time to compile shader without caching: %.2fms", timer.GetTimeMilliseconds());
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
const auto key = GetCacheKey(vertex_shader, geometry_shader, fragment_shader);
|
||||
auto iter = m_index.find(key);
|
||||
if (iter == m_index.end())
|
||||
return CompileAndAddProgram(key, vertex_shader, geometry_shader, fragment_shader, callback);
|
||||
|
||||
std::vector<u8> data(iter->second.blob_size);
|
||||
if (std::fseek(m_blob_file, iter->second.file_offset, SEEK_SET) != 0 ||
|
||||
std::fread(data.data(), 1, iter->second.blob_size, m_blob_file) != iter->second.blob_size)
|
||||
{
|
||||
Console.Error("Read blob from file failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
Program prog;
|
||||
if (prog.CreateFromBinary(data.data(), static_cast<u32>(data.size()), iter->second.blob_format))
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Console.WriteLn("Time to create program from binary: %.2fms", timer.GetTimeMilliseconds());
|
||||
#endif
|
||||
|
||||
return std::optional<Program>(std::move(prog));
|
||||
}
|
||||
|
||||
Console.Warning(
|
||||
"Failed to create program from binary, this may be due to a driver or GPU Change. Recreating cache.");
|
||||
if (!Recreate())
|
||||
return CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, false);
|
||||
else
|
||||
return CompileAndAddProgram(key, vertex_shader, geometry_shader, fragment_shader, callback);
|
||||
}
|
||||
|
||||
bool ShaderCache::GetProgram(Program* out_program, const std::string_view vertex_shader,
|
||||
const std::string_view geometry_shader, const std::string_view fragment_shader,
|
||||
const PreLinkCallback& callback /* = */)
|
||||
{
|
||||
auto prog = GetProgram(vertex_shader, geometry_shader, fragment_shader, callback);
|
||||
if (!prog)
|
||||
return false;
|
||||
|
||||
*out_program = std::move(*prog);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderCache::WriteToBlobFile(const CacheIndexKey& key, const std::vector<u8>& prog_data, u32 prog_format)
|
||||
{
|
||||
if (!m_blob_file || std::fseek(m_blob_file, 0, SEEK_END) != 0)
|
||||
return false;
|
||||
|
||||
CacheIndexData data;
|
||||
data.file_offset = static_cast<u32>(std::ftell(m_blob_file));
|
||||
data.blob_size = static_cast<u32>(prog_data.size());
|
||||
data.blob_format = prog_format;
|
||||
|
||||
CacheIndexEntry entry = {};
|
||||
entry.vertex_source_hash_low = key.vertex_source_hash_low;
|
||||
entry.vertex_source_hash_high = key.vertex_source_hash_high;
|
||||
entry.vertex_source_length = key.vertex_source_length;
|
||||
entry.geometry_source_hash_low = key.geometry_source_hash_low;
|
||||
entry.geometry_source_hash_high = key.geometry_source_hash_high;
|
||||
entry.geometry_source_length = key.geometry_source_length;
|
||||
entry.fragment_source_hash_low = key.fragment_source_hash_low;
|
||||
entry.fragment_source_hash_high = key.fragment_source_hash_high;
|
||||
entry.fragment_source_length = key.fragment_source_length;
|
||||
entry.file_offset = data.file_offset;
|
||||
entry.blob_size = data.blob_size;
|
||||
entry.blob_format = data.blob_format;
|
||||
|
||||
if (std::fwrite(prog_data.data(), 1, entry.blob_size, m_blob_file) != entry.blob_size ||
|
||||
std::fflush(m_blob_file) != 0 || std::fwrite(&entry, sizeof(entry), 1, m_index_file) != 1 ||
|
||||
std::fflush(m_index_file) != 0)
|
||||
{
|
||||
Console.Error("Failed to write shader blob to file");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_index.emplace(key, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::CompileProgram(const std::string_view& vertex_shader,
|
||||
const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader,
|
||||
const PreLinkCallback& callback, bool set_retrievable)
|
||||
{
|
||||
Program prog;
|
||||
if (!prog.Compile(vertex_shader, geometry_shader, fragment_shader))
|
||||
return std::nullopt;
|
||||
|
||||
if (callback)
|
||||
callback(prog);
|
||||
|
||||
if (set_retrievable)
|
||||
prog.SetBinaryRetrievableHint();
|
||||
|
||||
if (!prog.Link())
|
||||
return std::nullopt;
|
||||
|
||||
return std::optional<Program>(std::move(prog));
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::CompileComputeProgram(const std::string_view& glsl,
|
||||
const PreLinkCallback& callback, bool set_retrievable)
|
||||
{
|
||||
Program prog;
|
||||
if (!prog.CompileCompute(glsl))
|
||||
return std::nullopt;
|
||||
|
||||
if (callback)
|
||||
callback(prog);
|
||||
|
||||
if (set_retrievable)
|
||||
prog.SetBinaryRetrievableHint();
|
||||
|
||||
if (!prog.Link())
|
||||
return std::nullopt;
|
||||
|
||||
return std::optional<Program>(std::move(prog));
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::CompileAndAddProgram(const CacheIndexKey& key,
|
||||
const std::string_view& vertex_shader,
|
||||
const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader,
|
||||
const PreLinkCallback& callback)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
std::optional<Program> prog = CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, true);
|
||||
if (!prog)
|
||||
return std::nullopt;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float compile_time = timer.GetTimeMilliseconds();
|
||||
timer.Reset();
|
||||
#endif
|
||||
|
||||
std::vector<u8> prog_data;
|
||||
u32 prog_format = 0;
|
||||
if (!prog->GetBinary(&prog_data, &prog_format))
|
||||
return std::nullopt;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float binary_time = timer.GetTimeMilliseconds();
|
||||
timer.Reset();
|
||||
#endif
|
||||
|
||||
WriteToBlobFile(key, prog_data, prog_format);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float write_time = timer.GetTimeMilliseconds();
|
||||
Console.WriteLn("Compiled and cached shader: Compile: %.2fms, Binary: %.2fms, Write: %.2fms", compile_time, binary_time, write_time);
|
||||
#endif
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::GetComputeProgram(const std::string_view glsl, const PreLinkCallback& callback)
|
||||
{
|
||||
if (!m_program_binary_supported || !m_blob_file)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
std::optional<Program> res = CompileComputeProgram(glsl, callback, false);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Console.WriteLn("Time to compile shader without caching: %.2fms", timer.GetTimeMilliseconds());
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
const auto key = GetCacheKey(glsl, std::string_view(), std::string_view());
|
||||
auto iter = m_index.find(key);
|
||||
if (iter == m_index.end())
|
||||
return CompileAndAddComputeProgram(key, glsl, callback);
|
||||
|
||||
std::vector<u8> data(iter->second.blob_size);
|
||||
if (std::fseek(m_blob_file, iter->second.file_offset, SEEK_SET) != 0 ||
|
||||
std::fread(data.data(), 1, iter->second.blob_size, m_blob_file) != iter->second.blob_size)
|
||||
{
|
||||
Console.Error("Read blob from file failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
Program prog;
|
||||
if (prog.CreateFromBinary(data.data(), static_cast<u32>(data.size()), iter->second.blob_format))
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Console.WriteLn("Time to create program from binary: %.2fms", timer.GetTimeMilliseconds());
|
||||
#endif
|
||||
|
||||
return std::optional<Program>(std::move(prog));
|
||||
}
|
||||
|
||||
Console.Warning(
|
||||
"Failed to create program from binary, this may be due to a driver or GPU Change. Recreating cache.");
|
||||
if (!Recreate())
|
||||
return CompileComputeProgram(glsl, callback, false);
|
||||
else
|
||||
return CompileAndAddComputeProgram(key, glsl, callback);
|
||||
}
|
||||
|
||||
bool ShaderCache::GetComputeProgram(Program* out_program, const std::string_view glsl, const PreLinkCallback& callback)
|
||||
{
|
||||
auto prog = GetComputeProgram(glsl, callback);
|
||||
if (!prog)
|
||||
return false;
|
||||
|
||||
*out_program = std::move(*prog);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Program> ShaderCache::CompileAndAddComputeProgram(
|
||||
const CacheIndexKey& key, const std::string_view& glsl, const PreLinkCallback& callback)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
Common::Timer timer;
|
||||
#endif
|
||||
|
||||
std::optional<Program> prog = CompileComputeProgram(glsl, callback, true);
|
||||
if (!prog)
|
||||
return std::nullopt;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float compile_time = timer.GetTimeMilliseconds();
|
||||
timer.Reset();
|
||||
#endif
|
||||
|
||||
std::vector<u8> prog_data;
|
||||
u32 prog_format = 0;
|
||||
if (!prog->GetBinary(&prog_data, &prog_format))
|
||||
return std::nullopt;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float binary_time = timer.GetTimeMilliseconds();
|
||||
timer.Reset();
|
||||
#endif
|
||||
|
||||
WriteToBlobFile(key, prog_data, prog_format);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
const float write_time = timer.GetTimeMilliseconds();
|
||||
Console.WriteLn("Compiled and cached compute shader: Compile: %.2fms, Binary: %.2fms, Write: %.2fms", compile_time, binary_time, write_time);
|
||||
#endif
|
||||
|
||||
return prog;
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,120 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/HashCombine.h"
|
||||
#include "common/GL/Program.h"
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class ShaderCache
|
||||
{
|
||||
public:
|
||||
using PreLinkCallback = std::function<void(Program&)>;
|
||||
|
||||
ShaderCache();
|
||||
~ShaderCache();
|
||||
|
||||
bool Open(bool is_gles, std::string_view base_path, u32 version);
|
||||
|
||||
std::optional<Program> GetProgram(const std::string_view vertex_shader, const std::string_view geometry_shader,
|
||||
const std::string_view fragment_shader, const PreLinkCallback& callback = {});
|
||||
bool GetProgram(Program* out_program, const std::string_view vertex_shader, const std::string_view geometry_shader,
|
||||
const std::string_view fragment_shader, const PreLinkCallback& callback = {});
|
||||
|
||||
std::optional<Program> GetComputeProgram(const std::string_view glsl, const PreLinkCallback& callback = {});
|
||||
bool GetComputeProgram(Program* out_program, const std::string_view glsl, const PreLinkCallback& callback = {});
|
||||
|
||||
private:
|
||||
static constexpr u32 FILE_VERSION = 1;
|
||||
|
||||
struct CacheIndexKey
|
||||
{
|
||||
u64 vertex_source_hash_low;
|
||||
u64 vertex_source_hash_high;
|
||||
u32 vertex_source_length;
|
||||
u64 geometry_source_hash_low;
|
||||
u64 geometry_source_hash_high;
|
||||
u32 geometry_source_length;
|
||||
u64 fragment_source_hash_low;
|
||||
u64 fragment_source_hash_high;
|
||||
u32 fragment_source_length;
|
||||
|
||||
bool operator==(const CacheIndexKey& key) const;
|
||||
bool operator!=(const CacheIndexKey& key) const;
|
||||
};
|
||||
|
||||
struct CacheIndexEntryHasher
|
||||
{
|
||||
std::size_t operator()(const CacheIndexKey& e) const noexcept
|
||||
{
|
||||
std::size_t h = 0;
|
||||
HashCombine(h,
|
||||
e.vertex_source_hash_low, e.vertex_source_hash_high, e.vertex_source_length,
|
||||
e.geometry_source_hash_low, e.geometry_source_hash_high, e.geometry_source_length,
|
||||
e.fragment_source_hash_low, e.fragment_source_hash_high, e.fragment_source_length);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct CacheIndexData
|
||||
{
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
u32 blob_format;
|
||||
};
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static CacheIndexKey GetCacheKey(const std::string_view& vertex_shader, const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader);
|
||||
|
||||
std::string GetIndexFileName() const;
|
||||
std::string GetBlobFileName() const;
|
||||
|
||||
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
|
||||
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
|
||||
void Close();
|
||||
bool Recreate();
|
||||
|
||||
bool WriteToBlobFile(const CacheIndexKey& key, const std::vector<u8>& prog_data, u32 prog_format);
|
||||
|
||||
std::optional<Program> CompileProgram(const std::string_view& vertex_shader, const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader, const PreLinkCallback& callback,
|
||||
bool set_retrievable);
|
||||
std::optional<Program> CompileAndAddProgram(const CacheIndexKey& key, const std::string_view& vertex_shader,
|
||||
const std::string_view& geometry_shader,
|
||||
const std::string_view& fragment_shader, const PreLinkCallback& callback);
|
||||
|
||||
std::optional<Program> CompileComputeProgram(const std::string_view& glsl, const PreLinkCallback& callback, bool set_retrievable);
|
||||
std::optional<Program> CompileAndAddComputeProgram(const CacheIndexKey& key, const std::string_view& glsl, const PreLinkCallback& callback);
|
||||
|
||||
std::string m_base_path;
|
||||
std::FILE* m_index_file = nullptr;
|
||||
std::FILE* m_blob_file = nullptr;
|
||||
|
||||
CacheIndex m_index;
|
||||
u32 m_version = 0;
|
||||
bool m_program_binary_supported = false;
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -1,346 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "StreamBuffer.h"
|
||||
#include "common/Align.h"
|
||||
#include "common/Assertions.h"
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
StreamBuffer::StreamBuffer(GLenum target, GLuint buffer_id, u32 size)
|
||||
: m_target(target)
|
||||
, m_buffer_id(buffer_id)
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
StreamBuffer::~StreamBuffer()
|
||||
{
|
||||
glDeleteBuffers(1, &m_buffer_id);
|
||||
}
|
||||
|
||||
void StreamBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(m_target, m_buffer_id);
|
||||
}
|
||||
|
||||
void StreamBuffer::Unbind()
|
||||
{
|
||||
glBindBuffer(m_target, 0);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Uses glBufferSubData() to update. Preferred for drivers which don't support {ARB,EXT}_buffer_storage.
|
||||
class BufferSubDataStreamBuffer final : public StreamBuffer
|
||||
{
|
||||
public:
|
||||
~BufferSubDataStreamBuffer() override = default;
|
||||
|
||||
MappingResult Map(u32 alignment, u32 min_size) override
|
||||
{
|
||||
return MappingResult{static_cast<void*>(m_cpu_buffer.data()), 0, 0, m_size / alignment};
|
||||
}
|
||||
|
||||
void Unmap(u32 used_size) override
|
||||
{
|
||||
if (used_size == 0)
|
||||
return;
|
||||
|
||||
glBindBuffer(m_target, m_buffer_id);
|
||||
glBufferSubData(m_target, 0, used_size, m_cpu_buffer.data());
|
||||
}
|
||||
|
||||
u32 GetChunkSize() const override
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
static std::unique_ptr<StreamBuffer> Create(GLenum target, u32 size)
|
||||
{
|
||||
glGetError();
|
||||
|
||||
GLuint buffer_id;
|
||||
glGenBuffers(1, &buffer_id);
|
||||
glBindBuffer(target, buffer_id);
|
||||
glBufferData(target, size, nullptr, GL_STREAM_DRAW);
|
||||
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
glBindBuffer(target, 0);
|
||||
glDeleteBuffers(1, &buffer_id);
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::unique_ptr<StreamBuffer>(new BufferSubDataStreamBuffer(target, buffer_id, size));
|
||||
}
|
||||
|
||||
private:
|
||||
BufferSubDataStreamBuffer(GLenum target, GLuint buffer_id, u32 size)
|
||||
: StreamBuffer(target, buffer_id, size)
|
||||
, m_cpu_buffer(size)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<u8> m_cpu_buffer;
|
||||
};
|
||||
|
||||
// Uses BufferData() to orphan the buffer after every update. Used on Mali where BufferSubData forces a sync.
|
||||
class BufferDataStreamBuffer final : public StreamBuffer
|
||||
{
|
||||
public:
|
||||
~BufferDataStreamBuffer() override = default;
|
||||
|
||||
MappingResult Map(u32 alignment, u32 min_size) override
|
||||
{
|
||||
return MappingResult{static_cast<void*>(m_cpu_buffer.data()), 0, 0, m_size / alignment};
|
||||
}
|
||||
|
||||
void Unmap(u32 used_size) override
|
||||
{
|
||||
if (used_size == 0)
|
||||
return;
|
||||
|
||||
glBindBuffer(m_target, m_buffer_id);
|
||||
glBufferData(m_target, used_size, m_cpu_buffer.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
u32 GetChunkSize() const override
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
static std::unique_ptr<StreamBuffer> Create(GLenum target, u32 size)
|
||||
{
|
||||
glGetError();
|
||||
|
||||
GLuint buffer_id;
|
||||
glGenBuffers(1, &buffer_id);
|
||||
glBindBuffer(target, buffer_id);
|
||||
glBufferData(target, size, nullptr, GL_STREAM_DRAW);
|
||||
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
glBindBuffer(target, 0);
|
||||
glDeleteBuffers(1, &buffer_id);
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::unique_ptr<StreamBuffer>(new BufferDataStreamBuffer(target, buffer_id, size));
|
||||
}
|
||||
|
||||
private:
|
||||
BufferDataStreamBuffer(GLenum target, GLuint buffer_id, u32 size)
|
||||
: StreamBuffer(target, buffer_id, size)
|
||||
, m_cpu_buffer(size)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<u8> m_cpu_buffer;
|
||||
};
|
||||
|
||||
// Base class for implementations which require syncing.
|
||||
class SyncingStreamBuffer : public StreamBuffer
|
||||
{
|
||||
public:
|
||||
enum : u32
|
||||
{
|
||||
NUM_SYNC_POINTS = 16
|
||||
};
|
||||
|
||||
virtual ~SyncingStreamBuffer() override
|
||||
{
|
||||
for (u32 i = m_available_block_index; i <= m_used_block_index; i++)
|
||||
{
|
||||
pxAssert(m_sync_objects[i]);
|
||||
glDeleteSync(m_sync_objects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SyncingStreamBuffer(GLenum target, GLuint buffer_id, u32 size)
|
||||
: StreamBuffer(target, buffer_id, size)
|
||||
, m_bytes_per_block((size + (NUM_SYNC_POINTS)-1) / NUM_SYNC_POINTS)
|
||||
{
|
||||
}
|
||||
|
||||
__fi u32 GetSyncIndexForOffset(u32 offset) { return offset / m_bytes_per_block; }
|
||||
|
||||
__fi void AddSyncsForOffset(u32 offset)
|
||||
{
|
||||
const u32 end = GetSyncIndexForOffset(offset);
|
||||
for (; m_used_block_index < end; m_used_block_index++)
|
||||
{
|
||||
pxAssert(!m_sync_objects[m_used_block_index]);
|
||||
m_sync_objects[m_used_block_index] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
__fi void WaitForSync(GLsync& sync)
|
||||
{
|
||||
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(sync);
|
||||
sync = nullptr;
|
||||
}
|
||||
|
||||
__fi void EnsureSyncsWaitedForOffset(u32 offset)
|
||||
{
|
||||
const u32 end = std::min<u32>(GetSyncIndexForOffset(offset) + 1, NUM_SYNC_POINTS);
|
||||
for (; m_available_block_index < end; m_available_block_index++)
|
||||
{
|
||||
pxAssert(m_sync_objects[m_available_block_index]);
|
||||
WaitForSync(m_sync_objects[m_available_block_index]);
|
||||
}
|
||||
}
|
||||
|
||||
void AllocateSpace(u32 size)
|
||||
{
|
||||
// add sync objects for writes since the last allocation
|
||||
AddSyncsForOffset(m_position);
|
||||
|
||||
// wait for sync objects for the space we want to use
|
||||
EnsureSyncsWaitedForOffset(m_position + size);
|
||||
|
||||
// wrap-around?
|
||||
if ((m_position + size) > m_size)
|
||||
{
|
||||
// current position ... buffer end
|
||||
AddSyncsForOffset(m_size);
|
||||
|
||||
// rewind, and try again
|
||||
m_position = 0;
|
||||
|
||||
// wait for the sync at the start of the buffer
|
||||
WaitForSync(m_sync_objects[0]);
|
||||
m_available_block_index = 1;
|
||||
|
||||
// and however much more we need to satisfy the allocation
|
||||
EnsureSyncsWaitedForOffset(size);
|
||||
m_used_block_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetChunkSize() const override
|
||||
{
|
||||
return m_size / NUM_SYNC_POINTS;
|
||||
}
|
||||
|
||||
u32 m_position = 0;
|
||||
u32 m_used_block_index = 0;
|
||||
u32 m_available_block_index = NUM_SYNC_POINTS;
|
||||
u32 m_bytes_per_block;
|
||||
std::array<GLsync, NUM_SYNC_POINTS> m_sync_objects{};
|
||||
};
|
||||
|
||||
class BufferStorageStreamBuffer : public SyncingStreamBuffer
|
||||
{
|
||||
public:
|
||||
~BufferStorageStreamBuffer() override
|
||||
{
|
||||
glBindBuffer(m_target, m_buffer_id);
|
||||
glUnmapBuffer(m_target);
|
||||
glBindBuffer(m_target, 0);
|
||||
}
|
||||
|
||||
MappingResult Map(u32 alignment, u32 min_size) override
|
||||
{
|
||||
if (m_position > 0)
|
||||
m_position = Common::AlignUp(m_position, alignment);
|
||||
|
||||
AllocateSpace(min_size);
|
||||
pxAssert((m_position + min_size) <= (m_available_block_index * m_bytes_per_block));
|
||||
|
||||
const u32 free_space_in_block = ((m_available_block_index * m_bytes_per_block) - m_position);
|
||||
return MappingResult{static_cast<void*>(m_mapped_ptr + m_position), m_position, m_position / alignment,
|
||||
free_space_in_block / alignment};
|
||||
}
|
||||
|
||||
void Unmap(u32 used_size) override
|
||||
{
|
||||
pxAssert((m_position + used_size) <= m_size);
|
||||
if (!m_coherent)
|
||||
{
|
||||
Bind();
|
||||
glFlushMappedBufferRange(m_target, m_position, used_size);
|
||||
}
|
||||
|
||||
m_position += used_size;
|
||||
}
|
||||
|
||||
static std::unique_ptr<StreamBuffer> Create(GLenum target, u32 size, bool coherent = true)
|
||||
{
|
||||
glGetError();
|
||||
|
||||
GLuint buffer_id;
|
||||
glGenBuffers(1, &buffer_id);
|
||||
glBindBuffer(target, buffer_id);
|
||||
|
||||
const u32 flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
|
||||
const u32 map_flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT);
|
||||
if (GLAD_GL_VERSION_4_4 || GLAD_GL_ARB_buffer_storage)
|
||||
glBufferStorage(target, size, nullptr, flags);
|
||||
else if (GLAD_GL_EXT_buffer_storage)
|
||||
glBufferStorageEXT(target, size, nullptr, flags);
|
||||
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
glBindBuffer(target, 0);
|
||||
glDeleteBuffers(1, &buffer_id);
|
||||
return {};
|
||||
}
|
||||
|
||||
u8* mapped_ptr = static_cast<u8*>(glMapBufferRange(target, 0, size, map_flags));
|
||||
pxAssertRel(mapped_ptr, "Persistent buffer was mapped");
|
||||
|
||||
return std::unique_ptr<StreamBuffer>(new BufferStorageStreamBuffer(target, buffer_id, size, mapped_ptr, coherent));
|
||||
}
|
||||
|
||||
private:
|
||||
BufferStorageStreamBuffer(GLenum target, GLuint buffer_id, u32 size, u8* mapped_ptr, bool coherent)
|
||||
: SyncingStreamBuffer(target, buffer_id, size)
|
||||
, m_mapped_ptr(mapped_ptr)
|
||||
, m_coherent(coherent)
|
||||
{
|
||||
}
|
||||
|
||||
u8* m_mapped_ptr;
|
||||
bool m_coherent;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
std::unique_ptr<StreamBuffer> StreamBuffer::Create(GLenum target, u32 size)
|
||||
{
|
||||
std::unique_ptr<StreamBuffer> buf;
|
||||
if (GLAD_GL_VERSION_4_4 || GLAD_GL_ARB_buffer_storage || GLAD_GL_EXT_buffer_storage)
|
||||
{
|
||||
buf = detail::BufferStorageStreamBuffer::Create(target, size);
|
||||
if (buf)
|
||||
return buf;
|
||||
}
|
||||
|
||||
// BufferSubData is slower on all drivers except NVIDIA...
|
||||
const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
if (std::strstr(vendor, "NVIDIA"))
|
||||
return detail::BufferSubDataStreamBuffer::Create(target, size);
|
||||
else
|
||||
return detail::BufferDataStreamBuffer::Create(target, size);
|
||||
}
|
||||
} // namespace GL
|
||||
@@ -1,61 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 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 PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "glad.h"
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
/// Provides a buffer for streaming data to the GPU, ideally in write-combined memory.
|
||||
class StreamBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~StreamBuffer();
|
||||
|
||||
__fi GLuint GetGLBufferId() const { return m_buffer_id; }
|
||||
__fi GLenum GetGLTarget() const { return m_target; }
|
||||
__fi u32 GetSize() const { return m_size; }
|
||||
|
||||
void Bind();
|
||||
void Unbind();
|
||||
|
||||
struct MappingResult
|
||||
{
|
||||
void* pointer;
|
||||
u32 buffer_offset;
|
||||
u32 index_aligned; // offset / alignment, suitable for base vertex
|
||||
u32 space_aligned; // remaining space / alignment
|
||||
};
|
||||
|
||||
virtual MappingResult Map(u32 alignment, u32 min_size) = 0;
|
||||
virtual void Unmap(u32 used_size) = 0;
|
||||
|
||||
/// Returns the minimum granularity of blocks which sync objects will be created around.
|
||||
virtual u32 GetChunkSize() const = 0;
|
||||
|
||||
static std::unique_ptr<StreamBuffer> Create(GLenum target, u32 size);
|
||||
|
||||
protected:
|
||||
StreamBuffer(GLenum target, GLuint buffer_id, u32 size);
|
||||
|
||||
GLenum m_target;
|
||||
GLuint m_buffer_id;
|
||||
u32 m_size;
|
||||
};
|
||||
} // namespace GL
|
||||
@@ -89,6 +89,7 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
|
||||
// Prevent recursive exception filtering.
|
||||
if (s_in_exception_handler)
|
||||
{
|
||||
lock.unlock();
|
||||
CallExistingSignalHandler(signal, siginfo, ctx);
|
||||
return;
|
||||
}
|
||||
@@ -100,6 +101,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
|
||||
|
||||
#if defined(__APPLE__) && defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext->__ss.__rip);
|
||||
#elif defined(__FreeBSD__) && defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.mc_rip);
|
||||
#elif defined(__x86_64__)
|
||||
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.gregs[REG_RIP]);
|
||||
#else
|
||||
@@ -119,6 +122,7 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
|
||||
return;
|
||||
|
||||
// Call old signal handler, which will likely dump core.
|
||||
lock.unlock();
|
||||
CallExistingSignalHandler(signal, siginfo, ctx);
|
||||
}
|
||||
|
||||
@@ -133,6 +137,10 @@ bool HostSys::InstallPageFaultHandler(PageFaultHandler handler)
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = SysPageFaultSignalFilter;
|
||||
#ifdef __linux__
|
||||
// Don't block the signal from executing recursively, we want to fire the original handler.
|
||||
sa.sa_flags |= SA_NODEFER;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
// MacOS uses SIGBUS for memory permission violations
|
||||
if (sigaction(SIGBUS, &sa, &s_old_sigbus_action) != 0)
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include "common/Threading.h"
|
||||
#include "common/WindowInfo.h"
|
||||
|
||||
#ifdef DBUS_API
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
|
||||
// Returns 0 on failure (not supported by the operating system).
|
||||
u64 GetPhysicalMemory()
|
||||
{
|
||||
@@ -69,11 +73,77 @@ std::string GetOSVersionString()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef X11_API
|
||||
#ifdef DBUS_API
|
||||
|
||||
bool ChangeScreenSaverStateDBus(const bool inhibit_requested, const char* program_name, const char* reason)
|
||||
{
|
||||
static dbus_uint32_t s_cookie;
|
||||
// "error_dbus" doesn't need to be cleared in the end with "dbus_message_unref" at least if there is
|
||||
// no error set, since calling "dbus_error_free" reinitializes it like "dbus_error_init" after freeing.
|
||||
DBusError error_dbus;
|
||||
dbus_error_init(&error_dbus);
|
||||
DBusConnection* connection = nullptr;
|
||||
DBusMessage* message = nullptr;
|
||||
DBusMessage* response = nullptr;
|
||||
// Initialized here because initializations should be before "goto" statements.
|
||||
const char* bus_method = (inhibit_requested) ? "Inhibit" : "UnInhibit";
|
||||
// "dbus_bus_get" gets a pointer to the same connection in libdbus, if exists, without creating a new connection.
|
||||
// this doesn't need to be deleted, except if there's an error then calling "dbus_connection_unref", to free it,
|
||||
// might be better so a new connection is established on the next try.
|
||||
if (!(connection = dbus_bus_get(DBUS_BUS_SESSION, &error_dbus)) || (dbus_error_is_set(&error_dbus)))
|
||||
goto cleanup;
|
||||
if (!(message = dbus_message_new_method_call("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", bus_method)))
|
||||
goto cleanup;
|
||||
// Initialize an append iterator for the message, gets freed with the message.
|
||||
DBusMessageIter message_itr;
|
||||
dbus_message_iter_init_append(message, &message_itr);
|
||||
if (inhibit_requested)
|
||||
{
|
||||
// Append process/window name.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_STRING, &program_name))
|
||||
goto cleanup;
|
||||
// Append reason for inhibiting the screensaver.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_STRING, &reason))
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only Append the cookie.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_UINT32, &s_cookie))
|
||||
goto cleanup;
|
||||
}
|
||||
// Send message and get response.
|
||||
if (!(response = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error_dbus))
|
||||
|| dbus_error_is_set(&error_dbus))
|
||||
goto cleanup;
|
||||
if (inhibit_requested)
|
||||
{
|
||||
// Get the cookie from the response message.
|
||||
if (!dbus_message_get_args(response, &error_dbus, DBUS_TYPE_UINT32, &s_cookie, DBUS_TYPE_INVALID))
|
||||
goto cleanup;
|
||||
}
|
||||
dbus_message_unref(message);
|
||||
dbus_message_unref(response);
|
||||
return true;
|
||||
cleanup:
|
||||
if (dbus_error_is_set(&error_dbus))
|
||||
dbus_error_free(&error_dbus);
|
||||
if (connection)
|
||||
dbus_connection_unref(connection);
|
||||
if (message)
|
||||
dbus_message_unref(message);
|
||||
if (response)
|
||||
dbus_message_unref(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(DBUS_API) && defined(X11_API)
|
||||
|
||||
static bool SetScreensaverInhibitX11(const WindowInfo& wi, bool inhibit)
|
||||
{
|
||||
extern char **environ;
|
||||
extern char** environ;
|
||||
|
||||
const char* command = "xdg-screensaver";
|
||||
const char* operation = inhibit ? "suspend" : "resume";
|
||||
@@ -88,8 +158,6 @@ static bool SetScreensaverInhibitX11(const WindowInfo& wi, bool inhibit)
|
||||
return (res == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool SetScreensaverInhibit(const WindowInfo& wi, bool inhibit)
|
||||
{
|
||||
switch (wi.type)
|
||||
@@ -106,8 +174,18 @@ static bool SetScreensaverInhibit(const WindowInfo& wi, bool inhibit)
|
||||
|
||||
static std::optional<WindowInfo> s_inhibit_window_info;
|
||||
|
||||
#endif
|
||||
|
||||
bool WindowInfo::InhibitScreensaver(const WindowInfo& wi, bool inhibit)
|
||||
{
|
||||
|
||||
#ifdef DBUS_API
|
||||
|
||||
return ChangeScreenSaverStateDBus(inhibit, "PCSX2", "PCSX2 VM is running.");
|
||||
|
||||
#else
|
||||
|
||||
//ChangeScreenSaverStateDBus
|
||||
if (s_inhibit_window_info.has_value())
|
||||
{
|
||||
// Bit of extra logic here, because wx spams it and we don't want to
|
||||
@@ -132,6 +210,9 @@ bool WindowInfo::InhibitScreensaver(const WindowInfo& wi, bool inhibit)
|
||||
|
||||
s_inhibit_window_info = wi;
|
||||
return true;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool Common::PlaySoundAsync(const char* path)
|
||||
|
||||
318
common/Perf.cpp
318
common/Perf.cpp
@@ -15,197 +15,207 @@
|
||||
|
||||
#include "common/Perf.h"
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#ifdef __unix__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "common/Assertions.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
#include "jitprofiling.h"
|
||||
#endif
|
||||
|
||||
#include <string> // std::string
|
||||
#include <cstring> // strncpy
|
||||
#include <algorithm> // std::remove_if
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <atomic>
|
||||
#include <ctime>
|
||||
#include <mutex>
|
||||
#include <elf.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
//#define ProfileWithPerf
|
||||
#define MERGE_BLOCK_RESULT
|
||||
//#define ProfileWithPerfJitDump
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
#ifdef _WIN32
|
||||
#if defined(ENABLE_VTUNE) && defined(_WIN32)
|
||||
#pragma comment(lib, "jitprofiling.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Perf
|
||||
{
|
||||
// Warning object aren't thread safe
|
||||
InfoVector any("");
|
||||
InfoVector ee("EE");
|
||||
InfoVector iop("IOP");
|
||||
InfoVector vu("VU");
|
||||
InfoVector vif("VIF");
|
||||
Group any("");
|
||||
Group ee("EE");
|
||||
Group iop("IOP");
|
||||
Group vu0("VU0");
|
||||
Group vu1("VU1");
|
||||
Group vif("VIF");
|
||||
|
||||
// Perf is only supported on linux
|
||||
#if defined(__linux__) && (defined(ProfileWithPerf) || defined(ENABLE_VTUNE))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of the Info object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Info::Info(uptr x86, u32 size, const char* symbol)
|
||||
: m_x86(x86)
|
||||
, m_size(size)
|
||||
, m_dynamic(false)
|
||||
#if defined(__linux__) && defined(ProfileWithPerf)
|
||||
static std::FILE* s_map_file = nullptr;
|
||||
static bool s_map_file_opened = false;
|
||||
static std::mutex s_mutex;
|
||||
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
strncpy(m_symbol, symbol, sizeof(m_symbol));
|
||||
}
|
||||
std::unique_lock lock(s_mutex);
|
||||
|
||||
Info::Info(uptr x86, u32 size, const char* symbol, u32 pc)
|
||||
: m_x86(x86)
|
||||
, m_size(size)
|
||||
, m_dynamic(true)
|
||||
{
|
||||
snprintf(m_symbol, sizeof(m_symbol), "%s_0x%08x", symbol, pc);
|
||||
}
|
||||
|
||||
void Info::Print(FILE* fp)
|
||||
{
|
||||
fprintf(fp, "%x %x %s\n", m_x86, m_size, m_symbol);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of the InfoVector object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InfoVector::InfoVector(const char* prefix)
|
||||
{
|
||||
strncpy(m_prefix, prefix, sizeof(m_prefix));
|
||||
#ifdef ENABLE_VTUNE
|
||||
m_vtune_id = iJIT_GetNewMethodID();
|
||||
#else
|
||||
m_vtune_id = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void InfoVector::print(FILE* fp)
|
||||
{
|
||||
for (auto&& it : m_v)
|
||||
it.Print(fp);
|
||||
}
|
||||
|
||||
void InfoVector::map(uptr x86, u32 size, const char* symbol)
|
||||
{
|
||||
// This function is typically used for dispatcher and recompiler.
|
||||
// Dispatchers are on a page and must always be kept.
|
||||
// Recompilers are much bigger (TODO check VIF) and are only
|
||||
// useful when MERGE_BLOCK_RESULT is defined
|
||||
#if defined(ENABLE_VTUNE) || !defined(MERGE_BLOCK_RESULT)
|
||||
u32 max_code_size = 16 * _1kb;
|
||||
#else
|
||||
u32 max_code_size = _1gb;
|
||||
#endif
|
||||
|
||||
if (size < max_code_size)
|
||||
if (!s_map_file)
|
||||
{
|
||||
m_v.emplace_back(x86, size, symbol);
|
||||
if (s_map_file_opened)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
std::string name = std::string(symbol);
|
||||
|
||||
iJIT_Method_Load ml;
|
||||
|
||||
memset(&ml, 0, sizeof(ml));
|
||||
|
||||
ml.method_id = iJIT_GetNewMethodID();
|
||||
ml.method_name = (char*)name.c_str();
|
||||
ml.method_load_address = (void*)x86;
|
||||
ml.method_size = size;
|
||||
|
||||
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &ml);
|
||||
|
||||
//fprintf(stderr, "mapF %s: %p size %dKB\n", ml.method_name, ml.method_load_address, ml.method_size / 1024u);
|
||||
#endif
|
||||
char file[256];
|
||||
snprintf(file, std::size(file), "/tmp/perf-%d.map", getpid());
|
||||
s_map_file = std::fopen(file, "wb");
|
||||
s_map_file_opened = true;
|
||||
if (!s_map_file)
|
||||
return;
|
||||
}
|
||||
|
||||
std::fprintf(s_map_file, "%" PRIx64 " %zx %s\n", static_cast<u64>(reinterpret_cast<uintptr_t>(ptr)), size, symbol);
|
||||
std::fflush(s_map_file);
|
||||
}
|
||||
#elif defined(__linux__) && defined(ProfileWithPerfJitDump)
|
||||
enum : u32
|
||||
{
|
||||
JIT_CODE_LOAD = 0,
|
||||
JIT_CODE_MOVE = 1,
|
||||
JIT_CODE_DEBUG_INFO = 2,
|
||||
JIT_CODE_CLOSE = 3,
|
||||
JIT_CODE_UNWINDING_INFO = 4
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct JITDUMP_HEADER
|
||||
{
|
||||
u32 magic = 0x4A695444; // JiTD
|
||||
u32 version = 1;
|
||||
u32 header_size = sizeof(JITDUMP_HEADER);
|
||||
u32 elf_mach;
|
||||
u32 pad1 = 0;
|
||||
u32 pid;
|
||||
u64 timestamp;
|
||||
u64 flags = 0;
|
||||
};
|
||||
struct JITDUMP_RECORD_HEADER
|
||||
{
|
||||
u32 id;
|
||||
u32 total_size;
|
||||
u64 timestamp;
|
||||
};
|
||||
struct JITDUMP_CODE_LOAD
|
||||
{
|
||||
JITDUMP_RECORD_HEADER header;
|
||||
u32 pid;
|
||||
u32 tid;
|
||||
u64 vma;
|
||||
u64 code_addr;
|
||||
u64 code_size;
|
||||
u64 code_index;
|
||||
// name
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static u64 JitDumpTimestamp()
|
||||
{
|
||||
struct timespec ts = {};
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (static_cast<u64>(ts.tv_sec) * 1000000000ULL) + static_cast<u64>(ts.tv_nsec);
|
||||
}
|
||||
|
||||
void InfoVector::map(uptr x86, u32 size, u32 pc)
|
||||
static FILE* s_jitdump_file = nullptr;
|
||||
static bool s_jitdump_file_opened = false;
|
||||
static std::mutex s_jitdump_mutex;
|
||||
static u32 s_jitdump_record_id;
|
||||
|
||||
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
#ifndef MERGE_BLOCK_RESULT
|
||||
m_v.emplace_back(x86, size, m_prefix, pc);
|
||||
#endif
|
||||
const u32 namelen = std::strlen(symbol) + 1;
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
iJIT_Method_Load_V2 ml;
|
||||
std::unique_lock lock(s_jitdump_mutex);
|
||||
if (!s_jitdump_file)
|
||||
{
|
||||
if (!s_jitdump_file_opened)
|
||||
{
|
||||
char file[256];
|
||||
snprintf(file, std::size(file), "jit-%d.dump", getpid());
|
||||
s_jitdump_file = fopen(file, "w+b");
|
||||
s_jitdump_file_opened = true;
|
||||
if (!s_jitdump_file)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&ml, 0, sizeof(ml));
|
||||
void* perf_marker = mmap(nullptr, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(s_jitdump_file), 0);
|
||||
pxAssertRel(perf_marker != MAP_FAILED, "Map perf marker");
|
||||
|
||||
#ifdef MERGE_BLOCK_RESULT
|
||||
ml.method_id = m_vtune_id;
|
||||
ml.method_name = m_prefix;
|
||||
#else
|
||||
std::string name = std::string(m_prefix) + "_" + std::to_string(pc);
|
||||
JITDUMP_HEADER jh = {};
|
||||
jh.elf_mach = EM_X86_64;
|
||||
jh.pid = getpid();
|
||||
jh.timestamp = JitDumpTimestamp();
|
||||
std::fwrite(&jh, sizeof(jh), 1, s_jitdump_file);
|
||||
}
|
||||
|
||||
JITDUMP_CODE_LOAD cl = {};
|
||||
cl.header.id = JIT_CODE_LOAD;
|
||||
cl.header.total_size = sizeof(cl) + namelen + static_cast<u32>(size);
|
||||
cl.header.timestamp = JitDumpTimestamp();
|
||||
cl.pid = getpid();
|
||||
cl.tid = syscall(SYS_gettid);
|
||||
cl.vma = 0;
|
||||
cl.code_addr = static_cast<u64>(reinterpret_cast<uintptr_t>(ptr));
|
||||
cl.code_size = static_cast<u64>(size);
|
||||
cl.code_index = s_jitdump_record_id++;
|
||||
std::fwrite(&cl, sizeof(cl), 1, s_jitdump_file);
|
||||
std::fwrite(symbol, namelen, 1, s_jitdump_file);
|
||||
std::fwrite(ptr, size, 1, s_jitdump_file);
|
||||
std::fflush(s_jitdump_file);
|
||||
}
|
||||
#elif defined(ENABLE_VTUNE)
|
||||
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
iJIT_Method_Load_V2 ml = {};
|
||||
ml.method_id = iJIT_GetNewMethodID();
|
||||
ml.method_name = (char*)name.c_str();
|
||||
#endif
|
||||
ml.method_load_address = (void*)x86;
|
||||
ml.method_size = size;
|
||||
|
||||
ml.method_name = const_cast<char*>(symbol);
|
||||
ml.method_load_address = const_cast<void*>(ptr);
|
||||
ml.method_size = static_cast<unsigned int>(size);
|
||||
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, &ml);
|
||||
|
||||
//fprintf(stderr, "mapB %s: %p size %d\n", ml.method_name, ml.method_load_address, ml.method_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InfoVector::reset()
|
||||
#if (defined(__linux__) && (defined(ProfileWithPerf) || defined(ProfileWithPerfJitDump))) || defined(ENABLE_VTUNE)
|
||||
void Group::Register(const void* ptr, size_t size, const char* symbol)
|
||||
{
|
||||
auto dynamic = std::remove_if(m_v.begin(), m_v.end(), [](Info i) { return i.m_dynamic; });
|
||||
m_v.erase(dynamic, m_v.end());
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s", m_prefix, symbol);
|
||||
else
|
||||
StringUtil::Strlcpy(full_symbol, symbol, std::size(full_symbol));
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Global function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dump()
|
||||
void Group::RegisterPC(const void* ptr, size_t size, u32 pc)
|
||||
{
|
||||
char file[256];
|
||||
snprintf(file, 250, "/tmp/perf-%d.map", getpid());
|
||||
FILE* fp = fopen(file, "w");
|
||||
|
||||
any.print(fp);
|
||||
ee.print(fp);
|
||||
iop.print(fp);
|
||||
vu.print(fp);
|
||||
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%08X", m_prefix, pc);
|
||||
else
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%08X", pc);
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
void dump_and_reset()
|
||||
void Group::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key)
|
||||
{
|
||||
dump();
|
||||
|
||||
any.reset();
|
||||
ee.reset();
|
||||
iop.reset();
|
||||
vu.reset();
|
||||
char full_symbol[128];
|
||||
if (HasPrefix())
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s%016" PRIX64, m_prefix, prefix, key);
|
||||
else
|
||||
std::snprintf(full_symbol, std::size(full_symbol), "%s%016" PRIX64, prefix, key);
|
||||
RegisterMethod(ptr, size, full_symbol);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Dummy implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InfoVector::InfoVector(const char* prefix)
|
||||
: m_vtune_id(0)
|
||||
{
|
||||
}
|
||||
void InfoVector::map(uptr x86, u32 size, const char* symbol) {}
|
||||
void InfoVector::map(uptr x86, u32 size, u32 pc) {}
|
||||
void InfoVector::reset() {}
|
||||
|
||||
void dump() {}
|
||||
void dump_and_reset() {}
|
||||
|
||||
void Group::Register(const void* ptr, size_t size, const char* symbol) {}
|
||||
void Group::RegisterPC(const void* ptr, size_t size, u32 pc) {}
|
||||
void Group::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key) {}
|
||||
#endif
|
||||
} // namespace Perf
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user