Compare commits
164 Commits
Canary-1.2
...
44e54ba6bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44e54ba6bf | ||
|
|
eb6b0e9adc | ||
|
|
9631bdfe16 | ||
|
|
2a84656ffc | ||
|
|
6c6580ddcc | ||
|
|
c47448628c | ||
|
|
d0ac83b493 | ||
|
|
e0ddbe55c0 | ||
|
|
4a4078865f | ||
|
|
3f59bade94 | ||
|
|
c2ed0fd5fd | ||
|
|
6e731ad942 | ||
|
|
de16d8fa3e | ||
|
|
9b1fb3a27b | ||
|
|
b9150a0092 | ||
|
|
c1002d4826 | ||
|
|
b1de7696ee | ||
|
|
f91cd05260 | ||
|
|
920933bc9f | ||
|
|
52b0b45d34 | ||
|
|
12f0dbcc70 | ||
|
|
719be560ec | ||
|
|
18238736be | ||
|
|
5d9e4ad7a4 | ||
|
|
adba775f0c | ||
|
|
2ffaeb2803 | ||
|
|
b16b844760 | ||
|
|
bc07bc482d | ||
|
|
61975ca44d | ||
|
|
66054dd225 | ||
|
|
b1f61e5143 | ||
|
|
0d7d0e8092 | ||
|
|
aa2178dbe5 | ||
|
|
f92d09711b | ||
|
|
45ee8cd0e8 | ||
|
|
395bbd144a | ||
|
|
744d813b87 | ||
|
|
7d59ada798 | ||
|
|
a4b5304935 | ||
|
|
0965ee905d | ||
|
|
855161b23b | ||
|
|
6b55d158b7 | ||
|
|
91f73a4891 | ||
|
|
883d4d863a | ||
|
|
ca5de909a1 | ||
|
|
5172567b08 | ||
|
|
6fe4cee7c0 | ||
|
|
8623452abc | ||
|
|
17e8ae1d9a | ||
|
|
7591b07fce | ||
|
|
89b4389ed2 | ||
|
|
d9ee729199 | ||
|
|
ba0cd13cff | ||
|
|
501b199e24 | ||
|
|
8aecccadb8 | ||
|
|
e23d610f49 | ||
|
|
f6822f7358 | ||
|
|
d3f84a1305 | ||
|
|
06d34a5992 | ||
|
|
e8e1dc6619 | ||
|
|
c5603d4c36 | ||
|
|
05b56730d6 | ||
|
|
43f7b000ca | ||
|
|
ad89cf39b6 | ||
|
|
96c33a0b92 | ||
|
|
e0db55df46 | ||
|
|
30fef8e96e | ||
|
|
9cb5f5689b | ||
|
|
a205ec374b | ||
|
|
aab9b58542 | ||
|
|
daa648dc40 | ||
|
|
1024aa8757 | ||
|
|
13388e972a | ||
|
|
1eb78872d8 | ||
|
|
fe9fe2a10f | ||
|
|
6ab899f621 | ||
|
|
faacec9801 | ||
|
|
55fdb3f6b2 | ||
|
|
1129ab0e8c | ||
|
|
b6b391b2cf | ||
|
|
f3cf03495d | ||
|
|
7bce8206d5 | ||
|
|
efa0cc7554 | ||
|
|
1c0813d09d | ||
|
|
8bec09d7ff | ||
|
|
e4b4e94b56 | ||
|
|
764c9e9d4e | ||
|
|
05e991db87 | ||
|
|
2cd876b1cb | ||
|
|
93a298523f | ||
|
|
253cbb2810 | ||
|
|
9c226dcc7a | ||
|
|
30a534edcd | ||
|
|
1d88771d1b | ||
|
|
4e8157688e | ||
|
|
5085af0050 | ||
|
|
2c8edaf89e | ||
|
|
aa8ba8b503 | ||
|
|
a4211fec33 | ||
|
|
54b233dd78 | ||
|
|
d1da937fce | ||
|
|
4a8f98126f | ||
|
|
e55629a908 | ||
|
|
c638a7daf8 | ||
|
|
5e5e180fea | ||
|
|
131fe71205 | ||
|
|
6af388c623 | ||
|
|
45cec4e7cf | ||
|
|
479b38f035 | ||
|
|
3ecc7819cc | ||
|
|
4b1d94ccd8 | ||
|
|
4ae9f1c0d2 | ||
|
|
717851985e | ||
|
|
bd08a111a8 | ||
|
|
1972a47f39 | ||
|
|
222ceb818b | ||
|
|
b0fcc5bee1 | ||
|
|
820e8f7375 | ||
|
|
e8a7d5b0b7 | ||
|
|
fafb99c702 | ||
|
|
df9e6e4812 | ||
|
|
566f3d079a | ||
|
|
d7707d4176 | ||
|
|
7a9b62884a | ||
|
|
de9faf183a | ||
|
|
0bf7c5dfa2 | ||
|
|
11bc32d98e | ||
|
|
063430ea16 | ||
|
|
65f08caaa3 | ||
|
|
f225b18c05 | ||
|
|
d8549f687b | ||
|
|
5ab50680b4 | ||
|
|
a0edc5c2b0 | ||
|
|
158ea7b4d6 | ||
|
|
8bc3de8303 | ||
|
|
c812106611 | ||
|
|
11e4d8f970 | ||
|
|
774edb7b29 | ||
|
|
55536f5d78 | ||
|
|
b2eecd28ce | ||
|
|
fe43c32e60 | ||
|
|
8117e160c2 | ||
|
|
bf713a80d6 | ||
|
|
b38b5a1e70 | ||
|
|
2d7700949c | ||
|
|
ea2287af03 | ||
|
|
37af8c70aa | ||
|
|
50cee3fd19 | ||
|
|
a46aacf2e2 | ||
|
|
ad9d6588e8 | ||
|
|
38ef65aae0 | ||
|
|
9f94aa1c79 | ||
|
|
2c9a26c11c | ||
|
|
a4a15a4c80 | ||
|
|
cc3b95eee1 | ||
|
|
2ab806f759 | ||
|
|
6d75410bd2 | ||
|
|
196b2eaf66 | ||
|
|
82fe519766 | ||
|
|
ff05e03cc8 | ||
|
|
e18c6d90c4 | ||
|
|
9075a3960b | ||
|
|
3cf54987d2 | ||
|
|
9c12f52805 |
4
.github/workflows/canary.yml
vendored
4
.github/workflows/canary.yml
vendored
@@ -29,7 +29,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
name: Create tag
|
name: Create tag
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
@@ -202,7 +202,7 @@ jobs:
|
|||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -18,7 +18,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
name: Create tag
|
name: Create tag
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get version info
|
- name: Get version info
|
||||||
id: version_info
|
id: version_info
|
||||||
@@ -183,7 +183,7 @@ jobs:
|
|||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
name: Release MacOS universal
|
name: Release MacOS universal
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,9 @@
|
|||||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
|
||||||
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
|
||||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.7.1" />
|
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
|
|||||||
@@ -39,12 +39,12 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
Click below to join the Discord:
|
Click below to join the Discord:
|
||||||
<br>
|
<br>
|
||||||
<a href="https://discord.gg/dHPrkBkkyA">
|
<a href="https://discord.gg/PEuzjrFXUA">
|
||||||
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
<img src="https://img.shields.io/discord/1294443224030511104?color=5865F2&label=Ryubing&logo=discord&logoColor=white" alt="Discord">
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png">
|
<img src="https://raw.githubusercontent.com/Ryubing/Ryujinx/refs/heads/master/docs/shell.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -332,6 +332,7 @@
|
|||||||
0100E680149DC000,"Arcaea",,playable,2023-03-16 19:31:21
|
0100E680149DC000,"Arcaea",,playable,2023-03-16 19:31:21
|
||||||
01003C2010C78000,"Archaica: The Path Of Light",crash,nothing,2020-10-16 13:22:26
|
01003C2010C78000,"Archaica: The Path Of Light",crash,nothing,2020-10-16 13:22:26
|
||||||
01004DA012976000,"Area 86",,playable,2020-12-16 16:45:52
|
01004DA012976000,"Area 86",,playable,2020-12-16 16:45:52
|
||||||
|
01008d8006a6a000,"Arena of Valor",crash,boots,2025-02-03 22:19:34
|
||||||
0100691013C46000,"ARIA CHRONICLE",,playable,2022-11-16 13:50:55
|
0100691013C46000,"ARIA CHRONICLE",,playable,2022-11-16 13:50:55
|
||||||
0100D4A00B284000,"ARK: Survival Evolved",gpu;nvdec;online-broken;UE4;ldn-untested,ingame,2024-04-16 00:53:56
|
0100D4A00B284000,"ARK: Survival Evolved",gpu;nvdec;online-broken;UE4;ldn-untested,ingame,2024-04-16 00:53:56
|
||||||
0100C56012C96000,"Arkanoid vs. Space Invaders",services,ingame,2021-01-21 12:50:30
|
0100C56012C96000,"Arkanoid vs. Space Invaders",services,ingame,2021-01-21 12:50:30
|
||||||
@@ -426,6 +427,7 @@
|
|||||||
0100E48013A34000,"Balan Wonderworld Demo",gpu;services;UE4;demo,ingame,2023-02-16 20:05:07
|
0100E48013A34000,"Balan Wonderworld Demo",gpu;services;UE4;demo,ingame,2023-02-16 20:05:07
|
||||||
0100CD801CE5E000,"Balatro",,ingame,2024-04-21 02:01:53
|
0100CD801CE5E000,"Balatro",,ingame,2024-04-21 02:01:53
|
||||||
010010A00DA48000,"Baldur's Gate and Baldur's Gate II: Enhanced Editions",32-bit,playable,2022-09-12 23:52:15
|
010010A00DA48000,"Baldur's Gate and Baldur's Gate II: Enhanced Editions",32-bit,playable,2022-09-12 23:52:15
|
||||||
|
0100fd1014726000,"Baldur's Gate: Dark Alliance",ldn-untested,ingame,2025-02-03 22:21:00
|
||||||
0100BC400FB64000,"Balthazar's Dream",,playable,2022-09-13 00:13:22
|
0100BC400FB64000,"Balthazar's Dream",,playable,2022-09-13 00:13:22
|
||||||
01008D30128E0000,"Bamerang",,playable,2022-10-26 00:29:39
|
01008D30128E0000,"Bamerang",,playable,2022-10-26 00:29:39
|
||||||
010013C010C5C000,"Banner of the Maid",,playable,2021-06-14 15:23:37
|
010013C010C5C000,"Banner of the Maid",,playable,2021-06-14 15:23:37
|
||||||
@@ -528,6 +530,7 @@
|
|||||||
01005950022EC000,"Blade Strangers",nvdec,playable,2022-07-17 19:02:43
|
01005950022EC000,"Blade Strangers",nvdec,playable,2022-07-17 19:02:43
|
||||||
0100DF0011A6A000,"Bladed Fury",,playable,2022-10-26 11:36:26
|
0100DF0011A6A000,"Bladed Fury",,playable,2022-10-26 11:36:26
|
||||||
0100CFA00CC74000,"Blades of Time",deadlock;online,boots,2022-07-17 19:19:58
|
0100CFA00CC74000,"Blades of Time",deadlock;online,boots,2022-07-17 19:19:58
|
||||||
|
01003d700dd8a000,"Blades",,boots,2025-02-03 22:22:00
|
||||||
01006CC01182C000,"Blair Witch",nvdec;UE4,playable,2022-10-01 14:06:16
|
01006CC01182C000,"Blair Witch",nvdec;UE4,playable,2022-10-01 14:06:16
|
||||||
010039501405E000,"Blanc",gpu;slow,ingame,2023-02-22 14:00:13
|
010039501405E000,"Blanc",gpu;slow,ingame,2023-02-22 14:00:13
|
||||||
0100698009C6E000,"Blasphemous",nvdec,playable,2021-03-01 12:15:31
|
0100698009C6E000,"Blasphemous",nvdec,playable,2021-03-01 12:15:31
|
||||||
@@ -955,7 +958,7 @@
|
|||||||
010012800EBAE000,"Disney TSUM TSUM FESTIVAL",crash,menus,2020-07-14 14:05:28
|
010012800EBAE000,"Disney TSUM TSUM FESTIVAL",crash,menus,2020-07-14 14:05:28
|
||||||
01009740120FE000,"DISTRAINT 2",,playable,2020-09-03 16:08:12
|
01009740120FE000,"DISTRAINT 2",,playable,2020-09-03 16:08:12
|
||||||
010075B004DD2000,"DISTRAINT: Deluxe Edition",,playable,2020-06-15 23:42:24
|
010075B004DD2000,"DISTRAINT: Deluxe Edition",,playable,2020-06-15 23:42:24
|
||||||
010027400CDC6000,"Divinity: Original Sin 2 - Definitive Edition",services;crash;online-broken;regression,menus,2023-08-13 17:20:03
|
010027400CDC6000,"Divinity: Original Sin 2 - Definitive Edition",services;crash;online-broken;regression,ingame,2025-02-03 22:12:30
|
||||||
01001770115C8000,"Dodo Peak",nvdec;UE4,playable,2022-10-04 16:13:05
|
01001770115C8000,"Dodo Peak",nvdec;UE4,playable,2022-10-04 16:13:05
|
||||||
010077B0100DA000,"Dogurai",,playable,2020-10-04 02:40:16
|
010077B0100DA000,"Dogurai",,playable,2020-10-04 02:40:16
|
||||||
010048100D51A000,"Dokapon Up! Mugen no Roulette",gpu;Needs Update,menus,2022-12-08 19:39:10
|
010048100D51A000,"Dokapon Up! Mugen no Roulette",gpu;Needs Update,menus,2022-12-08 19:39:10
|
||||||
@@ -966,6 +969,7 @@
|
|||||||
0100751007ADA000,"Don't Starve: Nintendo Switch Edition",nvdec,playable,2022-02-05 20:43:34
|
0100751007ADA000,"Don't Starve: Nintendo Switch Edition",nvdec,playable,2022-02-05 20:43:34
|
||||||
010088B010DD2000,"Dongo Adventure",,playable,2022-10-04 16:22:26
|
010088B010DD2000,"Dongo Adventure",,playable,2022-10-04 16:22:26
|
||||||
0100C1F0051B6000,"Donkey Kong Country™: Tropical Freeze",,playable,2024-08-05 16:46:10
|
0100C1F0051B6000,"Donkey Kong Country™: Tropical Freeze",,playable,2024-08-05 16:46:10
|
||||||
|
01009D901BC56000,"Donkey Kong Country™: Returns HD",gpu,ingame,2025-02-16 13:44:12
|
||||||
0100F2C00F060000,"Doodle Derby",,boots,2020-12-04 22:51:48
|
0100F2C00F060000,"Doodle Derby",,boots,2020-12-04 22:51:48
|
||||||
0100416004C00000,"DOOM",gpu;slow;nvdec;online-broken,ingame,2024-09-23 15:40:07
|
0100416004C00000,"DOOM",gpu;slow;nvdec;online-broken,ingame,2024-09-23 15:40:07
|
||||||
010018900DD00000,"DOOM (1993)",nvdec;online-broken,menus,2022-09-06 13:32:19
|
010018900DD00000,"DOOM (1993)",nvdec;online-broken,menus,2022-09-06 13:32:19
|
||||||
@@ -1155,7 +1159,7 @@
|
|||||||
010095600AA36000,"Fill-a-Pix: Phil's Epic Adventure",,playable,2020-12-22 13:48:22
|
010095600AA36000,"Fill-a-Pix: Phil's Epic Adventure",,playable,2020-12-22 13:48:22
|
||||||
0100C3A00BB76000,"Fimbul",nvdec,playable,2022-07-26 13:31:47
|
0100C3A00BB76000,"Fimbul",nvdec,playable,2022-07-26 13:31:47
|
||||||
0100C8200E942000,"Fin and the Ancient Mystery",nvdec,playable,2020-12-17 16:40:39
|
0100C8200E942000,"Fin and the Ancient Mystery",nvdec,playable,2020-12-17 16:40:39
|
||||||
01000EA014150000,"FINAL FANTASY",crash,nothing,2024-09-05 20:55:30
|
01000EA014150000,"FINAL FANTASY",,playable,2025-02-16 21:27:30
|
||||||
01006B7014156000,"FINAL FANTASY II",crash,nothing,2024-04-13 19:18:04
|
01006B7014156000,"FINAL FANTASY II",crash,nothing,2024-04-13 19:18:04
|
||||||
01006F000B056000,"FINAL FANTASY IX",audout;nvdec,playable,2021-06-05 11:35:00
|
01006F000B056000,"FINAL FANTASY IX",audout;nvdec,playable,2021-06-05 11:35:00
|
||||||
0100AA201415C000,"FINAL FANTASY V",,playable,2023-04-26 01:11:55
|
0100AA201415C000,"FINAL FANTASY V",,playable,2023-04-26 01:11:55
|
||||||
@@ -1246,7 +1250,7 @@
|
|||||||
0100A6B00D4EC000,"Furwind",,playable,2021-02-19 19:44:08
|
0100A6B00D4EC000,"Furwind",,playable,2021-02-19 19:44:08
|
||||||
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
|
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
|
||||||
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
|
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
|
||||||
0100E1F013674000,"FUSER™",nvdec;UE4,playable,2022-10-17 20:58:32
|
0100E1F013674000,"FUSER™",nvdec;UE4;slow;gpu,ingame,2025-02-12 16:03:00
|
||||||
0100A7A015E4C000,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
|
0100A7A015E4C000,"Fushigi no Gensokyo Lotus Labyrinth",Needs Update;audio;gpu;nvdec,ingame,2021-01-20 15:30:02
|
||||||
01003C300B274000,"Futari de! Nyanko Daisensou",,playable,2024-01-05 22:26:52
|
01003C300B274000,"Futari de! Nyanko Daisensou",,playable,2024-01-05 22:26:52
|
||||||
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
|
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
|
||||||
@@ -1432,7 +1436,7 @@
|
|||||||
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
||||||
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
||||||
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
||||||
0100F7E00C70E000,"Hogwarts Legacy",slow,ingame,2024-09-03 19:53:58
|
0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58
|
||||||
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
||||||
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
||||||
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
||||||
@@ -1654,7 +1658,7 @@
|
|||||||
0100A73006E74000,"Legendary Eleven",,playable,2021-06-08 12:09:03
|
0100A73006E74000,"Legendary Eleven",,playable,2021-06-08 12:09:03
|
||||||
0100A7700B46C000,"Legendary Fishing",online,playable,2021-04-14 15:08:46
|
0100A7700B46C000,"Legendary Fishing",online,playable,2021-04-14 15:08:46
|
||||||
0100739018020000,"LEGO® 2K Drive",gpu;ldn-works,ingame,2024-04-09 02:05:12
|
0100739018020000,"LEGO® 2K Drive",gpu;ldn-works,ingame,2024-04-09 02:05:12
|
||||||
01003A30012C0000,"LEGO® CITY Undercover",nvdec,playable,2024-09-30 08:44:27
|
010085500130a000,"LEGO® CITY Undercover",nvdec,playable,2024-09-30 08:44:27
|
||||||
010070D009FEC000,"LEGO® DC Super-Villains",,playable,2021-05-27 18:10:37
|
010070D009FEC000,"LEGO® DC Super-Villains",,playable,2021-05-27 18:10:37
|
||||||
010052A00B5D2000,"LEGO® Harry Potter™ Collection",crash,ingame,2024-01-31 10:28:07
|
010052A00B5D2000,"LEGO® Harry Potter™ Collection",crash,ingame,2024-01-31 10:28:07
|
||||||
010073C01AF34000,"LEGO® Horizon Adventures™",vulkan-backend-bug;opengl-backend-bug;UE4,ingame,2025-01-07 04:24:56
|
010073C01AF34000,"LEGO® Horizon Adventures™",vulkan-backend-bug;opengl-backend-bug;UE4,ingame,2025-01-07 04:24:56
|
||||||
@@ -1796,6 +1800,7 @@
|
|||||||
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
||||||
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
||||||
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
||||||
|
010012301932A000,"Melatonin",,playable,2025-02-16 04:08:17
|
||||||
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
||||||
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
||||||
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
||||||
@@ -1913,6 +1918,7 @@
|
|||||||
010073E008E6E000,"Mugsters",,playable,2021-01-28 17:57:17
|
010073E008E6E000,"Mugsters",,playable,2021-01-28 17:57:17
|
||||||
0100A8400471A000,"MUJO",,playable,2020-05-08 16:31:04
|
0100A8400471A000,"MUJO",,playable,2020-05-08 16:31:04
|
||||||
0100211005E94000,"Mulaka",,playable,2021-01-28 18:07:20
|
0100211005E94000,"Mulaka",,playable,2021-01-28 18:07:20
|
||||||
|
01008e2013fb4000,"Multi Quiz",ldn-untested,ingame,2025-02-03 22:26:00
|
||||||
010038B00B9AE000,"Mummy Pinball",,playable,2022-08-05 16:08:11
|
010038B00B9AE000,"Mummy Pinball",,playable,2022-08-05 16:08:11
|
||||||
01008E200C5C2000,"Muse Dash",,playable,2020-06-06 14:41:29
|
01008E200C5C2000,"Muse Dash",,playable,2020-06-06 14:41:29
|
||||||
010035901046C000,"Mushroom Quest",,playable,2020-05-17 13:07:08
|
010035901046C000,"Mushroom Quest",,playable,2020-05-17 13:07:08
|
||||||
@@ -2028,6 +2034,7 @@
|
|||||||
010003C00B868000,"Ninjin: Clash of Carrots",online-broken,playable,2024-07-10 05:12:26
|
010003C00B868000,"Ninjin: Clash of Carrots",online-broken,playable,2024-07-10 05:12:26
|
||||||
0100746010E4C000,"NinNinDays",,playable,2022-11-20 15:17:29
|
0100746010E4C000,"NinNinDays",,playable,2022-11-20 15:17:29
|
||||||
0100C9A00ECE6000,"Nintendo 64™ – Nintendo Switch Online",gpu;vulkan,ingame,2024-04-23 20:21:07
|
0100C9A00ECE6000,"Nintendo 64™ – Nintendo Switch Online",gpu;vulkan,ingame,2024-04-23 20:21:07
|
||||||
|
0100e0601c632000,"Nintendo 64™ – Nintendo Switch Online: MATURE 17+",,ingame,2025-02-03 22:27:00
|
||||||
0100D870045B6000,"Nintendo Entertainment System™ - Nintendo Switch Online",online,playable,2022-07-01 15:45:06
|
0100D870045B6000,"Nintendo Entertainment System™ - Nintendo Switch Online",online,playable,2022-07-01 15:45:06
|
||||||
0100C4B0034B2000,"Nintendo Labo Toy-Con 01 Variety Kit",gpu,ingame,2022-08-07 12:56:07
|
0100C4B0034B2000,"Nintendo Labo Toy-Con 01 Variety Kit",gpu,ingame,2022-08-07 12:56:07
|
||||||
01001E9003502000,"Nintendo Labo Toy-Con 03 Vehicle Kit",services;crash,menus,2022-08-03 17:20:11
|
01001E9003502000,"Nintendo Labo Toy-Con 03 Vehicle Kit",services;crash,menus,2022-08-03 17:20:11
|
||||||
@@ -2058,7 +2065,7 @@
|
|||||||
010002700C34C000,"Numbala",,playable,2020-05-11 12:01:07
|
010002700C34C000,"Numbala",,playable,2020-05-11 12:01:07
|
||||||
010020500C8C8000,"Number Place 10000",gpu,menus,2021-11-24 09:14:23
|
010020500C8C8000,"Number Place 10000",gpu,menus,2021-11-24 09:14:23
|
||||||
010003701002C000,"Nurse Love Syndrome",,playable,2022-10-13 10:05:22
|
010003701002C000,"Nurse Love Syndrome",,playable,2022-10-13 10:05:22
|
||||||
0000000000000000,"nx-hbmenu",Needs Update;homebrew,boots,2024-04-06 22:05:32
|
,"nx-hbmenu",Needs Update;homebrew,boots,2024-04-06 22:05:32
|
||||||
,"nxquake2",services;crash;homebrew,nothing,2022-08-04 23:14:04
|
,"nxquake2",services;crash;homebrew,nothing,2022-08-04 23:14:04
|
||||||
010049F00EC30000,"Nyan Cat: Lost in Space",online,playable,2021-06-12 13:22:03
|
010049F00EC30000,"Nyan Cat: Lost in Space",online,playable,2021-06-12 13:22:03
|
||||||
01002E6014FC4000,"O---O",,playable,2022-10-29 12:12:14
|
01002E6014FC4000,"O---O",,playable,2022-10-29 12:12:14
|
||||||
@@ -2466,7 +2473,7 @@
|
|||||||
0100AFE00DDAC000,"Royal Roads",,playable,2020-11-17 12:54:38
|
0100AFE00DDAC000,"Royal Roads",,playable,2020-11-17 12:54:38
|
||||||
0100E2C00B414000,"RPG Maker MV",nvdec,playable,2021-01-05 20:12:01
|
0100E2C00B414000,"RPG Maker MV",nvdec,playable,2021-01-05 20:12:01
|
||||||
01005CD015986000,"rRootage Reloaded",,playable,2022-08-05 23:20:18
|
01005CD015986000,"rRootage Reloaded",,playable,2022-08-05 23:20:18
|
||||||
0000000000000000,"RSDKv5u",homebrew,ingame,2024-04-01 16:25:34
|
,"RSDKv5u",homebrew,ingame,2024-04-01 16:25:34
|
||||||
010009B00D33C000,"Rugby Challenge 4",slow;online-broken;UE4,playable,2022-10-06 12:45:53
|
010009B00D33C000,"Rugby Challenge 4",slow;online-broken;UE4,playable,2022-10-06 12:45:53
|
||||||
01006EC00F2CC000,"RUINER",UE4,playable,2022-10-03 14:11:33
|
01006EC00F2CC000,"RUINER",UE4,playable,2022-10-03 14:11:33
|
||||||
010074F00DE4A000,"Run the Fan",,playable,2021-02-27 13:36:28
|
010074F00DE4A000,"Run the Fan",,playable,2021-02-27 13:36:28
|
||||||
@@ -2475,6 +2482,7 @@
|
|||||||
010081C0191D8000,"Rune Factory 3 Special",,playable,2023-10-15 08:32:49
|
010081C0191D8000,"Rune Factory 3 Special",,playable,2023-10-15 08:32:49
|
||||||
010051D00E3A4000,"Rune Factory 4 Special",32-bit;crash;nvdec,ingame,2023-05-06 08:49:17
|
010051D00E3A4000,"Rune Factory 4 Special",32-bit;crash;nvdec,ingame,2023-05-06 08:49:17
|
||||||
010014D01216E000,"Rune Factory 5 (JP)",gpu,ingame,2021-06-01 12:00:36
|
010014D01216E000,"Rune Factory 5 (JP)",gpu,ingame,2021-06-01 12:00:36
|
||||||
|
010071E0145F8000,"Rustler",,playable,2025-02-10 20:17:12
|
||||||
0100E21013908000,"RWBY: Grimm Eclipse - Definitive Edition",online-broken,playable,2022-11-03 10:44:01
|
0100E21013908000,"RWBY: Grimm Eclipse - Definitive Edition",online-broken,playable,2022-11-03 10:44:01
|
||||||
010012C0060F0000,"RXN -Raijin-",nvdec,playable,2021-01-10 16:05:43
|
010012C0060F0000,"RXN -Raijin-",nvdec,playable,2021-01-10 16:05:43
|
||||||
0100B8B012ECA000,"S.N.I.P.E.R. - Hunter Scope",,playable,2021-04-19 15:58:09
|
0100B8B012ECA000,"S.N.I.P.E.R. - Hunter Scope",,playable,2021-04-19 15:58:09
|
||||||
@@ -2483,7 +2491,7 @@
|
|||||||
0100A5200C2E0000,"Safety First!",,playable,2021-01-06 09:05:23
|
0100A5200C2E0000,"Safety First!",,playable,2021-01-06 09:05:23
|
||||||
0100A51013530000,"SaGa Frontier Remastered",nvdec,playable,2022-11-03 13:54:56
|
0100A51013530000,"SaGa Frontier Remastered",nvdec,playable,2022-11-03 13:54:56
|
||||||
010003A00D0B4000,"SaGa SCARLET GRACE: AMBITIONS™",,playable,2022-10-06 13:20:31
|
010003A00D0B4000,"SaGa SCARLET GRACE: AMBITIONS™",,playable,2022-10-06 13:20:31
|
||||||
01008D100D43E000,"Saints Row IV®: Re-Elected™",ldn-untested;LAN,playable,2023-12-04 18:33:37
|
01008D100D43E000,"Saints Row IV®: Re-Elected™",ldn-untested;LAN;deadlock,ingame,2025-02-02 16:57:53
|
||||||
0100DE600BEEE000,"SAINTS ROW®: THE THIRD™ - THE FULL PACKAGE",slow;LAN,playable,2023-08-24 02:40:58
|
0100DE600BEEE000,"SAINTS ROW®: THE THIRD™ - THE FULL PACKAGE",slow;LAN,playable,2023-08-24 02:40:58
|
||||||
01007F000EB36000,"Sakai and...",nvdec,playable,2022-12-15 13:53:19
|
01007F000EB36000,"Sakai and...",nvdec,playable,2022-12-15 13:53:19
|
||||||
0100B1400E8FE000,"Sakuna: Of Rice and Ruin",,playable,2023-07-24 13:47:13
|
0100B1400E8FE000,"Sakuna: Of Rice and Ruin",,playable,2023-07-24 13:47:13
|
||||||
@@ -2532,7 +2540,7 @@
|
|||||||
0100C3E00B700000,"SEGA AGES Space Harrier",,playable,2021-01-11 12:57:40
|
0100C3E00B700000,"SEGA AGES Space Harrier",,playable,2021-01-11 12:57:40
|
||||||
010054400D2E6000,"SEGA AGES Virtua Racing",online-broken,playable,2023-01-29 17:08:39
|
010054400D2E6000,"SEGA AGES Virtua Racing",online-broken,playable,2023-01-29 17:08:39
|
||||||
01001E700AC60000,"SEGA AGES Wonder Boy: Monster Land",online,playable,2021-05-05 16:28:25
|
01001E700AC60000,"SEGA AGES Wonder Boy: Monster Land",online,playable,2021-05-05 16:28:25
|
||||||
0100B3C014BDA000,"SEGA Genesis™ – Nintendo Switch Online",crash;regression,nothing,2022-04-11 07:27:21
|
0100B3C014BDA000,"SEGA Genesis™ – Nintendo Switch Online",crash;regression,ingame,2025-02-03 22:13:30
|
||||||
0100F7300B24E000,"SEGA Mega Drive Classics",online,playable,2021-01-05 11:08:00
|
0100F7300B24E000,"SEGA Mega Drive Classics",online,playable,2021-01-05 11:08:00
|
||||||
01009840046BC000,"Semispheres",,playable,2021-01-06 23:08:31
|
01009840046BC000,"Semispheres",,playable,2021-01-06 23:08:31
|
||||||
0100D1800D902000,"SENRAN KAGURA Peach Ball",,playable,2021-06-03 15:12:10
|
0100D1800D902000,"SENRAN KAGURA Peach Ball",,playable,2021-06-03 15:12:10
|
||||||
@@ -2668,10 +2676,10 @@
|
|||||||
01004F401BEBE000,"Song of Nunu: A League of Legends Story",,ingame,2024-07-12 18:53:44
|
01004F401BEBE000,"Song of Nunu: A League of Legends Story",,ingame,2024-07-12 18:53:44
|
||||||
0100E5400BF94000,"Songbird Symphony",,playable,2021-02-27 02:44:04
|
0100E5400BF94000,"Songbird Symphony",,playable,2021-02-27 02:44:04
|
||||||
010031D00A604000,"Songbringer",,playable,2020-06-22 10:42:02
|
010031D00A604000,"Songbringer",,playable,2020-06-22 10:42:02
|
||||||
0000000000000000,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20
|
,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20
|
||||||
0000000000000000,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30
|
,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30
|
||||||
0000000000000000,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32
|
,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32
|
||||||
0000000000000000,"Sonic CD",crash;homebrew,ingame,2024-04-01 16:25:31
|
,"Sonic CD",crash;homebrew,ingame,2024-04-01 16:25:31
|
||||||
010040E0116B8000,"Sonic Colors: Ultimate",,playable,2022-11-12 21:24:26
|
010040E0116B8000,"Sonic Colors: Ultimate",,playable,2022-11-12 21:24:26
|
||||||
01001270012B6000,"SONIC FORCES™",,playable,2024-07-28 13:11:21
|
01001270012B6000,"SONIC FORCES™",,playable,2024-07-28 13:11:21
|
||||||
01004AD014BF0000,"Sonic Frontiers",gpu;deadlock;amd-vendor-bug;intel-vendor-bug,ingame,2024-09-05 09:18:53
|
01004AD014BF0000,"Sonic Frontiers",gpu;deadlock;amd-vendor-bug;intel-vendor-bug,ingame,2024-09-05 09:18:53
|
||||||
@@ -2688,7 +2696,7 @@
|
|||||||
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
|
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
|
||||||
010047B010260000,"Space Pioneer",,playable,2022-10-20 12:24:37
|
010047B010260000,"Space Pioneer",,playable,2022-10-20 12:24:37
|
||||||
010010A009830000,"Space Ribbon",,playable,2022-08-15 17:17:10
|
010010A009830000,"Space Ribbon",,playable,2022-08-15 17:17:10
|
||||||
0000000000000000,"SpaceCadetPinball",homebrew,ingame,2024-04-18 19:30:04
|
,"SpaceCadetPinball",homebrew,ingame,2024-04-18 19:30:04
|
||||||
0100D9B0041CE000,"Spacecats with Lasers",,playable,2022-08-15 17:22:44
|
0100D9B0041CE000,"Spacecats with Lasers",,playable,2022-08-15 17:22:44
|
||||||
010034800FB60000,"Spaceland",,playable,2020-11-01 14:31:56
|
010034800FB60000,"Spaceland",,playable,2020-11-01 14:31:56
|
||||||
010028D0045CE000,"Sparkle 2",,playable,2020-10-19 11:51:39
|
010028D0045CE000,"Sparkle 2",,playable,2020-10-19 11:51:39
|
||||||
@@ -2832,8 +2840,9 @@
|
|||||||
01009B90006DC000,"Super Mario Maker™ 2",online-broken;ldn-broken,playable,2024-08-25 11:05:19
|
01009B90006DC000,"Super Mario Maker™ 2",online-broken;ldn-broken,playable,2024-08-25 11:05:19
|
||||||
0100000000010000,"Super Mario Odyssey™",nvdec;intel-vendor-bug;mac-bug,playable,2024-08-25 01:32:34
|
0100000000010000,"Super Mario Odyssey™",nvdec;intel-vendor-bug;mac-bug,playable,2024-08-25 01:32:34
|
||||||
010036B0034E4000,"Super Mario Party™",gpu;Needs Update;ldn-works,ingame,2024-06-21 05:10:16
|
010036B0034E4000,"Super Mario Party™",gpu;Needs Update;ldn-works,ingame,2024-06-21 05:10:16
|
||||||
|
0100965017338000,"Super Mario Party Jamboree",mac-bug;gpu,ingame,2025-02-17 02:09:20
|
||||||
0100BC0018138000,"Super Mario RPG™",gpu;audio;nvdec,ingame,2024-06-19 17:43:42
|
0100BC0018138000,"Super Mario RPG™",gpu;audio;nvdec,ingame,2024-06-19 17:43:42
|
||||||
0000000000000000,"Super Mario World",homebrew,boots,2024-06-13 01:40:31
|
,"Super Mario World",homebrew,boots,2024-06-13 01:40:31
|
||||||
010049900F546000,"Super Mario™ 3D All-Stars",services-horizon;slow;vulkan;amd-vendor-bug,ingame,2024-05-07 02:38:16
|
010049900F546000,"Super Mario™ 3D All-Stars",services-horizon;slow;vulkan;amd-vendor-bug,ingame,2024-05-07 02:38:16
|
||||||
010028600EBDA000,"Super Mario™ 3D World + Bowser’s Fury",ldn-works,playable,2024-07-31 10:45:37
|
010028600EBDA000,"Super Mario™ 3D World + Bowser’s Fury",ldn-works,playable,2024-07-31 10:45:37
|
||||||
01004F8006A78000,"Super Meat Boy",services,playable,2020-04-02 23:10:07
|
01004F8006A78000,"Super Meat Boy",services,playable,2020-04-02 23:10:07
|
||||||
@@ -2964,6 +2973,7 @@
|
|||||||
0100C38004DCC000,"The Flame In The Flood: Complete Edition",gpu;nvdec;UE4,ingame,2022-08-22 16:23:49
|
0100C38004DCC000,"The Flame In The Flood: Complete Edition",gpu;nvdec;UE4,ingame,2022-08-22 16:23:49
|
||||||
010007700D4AC000,"The Forbidden Arts",,playable,2021-01-26 16:26:24
|
010007700D4AC000,"The Forbidden Arts",,playable,2021-01-26 16:26:24
|
||||||
010030700CBBC000,"The friends of Ringo Ishikawa",,playable,2022-08-22 16:33:17
|
010030700CBBC000,"The friends of Ringo Ishikawa",,playable,2022-08-22 16:33:17
|
||||||
|
0100b620139d8000,"The Game of Life 2",ldn-untested,ingame,2025-02-03 22:30:00
|
||||||
01006350148DA000,"The Gardener and the Wild Vines",gpu,ingame,2024-04-29 16:32:10
|
01006350148DA000,"The Gardener and the Wild Vines",gpu,ingame,2024-04-29 16:32:10
|
||||||
0100B13007A6A000,"The Gardens Between",,playable,2021-01-29 16:16:53
|
0100B13007A6A000,"The Gardens Between",,playable,2021-01-29 16:16:53
|
||||||
010036E00FB20000,"The Great Ace Attorney Chronicles",,playable,2023-06-22 21:26:29
|
010036E00FB20000,"The Great Ace Attorney Chronicles",,playable,2023-06-22 21:26:29
|
||||||
@@ -2981,6 +2991,8 @@
|
|||||||
010015D003EE4000,"The Jackbox Party Pack 2",online-working,playable,2022-08-22 18:23:40
|
010015D003EE4000,"The Jackbox Party Pack 2",online-working,playable,2022-08-22 18:23:40
|
||||||
0100CC80013D6000,"The Jackbox Party Pack 3",slow;online-working,playable,2022-08-22 18:41:06
|
0100CC80013D6000,"The Jackbox Party Pack 3",slow;online-working,playable,2022-08-22 18:41:06
|
||||||
0100E1F003EE8000,"The Jackbox Party Pack 4",online-working,playable,2022-08-22 18:56:34
|
0100E1F003EE8000,"The Jackbox Party Pack 4",online-working,playable,2022-08-22 18:56:34
|
||||||
|
01006fe0096ac000,"The Jackbox Party Pack 5",slow;online-working,ingame,2025-02-14 05:32:00
|
||||||
|
01005a400db52000,"The Jackbox Party Pack 6",slow;online-working,ingame,2025-02-14 05:26:00
|
||||||
010052C00B184000,"The Journey Down: Chapter One",nvdec,playable,2021-02-24 13:32:41
|
010052C00B184000,"The Journey Down: Chapter One",nvdec,playable,2021-02-24 13:32:41
|
||||||
01006BC00B188000,"The Journey Down: Chapter Three",nvdec,playable,2021-02-24 13:45:27
|
01006BC00B188000,"The Journey Down: Chapter Three",nvdec,playable,2021-02-24 13:45:27
|
||||||
01009AB00B186000,"The Journey Down: Chapter Two",nvdec,playable,2021-02-24 13:32:13
|
01009AB00B186000,"The Journey Down: Chapter Two",nvdec,playable,2021-02-24 13:32:13
|
||||||
@@ -3159,6 +3171,7 @@
|
|||||||
010055E00CA68000,"Trine 4: The Nightmare Prince",gpu,nothing,2025-01-07 05:47:46
|
010055E00CA68000,"Trine 4: The Nightmare Prince",gpu,nothing,2025-01-07 05:47:46
|
||||||
0100D9000A930000,"Trine Enchanted Edition",ldn-untested;nvdec,playable,2021-06-03 11:28:15
|
0100D9000A930000,"Trine Enchanted Edition",ldn-untested;nvdec,playable,2021-06-03 11:28:15
|
||||||
01002D7010A54000,"Trinity Trigger",crash,ingame,2023-03-03 03:09:09
|
01002D7010A54000,"Trinity Trigger",crash,ingame,2023-03-03 03:09:09
|
||||||
|
010020700a5e0000,"TRIVIAL PURSUIT Live!",ldn-untested,ingame,2025-02-03 22:35:00
|
||||||
0100868013FFC000,"TRIVIAL PURSUIT Live! 2",,boots,2022-12-19 00:04:33
|
0100868013FFC000,"TRIVIAL PURSUIT Live! 2",,boots,2022-12-19 00:04:33
|
||||||
0100F78002040000,"Troll and I™",gpu;nvdec,ingame,2021-06-04 16:58:50
|
0100F78002040000,"Troll and I™",gpu;nvdec,ingame,2021-06-04 16:58:50
|
||||||
0100145011008000,"Trollhunters: Defenders of Arcadia",gpu;nvdec,ingame,2020-11-30 13:27:09
|
0100145011008000,"Trollhunters: Defenders of Arcadia",gpu;nvdec,ingame,2020-11-30 13:27:09
|
||||||
@@ -3208,6 +3221,7 @@
|
|||||||
0100AB2010B4C000,"Unlock The King",,playable,2020-09-01 13:58:27
|
0100AB2010B4C000,"Unlock The King",,playable,2020-09-01 13:58:27
|
||||||
0100A3E011CB0000,"Unlock the King 2",,playable,2021-06-15 20:43:55
|
0100A3E011CB0000,"Unlock the King 2",,playable,2021-06-15 20:43:55
|
||||||
01005AA00372A000,"UNO® for Nintendo Switch",nvdec;ldn-untested,playable,2022-07-28 14:49:47
|
01005AA00372A000,"UNO® for Nintendo Switch",nvdec;ldn-untested,playable,2022-07-28 14:49:47
|
||||||
|
0100b6e012ebe000,"UNO",ldn-untested,ingame,2025-02-03 22:40:00
|
||||||
0100E5D00CC0C000,"Unravel Two",nvdec,playable,2024-05-23 15:45:05
|
0100E5D00CC0C000,"Unravel Two",nvdec,playable,2024-05-23 15:45:05
|
||||||
010001300CC4A000,"Unruly Heroes",,playable,2021-01-07 18:09:31
|
010001300CC4A000,"Unruly Heroes",,playable,2021-01-07 18:09:31
|
||||||
0100B410138C0000,"Unspottable",,playable,2022-10-25 19:28:49
|
0100B410138C0000,"Unspottable",,playable,2022-10-25 19:28:49
|
||||||
@@ -3372,6 +3386,7 @@
|
|||||||
0100F47016F26000,"Yomawari 3",,playable,2022-05-10 08:26:51
|
0100F47016F26000,"Yomawari 3",,playable,2022-05-10 08:26:51
|
||||||
010012F00B6F2000,"Yomawari: The Long Night Collection",,playable,2022-09-03 14:36:59
|
010012F00B6F2000,"Yomawari: The Long Night Collection",,playable,2022-09-03 14:36:59
|
||||||
0100CC600ABB2000,"Yonder: The Cloud Catcher Chronicles (Retail Only)",,playable,2021-01-28 14:06:25
|
0100CC600ABB2000,"Yonder: The Cloud Catcher Chronicles (Retail Only)",,playable,2021-01-28 14:06:25
|
||||||
|
0100534009ff2000,"Yonder: The Cloud Catcher Chronicles",,playable,2025-02-03 22:19:13
|
||||||
0100BE50042F6000,"Yono and the Celestial Elephants",,playable,2021-01-28 18:23:58
|
0100BE50042F6000,"Yono and the Celestial Elephants",,playable,2021-01-28 18:23:58
|
||||||
0100F110029C8000,"Yooka-Laylee",,playable,2021-01-28 14:21:45
|
0100F110029C8000,"Yooka-Laylee",,playable,2021-01-28 14:21:45
|
||||||
010022F00DA66000,"Yooka-Laylee and the Impossible Lair",,playable,2021-03-05 17:32:21
|
010022F00DA66000,"Yooka-Laylee and the Impossible Lair",,playable,2021-03-05 17:32:21
|
||||||
|
|||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using ARMeilleure.CodeGen.Linking;
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using ARMeilleure.Translation.Cache;
|
using ARMeilleure.Translation.Cache;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen
|
namespace ARMeilleure.CodeGen
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace ARMeilleure.Memory
|
|||||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||||
|
|
||||||
public IJitMemoryBlock Block { get; }
|
public IJitMemoryBlock Block { get; }
|
||||||
|
public IJitMemoryAllocator Allocator { get; }
|
||||||
|
|
||||||
public nint Pointer => Block.Pointer;
|
public nint Pointer => Block.Pointer;
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ namespace ARMeilleure.Memory
|
|||||||
granularity = DefaultGranularity;
|
granularity = DefaultGranularity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Allocator = allocator;
|
||||||
Block = allocator.Reserve(maxSize);
|
Block = allocator.Reserve(maxSize);
|
||||||
_maxSize = maxSize;
|
_maxSize = maxSize;
|
||||||
_sizeGranularity = granularity;
|
_sizeGranularity = granularity;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using Ryujinx.Common.Memory.PartialUnmaps;
|
using Ryujinx.Common.Memory.PartialUnmaps;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.State
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using ARMeilleure.Instructions;
|
|||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using ARMeilleure.CodeGen;
|
|||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.Native;
|
using ARMeilleure.Native;
|
||||||
|
using Humanizer;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -18,9 +20,8 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
private static readonly int _pageMask = _pageSize - 1;
|
private static readonly int _pageMask = _pageSize - 1;
|
||||||
|
|
||||||
private const int CodeAlignment = 4; // Bytes.
|
private const int CodeAlignment = 4; // Bytes.
|
||||||
private const int CacheSize = 2047 * 1024 * 1024;
|
private const int CacheSize = 256 * 1024 * 1024;
|
||||||
|
|
||||||
private static ReservedRegion _jitRegion;
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static CacheMemoryAllocator _cacheAllocator;
|
private static CacheMemoryAllocator _cacheAllocator;
|
||||||
@@ -30,6 +31,9 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
private static readonly Lock _lock = new();
|
private static readonly Lock _lock = new();
|
||||||
private static bool _initialized;
|
private static bool _initialized;
|
||||||
|
|
||||||
|
private static readonly List<ReservedRegion> _jitRegions = [];
|
||||||
|
private static int _activeRegionIndex = 0;
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
public static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
|
public static partial nint FlushInstructionCache(nint hProcess, nint lpAddress, nuint dwSize);
|
||||||
@@ -48,7 +52,9 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
ReservedRegion firstRegion = new(allocator, CacheSize);
|
||||||
|
_jitRegions.Add(firstRegion);
|
||||||
|
_activeRegionIndex = 0;
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
@@ -59,7 +65,9 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
|
JitUnwindWindows.InstallFunctionTableHandler(
|
||||||
|
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
@@ -75,8 +83,8 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
Debug.Assert(_initialized);
|
Debug.Assert(_initialized);
|
||||||
|
|
||||||
int funcOffset = Allocate(code.Length);
|
int funcOffset = Allocate(code.Length);
|
||||||
|
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
|
||||||
nint funcPtr = _jitRegion.Pointer + funcOffset;
|
nint funcPtr = targetRegion.Pointer + funcOffset;
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
@@ -90,9 +98,9 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReprotectAsWritable(funcOffset, code.Length);
|
ReprotectAsWritable(targetRegion, funcOffset, code.Length);
|
||||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||||
ReprotectAsExecutable(funcOffset, code.Length);
|
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
@@ -116,52 +124,83 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
Debug.Assert(_initialized);
|
Debug.Assert(_initialized);
|
||||||
|
|
||||||
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
|
foreach (ReservedRegion region in _jitRegions)
|
||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
|
||||||
{
|
{
|
||||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
|
||||||
|
|
||||||
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
|
{
|
||||||
|
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsWritable(int offset, int size)
|
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
|
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = offset & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||||
|
|
||||||
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsExecutable(int offset, int size)
|
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
|
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = offset & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||||
|
|
||||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int Allocate(int codeSize)
|
private static int Allocate(int codeSize)
|
||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
|
||||||
|
|
||||||
if (allocOffset < 0)
|
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("JIT Cache exhausted.");
|
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||||
|
|
||||||
|
if (allocOffset >= 0)
|
||||||
|
{
|
||||||
|
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||||
|
_activeRegionIndex = i;
|
||||||
|
return allocOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
int exhaustedRegion = _activeRegionIndex;
|
||||||
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
|
_jitRegions.Add(newRegion);
|
||||||
|
_activeRegionIndex = _jitRegions.Count - 1;
|
||||||
|
|
||||||
|
int newRegionNumber = _activeRegionIndex;
|
||||||
|
|
||||||
return allocOffset;
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
|
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||||
|
|
||||||
|
int allocOffsetNew = _cacheAllocator.Allocate(codeSize);
|
||||||
|
if (allocOffsetNew < 0)
|
||||||
|
{
|
||||||
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
|
}
|
||||||
|
|
||||||
|
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
|
||||||
|
return allocOffsetNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int AlignCodeSize(int codeSize)
|
private static int AlignCodeSize(int codeSize)
|
||||||
{
|
{
|
||||||
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
||||||
@@ -185,18 +224,21 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
foreach (ReservedRegion _ in _jitRegions)
|
||||||
|
|
||||||
if (index < 0)
|
|
||||||
{
|
{
|
||||||
index = ~index - 1;
|
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
|
||||||
}
|
|
||||||
|
|
||||||
if (index >= 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
entry = _cacheEntries[index];
|
index = ~index - 1;
|
||||||
entryIndex = index;
|
}
|
||||||
return true;
|
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
entry = _cacheEntries[index];
|
||||||
|
entryIndex = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation.Cache
|
namespace ARMeilleure.Translation.Cache
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
class DelegateInfo
|
class DelegateInfo
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
delegate void DispatcherFunction(nint nativeContext, ulong startAddress);
|
delegate void DispatcherFunction(nint nativeContext, ulong startAddress);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
delegate ulong GuestFunction(nint nativeContextPtr);
|
delegate ulong GuestFunction(nint nativeContextPtr);
|
||||||
|
|||||||
@@ -144,17 +144,15 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
|
|
||||||
public List<ulong> GetBlacklistedFunctions()
|
public List<ulong> GetBlacklistedFunctions()
|
||||||
{
|
{
|
||||||
List<ulong> funcs = new List<ulong>();
|
List<ulong> funcs = [];
|
||||||
|
|
||||||
foreach (var profiledFunc in ProfiledFuncs)
|
foreach ((ulong ptr, FuncProfile funcProfile) in ProfiledFuncs)
|
||||||
{
|
{
|
||||||
if (profiledFunc.Value.Blacklist)
|
if (!funcProfile.Blacklist)
|
||||||
{
|
continue;
|
||||||
if (!funcs.Contains(profiledFunc.Key))
|
|
||||||
{
|
if (!funcs.Contains(ptr))
|
||||||
funcs.Add(profiledFunc.Key);
|
funcs.Add(ptr);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return funcs;
|
return funcs;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using ARMeilleure.Diagnostics;
|
|||||||
using ARMeilleure.Instructions;
|
using ARMeilleure.Instructions;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.Signal;
|
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation.Cache;
|
using ARMeilleure.Translation.Cache;
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation.Cache;
|
using ARMeilleure.Translation.Cache;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo;
|
using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Ryujinx.Audio.Common;
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Audio.Backends.Common
|
namespace Ryujinx.Audio.Backends.Common
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CpuAddress = System.UInt64;
|
using CpuAddress = System.UInt64;
|
||||||
using DspAddress = System.UInt64;
|
using DspAddress = System.UInt64;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
|||||||
118
src/Ryujinx.Common/Helpers/Patterns.cs
Normal file
118
src/Ryujinx.Common/Helpers/Patterns.cs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Helper
|
||||||
|
{
|
||||||
|
public static partial class Patterns
|
||||||
|
{
|
||||||
|
#region Accessors
|
||||||
|
|
||||||
|
public static readonly Regex Numeric = NumericRegex();
|
||||||
|
|
||||||
|
public static readonly Regex AmdGcn = AmdGcnRegex();
|
||||||
|
public static readonly Regex NvidiaConsumerClass = NvidiaConsumerClassRegex();
|
||||||
|
|
||||||
|
public static readonly Regex DomainLp1Ns = DomainLp1NsRegex();
|
||||||
|
public static readonly Regex DomainLp1Lp1Npln = DomainLp1Lp1NplnRegex();
|
||||||
|
public static readonly Regex DomainLp1Znc = DomainLp1ZncRegex();
|
||||||
|
public static readonly Regex DomainSbApi = DomainSbApiRegex();
|
||||||
|
public static readonly Regex DomainSbAccounts = DomainSbAccountsRegex();
|
||||||
|
public static readonly Regex DomainAccounts = DomainAccountsRegex();
|
||||||
|
|
||||||
|
public static readonly Regex Module = ModuleRegex();
|
||||||
|
public static readonly Regex FsSdk = FsSdkRegex();
|
||||||
|
public static readonly Regex SdkMw = SdkMwRegex();
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public static readonly Regex CJK = CJKRegex();
|
||||||
|
|
||||||
|
public static readonly Regex LdnPassphrase = LdnPassphraseRegex();
|
||||||
|
|
||||||
|
public static readonly Regex CleanText = CleanTextRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Generated pattern stubs
|
||||||
|
|
||||||
|
#region Numeric validation
|
||||||
|
|
||||||
|
[GeneratedRegex("[0-9]|.")]
|
||||||
|
internal static partial Regex NumericRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GPU names
|
||||||
|
|
||||||
|
[GeneratedRegex(
|
||||||
|
"Radeon (((HD|R(5|7|9|X)) )?((M?[2-6]\\d{2}(\\D|$))|([7-8]\\d{3}(\\D|$))|Fury|Nano))|(Pro Duo)")]
|
||||||
|
internal static partial Regex AmdGcnRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex("NVIDIA GeForce (R|G)?TX? (\\d{3}\\d?)M?")]
|
||||||
|
internal static partial Regex NvidiaConsumerClassRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DNS blocking
|
||||||
|
|
||||||
|
public static readonly Regex[] BlockedHosts =
|
||||||
|
[
|
||||||
|
DomainLp1Ns,
|
||||||
|
DomainLp1Lp1Npln,
|
||||||
|
DomainLp1Znc,
|
||||||
|
DomainSbApi,
|
||||||
|
DomainSbAccounts,
|
||||||
|
DomainAccounts
|
||||||
|
];
|
||||||
|
|
||||||
|
const RegexOptions DnsRegexOpts =
|
||||||
|
RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^(.*)\-lp1\.(n|s)\.n\.srv\.nintendo\.net$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainLp1NsRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^(.*)\-lp1\.lp1\.t\.npln\.srv\.nintendo\.net$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainLp1Lp1NplnRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^(.*)\-lp1\.(znc|p)\.srv\.nintendo\.net$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainLp1ZncRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^(.*)\-sb\-api\.accounts\.nintendo\.com$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainSbApiRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^(.*)\-sb\.accounts\.nintendo\.com$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainSbAccountsRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^accounts\.nintendo\.com$", DnsRegexOpts)]
|
||||||
|
internal static partial Regex DomainAccountsRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Executable information
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[a-z]:[\\/][ -~]{5,}\.nss", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)]
|
||||||
|
internal static partial Regex ModuleRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"sdk_version: ([0-9.]*)")]
|
||||||
|
internal static partial Regex FsSdkRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"SDK MW[ -~]*")]
|
||||||
|
internal static partial Regex SdkMwRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CJK
|
||||||
|
|
||||||
|
[GeneratedRegex(
|
||||||
|
"\\p{IsHangulJamo}|\\p{IsCJKRadicalsSupplement}|\\p{IsCJKSymbolsandPunctuation}|\\p{IsEnclosedCJKLettersandMonths}|\\p{IsCJKCompatibility}|\\p{IsCJKUnifiedIdeographsExtensionA}|\\p{IsCJKUnifiedIdeographs}|\\p{IsHangulSyllables}|\\p{IsCJKCompatibilityForms}")]
|
||||||
|
private static partial Regex CJKRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
[GeneratedRegex("Ryujinx-[0-9a-f]{8}")]
|
||||||
|
private static partial Regex LdnPassphraseRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"[^\u0000\u0009\u000A\u000D\u0020-\uFFFF]..")]
|
||||||
|
private static partial Regex CleanTextRegex();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,14 +10,18 @@ namespace Ryujinx.Common.Helper
|
|||||||
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
||||||
public static bool IsWindows => OperatingSystem.IsWindows();
|
public static bool IsWindows => OperatingSystem.IsWindows();
|
||||||
public static bool IsLinux => OperatingSystem.IsLinux();
|
public static bool IsLinux => OperatingSystem.IsLinux();
|
||||||
|
|
||||||
|
public static bool IsArm => RuntimeInformation.OSArchitecture is Architecture.Arm64;
|
||||||
|
|
||||||
|
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64;
|
||||||
|
|
||||||
public static bool IsIntelMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.X64;
|
public static bool IsIntelMac => IsMacOS && IsX64;
|
||||||
public static bool IsArmMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.Arm64;
|
public static bool IsArmMac => IsMacOS && IsArm;
|
||||||
|
|
||||||
public static bool IsX64Windows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.X64);
|
public static bool IsX64Windows => IsWindows && IsX64;
|
||||||
public static bool IsArmWindows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
|
public static bool IsArmWindows => IsWindows && IsArm;
|
||||||
|
|
||||||
public static bool IsX64Linux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.X64);
|
public static bool IsX64Linux => IsLinux && IsX64;
|
||||||
public static bool IsArmLinux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
|
public static bool IsArmLinux => IsLinux && IsArmMac;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/Ryujinx.Common/SharedConstants.cs
Normal file
9
src/Ryujinx.Common/SharedConstants.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public static class SharedConstants
|
||||||
|
{
|
||||||
|
public const string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||||
|
public const short LanPlayPort = 30456;
|
||||||
|
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ using Ryujinx.Common.Configuration;
|
|||||||
using Ryujinx.Common.Helper;
|
using Ryujinx.Common.Helper;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Common
|
namespace Ryujinx.Common
|
||||||
{
|
{
|
||||||
@@ -48,15 +47,15 @@ namespace Ryujinx.Common
|
|||||||
"01006f8002326000", // Animal Crossings: New Horizons
|
"01006f8002326000", // Animal Crossings: New Horizons
|
||||||
"01009bf0072d4000", // Captain Toad: Treasure Tracker
|
"01009bf0072d4000", // Captain Toad: Treasure Tracker
|
||||||
"01009510001ca000", // Fast RMX
|
"01009510001ca000", // Fast RMX
|
||||||
"01005CA01580E000", // Persona 5 Royale
|
"01005CA01580E000", // Persona 5 Royal
|
||||||
|
"0100b880154fc000", // Persona 5 The Royal (Japan)
|
||||||
"010015100b514000", // Super Mario Bros. Wonder
|
"010015100b514000", // Super Mario Bros. Wonder
|
||||||
"0100000000010000", // Super Mario Odyssey
|
"0100000000010000", // Super Mario Odyssey
|
||||||
|
|
||||||
// Further testing is appreciated, I did not test the entire game:
|
// Further testing is appreciated, I did not test the entire game:
|
||||||
"01007300020fa000", // Astral Chain
|
//"010076f0049a2000", // Bayonetta
|
||||||
"010076f0049a2000", // Bayonetta
|
//"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
||||||
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
//"0100f4300bf2c000", // New Pokemon Snap
|
||||||
"0100f4300bf2c000", // New Pokemon Snap
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public static string GetDiscordGameAsset(string titleId)
|
public static string GetDiscordGameAsset(string titleId)
|
||||||
@@ -164,15 +163,16 @@ namespace Ryujinx.Common
|
|||||||
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
|
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
|
||||||
|
|
||||||
//NSO Membership games
|
//NSO Membership games
|
||||||
"0100ccf019c8c000", // F-ZERO 99
|
|
||||||
"0100c62011050000", // GB - Nintendo Switch Online
|
"0100c62011050000", // GB - Nintendo Switch Online
|
||||||
"010012f017576000", // GBA - Nintendo Switch Online
|
"010012f017576000", // GBA - Nintendo Switch Online
|
||||||
"0100c9a00ece6000", // N64 - Nintendo Switch Online
|
"0100c9a00ece6000", // N64 - Nintendo Switch Online
|
||||||
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
|
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
|
||||||
"0100d870045b6000", // NES - Nintendo Switch Online
|
"0100d870045b6000", // NES - Nintendo Switch Online
|
||||||
|
"0100b3c014bda000", // SEGA Genesis - Nintendo Switch Online
|
||||||
|
"01008d300c50c000", // SNES - Nintendo Switch Online
|
||||||
|
"0100ccf019c8c000", // F-ZERO 99
|
||||||
"0100ad9012510000", // PAC-MAN 99
|
"0100ad9012510000", // PAC-MAN 99
|
||||||
"010040600c5ce000", // Tetris 99
|
"010040600c5ce000", // Tetris 99
|
||||||
"01008d300c50c000", // SNES - Nintendo Switch Online
|
|
||||||
"0100277011f1a000", // Super Mario Bros. 35
|
"0100277011f1a000", // Super Mario Bros. 35
|
||||||
|
|
||||||
//Misc Nintendo 1st party games
|
//Misc Nintendo 1st party games
|
||||||
@@ -218,6 +218,7 @@ namespace Ryujinx.Common
|
|||||||
//Misc Games
|
//Misc Games
|
||||||
"010056e00853a000", // A Hat in Time
|
"010056e00853a000", // A Hat in Time
|
||||||
"0100fd1014726000", // Baldurs Gate: Dark Alliance
|
"0100fd1014726000", // Baldurs Gate: Dark Alliance
|
||||||
|
"01008c2019598000", // Bluey: The Video Game
|
||||||
"0100c6800b934000", // Brawlhalla
|
"0100c6800b934000", // Brawlhalla
|
||||||
"0100dbf01000a000", // Burnout Paradise Remastered
|
"0100dbf01000a000", // Burnout Paradise Remastered
|
||||||
"0100744001588000", // Cars 3: Driven to Win
|
"0100744001588000", // Cars 3: Driven to Win
|
||||||
@@ -228,6 +229,7 @@ namespace Ryujinx.Common
|
|||||||
"01008c8012920000", // Dying Light Platinum Edition
|
"01008c8012920000", // Dying Light Platinum Edition
|
||||||
"01001cc01b2d4000", // Goat Simulator 3
|
"01001cc01b2d4000", // Goat Simulator 3
|
||||||
"01003620068ea000", // Hand of Fate 2
|
"01003620068ea000", // Hand of Fate 2
|
||||||
|
"0100f7e00c70e000", // Hogwarts Legacy
|
||||||
"010085500130a000", // Lego City: Undercover
|
"010085500130a000", // Lego City: Undercover
|
||||||
"010073c01af34000", // LEGO Horizon Adventures
|
"010073c01af34000", // LEGO Horizon Adventures
|
||||||
"0100d71004694000", // Minecraft
|
"0100d71004694000", // Minecraft
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
|
|||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using ARMeilleure.Common;
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using Ryujinx.Cpu.Signal;
|
using Ryujinx.Cpu.Signal;
|
||||||
using Ryujinx.Memory;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Jit
|
namespace Ryujinx.Cpu.Jit
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
|
|||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using Ryujinx.Memory.Tracking;
|
|||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Jit
|
namespace Ryujinx.Cpu.Jit
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using ARMeilleure.Memory;
|
|||||||
using Ryujinx.Cpu.LightningJit.Arm32;
|
using Ryujinx.Cpu.LightningJit.Arm32;
|
||||||
using Ryujinx.Cpu.LightningJit.Arm64;
|
using Ryujinx.Cpu.LightningJit.Arm64;
|
||||||
using Ryujinx.Cpu.LightningJit.State;
|
using Ryujinx.Cpu.LightningJit.State;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit
|
namespace Ryujinx.Cpu.LightningJit
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using ARMeilleure.Common;
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using Ryujinx.Cpu.LightningJit.CodeGen;
|
using Ryujinx.Cpu.LightningJit.CodeGen;
|
||||||
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Cpu.LightningJit.CodeGen;
|
using Ryujinx.Cpu.LightningJit.CodeGen;
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ryujinx.Cpu.LightningJit.CodeGen;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
||||||
{
|
{
|
||||||
static class InstEmitVfpMove
|
static class InstEmitVfpMove
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit.Arm64
|
namespace Ryujinx.Cpu.LightningJit.Arm64
|
||||||
{
|
{
|
||||||
static class SysUtils
|
static class SysUtils
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using ARMeilleure.Memory;
|
|||||||
using Ryujinx.Cpu.LightningJit.CodeGen;
|
using Ryujinx.Cpu.LightningJit.CodeGen;
|
||||||
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
||||||
using Ryujinx.Cpu.LightningJit.Graph;
|
using Ryujinx.Cpu.LightningJit.Graph;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
|
using Humanizer;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -15,9 +17,8 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
private static readonly int _pageMask = _pageSize - 1;
|
private static readonly int _pageMask = _pageSize - 1;
|
||||||
|
|
||||||
private const int CodeAlignment = 4; // Bytes.
|
private const int CodeAlignment = 4; // Bytes.
|
||||||
private const int CacheSize = 2047 * 1024 * 1024;
|
private const int CacheSize = 256 * 1024 * 1024;
|
||||||
|
|
||||||
private static ReservedRegion _jitRegion;
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static CacheMemoryAllocator _cacheAllocator;
|
private static CacheMemoryAllocator _cacheAllocator;
|
||||||
@@ -26,6 +27,8 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
|
|
||||||
private static readonly Lock _lock = new();
|
private static readonly Lock _lock = new();
|
||||||
private static bool _initialized;
|
private static bool _initialized;
|
||||||
|
private static readonly List<ReservedRegion> _jitRegions = [];
|
||||||
|
private static int _activeRegionIndex = 0;
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||||
@@ -45,7 +48,9 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
ReservedRegion firstRegion = new(allocator, CacheSize);
|
||||||
|
_jitRegions.Add(firstRegion);
|
||||||
|
_activeRegionIndex = 0;
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
@@ -65,8 +70,8 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
Debug.Assert(_initialized);
|
Debug.Assert(_initialized);
|
||||||
|
|
||||||
int funcOffset = Allocate(code.Length);
|
int funcOffset = Allocate(code.Length);
|
||||||
|
ReservedRegion targetRegion = _jitRegions[_activeRegionIndex];
|
||||||
nint funcPtr = _jitRegion.Pointer + funcOffset;
|
nint funcPtr = targetRegion.Pointer + funcOffset;
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||||
{
|
{
|
||||||
@@ -80,18 +85,11 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReprotectAsWritable(funcOffset, code.Length);
|
ReprotectAsWritable(targetRegion, funcOffset, code.Length);
|
||||||
code.CopyTo(new Span<byte>((void*)funcPtr, code.Length));
|
Marshal.Copy(code.ToArray(), 0, funcPtr, code.Length);
|
||||||
ReprotectAsExecutable(funcOffset, code.Length);
|
ReprotectAsExecutable(targetRegion, funcOffset, code.Length);
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length);
|
||||||
{
|
|
||||||
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (nuint)code.Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Add(funcOffset, code.Length);
|
Add(funcOffset, code.Length);
|
||||||
@@ -106,50 +104,80 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
{
|
{
|
||||||
Debug.Assert(_initialized);
|
Debug.Assert(_initialized);
|
||||||
|
|
||||||
int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
|
foreach (ReservedRegion region in _jitRegions)
|
||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
|
||||||
{
|
{
|
||||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
if (pointer.ToInt64() < region.Pointer.ToInt64() ||
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int funcOffset = (int)(pointer.ToInt64() - region.Pointer.ToInt64());
|
||||||
|
|
||||||
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
|
{
|
||||||
|
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsWritable(int offset, int size)
|
private static void ReprotectAsWritable(ReservedRegion region, int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
|
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = offset & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||||
|
|
||||||
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReprotectAsExecutable(int offset, int size)
|
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size)
|
||||||
{
|
{
|
||||||
int endOffs = offset + size;
|
int endOffs = offset + size;
|
||||||
|
|
||||||
int regionStart = offset & ~_pageMask;
|
int regionStart = offset & ~_pageMask;
|
||||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||||
|
|
||||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int Allocate(int codeSize)
|
private static int Allocate(int codeSize)
|
||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
|
||||||
|
|
||||||
if (allocOffset < 0)
|
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("JIT Cache exhausted.");
|
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||||
|
|
||||||
|
if (allocOffset >= 0)
|
||||||
|
{
|
||||||
|
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||||
|
_activeRegionIndex = i;
|
||||||
|
return allocOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
int exhaustedRegion = _activeRegionIndex;
|
||||||
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
|
_jitRegions.Add(newRegion);
|
||||||
|
_activeRegionIndex = _jitRegions.Count - 1;
|
||||||
|
|
||||||
|
int newRegionNumber = _activeRegionIndex;
|
||||||
|
|
||||||
return allocOffset;
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
|
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||||
|
|
||||||
|
int allocOffsetNew = _cacheAllocator.Allocate(codeSize);
|
||||||
|
if (allocOffsetNew < 0)
|
||||||
|
{
|
||||||
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
|
}
|
||||||
|
|
||||||
|
newRegion.ExpandIfNeeded((ulong)allocOffsetNew + (ulong)codeSize);
|
||||||
|
return allocOffsetNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AlignCodeSize(int codeSize)
|
private static int AlignCodeSize(int codeSize)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit.Cache
|
namespace Ryujinx.Cpu.LightningJit.Cache
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||||||
{
|
{
|
||||||
private const int CodeAlignment = 4; // Bytes.
|
private const int CodeAlignment = 4; // Bytes.
|
||||||
private const int SharedCacheSize = 2047 * 1024 * 1024;
|
private const int SharedCacheSize = 2047 * 1024 * 1024;
|
||||||
private const int LocalCacheSize = 128 * 1024 * 1024;
|
private const int LocalCacheSize = 256 * 1024 * 1024;
|
||||||
|
|
||||||
// How many calls to the same function we allow until we pad the shared cache to force the function to become available there
|
// How many calls to the same function we allow until we pad the shared cache to force the function to become available there
|
||||||
// and allow the guest to take the fast path.
|
// and allow the guest to take the fast path.
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit
|
namespace Ryujinx.Cpu.LightningJit
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.LightningJit
|
namespace Ryujinx.Cpu.LightningJit
|
||||||
{
|
{
|
||||||
class TranslatedFunction
|
class TranslatedFunction
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Ryujinx.Cpu.LightningJit.Cache;
|
|||||||
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
|
||||||
using Ryujinx.Cpu.LightningJit.State;
|
using Ryujinx.Cpu.LightningJit.State;
|
||||||
using Ryujinx.Cpu.Signal;
|
using Ryujinx.Cpu.Signal;
|
||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Signal
|
namespace Ryujinx.Cpu.Signal
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Ryujinx.Common.Logging;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Device
|
namespace Ryujinx.Graphics.Device
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
|
namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
|
||||||
|
|||||||
@@ -913,7 +913,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
Span<Rectangle<int>> scissors =
|
Span<Rectangle<int>> scissors =
|
||||||
[
|
[
|
||||||
new Rectangle<int>(scissorX, scissorY, scissorW, scissorH)
|
new(scissorX, scissorY, scissorW, scissorH)
|
||||||
];
|
];
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetScissors(scissors);
|
_context.Renderer.Pipeline.SetScissors(scissors);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ryujinx.Graphics.Device;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Ryujinx.Graphics.Gpu.Memory;
|
|||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using Ryujinx.Memory.Range;
|
using Ryujinx.Memory.Range;
|
||||||
using System;
|
using System;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using Ryujinx.Memory;
|
|||||||
using Ryujinx.Memory.Range;
|
using Ryujinx.Memory.Range;
|
||||||
using Ryujinx.Memory.Tracking;
|
using Ryujinx.Memory.Tracking;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
|
|||||||
using Ryujinx.Graphics.Gpu.Engine;
|
using Ryujinx.Graphics.Gpu.Engine;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Shader
|
namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
|
|
||||||
ShaderProgram program = translatorContext.Translate();
|
ShaderProgram program = translatorContext.Translate();
|
||||||
|
|
||||||
CachedShaderStage[] shaders = [new CachedShaderStage(program.Info, shader.Code, shader.Cb1Data)];
|
CachedShaderStage[] shaders = [new(program.Info, shader.Code, shader.Cb1Data)];
|
||||||
|
|
||||||
_compilationQueue.Enqueue(new ProgramCompilation([program], shaders, newSpecState, programIndex, isCompute: true));
|
_compilationQueue.Enqueue(new ProgramCompilation([program], shaders, newSpecState, programIndex, isCompute: true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ryujinx.Common;
|
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
|||||||
}
|
}
|
||||||
|
|
||||||
using ManualResetEvent waitEvent = new(false);
|
using ManualResetEvent waitEvent = new(false);
|
||||||
SyncpointWaiterHandle info = _syncpoints[id].RegisterCallback(threshold, (x) => waitEvent.Set());
|
SyncpointWaiterHandle info = _syncpoints[id].RegisterCallback(threshold, _ => waitEvent.Set());
|
||||||
|
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
@@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
|||||||
|
|
||||||
bool signaled = waitEvent.WaitOne(timeout);
|
bool signaled = waitEvent.WaitOne(timeout);
|
||||||
|
|
||||||
if (!signaled && info != null)
|
if (!signaled)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Gpu, $"Wait on syncpoint {id} for threshold {threshold} took more than {timeout.TotalMilliseconds}ms, resuming execution...");
|
Logger.Error?.Print(LogClass.Gpu, $"Wait on syncpoint {id} for threshold {threshold} took more than {timeout.TotalMilliseconds}ms, resuming execution...");
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using SharpMetal.Metal;
|
using SharpMetal.Metal;
|
||||||
using System;
|
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Metal
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/Ryujinx.Graphics.Nvdec.FFmpeg/Library/win-x64/avcodec-59.dll
Normal file
BIN
src/Ryujinx.Graphics.Nvdec.FFmpeg/Library/win-x64/avcodec-59.dll
Normal file
Binary file not shown.
BIN
src/Ryujinx.Graphics.Nvdec.FFmpeg/Library/win-x64/avutil-57.dll
Normal file
BIN
src/Ryujinx.Graphics.Nvdec.FFmpeg/Library/win-x64/avutil-57.dll
Normal file
Binary file not shown.
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
struct AVCodec
|
struct AVCodec
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
struct AVCodec501
|
struct AVCodec501
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
struct FFCodec<T> where T : struct
|
struct FFCodec<T> where T : struct
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
{
|
{
|
||||||
struct FFCodecLegacy<T> where T : struct
|
struct FFCodecLegacy<T> where T : struct
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
|||||||
public const string AvCodecLibraryName = "avcodec";
|
public const string AvCodecLibraryName = "avcodec";
|
||||||
public const string AvUtilLibraryName = "avutil";
|
public const string AvUtilLibraryName = "avutil";
|
||||||
|
|
||||||
|
// Library Name, Min Version, Max Version.
|
||||||
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new()
|
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new()
|
||||||
{
|
{
|
||||||
{ AvCodecLibraryName, (58, 59) },
|
{ AvCodecLibraryName, (58, 59) },
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
|
<RuntimeIdentifiers>win-x64;osx-x64;osx-arm64;linux-x64;linux-arm64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -10,4 +11,31 @@
|
|||||||
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ContentWithTargetPath Include="Library\win-x64\*" Condition="'$(RuntimeIdentifier)' == 'win-x64'">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
|
||||||
|
<ContentWithTargetPath Include="Library\osx-x64\*" Condition="'$(RuntimeIdentifier)' == 'osx-x64'">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
|
||||||
|
<ContentWithTargetPath Include="Library\osx-arm64\*" Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
|
||||||
|
<ContentWithTargetPath Include="Library\linux-x64\*" Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
|
||||||
|
<ContentWithTargetPath Include="Library\linux-arm64\*" Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Bits10 = 10, // < 10 bits
|
Bits10 = 10, // < 10 bits
|
||||||
Bits12 = 12, // < 12 bits
|
Bits12 = 12, // < 12 bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,56 +1,75 @@
|
|||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal enum CodecErr
|
internal enum CodecErr
|
||||||
{
|
{
|
||||||
/*!\brief Operation completed without error */
|
/// <summary>
|
||||||
CodecOk,
|
/// Operation completed without error
|
||||||
|
/// </summary>
|
||||||
|
Ok,
|
||||||
|
|
||||||
/*!\brief Unspecified error */
|
/// <summary>
|
||||||
CodecError,
|
/// Unspecified error
|
||||||
|
/// </summary>
|
||||||
|
Error,
|
||||||
|
|
||||||
/*!\brief Memory operation failed */
|
/// <summary>
|
||||||
CodecMemError,
|
/// Memory operation failed
|
||||||
|
/// </summary>
|
||||||
|
MemError,
|
||||||
|
|
||||||
/*!\brief ABI version mismatch */
|
/// <summary>
|
||||||
CodecAbiMismatch,
|
/// ABI version mismatch
|
||||||
|
/// </summary>
|
||||||
|
AbiMismatch,
|
||||||
|
|
||||||
/*!\brief Algorithm does not have required capability */
|
/// <summary>
|
||||||
CodecIncapable,
|
/// Algorithm does not have required capability
|
||||||
|
/// </summary>
|
||||||
|
Incapable,
|
||||||
|
|
||||||
/*!\brief The given bitstream is not supported.
|
/// <summary>
|
||||||
*
|
/// The given bitstream is not supported.
|
||||||
* The bitstream was unable to be parsed at the highest level. The decoder
|
/// </summary>
|
||||||
* is unable to proceed. This error \ref SHOULD be treated as fatal to the
|
/// <remarks>
|
||||||
* stream. */
|
/// The bitstream was unable to be parsed at the highest level.<br/>
|
||||||
CodecUnsupBitstream,
|
/// The decoder is unable to proceed.<br/>
|
||||||
|
/// This error SHOULD be treated as fatal to the stream.
|
||||||
|
/// </remarks>
|
||||||
|
UnsupBitstream,
|
||||||
|
|
||||||
/*!\brief Encoded bitstream uses an unsupported feature
|
/// <summary>
|
||||||
*
|
/// Encoded bitstream uses an unsupported feature
|
||||||
* The decoder does not implement a feature required by the encoder. This
|
/// </summary>
|
||||||
* return code should only be used for features that prevent future
|
/// <remarks>
|
||||||
* pictures from being properly decoded. This error \ref MAY be treated as
|
/// The decoder does not implement a feature required by the encoder.<br/>
|
||||||
* fatal to the stream or \ref MAY be treated as fatal to the current GOP.
|
/// This return code should only be used for features that prevent future
|
||||||
*/
|
/// pictures from being properly decoded.<br/>
|
||||||
CodecUnsupFeature,
|
/// <br/>
|
||||||
|
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
|
||||||
|
/// </remarks>
|
||||||
|
UnsupFeature,
|
||||||
|
|
||||||
/*!\brief The coded data for this stream is corrupt or incomplete
|
/// <summary>
|
||||||
*
|
/// The coded data for this stream is corrupt or incomplete.
|
||||||
* There was a problem decoding the current frame. This return code
|
/// </summary>
|
||||||
* should only be used for failures that prevent future pictures from
|
/// <remarks>
|
||||||
* being properly decoded. This error \ref MAY be treated as fatal to the
|
/// There was a problem decoding the current frame.<br/>
|
||||||
* stream or \ref MAY be treated as fatal to the current GOP. If decoding
|
/// This return code should only be used
|
||||||
* is continued for the current GOP, artifacts may be present.
|
/// for failures that prevent future pictures from being properly decoded.<br/>
|
||||||
*/
|
/// <br/>
|
||||||
CodecCorruptFrame,
|
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.<br/>
|
||||||
|
/// If decoding is continued for the current GOP, artifacts may be present.
|
||||||
|
/// </remarks>
|
||||||
|
CorruptFrame,
|
||||||
|
|
||||||
/*!\brief An application-supplied parameter is not valid.
|
/// <summary>
|
||||||
*
|
/// An application-supplied parameter is not valid.
|
||||||
*/
|
/// </summary>
|
||||||
CodecInvalidParam,
|
InvalidParam,
|
||||||
|
|
||||||
/*!\brief An iterator reached the end of list.
|
/// <summary>
|
||||||
*
|
/// An iterator reached the end of list.
|
||||||
*/
|
/// </summary>
|
||||||
CodecListEnd,
|
ListEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static byte ClipPixel(int val)
|
public static byte ClipPixel(int val)
|
||||||
{
|
{
|
||||||
return (byte)((val > 255) ? 255 : (val < 0) ? 0 : val);
|
return (byte)(val > 255 ? 255 : val < 0 ? 0 : val);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -56,4 +56,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
return numValues > 0 ? GetMsb(numValues) + 1 : 0;
|
return numValues > 0 ? GetMsb(numValues) + 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,6 +51,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(item.Pointer);
|
Marshal.FreeHGlobal(item.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Pointer = ptr;
|
item.Pointer = ptr;
|
||||||
item.Length = lengthInBytes;
|
item.Length = lengthInBytes;
|
||||||
break;
|
break;
|
||||||
@@ -58,7 +59,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ArrayPtr<T>(ptr, length);
|
ArrayPtr<T> allocation = new(ptr, length);
|
||||||
|
|
||||||
|
allocation.AsSpan().Fill(default);
|
||||||
|
|
||||||
|
return allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged
|
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
|||||||
new Span<T>(ptr, length).Fill(value);
|
new Span<T>(ptr, length).Fill(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
public const int Vp9InterpExtend = 4;
|
public const int InterpExtend = 4;
|
||||||
|
|
||||||
public const int MaxMbPlane = 3;
|
public const int MaxMbPlane = 3;
|
||||||
|
|
||||||
@@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
/* Segment Feature Masks */
|
/* Segment Feature Masks */
|
||||||
public const int MaxMvRefCandidates = 2;
|
public const int MaxMvRefCandidates = 2;
|
||||||
|
|
||||||
|
public const int IntraInterContexts = 4;
|
||||||
public const int CompInterContexts = 5;
|
public const int CompInterContexts = 5;
|
||||||
public const int RefContexts = 5;
|
public const int RefContexts = 5;
|
||||||
|
|
||||||
@@ -32,12 +35,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
public const int EightTapSmooth = 1;
|
public const int EightTapSmooth = 1;
|
||||||
public const int EightTapSharp = 2;
|
public const int EightTapSharp = 2;
|
||||||
public const int SwitchableFilters = 3; /* Number of switchable filters */
|
public const int SwitchableFilters = 3; /* Number of switchable filters */
|
||||||
|
|
||||||
public const int Bilinear = 3;
|
public const int Bilinear = 3;
|
||||||
public const int Switchable = 4; /* should be the last one */
|
|
||||||
|
// The codec can operate in four possible inter prediction filter mode:
|
||||||
|
// 8-tap, 8-tap-smooth, 8-tap-sharp, and switching between the three.
|
||||||
|
public const int SwitchableFilterContexts = SwitchableFilters + 1;
|
||||||
|
public const int Switchable = 4; /* Should be the last one */
|
||||||
|
|
||||||
// Frame
|
// Frame
|
||||||
public const int RefsPerFrame = 3;
|
public const int RefsPerFrame = 3;
|
||||||
|
|
||||||
|
public const int RefFramesLog2 = 3;
|
||||||
|
public const int RefFrames = 1 << RefFramesLog2;
|
||||||
|
|
||||||
|
// 1 scratch frame for the new frame, 3 for scaled references on the encoder.
|
||||||
|
public const int FrameBuffers = RefFrames + 4;
|
||||||
|
|
||||||
|
public const int FrameContextsLog2 = 2;
|
||||||
|
public const int FrameContexts = 1 << FrameContextsLog2;
|
||||||
|
|
||||||
public const int NumPingPongBuffers = 2;
|
public const int NumPingPongBuffers = 2;
|
||||||
|
|
||||||
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
||||||
@@ -48,9 +65,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
public const int MvLow = -(1 << MvInUseBits);
|
public const int MvLow = -(1 << MvInUseBits);
|
||||||
|
|
||||||
// Coefficient token alphabet
|
// Coefficient token alphabet
|
||||||
public const int ZeroToken = 0; // 0 Extra Bits 0+0
|
public const int ZeroToken = 0; // 0 Extra Bits 0+0
|
||||||
public const int OneToken = 1; // 1 Extra Bits 0+1
|
public const int OneToken = 1; // 1 Extra Bits 0+1
|
||||||
public const int TwoToken = 2; // 2 Extra Bits 0+1
|
public const int TwoToken = 2; // 2 Extra Bits 0+1
|
||||||
|
|
||||||
public const int PivotNode = 2;
|
public const int PivotNode = 2;
|
||||||
|
|
||||||
@@ -65,5 +82,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
public const int SegmentAbsData = 1;
|
public const int SegmentAbsData = 1;
|
||||||
public const int MaxSegments = 8;
|
public const int MaxSegments = 8;
|
||||||
|
|
||||||
|
public const int PartitionTypes = (int)PartitionType.PartitionTypes;
|
||||||
|
|
||||||
|
public const int PartitionPlOffset = 4; // Number of probability models per block size
|
||||||
|
public const int PartitionContexts = 4 * PartitionPlOffset;
|
||||||
|
|
||||||
|
public const int PlaneTypes = (int)PlaneType.PlaneTypes;
|
||||||
|
|
||||||
|
public const int IntraModes = (int)PredictionMode.TmPred + 1;
|
||||||
|
|
||||||
|
public const int InterModes = 1 + (int)PredictionMode.NewMv - (int)PredictionMode.NearestMv;
|
||||||
|
|
||||||
|
public const int SkipContexts = 3;
|
||||||
|
public const int InterModeContexts = 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
{
|
||||||
|
internal static class DSubExp
|
||||||
|
{
|
||||||
|
public static int InvRecenterNonneg(int v, int m)
|
||||||
|
{
|
||||||
|
if (v > 2 * m)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (v & 1) != 0 ? m - ((v + 1) >> 1) : m + (v >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] _invMapTable =
|
||||||
|
[
|
||||||
|
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 1, 2, 3, 4,
|
||||||
|
5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34,
|
||||||
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62,
|
||||||
|
63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90,
|
||||||
|
91, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114,
|
||||||
|
115, 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
|
||||||
|
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||||
|
160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
|
||||||
|
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205,
|
||||||
|
206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
|
||||||
|
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250,
|
||||||
|
251, 252, 253, 253
|
||||||
|
];
|
||||||
|
|
||||||
|
public static int InvRemapProb(int v, int m)
|
||||||
|
{
|
||||||
|
Debug.Assert(v < _invMapTable.Length / sizeof(byte));
|
||||||
|
|
||||||
|
v = _invMapTable[v];
|
||||||
|
m--;
|
||||||
|
if (m << 1 <= Prob.MaxProb)
|
||||||
|
{
|
||||||
|
return 1 + InvRecenterNonneg(v, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
@@ -10,11 +10,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
internal static class DecodeMv
|
internal static class DecodeMv
|
||||||
{
|
{
|
||||||
private const int MvrefNeighbours = 8;
|
private const int RefNeighbours = 8;
|
||||||
|
|
||||||
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
|
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
|
||||||
{
|
{
|
||||||
return (PredictionMode)r.ReadTree(Luts.Vp9IntraModeTree, p);
|
return (PredictionMode)r.ReadTree(Luts.IntraModeTree, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
||||||
@@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
||||||
{
|
{
|
||||||
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
int mode = r.ReadTree(Luts.InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.InterMode[ctx][mode];
|
++xd.Counts.Value.InterMode[ctx][mode];
|
||||||
@@ -52,22 +52,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
||||||
{
|
{
|
||||||
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
|
return r.ReadTree(Luts.SegmentTree, segTreeProbs.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8:
|
case TxSize.Tx8X8: return fc.Tx8x8Prob[ctx].AsSpan();
|
||||||
return fc.Tx8x8Prob[ctx].AsSpan();
|
case TxSize.Tx16X16: return fc.Tx16x16Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16:
|
case TxSize.Tx32X32: return fc.Tx32x32Prob[ctx].AsSpan();
|
||||||
return fc.Tx16x16Prob[ctx].AsSpan();
|
|
||||||
case TxSize.Tx32x32:
|
|
||||||
return fc.Tx32x32Prob[ctx].AsSpan();
|
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "Invalid maxTxSize.");
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
return ReadOnlySpan<byte>.Empty;
|
return ReadOnlySpan<byte>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,15 +72,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8:
|
case TxSize.Tx8X8: return counts.Tx8x8[ctx].AsSpan();
|
||||||
return counts.Tx8x8[ctx].AsSpan();
|
case TxSize.Tx16X16: return counts.Tx16x16[ctx].AsSpan();
|
||||||
case TxSize.Tx16x16:
|
case TxSize.Tx32X32: return counts.Tx32x32[ctx].AsSpan();
|
||||||
return counts.Tx16x16[ctx].AsSpan();
|
|
||||||
case TxSize.Tx32x32:
|
|
||||||
return counts.Tx32x32[ctx].AsSpan();
|
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "Invalid maxTxSize.");
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
return Span<uint>.Empty;
|
return Span<uint>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,10 +86,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int ctx = xd.GetTxSizeContext();
|
int ctx = xd.GetTxSizeContext();
|
||||||
ReadOnlySpan<byte> txProbs = GetTxProbs(ref cm.Fc.Value, maxTxSize, ctx);
|
ReadOnlySpan<byte> txProbs = GetTxProbs(ref cm.Fc.Value, maxTxSize, ctx);
|
||||||
TxSize txSize = (TxSize)r.Read(txProbs[0]);
|
TxSize txSize = (TxSize)r.Read(txProbs[0]);
|
||||||
if (txSize != TxSize.Tx4x4 && maxTxSize >= TxSize.Tx16x16)
|
if (txSize != TxSize.Tx4X4 && maxTxSize >= TxSize.Tx16X16)
|
||||||
{
|
{
|
||||||
txSize += r.Read(txProbs[1]);
|
txSize += r.Read(txProbs[1]);
|
||||||
if (txSize != TxSize.Tx8x8 && maxTxSize >= TxSize.Tx32x32)
|
if (txSize != TxSize.Tx8X8 && maxTxSize >= TxSize.Tx32X32)
|
||||||
{
|
{
|
||||||
txSize += r.Read(txProbs[2]);
|
txSize += r.Read(txProbs[2]);
|
||||||
}
|
}
|
||||||
@@ -116,7 +108,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
TxMode txMode = cm.TxMode;
|
TxMode txMode = cm.TxMode;
|
||||||
BlockSize bsize = xd.Mi[0].Value.SbType;
|
BlockSize bsize = xd.Mi[0].Value.SbType;
|
||||||
TxSize maxTxSize = Luts.MaxTxSizeLookup[(int)bsize];
|
TxSize maxTxSize = Luts.MaxTxSizeLookup[(int)bsize];
|
||||||
if (allowSelect && txMode == TxMode.TxModeSelect && bsize >= BlockSize.Block8x8)
|
if (allowSelect && txMode == TxMode.TxModeSelect && bsize >= BlockSize.Block8X8)
|
||||||
{
|
{
|
||||||
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
||||||
}
|
}
|
||||||
@@ -124,34 +116,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis,
|
||||||
|
int yMis)
|
||||||
{
|
{
|
||||||
int x, y, segmentId = int.MaxValue;
|
int segmentId = int.MaxValue;
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
for (int y = 0; y < yMis; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
segmentId = Math.Min(segmentId, segmentIds[miOffset + y * cm.MiCols + x]);
|
segmentId = Math.Min(segmentId, segmentIds[miOffset + (y * cm.MiCols) + x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
|
private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
|
||||||
{
|
{
|
||||||
int x, y;
|
|
||||||
|
|
||||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
for (int y = 0; y < yMis; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
|
cm.CurrentFrameSegMap[miOffset + (y * cm.MiCols) + x] = (byte)segmentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,13 +154,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int xMis,
|
int xMis,
|
||||||
int yMis)
|
int yMis)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < yMis; y++)
|
||||||
|
|
||||||
for (y = 0; y < yMis; y++)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < xMis; x++)
|
for (int x = 0; x < xMis; x++)
|
||||||
{
|
{
|
||||||
currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
|
currentSegmentIds[miOffset + (y * cm.MiCols) + x] = (byte)(!lastSegmentIds.IsNull
|
||||||
|
? lastSegmentIds[miOffset + (y * cm.MiCols) + x]
|
||||||
|
: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,13 +178,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +198,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Segmentation seg = ref cm.Seg;
|
ref Segmentation seg = ref cm.Seg;
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
int predictedSegmentId, segmentId;
|
int predictedSegmentId, segmentId;
|
||||||
int miOffset = miRow * cm.MiCols + miCol;
|
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||||
|
|
||||||
if (!seg.Enabled)
|
if (!seg.Enabled)
|
||||||
{
|
{
|
||||||
@@ -224,7 +212,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return predictedSegmentId;
|
return predictedSegmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,20 +219,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
|
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
|
||||||
mi.SegIdPredicted = (sbyte)r.Read(predProb);
|
mi.SegIdPredicted = (sbyte)r.Read(predProb);
|
||||||
segmentId = mi.SegIdPredicted != 0 ? predictedSegmentId : ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = mi.SegIdPredicted != 0
|
||||||
|
? predictedSegmentId
|
||||||
|
: ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
|
||||||
|
|
||||||
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.Skip) != 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -260,12 +249,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return skip;
|
return skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
private static int ReadComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||||
{
|
{
|
||||||
int mag, d, fr, hp;
|
int mag, d, fr, hp;
|
||||||
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
||||||
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
|
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.MvClassTree, fc.Classes[mvcomp].AsSpan());
|
||||||
bool class0 = mvClass == MvClassType.MvClass0;
|
bool class0 = mvClass == MvClassType.Class0;
|
||||||
|
|
||||||
// Integer part
|
// Integer part
|
||||||
if (class0)
|
if (class0)
|
||||||
@@ -275,11 +264,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
for (i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
d |= r.Read(fc.Bits[mvcomp][i]) << i;
|
d |= r.Read(fc.Bits[mvcomp][i]) << i;
|
||||||
}
|
}
|
||||||
@@ -288,40 +276,39 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fractional part
|
// Fractional part
|
||||||
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
fr = r.ReadTree(Luts.MvFpTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
||||||
|
|
||||||
// High precision part (if hp is not used, the default value of the hp is 1)
|
// High precision part (if hp is not used, the default value of the hp is 1)
|
||||||
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
||||||
|
|
||||||
return sign ? -mag : mag;
|
return sign ? -mag : mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadMv(
|
private static void Read(
|
||||||
ref Reader r,
|
ref Reader r,
|
||||||
ref Mv mv,
|
ref Mv mv,
|
||||||
ref Mv refr,
|
ref Mv refr,
|
||||||
ref Vp9EntropyProbs fc,
|
ref Vp9EntropyProbs fc,
|
||||||
Ptr<Vp9BackwardUpdates> counts,
|
Ptr<Vp9BackwardUpdates> counts,
|
||||||
bool allowHP)
|
bool allowHp)
|
||||||
{
|
{
|
||||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
MvJointType jointType = (MvJointType)r.ReadTree(Luts.MvJointTree, fc.Joints.AsSpan());
|
||||||
bool useHP = allowHP && refr.UseMvHp();
|
bool useHp = allowHp && refr.UseHp();
|
||||||
Mv diff = new();
|
Mv diff = new();
|
||||||
|
|
||||||
if (Mv.MvJointVertical(jointType))
|
if (Mv.JointVertical(jointType))
|
||||||
{
|
{
|
||||||
diff.Row = (short)ReadMvComponent(ref r, ref fc, 0, useHP);
|
diff.Row = (short)ReadComponent(ref r, ref fc, 0, useHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mv.MvJointHorizontal(jointType))
|
if (Mv.JointHorizontal(jointType))
|
||||||
{
|
{
|
||||||
diff.Col = (short)ReadMvComponent(ref r, ref fc, 1, useHP);
|
diff.Col = (short)ReadComponent(ref r, ref fc, 1, useHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
diff.IncMv(counts);
|
diff.Inc(counts);
|
||||||
|
|
||||||
mv.Row = (short)(refr.Row + diff.Row);
|
mv.Row = (short)(refr.Row + diff.Row);
|
||||||
mv.Col = (short)(refr.Col + diff.Col);
|
mv.Col = (short)(refr.Col + diff.Col);
|
||||||
@@ -329,7 +316,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.ReferenceMode == ReferenceMode.ReferenceModeSelect)
|
if (cm.ReferenceMode == ReferenceMode.Select)
|
||||||
{
|
{
|
||||||
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
|
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
|
||||||
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
|
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
|
||||||
@@ -354,15 +341,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
|
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
|
||||||
|
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||||
{
|
{
|
||||||
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame);
|
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame);
|
||||||
refFrame[1] = Constants.None;
|
refFrame[1] = Constants.None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
|
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
|
||||||
if (mode == ReferenceMode.CompoundReference)
|
if (mode == ReferenceMode.Compound)
|
||||||
{
|
{
|
||||||
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
|
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
|
||||||
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
|
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
|
||||||
@@ -375,7 +362,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
refFrame[idx] = cm.CompFixedRef;
|
refFrame[idx] = cm.CompFixedRef;
|
||||||
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
|
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
|
||||||
}
|
}
|
||||||
else if (mode == ReferenceMode.SingleReference)
|
else if (mode == ReferenceMode.Single)
|
||||||
{
|
{
|
||||||
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
|
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
|
||||||
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
|
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
|
||||||
@@ -412,7 +399,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||||
{
|
{
|
||||||
int ctx = xd.GetPredContextSwitchableInterp();
|
int ctx = xd.GetPredContextSwitchableInterp();
|
||||||
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
byte type = (byte)r.ReadTree(Luts.SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
||||||
@@ -424,23 +411,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
|
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
|
||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (bsize)
|
switch (bsize)
|
||||||
{
|
{
|
||||||
case BlockSize.Block4x4:
|
case BlockSize.Block4X4:
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.Mode = mi.Bmi[3].Mode;
|
mi.Mode = mi.Bmi[3].Mode;
|
||||||
break;
|
break;
|
||||||
case BlockSize.Block4x8:
|
case BlockSize.Block4X8:
|
||||||
mi.Bmi[0].Mode = mi.Bmi[2].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[0].Mode = mi.Bmi[2].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
mi.Bmi[1].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[1].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
break;
|
break;
|
||||||
case BlockSize.Block8x4:
|
case BlockSize.Block8X4:
|
||||||
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
break;
|
break;
|
||||||
@@ -459,27 +446,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
mi.RefFrame[1] = Constants.None;
|
mi.RefFrame[1] = Constants.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsMvValid(ref Mv mv)
|
private static void CopyPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
||||||
{
|
|
||||||
return mv.Row > Constants.MvLow &&
|
|
||||||
mv.Row < Constants.MvUpp &&
|
|
||||||
mv.Col > Constants.MvLow &&
|
|
||||||
mv.Col < Constants.MvUpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CopyMvPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
|
||||||
{
|
{
|
||||||
dst[0] = src[0];
|
dst[0] = src[0];
|
||||||
dst[1] = src[1];
|
dst[1] = src[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ZeroMvPair(ref Array2<Mv> dst)
|
private static void ZeroPair(ref Array2<Mv> dst)
|
||||||
{
|
{
|
||||||
dst[0] = new Mv();
|
dst[0] = new Mv();
|
||||||
dst[1] = new Mv();
|
dst[1] = new Mv();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AssignMv(
|
private static bool Assign(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
@@ -487,45 +466,45 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Array2<Mv> refMv,
|
ref Array2<Mv> refMv,
|
||||||
ref Array2<Mv> nearNearestMv,
|
ref Array2<Mv> nearNearestMv,
|
||||||
int isCompound,
|
int isCompound,
|
||||||
bool allowHP,
|
bool allowHp,
|
||||||
ref Reader r)
|
ref Reader r)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case PredictionMode.NewMv:
|
case PredictionMode.NewMv:
|
||||||
{
|
{
|
||||||
for (i = 0; i < 1 + isCompound; ++i)
|
for (int i = 0; i < 1 + isCompound; ++i)
|
||||||
{
|
{
|
||||||
ReadMv(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHP);
|
Read(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHp);
|
||||||
ret = ret && IsMvValid(ref mv[i]);
|
ret = ret && mv[i].IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PredictionMode.NearMv:
|
case PredictionMode.NearMv:
|
||||||
case PredictionMode.NearestMv:
|
case PredictionMode.NearestMv:
|
||||||
{
|
{
|
||||||
CopyMvPair(ref mv, ref nearNearestMv);
|
CopyPair(ref mv, ref nearNearestMv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PredictionMode.ZeroMv:
|
case PredictionMode.ZeroMv:
|
||||||
{
|
{
|
||||||
ZeroMvPair(ref mv);
|
ZeroPair(ref mv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||||
{
|
{
|
||||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||||
{
|
{
|
||||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame) != Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctx = xd.GetIntraInterContext();
|
int ctx = xd.GetIntraInterContext();
|
||||||
@@ -538,33 +517,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return isInter;
|
return isInter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
private static void DecFindBestRefs(bool allowHp, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
// Make sure all the candidates are properly clamped etc
|
// Make sure all the candidates are properly clamped etc
|
||||||
for (i = 0; i < refmvCount; ++i)
|
for (int i = 0; i < refmvCount; ++i)
|
||||||
{
|
{
|
||||||
mvlist[i].LowerMvPrecision(allowHP);
|
mvlist[i].LowerPrecision(allowHp);
|
||||||
bestMv = mvlist[i];
|
bestMv = mvlist[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AddMvRefListEb(Mv mv, ref int refMvCount, Span<Mv> mvRefList, bool earlyBreak)
|
private static bool AddRefListEb(Mv mv, ref int refCount, Span<Mv> mvRefList, bool earlyBreak)
|
||||||
{
|
{
|
||||||
if (refMvCount != 0)
|
if (refCount != 0)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
|
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
|
||||||
{
|
{
|
||||||
mvRefList[refMvCount] = mv;
|
mvRefList[refCount] = mv;
|
||||||
refMvCount++;
|
refCount++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mvRefList[refMvCount++] = mv;
|
mvRefList[refCount++] = mv;
|
||||||
if (earlyBreak)
|
if (earlyBreak)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -574,19 +550,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs mv sign inversion if indicated by the reference frame combination.
|
private static bool IsDiffRefFrameAddEb(
|
||||||
private static Mv ScaleMv(ref ModeInfo mi, int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
|
|
||||||
{
|
|
||||||
Mv mv = mi.Mv[refr];
|
|
||||||
if (refSignBias[mi.RefFrame[refr]] != refSignBias[thisRefFrame])
|
|
||||||
{
|
|
||||||
mv.Row *= -1;
|
|
||||||
mv.Col *= -1;
|
|
||||||
}
|
|
||||||
return mv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsDiffRefFrameAddMvEb(
|
|
||||||
ref ModeInfo mbmi,
|
ref ModeInfo mbmi,
|
||||||
sbyte refFrame,
|
sbyte refFrame,
|
||||||
ref Array4<sbyte> refSignBias,
|
ref Array4<sbyte> refSignBias,
|
||||||
@@ -598,26 +562,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (mbmi.RefFrame[0] != refFrame)
|
if (mbmi.RefFrame[0] != refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 0, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(mbmi.ScaleMv(0, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||||
{
|
earlyBreak))
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame && Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
|
||||||
{
|
|
||||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 1, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame &&
|
||||||
|
Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
||||||
|
{
|
||||||
|
if (AddRefListEb(mbmi.ScaleMv(1, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||||
|
earlyBreak))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function searches the neighborhood of a given MB/SB
|
// This function searches the neighborhood of a given MB/SB
|
||||||
// to try and find candidate reference vectors.
|
// to try and find candidate reference vectors.
|
||||||
private static int DecFindMvRefs(
|
private static int DecFindRefs(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
@@ -632,14 +600,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
|
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
|
||||||
int i, refmvCount = 0;
|
int i, refmvCount = 0;
|
||||||
bool differentRefFound = false;
|
bool differentRefFound = false;
|
||||||
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs ? new Ptr<MvRef>(ref cm.PrevFrameMvs[miRow * cm.MiCols + miCol]) : Ptr<MvRef>.Null;
|
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs
|
||||||
|
? new Ptr<MvRef>(ref cm.PrevFrameMvs[(miRow * cm.MiCols) + miCol])
|
||||||
|
: Ptr<MvRef>.Null;
|
||||||
ref TileInfo tile = ref xd.Tile;
|
ref TileInfo tile = ref xd.Tile;
|
||||||
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
|
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
|
||||||
// searching after the first mv is found.
|
// searching after the first mv is found.
|
||||||
bool earlyBreak = mode != PredictionMode.NearMv;
|
bool earlyBreak = mode != PredictionMode.NearMv;
|
||||||
|
|
||||||
// Blank the reference vector list
|
// Blank the reference vector list
|
||||||
mvRefList[..Constants.MaxMvRefCandidates].Clear();
|
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (isSub8X8 != 0)
|
if (isSub8X8 != 0)
|
||||||
@@ -651,19 +621,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
differentRefFound = true;
|
differentRefFound = true;
|
||||||
|
|
||||||
if (candidateMi.RefFrame[0] == refFrame)
|
if (candidateMi.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount,
|
||||||
|
mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (candidateMi.RefFrame[1] == refFrame)
|
else if (candidateMi.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount,
|
||||||
|
mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -675,24 +647,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// Check the rest of the neighbors in much the same way
|
// Check the rest of the neighbors in much the same way
|
||||||
// as before except we don't need to keep track of sub blocks or
|
// as before except we don't need to keep track of sub blocks or
|
||||||
// mode counts.
|
// mode counts.
|
||||||
for (; i < MvrefNeighbours; ++i)
|
for (; i < RefNeighbours; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
differentRefFound = true;
|
differentRefFound = true;
|
||||||
|
|
||||||
if (candidate.RefFrame[0] == refFrame)
|
if (candidate.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (candidate.RefFrame[1] == refFrame)
|
else if (candidate.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -705,14 +677,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
|
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
|
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
|
||||||
{
|
{
|
||||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
if (AddRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -724,15 +696,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
// different reference frames.
|
// different reference frames.
|
||||||
if (differentRefFound)
|
if (differentRefFound)
|
||||||
{
|
{
|
||||||
for (i = 0; i < MvrefNeighbours; ++i)
|
for (i = 0; i < RefNeighbours; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
|
|
||||||
// If the candidate is Intra we don't want to consider its mv.
|
// If the candidate is Intra we don't want to consider its mv.
|
||||||
if (IsDiffRefFrameAddMvEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, earlyBreak))
|
if (IsDiffRefFrameAddEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList,
|
||||||
|
earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -751,7 +724,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
mv.Row *= -1;
|
mv.Row *= -1;
|
||||||
mv.Col *= -1;
|
mv.Col *= -1;
|
||||||
}
|
}
|
||||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
|
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -759,7 +733,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
|
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
|
||||||
prevFrameMvs.Value.RefFrame[1] != refFrame &&
|
prevFrameMvs.Value.RefFrame[1] != refFrame &&
|
||||||
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) != Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) !=
|
||||||
|
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
||||||
{
|
{
|
||||||
Mv mv = prevFrameMvs.Value.Mv[1];
|
Mv mv = prevFrameMvs.Value.Mv[1];
|
||||||
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
|
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
|
||||||
@@ -767,7 +742,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
mv.Row *= -1;
|
mv.Row *= -1;
|
||||||
mv.Col *= -1;
|
mv.Col *= -1;
|
||||||
}
|
}
|
||||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
|
||||||
|
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||||
{
|
{
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
@@ -784,17 +760,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
refmvCount = 1;
|
refmvCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
// Clamp vectors
|
// Clamp vectors
|
||||||
for (i = 0; i < refmvCount; ++i)
|
for (i = 0; i < refmvCount; ++i)
|
||||||
{
|
{
|
||||||
mvRefList[i].ClampMvRef(ref xd);
|
mvRefList[i].ClampRef(ref xd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return refmvCount;
|
return refmvCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendSub8x8MvsForIdx(
|
private static void AppendSub8X8ForIdx(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
Span<Position> mvRefSearch,
|
Span<Position> mvRefSearch,
|
||||||
@@ -803,46 +779,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
int refr,
|
int refr,
|
||||||
int miRow,
|
int miRow,
|
||||||
int miCol,
|
int miCol,
|
||||||
ref Mv bestSub8x8)
|
ref Mv bestSub8X8)
|
||||||
{
|
{
|
||||||
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
|
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
ref Array4<BModeInfo> bmi = ref mi.Bmi;
|
ref Array4<BModeInfo> bmi = ref mi.Bmi;
|
||||||
int n;
|
|
||||||
int refmvCount;
|
int refmvCount;
|
||||||
|
|
||||||
Debug.Assert(Constants.MaxMvRefCandidates == 2);
|
Debug.Assert(Constants.MaxMvRefCandidates == 2);
|
||||||
|
|
||||||
refmvCount = DecFindMvRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, block, 1);
|
refmvCount = DecFindRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol,
|
||||||
|
block, 1);
|
||||||
|
|
||||||
switch (block)
|
switch (block)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
bestSub8x8 = mvList[refmvCount - 1];
|
bestSub8X8 = mvList[refmvCount - 1];
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
{
|
{
|
||||||
bestSub8x8 = bmi[0].Mv[refr];
|
bestSub8X8 = bmi[0].Mv[refr];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bestSub8x8 = new Mv();
|
bestSub8X8 = new Mv();
|
||||||
for (n = 0; n < refmvCount; ++n)
|
for (int n = 0; n < refmvCount; ++n)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
|
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
|
||||||
{
|
{
|
||||||
bestSub8x8 = mvList[n];
|
bestSub8X8 = mvList[n];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
{
|
{
|
||||||
bestSub8x8 = bmi[2].Mv[refr];
|
bestSub8X8 = bmi[2].Mv[refr];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -851,16 +828,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
candidates[1] = bmi[0].Mv[refr];
|
candidates[1] = bmi[0].Mv[refr];
|
||||||
candidates[2] = mvList[0];
|
candidates[2] = mvList[0];
|
||||||
candidates[3] = mvList[1];
|
candidates[3] = mvList[1];
|
||||||
bestSub8x8 = new Mv();
|
bestSub8X8 = new Mv();
|
||||||
for (n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
for (int n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
||||||
{
|
{
|
||||||
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
|
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
|
||||||
{
|
{
|
||||||
bestSub8x8 = candidates[n];
|
bestSub8X8 = candidates[n];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "Invalid block index.");
|
Debug.Assert(false, "Invalid block index.");
|
||||||
@@ -868,19 +846,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, int miCol)
|
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow,
|
||||||
|
int miCol)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int contextCounter = 0;
|
int contextCounter = 0;
|
||||||
ref TileInfo tile = ref xd.Tile;
|
ref TileInfo tile = ref xd.Tile;
|
||||||
|
|
||||||
// Get mode count from nearest 2 blocks
|
// Get mode count from nearest 2 blocks
|
||||||
for (i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
ref Position mvRef = ref mvRefSearch[i];
|
ref Position mvRef = ref mvRefSearch[i];
|
||||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||||
{
|
{
|
||||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||||
// Keep counts for entropy encoding.
|
// Keep counts for entropy encoding.
|
||||||
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
|
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
|
||||||
}
|
}
|
||||||
@@ -898,7 +876,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Reader r)
|
ref Reader r)
|
||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
bool allowHP = cm.AllowHighPrecisionMv;
|
bool allowHp = cm.AllowHighPrecisionMv;
|
||||||
Array2<Mv> bestRefMvs = new();
|
Array2<Mv> bestRefMvs = new();
|
||||||
int refr, isCompound;
|
int refr, isCompound;
|
||||||
byte interModeCtx;
|
byte interModeCtx;
|
||||||
@@ -908,19 +886,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
isCompound = mi.HasSecondRef() ? 1 : 0;
|
isCompound = mi.HasSecondRef() ? 1 : 0;
|
||||||
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
|
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
|
||||||
|
|
||||||
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.Skip) != 0)
|
||||||
{
|
{
|
||||||
mi.Mode = PredictionMode.ZeroMv;
|
mi.Mode = PredictionMode.ZeroMv;
|
||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8X8)
|
||||||
{
|
{
|
||||||
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
xd.ErrorInfo.Value.InternalError(CodecErr.UnsupBitstream,
|
||||||
|
"Invalid usage of segement feature on small blocks");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bsize >= BlockSize.Block8x8)
|
if (bsize >= BlockSize.Block8X8)
|
||||||
{
|
{
|
||||||
mi.Mode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
mi.Mode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
||||||
}
|
}
|
||||||
@@ -942,42 +920,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
sbyte frame = mi.RefFrame[refr];
|
sbyte frame = mi.RefFrame[refr];
|
||||||
int refmvCount;
|
int refmvCount;
|
||||||
|
|
||||||
refmvCount = DecFindMvRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, -1, 0);
|
refmvCount = DecFindRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol,
|
||||||
|
-1, 0);
|
||||||
|
|
||||||
DecFindBestRefMvs(allowHP, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
DecFindBestRefs(allowHp, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.InterpFilter = (cm.InterpFilter == Constants.Switchable) ? ReadSwitchableInterpFilter(ref cm, ref xd, ref r) : cm.InterpFilter;
|
mi.InterpFilter = cm.InterpFilter == Constants.Switchable
|
||||||
|
? ReadSwitchableInterpFilter(ref cm, ref xd, ref r)
|
||||||
|
: cm.InterpFilter;
|
||||||
|
|
||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8X8)
|
||||||
{
|
{
|
||||||
int num4X4W = 1 << xd.BmodeBlocksWl;
|
int num4X4W = 1 << xd.BmodeBlocksWl;
|
||||||
int num4X4H = 1 << xd.BmodeBlocksHl;
|
int num4X4H = 1 << xd.BmodeBlocksHl;
|
||||||
int idx, idy;
|
int idx, idy;
|
||||||
PredictionMode bMode = 0;
|
PredictionMode bMode = 0;
|
||||||
Array2<Mv> bestSub8x8 = new();
|
Array2<Mv> bestSub8X8 = new();
|
||||||
const uint InvalidMv = 0x80008000;
|
const uint InvalidMv = 0x80008000;
|
||||||
// Initialize the 2nd element as even though it won't be used meaningfully
|
// Initialize the 2nd element as even though it won't be used meaningfully
|
||||||
// if isCompound is false.
|
// if isCompound is false.
|
||||||
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = InvalidMv;
|
Unsafe.As<Mv, uint>(ref bestSub8X8[1]) = InvalidMv;
|
||||||
for (idy = 0; idy < 2; idy += num4X4H)
|
for (idy = 0; idy < 2; idy += num4X4H)
|
||||||
{
|
{
|
||||||
for (idx = 0; idx < 2; idx += num4X4W)
|
for (idx = 0; idx < 2; idx += num4X4W)
|
||||||
{
|
{
|
||||||
int j = idy * 2 + idx;
|
int j = (idy * 2) + idx;
|
||||||
bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
||||||
|
|
||||||
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
|
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
|
||||||
{
|
{
|
||||||
for (refr = 0; refr < 1 + isCompound; ++refr)
|
for (refr = 0; refr < 1 + isCompound; ++refr)
|
||||||
{
|
{
|
||||||
AppendSub8x8MvsForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, ref bestSub8x8[refr]);
|
AppendSub8X8ForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol,
|
||||||
|
ref bestSub8X8[refr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AssignMv(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, isCompound, allowHP, ref r))
|
if (!Assign(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8X8,
|
||||||
|
isCompound, allowHp, ref r))
|
||||||
{
|
{
|
||||||
xd.Corrupted |= true;
|
xd.Corrupted |= true;
|
||||||
break;
|
break;
|
||||||
@@ -997,11 +980,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
mi.Mode = bMode;
|
mi.Mode = bMode;
|
||||||
|
|
||||||
CopyMvPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
CopyPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xd.Corrupted |= !AssignMv(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, isCompound, allowHP, ref r);
|
xd.Corrupted |= !Assign(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs,
|
||||||
|
isCompound, allowHp, ref r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1029,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(b == 1 || b == 3);
|
Debug.Assert(b == 1 || b == 3);
|
||||||
|
|
||||||
return curMi.Value.Bmi[b - 1].Mode;
|
return curMi.Value.Bmi[b - 1].Mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,7 +1045,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(b == 2 || b == 3);
|
Debug.Assert(b == 2 || b == 3);
|
||||||
|
|
||||||
return curMi.Value.Bmi[b - 2].Mode;
|
return curMi.Value.Bmi[b - 2].Mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1057,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
||||||
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
||||||
|
|
||||||
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1092,8 +1073,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
Ptr<ModeInfo> aboveMi = xd.AboveMi;
|
Ptr<ModeInfo> aboveMi = xd.AboveMi;
|
||||||
Ptr<ModeInfo> leftMi = xd.LeftMi;
|
Ptr<ModeInfo> leftMi = xd.LeftMi;
|
||||||
BlockSize bsize = mi.Value.SbType;
|
BlockSize bsize = mi.Value.SbType;
|
||||||
int i;
|
|
||||||
int miOffset = miRow * cm.MiCols + miCol;
|
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||||
|
|
||||||
mi.Value.SegmentId = (sbyte)ReadIntraSegmentId(ref cm, miOffset, xMis, yMis, ref r);
|
mi.Value.SegmentId = (sbyte)ReadIntraSegmentId(ref cm, miOffset, xMis, yMis, ref r);
|
||||||
mi.Value.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
|
mi.Value.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
|
||||||
@@ -1103,8 +1084,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
switch (bsize)
|
switch (bsize)
|
||||||
{
|
{
|
||||||
case BlockSize.Block4x4:
|
case BlockSize.Block4X4:
|
||||||
for (i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
mi.Value.Bmi[i].Mode =
|
mi.Value.Bmi[i].Mode =
|
||||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
|
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
|
||||||
@@ -1112,13 +1093,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
mi.Value.Mode = mi.Value.Bmi[3].Mode;
|
mi.Value.Mode = mi.Value.Bmi[3].Mode;
|
||||||
break;
|
break;
|
||||||
case BlockSize.Block4x8:
|
case BlockSize.Block4X8:
|
||||||
mi.Value.Bmi[0].Mode = mi.Value.Bmi[2].Mode =
|
mi.Value.Bmi[0].Mode = mi.Value.Bmi[2].Mode =
|
||||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
||||||
mi.Value.Bmi[1].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
mi.Value.Bmi[1].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
||||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 1));
|
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 1));
|
||||||
break;
|
break;
|
||||||
case BlockSize.Block8x4:
|
case BlockSize.Block8X4:
|
||||||
mi.Value.Bmi[0].Mode = mi.Value.Bmi[1].Mode =
|
mi.Value.Bmi[0].Mode = mi.Value.Bmi[1].Mode =
|
||||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
||||||
mi.Value.Bmi[2].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
mi.Value.Bmi[2].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
||||||
@@ -1149,8 +1130,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Reader r = ref twd.BitReader;
|
ref Reader r = ref twd.BitReader;
|
||||||
ref MacroBlockD xd = ref twd.Xd;
|
ref MacroBlockD xd = ref twd.Xd;
|
||||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||||
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice(miRow * cm.MiCols + miCol);
|
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice((miRow * cm.MiCols) + miCol);
|
||||||
int w, h;
|
|
||||||
|
|
||||||
if (cm.FrameIsIntraOnly())
|
if (cm.FrameIsIntraOnly())
|
||||||
{
|
{
|
||||||
@@ -1160,17 +1140,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
|
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
|
||||||
|
|
||||||
for (h = 0; h < yMis; ++h)
|
for (int h = 0; h < yMis; ++h)
|
||||||
{
|
{
|
||||||
for (w = 0; w < xMis; ++w)
|
for (int w = 0; w < xMis; ++w)
|
||||||
{
|
{
|
||||||
ref MvRef mv = ref frameMvs[w];
|
ref MvRef mv = ref frameMvs[w];
|
||||||
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
|
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
|
||||||
CopyMvPair(ref mv.Mv, ref mi.Mv);
|
CopyPair(ref mv.Mv, ref mi.Mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
frameMvs = frameMvs.Slice(cm.MiCols);
|
frameMvs = frameMvs.Slice(cm.MiCols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
@@ -12,15 +12,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
|
|
||||||
private readonly MemoryAllocator _allocator = new();
|
private readonly MemoryAllocator _allocator = new();
|
||||||
|
|
||||||
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
public ISurface CreateSurface(int width, int height)
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
|
|
||||||
{
|
{
|
||||||
Constants.EightTapSmooth,
|
return new Surface(width, height);
|
||||||
Constants.EightTap,
|
}
|
||||||
Constants.EightTapSharp,
|
|
||||||
Constants.Bilinear,
|
private static ReadOnlySpan<byte> LiteralToFilter =>
|
||||||
};
|
[
|
||||||
|
Constants.EightTapSmooth, Constants.EightTap, Constants.EightTapSharp, Constants.Bilinear
|
||||||
|
];
|
||||||
|
|
||||||
public unsafe bool Decode(
|
public unsafe bool Decode(
|
||||||
ref Vp9PictureInfo pictureInfo,
|
ref Vp9PictureInfo pictureInfo,
|
||||||
@@ -29,25 +29,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ReadOnlySpan<Vp9MvRef> mvsIn,
|
ReadOnlySpan<Vp9MvRef> mvsIn,
|
||||||
Span<Vp9MvRef> mvsOut)
|
Span<Vp9MvRef> mvsOut)
|
||||||
{
|
{
|
||||||
Vp9Common cm = new()
|
Vp9Common cm = new();
|
||||||
{
|
|
||||||
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
|
|
||||||
IntraOnly = pictureInfo.IntraOnly,
|
|
||||||
|
|
||||||
Width = output.Width,
|
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
||||||
Height = output.Height,
|
cm.IntraOnly = pictureInfo.IntraOnly;
|
||||||
SubsamplingX = 1,
|
|
||||||
SubsamplingY = 1,
|
|
||||||
|
|
||||||
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
|
cm.Width = output.Width;
|
||||||
|
cm.Height = output.Height;
|
||||||
|
cm.SubsamplingX = 1;
|
||||||
|
cm.SubsamplingY = 1;
|
||||||
|
|
||||||
RefFrameSignBias = pictureInfo.RefFrameSignBias,
|
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
|
||||||
|
|
||||||
BaseQindex = pictureInfo.BaseQIndex,
|
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
|
||||||
YDcDeltaQ = pictureInfo.YDcDeltaQ,
|
|
||||||
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
|
cm.BaseQindex = pictureInfo.BaseQIndex;
|
||||||
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
|
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
|
||||||
};
|
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
|
||||||
|
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
|
||||||
|
|
||||||
cm.Mb.Lossless = pictureInfo.Lossless;
|
cm.Mb.Lossless = pictureInfo.Lossless;
|
||||||
cm.Mb.Bd = 8;
|
cm.Mb.Bd = 8;
|
||||||
@@ -68,6 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
cm.CompFixedRef = pictureInfo.CompFixedRef;
|
cm.CompFixedRef = pictureInfo.CompFixedRef;
|
||||||
cm.CompVarRef = pictureInfo.CompVarRef;
|
cm.CompVarRef = pictureInfo.CompVarRef;
|
||||||
|
|
||||||
|
cm.BitDepth = BitDepth.Bits8;
|
||||||
|
|
||||||
cm.Log2TileCols = pictureInfo.Log2TileCols;
|
cm.Log2TileCols = pictureInfo.Log2TileCols;
|
||||||
cm.Log2TileRows = pictureInfo.Log2TileRows;
|
cm.Log2TileRows = pictureInfo.Log2TileRows;
|
||||||
|
|
||||||
@@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
|
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
|
||||||
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
|
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
|
||||||
|
|
||||||
|
cm.Lf.FilterLevel = pictureInfo.LoopFilterLevel;
|
||||||
|
cm.Lf.SharpnessLevel = pictureInfo.LoopFilterSharpnessLevel;
|
||||||
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
|
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
|
||||||
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
|
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
|
||||||
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
|
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
|
||||||
@@ -105,7 +108,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
cm.SetupSegmentationDequant();
|
cm.SetupSegmentationDequant();
|
||||||
cm.SetupScaleFactors();
|
cm.SetupScaleFactors();
|
||||||
|
|
||||||
SetMvs(ref cm, mvsIn);
|
cm.SetMvs(mvsIn);
|
||||||
|
|
||||||
|
if (cm.Lf.FilterLevel != 0 && cm.SkipLoopFilter == 0)
|
||||||
|
{
|
||||||
|
LoopFilter.LoopFilterFrameInit(ref cm, cm.Lf.FilterLevel);
|
||||||
|
}
|
||||||
|
|
||||||
fixed (byte* dataPtr = bitstream)
|
fixed (byte* dataPtr = bitstream)
|
||||||
{
|
{
|
||||||
@@ -114,10 +122,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
|
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
|
||||||
{
|
{
|
||||||
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
|
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
|
||||||
|
|
||||||
|
LoopFilter.LoopFilterFrameMt(
|
||||||
|
ref cm.Mb.CurBuf,
|
||||||
|
ref cm,
|
||||||
|
ref cm.Mb,
|
||||||
|
cm.Lf.FilterLevel,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
maxThreads);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
|
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
|
||||||
|
|
||||||
|
LoopFilter.LoopFilterFrame(
|
||||||
|
ref cm.Mb.CurBuf,
|
||||||
|
ref cm,
|
||||||
|
ref cm.Mb,
|
||||||
|
cm.Lf.FilterLevel,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InternalErrorException)
|
catch (InternalErrorException)
|
||||||
@@ -126,7 +151,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetMvs(ref cm, mvsOut);
|
cm.GetMvs(mvsOut);
|
||||||
|
|
||||||
cm.FreeTileWorkerData(_allocator);
|
cm.FreeTileWorkerData(_allocator);
|
||||||
cm.FreeContextBuffers(_allocator);
|
cm.FreeContextBuffers(_allocator);
|
||||||
@@ -134,48 +159,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (mvs.Length > cm.PrevFrameMvs.Length)
|
_allocator.Dispose();
|
||||||
{
|
|
||||||
throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < mvs.Length; i++)
|
|
||||||
{
|
|
||||||
ref var mv = ref cm.PrevFrameMvs[i];
|
|
||||||
|
|
||||||
mv.Mv[0].Row = mvs[i].Mvs[0].Row;
|
|
||||||
mv.Mv[0].Col = mvs[i].Mvs[0].Col;
|
|
||||||
mv.Mv[1].Row = mvs[i].Mvs[1].Row;
|
|
||||||
mv.Mv[1].Col = mvs[i].Mvs[1].Col;
|
|
||||||
|
|
||||||
mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
|
|
||||||
mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
|
|
||||||
{
|
|
||||||
if (mvs.Length > cm.CurFrameMvs.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < mvs.Length; i++)
|
|
||||||
{
|
|
||||||
ref var mv = ref cm.CurFrameMvs[i];
|
|
||||||
|
|
||||||
mvs[i].Mvs[0].Row = mv.Mv[0].Row;
|
|
||||||
mvs[i].Mvs[0].Col = mv.Mv[0].Col;
|
|
||||||
mvs[i].Mvs[1].Row = mv.Mv[1].Row;
|
|
||||||
mvs[i].Mvs[1].Col = mv.Mv[1].Col;
|
|
||||||
|
|
||||||
mvs[i].RefFrames[0] = mv.RefFrame[0];
|
|
||||||
mvs[i].RefFrames[1] = mv.RefFrame[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => _allocator.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
@@ -19,24 +19,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
const int MaxNeighbors = 2;
|
const int MaxNeighbors = 2;
|
||||||
|
|
||||||
return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
|
return (1 + tokenCache[neighbors[(MaxNeighbors * c) + 0]] +
|
||||||
}
|
tokenCache[neighbors[(MaxNeighbors * c) + 1]]) >> 1;
|
||||||
|
|
||||||
private static int ReadCoeff(
|
|
||||||
ref Reader r,
|
|
||||||
ReadOnlySpan<byte> probs,
|
|
||||||
int n,
|
|
||||||
ref ulong value,
|
|
||||||
ref int count,
|
|
||||||
ref uint range)
|
|
||||||
{
|
|
||||||
int i, val = 0;
|
|
||||||
for (i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
val = (val << 1) | r.ReadBool(probs[i], ref value, ref count, ref range);
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int DecodeCoefs(
|
private static int DecodeCoefs(
|
||||||
@@ -58,13 +42,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
||||||
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
||||||
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
|
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
|
||||||
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
int dqShift = txSize == TxSize.Tx32X32 ? 1 : 0;
|
||||||
int v;
|
int v;
|
||||||
short dqv = dq[0];
|
short dqv = dq[0];
|
||||||
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
ReadOnlySpan<byte> cat6Prob = xd.Bd == 12
|
||||||
? Luts.Vp9Cat6ProbHigh12
|
? Luts.Cat6ProbHigh12
|
||||||
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
|
: xd.Bd == 10
|
||||||
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
? Luts.Cat6ProbHigh12.Slice(2)
|
||||||
|
: Luts.Cat6Prob;
|
||||||
|
int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14;
|
||||||
// Keep value, range, and count as locals. The compiler produces better
|
// Keep value, range, and count as locals. The compiler produces better
|
||||||
// results with the locals than using r directly.
|
// results with the locals than using r directly.
|
||||||
ulong value = r.Value;
|
ulong value = r.Value;
|
||||||
@@ -75,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
int val = -1;
|
int val = -1;
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate[1..];
|
bandTranslate = bandTranslate.Slice(1);
|
||||||
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
@@ -107,18 +93,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
|
|
||||||
return c; // Zero tokens at the end (no eob token)
|
return c; // Zero tokens at the end (no eob token)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate[1..];
|
bandTranslate = bandTranslate.Slice(1);
|
||||||
prob = ref coefProbs[band][ctx];
|
prob = ref coefProbs[band][ctx];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[prob[Constants.PivotNode] - 1];
|
ReadOnlySpan<byte> p = Luts.Pareto8Full[prob[Constants.PivotNode] - 1];
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
|
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
|
||||||
@@ -133,20 +119,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
{
|
{
|
||||||
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range);
|
val = Constants.Cat6MinVal + r.ReadCoeff(cat6Prob, cat6Bits, ref value,
|
||||||
|
ref count, ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range);
|
val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value,
|
||||||
|
ref count, ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
|
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range);
|
val = Constants.Cat4MinVal + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range);
|
val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -154,13 +144,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
tokenCache[scan[c]] = 4;
|
tokenCache[scan[c]] = 4;
|
||||||
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
|
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
|
||||||
{
|
{
|
||||||
val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range);
|
val = Constants.Cat2MinVal + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range);
|
val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count,
|
||||||
|
ref range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Val may use 18-bits
|
// Val may use 18-bits
|
||||||
v = (int)(((long)val * dqv) >> dqShift);
|
v = (int)(((long)val * dqv) >> dqShift);
|
||||||
}
|
}
|
||||||
@@ -188,7 +181,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
tokenCache[scan[c]] = 1;
|
tokenCache[scan[c]] = 1;
|
||||||
v = dqv >> dqShift;
|
v = dqv >> dqShift;
|
||||||
}
|
}
|
||||||
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v, xd.Bd);
|
|
||||||
|
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v,
|
||||||
|
xd.Bd);
|
||||||
++c;
|
++c;
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
dqv = dq[1];
|
dqv = dq[1];
|
||||||
@@ -197,11 +192,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks)
|
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y,
|
||||||
|
uint txSizeInBlocks)
|
||||||
{
|
{
|
||||||
if (xd.MaxBlocksWide != 0)
|
if (xd.MaxBlocksWide != 0)
|
||||||
{
|
{
|
||||||
@@ -210,6 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
|
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xd.MaxBlocksHigh != 0)
|
if (xd.MaxBlocksHigh != 0)
|
||||||
{
|
{
|
||||||
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
|
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
|
||||||
@@ -238,15 +234,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
||||||
int eob;
|
int eob;
|
||||||
Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
|
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
|
||||||
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
|
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
|
||||||
int ctx;
|
int ctx;
|
||||||
int ctxShiftA = 0;
|
int ctxShiftA = 0;
|
||||||
int ctxShiftL = 0;
|
int ctxShiftL = 0;
|
||||||
|
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4:
|
case TxSize.Tx4X4:
|
||||||
ctx = a[0] != 0 ? 1 : 0;
|
ctx = a[0] != 0 ? 1 : 0;
|
||||||
ctx += l[0] != 0 ? 1 : 0;
|
ctx += l[0] != 0 ? 1 : 0;
|
||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
@@ -261,8 +257,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
ref r);
|
ref r);
|
||||||
a[0] = l[0] = (sbyte)(eob > 0 ? 1 : 0);
|
a[0] = l[0] = (sbyte)(eob > 0 ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx8x8:
|
case TxSize.Tx8X8:
|
||||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx8x8);
|
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx8X8);
|
||||||
ctx = MemoryMarshal.Cast<sbyte, ushort>(a)[0] != 0 ? 1 : 0;
|
ctx = MemoryMarshal.Cast<sbyte, ushort>(a)[0] != 0 ? 1 : 0;
|
||||||
ctx += MemoryMarshal.Cast<sbyte, ushort>(l)[0] != 0 ? 1 : 0;
|
ctx += MemoryMarshal.Cast<sbyte, ushort>(l)[0] != 0 ? 1 : 0;
|
||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
@@ -278,8 +274,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
MemoryMarshal.Cast<sbyte, ushort>(a)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftA);
|
MemoryMarshal.Cast<sbyte, ushort>(a)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftA);
|
||||||
MemoryMarshal.Cast<sbyte, ushort>(l)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftL);
|
MemoryMarshal.Cast<sbyte, ushort>(l)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftL);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx16x16:
|
case TxSize.Tx16X16:
|
||||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx16x16);
|
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx16X16);
|
||||||
ctx = MemoryMarshal.Cast<sbyte, uint>(a)[0] != 0 ? 1 : 0;
|
ctx = MemoryMarshal.Cast<sbyte, uint>(a)[0] != 0 ? 1 : 0;
|
||||||
ctx += MemoryMarshal.Cast<sbyte, uint>(l)[0] != 0 ? 1 : 0;
|
ctx += MemoryMarshal.Cast<sbyte, uint>(l)[0] != 0 ? 1 : 0;
|
||||||
eob = DecodeCoefs(
|
eob = DecodeCoefs(
|
||||||
@@ -295,8 +291,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
MemoryMarshal.Cast<sbyte, uint>(a)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftA);
|
MemoryMarshal.Cast<sbyte, uint>(a)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftA);
|
||||||
MemoryMarshal.Cast<sbyte, uint>(l)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftL);
|
MemoryMarshal.Cast<sbyte, uint>(l)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftL);
|
||||||
break;
|
break;
|
||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32X32:
|
||||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx32x32);
|
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx32X32);
|
||||||
// NOTE: Casting to ulong here is safe because the default memory
|
// NOTE: Casting to ulong here is safe because the default memory
|
||||||
// alignment is at least 8 bytes and the Tx32x32 is aligned on 8 byte
|
// alignment is at least 8 bytes and the Tx32x32 is aligned on 8 byte
|
||||||
// boundaries.
|
// boundaries.
|
||||||
@@ -324,4 +320,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
|||||||
return eob;
|
return eob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -75,17 +75,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
Vector128<int> zero = Vector128<int>.Zero;
|
Vector128<int> zero = Vector128<int>.Zero;
|
||||||
Vector128<int> const64 = Vector128.Create(64);
|
Vector128<int> const64 = Vector128.Create(64);
|
||||||
|
|
||||||
ulong x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
fixed (Array8<short>* xFilter = xFilters)
|
fixed (Array8<short>* xFilter = xFilters)
|
||||||
{
|
{
|
||||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + (uint)(x0Q4 & SubpelMask) * 8);
|
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + ((uint)(x0Q4 & SubpelMask) * 8));
|
||||||
|
|
||||||
for (y = 0; y < (uint)h; ++y)
|
for (ulong y = 0; y < (uint)h; ++y)
|
||||||
{
|
{
|
||||||
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
|
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
|
||||||
for (x = 0; x < (uint)w; x += 4)
|
for (ulong x = 0; x < (uint)w; x += 4)
|
||||||
{
|
{
|
||||||
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
|
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
|
||||||
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
|
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
|
||||||
@@ -94,8 +93,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||||
|
|
||||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
Sse.StoreScalar((float*)&dst[x],
|
||||||
|
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
@@ -117,22 +118,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
@@ -140,6 +139,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
@@ -156,25 +156,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
dst[x] = (byte)BitUtils.RoundPowerOfTwo(
|
||||||
|
dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
@@ -203,18 +204,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
srcStride * 6,
|
srcStride * 6,
|
||||||
srcStride * 7);
|
srcStride * 7);
|
||||||
|
|
||||||
ulong x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
fixed (Array8<short>* yFilter = yFilters)
|
fixed (Array8<short>* yFilter = yFilters)
|
||||||
{
|
{
|
||||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + (uint)(y0Q4 & SubpelMask) * 8);
|
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + ((uint)(y0Q4 & SubpelMask) * 8));
|
||||||
|
|
||||||
ulong srcBaseY = (uint)y0Q4 >> SubpelBits;
|
ulong srcBaseY = (uint)y0Q4 >> SubpelBits;
|
||||||
for (y = 0; y < (uint)h; ++y)
|
for (ulong y = 0; y < (uint)h; ++y)
|
||||||
{
|
{
|
||||||
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
|
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
|
||||||
for (x = 0; x < (uint)w; x += 4)
|
for (ulong x = 0; x < (uint)w; x += 4)
|
||||||
{
|
{
|
||||||
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
|
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
|
||||||
|
|
||||||
@@ -240,8 +240,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
|
|
||||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||||
|
|
||||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
Sse.StoreScalar((float*)&dst[x],
|
||||||
|
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,22 +264,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
@@ -285,6 +285,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
@@ -301,18 +302,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
@@ -321,6 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
@@ -420,15 +421,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
|
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
|
||||||
// big enough.
|
// big enough.
|
||||||
byte* temp = stackalloc byte[64 * 135];
|
byte* temp = stackalloc byte[64 * 135];
|
||||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||||
|
|
||||||
Debug.Assert(w <= 64);
|
Debug.Assert(w <= 64);
|
||||||
Debug.Assert(h <= 64);
|
Debug.Assert(h <= 64);
|
||||||
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
|
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
|
||||||
Debug.Assert(xStepQ4 <= 64);
|
Debug.Assert(xStepQ4 <= 64);
|
||||||
|
|
||||||
ConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight);
|
ConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4, w,
|
||||||
ConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
intermediateHeight);
|
||||||
|
ConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void Convolve8Avg(
|
public static unsafe void Convolve8Avg(
|
||||||
@@ -489,11 +491,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int w,
|
int w,
|
||||||
int h)
|
int h)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < h; ++y)
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||||
}
|
}
|
||||||
@@ -611,18 +611,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
@@ -630,6 +629,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
@@ -647,25 +647,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= (SubpelTaps / 2) - 1;
|
||||||
src -= SubpelTaps / 2 - 1;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
int xQ4 = x0Q4;
|
int xQ4 = x0Q4;
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcX[k] * xFilter[k];
|
sum += srcX[k] * xFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||||
|
dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
||||||
xQ4 += xStepQ4;
|
xQ4 += xStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
src += srcStride;
|
src += srcStride;
|
||||||
dst += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
@@ -683,18 +684,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
@@ -702,6 +702,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
@@ -719,26 +720,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
|
||||||
|
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int yQ4 = y0Q4;
|
int yQ4 = y0Q4;
|
||||||
for (y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||||
int k, sum = 0;
|
int sum = 0;
|
||||||
for (k = 0; k < SubpelTaps; ++k)
|
for (int k = 0; k < SubpelTaps; ++k)
|
||||||
{
|
{
|
||||||
sum += srcY[k * srcStride] * yFilter[k];
|
sum += srcY[k * srcStride] * yFilter[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
|
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||||
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd),
|
||||||
|
1);
|
||||||
yQ4 += yStepQ4;
|
yQ4 += yStepQ4;
|
||||||
}
|
}
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++dst;
|
++dst;
|
||||||
}
|
}
|
||||||
@@ -771,15 +773,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
|
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
|
||||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||||
ushort* temp = stackalloc ushort[64 * 135];
|
ushort* temp = stackalloc ushort[64 * 135];
|
||||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||||
|
|
||||||
Debug.Assert(w <= 64);
|
Debug.Assert(w <= 64);
|
||||||
Debug.Assert(h <= 64);
|
Debug.Assert(h <= 64);
|
||||||
Debug.Assert(yStepQ4 <= 32);
|
Debug.Assert(yStepQ4 <= 32);
|
||||||
Debug.Assert(xStepQ4 <= 32);
|
Debug.Assert(xStepQ4 <= 32);
|
||||||
|
|
||||||
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
|
HighbdConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4,
|
||||||
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
|
w, intermediateHeight, bd);
|
||||||
|
HighbdConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h,
|
||||||
|
bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdConvolve8Horiz(
|
public static unsafe void HighbdConvolve8Horiz(
|
||||||
@@ -928,11 +932,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
int x, y;
|
for (int y = 0; y < h; ++y)
|
||||||
|
|
||||||
for (y = 0; y < h; ++y)
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||||
}
|
}
|
||||||
@@ -942,4 +944,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
|||||||
public const int SubpelShifts = 1 << SubpelBits;
|
public const int SubpelShifts = 1 << SubpelBits;
|
||||||
public const int SubpelTaps = 8;
|
public const int SubpelTaps = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user