Compare commits

..

3 Commits

Author SHA1 Message Date
Evan Husted
d64bf7d93c small simplification 2025-01-29 18:15:15 -06:00
Evan Husted
52338db1e8 docs on the new ApplicationLibrary method 2025-01-29 18:09:10 -06:00
Evan Husted
aa01f70f46 UI: Pretty Atmosphère mod names 2025-01-29 17:56:43 -06:00
317 changed files with 5538 additions and 16627 deletions

View File

@@ -29,7 +29,7 @@ env:
jobs: jobs:
tag: tag:
name: Create tag name: Create tag
runs-on: ubuntu-24.04 runs-on: ubuntu-20.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-24.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -18,7 +18,7 @@ env:
jobs: jobs:
tag: tag:
name: Create tag name: Create tag
runs-on: ubuntu-24.04 runs-on: ubuntu-20.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-24.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -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/PEuzjrFXUA"> <a href="https://discord.gg/dHPrkBkkyA">
<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/Ryubing/Ryujinx/refs/heads/master/docs/shell.png"> <img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png">
</p> </p>
## Usage ## Usage

View File

@@ -332,7 +332,6 @@
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
@@ -427,7 +426,6 @@
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
@@ -530,7 +528,6 @@
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
@@ -958,7 +955,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,ingame,2025-02-03 22:12:30 010027400CDC6000,"Divinity: Original Sin 2 - Definitive Edition",services;crash;online-broken;regression,menus,2023-08-13 17:20:03
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
@@ -969,7 +966,6 @@
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
@@ -1159,7 +1155,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",,playable,2025-02-16 21:27:30 01000EA014150000,"FINAL FANTASY",crash,nothing,2024-09-05 20:55: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
@@ -1250,7 +1246,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;slow;gpu,ingame,2025-02-12 16:03:00 0100E1F013674000,"FUSER™",nvdec;UE4,playable,2022-10-17 20:58:32
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
@@ -1658,7 +1654,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
010085500130a000,"LEGO® CITY Undercover",nvdec,playable,2024-09-30 08:44:27 01003A30012C0000,"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
@@ -1917,7 +1913,6 @@
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
@@ -2033,7 +2028,6 @@
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
@@ -2064,7 +2058,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
,"nx-hbmenu",Needs Update;homebrew,boots,2024-04-06 22:05:32 0000000000000000,"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
@@ -2472,7 +2466,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
,"RSDKv5u",homebrew,ingame,2024-04-01 16:25:34 0000000000000000,"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
@@ -2481,7 +2475,6 @@
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
@@ -2490,7 +2483,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;deadlock,ingame,2025-02-02 16:57:53 01008D100D43E000,"Saints Row IV®: Re-Elected™",ldn-untested;LAN,playable,2023-12-04 18:33:37
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
@@ -2539,7 +2532,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,ingame,2025-02-03 22:13:30 0100B3C014BDA000,"SEGA Genesis™ Nintendo Switch Online",crash;regression,nothing,2022-04-11 07:27:21
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
@@ -2675,10 +2668,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
,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20 0000000000000000,"Sonic 1 (2013)",crash;homebrew,ingame,2024-04-06 18:31:20
,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30 0000000000000000,"Sonic 2 (2013)",crash;homebrew,ingame,2024-04-01 16:25:30
,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32 0000000000000000,"Sonic A.I.R",homebrew,ingame,2024-04-01 16:25:32
,"Sonic CD",crash;homebrew,ingame,2024-04-01 16:25:31 0000000000000000,"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
@@ -2695,7 +2688,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
,"SpaceCadetPinball",homebrew,ingame,2024-04-18 19:30:04 0000000000000000,"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
@@ -2839,9 +2832,8 @@
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
,"Super Mario World",homebrew,boots,2024-06-13 01:40:31 0000000000000000,"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 + Bowsers Fury",ldn-works,playable,2024-07-31 10:45:37 010028600EBDA000,"Super Mario™ 3D World + Bowsers 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
@@ -2972,7 +2964,6 @@
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
@@ -2990,8 +2981,6 @@
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
@@ -3170,7 +3159,6 @@
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
@@ -3220,7 +3208,6 @@
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
@@ -3385,7 +3372,6 @@
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 title_id game_name labels status last_updated
332 0100E680149DC000 Arcaea playable 2023-03-16 19:31:21
333 01003C2010C78000 Archaica: The Path Of Light crash nothing 2020-10-16 13:22:26
334 01004DA012976000 Area 86 playable 2020-12-16 16:45:52
01008d8006a6a000 Arena of Valor crash boots 2025-02-03 22:19:34
335 0100691013C46000 ARIA CHRONICLE playable 2022-11-16 13:50:55
336 0100D4A00B284000 ARK: Survival Evolved gpu;nvdec;online-broken;UE4;ldn-untested ingame 2024-04-16 00:53:56
337 0100C56012C96000 Arkanoid vs. Space Invaders services ingame 2021-01-21 12:50:30
426 0100E48013A34000 Balan Wonderworld Demo gpu;services;UE4;demo ingame 2023-02-16 20:05:07
427 0100CD801CE5E000 Balatro ingame 2024-04-21 02:01:53
428 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
429 0100BC400FB64000 Balthazar's Dream playable 2022-09-13 00:13:22
430 01008D30128E0000 Bamerang playable 2022-10-26 00:29:39
431 010013C010C5C000 Banner of the Maid playable 2021-06-14 15:23:37
528 01005950022EC000 Blade Strangers nvdec playable 2022-07-17 19:02:43
529 0100DF0011A6A000 Bladed Fury playable 2022-10-26 11:36:26
530 0100CFA00CC74000 Blades of Time deadlock;online boots 2022-07-17 19:19:58
01003d700dd8a000 Blades boots 2025-02-03 22:22:00
531 01006CC01182C000 Blair Witch nvdec;UE4 playable 2022-10-01 14:06:16
532 010039501405E000 Blanc gpu;slow ingame 2023-02-22 14:00:13
533 0100698009C6E000 Blasphemous nvdec playable 2021-03-01 12:15:31
955 010012800EBAE000 Disney TSUM TSUM FESTIVAL crash menus 2020-07-14 14:05:28
956 01009740120FE000 DISTRAINT 2 playable 2020-09-03 16:08:12
957 010075B004DD2000 DISTRAINT: Deluxe Edition playable 2020-06-15 23:42:24
958 010027400CDC6000 Divinity: Original Sin 2 - Definitive Edition services;crash;online-broken;regression ingame menus 2025-02-03 22:12:30 2023-08-13 17:20:03
959 01001770115C8000 Dodo Peak nvdec;UE4 playable 2022-10-04 16:13:05
960 010077B0100DA000 Dogurai playable 2020-10-04 02:40:16
961 010048100D51A000 Dokapon Up! Mugen no Roulette gpu;Needs Update menus 2022-12-08 19:39:10
966 0100751007ADA000 Don't Starve: Nintendo Switch Edition nvdec playable 2022-02-05 20:43:34
967 010088B010DD2000 Dongo Adventure playable 2022-10-04 16:22:26
968 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
969 0100F2C00F060000 Doodle Derby boots 2020-12-04 22:51:48
970 0100416004C00000 DOOM gpu;slow;nvdec;online-broken ingame 2024-09-23 15:40:07
971 010018900DD00000 DOOM (1993) nvdec;online-broken menus 2022-09-06 13:32:19
1155 010095600AA36000 Fill-a-Pix: Phil's Epic Adventure playable 2020-12-22 13:48:22
1156 0100C3A00BB76000 Fimbul nvdec playable 2022-07-26 13:31:47
1157 0100C8200E942000 Fin and the Ancient Mystery nvdec playable 2020-12-17 16:40:39
1158 01000EA014150000 FINAL FANTASY crash playable nothing 2025-02-16 21:27:30 2024-09-05 20:55:30
1159 01006B7014156000 FINAL FANTASY II crash nothing 2024-04-13 19:18:04
1160 01006F000B056000 FINAL FANTASY IX audout;nvdec playable 2021-06-05 11:35:00
1161 0100AA201415C000 FINAL FANTASY V playable 2023-04-26 01:11:55
1246 0100A6B00D4EC000 Furwind playable 2021-02-19 19:44:08
1247 0100ECE00C0C4000 Fury Unleashed crash;services ingame 2020-10-18 11:52:40
1248 010070000ED9E000 Fury Unleashed Demo playable 2020-10-08 20:09:21
1249 0100E1F013674000 FUSER™ nvdec;UE4;slow;gpu nvdec;UE4 ingame playable 2025-02-12 16:03:00 2022-10-17 20:58:32
1250 0100A7A015E4C000 Fushigi no Gensokyo Lotus Labyrinth Needs Update;audio;gpu;nvdec ingame 2021-01-20 15:30:02
1251 01003C300B274000 Futari de! Nyanko Daisensou playable 2024-01-05 22:26:52
1252 010055801134E000 FUZE Player online-broken;vulkan-backend-bug ingame 2022-10-18 12:23:53
1654 0100A73006E74000 Legendary Eleven playable 2021-06-08 12:09:03
1655 0100A7700B46C000 Legendary Fishing online playable 2021-04-14 15:08:46
1656 0100739018020000 LEGO® 2K Drive gpu;ldn-works ingame 2024-04-09 02:05:12
1657 010085500130a000 01003A30012C0000 LEGO® CITY Undercover nvdec playable 2024-09-30 08:44:27
1658 010070D009FEC000 LEGO® DC Super-Villains playable 2021-05-27 18:10:37
1659 010052A00B5D2000 LEGO® Harry Potter™ Collection crash ingame 2024-01-31 10:28:07
1660 010073C01AF34000 LEGO® Horizon Adventures™ vulkan-backend-bug;opengl-backend-bug;UE4 ingame 2025-01-07 04:24:56
1913 010073E008E6E000 Mugsters playable 2021-01-28 17:57:17
1914 0100A8400471A000 MUJO playable 2020-05-08 16:31:04
1915 0100211005E94000 Mulaka playable 2021-01-28 18:07:20
01008e2013fb4000 Multi Quiz ldn-untested ingame 2025-02-03 22:26:00
1916 010038B00B9AE000 Mummy Pinball playable 2022-08-05 16:08:11
1917 01008E200C5C2000 Muse Dash playable 2020-06-06 14:41:29
1918 010035901046C000 Mushroom Quest playable 2020-05-17 13:07:08
2028 010003C00B868000 Ninjin: Clash of Carrots online-broken playable 2024-07-10 05:12:26
2029 0100746010E4C000 NinNinDays playable 2022-11-20 15:17:29
2030 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
2031 0100D870045B6000 Nintendo Entertainment System™ - Nintendo Switch Online online playable 2022-07-01 15:45:06
2032 0100C4B0034B2000 Nintendo Labo Toy-Con 01 Variety Kit gpu ingame 2022-08-07 12:56:07
2033 01001E9003502000 Nintendo Labo Toy-Con 03 Vehicle Kit services;crash menus 2022-08-03 17:20:11
2058 010002700C34C000 Numbala playable 2020-05-11 12:01:07
2059 010020500C8C8000 Number Place 10000 gpu menus 2021-11-24 09:14:23
2060 010003701002C000 Nurse Love Syndrome playable 2022-10-13 10:05:22
2061 0000000000000000 nx-hbmenu Needs Update;homebrew boots 2024-04-06 22:05:32
2062 nxquake2 services;crash;homebrew nothing 2022-08-04 23:14:04
2063 010049F00EC30000 Nyan Cat: Lost in Space online playable 2021-06-12 13:22:03
2064 01002E6014FC4000 O---O playable 2022-10-29 12:12:14
2466 0100AFE00DDAC000 Royal Roads playable 2020-11-17 12:54:38
2467 0100E2C00B414000 RPG Maker MV nvdec playable 2021-01-05 20:12:01
2468 01005CD015986000 rRootage Reloaded playable 2022-08-05 23:20:18
2469 0000000000000000 RSDKv5u homebrew ingame 2024-04-01 16:25:34
2470 010009B00D33C000 Rugby Challenge 4 slow;online-broken;UE4 playable 2022-10-06 12:45:53
2471 01006EC00F2CC000 RUINER UE4 playable 2022-10-03 14:11:33
2472 010074F00DE4A000 Run the Fan playable 2021-02-27 13:36:28
2475 010081C0191D8000 Rune Factory 3 Special playable 2023-10-15 08:32:49
2476 010051D00E3A4000 Rune Factory 4 Special 32-bit;crash;nvdec ingame 2023-05-06 08:49:17
2477 010014D01216E000 Rune Factory 5 (JP) gpu ingame 2021-06-01 12:00:36
010071E0145F8000 Rustler playable 2025-02-10 20:17:12
2478 0100E21013908000 RWBY: Grimm Eclipse - Definitive Edition online-broken playable 2022-11-03 10:44:01
2479 010012C0060F0000 RXN -Raijin- nvdec playable 2021-01-10 16:05:43
2480 0100B8B012ECA000 S.N.I.P.E.R. - Hunter Scope playable 2021-04-19 15:58:09
2483 0100A5200C2E0000 Safety First! playable 2021-01-06 09:05:23
2484 0100A51013530000 SaGa Frontier Remastered nvdec playable 2022-11-03 13:54:56
2485 010003A00D0B4000 SaGa SCARLET GRACE: AMBITIONS™ playable 2022-10-06 13:20:31
2486 01008D100D43E000 Saints Row IV®: Re-Elected™ ldn-untested;LAN;deadlock ldn-untested;LAN ingame playable 2025-02-02 16:57:53 2023-12-04 18:33:37
2487 0100DE600BEEE000 SAINTS ROW®: THE THIRD™ - THE FULL PACKAGE slow;LAN playable 2023-08-24 02:40:58
2488 01007F000EB36000 Sakai and... nvdec playable 2022-12-15 13:53:19
2489 0100B1400E8FE000 Sakuna: Of Rice and Ruin playable 2023-07-24 13:47:13
2532 0100C3E00B700000 SEGA AGES Space Harrier playable 2021-01-11 12:57:40
2533 010054400D2E6000 SEGA AGES Virtua Racing online-broken playable 2023-01-29 17:08:39
2534 01001E700AC60000 SEGA AGES Wonder Boy: Monster Land online playable 2021-05-05 16:28:25
2535 0100B3C014BDA000 SEGA Genesis™ – Nintendo Switch Online crash;regression ingame nothing 2025-02-03 22:13:30 2022-04-11 07:27:21
2536 0100F7300B24E000 SEGA Mega Drive Classics online playable 2021-01-05 11:08:00
2537 01009840046BC000 Semispheres playable 2021-01-06 23:08:31
2538 0100D1800D902000 SENRAN KAGURA Peach Ball playable 2021-06-03 15:12:10
2668 01004F401BEBE000 Song of Nunu: A League of Legends Story ingame 2024-07-12 18:53:44
2669 0100E5400BF94000 Songbird Symphony playable 2021-02-27 02:44:04
2670 010031D00A604000 Songbringer playable 2020-06-22 10:42:02
2671 0000000000000000 Sonic 1 (2013) crash;homebrew ingame 2024-04-06 18:31:20
2672 0000000000000000 Sonic 2 (2013) crash;homebrew ingame 2024-04-01 16:25:30
2673 0000000000000000 Sonic A.I.R homebrew ingame 2024-04-01 16:25:32
2674 0000000000000000 Sonic CD crash;homebrew ingame 2024-04-01 16:25:31
2675 010040E0116B8000 Sonic Colors: Ultimate playable 2022-11-12 21:24:26
2676 01001270012B6000 SONIC FORCES™ playable 2024-07-28 13:11:21
2677 01004AD014BF0000 Sonic Frontiers gpu;deadlock;amd-vendor-bug;intel-vendor-bug ingame 2024-09-05 09:18:53
2688 0100707011722000 Space Elite Force playable 2020-11-27 15:21:05
2689 010047B010260000 Space Pioneer playable 2022-10-20 12:24:37
2690 010010A009830000 Space Ribbon playable 2022-08-15 17:17:10
2691 0000000000000000 SpaceCadetPinball homebrew ingame 2024-04-18 19:30:04
2692 0100D9B0041CE000 Spacecats with Lasers playable 2022-08-15 17:22:44
2693 010034800FB60000 Spaceland playable 2020-11-01 14:31:56
2694 010028D0045CE000 Sparkle 2 playable 2020-10-19 11:51:39
2832 01009B90006DC000 Super Mario Maker™ 2 online-broken;ldn-broken playable 2024-08-25 11:05:19
2833 0100000000010000 Super Mario Odyssey™ nvdec;intel-vendor-bug;mac-bug playable 2024-08-25 01:32:34
2834 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
2835 0100BC0018138000 Super Mario RPG™ gpu;audio;nvdec ingame 2024-06-19 17:43:42
2836 0000000000000000 Super Mario World homebrew boots 2024-06-13 01:40:31
2837 010049900F546000 Super Mario™ 3D All-Stars services-horizon;slow;vulkan;amd-vendor-bug ingame 2024-05-07 02:38:16
2838 010028600EBDA000 Super Mario™ 3D World + Bowser’s Fury ldn-works playable 2024-07-31 10:45:37
2839 01004F8006A78000 Super Meat Boy services playable 2020-04-02 23:10:07
2964 0100C38004DCC000 The Flame In The Flood: Complete Edition gpu;nvdec;UE4 ingame 2022-08-22 16:23:49
2965 010007700D4AC000 The Forbidden Arts playable 2021-01-26 16:26:24
2966 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
2967 01006350148DA000 The Gardener and the Wild Vines gpu ingame 2024-04-29 16:32:10
2968 0100B13007A6A000 The Gardens Between playable 2021-01-29 16:16:53
2969 010036E00FB20000 The Great Ace Attorney Chronicles playable 2023-06-22 21:26:29
2981 010015D003EE4000 The Jackbox Party Pack 2 online-working playable 2022-08-22 18:23:40
2982 0100CC80013D6000 The Jackbox Party Pack 3 slow;online-working playable 2022-08-22 18:41:06
2983 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
2984 010052C00B184000 The Journey Down: Chapter One nvdec playable 2021-02-24 13:32:41
2985 01006BC00B188000 The Journey Down: Chapter Three nvdec playable 2021-02-24 13:45:27
2986 01009AB00B186000 The Journey Down: Chapter Two nvdec playable 2021-02-24 13:32:13
3159 010055E00CA68000 Trine 4: The Nightmare Prince gpu nothing 2025-01-07 05:47:46
3160 0100D9000A930000 Trine Enchanted Edition ldn-untested;nvdec playable 2021-06-03 11:28:15
3161 01002D7010A54000 Trinity Trigger crash ingame 2023-03-03 03:09:09
010020700a5e0000 TRIVIAL PURSUIT Live! ldn-untested ingame 2025-02-03 22:35:00
3162 0100868013FFC000 TRIVIAL PURSUIT Live! 2 boots 2022-12-19 00:04:33
3163 0100F78002040000 Troll and I™ gpu;nvdec ingame 2021-06-04 16:58:50
3164 0100145011008000 Trollhunters: Defenders of Arcadia gpu;nvdec ingame 2020-11-30 13:27:09
3208 0100AB2010B4C000 Unlock The King playable 2020-09-01 13:58:27
3209 0100A3E011CB0000 Unlock the King 2 playable 2021-06-15 20:43:55
3210 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
3211 0100E5D00CC0C000 Unravel Two nvdec playable 2024-05-23 15:45:05
3212 010001300CC4A000 Unruly Heroes playable 2021-01-07 18:09:31
3213 0100B410138C0000 Unspottable playable 2022-10-25 19:28:49
3372 0100F47016F26000 Yomawari 3 playable 2022-05-10 08:26:51
3373 010012F00B6F2000 Yomawari: The Long Night Collection playable 2022-09-03 14:36:59
3374 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
3375 0100BE50042F6000 Yono and the Celestial Elephants playable 2021-01-28 18:23:58
3376 0100F110029C8000 Yooka-Laylee playable 2021-01-28 14:21:45
3377 010022F00DA66000 Yooka-Laylee and the Impossible Lair playable 2021-03-05 17:32:21

View File

@@ -1,6 +1,7 @@
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

View File

@@ -1,3 +1,4 @@
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

View File

@@ -7,7 +7,6 @@ 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;
@@ -22,7 +21,6 @@ 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;

View File

@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,5 +1,6 @@
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;

View File

@@ -1,6 +1,7 @@
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;

View File

@@ -1,4 +1,5 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
namespace ARMeilleure.State namespace ARMeilleure.State
{ {

View File

@@ -6,6 +6,7 @@ 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;

View File

@@ -2,8 +2,6 @@ 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;
@@ -20,8 +18,9 @@ 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 = 256 * 1024 * 1024; private const int CacheSize = 2047 * 1024 * 1024;
private static ReservedRegion _jitRegion;
private static JitCacheInvalidation _jitCacheInvalidator; private static JitCacheInvalidation _jitCacheInvalidator;
private static CacheMemoryAllocator _cacheAllocator; private static CacheMemoryAllocator _cacheAllocator;
@@ -31,9 +30,6 @@ 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 = new();
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);
@@ -52,9 +48,7 @@ namespace ARMeilleure.Translation.Cache
return; return;
} }
ReservedRegion firstRegion = new(allocator, CacheSize); _jitRegion = new ReservedRegion(allocator, CacheSize);
_jitRegions.Add(firstRegion);
_activeRegionIndex = 0;
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS()) if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
{ {
@@ -65,9 +59,7 @@ namespace ARMeilleure.Translation.Cache
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
JitUnwindWindows.InstallFunctionTableHandler( JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
);
} }
_initialized = true; _initialized = true;
@@ -83,8 +75,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 = targetRegion.Pointer + funcOffset; nint funcPtr = _jitRegion.Pointer + funcOffset;
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
@@ -98,9 +90,9 @@ namespace ARMeilleure.Translation.Cache
} }
else else
{ {
ReprotectAsWritable(targetRegion, funcOffset, code.Length); ReprotectAsWritable(funcOffset, code.Length);
Marshal.Copy(code, 0, funcPtr, code.Length); Marshal.Copy(code, 0, funcPtr, code.Length);
ReprotectAsExecutable(targetRegion, funcOffset, code.Length); ReprotectAsExecutable(funcOffset, code.Length);
if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
@@ -124,83 +116,52 @@ namespace ARMeilleure.Translation.Cache
{ {
Debug.Assert(_initialized); Debug.Assert(_initialized);
foreach (ReservedRegion region in _jitRegions) int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
{ {
if (pointer.ToInt64() < region.Pointer.ToInt64() || _cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64()) _cacheEntries.RemoveAt(entryIndex);
{
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(ReservedRegion region, int offset, int size) private static void ReprotectAsWritable(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;
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
} }
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size) private static void ReprotectAsExecutable(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;
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.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);
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++) int allocOffset = _cacheAllocator.Allocate(codeSize);
{
int allocOffset = _cacheAllocator.Allocate(codeSize);
if (allocOffset >= 0) if (allocOffset < 0)
{ {
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize); throw new OutOfMemoryException("JIT Cache exhausted.");
_activeRegionIndex = i;
return allocOffset;
}
} }
int exhaustedRegion = _activeRegionIndex; _jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
var newRegion = new ReservedRegion(_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);
@@ -224,21 +185,18 @@ namespace ARMeilleure.Translation.Cache
{ {
lock (_lock) lock (_lock)
{ {
foreach (ReservedRegion _ in _jitRegions) int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default));
if (index < 0)
{ {
int index = _cacheEntries.BinarySearch(new CacheEntry(offset, 0, default)); index = ~index - 1;
}
if (index < 0) if (index >= 0)
{ {
index = ~index - 1; entry = _cacheEntries[index];
} entryIndex = index;
return true;
if (index >= 0)
{
entry = _cacheEntries[index];
entryIndex = index;
return true;
}
} }
} }

View File

@@ -1,4 +1,5 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ARMeilleure.Translation.Cache namespace ARMeilleure.Translation.Cache

View File

@@ -1,3 +1,5 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
class DelegateInfo class DelegateInfo

View File

@@ -1,3 +1,5 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate void DispatcherFunction(nint nativeContext, ulong startAddress); delegate void DispatcherFunction(nint nativeContext, ulong startAddress);

View File

@@ -1,3 +1,5 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate ulong GuestFunction(nint nativeContextPtr); delegate ulong GuestFunction(nint nativeContextPtr);

View File

@@ -144,15 +144,17 @@ namespace ARMeilleure.Translation.PTC
public List<ulong> GetBlacklistedFunctions() public List<ulong> GetBlacklistedFunctions()
{ {
List<ulong> funcs = []; List<ulong> funcs = new List<ulong>();
foreach ((ulong ptr, FuncProfile funcProfile) in ProfiledFuncs) foreach (var profiledFunc in ProfiledFuncs)
{ {
if (!funcProfile.Blacklist) if (profiledFunc.Value.Blacklist)
continue; {
if (!funcs.Contains(profiledFunc.Key))
if (!funcs.Contains(ptr)) {
funcs.Add(ptr); funcs.Add(profiledFunc.Key);
}
}
} }
return funcs; return funcs;

View File

@@ -1,4 +1,5 @@
using ARMeilleure.Common; using ARMeilleure.Common;
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {

View File

@@ -5,6 +5,7 @@ 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;

View File

@@ -4,6 +4,7 @@ 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;

View File

@@ -4,6 +4,7 @@ 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;

View File

@@ -1,4 +1,5 @@
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;

View File

@@ -1,3 +1,4 @@
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;

View File

@@ -4,6 +4,7 @@ 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;

View File

@@ -1,6 +1,7 @@
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

View File

@@ -1,3 +1,4 @@
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;

View File

@@ -6,16 +6,4 @@ namespace Ryujinx.Common.Configuration
Unbounded, Unbounded,
Custom Custom
} }
public static class VSyncModeExtensions
{
public static VSyncMode Next(this VSyncMode vsync, bool customEnabled = false) =>
vsync switch
{
VSyncMode.Switch => customEnabled ? VSyncMode.Custom : VSyncMode.Unbounded,
VSyncMode.Unbounded => VSyncMode.Switch,
VSyncMode.Custom => VSyncMode.Unbounded,
_ => VSyncMode.Switch
};
}
} }

View File

@@ -1,4 +1,5 @@
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;

View File

@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,118 +0,0 @@
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
}
}

View File

@@ -1,58 +0,0 @@
using Gommon;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.Common.Helper
{
public class RefEvent<T>
{
public delegate void Handler(ref T arg);
private readonly Lock _subLock = new();
private readonly List<Handler> _subscriptions = [];
public bool HasSubscribers
{
get
{
lock (_subLock)
return _subscriptions.Count != 0;
}
}
public IReadOnlyList<Handler> Subscriptions
{
get
{
lock (_subLock)
return _subscriptions;
}
}
public void Add(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Add(subscriber);
}
public void Remove(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Remove(subscriber);
}
public void Clear()
{
lock (_subLock)
_subscriptions.Clear();
}
public void Call(ref T arg)
{
foreach (Handler subscription in Subscriptions)
subscription(ref arg);
}
}
}

View File

@@ -11,17 +11,13 @@ namespace Ryujinx.Common.Helper
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 IsIntelMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.X64;
public static bool IsArmMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.Arm64;
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64; public static bool IsX64Windows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmWindows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsIntelMac => IsMacOS && IsX64; public static bool IsX64Linux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmMac => IsMacOS && IsArm; public static bool IsArmLinux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsX64Windows => IsWindows && IsX64;
public static bool IsArmWindows => IsWindows && IsArm;
public static bool IsX64Linux => IsLinux && IsX64;
public static bool IsArmLinux => IsLinux && IsArmMac;
} }
} }

View File

@@ -3,6 +3,7 @@ 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
{ {
@@ -29,11 +30,10 @@ namespace Ryujinx.Common
public static readonly string[] GreatMetalTitles = public static readonly string[] GreatMetalTitles =
[ [
"01009b500007c000", // ARMS "010076f0049a2000", // Bayonetta
"0100a5c00d162000", // Cuphead "0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune "010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover "01003a30012c0000", // LEGO City Undercover
"010048701995e000", // Luigi's Manion 2 HD
"010028600EBDA000", // Mario 3D World "010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe "0100152000022000", // Mario Kart 8 Deluxe
"010075a016a3a000", // Persona 4 Arena Ultimax "010075a016a3a000", // Persona 4 Arena Ultimax
@@ -47,15 +47,11 @@ 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 Royal "01005CA01580E000", // Persona 5 Royale
"0100b880154fc000", // Persona 5 The Royal (Japan)
"010015100b514000", // Super Mario Bros. Wonder
"0100000000010000", // Super Mario Odyssey "0100000000010000", // Super Mario Odyssey
// Further testing is appreciated, I did not test the entire game: //Isaac claims it has a issue in level 2, but I am not able to replicate it on my M3. More testing would be appreciated:
//"010076f0049a2000", // Bayonetta "010015100b514000", // Super Mario Bros. Wonder
//"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
//"0100f4300bf2c000", // New Pokemon Snap
]; ];
public static string GetDiscordGameAsset(string titleId) public static string GetDiscordGameAsset(string titleId)
@@ -163,16 +159,15 @@ 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,7 +213,6 @@ 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
@@ -229,7 +223,6 @@ 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

View File

@@ -1,5 +1,4 @@
using Gommon; using Gommon;
using Ryujinx.Common.Helper;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
@@ -56,7 +55,7 @@ namespace Ryujinx.Common.Utilities
{ {
_color = HsbToRgb((_color.GetHue() + Speed) / 360); _color = HsbToRgb((_color.GetHue() + Speed) / 360);
_updatedHandler.Call(ref _color); _updatedHandler.Call(_color.ToArgb());
} }
} }
@@ -68,13 +67,13 @@ namespace Ryujinx.Common.Utilities
_color = Color.Blue; _color = Color.Blue;
} }
public static event RefEvent<Color>.Handler Updated public static event Action<int> Updated
{ {
add => _updatedHandler.Add(value); add => _updatedHandler.Add(value);
remove => _updatedHandler.Remove(value); remove => _updatedHandler.Remove(value);
} }
private static readonly RefEvent<Color> _updatedHandler = new(); private static readonly Event<int> _updatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1) private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{ {

View File

@@ -1,5 +1,6 @@
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;

View File

@@ -5,6 +5,7 @@ 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;

View File

@@ -1,4 +1,5 @@
using Ryujinx.Memory; using Ryujinx.Memory;
using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;

View File

@@ -2,6 +2,7 @@ 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
{ {

View File

@@ -5,6 +5,7 @@ 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;

View File

@@ -8,6 +8,7 @@ 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

View File

@@ -3,6 +3,7 @@ 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

View File

@@ -2,6 +2,7 @@ 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;

View File

@@ -1,4 +1,5 @@
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

View File

@@ -1,3 +1,5 @@
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

View File

@@ -1,3 +1,5 @@
using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm64 namespace Ryujinx.Cpu.LightningJit.Arm64
{ {
static class SysUtils static class SysUtils

View File

@@ -3,6 +3,7 @@ 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;

View File

@@ -1,6 +1,4 @@
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;
@@ -17,8 +15,9 @@ 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 = 256 * 1024 * 1024; private const int CacheSize = 2047 * 1024 * 1024;
private static ReservedRegion _jitRegion;
private static JitCacheInvalidation _jitCacheInvalidator; private static JitCacheInvalidation _jitCacheInvalidator;
private static CacheMemoryAllocator _cacheAllocator; private static CacheMemoryAllocator _cacheAllocator;
@@ -27,8 +26,6 @@ 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 = new();
private static int _activeRegionIndex = 0;
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
@@ -48,9 +45,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
return; return;
} }
ReservedRegion firstRegion = new(allocator, CacheSize); _jitRegion = new ReservedRegion(allocator, CacheSize);
_jitRegions.Add(firstRegion);
_activeRegionIndex = 0;
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS()) if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
{ {
@@ -70,8 +65,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 = targetRegion.Pointer + funcOffset; nint funcPtr = _jitRegion.Pointer + funcOffset;
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
@@ -85,11 +80,18 @@ namespace Ryujinx.Cpu.LightningJit.Cache
} }
else else
{ {
ReprotectAsWritable(targetRegion, funcOffset, code.Length); ReprotectAsWritable(funcOffset, code.Length);
Marshal.Copy(code.ToArray(), 0, funcPtr, code.Length); code.CopyTo(new Span<byte>((void*)funcPtr, code.Length));
ReprotectAsExecutable(targetRegion, funcOffset, code.Length); ReprotectAsExecutable(funcOffset, code.Length);
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length); if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{
FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (nuint)code.Length);
}
else
{
_jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length);
}
} }
Add(funcOffset, code.Length); Add(funcOffset, code.Length);
@@ -104,80 +106,50 @@ namespace Ryujinx.Cpu.LightningJit.Cache
{ {
Debug.Assert(_initialized); Debug.Assert(_initialized);
foreach (ReservedRegion region in _jitRegions) int funcOffset = (int)(pointer.ToInt64() - _jitRegion.Pointer.ToInt64());
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
{ {
if (pointer.ToInt64() < region.Pointer.ToInt64() || _cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
pointer.ToInt64() >= (region.Pointer + CacheSize).ToInt64()) _cacheEntries.RemoveAt(entryIndex);
{
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(ReservedRegion region, int offset, int size) private static void ReprotectAsWritable(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;
region.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
} }
private static void ReprotectAsExecutable(ReservedRegion region, int offset, int size) private static void ReprotectAsExecutable(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;
region.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart)); _jitRegion.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);
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++) int allocOffset = _cacheAllocator.Allocate(codeSize);
{
int allocOffset = _cacheAllocator.Allocate(codeSize);
if (allocOffset >= 0) if (allocOffset < 0)
{ {
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize); throw new OutOfMemoryException("JIT Cache exhausted.");
_activeRegionIndex = i;
return allocOffset;
}
} }
int exhaustedRegion = _activeRegionIndex; _jitRegion.ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
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)

View File

@@ -1,4 +1,5 @@
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

View File

@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -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 = 256 * 1024 * 1024; private const int LocalCacheSize = 128 * 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.

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Cpu.LightningJit namespace Ryujinx.Cpu.LightningJit

View File

@@ -1,3 +1,5 @@
using System;
namespace Ryujinx.Cpu.LightningJit namespace Ryujinx.Cpu.LightningJit
{ {
class TranslatedFunction class TranslatedFunction

View File

@@ -5,6 +5,7 @@ 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;

View File

@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.Signal namespace Ryujinx.Cpu.Signal

View File

@@ -1,4 +1,6 @@
using Ryujinx.Common.Logging;
using System; using System;
using System.Threading;
namespace Ryujinx.Graphics.Device namespace Ryujinx.Graphics.Device
{ {

View File

@@ -1,5 +1,6 @@
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

View File

@@ -1,3 +1,4 @@
using Ryujinx.Graphics.Device;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;

View File

@@ -4,6 +4,7 @@ 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

View File

@@ -1,4 +1,5 @@
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;

View File

@@ -7,6 +7,7 @@ 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;

View File

@@ -1,5 +1,6 @@
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;

View File

@@ -2,6 +2,7 @@ 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

View File

@@ -1,3 +1,4 @@
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;

View File

@@ -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, _ => waitEvent.Set()); SyncpointWaiterHandle info = _syncpoints[id].RegisterCallback(threshold, (x) => 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) if (!signaled && info != null)
{ {
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...");

View File

@@ -1,6 +1,7 @@
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

View File

@@ -1,3 +1,5 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct AVCodec struct AVCodec

View File

@@ -1,3 +1,5 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct AVCodec501 struct AVCodec501

View File

@@ -1,4 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {

View File

@@ -1,4 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {

View File

@@ -1,3 +1,5 @@
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

View File

@@ -1,3 +1,5 @@
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

View File

@@ -1,5 +1,6 @@
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
{ {

View File

@@ -1,75 +1,56 @@
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal enum CodecErr internal enum CodecErr
{ {
/// <summary> /*!\brief Operation completed without error */
/// Operation completed without error CodecOk,
/// </summary>
Ok,
/// <summary> /*!\brief Unspecified error */
/// Unspecified error CodecError,
/// </summary>
Error,
/// <summary> /*!\brief Memory operation failed */
/// Memory operation failed CodecMemError,
/// </summary>
MemError,
/// <summary> /*!\brief ABI version mismatch */
/// ABI version mismatch CodecAbiMismatch,
/// </summary>
AbiMismatch,
/// <summary> /*!\brief Algorithm does not have required capability */
/// Algorithm does not have required capability CodecIncapable,
/// </summary>
Incapable,
/// <summary> /*!\brief The given bitstream is not supported.
/// The given bitstream is not supported. *
/// </summary> * The bitstream was unable to be parsed at the highest level. The decoder
/// <remarks> * is unable to proceed. This error \ref SHOULD be treated as fatal to the
/// The bitstream was unable to be parsed at the highest level.<br/> * stream. */
/// The decoder is unable to proceed.<br/> CodecUnsupBitstream,
/// This error SHOULD be treated as fatal to the stream.
/// </remarks>
UnsupBitstream,
/// <summary> /*!\brief Encoded bitstream uses an unsupported feature
/// Encoded bitstream uses an unsupported feature *
/// </summary> * The decoder does not implement a feature required by the encoder. This
/// <remarks> * return code should only be used for features that prevent future
/// The decoder does not implement a feature required by the encoder.<br/> * pictures from being properly decoded. This error \ref MAY be treated as
/// This return code should only be used for features that prevent future * fatal to the stream or \ref MAY be treated as fatal to the current GOP.
/// pictures from being properly decoded.<br/> */
/// <br/> CodecUnsupFeature,
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
/// </remarks>
UnsupFeature,
/// <summary> /*!\brief The coded data for this stream is corrupt or incomplete
/// The coded data for this stream is corrupt or incomplete. *
/// </summary> * There was a problem decoding the current frame. This return code
/// <remarks> * should only be used for failures that prevent future pictures from
/// There was a problem decoding the current frame.<br/> * being properly decoded. This error \ref MAY be treated as fatal to the
/// This return code should only be used * stream or \ref MAY be treated as fatal to the current GOP. If decoding
/// for failures that prevent future pictures from being properly decoded.<br/> * is continued for the current GOP, artifacts may be present.
/// <br/> */
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.<br/> CodecCorruptFrame,
/// If decoding is continued for the current GOP, artifacts may be present.
/// </remarks>
CorruptFrame,
/// <summary> /*!\brief An application-supplied parameter is not valid.
/// An application-supplied parameter is not valid. *
/// </summary> */
InvalidParam, CodecInvalidParam,
/// <summary> /*!\brief An iterator reached the end of list.
/// An iterator reached the end of list. *
/// </summary> */
ListEnd CodecListEnd,
} }
} }

View File

@@ -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)]

View File

@@ -51,7 +51,6 @@ 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;
@@ -59,11 +58,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
} }
} }
ArrayPtr<T> allocation = new ArrayPtr<T>(ptr, length); return new ArrayPtr<T>(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

View File

@@ -1,10 +1,8 @@
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 InterpExtend = 4; public const int Vp9InterpExtend = 4;
public const int MaxMbPlane = 3; public const int MaxMbPlane = 3;
@@ -27,7 +25,6 @@ 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;
@@ -35,26 +32,12 @@ 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 */
@@ -65,9 +48,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;
@@ -82,19 +65,5 @@ 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;
} }
} }

View File

@@ -1,47 +0,0 @@
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

View File

@@ -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 RefNeighbours = 8; private const int MvrefNeighbours = 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.IntraModeTree, p); return (PredictionMode)r.ReadTree(Luts.Vp9IntraModeTree, 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.InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan()); int mode = r.ReadTree(Luts.Vp9InterModeTree, 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,18 +52,22 @@ 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.SegmentTree, segTreeProbs.AsSpan()); return r.ReadTree(Luts.Vp9SegmentTree, 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: return fc.Tx8x8Prob[ctx].AsSpan(); case TxSize.Tx8x8:
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan(); return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan(); case TxSize.Tx16x16:
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;
} }
} }
@@ -72,11 +76,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan(); case TxSize.Tx8x8:
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan(); return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan(); case TxSize.Tx16x16:
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;
} }
} }
@@ -116,32 +124,34 @@ 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, private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
int yMis)
{ {
int segmentId = int.MaxValue; int x, y, segmentId = int.MaxValue;
for (int y = 0; y < yMis; y++) for (y = 0; y < yMis; y++)
{ {
for (int x = 0; x < xMis; x++) for (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 (int y = 0; y < yMis; y++) for (y = 0; y < yMis; y++)
{ {
for (int x = 0; x < xMis; x++) for (x = 0; x < xMis; x++)
{ {
cm.CurrentFrameSegMap[miOffset + (y * cm.MiCols) + x] = (byte)segmentId; cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
} }
} }
} }
@@ -154,13 +164,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int xMis, int xMis,
int yMis) int yMis)
{ {
for (int y = 0; y < yMis; y++) int x, y;
for (y = 0; y < yMis; y++)
{ {
for (int x = 0; x < xMis; x++) for (x = 0; x < xMis; x++)
{ {
currentSegmentIds[miOffset + (y * cm.MiCols) + x] = (byte)(!lastSegmentIds.IsNull currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
? lastSegmentIds[miOffset + (y * cm.MiCols) + x]
: 0);
} }
} }
} }
@@ -178,11 +188,13 @@ 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;
} }
@@ -198,7 +210,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)
{ {
@@ -212,6 +224,7 @@ 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;
} }
@@ -219,22 +232,20 @@ 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 segmentId = mi.SegIdPredicted != 0 ? predictedSegmentId : ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
? 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.Skip) != 0) if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlSkip) != 0)
{ {
return 1; return 1;
} }
@@ -249,12 +260,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return skip; return skip;
} }
private static int ReadComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp) private static int ReadMvComponent(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.MvClassTree, fc.Classes[mvcomp].AsSpan()); MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
bool class0 = mvClass == MvClassType.Class0; bool class0 = mvClass == MvClassType.MvClass0;
// Integer part // Integer part
if (class0) if (class0)
@@ -264,10 +275,11 @@ 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 (int i = 0; i < n; ++i) for (i = 0; i < n; ++i)
{ {
d |= r.Read(fc.Bits[mvcomp][i]) << i; d |= r.Read(fc.Bits[mvcomp][i]) << i;
} }
@@ -276,39 +288,40 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
// Fractional part // Fractional part
fr = r.ReadTree(Luts.MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan()); fr = r.ReadTree(Luts.Vp9MvFPTree, 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 Read( private static void ReadMv(
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.MvJointTree, fc.Joints.AsSpan()); MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
bool useHp = allowHp && refr.UseHp(); bool useHP = allowHP && refr.UseMvHp();
Mv diff = new(); Mv diff = new();
if (Mv.JointVertical(jointType)) if (Mv.MvJointVertical(jointType))
{ {
diff.Row = (short)ReadComponent(ref r, ref fc, 0, useHp); diff.Row = (short)ReadMvComponent(ref r, ref fc, 0, useHP);
} }
if (Mv.JointHorizontal(jointType)) if (Mv.MvJointHorizontal(jointType))
{ {
diff.Col = (short)ReadComponent(ref r, ref fc, 1, useHp); diff.Col = (short)ReadMvComponent(ref r, ref fc, 1, useHP);
} }
diff.Inc(counts); diff.IncMv(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);
@@ -316,7 +329,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.Select) if (cm.ReferenceMode == ReferenceMode.ReferenceModeSelect)
{ {
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]);
@@ -341,15 +354,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.RefFrame) != 0) if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
{ {
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame); refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame);
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.Compound) if (mode == ReferenceMode.CompoundReference)
{ {
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);
@@ -362,7 +375,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.Single) else if (mode == ReferenceMode.SingleReference)
{ {
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]);
@@ -399,7 +412,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.SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan()); byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, 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];
@@ -411,12 +424,12 @@ 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 (int i = 0; i < 4; ++i) for (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);
} }
@@ -446,19 +459,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mi.RefFrame[1] = Constants.None; mi.RefFrame[1] = Constants.None;
} }
private static void CopyPair(ref Array2<Mv> dst, ref Array2<Mv> src) private static bool IsMvValid(ref Mv mv)
{
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 ZeroPair(ref Array2<Mv> dst) private static void ZeroMvPair(ref Array2<Mv> dst)
{ {
dst[0] = new Mv(); dst[0] = new Mv();
dst[1] = new Mv(); dst[1] = new Mv();
} }
private static bool Assign( private static bool AssignMv(
ref Vp9Common cm, ref Vp9Common cm,
ref MacroBlockD xd, ref MacroBlockD xd,
PredictionMode mode, PredictionMode mode,
@@ -466,45 +487,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 (int i = 0; i < 1 + isCompound; ++i) for (i = 0; i < 1 + isCompound; ++i)
{ {
Read(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHp); ReadMv(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHP);
ret = ret && mv[i].IsValid(); ret = ret && IsMvValid(ref mv[i]);
} }
break; break;
} }
case PredictionMode.NearMv: case PredictionMode.NearMv:
case PredictionMode.NearestMv: case PredictionMode.NearestMv:
{ {
CopyPair(ref mv, ref nearNearestMv); CopyMvPair(ref mv, ref nearNearestMv);
break; break;
} }
case PredictionMode.ZeroMv: case PredictionMode.ZeroMv:
{ {
ZeroPair(ref mv); ZeroMvPair(ref mv);
break; break;
} }
default: return false; default:
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.RefFrame) != 0) if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
{ {
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame) != Constants.IntraFrame; return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
} }
int ctx = xd.GetIntraInterContext(); int ctx = xd.GetIntraInterContext();
@@ -517,30 +538,33 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return isInter; return isInter;
} }
private static void DecFindBestRefs(bool allowHp, Span<Mv> mvlist, ref Mv bestMv, int refmvCount) private static void DecFindBestRefMvs(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 (int i = 0; i < refmvCount; ++i) for (i = 0; i < refmvCount; ++i)
{ {
mvlist[i].LowerPrecision(allowHp); mvlist[i].LowerMvPrecision(allowHP);
bestMv = mvlist[i]; bestMv = mvlist[i];
} }
} }
private static bool AddRefListEb(Mv mv, ref int refCount, Span<Mv> mvRefList, bool earlyBreak) private static bool AddMvRefListEb(Mv mv, ref int refMvCount, Span<Mv> mvRefList, bool earlyBreak)
{ {
if (refCount != 0) if (refMvCount != 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[refCount] = mv; mvRefList[refMvCount] = mv;
refCount++; refMvCount++;
return true; return true;
} }
} }
else else
{ {
mvRefList[refCount++] = mv; mvRefList[refMvCount++] = mv;
if (earlyBreak) if (earlyBreak)
{ {
return true; return true;
@@ -550,7 +574,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return false; return false;
} }
private static bool IsDiffRefFrameAddEb( // Performs mv sign inversion if indicated by the reference frame combination.
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,
@@ -562,30 +598,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (mbmi.RefFrame[0] != refFrame) if (mbmi.RefFrame[0] != refFrame)
{ {
if (AddRefListEb(mbmi.ScaleMv(0, refFrame, ref refSignBias), ref refmvCount, mvRefList, if (AddMvRefListEb(ScaleMv(ref mbmi, 0, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
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 (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, if (AddMvRefListEb(ScaleMv(ref mbmi, 1, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
earlyBreak))
{ {
return true; 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 DecFindRefs( private static int DecFindMvRefs(
ref Vp9Common cm, ref Vp9Common cm,
ref MacroBlockD xd, ref MacroBlockD xd,
PredictionMode mode, PredictionMode mode,
@@ -595,24 +627,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int miRow, int miRow,
int miCol, int miCol,
int block, int block,
int isSub8x8) int isSub8X8)
{ {
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 Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs ? new Ptr<MvRef>(ref cm.PrevFrameMvs[miRow * cm.MiCols + miCol]) : Ptr<MvRef>.Null;
? 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.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv()); mvRefList[..Constants.MaxMvRefCandidates].Clear();
i = 0; i = 0;
if (isSub8x8 != 0) if (isSub8X8 != 0)
{ {
// If the size < 8x8 we get the mv from the bmi substructure for the // If the size < 8x8 we get the mv from the bmi substructure for the
// nearest two blocks. // nearest two blocks.
@@ -621,21 +651,19 @@ 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 (AddRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, if (AddMvRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
mvRefList, earlyBreak))
{ {
goto Done; goto Done;
} }
} }
else if (candidateMi.RefFrame[1] == refFrame) else if (candidateMi.RefFrame[1] == refFrame)
{ {
if (AddRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, if (AddMvRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
mvRefList, earlyBreak))
{ {
goto Done; goto Done;
} }
@@ -647,24 +675,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 < RefNeighbours; ++i) for (; i < MvrefNeighbours; ++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 (AddRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak)) if (AddMvRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
{ {
goto Done; goto Done;
} }
} }
else if (candidate.RefFrame[1] == refFrame) else if (candidate.RefFrame[1] == refFrame)
{ {
if (AddRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak)) if (AddMvRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
{ {
goto Done; goto Done;
} }
@@ -677,14 +705,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (prevFrameMvs.Value.RefFrame[0] == refFrame) if (prevFrameMvs.Value.RefFrame[0] == refFrame)
{ {
if (AddRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak)) if (AddMvRefListEb(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 (AddRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak)) if (AddMvRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
{ {
goto Done; goto Done;
} }
@@ -696,16 +724,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// different reference frames. // different reference frames.
if (differentRefFound) if (differentRefFound)
{ {
for (i = 0; i < RefNeighbours; ++i) for (i = 0; i < MvrefNeighbours; ++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 (IsDiffRefFrameAddEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, if (IsDiffRefFrameAddMvEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, earlyBreak))
earlyBreak))
{ {
goto Done; goto Done;
} }
@@ -724,8 +751,7 @@ 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;
} }
@@ -733,8 +759,7 @@ 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[1]) != Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
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])
@@ -742,8 +767,7 @@ 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;
} }
@@ -760,17 +784,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].ClampRef(ref xd); mvRefList[i].ClampMvRef(ref xd);
} }
return refmvCount; return refmvCount;
} }
private static void AppendSub8x8ForIdx( private static void AppendSub8x8MvsForIdx(
ref Vp9Common cm, ref Vp9Common cm,
ref MacroBlockD xd, ref MacroBlockD xd,
Span<Position> mvRefSearch, Span<Position> mvRefSearch,
@@ -784,12 +808,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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 = DecFindRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, refmvCount = DecFindMvRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, block, 1);
block, 1);
switch (block) switch (block)
{ {
@@ -805,7 +829,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else else
{ {
bestSub8x8 = new Mv(); bestSub8x8 = new Mv();
for (int n = 0; n < refmvCount; ++n) for (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]))
{ {
@@ -814,7 +838,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
} }
break; break;
case 3: case 3:
if (bMode == PredictionMode.NearestMv) if (bMode == PredictionMode.NearestMv)
@@ -829,7 +852,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
candidates[2] = mvList[0]; candidates[2] = mvList[0];
candidates[3] = mvList[1]; candidates[3] = mvList[1];
bestSub8x8 = new Mv(); bestSub8x8 = new Mv();
for (int n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n) for (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]))
{ {
@@ -838,7 +861,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
} }
break; break;
default: default:
Debug.Assert(false, "Invalid block index."); Debug.Assert(false, "Invalid block index.");
@@ -846,19 +868,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, int miCol)
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 (int i = 0; i < 2; ++i) for (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];
} }
@@ -876,7 +898,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;
@@ -886,13 +908,13 @@ 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.Skip) != 0) if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.SegLvlSkip) != 0)
{ {
mi.Mode = PredictionMode.ZeroMv; mi.Mode = PredictionMode.ZeroMv;
if (bsize < BlockSize.Block8x8) if (bsize < BlockSize.Block8x8)
{ {
xd.ErrorInfo.Value.InternalError(CodecErr.UnsupBitstream, xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
"Invalid usage of segement feature on small blocks");
return; return;
} }
} }
@@ -920,58 +942,53 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
sbyte frame = mi.RefFrame[refr]; sbyte frame = mi.RefFrame[refr];
int refmvCount; int refmvCount;
refmvCount = DecFindRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, refmvCount = DecFindMvRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, -1, 0);
-1, 0);
DecFindBestRefs(allowHp, tmpMvs, ref bestRefMvs[refr], refmvCount); DecFindBestRefMvs(allowHP, tmpMvs, ref bestRefMvs[refr], refmvCount);
} }
} }
} }
mi.InterpFilter = cm.InterpFilter == Constants.Switchable mi.InterpFilter = (cm.InterpFilter == Constants.Switchable) ? ReadSwitchableInterpFilter(ref cm, ref xd, ref r) : cm.InterpFilter;
? 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)
{ {
AppendSub8x8ForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, AppendSub8x8MvsForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, ref bestSub8x8[refr]);
ref bestSub8x8[refr]);
} }
} }
if (!Assign(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, if (!AssignMv(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, isCompound, allowHP, ref r))
isCompound, allowHp, ref r))
{ {
xd.Corrupted |= true; xd.Corrupted |= true;
break; break;
} }
if (num4x4H == 2) if (num4X4H == 2)
{ {
mi.Bmi[j + 2] = mi.Bmi[j]; mi.Bmi[j + 2] = mi.Bmi[j];
} }
if (num4x4W == 2) if (num4X4W == 2)
{ {
mi.Bmi[j + 1] = mi.Bmi[j]; mi.Bmi[j + 1] = mi.Bmi[j];
} }
@@ -980,12 +997,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mi.Mode = bMode; mi.Mode = bMode;
CopyPair(ref mi.Mv, ref mi.Bmi[3].Mv); CopyMvPair(ref mi.Mv, ref mi.Bmi[3].Mv);
} }
else else
{ {
xd.Corrupted |= !Assign(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, xd.Corrupted |= !AssignMv(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, isCompound, allowHP, ref r);
isCompound, allowHp, ref r);
} }
} }
@@ -1029,6 +1045,7 @@ 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;
} }
@@ -1045,6 +1062,7 @@ 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;
} }
@@ -1057,6 +1075,7 @@ 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();
} }
@@ -1073,8 +1092,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);
@@ -1085,7 +1104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (bsize) switch (bsize)
{ {
case BlockSize.Block4x4: case BlockSize.Block4x4:
for (int i = 0; i < 4; ++i) for (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));
@@ -1130,7 +1149,8 @@ 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())
{ {
@@ -1140,15 +1160,14 @@ 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 (int h = 0; h < yMis; ++h) for (h = 0; h < yMis; ++h)
{ {
for (int w = 0; w < xMis; ++w) for (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);
CopyPair(ref mv.Mv, ref mi.Mv); CopyMvPair(ref mv.Mv, ref mi.Mv);
} }
frameMvs = frameMvs.Slice(cm.MiCols); frameMvs = frameMvs.Slice(cm.MiCols);
} }
} }

View File

@@ -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,14 +12,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private readonly MemoryAllocator _allocator = new(); private readonly MemoryAllocator _allocator = new();
public ISurface CreateSurface(int width, int height) public ISurface CreateSurface(int width, int height) => new Surface(width, height);
{
return new Surface(width, height);
}
private static ReadOnlySpan<byte> LiteralToFilter => new byte[] private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
{ {
Constants.EightTapSmooth, Constants.EightTap, Constants.EightTapSharp, Constants.Bilinear Constants.EightTapSmooth,
Constants.EightTap,
Constants.EightTapSharp,
Constants.Bilinear,
}; };
public unsafe bool Decode( public unsafe bool Decode(
@@ -29,24 +29,25 @@ 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,
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame; Width = output.Width,
cm.IntraOnly = pictureInfo.IntraOnly; Height = output.Height,
SubsamplingX = 1,
SubsamplingY = 1,
cm.Width = output.Width; UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
cm.Height = output.Height;
cm.SubsamplingX = 1;
cm.SubsamplingY = 1;
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs; RefFrameSignBias = pictureInfo.RefFrameSignBias,
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias; BaseQindex = pictureInfo.BaseQIndex,
YDcDeltaQ = pictureInfo.YDcDeltaQ,
cm.BaseQindex = pictureInfo.BaseQIndex; UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ; UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
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;
@@ -67,8 +68,6 @@ 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;
@@ -79,8 +78,6 @@ 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;
@@ -108,12 +105,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.SetupSegmentationDequant(); cm.SetupSegmentationDequant();
cm.SetupScaleFactors(); cm.SetupScaleFactors();
cm.SetMvs(mvsIn); SetMvs(ref cm, mvsIn);
if (cm.Lf.FilterLevel != 0 && cm.SkipLoopFilter == 0)
{
LoopFilter.LoopFilterFrameInit(ref cm, cm.Lf.FilterLevel);
}
fixed (byte* dataPtr = bitstream) fixed (byte* dataPtr = bitstream)
{ {
@@ -122,27 +114,10 @@ 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)
@@ -151,7 +126,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
cm.GetMvs(mvsOut); GetMvs(ref cm, mvsOut);
cm.FreeTileWorkerData(_allocator); cm.FreeTileWorkerData(_allocator);
cm.FreeContextBuffers(_allocator); cm.FreeContextBuffers(_allocator);
@@ -159,9 +134,48 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return true; return true;
} }
public void Dispose() private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
{ {
_allocator.Dispose(); if (mvs.Length > cm.PrevFrameMvs.Length)
{
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();
} }
} }

View File

@@ -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;
@@ -17,10 +17,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c) private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
{ {
const int maxNeighbors = 2; const int MaxNeighbors = 2;
return (1 + tokenCache[neighbors[(maxNeighbors * c) + 0]] + return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
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(
@@ -42,15 +58,13 @@ 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.Cat6ProbHigh12 ? Luts.Vp9Cat6ProbHigh12
: xd.Bd == 10 : (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
? Luts.Cat6ProbHigh12.Slice(2) int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
: 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;
@@ -61,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int val = -1; int val = -1;
band = bandTranslate[0]; band = bandTranslate[0];
bandTranslate = bandTranslate.Slice(1); bandTranslate = bandTranslate[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)
{ {
@@ -93,18 +107,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.Slice(1); bandTranslate = bandTranslate[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.Pareto8Full[prob[Constants.PivotNode] - 1]; ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[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];
@@ -119,24 +133,20 @@ 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 + r.ReadCoeff(cat6Prob, cat6Bits, ref value, val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range);
ref count, ref range);
} }
else else
{ {
val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value, val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range);
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 + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count, val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range);
ref range);
} }
else else
{ {
val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count, val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range);
ref range);
} }
} }
else else
@@ -144,16 +154,13 @@ 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 + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count, val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range);
ref range);
} }
else else
{ {
val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count, val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range);
ref range);
} }
} }
// Val may use 18-bits // Val may use 18-bits
v = (int)(((long)val * dqv) >> dqShift); v = (int)(((long)val * dqv) >> dqShift);
} }
@@ -181,9 +188,7 @@ 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];
@@ -192,11 +197,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, private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks)
uint txSizeInBlocks)
{ {
if (xd.MaxBlocksWide != 0) if (xd.MaxBlocksWide != 0)
{ {
@@ -205,7 +210,6 @@ 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)
@@ -234,8 +238,8 @@ 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().Slice(x); Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y); Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
int ctx; int ctx;
int ctxShiftA = 0; int ctxShiftA = 0;
int ctxShiftL = 0; int ctxShiftL = 0;

View File

@@ -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,16 +75,17 @@ 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);
src -= (SubpelTaps / 2) - 1; ulong x, y;
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 (ulong y = 0; y < (uint)h; ++y) for (y = 0; y < (uint)h; ++y)
{ {
ulong srcOffset = (uint)x0Q4 >> SubpelBits; ulong srcOffset = (uint)x0Q4 >> SubpelBits;
for (ulong x = 0; x < (uint)w; x += 4) for (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]);
@@ -93,10 +94,8 @@ 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], Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
} }
src += srcStride; src += srcStride;
dst += dstStride; dst += dstStride;
} }
@@ -118,20 +117,22 @@ 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;
} }
src -= (SubpelTaps / 2) - 1; int x, y;
src -= SubpelTaps / 2 - 1;
for (int y = 0; y < h; ++y) for (y = 0; y < h; ++y)
{ {
int xQ4 = x0Q4; int xQ4 = x0Q4;
for (int x = 0; x < w; ++x) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcX[k] * xFilter[k]; sum += srcX[k] * xFilter[k];
} }
@@ -139,7 +140,6 @@ 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,26 +156,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w, int w,
int h) int h)
{ {
src -= (SubpelTaps / 2) - 1; int x, y;
src -= SubpelTaps / 2 - 1;
for (int y = 0; y < h; ++y) for (y = 0; y < h; ++y)
{ {
int xQ4 = x0Q4; int xQ4 = x0Q4;
for (int x = 0; x < w; ++x) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcX[k] * xFilter[k]; sum += srcX[k] * xFilter[k];
} }
dst[x] = (byte)BitUtils.RoundPowerOfTwo( dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
xQ4 += xStepQ4; xQ4 += xStepQ4;
} }
src += srcStride; src += srcStride;
dst += dstStride; dst += dstStride;
} }
@@ -204,17 +203,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
srcStride * 6, srcStride * 6,
srcStride * 7); srcStride * 7);
src -= srcStride * ((SubpelTaps / 2) - 1); ulong x, y;
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 (ulong y = 0; y < (uint)h; ++y) for (y = 0; y < (uint)h; ++y)
{ {
ulong srcOffset = (srcBaseY + y) * (uint)srcStride; ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
for (ulong x = 0; x < (uint)w; x += 4) for (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,10 +240,8 @@ 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], Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
} }
dst += dstStride; dst += dstStride;
} }
} }
@@ -264,20 +262,22 @@ 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;
} }
src -= srcStride * ((SubpelTaps / 2) - 1); int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
for (int x = 0; x < w; ++x) for (x = 0; x < w; ++x)
{ {
int yQ4 = y0Q4; int yQ4 = y0Q4;
for (int y = 0; y < h; ++y) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcY[k * srcStride] * yFilter[k]; sum += srcY[k * srcStride] * yFilter[k];
} }
@@ -285,7 +285,6 @@ 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;
} }
@@ -302,17 +301,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w, int w,
int h) int h)
{ {
src -= srcStride * ((SubpelTaps / 2) - 1); int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
for (int x = 0; x < w; ++x) for (x = 0; x < w; ++x)
{ {
int yQ4 = y0Q4; int yQ4 = y0Q4;
for (int y = 0; y < h; ++y) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcY[k * srcStride] * yFilter[k]; sum += srcY[k * srcStride] * yFilter[k];
} }
@@ -321,7 +321,6 @@ 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;
} }
@@ -421,16 +420,15 @@ 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, ConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight);
intermediateHeight); ConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
ConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
} }
public static unsafe void Convolve8Avg( public static unsafe void Convolve8Avg(
@@ -491,9 +489,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w, int w,
int h) int h)
{ {
for (int y = 0; y < h; ++y) int x, y;
for (y = 0; y < h; ++y)
{ {
for (int x = 0; x < w; ++x) for (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,17 +611,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
src -= (SubpelTaps / 2) - 1; int x, y;
src -= SubpelTaps / 2 - 1;
for (int y = 0; y < h; ++y) for (y = 0; y < h; ++y)
{ {
int xQ4 = x0Q4; int xQ4 = x0Q4;
for (int x = 0; x < w; ++x) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcX[k] * xFilter[k]; sum += srcX[k] * xFilter[k];
} }
@@ -629,7 +630,6 @@ 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,26 +647,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
src -= (SubpelTaps / 2) - 1; int x, y;
src -= SubpelTaps / 2 - 1;
for (int y = 0; y < h; ++y) for (y = 0; y < h; ++y)
{ {
int xQ4 = x0Q4; int xQ4 = x0Q4;
for (int x = 0; x < w; ++x) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcX[k] * xFilter[k]; sum += srcX[k] * xFilter[k];
} }
dst[x] = (ushort)BitUtils.RoundPowerOfTwo( dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
xQ4 += xStepQ4; xQ4 += xStepQ4;
} }
src += srcStride; src += srcStride;
dst += dstStride; dst += dstStride;
} }
@@ -684,17 +683,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
src -= srcStride * ((SubpelTaps / 2) - 1); int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
for (int x = 0; x < w; ++x) for (x = 0; x < w; ++x)
{ {
int yQ4 = y0Q4; int yQ4 = y0Q4;
for (int y = 0; y < h; ++y) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (k = 0; k < SubpelTaps; ++k)
{ {
sum += srcY[k * srcStride] * yFilter[k]; sum += srcY[k * srcStride] * yFilter[k];
} }
@@ -702,7 +702,6 @@ 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;
} }
@@ -720,27 +719,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
src -= srcStride * ((SubpelTaps / 2) - 1); int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
for (int x = 0; x < w; ++x) for (x = 0; x < w; ++x)
{ {
int yQ4 = y0Q4; int yQ4 = y0Q4;
for (int y = 0; y < h; ++y) for (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 sum = 0; int k, sum = 0;
for (int k = 0; k < SubpelTaps; ++k) for (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), dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
1);
yQ4 += yStepQ4; yQ4 += yStepQ4;
} }
++src; ++src;
++dst; ++dst;
} }
@@ -773,17 +771,15 @@ 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, HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
w, intermediateHeight, bd); HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, 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(
@@ -932,9 +928,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
for (int y = 0; y < h; ++y) int x, y;
for (y = 0; y < h; ++y)
{ {
for (int x = 0; x < w; ++x) for (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);
} }

View File

@@ -1,4 +1,4 @@
using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Common;
namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
@@ -6,22 +6,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
private static unsafe ref byte Dst(byte* dst, int stride, int x, int y) private static unsafe ref byte Dst(byte* dst, int stride, int x, int y)
{ {
return ref dst[x + (y * stride)]; return ref dst[x + y * stride];
} }
private static unsafe ref ushort Dst(ushort* dst, int stride, int x, int y) private static unsafe ref ushort Dst(ushort* dst, int stride, int x, int y)
{ {
return ref dst[x + (y * stride)]; return ref dst[x + y * stride];
} }
private static byte Avg3(byte a, byte b, byte c) private static byte Avg3(byte a, byte b, byte c)
{ {
return (byte)((a + (2 * b) + c + 2) >> 2); return (byte)((a + 2 * b + c + 2) >> 2);
} }
private static ushort Avg3(ushort a, ushort b, ushort c) private static ushort Avg3(ushort a, ushort b, ushort c)
{ {
return (ushort)((a + (2 * b) + c + 2) >> 2); return (ushort)((a + 2 * b + c + 2) >> 2);
} }
private static byte Avg2(byte a, byte b) private static byte Avg2(byte a, byte b)
@@ -51,8 +51,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D207Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D207Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int r, c;
// First column // First column
for (int r = 0; r < bs - 1; ++r) for (r = 0; r < bs - 1; ++r)
{ {
dst[r * stride] = Avg2(left[r], left[r + 1]); dst[r * stride] = Avg2(left[r], left[r + 1]);
} }
@@ -61,7 +62,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst++; dst++;
// Second column // Second column
for (int r = 0; r < bs - 2; ++r) for (r = 0; r < bs - 2; ++r)
{ {
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]); dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
} }
@@ -71,16 +72,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst++; dst++;
// Rest of last row // Rest of last row
for (int c = 0; c < bs - 2; ++c) for (c = 0; c < bs - 2; ++c)
{ {
dst[((bs - 1) * stride) + c] = left[bs - 1]; dst[(bs - 1) * stride + c] = left[bs - 1];
} }
for (int r = bs - 2; r >= 0; --r) for (r = bs - 2; r >= 0; --r)
{ {
for (int c = 0; c < bs - 2; ++c) for (c = 0; c < bs - 2; ++c)
{ {
dst[(r * stride) + c] = dst[((r + 1) * stride) + c - 2]; dst[r * stride + c] = dst[(r + 1) * stride + c - 2];
} }
} }
} }
@@ -102,18 +103,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D63Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D63Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
for (int c = 0; c < bs; ++c) int r, c;
int size;
for (c = 0; c < bs; ++c)
{ {
dst[c] = Avg2(above[c], above[c + 1]); dst[c] = Avg2(above[c], above[c + 1]);
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]); dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
} }
for (r = 2, size = bs - 2; r < bs; r += 2, --size)
for (int r = 2, size = bs - 2; r < bs; r += 2, --size)
{ {
MemoryUtil.Copy(dst + ((r + 0) * stride), dst + (r >> 1), size); MemoryUtil.Copy(dst + (r + 0) * stride, dst + (r >> 1), size);
MemoryUtil.Fill(dst + ((r + 0) * stride) + size, above[bs - 1], bs - size); MemoryUtil.Fill(dst + (r + 0) * stride + size, above[bs - 1], bs - size);
MemoryUtil.Copy(dst + ((r + 1) * stride), dst + stride + (r >> 1), size); MemoryUtil.Copy(dst + (r + 1) * stride, dst + stride + (r >> 1), size);
MemoryUtil.Fill(dst + ((r + 1) * stride) + size, above[bs - 1], bs - size); MemoryUtil.Fill(dst + (r + 1) * stride + size, above[bs - 1], bs - size);
} }
} }
@@ -136,15 +138,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
byte aboveRight = above[bs - 1]; byte aboveRight = above[bs - 1];
byte* dstRow0 = dst; byte* dstRow0 = dst;
int x, size;
for (int x = 0; x < bs - 1; ++x) for (x = 0; x < bs - 1; ++x)
{ {
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]); dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
} }
dst[bs - 1] = aboveRight; dst[bs - 1] = aboveRight;
dst += stride; dst += stride;
for (int x = 1, size = bs - 2; x < bs; ++x, --size) for (x = 1, size = bs - 2; x < bs; ++x, --size)
{ {
MemoryUtil.Copy(dst, dstRow0 + x, size); MemoryUtil.Copy(dst, dstRow0 + x, size);
MemoryUtil.Fill(dst + size, aboveRight, x + 1); MemoryUtil.Fill(dst + size, aboveRight, x + 1);
@@ -169,8 +171,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D117Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D117Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int r, c;
// First row // First row
for (int c = 0; c < bs; c++) for (c = 0; c < bs; c++)
{ {
dst[c] = Avg2(above[c - 1], above[c]); dst[c] = Avg2(above[c - 1], above[c]);
} }
@@ -179,7 +183,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// Second row // Second row
dst[0] = Avg3(left[0], above[-1], above[0]); dst[0] = Avg3(left[0], above[-1], above[0]);
for (int c = 1; c < bs; c++) for (c = 1; c < bs; c++)
{ {
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]); dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
} }
@@ -188,17 +192,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// The rest of first col // The rest of first col
dst[0] = Avg3(above[-1], left[0], left[1]); dst[0] = Avg3(above[-1], left[0], left[1]);
for (int r = 3; r < bs; ++r) for (r = 3; r < bs; ++r)
{ {
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]); dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
} }
// The rest of the block // The rest of the block
for (int r = 2; r < bs; ++r) for (r = 2; r < bs; ++r)
{ {
for (int c = 1; c < bs; c++) for (c = 1; c < bs; c++)
{ {
dst[c] = dst[(-2 * stride) + c - 1]; dst[c] = dst[-2 * stride + c - 1];
} }
dst += stride; dst += stride;
@@ -222,26 +226,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int i;
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left // Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
for (int i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
{ {
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]); border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
} }
border[bs - 2] = Avg3(above[-1], left[0], left[1]); border[bs - 2] = Avg3(above[-1], left[0], left[1]);
border[bs - 1] = Avg3(left[0], above[-1], above[0]); border[bs - 1] = Avg3(left[0], above[-1], above[0]);
border[bs - 0] = Avg3(above[-1], above[0], above[1]); border[bs - 0] = Avg3(above[-1], above[0], above[1]);
// dst[0][2, size), i.e., remaining top border ascending // dst[0][2, size), i.e., remaining top border ascending
for (int i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
{ {
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]); border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
} }
for (int i = 0; i < bs; ++i) for (i = 0; i < bs; ++i)
{ {
MemoryUtil.Copy(dst + (i * stride), border + bs - 1 - i, bs); MemoryUtil.Copy(dst + i * stride, border + bs - 1 - i, bs);
} }
} }
@@ -262,8 +266,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D153Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D153Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int r, c;
dst[0] = Avg2(above[-1], left[0]); dst[0] = Avg2(above[-1], left[0]);
for (int r = 1; r < bs; r++) for (r = 1; r < bs; r++)
{ {
dst[r * stride] = Avg2(left[r - 1], left[r]); dst[r * stride] = Avg2(left[r - 1], left[r]);
} }
@@ -272,23 +277,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[0] = Avg3(left[0], above[-1], above[0]); dst[0] = Avg3(left[0], above[-1], above[0]);
dst[stride] = Avg3(above[-1], left[0], left[1]); dst[stride] = Avg3(above[-1], left[0], left[1]);
for (int r = 2; r < bs; r++) for (r = 2; r < bs; r++)
{ {
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]); dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
} }
dst++; dst++;
for (int c = 0; c < bs - 2; c++) for (c = 0; c < bs - 2; c++)
{ {
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]); dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
} }
dst += stride; dst += stride;
for (int r = 1; r < bs; ++r) for (r = 1; r < bs; ++r)
{ {
for (int c = 0; c < bs - 2; c++) for (c = 0; c < bs - 2; c++)
{ {
dst[c] = dst[-stride + c - 2]; dst[c] = dst[-stride + c - 2];
} }
@@ -319,7 +324,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void VPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void VPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Copy(dst, above, bs); MemoryUtil.Copy(dst, above, bs);
dst += stride; dst += stride;
@@ -348,40 +355,43 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void HPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void HPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, left[r], bs); MemoryUtil.Fill(dst, left[r], bs);
dst += stride; dst += stride;
} }
} }
public static unsafe void TmPredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void TMPredictor4x4(byte* dst, int stride, byte* above, byte* left)
{ {
TmPredictor(dst, stride, 4, above, left); TMPredictor(dst, stride, 4, above, left);
} }
public static unsafe void TmPredictor8x8(byte* dst, int stride, byte* above, byte* left) public static unsafe void TMPredictor8x8(byte* dst, int stride, byte* above, byte* left)
{ {
TmPredictor(dst, stride, 8, above, left); TMPredictor(dst, stride, 8, above, left);
} }
public static unsafe void TmPredictor16x16(byte* dst, int stride, byte* above, byte* left) public static unsafe void TMPredictor16x16(byte* dst, int stride, byte* above, byte* left)
{ {
TmPredictor(dst, stride, 16, above, left); TMPredictor(dst, stride, 16, above, left);
} }
public static unsafe void TmPredictor32x32(byte* dst, int stride, byte* above, byte* left) public static unsafe void TMPredictor32x32(byte* dst, int stride, byte* above, byte* left)
{ {
TmPredictor(dst, stride, 32, above, left); TMPredictor(dst, stride, 32, above, left);
} }
private static unsafe void TmPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void TMPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int r, c;
int yTopLeft = above[-1]; int yTopLeft = above[-1];
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
for (int c = 0; c < bs; c++) for (c = 0; c < bs; c++)
{ {
dst[c] = BitUtils.ClipPixel(left[r] + above[c] - yTopLeft); dst[c] = BitUtils.ClipPixel(left[r] + above[c] - yTopLeft);
} }
@@ -412,7 +422,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void Dc128Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void Dc128Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (byte)128, bs); MemoryUtil.Fill(dst, (byte)128, bs);
dst += stride; dst += stride;
@@ -441,16 +453,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void DcLeftPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void DcLeftPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += left[i]; sum += left[i];
} }
expectedDc = (sum + (bs >> 1)) / bs; expectedDc = (sum + (bs >> 1)) / bs;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (byte)expectedDc, bs); MemoryUtil.Fill(dst, (byte)expectedDc, bs);
dst += stride; dst += stride;
@@ -479,16 +491,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void DcTopPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void DcTopPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += above[i]; sum += above[i];
} }
expectedDc = (sum + (bs >> 1)) / bs; expectedDc = (sum + (bs >> 1)) / bs;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (byte)expectedDc, bs); MemoryUtil.Fill(dst, (byte)expectedDc, bs);
dst += stride; dst += stride;
@@ -517,10 +529,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void DcPredictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void DcPredictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
int count = 2 * bs; int count = 2 * bs;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += above[i]; sum += above[i];
sum += left[i]; sum += left[i];
@@ -528,7 +540,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
expectedDc = (sum + (count >> 1)) / count; expectedDc = (sum + (count >> 1)) / count;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (byte)expectedDc, bs); MemoryUtil.Fill(dst, (byte)expectedDc, bs);
dst += stride; dst += stride;
@@ -543,10 +555,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
byte k = left[2]; byte k = left[2];
byte l = left[3]; byte l = left[3];
MemoryUtil.Fill(dst + (stride * 0), Avg3(h, I, j), 4); MemoryUtil.Fill(dst + stride * 0, Avg3(h, I, j), 4);
MemoryUtil.Fill(dst + (stride * 1), Avg3(I, j, k), 4); MemoryUtil.Fill(dst + stride * 1, Avg3(I, j, k), 4);
MemoryUtil.Fill(dst + (stride * 2), Avg3(j, k, l), 4); MemoryUtil.Fill(dst + stride * 2, Avg3(j, k, l), 4);
MemoryUtil.Fill(dst + (stride * 3), Avg3(k, l, l), 4); MemoryUtil.Fill(dst + stride * 3, Avg3(k, l, l), 4);
} }
public static unsafe void VePredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void VePredictor4x4(byte* dst, int stride, byte* above, byte* left)
@@ -562,9 +574,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[1] = Avg3(I, j, k); dst[1] = Avg3(I, j, k);
dst[2] = Avg3(j, k, l); dst[2] = Avg3(j, k, l);
dst[3] = Avg3(k, l, m); dst[3] = Avg3(k, l, m);
MemoryUtil.Copy(dst + (stride * 1), dst, 4); MemoryUtil.Copy(dst + stride * 1, dst, 4);
MemoryUtil.Copy(dst + (stride * 2), dst, 4); MemoryUtil.Copy(dst + stride * 2, dst, 4);
MemoryUtil.Copy(dst + (stride * 3), dst, 4); MemoryUtil.Copy(dst + stride * 3, dst, 4);
} }
public static unsafe void D207Predictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D207Predictor4x4(byte* dst, int stride, byte* above, byte* left)
@@ -579,8 +591,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 1, 0) = Avg3(I, j, k); Dst(dst, stride, 1, 0) = Avg3(I, j, k);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l); Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l); Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
} }
public static unsafe void D63Predictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D63Predictor4x4(byte* dst, int stride, byte* above, byte* left)
@@ -605,7 +616,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8 Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
} }
public static unsafe void D63EPredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
{ {
byte a = above[0]; byte a = above[0];
byte b = above[1]; byte b = above[1];
@@ -641,14 +652,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 0, 0) = Avg3(a, b, c); Dst(dst, stride, 0, 0) = Avg3(a, b, c);
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d); Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e); Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
Dst(dst, stride, 3, 3) = h; // differs from vp8 Dst(dst, stride, 3, 3) = h; // differs from vp8
} }
public static unsafe void D45EPredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
{ {
byte a = above[0]; byte a = above[0];
byte b = above[1]; byte b = above[1];
@@ -661,8 +671,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 0, 0) = Avg3(a, b, c); Dst(dst, stride, 0, 0) = Avg3(a, b, c);
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d); Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e); Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
Dst(dst, stride, 3, 3) = Avg3(g, h, h); Dst(dst, stride, 3, 3) = Avg3(g, h, h);
@@ -705,8 +714,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 0, 3) = Avg3(j, k, l); Dst(dst, stride, 0, 3) = Avg3(j, k, l);
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k); Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j); Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
Dst(dst, stride, 3, 3) = Dst(dst, stride, 3, 3) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
Dst(dst, stride, 3, 0) = Avg3(d, c, b); Dst(dst, stride, 3, 0) = Avg3(d, c, b);
@@ -750,39 +758,38 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD207Predictor(dst, stride, 32, above, left, bd); HighbdD207Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD207Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD207Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int r, c;
// First column. // First column.
for (int r = 0; r < bs - 1; ++r) for (r = 0; r < bs - 1; ++r)
{ {
dst[r * stride] = Avg2(left[r], left[r + 1]); dst[r * stride] = Avg2(left[r], left[r + 1]);
} }
dst[(bs - 1) * stride] = left[bs - 1]; dst[(bs - 1) * stride] = left[bs - 1];
dst++; dst++;
// Second column. // Second column.
for (int r = 0; r < bs - 2; ++r) for (r = 0; r < bs - 2; ++r)
{ {
dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]); dst[r * stride] = Avg3(left[r], left[r + 1], left[r + 2]);
} }
dst[(bs - 2) * stride] = Avg3(left[bs - 2], left[bs - 1], left[bs - 1]); dst[(bs - 2) * stride] = Avg3(left[bs - 2], left[bs - 1], left[bs - 1]);
dst[(bs - 1) * stride] = left[bs - 1]; dst[(bs - 1) * stride] = left[bs - 1];
dst++; dst++;
// Rest of last row. // Rest of last row.
for (int c = 0; c < bs - 2; ++c) for (c = 0; c < bs - 2; ++c)
{ {
dst[((bs - 1) * stride) + c] = left[bs - 1]; dst[(bs - 1) * stride + c] = left[bs - 1];
} }
for (int r = bs - 2; r >= 0; --r) for (r = bs - 2; r >= 0; --r)
{ {
for (int c = 0; c < bs - 2; ++c) for (c = 0; c < bs - 2; ++c)
{ {
dst[(r * stride) + c] = dst[((r + 1) * stride) + c - 2]; dst[r * stride + c] = dst[(r + 1) * stride + c - 2];
} }
} }
} }
@@ -802,21 +809,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD63Predictor(dst, stride, 32, above, left, bd); HighbdD63Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD63Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD63Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
for (int c = 0; c < bs; ++c) int r, c;
int size;
for (c = 0; c < bs; ++c)
{ {
dst[c] = Avg2(above[c], above[c + 1]); dst[c] = Avg2(above[c], above[c + 1]);
dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]); dst[stride + c] = Avg3(above[c], above[c + 1], above[c + 2]);
} }
for (r = 2, size = bs - 2; r < bs; r += 2, --size)
for (int r = 2, size = bs - 2; r < bs; r += 2, --size)
{ {
MemoryUtil.Copy(dst + ((r + 0) * stride), dst + (r >> 1), size); MemoryUtil.Copy(dst + (r + 0) * stride, dst + (r >> 1), size);
MemoryUtil.Fill(dst + ((r + 0) * stride) + size, above[bs - 1], bs - size); MemoryUtil.Fill(dst + (r + 0) * stride + size, above[bs - 1], bs - size);
MemoryUtil.Copy(dst + ((r + 1) * stride), dst + stride + (r >> 1), size); MemoryUtil.Copy(dst + (r + 1) * stride, dst + stride + (r >> 1), size);
MemoryUtil.Fill(dst + ((r + 1) * stride) + size, above[bs - 1], bs - size); MemoryUtil.Fill(dst + (r + 1) * stride + size, above[bs - 1], bs - size);
} }
} }
@@ -835,20 +842,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD45Predictor(dst, stride, 32, above, left, bd); HighbdD45Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD45Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD45Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
ushort aboveRight = above[bs - 1]; ushort aboveRight = above[bs - 1];
ushort* dstRow0 = dst; ushort* dstRow0 = dst;
int x, size;
for (int x = 0; x < bs - 1; ++x) for (x = 0; x < bs - 1; ++x)
{ {
dst[x] = Avg3(above[x], above[x + 1], above[x + 2]); dst[x] = Avg3(above[x], above[x + 1], above[x + 2]);
} }
dst[bs - 1] = aboveRight; dst[bs - 1] = aboveRight;
dst += stride; dst += stride;
for (int x = 1, size = bs - 2; x < bs; ++x, --size) for (x = 1, size = bs - 2; x < bs; ++x, --size)
{ {
MemoryUtil.Copy(dst, dstRow0 + x, size); MemoryUtil.Copy(dst, dstRow0 + x, size);
MemoryUtil.Fill(dst + size, aboveRight, x + 1); MemoryUtil.Fill(dst + size, aboveRight, x + 1);
@@ -871,11 +877,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD117Predictor(dst, stride, 32, above, left, bd); HighbdD117Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD117Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD117Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int r, c;
// First row // First row
for (int c = 0; c < bs; c++) for (c = 0; c < bs; c++)
{ {
dst[c] = Avg2(above[c - 1], above[c]); dst[c] = Avg2(above[c - 1], above[c]);
} }
@@ -884,7 +891,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// Second row // Second row
dst[0] = Avg3(left[0], above[-1], above[0]); dst[0] = Avg3(left[0], above[-1], above[0]);
for (int c = 1; c < bs; c++) for (c = 1; c < bs; c++)
{ {
dst[c] = Avg3(above[c - 2], above[c - 1], above[c]); dst[c] = Avg3(above[c - 2], above[c - 1], above[c]);
} }
@@ -893,17 +900,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// The rest of first col // The rest of first col
dst[0] = Avg3(above[-1], left[0], left[1]); dst[0] = Avg3(above[-1], left[0], left[1]);
for (int r = 3; r < bs; ++r) for (r = 3; r < bs; ++r)
{ {
dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]); dst[(r - 2) * stride] = Avg3(left[r - 3], left[r - 2], left[r - 1]);
} }
// The rest of the block // The rest of the block
for (int r = 2; r < bs; ++r) for (r = 2; r < bs; ++r)
{ {
for (int c = 1; c < bs; c++) for (c = 1; c < bs; c++)
{ {
dst[c] = dst[(-2 * stride) + c - 1]; dst[c] = dst[-2 * stride + c - 1];
} }
dst += stride; dst += stride;
@@ -925,29 +932,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD135Predictor(dst, stride, 32, above, left, bd); HighbdD135Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int i;
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left // Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
for (int i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
{ {
border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]); border[i] = Avg3(left[bs - 3 - i], left[bs - 2 - i], left[bs - 1 - i]);
} }
border[bs - 2] = Avg3(above[-1], left[0], left[1]); border[bs - 2] = Avg3(above[-1], left[0], left[1]);
border[bs - 1] = Avg3(left[0], above[-1], above[0]); border[bs - 1] = Avg3(left[0], above[-1], above[0]);
border[bs - 0] = Avg3(above[-1], above[0], above[1]); border[bs - 0] = Avg3(above[-1], above[0], above[1]);
// dst[0][2, size), i.e., remaining top border ascending // dst[0][2, size), i.e., remaining top border ascending
for (int i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
{ {
border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]); border[bs + 1 + i] = Avg3(above[i], above[i + 1], above[i + 2]);
} }
for (int i = 0; i < bs; ++i) for (i = 0; i < bs; ++i)
{ {
MemoryUtil.Copy(dst + (i * stride), border + bs - 1 - i, bs); MemoryUtil.Copy(dst + i * stride, border + bs - 1 - i, bs);
} }
} }
@@ -966,11 +972,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdD153Predictor(dst, stride, 32, above, left, bd); HighbdD153Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdD153Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdD153Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int r, c;
dst[0] = Avg2(above[-1], left[0]); dst[0] = Avg2(above[-1], left[0]);
for (int r = 1; r < bs; r++) for (r = 1; r < bs; r++)
{ {
dst[r * stride] = Avg2(left[r - 1], left[r]); dst[r * stride] = Avg2(left[r - 1], left[r]);
} }
@@ -979,23 +985,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[0] = Avg3(left[0], above[-1], above[0]); dst[0] = Avg3(left[0], above[-1], above[0]);
dst[stride] = Avg3(above[-1], left[0], left[1]); dst[stride] = Avg3(above[-1], left[0], left[1]);
for (int r = 2; r < bs; r++) for (r = 2; r < bs; r++)
{ {
dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]); dst[r * stride] = Avg3(left[r - 2], left[r - 1], left[r]);
} }
dst++; dst++;
for (int c = 0; c < bs - 2; c++) for (c = 0; c < bs - 2; c++)
{ {
dst[c] = Avg3(above[c - 1], above[c], above[c + 1]); dst[c] = Avg3(above[c - 1], above[c], above[c + 1]);
} }
dst += stride; dst += stride;
for (int r = 1; r < bs; ++r) for (r = 1; r < bs; ++r)
{ {
for (int c = 0; c < bs - 2; c++) for (c = 0; c < bs - 2; c++)
{ {
dst[c] = dst[-stride + c - 2]; dst[c] = dst[-stride + c - 2];
} }
@@ -1024,10 +1030,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdVPredictor(dst, stride, 32, above, left, bd); HighbdVPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdVPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdVPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Copy(dst, above, bs); MemoryUtil.Copy(dst, above, bs);
dst += stride; dst += stride;
@@ -1054,44 +1060,44 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdHPredictor(dst, stride, 32, above, left, bd); HighbdHPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdHPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdHPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, left[r], bs); MemoryUtil.Fill(dst, left[r], bs);
dst += stride; dst += stride;
} }
} }
public static unsafe void HighbdTmPredictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdTMPredictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
{ {
HighbdTmPredictor(dst, stride, 4, above, left, bd); HighbdTMPredictor(dst, stride, 4, above, left, bd);
} }
public static unsafe void HighbdTmPredictor8x8(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdTMPredictor8x8(ushort* dst, int stride, ushort* above, ushort* left, int bd)
{ {
HighbdTmPredictor(dst, stride, 8, above, left, bd); HighbdTMPredictor(dst, stride, 8, above, left, bd);
} }
public static unsafe void HighbdTmPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdTMPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
{ {
HighbdTmPredictor(dst, stride, 16, above, left, bd); HighbdTMPredictor(dst, stride, 16, above, left, bd);
} }
public static unsafe void HighbdTmPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdTMPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
{ {
HighbdTmPredictor(dst, stride, 32, above, left, bd); HighbdTMPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdTmPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdTMPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int r, c;
int yTopLeft = above[-1]; int yTopLeft = above[-1];
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
for (int c = 0; c < bs; c++) for (c = 0; c < bs; c++)
{ {
dst[c] = BitUtils.ClipPixelHighbd(left[r] + above[c] - yTopLeft, bd); dst[c] = BitUtils.ClipPixelHighbd(left[r] + above[c] - yTopLeft, bd);
} }
@@ -1110,22 +1116,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdDc128Predictor(dst, stride, 8, above, left, bd); HighbdDc128Predictor(dst, stride, 8, above, left, bd);
} }
public static unsafe void HighbdDc128Predictor16x16(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDc128Predictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDc128Predictor(dst, stride, 16, above, left, bd); HighbdDc128Predictor(dst, stride, 16, above, left, bd);
} }
public static unsafe void HighbdDc128Predictor32x32(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDc128Predictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDc128Predictor(dst, stride, 32, above, left, bd); HighbdDc128Predictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdDc128Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdDc128Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
for (int r = 0; r < bs; r++) int r;
for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (ushort)(128 << (bd - 8)), bs); MemoryUtil.Fill(dst, (ushort)(128 << (bd - 8)), bs);
dst += stride; dst += stride;
@@ -1142,31 +1147,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdDcLeftPredictor(dst, stride, 8, above, left, bd); HighbdDcLeftPredictor(dst, stride, 8, above, left, bd);
} }
public static unsafe void HighbdDcLeftPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDcLeftPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDcLeftPredictor(dst, stride, 16, above, left, bd); HighbdDcLeftPredictor(dst, stride, 16, above, left, bd);
} }
public static unsafe void HighbdDcLeftPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDcLeftPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDcLeftPredictor(dst, stride, 32, above, left, bd); HighbdDcLeftPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdDcLeftPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdDcLeftPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += left[i]; sum += left[i];
} }
expectedDc = (sum + (bs >> 1)) / bs; expectedDc = (sum + (bs >> 1)) / bs;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (ushort)expectedDc, bs); MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
dst += stride; dst += stride;
@@ -1183,31 +1185,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdDcTopPredictor(dst, stride, 8, above, left, bd); HighbdDcTopPredictor(dst, stride, 8, above, left, bd);
} }
public static unsafe void HighbdDcTopPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDcTopPredictor16x16(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDcTopPredictor(dst, stride, 16, above, left, bd); HighbdDcTopPredictor(dst, stride, 16, above, left, bd);
} }
public static unsafe void HighbdDcTopPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, public static unsafe void HighbdDcTopPredictor32x32(ushort* dst, int stride, ushort* above, ushort* left, int bd)
int bd)
{ {
HighbdDcTopPredictor(dst, stride, 32, above, left, bd); HighbdDcTopPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdDcTopPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdDcTopPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += above[i]; sum += above[i];
} }
expectedDc = (sum + (bs >> 1)) / bs; expectedDc = (sum + (bs >> 1)) / bs;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (ushort)expectedDc, bs); MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
dst += stride; dst += stride;
@@ -1234,13 +1233,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
HighbdDcPredictor(dst, stride, 32, above, left, bd); HighbdDcPredictor(dst, stride, 32, above, left, bd);
} }
private static unsafe void HighbdDcPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, private static unsafe void HighbdDcPredictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
int bd)
{ {
int expectedDc, sum = 0; int i, r, expectedDc, sum = 0;
int count = 2 * bs; int count = 2 * bs;
for (int i = 0; i < bs; i++) for (i = 0; i < bs; i++)
{ {
sum += above[i]; sum += above[i];
sum += left[i]; sum += left[i];
@@ -1248,7 +1246,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
expectedDc = (sum + (count >> 1)) / count; expectedDc = (sum + (count >> 1)) / count;
for (int r = 0; r < bs; r++) for (r = 0; r < bs; r++)
{ {
MemoryUtil.Fill(dst, (ushort)expectedDc, bs); MemoryUtil.Fill(dst, (ushort)expectedDc, bs);
dst += stride; dst += stride;
@@ -1267,8 +1265,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 1, 0) = Avg3(I, j, k); Dst(dst, stride, 1, 0) = Avg3(I, j, k);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l); Dst(dst, stride, 3, 0) = Dst(dst, stride, 1, 1) = Avg3(j, k, l);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l); Dst(dst, stride, 3, 1) = Dst(dst, stride, 1, 2) = Avg3(k, l, l);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 0, 3) = Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
Dst(dst, stride, 1, 3) = Dst(dst, stride, 2, 3) = Dst(dst, stride, 3, 3) = l;
} }
public static unsafe void HighbdD63Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdD63Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
@@ -1306,8 +1303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 0, 0) = Avg3(a, b, c); Dst(dst, stride, 0, 0) = Avg3(a, b, c);
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d); Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 1) = Avg3(b, c, d);
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e); Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 2) = Avg3(c, d, e);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
Dst(dst, stride, 3, 3) = h; // Differs from vp8 Dst(dst, stride, 3, 3) = h; // Differs from vp8
@@ -1350,8 +1346,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 0, 3) = Avg3(j, k, l); Dst(dst, stride, 0, 3) = Avg3(j, k, l);
Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k); Dst(dst, stride, 1, 3) = Dst(dst, stride, 0, 2) = Avg3(I, j, k);
Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j); Dst(dst, stride, 2, 3) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 1) = Avg3(x, I, j);
Dst(dst, stride, 3, 3) = Dst(dst, stride, 3, 3) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 0) = Avg3(a, x, I);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 0) = Avg3(b, a, x);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 0) = Avg3(c, b, a);
Dst(dst, stride, 3, 0) = Avg3(d, c, b); Dst(dst, stride, 3, 0) = Avg3(d, c, b);

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +0,0 @@
using Ryujinx.Common.Memory;
using System;
using System.Runtime.Intrinsics.X86;
namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
internal class LoopFilterAuto
{
public static void LpfHorizontal4(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal4(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfHorizontal4(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfHorizontal4Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit0,
ReadOnlySpan<byte> limit0,
ReadOnlySpan<byte> thresh0,
ReadOnlySpan<byte> blimit1,
ReadOnlySpan<byte> limit1,
ReadOnlySpan<byte> thresh1)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
}
else
{
LoopFilterScalar.LpfHorizontal4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
thresh1[0]);
}
}
public static void LpfHorizontal8(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal8(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfHorizontal8(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfHorizontal8Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit0,
ReadOnlySpan<byte> limit0,
ReadOnlySpan<byte> thresh0,
ReadOnlySpan<byte> blimit1,
ReadOnlySpan<byte> limit1,
ReadOnlySpan<byte> thresh1)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
}
else
{
LoopFilterScalar.LpfHorizontal8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
thresh1[0]);
}
}
public static void LpfHorizontal16(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal16(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfHorizontal16(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfHorizontal16Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfHorizontal16Dual(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfHorizontal16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfVertical4(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical4(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfVertical4(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfVertical4Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit0,
ReadOnlySpan<byte> limit0,
ReadOnlySpan<byte> thresh0,
ReadOnlySpan<byte> blimit1,
ReadOnlySpan<byte> limit1,
ReadOnlySpan<byte> thresh1)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
}
else
{
LoopFilterScalar.LpfVertical4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
thresh1[0]);
}
}
public static void LpfVertical8(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical8(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfVertical8(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfVertical8Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit0,
ReadOnlySpan<byte> limit0,
ReadOnlySpan<byte> thresh0,
ReadOnlySpan<byte> blimit1,
ReadOnlySpan<byte> limit1,
ReadOnlySpan<byte> thresh1)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
}
else
{
LoopFilterScalar.LpfVertical8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
thresh1[0]);
}
}
public static void LpfVertical16(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical16(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfVertical16(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
public static void LpfVertical16Dual(
ArrayPtr<byte> s,
int pitch,
ReadOnlySpan<byte> blimit,
ReadOnlySpan<byte> limit,
ReadOnlySpan<byte> thresh)
{
if (Sse2.IsSupported)
{
LoopFilterSse2.LpfVertical16Dual(s, pitch, blimit, limit, thresh);
}
else
{
LoopFilterScalar.LpfVertical16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Common;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
@@ -12,9 +12,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
Debug.Assert(den != 0); Debug.Assert(den != 0);
{ {
int p = (int)((((ulong)num * 256) + (den >> 1)) / den); int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
// (p > 255) ? 255 : (p < 1) ? 1 : p; // (p > 255) ? 255 : (p < 1) ? 1 : p;
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0); int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
return (byte)clippedProb; return (byte)clippedProb;
} }
} }
@@ -22,13 +23,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
/* This function assumes prob1 and prob2 are already within [1,255] range. */ /* This function assumes prob1 and prob2 are already within [1,255] range. */
public static byte WeightedProb(int prob1, int prob2, int factor) public static byte WeightedProb(int prob1, int prob2, int factor)
{ {
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8); return (byte)BitUtils.RoundPowerOfTwo(prob1 * (256 - factor) + prob2 * factor, 8);
} }
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT; // MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
private static readonly uint[] CountToUpdateFactor = private static readonly uint[] _countToUpdateFactor = {
{ 0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, 70, 76, 83, 89, 96, 102, 108, 115, 121, 128 70, 76, 83, 89, 96, 102, 108, 115, 121, 128,
}; };
private const int ModeMvCountSat = 20; private const int ModeMvCountSat = 20;
@@ -40,11 +41,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
return preProb; return preProb;
} }
else
{
uint count = Math.Min(den, ModeMvCountSat);
uint factor = _countToUpdateFactor[(int)count];
byte prob = GetProb(ct0, den);
uint count = Math.Min(den, ModeMvCountSat); return WeightedProb(preProb, prob, (int)factor);
uint factor = CountToUpdateFactor[(int)count]; }
byte prob = GetProb(ct0, den);
return WeightedProb(preProb, prob, (int)factor);
} }
private static uint TreeMergeProbsImpl( private static uint TreeMergeProbsImpl(
@@ -55,15 +59,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<byte> probs) Span<byte> probs)
{ {
int l = tree[i]; int l = tree[i];
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs); uint leftCount = (l <= 0) ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
int r = tree[i + 1]; int r = tree[i + 1];
uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs); uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount); probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
return leftCount + rightCount; return leftCount + rightCount;
} }
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, Span<byte> probs)
Span<byte> probs)
{ {
TreeMergeProbsImpl(0, tree, preProbs, counts, probs); TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
} }

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
@@ -7,18 +6,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
internal struct Reader internal struct Reader
{ {
private static readonly byte[] Norm = private static readonly byte[] _norm = {
{ 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}; };
private const int BdValueSize = sizeof(ulong) * 8; private const int BdValueSize = sizeof(ulong) * 8;
// This is meant to be a large, positive constant that can still be efficiently // This is meant to be a large, positive constant that can still be efficiently
@@ -37,13 +36,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
return true; return true;
} }
else
{
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0;
Count = -8;
Range = 255;
Fill();
_buffer = new ArrayPtr<byte>(ref buffer[0], size); return ReadBit() != 0; // Marker bit
Value = 0; }
Count = -8;
Range = 255;
Fill();
return ReadBit() != 0; // Marker bit
} }
private void Fill() private void Fill()
@@ -63,7 +65,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer); ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
nv = bigEndianValues >> (BdValueSize - bits); nv = bigEndianValues >> (BdValueSize - bits);
count += bits; count += bits;
buffer = buffer.Slice(bits >> 3); buffer = buffer[(bits >> 3)..];
value = Value | (nv << (shift & 0x7)); value = Value | (nv << (shift & 0x7));
} }
else else
@@ -82,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
count += 8; count += 8;
value |= (ulong)buffer[0] << shift; value |= (ulong)buffer[0] << shift;
buffer = buffer.Slice(1); buffer = buffer[1..];
shift -= 8; shift -= 8;
} }
} }
@@ -96,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count; Count = count;
} }
public bool HasError() public readonly bool HasError()
{ {
// Check if we have reached the end of the buffer. // Check if we have reached the end of the buffer.
// //
@@ -122,7 +124,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigsplit; ulong bigsplit;
int count; int count;
uint range; uint range;
uint split = ((Range * (uint)prob) + (256 - (uint)prob)) >> 8; uint split = (Range * (uint)prob + (256 - (uint)prob)) >> 8;
if (Count < 0) if (Count < 0)
{ {
@@ -144,7 +146,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -186,7 +188,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public int ReadBool(int prob, ref ulong value, ref int count, ref uint range) public int ReadBool(int prob, ref ulong value, ref int count, ref uint range)
{ {
uint split = ((range * (uint)prob) + (256 - (uint)prob)) >> 8; uint split = (range * (uint)prob + (256 - (uint)prob)) >> 8;
ulong bigsplit = (ulong)split << (BdValueSize - 8); ulong bigsplit = (ulong)split << (BdValueSize - 8);
if (count < 0) if (count < 0)
@@ -200,20 +202,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit) if (value >= bigsplit)
{ {
range = range - split; range -= split;
value = value - bigsplit; value -= bigsplit;
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
} }
return 1; return 1;
} }
range = split; range = split;
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -229,82 +230,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count -= 8; Count -= 8;
_buffer = _buffer.Slice(-1); _buffer = _buffer.Slice(-1);
} }
return _buffer; return _buffer;
} }
private int DecodeUniform()
{
const int l = 8;
const int m = (1 << l) - 191;
int v = ReadLiteral(l - 1);
return v < m ? v : (v << 1) - m + ReadBit();
}
public int DecodeTermSubexp()
{
if (ReadBit() == 0)
{
return ReadLiteral(4);
}
if (ReadBit() == 0)
{
return ReadLiteral(4) + 16;
}
if (ReadBit() == 0)
{
return ReadLiteral(5) + 32;
}
return DecodeUniform() + 64;
}
public TxMode ReadTxMode()
{
TxMode txMode = (TxMode)ReadLiteral(2);
if (txMode == TxMode.Allow32x32)
{
txMode += ReadBit();
}
return txMode;
}
public int ReadCoeff(
ReadOnlySpan<byte> probs,
int n,
ref ulong value,
ref int count,
ref uint range)
{
int val = 0;
for (int i = 0; i < n; ++i)
{
val = (val << 1) | ReadBool(probs[i], ref value, ref count, ref range);
}
return val;
}
public void DiffUpdateProb(ref byte p)
{
if (Read(Entropy.DiffUpdateProb) != 0)
{
p = (byte)DSubExp.InvRemapProb(DecodeTermSubexp(), p);
}
}
public void UpdateMvProbs(Span<byte> p, int n)
{
for (int i = 0; i < n; ++i)
{
if (Read(EntropyMv.UpdateProb) != 0)
{
p[i] = (byte)((ReadLiteral(7) << 1) | 1);
}
}
}
} }
} }

View File

@@ -13,42 +13,42 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// for (int i = 1; i < 32; ++i) // for (int i = 1; i < 32; ++i)
// Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64))); // Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64)));
// Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64) // Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64)
public const short CosPi164 = 16364; public const short CosPi1_64 = 16364;
public const short CosPi264 = 16305; public const short CosPi2_64 = 16305;
public const short CosPi364 = 16207; public const short CosPi3_64 = 16207;
public const short CosPi464 = 16069; public const short CosPi4_64 = 16069;
public const short CosPi564 = 15893; public const short CosPi5_64 = 15893;
public const short CosPi664 = 15679; public const short CosPi6_64 = 15679;
public const short CosPi764 = 15426; public const short CosPi7_64 = 15426;
public const short CosPi864 = 15137; public const short CosPi8_64 = 15137;
public const short CosPi964 = 14811; public const short CosPi9_64 = 14811;
public const short CosPi1064 = 14449; public const short CosPi10_64 = 14449;
public const short CosPi1164 = 14053; public const short CosPi11_64 = 14053;
public const short CosPi1264 = 13623; public const short CosPi12_64 = 13623;
public const short CosPi1364 = 13160; public const short CosPi13_64 = 13160;
public const short CosPi1464 = 12665; public const short CosPi14_64 = 12665;
public const short CosPi1564 = 12140; public const short CosPi15_64 = 12140;
public const short CosPi1664 = 11585; public const short CosPi16_64 = 11585;
public const short CosPi1764 = 11003; public const short CosPi17_64 = 11003;
public const short CosPi1864 = 10394; public const short CosPi18_64 = 10394;
public const short CosPi1964 = 9760; public const short CosPi19_64 = 9760;
public const short CosPi2064 = 9102; public const short CosPi20_64 = 9102;
public const short CosPi2164 = 8423; public const short CosPi21_64 = 8423;
public const short CosPi2264 = 7723; public const short CosPi22_64 = 7723;
public const short CosPi2364 = 7005; public const short CosPi23_64 = 7005;
public const short CosPi2464 = 6270; public const short CosPi24_64 = 6270;
public const short CosPi2564 = 5520; public const short CosPi25_64 = 5520;
public const short CosPi2664 = 4756; public const short CosPi26_64 = 4756;
public const short CosPi2764 = 3981; public const short CosPi27_64 = 3981;
public const short CosPi2864 = 3196; public const short CosPi28_64 = 3196;
public const short CosPi2964 = 2404; public const short CosPi29_64 = 2404;
public const short CosPi3064 = 1606; public const short CosPi30_64 = 1606;
public const short CosPi3164 = 804; public const short CosPi31_64 = 804;
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3 // 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
public const short SinPi19 = 5283; public const short SinPi1_9 = 5283;
public const short SinPi29 = 9929; public const short SinPi2_9 = 9929;
public const short SinPi39 = 13377; public const short SinPi3_9 = 13377;
public const short SinPi49 = 15212; public const short SinPi4_9 = 15212;
} }
} }

View File

@@ -1,623 +0,0 @@
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class Entropy
{
public const int DiffUpdateProb = 252;
// Coefficient token alphabet
public const int ZeroToken = 0; // 0 Extra Bits 0+0
public const int OneToken = 1; // 1 Extra Bits 0+1
public const int TwoToken = 2; // 2 Extra Bits 0+1
public const int ThreeToken = 3; // 3 Extra Bits 0+1
public const int FourToken = 4; // 4 Extra Bits 0+1
public const int Category1Token = 5; // 5-6 Extra Bits 1+1
public const int Category2Token = 6; // 7-10 Extra Bits 2+1
public const int Category3Token = 7; // 11-18 Extra Bits 3+1
public const int Category4Token = 8; // 19-34 Extra Bits 4+1
public const int Category5Token = 9; // 35-66 Extra Bits 5+1
public const int Category6Token = 10; // 67+ Extra Bits 14+1
public const int EobToken = 11; // EOB Extra Bits 0+0
public const int EntropyTokens = 12;
public const int RefTypes = 2; // intra=0, inter=1
/* Middle dimension reflects the coefficient position within the transform. */
public const int CoefBands = 6;
/* Inside dimension is measure of nearby complexity, that reflects the energy
of nearby coefficients are nonzero. For the first coefficient (DC, unless
block type is 0), we look at the (already encoded) blocks above and to the
left of the current block. The context index is then the number (0,1,or 2)
of these blocks having nonzero coefficients.
After decoding a coefficient, the measure is determined by the size of the
most recently decoded coefficient.
Note that the intuitive meaning of this measure changes as coefficients
are decoded, e.g., prior to the first token, a zero means that my neighbors
are empty while, after the first token, because of the use of end-of-block,
a zero means we just decoded a zero and hence guarantees that a non-zero
coefficient will appear later in this block. However, this shift
in meaning is perfectly OK because our context depends also on the
coefficient band (and since zigzag positions 0, 1, and 2 are in
distinct bands). */
public const int CoeffContexts = 6;
public static int BAND_COEFF_CONTEXTS(int band)
{
return band == 0 ? 3 : CoeffContexts;
}
public const int UnconstrainedNodes = 3;
public const int PivotNode = 2;
public const int Cat1MinVal = 5;
public const int Cat2MinVal = 7;
public const int Cat3MinVal = 11;
public const int Cat4MinVal = 19;
public const int Cat5MinVal = 35;
public const int Cat6MinVal = 67;
public static readonly byte[] Cat1Prob = { 159 };
public static readonly byte[] Cat2Prob = { 165, 145 };
public static readonly byte[] Cat3Prob = { 173, 148, 140 };
public static readonly byte[] Cat4Prob = { 176, 155, 140, 135 };
public static readonly byte[] Cat5Prob = { 180, 157, 141, 134, 130 };
public static readonly byte[] Cat6Prob =
{
254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
};
public static readonly byte[] Cat6ProbHigh12 =
{
255, 255, 255, 255, 254, 254, 54, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
};
public const int EobModelToken = 3;
private static readonly byte[] CoefbandTrans8x8Plus =
{
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
// beyond MAXBAND_INDEX+1 all values are filled as 5
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
};
private static readonly byte[] CoefbandTrans4x4 = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
public static readonly byte[][] Pareto8Full =
{
new byte[] { 3, 86, 128, 6, 86, 23, 88, 29 }, new byte[] { 6, 86, 128, 11, 87, 42, 91, 52 },
new byte[] { 9, 86, 129, 17, 88, 61, 94, 76 }, new byte[] { 12, 86, 129, 22, 88, 77, 97, 93 },
new byte[] { 15, 87, 129, 28, 89, 93, 100, 110 }, new byte[] { 17, 87, 129, 33, 90, 105, 103, 123 },
new byte[] { 20, 88, 130, 38, 91, 118, 106, 136 }, new byte[] { 23, 88, 130, 43, 91, 128, 108, 146 },
new byte[] { 26, 89, 131, 48, 92, 139, 111, 156 }, new byte[] { 28, 89, 131, 53, 93, 147, 114, 163 },
new byte[] { 31, 90, 131, 58, 94, 156, 117, 171 }, new byte[] { 34, 90, 131, 62, 94, 163, 119, 177 },
new byte[] { 37, 90, 132, 66, 95, 171, 122, 184 }, new byte[] { 39, 90, 132, 70, 96, 177, 124, 189 },
new byte[] { 42, 91, 132, 75, 97, 183, 127, 194 }, new byte[] { 44, 91, 132, 79, 97, 188, 129, 198 },
new byte[] { 47, 92, 133, 83, 98, 193, 132, 202 }, new byte[] { 49, 92, 133, 86, 99, 197, 134, 205 },
new byte[] { 52, 93, 133, 90, 100, 201, 137, 208 }, new byte[] { 54, 93, 133, 94, 100, 204, 139, 211 },
new byte[] { 57, 94, 134, 98, 101, 208, 142, 214 }, new byte[] { 59, 94, 134, 101, 102, 211, 144, 216 },
new byte[] { 62, 94, 135, 105, 103, 214, 146, 218 },
new byte[] { 64, 94, 135, 108, 103, 216, 148, 220 },
new byte[] { 66, 95, 135, 111, 104, 219, 151, 222 },
new byte[] { 68, 95, 135, 114, 105, 221, 153, 223 },
new byte[] { 71, 96, 136, 117, 106, 224, 155, 225 },
new byte[] { 73, 96, 136, 120, 106, 225, 157, 226 },
new byte[] { 76, 97, 136, 123, 107, 227, 159, 228 },
new byte[] { 78, 97, 136, 126, 108, 229, 160, 229 },
new byte[] { 80, 98, 137, 129, 109, 231, 162, 231 },
new byte[] { 82, 98, 137, 131, 109, 232, 164, 232 },
new byte[] { 84, 98, 138, 134, 110, 234, 166, 233 },
new byte[] { 86, 98, 138, 137, 111, 235, 168, 234 },
new byte[] { 89, 99, 138, 140, 112, 236, 170, 235 },
new byte[] { 91, 99, 138, 142, 112, 237, 171, 235 },
new byte[] { 93, 100, 139, 145, 113, 238, 173, 236 },
new byte[] { 95, 100, 139, 147, 114, 239, 174, 237 },
new byte[] { 97, 101, 140, 149, 115, 240, 176, 238 },
new byte[] { 99, 101, 140, 151, 115, 241, 177, 238 },
new byte[] { 101, 102, 140, 154, 116, 242, 179, 239 },
new byte[] { 103, 102, 140, 156, 117, 242, 180, 239 },
new byte[] { 105, 103, 141, 158, 118, 243, 182, 240 },
new byte[] { 107, 103, 141, 160, 118, 243, 183, 240 },
new byte[] { 109, 104, 141, 162, 119, 244, 185, 241 },
new byte[] { 111, 104, 141, 164, 119, 244, 186, 241 },
new byte[] { 113, 104, 142, 166, 120, 245, 187, 242 },
new byte[] { 114, 104, 142, 168, 121, 245, 188, 242 },
new byte[] { 116, 105, 143, 170, 122, 246, 190, 243 },
new byte[] { 118, 105, 143, 171, 122, 246, 191, 243 },
new byte[] { 120, 106, 143, 173, 123, 247, 192, 244 },
new byte[] { 121, 106, 143, 175, 124, 247, 193, 244 },
new byte[] { 123, 107, 144, 177, 125, 248, 195, 244 },
new byte[] { 125, 107, 144, 178, 125, 248, 196, 244 },
new byte[] { 127, 108, 145, 180, 126, 249, 197, 245 },
new byte[] { 128, 108, 145, 181, 127, 249, 198, 245 },
new byte[] { 130, 109, 145, 183, 128, 249, 199, 245 },
new byte[] { 132, 109, 145, 184, 128, 249, 200, 245 },
new byte[] { 134, 110, 146, 186, 129, 250, 201, 246 },
new byte[] { 135, 110, 146, 187, 130, 250, 202, 246 },
new byte[] { 137, 111, 147, 189, 131, 251, 203, 246 },
new byte[] { 138, 111, 147, 190, 131, 251, 204, 246 },
new byte[] { 140, 112, 147, 192, 132, 251, 205, 247 },
new byte[] { 141, 112, 147, 193, 132, 251, 206, 247 },
new byte[] { 143, 113, 148, 194, 133, 251, 207, 247 },
new byte[] { 144, 113, 148, 195, 134, 251, 207, 247 },
new byte[] { 146, 114, 149, 197, 135, 252, 208, 248 },
new byte[] { 147, 114, 149, 198, 135, 252, 209, 248 },
new byte[] { 149, 115, 149, 199, 136, 252, 210, 248 },
new byte[] { 150, 115, 149, 200, 137, 252, 210, 248 },
new byte[] { 152, 115, 150, 201, 138, 252, 211, 248 },
new byte[] { 153, 115, 150, 202, 138, 252, 212, 248 },
new byte[] { 155, 116, 151, 204, 139, 253, 213, 249 },
new byte[] { 156, 116, 151, 205, 139, 253, 213, 249 },
new byte[] { 158, 117, 151, 206, 140, 253, 214, 249 },
new byte[] { 159, 117, 151, 207, 141, 253, 215, 249 },
new byte[] { 161, 118, 152, 208, 142, 253, 216, 249 },
new byte[] { 162, 118, 152, 209, 142, 253, 216, 249 },
new byte[] { 163, 119, 153, 210, 143, 253, 217, 249 },
new byte[] { 164, 119, 153, 211, 143, 253, 217, 249 },
new byte[] { 166, 120, 153, 212, 144, 254, 218, 250 },
new byte[] { 167, 120, 153, 212, 145, 254, 219, 250 },
new byte[] { 168, 121, 154, 213, 146, 254, 220, 250 },
new byte[] { 169, 121, 154, 214, 146, 254, 220, 250 },
new byte[] { 171, 122, 155, 215, 147, 254, 221, 250 },
new byte[] { 172, 122, 155, 216, 147, 254, 221, 250 },
new byte[] { 173, 123, 155, 217, 148, 254, 222, 250 },
new byte[] { 174, 123, 155, 217, 149, 254, 222, 250 },
new byte[] { 176, 124, 156, 218, 150, 254, 223, 250 },
new byte[] { 177, 124, 156, 219, 150, 254, 223, 250 },
new byte[] { 178, 125, 157, 220, 151, 254, 224, 251 },
new byte[] { 179, 125, 157, 220, 151, 254, 224, 251 },
new byte[] { 180, 126, 157, 221, 152, 254, 225, 251 },
new byte[] { 181, 126, 157, 221, 152, 254, 225, 251 },
new byte[] { 183, 127, 158, 222, 153, 254, 226, 251 },
new byte[] { 184, 127, 158, 223, 154, 254, 226, 251 },
new byte[] { 185, 128, 159, 224, 155, 255, 227, 251 },
new byte[] { 186, 128, 159, 224, 155, 255, 227, 251 },
new byte[] { 187, 129, 160, 225, 156, 255, 228, 251 },
new byte[] { 188, 130, 160, 225, 156, 255, 228, 251 },
new byte[] { 189, 131, 160, 226, 157, 255, 228, 251 },
new byte[] { 190, 131, 160, 226, 158, 255, 228, 251 },
new byte[] { 191, 132, 161, 227, 159, 255, 229, 251 },
new byte[] { 192, 132, 161, 227, 159, 255, 229, 251 },
new byte[] { 193, 133, 162, 228, 160, 255, 230, 252 },
new byte[] { 194, 133, 162, 229, 160, 255, 230, 252 },
new byte[] { 195, 134, 163, 230, 161, 255, 231, 252 },
new byte[] { 196, 134, 163, 230, 161, 255, 231, 252 },
new byte[] { 197, 135, 163, 231, 162, 255, 231, 252 },
new byte[] { 198, 135, 163, 231, 162, 255, 231, 252 },
new byte[] { 199, 136, 164, 232, 163, 255, 232, 252 },
new byte[] { 200, 136, 164, 232, 164, 255, 232, 252 },
new byte[] { 201, 137, 165, 233, 165, 255, 233, 252 },
new byte[] { 201, 137, 165, 233, 165, 255, 233, 252 },
new byte[] { 202, 138, 166, 233, 166, 255, 233, 252 },
new byte[] { 203, 138, 166, 233, 166, 255, 233, 252 },
new byte[] { 204, 139, 166, 234, 167, 255, 234, 252 },
new byte[] { 205, 139, 166, 234, 167, 255, 234, 252 },
new byte[] { 206, 140, 167, 235, 168, 255, 235, 252 },
new byte[] { 206, 140, 167, 235, 168, 255, 235, 252 },
new byte[] { 207, 141, 168, 236, 169, 255, 235, 252 },
new byte[] { 208, 141, 168, 236, 170, 255, 235, 252 },
new byte[] { 209, 142, 169, 237, 171, 255, 236, 252 },
new byte[] { 209, 143, 169, 237, 171, 255, 236, 252 },
new byte[] { 210, 144, 169, 237, 172, 255, 236, 252 },
new byte[] { 211, 144, 169, 237, 172, 255, 236, 252 },
new byte[] { 212, 145, 170, 238, 173, 255, 237, 252 },
new byte[] { 213, 145, 170, 238, 173, 255, 237, 252 },
new byte[] { 214, 146, 171, 239, 174, 255, 237, 253 },
new byte[] { 214, 146, 171, 239, 174, 255, 237, 253 },
new byte[] { 215, 147, 172, 240, 175, 255, 238, 253 },
new byte[] { 215, 147, 172, 240, 175, 255, 238, 253 },
new byte[] { 216, 148, 173, 240, 176, 255, 238, 253 },
new byte[] { 217, 148, 173, 240, 176, 255, 238, 253 },
new byte[] { 218, 149, 173, 241, 177, 255, 239, 253 },
new byte[] { 218, 149, 173, 241, 178, 255, 239, 253 },
new byte[] { 219, 150, 174, 241, 179, 255, 239, 253 },
new byte[] { 219, 151, 174, 241, 179, 255, 239, 253 },
new byte[] { 220, 152, 175, 242, 180, 255, 240, 253 },
new byte[] { 221, 152, 175, 242, 180, 255, 240, 253 },
new byte[] { 222, 153, 176, 242, 181, 255, 240, 253 },
new byte[] { 222, 153, 176, 242, 181, 255, 240, 253 },
new byte[] { 223, 154, 177, 243, 182, 255, 240, 253 },
new byte[] { 223, 154, 177, 243, 182, 255, 240, 253 },
new byte[] { 224, 155, 178, 244, 183, 255, 241, 253 },
new byte[] { 224, 155, 178, 244, 183, 255, 241, 253 },
new byte[] { 225, 156, 178, 244, 184, 255, 241, 253 },
new byte[] { 225, 157, 178, 244, 184, 255, 241, 253 },
new byte[] { 226, 158, 179, 244, 185, 255, 242, 253 },
new byte[] { 227, 158, 179, 244, 185, 255, 242, 253 },
new byte[] { 228, 159, 180, 245, 186, 255, 242, 253 },
new byte[] { 228, 159, 180, 245, 186, 255, 242, 253 },
new byte[] { 229, 160, 181, 245, 187, 255, 242, 253 },
new byte[] { 229, 160, 181, 245, 187, 255, 242, 253 },
new byte[] { 230, 161, 182, 246, 188, 255, 243, 253 },
new byte[] { 230, 162, 182, 246, 188, 255, 243, 253 },
new byte[] { 231, 163, 183, 246, 189, 255, 243, 253 },
new byte[] { 231, 163, 183, 246, 189, 255, 243, 253 },
new byte[] { 232, 164, 184, 247, 190, 255, 243, 253 },
new byte[] { 232, 164, 184, 247, 190, 255, 243, 253 },
new byte[] { 233, 165, 185, 247, 191, 255, 244, 253 },
new byte[] { 233, 165, 185, 247, 191, 255, 244, 253 },
new byte[] { 234, 166, 185, 247, 192, 255, 244, 253 },
new byte[] { 234, 167, 185, 247, 192, 255, 244, 253 },
new byte[] { 235, 168, 186, 248, 193, 255, 244, 253 },
new byte[] { 235, 168, 186, 248, 193, 255, 244, 253 },
new byte[] { 236, 169, 187, 248, 194, 255, 244, 253 },
new byte[] { 236, 169, 187, 248, 194, 255, 244, 253 },
new byte[] { 236, 170, 188, 248, 195, 255, 245, 253 },
new byte[] { 236, 170, 188, 248, 195, 255, 245, 253 },
new byte[] { 237, 171, 189, 249, 196, 255, 245, 254 },
new byte[] { 237, 172, 189, 249, 196, 255, 245, 254 },
new byte[] { 238, 173, 190, 249, 197, 255, 245, 254 },
new byte[] { 238, 173, 190, 249, 197, 255, 245, 254 },
new byte[] { 239, 174, 191, 249, 198, 255, 245, 254 },
new byte[] { 239, 174, 191, 249, 198, 255, 245, 254 },
new byte[] { 240, 175, 192, 249, 199, 255, 246, 254 },
new byte[] { 240, 176, 192, 249, 199, 255, 246, 254 },
new byte[] { 240, 177, 193, 250, 200, 255, 246, 254 },
new byte[] { 240, 177, 193, 250, 200, 255, 246, 254 },
new byte[] { 241, 178, 194, 250, 201, 255, 246, 254 },
new byte[] { 241, 178, 194, 250, 201, 255, 246, 254 },
new byte[] { 242, 179, 195, 250, 202, 255, 246, 254 },
new byte[] { 242, 180, 195, 250, 202, 255, 246, 254 },
new byte[] { 242, 181, 196, 250, 203, 255, 247, 254 },
new byte[] { 242, 181, 196, 250, 203, 255, 247, 254 },
new byte[] { 243, 182, 197, 251, 204, 255, 247, 254 },
new byte[] { 243, 183, 197, 251, 204, 255, 247, 254 },
new byte[] { 244, 184, 198, 251, 205, 255, 247, 254 },
new byte[] { 244, 184, 198, 251, 205, 255, 247, 254 },
new byte[] { 244, 185, 199, 251, 206, 255, 247, 254 },
new byte[] { 244, 185, 199, 251, 206, 255, 247, 254 },
new byte[] { 245, 186, 200, 251, 207, 255, 247, 254 },
new byte[] { 245, 187, 200, 251, 207, 255, 247, 254 },
new byte[] { 246, 188, 201, 252, 207, 255, 248, 254 },
new byte[] { 246, 188, 201, 252, 207, 255, 248, 254 },
new byte[] { 246, 189, 202, 252, 208, 255, 248, 254 },
new byte[] { 246, 190, 202, 252, 208, 255, 248, 254 },
new byte[] { 247, 191, 203, 252, 209, 255, 248, 254 },
new byte[] { 247, 191, 203, 252, 209, 255, 248, 254 },
new byte[] { 247, 192, 204, 252, 210, 255, 248, 254 },
new byte[] { 247, 193, 204, 252, 210, 255, 248, 254 },
new byte[] { 248, 194, 205, 252, 211, 255, 248, 254 },
new byte[] { 248, 194, 205, 252, 211, 255, 248, 254 },
new byte[] { 248, 195, 206, 252, 212, 255, 249, 254 },
new byte[] { 248, 196, 206, 252, 212, 255, 249, 254 },
new byte[] { 249, 197, 207, 253, 213, 255, 249, 254 },
new byte[] { 249, 197, 207, 253, 213, 255, 249, 254 },
new byte[] { 249, 198, 208, 253, 214, 255, 249, 254 },
new byte[] { 249, 199, 209, 253, 214, 255, 249, 254 },
new byte[] { 250, 200, 210, 253, 215, 255, 249, 254 },
new byte[] { 250, 200, 210, 253, 215, 255, 249, 254 },
new byte[] { 250, 201, 211, 253, 215, 255, 249, 254 },
new byte[] { 250, 202, 211, 253, 215, 255, 249, 254 },
new byte[] { 250, 203, 212, 253, 216, 255, 249, 254 },
new byte[] { 250, 203, 212, 253, 216, 255, 249, 254 },
new byte[] { 251, 204, 213, 253, 217, 255, 250, 254 },
new byte[] { 251, 205, 213, 253, 217, 255, 250, 254 },
new byte[] { 251, 206, 214, 254, 218, 255, 250, 254 },
new byte[] { 251, 206, 215, 254, 218, 255, 250, 254 },
new byte[] { 252, 207, 216, 254, 219, 255, 250, 254 },
new byte[] { 252, 208, 216, 254, 219, 255, 250, 254 },
new byte[] { 252, 209, 217, 254, 220, 255, 250, 254 },
new byte[] { 252, 210, 217, 254, 220, 255, 250, 254 },
new byte[] { 252, 211, 218, 254, 221, 255, 250, 254 },
new byte[] { 252, 212, 218, 254, 221, 255, 250, 254 },
new byte[] { 253, 213, 219, 254, 222, 255, 250, 254 },
new byte[] { 253, 213, 220, 254, 222, 255, 250, 254 },
new byte[] { 253, 214, 221, 254, 223, 255, 250, 254 },
new byte[] { 253, 215, 221, 254, 223, 255, 250, 254 },
new byte[] { 253, 216, 222, 254, 224, 255, 251, 254 },
new byte[] { 253, 217, 223, 254, 224, 255, 251, 254 },
new byte[] { 253, 218, 224, 254, 225, 255, 251, 254 },
new byte[] { 253, 219, 224, 254, 225, 255, 251, 254 },
new byte[] { 254, 220, 225, 254, 225, 255, 251, 254 },
new byte[] { 254, 221, 226, 254, 225, 255, 251, 254 },
new byte[] { 254, 222, 227, 255, 226, 255, 251, 254 },
new byte[] { 254, 223, 227, 255, 226, 255, 251, 254 },
new byte[] { 254, 224, 228, 255, 227, 255, 251, 254 },
new byte[] { 254, 225, 229, 255, 227, 255, 251, 254 },
new byte[] { 254, 226, 230, 255, 228, 255, 251, 254 },
new byte[] { 254, 227, 230, 255, 229, 255, 251, 254 },
new byte[] { 255, 228, 231, 255, 230, 255, 251, 254 },
new byte[] { 255, 229, 232, 255, 230, 255, 251, 254 },
new byte[] { 255, 230, 233, 255, 231, 255, 252, 254 },
new byte[] { 255, 231, 234, 255, 231, 255, 252, 254 },
new byte[] { 255, 232, 235, 255, 232, 255, 252, 254 },
new byte[] { 255, 233, 236, 255, 232, 255, 252, 254 },
new byte[] { 255, 235, 237, 255, 233, 255, 252, 254 },
new byte[] { 255, 236, 238, 255, 234, 255, 252, 254 },
new byte[] { 255, 238, 240, 255, 235, 255, 252, 255 },
new byte[] { 255, 239, 241, 255, 235, 255, 252, 254 },
new byte[] { 255, 241, 243, 255, 236, 255, 252, 254 },
new byte[] { 255, 243, 245, 255, 237, 255, 252, 254 },
new byte[] { 255, 246, 247, 255, 239, 255, 253, 255 }
};
internal static readonly byte[] DefaultCoefProbs4x4 =
{
// Y plane
// Intra
// Band 0
195, 29, 183, 84, 49, 136, 8, 42, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
31, 107, 169, 35, 99, 159, 17, 82, 140, 8, 66, 114, 2, 44, 76, 1, 19, 32,
// Band 2
40, 132, 201, 29, 114, 187, 13, 91, 157, 7, 75, 127, 3, 58, 95, 1, 28, 47,
// Band 3
69, 142, 221, 42, 122, 201, 15, 91, 159, 6, 67, 121, 1, 42, 77, 1, 17, 31,
// Band 4
102, 148, 228, 67, 117, 204, 17, 82, 154, 6, 59, 114, 2, 39, 75, 1, 15, 29,
// Band 5
156, 57, 233, 119, 57, 212, 58, 48, 163, 29, 40, 124, 12, 30, 81, 3, 12, 31,
// Inter
// Band 0
191, 107, 226, 124, 117, 204, 25, 99, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
29, 148, 210, 37, 126, 194, 8, 93, 157, 2, 68, 118, 1, 39, 69, 1, 17, 33,
// Band 2
41, 151, 213, 27, 123, 193, 3, 82, 144, 1, 58, 105, 1, 32, 60, 1, 13, 26,
// Band 3
59, 159, 220, 23, 126, 198, 4, 88, 151, 1, 66, 114, 1, 38, 71, 1, 18, 34,
// Band 4
114, 136, 232, 51, 114, 207, 11, 83, 155, 3, 56, 105, 1, 33, 65, 1, 17, 34,
// Band 5
149, 65, 234, 121, 57, 215, 61, 49, 166, 28, 36, 114, 12, 25, 76, 3, 16, 42,
// UV plane
// Intra
// Band 0
214, 49, 220, 132, 63, 188, 42, 65, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
85, 137, 221, 104, 131, 216, 49, 111, 192, 21, 87, 155, 2, 49, 87, 1, 16, 28,
// Band 2
89, 163, 230, 90, 137, 220, 29, 100, 183, 10, 70, 135, 2, 42, 81, 1, 17, 33,
// Band 3
108, 167, 237, 55, 133, 222, 15, 97, 179, 4, 72, 135, 1, 45, 85, 1, 19, 38,
// Band 4
124, 146, 240, 66, 124, 224, 17, 88, 175, 4, 58, 122, 1, 36, 75, 1, 18, 37,
// Band 5
141, 79, 241, 126, 70, 227, 66, 58, 182, 30, 44, 136, 12, 34, 96, 2, 20, 47,
// Inter
// Band 0
229, 99, 249, 143, 111, 235, 46, 109, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
82, 158, 236, 94, 146, 224, 25, 117, 191, 9, 87, 149, 3, 56, 99, 1, 33, 57,
// Band 2
83, 167, 237, 68, 145, 222, 10, 103, 177, 2, 72, 131, 1, 41, 79, 1, 20, 39,
// Band 3
99, 167, 239, 47, 141, 224, 10, 104, 178, 2, 73, 133, 1, 44, 85, 1, 22, 47,
// Band 4
127, 145, 243, 71, 129, 228, 17, 93, 177, 3, 61, 124, 1, 41, 84, 1, 21, 52,
// Band 5
157, 78, 244, 140, 72, 231, 69, 58, 184, 31, 44, 137, 14, 38, 105, 8, 23, 61
};
internal static readonly byte[] DefaultCoefProbs8x8 =
{
// Y plane
// Intra
// Band 0
125, 34, 187, 52, 41, 133, 6, 31, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
37, 109, 153, 51, 102, 147, 23, 87, 128, 8, 67, 101, 1, 41, 63, 1, 19, 29,
// Band 2
31, 154, 185, 17, 127, 175, 6, 96, 145, 2, 73, 114, 1, 51, 82, 1, 28, 45,
// Band 3
23, 163, 200, 10, 131, 185, 2, 93, 148, 1, 67, 111, 1, 41, 69, 1, 14, 24,
// Band 4
29, 176, 217, 12, 145, 201, 3, 101, 156, 1, 69, 111, 1, 39, 63, 1, 14, 23,
// Band 5
57, 192, 233, 25, 154, 215, 6, 109, 167, 3, 78, 118, 1, 48, 69, 1, 21, 29,
// Inter
// Band 0
202, 105, 245, 108, 106, 216, 18, 90, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
33, 172, 219, 64, 149, 206, 14, 117, 177, 5, 90, 141, 2, 61, 95, 1, 37, 57,
// Band 2
33, 179, 220, 11, 140, 198, 1, 89, 148, 1, 60, 104, 1, 33, 57, 1, 12, 21,
// Band 3
30, 181, 221, 8, 141, 198, 1, 87, 145, 1, 58, 100, 1, 31, 55, 1, 12, 20,
// Band 4
32, 186, 224, 7, 142, 198, 1, 86, 143, 1, 58, 100, 1, 31, 55, 1, 12, 22,
// Band 5
57, 192, 227, 20, 143, 204, 3, 96, 154, 1, 68, 112, 1, 42, 69, 1, 19, 32,
// UV plane
// Intra
// Band 0
212, 35, 215, 113, 47, 169, 29, 48, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
74, 129, 203, 106, 120, 203, 49, 107, 178, 19, 84, 144, 4, 50, 84, 1, 15, 25,
// Band 2
71, 172, 217, 44, 141, 209, 15, 102, 173, 6, 76, 133, 2, 51, 89, 1, 24, 42,
// Band 3
64, 185, 231, 31, 148, 216, 8, 103, 175, 3, 74, 131, 1, 46, 81, 1, 18, 30,
// Band 4
65, 196, 235, 25, 157, 221, 5, 105, 174, 1, 67, 120, 1, 38, 69, 1, 15, 30,
// Band 5
65, 204, 238, 30, 156, 224, 7, 107, 177, 2, 70, 124, 1, 42, 73, 1, 18, 34,
// Inter
// Band 0
225, 86, 251, 144, 104, 235, 42, 99, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
85, 175, 239, 112, 165, 229, 29, 136, 200, 12, 103, 162, 6, 77, 123, 2, 53, 84,
// Band 2
75, 183, 239, 30, 155, 221, 3, 106, 171, 1, 74, 128, 1, 44, 76, 1, 17, 28,
// Band 3
73, 185, 240, 27, 159, 222, 2, 107, 172, 1, 75, 127, 1, 42, 73, 1, 17, 29,
// Band 4
62, 190, 238, 21, 159, 222, 2, 107, 172, 1, 72, 122, 1, 40, 71, 1, 18, 32,
// Band 5
61, 199, 240, 27, 161, 226, 4, 113, 180, 1, 76, 129, 1, 46, 80, 1, 23, 41
};
internal static readonly byte[] DefaultCoefProbs16x16 =
{
// Y plane
// Intra
// Band 0
7, 27, 153, 5, 30, 95, 1, 16, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
50, 75, 127, 57, 75, 124, 27, 67, 108, 10, 54, 86, 1, 33, 52, 1, 12, 18,
// Band 2
43, 125, 151, 26, 108, 148, 7, 83, 122, 2, 59, 89, 1, 38, 60, 1, 17, 27,
// Band 3
23, 144, 163, 13, 112, 154, 2, 75, 117, 1, 50, 81, 1, 31, 51, 1, 14, 23,
// Band 4
18, 162, 185, 6, 123, 171, 1, 78, 125, 1, 51, 86, 1, 31, 54, 1, 14, 23,
// Band 5
15, 199, 227, 3, 150, 204, 1, 91, 146, 1, 55, 95, 1, 30, 53, 1, 11, 20,
// Inter
// Band 0
19, 55, 240, 19, 59, 196, 3, 52, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
41, 166, 207, 104, 153, 199, 31, 123, 181, 14, 101, 152, 5, 72, 106, 1, 36, 52,
// Band 2
35, 176, 211, 12, 131, 190, 2, 88, 144, 1, 60, 101, 1, 36, 60, 1, 16, 28,
// Band 3
28, 183, 213, 8, 134, 191, 1, 86, 142, 1, 56, 96, 1, 30, 53, 1, 12, 20,
// Band 4
20, 190, 215, 4, 135, 192, 1, 84, 139, 1, 53, 91, 1, 28, 49, 1, 11, 20,
// Band 5
13, 196, 216, 2, 137, 192, 1, 86, 143, 1, 57, 99, 1, 32, 56, 1, 13, 24,
// UV plane
// Intra
// Band 0
211, 29, 217, 96, 47, 156, 22, 43, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
78, 120, 193, 111, 116, 186, 46, 102, 164, 15, 80, 128, 2, 49, 76, 1, 18, 28,
// Band 2
71, 161, 203, 42, 132, 192, 10, 98, 150, 3, 69, 109, 1, 44, 70, 1, 18, 29,
// Band 3
57, 186, 211, 30, 140, 196, 4, 93, 146, 1, 62, 102, 1, 38, 65, 1, 16, 27,
// Band 4
47, 199, 217, 14, 145, 196, 1, 88, 142, 1, 57, 98, 1, 36, 62, 1, 15, 26,
// Band 5
26, 219, 229, 5, 155, 207, 1, 94, 151, 1, 60, 104, 1, 36, 62, 1, 16, 28,
// Inter
// Band 0
233, 29, 248, 146, 47, 220, 43, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
100, 163, 232, 179, 161, 222, 63, 142, 204, 37, 113, 174, 26, 89, 137, 18, 68, 97,
// Band 2
85, 181, 230, 32, 146, 209, 7, 100, 164, 3, 71, 121, 1, 45, 77, 1, 18, 30,
// Band 3
65, 187, 230, 20, 148, 207, 2, 97, 159, 1, 68, 116, 1, 40, 70, 1, 14, 29,
// Band 4
40, 194, 227, 8, 147, 204, 1, 94, 155, 1, 65, 112, 1, 39, 66, 1, 14, 26,
// Band 5
16, 208, 228, 3, 151, 207, 1, 98, 160, 1, 67, 117, 1, 41, 74, 1, 17, 31
};
internal static readonly byte[] DefaultCoefProbs32x32 =
{
// Y plane
// Intra
// Band 0
17, 38, 140, 7, 34, 80, 1, 17, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
37, 75, 128, 41, 76, 128, 26, 66, 116, 12, 52, 94, 2, 32, 55, 1, 10, 16,
// Band 2
50, 127, 154, 37, 109, 152, 16, 82, 121, 5, 59, 85, 1, 35, 54, 1, 13, 20,
// Band 3
40, 142, 167, 17, 110, 157, 2, 71, 112, 1, 44, 72, 1, 27, 45, 1, 11, 17,
// Band 4
30, 175, 188, 9, 124, 169, 1, 74, 116, 1, 48, 78, 1, 30, 49, 1, 11, 18,
// Band 5
10, 222, 223, 2, 150, 194, 1, 83, 128, 1, 48, 79, 1, 27, 45, 1, 11, 17,
// Inter
// Band 0
36, 41, 235, 29, 36, 193, 10, 27, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
85, 165, 222, 177, 162, 215, 110, 135, 195, 57, 113, 168, 23, 83, 120, 10, 49, 61,
// Band 2
85, 190, 223, 36, 139, 200, 5, 90, 146, 1, 60, 103, 1, 38, 65, 1, 18, 30,
// Band 3
72, 202, 223, 23, 141, 199, 2, 86, 140, 1, 56, 97, 1, 36, 61, 1, 16, 27,
// Band 4
55, 218, 225, 13, 145, 200, 1, 86, 141, 1, 57, 99, 1, 35, 61, 1, 13, 22,
// Band 5
15, 235, 212, 1, 132, 184, 1, 84, 139, 1, 57, 97, 1, 34, 56, 1, 14, 23,
// UV plane
// Intra
// Band 0
181, 21, 201, 61, 37, 123, 10, 38, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
47, 106, 172, 95, 104, 173, 42, 93, 159, 18, 77, 131, 4, 50, 81, 1, 17, 23,
// Band 2
62, 147, 199, 44, 130, 189, 28, 102, 154, 18, 75, 115, 2, 44, 65, 1, 12, 19,
// Band 3
55, 153, 210, 24, 130, 194, 3, 93, 146, 1, 61, 97, 1, 31, 50, 1, 10, 16,
// Band 4
49, 186, 223, 17, 148, 204, 1, 96, 142, 1, 53, 83, 1, 26, 44, 1, 11, 17,
// Band 5
13, 217, 212, 2, 136, 180, 1, 78, 124, 1, 50, 83, 1, 29, 49, 1, 14, 23,
// Inter
// Band 0
197, 13, 247, 82, 17, 222, 25, 17, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// Band 1
126, 186, 247, 234, 191, 243, 176, 177, 234, 104, 158, 220, 66, 128, 186, 55, 90, 137,
// Band 2
111, 197, 242, 46, 158, 219, 9, 104, 171, 2, 65, 125, 1, 44, 80, 1, 17, 91,
// Band 3
104, 208, 245, 39, 168, 224, 3, 109, 162, 1, 79, 124, 1, 50, 102, 1, 43, 102,
// Band 4
84, 220, 246, 31, 177, 231, 2, 115, 180, 1, 79, 134, 1, 55, 77, 1, 60, 79,
// Band 5
43, 243, 240, 8, 180, 217, 1, 115, 166, 1, 84, 121, 1, 51, 67, 1, 16, 6
};
public static byte[] GetBandTranslate(int txSize)
{
return txSize == (int)TxSize.Tx4x4 ? CoefbandTrans4x4 : CoefbandTrans8x8Plus;
}
public static void CopyProbs<T>(ref T dest, ReadOnlySpan<byte> probs) where T : unmanaged
{
if (Unsafe.SizeOf<T>() != probs.Length)
{
throw new Exception("size mismatch expected: " + probs.Length + " got: " + Unsafe.SizeOf<T>());
}
probs.CopyTo(MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref dest, 1)));
}
internal const int CoefCountSat = 24;
internal const int CoefMaxUpdateFactor = 112;
internal const int CoefCountSatKey = 24;
internal const int CoefMaxUpdateFactorKey = 112;
internal const int CoefCountSatAfterKey = 24;
internal const int CoefMaxUpdateFactorAfterKey = 128;
}
}

View File

@@ -1,400 +0,0 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video;
using System;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal class EntropyMode
{
public const int BlockSizeGroups = 4;
public const int TxSizeContexts = 2;
public static readonly byte[][][] KfYModeProb =
{
new[]
{
// above = dc
new byte[] { 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc
new byte[] { 92, 45, 102, 136, 116, 180, 74, 90, 100 }, // left = v
new byte[] { 73, 32, 19, 187, 222, 215, 46, 34, 100 }, // left = h
new byte[] { 91, 30, 32, 116, 121, 186, 93, 86, 94 }, // left = d45
new byte[] { 72, 35, 36, 149, 68, 206, 68, 63, 105 }, // left = d135
new byte[] { 73, 31, 28, 138, 57, 124, 55, 122, 151 }, // left = d117
new byte[] { 67, 23, 21, 140, 126, 197, 40, 37, 171 }, // left = d153
new byte[] { 86, 27, 28, 128, 154, 212, 45, 43, 53 }, // left = d207
new byte[] { 74, 32, 27, 107, 86, 160, 63, 134, 102 }, // left = d63
new byte[] { 59, 67, 44, 140, 161, 202, 78, 67, 119 } // left = tm
},
new[]
{
// above = v
new byte[] { 63, 36, 126, 146, 123, 158, 60, 90, 96 }, // left = dc
new byte[] { 43, 46, 168, 134, 107, 128, 69, 142, 92 }, // left = v
new byte[] { 44, 29, 68, 159, 201, 177, 50, 57, 77 }, // left = h
new byte[] { 58, 38, 76, 114, 97, 172, 78, 133, 92 }, // left = d45
new byte[] { 46, 41, 76, 140, 63, 184, 69, 112, 57 }, // left = d135
new byte[] { 38, 32, 85, 140, 46, 112, 54, 151, 133 }, // left = d117
new byte[] { 39, 27, 61, 131, 110, 175, 44, 75, 136 }, // left = d153
new byte[] { 52, 30, 74, 113, 130, 175, 51, 64, 58 }, // left = d207
new byte[] { 47, 35, 80, 100, 74, 143, 64, 163, 74 }, // left = d63
new byte[] { 36, 61, 116, 114, 128, 162, 80, 125, 82 } // left = tm
},
new[]
{
// above = h
new byte[] { 82, 26, 26, 171, 208, 204, 44, 32, 105 }, // left = dc
new byte[] { 55, 44, 68, 166, 179, 192, 57, 57, 108 }, // left = v
new byte[] { 42, 26, 11, 199, 241, 228, 23, 15, 85 }, // left = h
new byte[] { 68, 42, 19, 131, 160, 199, 55, 52, 83 }, // left = d45
new byte[] { 58, 50, 25, 139, 115, 232, 39, 52, 118 }, // left = d135
new byte[] { 50, 35, 33, 153, 104, 162, 64, 59, 131 }, // left = d117
new byte[] { 44, 24, 16, 150, 177, 202, 33, 19, 156 }, // left = d153
new byte[] { 55, 27, 12, 153, 203, 218, 26, 27, 49 }, // left = d207
new byte[] { 53, 49, 21, 110, 116, 168, 59, 80, 76 }, // left = d63
new byte[] { 38, 72, 19, 168, 203, 212, 50, 50, 107 } // left = tm
},
new[]
{
// above = d45
new byte[] { 103, 26, 36, 129, 132, 201, 83, 80, 93 }, // left = dc
new byte[] { 59, 38, 83, 112, 103, 162, 98, 136, 90 }, // left = v
new byte[] { 62, 30, 23, 158, 200, 207, 59, 57, 50 }, // left = h
new byte[] { 67, 30, 29, 84, 86, 191, 102, 91, 59 }, // left = d45
new byte[] { 60, 32, 33, 112, 71, 220, 64, 89, 104 }, // left = d135
new byte[] { 53, 26, 34, 130, 56, 149, 84, 120, 103 }, // left = d117
new byte[] { 53, 21, 23, 133, 109, 210, 56, 77, 172 }, // left = d153
new byte[] { 77, 19, 29, 112, 142, 228, 55, 66, 36 }, // left = d207
new byte[] { 61, 29, 29, 93, 97, 165, 83, 175, 162 }, // left = d63
new byte[] { 47, 47, 43, 114, 137, 181, 100, 99, 95 } // left = tm
},
new[]
{
// above = d135
new byte[] { 69, 23, 29, 128, 83, 199, 46, 44, 101 }, // left = dc
new byte[] { 53, 40, 55, 139, 69, 183, 61, 80, 110 }, // left = v
new byte[] { 40, 29, 19, 161, 180, 207, 43, 24, 91 }, // left = h
new byte[] { 60, 34, 19, 105, 61, 198, 53, 64, 89 }, // left = d45
new byte[] { 52, 31, 22, 158, 40, 209, 58, 62, 89 }, // left = d135
new byte[] { 44, 31, 29, 147, 46, 158, 56, 102, 198 }, // left = d117
new byte[] { 35, 19, 12, 135, 87, 209, 41, 45, 167 }, // left = d153
new byte[] { 55, 25, 21, 118, 95, 215, 38, 39, 66 }, // left = d207
new byte[] { 51, 38, 25, 113, 58, 164, 70, 93, 97 }, // left = d63
new byte[] { 47, 54, 34, 146, 108, 203, 72, 103, 151 } // left = tm
},
new[]
{
// above = d117
new byte[] { 64, 19, 37, 156, 66, 138, 49, 95, 133 }, // left = dc
new byte[] { 46, 27, 80, 150, 55, 124, 55, 121, 135 }, // left = v
new byte[] { 36, 23, 27, 165, 149, 166, 54, 64, 118 }, // left = h
new byte[] { 53, 21, 36, 131, 63, 163, 60, 109, 81 }, // left = d45
new byte[] { 40, 26, 35, 154, 40, 185, 51, 97, 123 }, // left = d135
new byte[] { 35, 19, 34, 179, 19, 97, 48, 129, 124 }, // left = d117
new byte[] { 36, 20, 26, 136, 62, 164, 33, 77, 154 }, // left = d153
new byte[] { 45, 18, 32, 130, 90, 157, 40, 79, 91 }, // left = d207
new byte[] { 45, 26, 28, 129, 45, 129, 49, 147, 123 }, // left = d63
new byte[] { 38, 44, 51, 136, 74, 162, 57, 97, 121 } // left = tm
},
new[]
{
// above = d153
new byte[] { 75, 17, 22, 136, 138, 185, 32, 34, 166 }, // left = dc
new byte[] { 56, 39, 58, 133, 117, 173, 48, 53, 187 }, // left = v
new byte[] { 35, 21, 12, 161, 212, 207, 20, 23, 145 }, // left = h
new byte[] { 56, 29, 19, 117, 109, 181, 55, 68, 112 }, // left = d45
new byte[] { 47, 29, 17, 153, 64, 220, 59, 51, 114 }, // left = d135
new byte[] { 46, 16, 24, 136, 76, 147, 41, 64, 172 }, // left = d117
new byte[] { 34, 17, 11, 108, 152, 187, 13, 15, 209 }, // left = d153
new byte[] { 51, 24, 14, 115, 133, 209, 32, 26, 104 }, // left = d207
new byte[] { 55, 30, 18, 122, 79, 179, 44, 88, 116 }, // left = d63
new byte[] { 37, 49, 25, 129, 168, 164, 41, 54, 148 } // left = tm
},
new[]
{
// above = d207
new byte[] { 82, 22, 32, 127, 143, 213, 39, 41, 70 }, // left = dc
new byte[] { 62, 44, 61, 123, 105, 189, 48, 57, 64 }, // left = v
new byte[] { 47, 25, 17, 175, 222, 220, 24, 30, 86 }, // left = h
new byte[] { 68, 36, 17, 106, 102, 206, 59, 74, 74 }, // left = d45
new byte[] { 57, 39, 23, 151, 68, 216, 55, 63, 58 }, // left = d135
new byte[] { 49, 30, 35, 141, 70, 168, 82, 40, 115 }, // left = d117
new byte[] { 51, 25, 15, 136, 129, 202, 38, 35, 139 }, // left = d153
new byte[] { 68, 26, 16, 111, 141, 215, 29, 28, 28 }, // left = d207
new byte[] { 59, 39, 19, 114, 75, 180, 77, 104, 42 }, // left = d63
new byte[] { 40, 61, 26, 126, 152, 206, 61, 59, 93 } // left = tm
},
new[]
{
// above = d63
new byte[] { 78, 23, 39, 111, 117, 170, 74, 124, 94 }, // left = dc
new byte[] { 48, 34, 86, 101, 92, 146, 78, 179, 134 }, // left = v
new byte[] { 47, 22, 24, 138, 187, 178, 68, 69, 59 }, // left = h
new byte[] { 56, 25, 33, 105, 112, 187, 95, 177, 129 }, // left = d45
new byte[] { 48, 31, 27, 114, 63, 183, 82, 116, 56 }, // left = d135
new byte[] { 43, 28, 37, 121, 63, 123, 61, 192, 169 }, // left = d117
new byte[] { 42, 17, 24, 109, 97, 177, 56, 76, 122 }, // left = d153
new byte[] { 58, 18, 28, 105, 139, 182, 70, 92, 63 }, // left = d207
new byte[] { 46, 23, 32, 74, 86, 150, 67, 183, 88 }, // left = d63
new byte[] { 36, 38, 48, 92, 122, 165, 88, 137, 91 } // left = tm
},
new[]
{
// above = tm
new byte[] { 65, 70, 60, 155, 159, 199, 61, 60, 81 }, // left = dc
new byte[] { 44, 78, 115, 132, 119, 173, 71, 112, 93 }, // left = v
new byte[] { 39, 38, 21, 184, 227, 206, 42, 32, 64 }, // left = h
new byte[] { 58, 47, 36, 124, 137, 193, 80, 82, 78 }, // left = d45
new byte[] { 49, 50, 35, 144, 95, 205, 63, 78, 59 }, // left = d135
new byte[] { 41, 53, 52, 148, 71, 142, 65, 128, 51 }, // left = d117
new byte[] { 40, 36, 28, 143, 143, 202, 40, 55, 137 }, // left = d153
new byte[] { 52, 34, 29, 129, 183, 227, 42, 35, 43 }, // left = d207
new byte[] { 42, 44, 44, 104, 105, 164, 64, 130, 80 }, // left = d63
new byte[] { 43, 81, 53, 140, 169, 204, 68, 84, 72 } // left = tm
}
};
public static readonly byte[][] KfUvModeProb =
{
new byte[] { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, // y = dc
new byte[] { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, // y = v
new byte[] { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, // y = h
new byte[] { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, // y = d45
new byte[] { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, // y = d135
new byte[] { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, // y = d117
new byte[] { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, // y = d153
new byte[] { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, // y = d207
new byte[] { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, // y = d63
new byte[] { 102, 19, 66, 162, 182, 122, 35, 59, 128 } // y = tm
};
private static readonly byte[] DefaultIfYProbs =
{
65, 32, 18, 144, 162, 194, 41, 51, 98, // block_size < 8x8
132, 68, 18, 165, 217, 196, 45, 40, 78, // block_size < 16x16
173, 80, 19, 176, 240, 193, 64, 35, 46, // block_size < 32x32
221, 135, 38, 194, 248, 121, 96, 85, 29 // block_size >= 32x32
};
private static readonly byte[] DefaultIfUvProbs =
{
120, 7, 76, 176, 208, 126, 28, 54, 103, // y = dc
48, 12, 154, 155, 139, 90, 34, 117, 119, // y = v
67, 6, 25, 204, 243, 158, 13, 21, 96, // y = h
97, 5, 44, 131, 176, 139, 48, 68, 97, // y = d45
83, 5, 42, 156, 111, 152, 26, 49, 152, // y = d135
80, 5, 58, 178, 74, 83, 33, 62, 145, // y = d117
86, 5, 32, 154, 192, 168, 14, 22, 163, // y = d153
85, 5, 32, 156, 216, 148, 19, 29, 73, // y = d207
77, 7, 64, 116, 132, 122, 37, 126, 120, // y = d63
101, 21, 107, 181, 192, 103, 19, 67, 125 // y = tm
};
private static readonly byte[] DefaultPartitionProbs =
{
// 8x8 . 4x4
199, 122, 141, // a/l both not split
147, 63, 159, // a split, l not split
148, 133, 118, // l split, a not split
121, 104, 114, // a/l both split
// 16x16 . 8x8
174, 73, 87, // a/l both not split
92, 41, 83, // a split, l not split
82, 99, 50, // l split, a not split
53, 39, 39, // a/l both split
// 32x32 . 16x16
177, 58, 59, // a/l both not split
68, 26, 63, // a split, l not split
52, 79, 25, // l split, a not split
17, 14, 12, // a/l both split
// 64x64 . 32x32
222, 34, 30, // a/l both not split
72, 16, 44, // a split, l not split
58, 32, 12, // l split, a not split
10, 7, 6 // a/l both split
};
private static readonly byte[] DefaultInterModeProbs =
{
2, 173, 34, // 0 = both zero mv
7, 145, 85, // 1 = one zero mv + one a predicted mv
7, 166, 63, // 2 = two predicted mvs
7, 94, 66, // 3 = one predicted/zero and one new mv
8, 64, 46, // 4 = two new mvs
17, 81, 31, // 5 = one intra neighbour + x
25, 29, 30 // 6 = two intra neighbours
};
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
public static readonly sbyte[] IntraModeTree =
{
-(int)PredictionMode.DcPred, 2, /* 0 = DC_NODE */ -(int)PredictionMode.TmPred, 4, /* 1 = TM_NODE */
-(int)PredictionMode.VPred, 6, /* 2 = V_NODE */ 8, 12, /* 3 = COM_NODE */ -(int)PredictionMode.HPred,
10, /* 4 = H_NODE */ -(int)PredictionMode.D135Pred, -(int)PredictionMode.D117Pred, /* 5 = D135_NODE */
-(int)PredictionMode.D45Pred, 14, /* 6 = D45_NODE */ -(int)PredictionMode.D63Pred,
16, /* 7 = D63_NODE */ -(int)PredictionMode.D153Pred, -(int)PredictionMode.D207Pred /* 8 = D153_NODE */
};
public static readonly sbyte[] InterModeTree =
{
-((int)PredictionMode.ZeroMv - (int)PredictionMode.NearestMv), 2,
-((int)PredictionMode.NearestMv - (int)PredictionMode.NearestMv), 4,
-((int)PredictionMode.NearMv - (int)PredictionMode.NearestMv),
-((int)PredictionMode.NewMv - (int)PredictionMode.NearestMv)
};
public static readonly sbyte[] PartitionTree =
{
-(sbyte)PartitionType.PartitionNone, 2, -(sbyte)PartitionType.PartitionHorz, 4,
-(sbyte)PartitionType.PartitionVert, -(sbyte)PartitionType.PartitionSplit
};
public static readonly sbyte[] SwitchableInterpTree =
{
-Constants.EightTap, 2, -Constants.EightTapSmooth, -Constants.EightTapSharp
};
private static readonly byte[] DefaultIntraInterP = { 9, 102, 187, 225 };
private static readonly byte[] DefaultCompInterP = { 239, 183, 119, 96, 41 };
private static readonly byte[] DefaultCompRefP = { 50, 126, 123, 221, 226 };
private static readonly byte[] DefaultSingleRefP = { 33, 16, 77, 74, 142, 142, 172, 170, 238, 247 };
private static readonly byte[] DefaultTxProbs = { 3, 136, 37, 5, 52, 13, 20, 152, 15, 101, 100, 66 };
static EntropyMode()
{
byte[][] KfPartitionProbs =
{
// 8x8 . 4x4
new byte[] { 158, 97, 94 }, // a/l both not split
new byte[] { 93, 24, 99 }, // a split, l not split
new byte[] { 85, 119, 44 }, // l split, a not split
new byte[] { 62, 59, 67 }, // a/l both split
// 16x16 . 8x8
new byte[] { 149, 53, 53 }, // a/l both not split
new byte[] { 94, 20, 48 }, // a split, l not split
new byte[] { 83, 53, 24 }, // l split, a not split
new byte[] { 52, 18, 18 }, // a/l both split
// 32x32 . 16x16
new byte[] { 150, 40, 39 }, // a/l both not split
new byte[] { 78, 12, 26 }, // a split, l not split
new byte[] { 67, 33, 11 }, // l split, a not split
new byte[] { 24, 7, 5 }, // a/l both split
// 64x64 . 32x32
new byte[] { 174, 35, 49 }, // a/l both not split
new byte[] { 68, 11, 27 }, // a split, l not split
new byte[] { 57, 15, 9 }, // l split, a not split
new byte[] { 12, 3, 3 } // a/l both split
};
}
private static readonly byte[] DefaultSkipProbs = { 192, 128, 64 };
private static readonly byte[] DefaultSwitchableInterpProb = { 235, 162, 36, 255, 34, 3, 149, 144 };
private static void InitModeProbs(ref Vp9EntropyProbs fc)
{
Entropy.CopyProbs(ref fc.UvModeProb, DefaultIfUvProbs);
Entropy.CopyProbs(ref fc.YModeProb, DefaultIfYProbs);
Entropy.CopyProbs(ref fc.SwitchableInterpProb, DefaultSwitchableInterpProb);
Entropy.CopyProbs(ref fc.PartitionProb, DefaultPartitionProbs);
Entropy.CopyProbs(ref fc.IntraInterProb, DefaultIntraInterP);
Entropy.CopyProbs(ref fc.CompInterProb, DefaultCompInterP);
Entropy.CopyProbs(ref fc.CompRefProb, DefaultCompRefP);
Entropy.CopyProbs(ref fc.SingleRefProb, DefaultSingleRefP);
Entropy.CopyProbs(ref fc.Tx32x32Prob, DefaultTxProbs.AsSpan().Slice(0, 6));
Entropy.CopyProbs(ref fc.Tx16x16Prob, DefaultTxProbs.AsSpan().Slice(6, 4));
Entropy.CopyProbs(ref fc.Tx8x8Prob, DefaultTxProbs.AsSpan().Slice(10, 2));
Entropy.CopyProbs(ref fc.SkipProb, DefaultSkipProbs);
Entropy.CopyProbs(ref fc.InterModeProb, DefaultInterModeProbs);
}
internal static void TxCountsToBranchCounts32x32(ReadOnlySpan<uint> txCount32x32P,
ref Array3<Array2<uint>> ct32x32P)
{
ct32x32P[0][0] = txCount32x32P[(int)TxSize.Tx4x4];
ct32x32P[0][1] = txCount32x32P[(int)TxSize.Tx8x8] + txCount32x32P[(int)TxSize.Tx16x16] +
txCount32x32P[(int)TxSize.Tx32x32];
ct32x32P[1][0] = txCount32x32P[(int)TxSize.Tx8x8];
ct32x32P[1][1] = txCount32x32P[(int)TxSize.Tx16x16] + txCount32x32P[(int)TxSize.Tx32x32];
ct32x32P[2][0] = txCount32x32P[(int)TxSize.Tx16x16];
ct32x32P[2][1] = txCount32x32P[(int)TxSize.Tx32x32];
}
internal static void TxCountsToBranchCounts16x16(ReadOnlySpan<uint> txCount16x16P,
ref Array2<Array2<uint>> ct16x16P)
{
ct16x16P[0][0] = txCount16x16P[(int)TxSize.Tx4x4];
ct16x16P[0][1] = txCount16x16P[(int)TxSize.Tx8x8] + txCount16x16P[(int)TxSize.Tx16x16];
ct16x16P[1][0] = txCount16x16P[(int)TxSize.Tx8x8];
ct16x16P[1][1] = txCount16x16P[(int)TxSize.Tx16x16];
}
internal static void TxCountsToBranchCounts8x8(ReadOnlySpan<uint> txCount8x8P,
ref Array1<Array2<uint>> ct8x8P)
{
ct8x8P[0][0] = txCount8x8P[(int)TxSize.Tx4x4];
ct8x8P[0][1] = txCount8x8P[(int)TxSize.Tx8x8];
}
public static unsafe void SetupPastIndependence(ref Vp9Common cm)
{
// Reset the segment feature data to the default stats:
// Features disabled, 0, with delta coding (Default state).
ref Types.LoopFilter lf = ref cm.Lf;
cm.Seg.ClearAllSegFeatures();
cm.Seg.AbsDelta = Segmentation.SegmentDeltadata;
if (!cm.LastFrameSegMap.IsNull)
{
MemoryUtil.Fill(cm.LastFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
}
if (!cm.CurrentFrameSegMap.IsNull)
{
MemoryUtil.Fill(cm.CurrentFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
}
// Reset the mode ref deltas for loop filter
lf.LastRefDeltas = new Array4<sbyte>();
lf.LastModeDeltas = new Array2<sbyte>();
lf.SetDefaultLfDeltas();
// To force update of the sharpness
lf.LastSharpnessLevel = -1;
cm.DefaultCoefProbs();
InitModeProbs(ref cm.Fc.Value);
cm.InitMvProbs();
if (cm.FrameType == FrameType.KeyFrame || cm.ErrorResilientMode != 0 || cm.ResetFrameContext == 3)
{
// Reset all frame contexts.
for (int i = 0; i < Constants.FrameContexts; ++i)
{
cm.FrameContexts[i] = cm.Fc.Value;
}
}
else if (cm.ResetFrameContext == 2)
{
// Reset only the frame context specified in the frame header.
cm.FrameContexts[(int)cm.FrameContextIdx] = cm.Fc.Value;
}
// prev_mip will only be allocated in encoder.
if (cm.FrameIsIntraOnly() && !cm.PrevMip.IsNull)
{
cm.PrevMi.Value = new ModeInfo();
}
cm.RefFrameSignBias = new Array4<sbyte>();
cm.FrameContextIdx = 0;
}
}
}

View File

@@ -1,165 +0,0 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class EntropyMv
{
public const int UpdateProb = 252;
/* Symbols for coding which components are zero jointly */
public const int Joints = 4;
public static readonly sbyte[] JointTree =
{
-(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4,
-(sbyte)MvJointType.Hzvnz, -(sbyte)MvJointType.Hnzvnz
};
public static readonly sbyte[] ClassTree =
{
-(sbyte)MvClassType.Class0, 2, -(sbyte)MvClassType.Class1, 4, 6, 8, -(sbyte)MvClassType.Class2,
-(sbyte)MvClassType.Class3, 10, 12, -(sbyte)MvClassType.Class4, -(sbyte)MvClassType.Class5,
-(sbyte)MvClassType.Class6, 14, 16, 18, -(sbyte)MvClassType.Class7, -(sbyte)MvClassType.Class8,
-(sbyte)MvClassType.Class9, -(sbyte)MvClassType.Class10
};
public static readonly sbyte[] Class0Tree = { -0, -1 };
public static readonly sbyte[] FpTree = { -0, 2, -1, 4, -2, -3 };
private static bool JointVertical(MvJointType type)
{
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
}
private static bool JointHorizontal(MvJointType type)
{
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
}
private static readonly byte[] LogInBase2 =
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 10
};
private static int ClassBase(MvClassType c)
{
return c != 0 ? Class0Size << ((int)c + 2) : 0;
}
private static MvClassType GetClass(int z, Ptr<int> offset)
{
MvClassType c = z >= Class0Size * 4096
? MvClassType.Class10
: (MvClassType)LogInBase2[z >> 3];
if (!offset.IsNull)
{
offset.Value = z - ClassBase(c);
}
return c;
}
private static void IncComponent(int v, ref Vp9BackwardUpdates compCounts, int compIndex, int incr, int usehp)
{
int s, z, c, o = 0, d, e, f;
Debug.Assert(v != 0); /* should not be zero */
s = v < 0 ? 1 : 0;
compCounts.Sign[compIndex][s] += (uint)incr;
z = (s != 0 ? -v : v) - 1; /* magnitude - 1 */
c = (int)GetClass(z, new Ptr<int>(ref o));
compCounts.Classes[compIndex][c] += (uint)incr;
d = o >> 3; /* int mv data */
f = (o >> 1) & 3; /* fractional pel mv data */
e = o & 1; /* high precision mv data */
if (c == (int)MvClassType.Class0)
{
compCounts.Class0[compIndex][d] += (uint)incr;
compCounts.Class0Fp[compIndex][d][f] += (uint)incr;
compCounts.Class0Hp[compIndex][e] += (uint)(usehp * incr);
}
else
{
int b = c + Class0Bits - 1; // number of bits
for (int i = 0; i < b; ++i)
{
compCounts.Bits[compIndex][i][(d >> i) & 1] += (uint)incr;
}
compCounts.Fp[compIndex][f] += (uint)incr;
compCounts.Hp[compIndex][e] += (uint)(usehp * incr);
}
}
public static void Inc(ref Mv mv, Ptr<Vp9BackwardUpdates> counts)
{
if (!counts.IsNull)
{
MvJointType j = mv.GetJoint();
++counts.Value.Joints[(int)j];
if (JointVertical(j))
{
IncComponent(mv.Row, ref counts.Value, 0, 1, 1);
}
if (JointHorizontal(j))
{
IncComponent(mv.Col, ref counts.Value, 1, 1, 1);
}
}
}
/* Symbols for coding magnitude class of nonzero components */
public const int Classes = 11;
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
public const int Class0Size = 1 << Class0Bits;
public const int OffsetBits = Classes + Class0Bits - 2;
public const int FpSize = 4;
public const int MaxBits = Classes + Class0Bits + 2;
public const int Max = (1 << MaxBits) - 1;
public const int Vals = (Max << 1) + 1;
public const int InUseBits = 14;
public const int Upp = (1 << InUseBits) - 1;
public const int Low = -(1 << InUseBits);
}
}

View File

@@ -1,79 +0,0 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal struct InternalFrameBuffer
{
public ArrayPtr<byte> Data;
public bool InUse;
}
internal struct InternalFrameBufferList
{
public ArrayPtr<InternalFrameBuffer> IntFb;
}
internal static class FrameBuffers
{
public static int GetFrameBuffer(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv, ulong minSize,
ref VpxCodecFrameBuffer fb)
{
int i;
Ptr<InternalFrameBufferList> intFbList = cbPriv;
if (intFbList.IsNull)
{
return -1;
}
// Find a free frame buffer.
for (i = 0; i < intFbList.Value.IntFb.Length; ++i)
{
if (!intFbList.Value.IntFb[i].InUse)
{
break;
}
}
if (i == intFbList.Value.IntFb.Length)
{
return -1;
}
if ((ulong)intFbList.Value.IntFb[i].Data.Length < minSize)
{
if (!intFbList.Value.IntFb[i].Data.IsNull)
{
allocator.Free(intFbList.Value.IntFb[i].Data);
}
// The data must be zeroed to fix a valgrind error from the C loop filter
// due to access uninitialized memory in frame border. It could be
// skipped if border were totally removed.
intFbList.Value.IntFb[i].Data = allocator.Allocate<byte>((int)minSize);
if (intFbList.Value.IntFb[i].Data.IsNull)
{
return -1;
}
}
fb.Data = intFbList.Value.IntFb[i].Data;
intFbList.Value.IntFb[i].InUse = true;
// Set the frame buffer's private data to point at the internal frame buffer.
fb.Priv = new Ptr<InternalFrameBuffer>(ref intFbList.Value.IntFb[i]);
return 0;
}
public static int ReleaseFrameBuffer(Ptr<InternalFrameBufferList> cbPriv, ref VpxCodecFrameBuffer fb)
{
if (!fb.Priv.IsNull)
{
fb.Priv.Value.InUse = false;
}
return 0;
}
}
}

View File

@@ -1,4 +1,4 @@
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 System; using System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm;
@@ -8,13 +8,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
internal static class Idct internal static class Idct
{ {
private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output); private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output);
private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd); private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd);
private struct Transform2D private struct Transform2D
{ {
public readonly Transform1D Cols; // Vertical and horizontal public Transform1D Cols, Rows; // Vertical and horizontal
public readonly Transform1D Rows; // Vertical and horizontal
public Transform2D(Transform1D cols, Transform1D rows) public Transform2D(Transform1D cols, Transform1D rows)
{ {
@@ -25,8 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct HighbdTransform2D private struct HighbdTransform2D
{ {
public readonly HighbdTransform1D Cols; // Vertical and horizontal public HighbdTransform1D Cols, Rows; // Vertical and horizontal
public readonly HighbdTransform1D Rows; // Vertical and horizontal
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows) public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
{ {
@@ -35,124 +32,121 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly Transform2D[] Iht4 = private static readonly Transform2D[] _iht4 = {
{
new(Idct4, Idct4), // DCT_DCT = 0 new(Idct4, Idct4), // DCT_DCT = 0
new(Iadst4, Idct4), // ADST_DCT = 1 new(Iadst4, Idct4), // ADST_DCT = 1
new(Idct4, Iadst4), // DCT_ADST = 2 new(Idct4, Iadst4), // DCT_ADST = 2
new(Iadst4, Iadst4) // ADST_ADST = 3 new(Iadst4, Iadst4), // ADST_ADST = 3
}; };
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[4 * 4]; Span<int> output = stackalloc int[4 * 4];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[4]; Span<int> tempIn = stackalloc int[4];
Span<int> tempOut = stackalloc int[4]; Span<int> tempOut = stackalloc int[4];
// Inverse transform row vectors // Inverse transform row vectors
for (int i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
Iht4[txType].Rows(input, outptr); _iht4[txType].Rows(input, outptr);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Inverse transform column vectors // Inverse transform column vectors
for (int i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
for (int j = 0; j < 4; ++j) for (j = 0; j < 4; ++j)
{ {
tempIn[j] = output[(j * 4) + i]; tempIn[j] = output[j * 4 + i];
} }
Iht4[txType].Cols(tempIn, tempOut); _iht4[txType].Cols(tempIn, tempOut);
for (int j = 0; j < 4; ++j) for (j = 0; j < 4; ++j)
{ {
dest[(j * stride) + i] = dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
} }
} }
} }
private static readonly Transform2D[] Iht8 = private static readonly Transform2D[] _iht8 = {
{
new(Idct8, Idct8), // DCT_DCT = 0 new(Idct8, Idct8), // DCT_DCT = 0
new(Iadst8, Idct8), // ADST_DCT = 1 new(Iadst8, Idct8), // ADST_DCT = 1
new(Idct8, Iadst8), // DCT_ADST = 2 new(Idct8, Iadst8), // DCT_ADST = 2
new(Iadst8, Iadst8) // ADST_ADST = 3 new(Iadst8, Iadst8), // ADST_ADST = 3
}; };
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[8 * 8]; Span<int> output = stackalloc int[8 * 8];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
Transform2D ht = Iht8[txType]; Transform2D ht = _iht8[txType];
// Inverse transform row vectors // Inverse transform row vectors
for (int i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Inverse transform column vectors // Inverse transform column vectors
for (int i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
for (int j = 0; j < 8; ++j) for (j = 0; j < 8; ++j)
{ {
tempIn[j] = output[(j * 8) + i]; tempIn[j] = output[j * 8 + i];
} }
ht.Cols(tempIn, tempOut); ht.Cols(tempIn, tempOut);
for (int j = 0; j < 8; ++j) for (j = 0; j < 8; ++j)
{ {
dest[(j * stride) + i] = dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
} }
} }
} }
private static readonly Transform2D[] Iht16 = private static readonly Transform2D[] _iht16 = {
{
new(Idct16, Idct16), // DCT_DCT = 0 new(Idct16, Idct16), // DCT_DCT = 0
new(Iadst16, Idct16), // ADST_DCT = 1 new(Iadst16, Idct16), // ADST_DCT = 1
new(Idct16, Iadst16), // DCT_ADST = 2 new(Idct16, Iadst16), // DCT_ADST = 2
new(Iadst16, Iadst16) // ADST_ADST = 3 new(Iadst16, Iadst16), // ADST_ADST = 3
}; };
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[16 * 16]; Span<int> output = stackalloc int[16 * 16];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
Transform2D ht = Iht16[txType]; Transform2D ht = _iht16[txType];
// Rows // Rows
for (int i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Columns // Columns
for (int i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
for (int j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
{ {
tempIn[j] = output[(j * 16) + i]; tempIn[j] = output[j * 16 + i];
} }
ht.Cols(tempIn, tempOut); ht.Cols(tempIn, tempOut);
for (int j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
{ {
dest[(j * stride) + i] = dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
} }
} }
} }
@@ -274,7 +268,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
public static void Iht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest, public static void Iht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest,
int stride, int eob) int stride, int eob)
{ {
if (txType == TxType.DctDct) if (txType == TxType.DctDct)
{ {
@@ -286,125 +280,121 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly HighbdTransform2D[] HighbdIht4 = private static readonly HighbdTransform2D[] _highbdIht4 = {
{
new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0 new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1 new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2 new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
new(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3 new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3
}; };
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd) public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
{ {
int i, j;
Span<int> output = stackalloc int[4 * 4]; Span<int> output = stackalloc int[4 * 4];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[4]; Span<int> tempIn = stackalloc int[4];
Span<int> tempOut = stackalloc int[4]; Span<int> tempOut = stackalloc int[4];
// Inverse transform row vectors. // Inverse transform row vectors.
for (int i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
HighbdIht4[txType].Rows(input, outptr, bd); _highbdIht4[txType].Rows(input, outptr, bd);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Inverse transform column vectors. // Inverse transform column vectors.
for (int i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
for (int j = 0; j < 4; ++j) for (j = 0; j < 4; ++j)
{ {
tempIn[j] = output[(j * 4) + i]; tempIn[j] = output[j * 4 + i];
} }
HighbdIht4[txType].Cols(tempIn, tempOut, bd); _highbdIht4[txType].Cols(tempIn, tempOut, bd);
for (int j = 0; j < 4; ++j) for (j = 0; j < 4; ++j)
{ {
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i], dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
} }
} }
} }
private static readonly HighbdTransform2D[] HighIht8 = private static readonly HighbdTransform2D[] _highIht8 = {
{
new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0 new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1 new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2 new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
new(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3 new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3
}; };
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd) public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
{ {
int i, j;
Span<int> output = stackalloc int[8 * 8]; Span<int> output = stackalloc int[8 * 8];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
HighbdTransform2D ht = HighIht8[txType]; HighbdTransform2D ht = _highIht8[txType];
// Inverse transform row vectors. // Inverse transform row vectors.
for (int i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input.Slice(8); input = input[8..];
outptr = output.Slice(8); outptr = output[8..];
} }
// Inverse transform column vectors. // Inverse transform column vectors.
for (int i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
for (int j = 0; j < 8; ++j) for (j = 0; j < 8; ++j)
{ {
tempIn[j] = output[(j * 8) + i]; tempIn[j] = output[j * 8 + i];
} }
ht.Cols(tempIn, tempOut, bd); ht.Cols(tempIn, tempOut, bd);
for (int j = 0; j < 8; ++j) for (j = 0; j < 8; ++j)
{ {
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i], dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
} }
} }
} }
private static readonly HighbdTransform2D[] HighIht16 = private static readonly HighbdTransform2D[] _highIht16 = {
{
new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0 new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1 new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2 new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
new(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3 new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3
}; };
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
int bd)
{ {
int i, j;
Span<int> output = stackalloc int[16 * 16]; Span<int> output = stackalloc int[16 * 16];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
HighbdTransform2D ht = HighIht16[txType]; HighbdTransform2D ht = _highIht16[txType];
// Rows // Rows
for (int i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input.Slice(16); input = input[16..];
outptr = output.Slice(16); outptr = output[16..];
} }
// Columns // Columns
for (int i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
for (int j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
{ {
tempIn[j] = output[(j * 16) + i]; tempIn[j] = output[j * 16 + i];
} }
ht.Cols(tempIn, tempOut, bd); ht.Cols(tempIn, tempOut, bd);
for (int j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
{ {
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i], dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
} }
} }
} }
@@ -444,7 +434,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// DC only DCT coefficient // DC only DCT coefficient
if (eob == 1) if (eob == 1)
{ {
VpxHighbdidct8x81AddC(input, dest, stride, bd); Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
} }
else if (eob <= 12) else if (eob <= 12)
{ {
@@ -501,8 +491,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
// Iht // Iht
public static void HighbdIht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, public static void HighbdIht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
int eob, int bd)
{ {
if (txType == TxType.DctDct) if (txType == TxType.DctDct)
{ {
@@ -514,8 +503,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
public static void HighbdIht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, public static void HighbdIht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
int eob, int bd)
{ {
if (txType == TxType.DctDct) if (txType == TxType.DctDct)
{ {
@@ -527,8 +515,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
public static void HighbdIht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, public static void HighbdIht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
int eob, int bd)
{ {
if (txType == TxType.DctDct) if (txType == TxType.DctDct)
{ {

View File

@@ -2,7 +2,7 @@ using System;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal class InternalErrorException : Exception class InternalErrorException : Exception
{ {
public InternalErrorException(string message) : base(message) public InternalErrorException(string message) : base(message)
{ {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More