Compare commits

...

81 Commits

Author SHA1 Message Date
Keaton
5c54ce9114 Merge 428b1e5cea into 3b5f6170d1 2025-01-24 23:27:47 -06:00
Evan Husted
3b5f6170d1 misc: chore: move Rainbow updating to a separate task started/stopped as needed
update gommon & use the Event class from it to allow easily clearing all handlers when the apphost exits to avoid leftover invalid event handlers in the rainbow event handler list.
More robust config application logic to ensure what needs to happen only happens once
2025-01-24 23:06:59 -06:00
Evan Husted
9b6afa0ea2 misc: chore: Add log line to the other parts of the Updater that represent "up to date" 2025-01-24 17:00:50 -06:00
Evan Husted
3541e282ea Fully disconnect gamepad handler for rainbow color if configuration is set with UseRainbowLed false
Also check if its even enabled before setting the rainbow color
Fixes strobing
2025-01-24 16:52:20 -06:00
Otozinclus
1ce37ec317 Add option to change controller LED color (#572)
This allows the user to change the controller LED while using Ryujinx.
Useful for PS4 and PS5 controllers as an example.

You can also use a spectrum-cycling Rainbow color option, or turn the LED off for DualSense controllers.

---------

Co-authored-by: Evan Husted <greem@greemdev.net>
2025-01-24 14:47:36 -06:00
Evan Husted
c06f16c5e6 infra: chore: Raise minimum required Windows 10 version
Inspired by the breakages covered in #409
2025-01-23 17:39:34 -06:00
Evan Husted
7829fd8ee7 misc: chore: OS + CPU arch helpers 2025-01-23 16:58:48 -06:00
Evan Husted
33079422fe misc: chore: code cleanups 2025-01-23 16:47:11 -06:00
Evan Husted
f81cb093fc misc: chore: Change references of GreemDev/Ryujinx to Ryubing/Ryujinx 2025-01-23 16:27:49 -06:00
Evan Husted
dc0c7a2912 infra: clarify how stable builds are made now 2025-01-23 16:27:25 -06:00
Evan Husted
1fbee5a584 infra: Metal label 2025-01-23 14:39:36 -06:00
Evan Husted
428b1e5cea Merge branch 'master' into VP9-loop-filtering 2025-01-23 01:09:44 -06:00
Evan Husted
c140e9b23c UI: Localize LED color & hide it until it's functional
Also moved IgnoreApplet to the System config section object.
2025-01-23 00:48:42 -06:00
Evan Husted
9c8055440e HLE: TryAdd firmware NCAs 2025-01-22 23:58:11 -06:00
Evan Husted
c03cd50fa3 UI: Add the ability to change a DualSense/DualShock 4's LED color.
Not functional yet. This is the UI & persistence side of #572.
2025-01-22 19:53:39 -06:00
Evan Husted
069f630776 docs: compat: boots: ENDER MAGNOLIA: Bloom in the Mist 2025-01-22 18:00:14 -06:00
Evan Husted
13d411e4de misc: chore: also ToLower the titleID for the OpenShaderDirectory button 2025-01-22 08:54:39 -06:00
Evan Husted
9f53b07491 misc: chore: Fix shader cache & CPU cache being in different folders on non-Windows
fixes #565
2025-01-22 08:52:21 -06:00
Evan Husted
cd8113dadf misc: chore: Collapse adding a game/autoload dir into a single reusable method. 2025-01-21 18:59:56 -06:00
Evan Husted
9089c4ffe5 misc: chore: Multi/Single file/folder picker extensions (for convenience)
The result of these extensions is an empty Optional when the user hits Cancel on the shown file picker.
2025-01-21 18:59:19 -06:00
Evan Husted
fe9d8d05bd UI: Fixed the Amiibo keybind only working when the UI had been updated. 2025-01-21 18:00:51 -06:00
Evan Husted
880a8ae748 misc: chore: Remove duplicated styling blocks in MainMenuBarView in favor of a reusable Avalonia Style. 2025-01-21 17:50:55 -06:00
asfasagag
11531dacb6 UI: Option to automatically Hide UI when game launches (#462)
Quality of life feature
Similar in function to the "Start Games in Fullscreen" toggle
For users who want to run games in windowed/non-fullscreen mode with
menu UI hidden, this eliminates the need to always click "Hide UI"
2025-01-21 17:36:51 -06:00
Evan Husted
3974739ed3 More descriptive classification 2025-01-21 17:35:22 -06:00
Evan Husted
440a3447fb docs: compat: Update South Park: The Fractured but Whole: playable -> boots 2025-01-21 17:10:54 -06:00
Evan Husted
65374ed6cb UI: [ci skip] clarify dirty hacks subtext 2025-01-21 16:57:05 -06:00
Evan Husted
789d6ab959 misc: chore: Improve autoloading DLC/updates logging, deliberately switch to Vulkan if Metal was somehow chosen on a non-mac system, add logger lines in the updater, cleanup enabled logs printing 2025-01-21 14:59:08 -06:00
Evan Husted
182db31343 metal: Added Persona 4 Arena Ultimax to Auto 2025-01-21 14:07:05 -06:00
Evan Husted
ea296b134d Use specific Ubuntu version in build script 2025-01-21 14:05:49 -06:00
Evan Husted
bf584442b2 misc: chore: remove needless call to string.Format 2025-01-21 14:05:49 -06:00
Otozinclus
cb7c294dbf Add more games to metal game list (#558)
Link's awakening I have played through most of the game with 0 issues.

In LEGO City undercover I have played multiple missions and explored the
map, I was unable to spot any issue. Except shadows flickering
sometimes, but that seems to happen on Vulkan and the PC version as well
and is propably normal.

Bayonetta seems to work flawless so far.

In Fast RMX, some tracks have flickering issues, like the second track
of the first cup. This happens on Vulkan as well.

-

Mario Bros. Wonder has following issues:

Overall issues:
- Sometimes there is short white flickering/artifacts, but they happen
on Vulkan as well.

Metal specific issue:
- In 2 underwater levels, a specific location causes a FPS drop not
present on Vulkan. But this is very minor and on all current M chips you
get on average better FPS with Metal (On my M3, there are occasional
drops that are worse with Vulkan), reducing stutter quite noticeably,
which is why I think it should get added to auto regardless.

- Isaac mentioned there is a issue in level 2, where the flowers singing
desync somehow. However, I was after lot of testing unable to replicate
this issue at all. More testing could be useful.

Fix: Fixed 2 typos in the comments
2025-01-21 14:05:41 -06:00
Daenorth
eaf1e7efd2 Cleanup in TitleIDs.cs (#546)
Just a little cleanup in TitleID.cs, adding a franchise title to most
franchises + sorting in alphabetical on all games.
2025-01-21 11:20:43 -06:00
Judas Drekonym
471e7ed2e4 Add TitleID sort method (#553)
Adds an additional application list sorting method for the TitleID. A
bit of a niche choice for sorting but I think the TID is a relevant
enough piece of metadata that it should be there. (And I personally
would be using it)

- Using existing TitleId constant in ApplicationSort, implying this was
meant to be in the sorting options at some point?
- Reuses the "DlcManagerTableHeadingTitleIdLabel" locale for fulfilling
the need already, might be better to make a unique one for this in the
long run but this codebase is new to me so I wanted to make the changes
as unobtrusive as possible
- Using app.Id for the comparer seems to work fine, not sure if using
something else like IdString would be better?
2025-01-21 11:06:40 -06:00
Matt Zinkevicius
ad3e80b383 Log .NET runtime version (#552)
I was looking into a crash, and found out it was an issue that was fixed
in .NET 9.0.1. Since Ryujinx embeds the runtime into the executable, it
not obvious which runtime a build uses. This logs the .NET runtime
version immediately after the build version.
2025-01-20 19:19:19 -06:00
Evan Husted
ed64a63094 UI: Visually merge "Actions" and "Tools" menu bar items into Actions
The contents of the menu item are dependent on whether you're in a game.
No functionality has been removed.
2025-01-20 16:56:05 -06:00
Evan Husted
8df7ba2d56 i18n: Norwegian DLC RomFS dumping translation 2025-01-20 15:55:37 -06:00
LotP1
e743d78115 Add/fix service reported info (#551)
fixes the GetConfig service call, which now returns success correctly
adds support for getting the device serial number (which is fake and
reports as "RYU00000000000")
2025-01-20 14:59:54 -06:00
Evan Husted
04ba762710 UI: Move DLC RomFS dumping under normal RomFS dumping.
Also removed it from DLC manager.
2025-01-20 14:30:28 -06:00
Evan Husted
f42b2ed59d misc: chore: more correct last used user checking 2025-01-20 13:33:59 -06:00
TSR Berry
e6f7d6e1d5 Remove duplicate BitUtils methods 2025-01-20 11:03:50 -06:00
TSR Berry
0ad5def417 Adjust docstrings for CodecError.cs 2025-01-20 11:03:50 -06:00
gdkchan
f012c3fbef Initialize loop filter parameters 2025-01-20 11:03:49 -06:00
gdkchan
b69b432b4c Implement VP9 loop filtering 2025-01-20 11:03:49 -06:00
Evan Husted
d135385cab Leftovers, oops 2025-01-20 09:32:38 -06:00
Evan Husted
b360f4e721 UI: Dump DLC RomFS.
You can access this in the Manage DLC screen, it's the new button on each DLC line.

Closes #548
2025-01-20 09:28:58 -06:00
Daenorth
a1c0c70ec2 Added missing TitleIDs (#545)
Added the remaining missing TitleIDs in the compat.csv list.
Excluding Homebrew apps.
2025-01-19 21:15:46 -06:00
Daenorth
290ac405ac Updated Ukrainian translation by Rondo (#543)
Co-authored-by: rrondo <46533574+rrondo@users.noreply.github.com>
2025-01-19 21:00:40 -06:00
Evan Husted
bbd64fd5f0 misc: chore: Cleanup AppletMetadata usage 2025-01-19 19:40:49 -06:00
Evan Husted
09446fd80e [ci skip] infra: Update copyright year in shortcut plist 2025-01-19 18:57:05 -06:00
Evan Husted
4f014a89cf docs: compat: Donkey Kong Country Returns HD 2025-01-19 18:28:43 -06:00
Evan Husted
6482e566ab UI: Compat: Unload compatibility entries when the window closes. 2025-01-19 17:41:50 -06:00
Evan Husted
7fcd9b792e UI: Compat: Update owned game title IDs when ApplicationLibrary app count updates 2025-01-19 17:41:31 -06:00
Evan Husted
e676fd8b17 UI: misc: simplify Intel Mac warning logic 2025-01-19 14:42:15 -06:00
Evan Husted
dd16e3cee1 misc: chore: very small cleanup in AvaHostUIHandler 2025-01-19 13:18:40 -06:00
Evan Husted
31e5f74e05 UI: misc: Replace spaces in Title with newlines when using custom title bar (since the Title is in an Avalonia tooltip) 2025-01-19 13:05:20 -06:00
Evan Husted
f2f099bddb remove Async suffixes; they're factory methods not actual async methods. 2025-01-19 12:46:32 -06:00
Evan Husted
2616dc57fb misc: chore: RelayCommand helper 2025-01-19 12:44:07 -06:00
Evan Husted
0cdf7cfe21 UI: Open cheat manager in catch-all try 2025-01-18 22:48:06 -06:00
Evan Husted
2ecf999569 misc: chore: change ThemeManager ThemeChanged to a basic Action since both arguments are unused 2025-01-18 22:48:06 -06:00
Daenorth
b612fc5155 Updated TitleIDs (#541)
Added more games to the RPC list. Now alphabetical.
2025-01-18 22:19:28 -06:00
Evan Husted
25eb545409 Update bug_report.yml 2025-01-18 20:55:28 -06:00
Jacob
52269964b6 Add the player select applet. (#537)
This introduces the somewhat completed version of the Player Select
Applet, allowing users to select either a user or a guest from the UI.
Note: Selecting the guest more then once currently does not work.

closes https://github.com/Ryubing/Ryujinx/issues/532
2025-01-18 20:40:33 -06:00
Evan Husted
ccdddac8fc Fix compile warnings 2025-01-18 19:34:31 -06:00
Daenorth
1bc30bf3ba Update locales.json (#538)
Added a missing translation line
2025-01-18 18:40:51 -06:00
Evan Husted
4868fface8 UI: Intel Mac warning
Upon launch, shows a warning about using an Intel Mac. This will only show once every boot. You can only turn it off by getting a better system.
2025-01-18 15:33:05 -06:00
Evan Husted
6fca4492d0 misc: chore: Remove status update event stuff in Headless 2025-01-18 15:15:08 -06:00
Evan Husted
ade2f256e0 misc: chore: remove duplicate graphics debug levels in headless windows 2025-01-18 11:19:38 -06:00
Evan Husted
580b150c9a Revert "infra: Conditionally compile Metal & OpenGL depending on if the target RuntimeIdentifier is mac"
This reverts commit 2f93a0f706.
2025-01-18 10:57:02 -06:00
Evan Husted
e6bad52945 Revert "Only selectively compile Metal & fix some compilation issues"
This reverts commit beda3206e0.
2025-01-18 10:56:58 -06:00
Evan Husted
beda3206e0 Only selectively compile Metal & fix some compilation issues 2025-01-18 10:52:32 -06:00
Evan Husted
2f93a0f706 infra: Conditionally compile Metal & OpenGL depending on if the target RuntimeIdentifier is mac 2025-01-18 10:38:29 -06:00
Evan Husted
80f44d9547 misc: chore: small cleanup 2025-01-18 10:33:57 -06:00
Evan Husted
b08e5db6d8 Headless: Dispose of inputmanager in a catch-all try 2025-01-18 10:30:19 -06:00
Evan Husted
6a291d4116 Headless: Use main UI logo for window icon instead of separate bmp 2025-01-18 10:26:12 -06:00
Evan Husted
6fc827fe67 headless: collapse headless window definition into a "Windows" folder, change GetWindowFlags to an abstract property. 2025-01-18 10:15:24 -06:00
Daniel Nylander
6cd4866d76 Updated sv_SE in locales.json (#513) 2025-01-17 18:04:18 -06:00
WilliamWsyHK
4d7ca5c0f0 Update Chinese translations (#375) 2025-01-17 17:35:34 -06:00
GabCoolGuy
a375faecc1 UI: Fix UpdateWaitWindow.axaml windows being too big on windows (#314) 2025-01-17 14:14:19 -06:00
Evan Husted
1728b0f20c WWE 2K18 is not playable. 2025-01-17 11:37:08 -06:00
LotP1
5aa071c59b remove notice for unusual core counts (#531) 2025-01-17 05:50:42 -06:00
Daenorth
1018c9db8b Update Norwegian Translation (#503)
Norwegian translation updated with the Compatibility list addition
2025-01-16 10:02:33 -06:00
186 changed files with 13689 additions and 3826 deletions

View File

@@ -22,7 +22,7 @@ body:
id: log
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
description: "A log file will help our developers to better diagnose and fix the issue. UPLOAD THE FILE. DO NOT COPY AND PASTE THE FILE'S CONTENT."
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
validations:
required: true

4
.github/labeler.yml vendored
View File

@@ -18,6 +18,10 @@ gpu:
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Vulkan/**', 'src/Spv.Generator/**']
'graphics-backend:metal':
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx.Graphics.Metal/**', 'src/Ryujinx.Graphics.Metal.SharpMetalExtensions/**']
gui:
- changed-files:
- any-glob-to-any-file: ['src/Ryujinx/**', 'src/Ryujinx.UI.Common/**', 'src/Ryujinx.UI.LocaleGenerator/**']

View File

@@ -202,7 +202,7 @@ jobs:
macos_release:
name: Release MacOS universal
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

View File

@@ -183,7 +183,7 @@ jobs:
macos_release:
name: Release MacOS universal
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

View File

@@ -42,7 +42,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.0.2" />
<PackageVersion Include="Gommon" Version="2.7.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />

View File

@@ -54,12 +54,13 @@ failing to meet this requirement may result in a poor gameplay experience or une
## Latest build
Stable builds are made every so often onto a separate "release" branch that then gets put into the releases you know and love.
Stable builds are made every so often, based on the `master` branch, that then gets put into the releases you know and love.
These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
They are released every month or so, to ensure consistent updates, while not being an annoying amount of individual updates to download over the course of that month.
You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest).
Canary builds are compiled automatically for each commit on the master branch.
Canary builds are compiled automatically for each commit on the `master` branch.
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
These canary builds are only recommended for experienced users.
@@ -109,7 +110,7 @@ If you are planning to contribute or just want to learn more about this project
- **Configuration**
The emulator has settings for enabling or disabling some logging, remapping controllers, and more.
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the user folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
You can configure all of them through the graphical interface or manually through the config file, `Config.json`, found in the Ryujinx data folder which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
## License

View File

@@ -19,7 +19,7 @@
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string>
<string>Copyright © 2018 - 2025 Ryujinx Team and Contributors.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>

View File

@@ -167,7 +167,7 @@
01006C40086EA000,"AeternoBlade",nvdec,playable,2020-12-14 20:06:48
0100B1C00949A000,"AeternoBlade Demo",nvdec,playable,2021-02-09 14:39:26
01009D100EA28000,"AeternoBlade II",online-broken;UE4;vulkan-backend-bug,playable,2022-09-12 21:11:18
,"AeternoBlade II Demo Version",gpu;nvdec,ingame,2021-02-09 15:10:19
0100B1C00949A000,"AeternoBlade II Demo Version",gpu;nvdec,ingame,2021-02-09 15:10:19
01001B400D334000,"AFL Evolution 2",slow;online-broken;UE4,playable,2022-12-07 12:45:56
0100DB100BBCE000,"Afterparty",,playable,2022-09-22 12:23:19
010087C011C4E000,"Agatha Christie - The ABC Murders",,playable,2020-10-27 17:08:23
@@ -477,7 +477,7 @@
010020700DE04000,"Bear With Me: The Lost Robots",nvdec,playable,2021-02-27 14:20:10
010024200E97E800,"Bear With Me: The Lost Robots Demo",nvdec,playable,2021-02-12 22:38:12
0100C0E014A4E000,"Bear's Restaurant",,playable,2024-08-11 21:26:59
,"BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~",crash,menus,2020-10-04 06:12:08
010045F00BF64000,"BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~",crash,menus,2020-10-04 06:12:08
01009C300BB4C000,"Beat Cop",,playable,2021-01-06 19:26:48
01002D20129FC000,"Beat Me!",online-broken,playable,2022-10-16 21:59:26
01006B0014590000,"BEAUTIFUL DESOLATION",gpu;nvdec,ingame,2022-10-26 10:34:38
@@ -703,7 +703,7 @@
01006A30124CA000,"Chocobo GP",gpu;crash,ingame,2022-06-04 14:52:18
0100BF600BF26000,"Chocobo's Mystery Dungeon EVERY BUDDY!",slow,playable,2020-05-26 13:53:13
01000BA0132EA000,"Choices That Matter: And The Sun Went Out",,playable,2020-12-17 15:44:08
,"Chou no Doku Hana no Kusari: Taishou Irokoi Ibun",gpu;nvdec,ingame,2020-09-28 17:58:04
0100A1200CA3C000,"Chou no Doku Hana no Kusari: Taishou Irokoi Ibun",gpu;nvdec,ingame,2020-09-28 17:58:04
010039A008E76000,"ChromaGun",,playable,2020-05-26 12:56:42
010006800E13A000,"Chronos: Before the Ashes",UE4;gpu;nvdec,ingame,2020-12-11 22:16:35
010039700BA7E000,"Circle of Sumo",,playable,2020-05-22 12:45:21
@@ -769,7 +769,7 @@
0100CCB01B1A0000,"COSMIC FANTASY COLLECTION",,ingame,2024-05-21 17:56:37
010067C00A776000,"Cosmic Star Heroine",,playable,2021-02-20 14:30:47
01003DD00F94A000,"COTTOn Reboot! [ コットン リブート! ]",,playable,2022-05-24 16:29:24
,"Cotton/Guardian Saturn Tribute Games",gpu,boots,2022-11-27 21:00:51
010077001526E000,"Cotton/Guardian Saturn Tribute Games",gpu,boots,2022-11-27 21:00:51
01000E301107A000,"Couch Co-Op Bundle Vol. 2",nvdec,playable,2022-10-02 12:04:21
0100C1E012A42000,"Country Tales",,playable,2021-06-17 16:45:39
01003370136EA000,"Cozy Grove",gpu,ingame,2023-07-30 22:22:19
@@ -830,7 +830,7 @@
01003ED0099B0000,"Danger Mouse: The Danger Games",crash;online,boots,2022-07-22 15:49:45
0100EFA013E7C000,"Danger Scavenger",nvdec,playable,2021-04-17 15:53:04
0100417007F78000,"Danmaku Unlimited 3",,playable,2020-11-15 00:48:35
,"Darius Cozmic Collection",,playable,2021-02-19 20:59:06
01000330105BE000,"Darius Cozmic Collection",,playable,2021-02-19 20:59:06
010059C00BED4000,"Darius Cozmic Collection Special Edition",,playable,2022-07-22 16:26:50
010015800F93C000,"Dariusburst - Another Chronicle EX+",online,playable,2021-04-05 14:21:43
01003D301357A000,"Dark Arcana: The Carnival",gpu;slow,ingame,2022-02-19 08:52:28
@@ -859,7 +859,7 @@
010095A011A14000,"Deadly Days",,playable,2020-11-27 13:38:55
0100BAC011928000,"Deadly Premonition 2: A Blessing In Disguise",,playable,2021-06-15 14:12:36
0100EBE00F22E000,"Deadly Premonition Origins",32-bit;nvdec,playable,2024-03-25 12:47:46
,"Dear Magi - Mahou Shounen Gakka -",,playable,2020-11-22 16:45:16
010015600D814000,"Dear Magi - Mahou Shounen Gakka -",,playable,2020-11-22 16:45:16
01000D60126B6000,"Death and Taxes",,playable,2020-12-15 20:27:49
010012B011AB2000,"Death Come True",nvdec,playable,2021-06-10 22:30:49
0100F3B00CF32000,"Death Coming",crash,nothing,2022-02-06 07:43:03
@@ -902,13 +902,13 @@
010023600C704000,"Deponia",nvdec,playable,2021-01-26 17:17:19
0100ED700469A000,"Deru - The Art of Cooperation",,playable,2021-01-07 16:59:59
0100D4600D0E4000,"Descenders",gpu,ingame,2020-12-10 15:22:36
,"Desire remaster ver.",crash,boots,2021-01-17 02:34:37
0100D870102BC000,"Desire remaster ver.",crash,boots,2021-01-17 02:34:37
010069500DD86000,"Destiny Connect: Tick-Tock Travelers",UE4;gpu;nvdec,ingame,2020-12-16 12:20:36
01008BB011ED6000,"Destrobots",,playable,2021-03-06 14:37:05
01009E701356A000,"Destroy All Humans!",gpu;nvdec;UE4,ingame,2023-01-14 22:23:53
010030600E65A000,"Detective Dolittle",,playable,2021-03-02 14:03:59
01009C0009842000,"Detective Gallo",nvdec,playable,2022-07-24 11:51:04
,"Detective Jinguji Saburo Prism of Eyes",,playable,2020-10-02 21:54:41
01002D400B0F6000,"Detective Jinguji Saburo Prism of Eyes",,playable,2020-10-02 21:54:41
010007500F27C000,"Detective Pikachu™ Returns",,playable,2023-10-07 10:24:59
010031B00CF66000,"Devil Engine",,playable,2021-06-04 11:54:30
01002F000E8F2000,"Devil Kingdom",,playable,2023-01-31 08:58:44
@@ -1057,7 +1057,7 @@
01004F000B716000,"Edna & Harvey: The Breakout Anniversary Edition",crash;nvdec,ingame,2022-08-01 16:59:56
01002550129F0000,"Effie",,playable,2022-10-27 14:36:39
0100CC0010A46000,"Ego Protocol: Remastered",nvdec,playable,2020-12-16 20:16:35
,"Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai",,playable,2020-11-12 00:11:50
01004CC00B352000,"Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai",,playable,2020-11-12 00:11:50
01003AD013BD2000,"Eight Dragons",nvdec,playable,2022-10-27 14:47:28
010020A01209C000,"El Hijo - A Wild West Tale",nvdec,playable,2021-04-19 17:44:08
0100B5B00EF38000,"Elden: Path of the Forgotten",,playable,2020-12-15 00:33:19
@@ -1070,6 +1070,7 @@
010017B0102A8000,"Emma: Lost in Memories",nvdec,playable,2021-01-28 16:19:10
010068300E08E000,"Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo -",gpu;nvdec,ingame,2022-11-20 16:18:45
01007A4008486000,"Enchanting Mahjong Match",gpu,ingame,2020-04-17 22:01:31
0100EF901E552000,"ENDER MAGNOLIA: Bloom in the Mist",deadlock,boots,2025-01-22 17:59:00
01004F3011F92000,"Endless Fables: Dark Moor",gpu;nvdec,ingame,2021-03-07 15:31:03
010067B017588000,"Endless Ocean™ Luminous",services-horizon;crash,ingame,2024-05-30 02:05:57
0100B8700BD14000,"Energy Cycle Edge",services,ingame,2021-11-30 05:02:31
@@ -1123,7 +1124,7 @@
01005C10136CA000,"Fantasy Tavern Sextet -Vol.2 Adventurer's Days-",gpu;slow;crash,ingame,2021-11-06 02:57:29
010022700E7D6000,"FAR: Lone Sails",,playable,2022-09-06 16:33:05
0100C9E00FD62000,"Farabel",,playable,2020-08-03 17:47:28
,"Farm Expert 2019 for Nintendo Switch",,playable,2020-07-09 21:42:57
0100ECD00C806000,"Farm Expert 2019 for Nintendo Switch",,playable,2020-07-09 21:42:57
01000E400ED98000,"Farm Mystery",nvdec,playable,2022-09-06 16:46:47
010086B00BB50000,"Farm Together",,playable,2021-01-19 20:01:19
0100EB600E914000,"Farming Simulator 20",nvdec,playable,2021-06-13 10:52:44
@@ -1246,12 +1247,12 @@
0100ECE00C0C4000,"Fury Unleashed",crash;services,ingame,2020-10-18 11:52:40
010070000ED9E000,"Fury Unleashed Demo",,playable,2020-10-08 20:09:21
0100E1F013674000,"FUSER™",nvdec;UE4,playable,2022-10-17 20:58:32
,"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
010055801134E000,"FUZE Player",online-broken;vulkan-backend-bug,ingame,2022-10-18 12:23:53
0100EAD007E98000,"FUZE4 Nintendo Switch",vulkan-backend-bug,playable,2022-09-06 19:25:01
010067600F1A0000,"FuzzBall",crash,nothing,2021-03-29 20:13:21
,"G-MODE Archives 06 The strongest ever Julia Miyamoto",,playable,2020-10-15 13:06:26
0100275011e54000,"G-MODE Archives 06 The strongest ever Julia Miyamoto",,playable,2020-10-15 13:06:26
0100EB10108EA000,"G.I. Joe: Operation Blackout",UE4;crash,boots,2020-11-21 12:37:44
010048600B14E000,"Gal Metal",,playable,2022-07-27 20:57:48
010024700901A000,"Gal*Gun 2",nvdec;UE4,playable,2022-07-27 12:45:37
@@ -1370,7 +1371,7 @@
01006F80082E4000,"GUILTY GEAR XX ACCENT CORE PLUS R",nvdec,playable,2021-01-13 09:28:33
01003C6008940000,"GUNBIRD for Nintendo Switch",32-bit,playable,2021-06-04 19:16:01
0100BCB00AE98000,"GUNBIRD2 for Nintendo Switch",,playable,2020-10-10 14:41:16
,"Gunka o haita neko",gpu;nvdec,ingame,2020-08-25 12:37:56
01003FF010312000,"Gunka o haita neko",gpu;nvdec,ingame,2020-08-25 12:37:56
010061000D318000,"Gunman Clive HD Collection",,playable,2020-10-09 12:17:35
01006D4003BCE000,"Guns, Gore and Cannoli 2",online,playable,2021-01-06 18:43:59
01008C800E654000,"Gunvolt Chronicles Luminous Avenger iX - Retail Version",,playable,2020-06-16 22:47:07
@@ -1564,7 +1565,7 @@
0100BDC00A664000,"KAMEN RIDER CLIMAX SCRAMBLE",nvdec;ldn-untested,playable,2024-07-03 08:51:11
0100A9801180E000,"KAMEN RIDER memory of heroez / Premium Sound Edition",,playable,2022-12-06 03:14:26
010085300314E000,"KAMIKO",,playable,2020-05-13 12:48:57
,"Kangokuto Mary Skelter Finale",audio;crash,ingame,2021-01-09 22:39:28
010042C011736000,"Kangokuto Mary Skelter Finale",audio;crash,ingame,2021-01-09 22:39:28
01007FD00DB20000,"Katakoi Contrast - collection of branch -",nvdec,playable,2022-12-09 09:41:26
0100D7000C2C6000,"Katamari Damacy REROLL",,playable,2022-08-02 21:35:05
0100F9800EDFA000,"KATANA KAMI: A Way of the Samurai Story",slow,playable,2022-04-09 10:40:16
@@ -1581,7 +1582,7 @@
0100FB400D832000,"KILL la KILL -IF",,playable,2020-06-09 14:47:08
010011B00910C000,"Kill The Bad Guy",,playable,2020-05-12 22:16:10
0100F2900B3E2000,"Killer Queen Black",ldn-untested;online,playable,2021-04-08 12:46:18
,"Kin'iro no Corda Octave",,playable,2020-09-22 13:23:12
010014A00C5E0000,"Kin'iro no Corda Octave",,playable,2020-09-22 13:23:12
010089000F0E8000,"Kine",UE4,playable,2022-09-14 14:28:37
0100E6B00FFBA000,"King Lucas",,playable,2022-09-21 19:43:23
0100B1300783E000,"King Oddball",,playable,2020-05-13 13:47:57
@@ -1612,7 +1613,7 @@
01009EF00DDB4000,"Knockout City™",services;online-broken,boots,2022-12-09 09:48:58
0100C57019BA2000,"Koa and the Five Pirates of Mara",gpu,ingame,2024-07-11 16:14:44
01001E500401C000,"Koi DX",,playable,2020-05-11 21:37:51
,"Koi no Hanasaku Hyakkaen",32-bit;gpu;nvdec,ingame,2020-10-03 14:17:10
010052300F612000,"Koi no Hanasaku Hyakkaen",32-bit;gpu;nvdec,ingame,2020-10-03 14:17:10
01005D200C9AA000,"Koloro",,playable,2022-08-03 12:34:02
0100464009294000,"Kona",,playable,2022-08-03 12:48:19
010016C011AAA000,"Kono Subarashii Sekai ni Shukufuku o Kono Yokubo no Isho ni Choai o",,playable,2023-04-26 09:51:08
@@ -1779,8 +1780,8 @@
0100EC000CE24000,"Mech Rage",,playable,2020-11-18 12:30:16
0100C4F005EB4000,"Mecho Tales",,playable,2022-08-04 17:03:19
0100E4600D31A000,"Mechstermination Force",,playable,2024-07-04 05:39:15
,"Medarot Classics Plus Kabuto Ver",,playable,2020-11-21 11:31:18
,"Medarot Classics Plus Kuwagata Ver",,playable,2020-11-21 11:30:40
01007580124C0000,"Medarot Classics Plus Kabuto Ver",,playable,2020-11-21 11:31:18
0100228012682000,"Medarot Classics Plus Kuwagata Ver",,playable,2020-11-21 11:30:40
0100BBC00CB9A000,"Mega Mall Story",slow,playable,2022-08-04 17:10:58
0100B0C0086B0000,"Mega Man 11",,playable,2021-04-26 12:07:53
010038E016264000,"Mega Man Battle Network Legacy Collection Vol. 1",,playable,2023-04-25 03:55:57
@@ -1797,7 +1798,7 @@
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
010062F011E7C000,"Memory Lane",UE4,playable,2022-10-05 14:31:03
0100EBE00D5B0000,"Meow Motors",UE4;gpu,ingame,2020-12-18 00:24:01
0100273008FBC000,"Mercenaries Saga Chronicles",,playable,2021-01-10 12:48:19
@@ -1873,7 +1874,7 @@
010093A01305C000,"Monster Hunter Rise Demo",online-broken;ldn-works;demo,playable,2022-10-18 23:04:17
0100E21011446000,"Monster Hunter Stories 2: Wings of Ruin",services,ingame,2022-07-10 19:27:30
010042501329E000,"MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version",demo,playable,2022-11-13 22:20:26
,"Monster Hunter XX Demo",32-bit;cpu,nothing,2020-03-22 10:12:28
0100C51003B46000,"Monster Hunter XX Demo",32-bit;cpu,nothing,2020-03-22 10:12:28
0100C3800049C000,"Monster Hunter XX Nintendo Switch Ver ( Double Cross )",,playable,2024-07-21 14:08:09
010088400366E000,"Monster Jam Crush It!",UE4;nvdec;online,playable,2021-04-08 19:29:27
010095C00F354000,"Monster Jam Steel Titans",crash;nvdec;UE4,menus,2021-11-14 09:45:38
@@ -1917,7 +1918,7 @@
010035901046C000,"Mushroom Quest",,playable,2020-05-17 13:07:08
0100700006EF6000,"Mushroom Wars 2",nvdec,playable,2020-09-28 15:26:08
010046400F310000,"Music Racer",,playable,2020-08-10 08:51:23
,"Musou Orochi 2 Ultimate",crash;nvdec,boots,2021-04-09 19:39:16
0100153006300000,"Musou Orochi 2 Ultimate",crash;nvdec,boots,2021-04-09 19:39:16
0100F6000EAA8000,"Must Dash Amigos",,playable,2022-09-20 16:45:56
01007B6006092000,"MUSYNX",,playable,2020-05-08 14:24:43
0100C3E00ACAA000,"Mutant Football League: Dynasty Edition",online-broken,playable,2022-08-05 17:01:51
@@ -1948,7 +1949,7 @@
0100A6F00AC70000,"NAIRI: Tower of Shirin",nvdec,playable,2020-08-09 19:49:12
010002F001220000,"NAMCO MUSEUM",ldn-untested,playable,2024-08-13 07:52:21
0100DAA00AEE6000,"NAMCO MUSEUM™ ARCADE PAC™",,playable,2021-06-07 21:44:50
,"NAMCOT COLLECTION",audio,playable,2020-06-25 13:35:22
010039F010E14000,"NAMCOT COLLECTION",audio,playable,2020-06-25 13:35:22
010072B00BDDE000,"Narcos: Rise of the Cartels",UE4;crash;nvdec,boots,2021-03-22 13:18:47
01006BB00800A000,"NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst",nvdec,playable,2024-06-16 14:58:05
010084D00CF5E000,"NARUTO SHIPPUDEN™: Ultimate Ninja® STORM 4 ROAD TO BORUTO",,playable,2024-06-29 13:04:22
@@ -2089,11 +2090,11 @@
0100F9D00C186000,"Olympia Soiree",,playable,2022-12-04 21:07:12
0100A8B00E14A000,"Olympic Games Tokyo 2020 The Official Video Game™",ldn-untested;nvdec;online,playable,2021-01-06 01:20:24
01001D600E51A000,"Omega Labyrinth Life",,playable,2021-02-23 21:03:03
,"Omega Vampire",nvdec,playable,2020-10-17 19:15:35
01005DE00CA34000,"Omega Vampire",nvdec,playable,2020-10-17 19:15:35
0100CDC00C40A000,"Omensight: Definitive Edition",UE4;crash;nvdec,ingame,2020-07-26 01:45:14
01006DB00D970000,"OMG Zombies!",32-bit,playable,2021-04-12 18:04:45
010014E017B14000,"OMORI",,playable,2023-01-07 20:21:02
,"Once Upon A Coma",nvdec,playable,2020-08-01 12:09:39
0100A5F011800000,"Once Upon A Coma",nvdec,playable,2020-08-01 12:09:39
0100BD3006A02000,"One More Dungeon",,playable,2021-01-06 09:10:58
010076600FD64000,"One Person Story",,playable,2020-07-14 11:51:02
0100774009CF6000,"ONE PIECE Pirate Warriors 3 Deluxe Edition",nvdec,playable,2020-05-10 06:23:52
@@ -2184,7 +2185,7 @@
010062B01525C000,"Persona 4 Golden",,playable,2024-08-07 17:48:07
01005CA01580E000,"Persona 5 Royal",gpu,ingame,2024-08-17 21:45:15
010087701B092000,"Persona 5 Tactica",,playable,2024-04-01 22:21:03
,"Persona 5: Scramble",deadlock,boots,2020-10-04 03:22:29
0100E4F010D92000,"Persona 5: Scramble",deadlock,boots,2020-10-04 03:22:29
0100801011C3E000,"Persona® 5 Strikers",nvdec;mac-bug,playable,2023-09-26 09:36:01
010044400EEAE000,"Petoons Party",nvdec,playable,2021-03-02 21:07:58
010053401147C000,"PGA TOUR 2K21",deadlock;nvdec,ingame,2022-10-05 21:53:50
@@ -2273,7 +2274,7 @@
0100D1C01C194000,"Powerful Pro Baseball 2024-2025",gpu,ingame,2024-08-25 06:40:48
01008E100E416000,"PowerSlave Exhumed",gpu,ingame,2023-07-31 23:19:10
010054F01266C000,"Prehistoric Dude",gpu,ingame,2020-10-12 12:38:48
,"Pretty Princess Magical Coordinate",,playable,2020-10-15 11:43:41
0100DB200D3E4000,"Pretty Princess Magical Coordinate",,playable,2020-10-15 11:43:41
01007F00128CC000,"Pretty Princess Party",,playable,2022-10-19 17:23:58
010009300D278000,"Preventive Strike",nvdec,playable,2022-10-06 10:55:51
0100210019428000,"Prince of Persia The Lost Crown",crash,ingame,2024-06-08 21:31:58
@@ -2294,13 +2295,13 @@
0100ACE00DAB6000,"Project Nimbus: Complete Edition",nvdec;UE4;vulkan-backend-bug,playable,2022-08-10 17:35:43
01002980140F6000,"Project TRIANGLE STRATEGY™ Debut Demo",UE4;demo,playable,2022-10-24 21:40:27
0100BDB01150E000,"Project Warlock",,playable,2020-06-16 10:50:41
,"Psikyo Collection Vol 1",32-bit,playable,2020-10-11 13:18:47
01009F100BC52000,"Psikyo Collection Vol 1",32-bit,playable,2020-10-11 13:18:47
0100A2300DB78000,"Psikyo Collection Vol. 3",,ingame,2021-06-07 02:46:23
01009D400C4A8000,"Psikyo Collection Vol.2",32-bit,playable,2021-06-07 03:22:07
01007A200F2E2000,"Psikyo Shooting Stars Alpha",32-bit,playable,2021-04-13 12:03:43
0100D7400F2E4000,"Psikyo Shooting Stars Bravo",32-bit,playable,2021-06-14 12:09:07
0100EC100A790000,"PSYVARIAR DELTA",nvdec,playable,2021-01-20 13:01:46
,"Puchitto kurasutā",Need-Update;crash;services,menus,2020-07-04 16:44:28
0100AE700F184000,"Puchitto kurasutā",Need-Update;crash;services,menus,2020-07-04 16:44:28
0100D61010526000,"Pulstario",,playable,2022-10-06 11:02:01
01009AE00B788000,"Pumped BMX Pro",nvdec;online-broken,playable,2022-09-20 17:40:50
01006C10131F6000,"Pumpkin Jack",nvdec;UE4,playable,2022-10-13 12:52:32
@@ -2325,7 +2326,7 @@
0100DCF00F13A000,"Queen's Quest 4: Sacred Truce",nvdec,playable,2022-10-13 12:59:21
0100492012378000,"Quell",gpu,ingame,2021-06-11 15:59:53
01001DE005012000,"Quest of Dungeons",,playable,2021-06-07 10:29:22
,"QuietMansion2",,playable,2020-09-03 14:59:35
010067D011E68000,"QuietMansion2",,playable,2020-09-03 14:59:35
0100AF100EE76000,"Quiplash 2 InterLASHional: The Say Anything Party Game!",online-working,playable,2022-10-19 17:43:45
0100E5400BE64000,"R-Type Dimensions EX",,playable,2020-10-09 12:04:43
0100F930136B6000,"R-Type® Final 2",slow;nvdec;UE4,ingame,2022-10-30 21:46:29
@@ -2383,7 +2384,7 @@
01007A800D520000,"Refunct",UE4,playable,2020-12-15 22:46:21
0100FDF0083A6000,"Regalia: Of Men and Monarchs - Royal Edition",,playable,2022-08-11 12:24:01
01005FD00F15A000,"Regions of Ruin",,playable,2020-08-05 11:38:58
,"Reine des Fleurs",cpu;crash,boots,2020-09-27 18:50:39
0100B5800C0E4000,"Reine des Fleurs",cpu;crash,boots,2020-09-27 18:50:39
0100F1900B144000,"REKT! High Octane Stunts",online,playable,2020-09-28 12:33:56
01002AD013C52000,"Relicta",nvdec;UE4,playable,2022-10-31 12:48:33
010095900B436000,"RemiLore",,playable,2021-06-03 18:58:15
@@ -2495,7 +2496,7 @@
01002DF00F76C000,"SAMURAI SHODOWN",UE4;crash;nvdec,menus,2020-09-06 02:17:00
0100F6800F48E000,"SAMURAI SHODOWN NEOGEO COLLECTION",nvdec,playable,2021-06-14 17:12:56
0100B6501A360000,"Samurai Warrior",,playable,2023-02-27 18:42:38
,"Sangoku Rensenki ~Otome no Heihou!~",gpu;nvdec,ingame,2020-10-17 19:13:14
01000EA00B23C000,"Sangoku Rensenki ~Otome no Heihou!~",gpu;nvdec,ingame,2020-10-17 19:13:14
0100A4700BC98000,"Satsujin Tantei Jack the Ripper",,playable,2021-06-21 16:32:54
0100F0000869C000,"Saturday Morning RPG",nvdec,playable,2022-08-12 12:41:50
01006EE00380C000,"Sausage Sports Club",gpu,ingame,2021-01-10 05:37:17
@@ -2532,7 +2533,7 @@
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
0100B3C014BDA000,"SEGA Genesis™ Nintendo Switch Online",crash;regression,nothing,2022-04-11 07:27:21
,"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
0100D1800D902000,"SENRAN KAGURA Peach Ball",,playable,2021-06-03 15:12:10
0100E0C00ADAC000,"SENRAN KAGURA Reflexions",,playable,2020-03-23 19:15:23
@@ -2585,7 +2586,7 @@
0100B2E00F13E000,"Shipped",,playable,2020-11-21 14:22:32
01000E800FCB4000,"Ships",,playable,2021-06-11 16:14:37
01007430122D0000,"Shiren the Wanderer: The Tower of Fortune and the Dice of Fate",nvdec,playable,2022-10-20 11:44:36
,"Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~",cpu;crash,boots,2020-09-27 19:01:25
010027300A660000,"Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~",cpu;crash,boots,2020-09-27 19:01:25
01000244016BAE00,"Shiro0",gpu,ingame,2024-01-13 08:54:39
0100CCE00DDB6000,"Shoot 1UP DX",,playable,2020-12-13 12:32:47
01001180021FA000,"Shovel Knight: Specter of Torment",,playable,2020-05-30 08:34:17
@@ -2626,7 +2627,7 @@
0100C52011460000,"Sky: Children of the Light",cpu;online-broken,nothing,2023-02-23 10:57:10
010041C01014E000,"Skybolt Zack",,playable,2021-04-12 18:28:00
0100A0A00D1AA000,"SKYHILL",,playable,2021-03-05 15:19:11
,"Skylanders Imaginators",crash;services,boots,2020-05-30 18:49:18
0100CCC0002E6000,"Skylanders Imaginators",crash;services,boots,2020-05-30 18:49:18
010021A00ABEE000,"SKYPEACE",,playable,2020-05-29 14:14:30
0100EA400BF44000,"SkyScrappers",,playable,2020-05-28 22:11:25
0100F3C00C400000,"SkyTime",slow,ingame,2020-05-30 09:24:51
@@ -2681,7 +2682,7 @@
01005EA01C0FC000,"SONIC X SHADOW GENERATIONS",crash,ingame,2025-01-07 04:20:45
010064F00C212000,"Soul Axiom Rebooted",nvdec;slow,ingame,2020-09-04 12:41:01
0100F2100F0B2000,"Soul Searching",,playable,2020-07-09 18:39:07
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken,playable,2024-07-08 17:47:28
01008F2005154000,"South Park™: The Fractured but Whole™ - Standard Edition",slow;online-broken;vulkan-backend-bug;gpu,ingame,2025-01-21 17:35:10
0100B9F00C162000,"Space Blaze",,playable,2020-08-30 16:18:05
010005500E81E000,"Space Cows",UE4;crash,menus,2020-06-15 11:33:20
0100707011722000,"Space Elite Force",,playable,2020-11-27 15:21:05
@@ -2797,7 +2798,7 @@
0100681011B56000,"Struggling",,playable,2020-10-15 20:37:03
0100AF000B4AE000,"Stunt Kite Party",nvdec,playable,2021-01-25 17:16:56
0100C5500E7AE000,"STURMWIND EX",audio;32-bit,playable,2022-09-16 12:01:39
,"Subarashiki Kono Sekai -Final Remix-",services;slow,ingame,2020-02-10 16:21:51
01001C1009892000,"Subarashiki Kono Sekai -Final Remix-",services;slow,ingame,2020-02-10 16:21:51
010001400E474000,"Subdivision Infinity DX",UE4;crash,boots,2021-03-03 14:26:46
0100E6400BCE8000,"Sublevel Zero Redux",,playable,2022-09-16 12:30:03
0100EDA00D866000,"Submerged",nvdec;UE4;vulkan-backend-bug,playable,2022-08-16 15:17:01
@@ -2846,9 +2847,9 @@
0100284007D6C000,"Super One More Jump",,playable,2022-08-17 16:47:47
01001F90122B2000,"Super Punch Patrol",,playable,2024-07-12 19:49:02
0100331005E8E000,"Super Putty Squad",gpu;32-bit,ingame,2024-04-29 15:51:54
,"SUPER ROBOT WARS T",online,playable,2021-03-25 11:00:40
,"SUPER ROBOT WARS V",online,playable,2020-06-23 12:56:37
,"SUPER ROBOT WARS X",online,playable,2020-08-05 19:18:51
01006C900CC60000,"SUPER ROBOT WARS T",online,playable,2021-03-25 11:00:40
0100CA400E300000,"SUPER ROBOT WARS V",online,playable,2020-06-23 12:56:37
010026800E304000,"SUPER ROBOT WARS X",online,playable,2020-08-05 19:18:51
01004CF00A60E000,"Super Saurio Fly",nvdec,playable,2020-08-06 13:12:14
010039700D200000,"Super Skelemania",,playable,2020-06-07 22:59:50
01006A800016E000,"Super Smash Bros.™ Ultimate",gpu;crash;nvdec;ldn-works;intel-vendor-bug,ingame,2024-09-14 23:05:21
@@ -3014,7 +3015,7 @@
010085A00C5E8000,"The Lord of the Rings: Adventure Card Game - Definitive Edition",online-broken,menus,2022-09-16 15:19:32
01008A000A404000,"The Lost Child",nvdec,playable,2021-02-23 15:44:20
0100BAB00A116000,"The Low Road",,playable,2021-02-26 13:23:22
,"The Mahjong",Needs Update;crash;services,nothing,2021-04-01 22:06:22
01005F3006AFE000,"The Mahjong",Needs Update;crash;services,nothing,2021-04-01 22:06:22
0100DC300AC78000,"The Messenger",,playable,2020-03-22 13:51:37
0100DEC00B2BC000,"The Midnight Sanctuary",nvdec;UE4;vulkan-backend-bug,playable,2022-10-03 17:17:32
0100F1B00B456000,"The MISSING: J.J. Macfield and the Island of Memories",,playable,2022-08-22 19:36:18
@@ -3060,7 +3061,7 @@
010064E00ECBC000,"The Unicorn Princess",,playable,2022-09-16 16:20:56
0100BCF00E970000,"The Vanishing of Ethan Carter",UE4,playable,2021-06-09 17:14:47
0100D0500B0A6000,"The VideoKid",nvdec,playable,2021-01-06 09:28:24
,"The Voice",services,menus,2020-07-28 20:48:49
01008CF00BA38000,"The Voice",services,menus,2020-07-28 20:48:49
010056E00B4F4000,"The Walking Dead: A New Frontier",,playable,2022-09-21 13:40:48
010099100B6AC000,"The Walking Dead: Season Two",,playable,2020-08-09 12:57:06
010029200B6AA000,"The Walking Dead: The Complete First Season",,playable,2021-06-04 13:10:56
@@ -3348,7 +3349,7 @@
01001C400482C000,"Wunderling DX",audio;crash,ingame,2022-09-10 13:20:12
01003B401148E000,"Wurroom",,playable,2020-10-07 22:46:21
010081700EDF4000,"WWE 2K Battlegrounds",nvdec;online-broken;UE4,playable,2022-10-07 12:44:40
010009800203E000,"WWE 2K18",nvdec,playable,2023-10-21 17:22:01
010009800203E000,"WWE 2K18",nvdec;online-broken,ingame,2025-01-17 11:36:56
0100DF100B97C000,"X-Morph: Defense",,playable,2020-06-22 11:05:31
0100D0B00FB74000,"XCOM® 2 Collection",gpu;crash,ingame,2022-10-04 09:38:30
0100CC9015360000,"XEL",gpu,ingame,2022-10-03 10:19:39
@@ -3376,7 +3377,7 @@
010022F00DA66000,"Yooka-Laylee and the Impossible Lair",,playable,2021-03-05 17:32:21
01006000040C2000,"Yoshis Crafted World™",gpu;audout,ingame,2021-08-30 13:25:51
0100AE800C9C6000,"Yoshis Crafted World™ Demo",gpu,boots,2020-12-16 14:57:40
,"Yoshiwara Higanbana Kuon no Chigiri",nvdec,playable,2020-10-17 19:14:46
0100BBA00B23E000,"Yoshiwara Higanbana Kuon no Chigiri",nvdec,playable,2020-10-17 19:14:46
01003A400C3DA800,"YouTube",,playable,2024-06-08 05:24:10
00100A7700CCAA40,"Youtubers Life00",nvdec,playable,2022-09-03 14:56:19
0100E390124D8000,"Ys IX: Monstrum Nox",,playable,2022-06-12 04:14:42
@@ -3386,7 +3387,7 @@
01002D60188DE000,"Yu-Gi-Oh! Rush Duel: Dawn of the Battle Royale!! Let's Go! Go Rush!!",crash,ingame,2023-03-17 01:54:01
010037D00DBDC000,"YU-NO: A girl who chants love at the bound of this world.",nvdec,playable,2021-01-26 17:03:52
0100B56011502000,"Yumeutsutsu Re:After",,playable,2022-11-20 16:09:06
,"Yunohana Spring! - Mellow Times -",audio;crash,menus,2020-09-27 19:27:40
0100DE200C0DA000,"Yunohana Spring! - Mellow Times -",audio;crash,menus,2020-09-27 19:27:40
0100307011C44000,"Yuppie Psycho: Executive Edition",crash,ingame,2020-12-11 10:37:06
0100FC900963E000,"Yuri",,playable,2021-06-11 13:08:50
010092400A678000,"Zaccaria Pinball",online-broken,playable,2022-09-03 15:44:28
@@ -3397,7 +3398,7 @@
0100AAC00E692000,"Zenith",,playable,2022-09-17 09:57:02
0100A6A00894C000,"ZERO GUNNER 2- for Nintendo Switch",,playable,2021-01-04 20:17:14
01004B001058C000,"Zero Strain",services;UE4,menus,2021-11-10 07:48:32
,"Zettai kaikyu gakuen",gpu;nvdec,ingame,2020-08-25 15:15:54
010021300F69E000,"Zettai kaikyu gakuen",gpu;nvdec,ingame,2020-08-25 15:15:54
0100D7B013DD0000,"Ziggy the Chaser",,playable,2021-02-04 20:34:27
010086700EF16000,"ZikSquare",gpu,ingame,2021-11-06 02:02:48
010069C0123D8000,"Zoids Wild Blast Unleashed",nvdec,playable,2022-10-15 11:26:59
@@ -3409,7 +3410,7 @@
0100CD300A1BA000,"Zombillie",,playable,2020-07-23 17:42:23
01001EE00A6B0000,"Zotrix: Solar Division",,playable,2021-06-07 20:34:05
0100B9B00C6A4000,"この世の果てで恋を唄う少女YU-NO",audio,ingame,2021-01-22 07:00:16
,"スーパーファミコン Nintendo Switch Online",slow,ingame,2020-03-14 05:48:38
0100E8600C504000,"スーパーファミコン Nintendo Switch Online",slow,ingame,2020-03-14 05:48:38
01000BB01CB8A000,"トラブル・マギア ~訳アリ少女は未来を勝ち取るために異国の魔法学校へ留学します~(Trouble Magia ~Wakeari Shoujo wa Mirai o Kachitoru Tame ni Ikoku no Mahou Gakkou e Ryuugaku Shimasu~)",,nothing,2024-09-28 07:03:14
010065500B218000,"メモリーズオフ - Innocent Fille",,playable,2022-12-02 17:36:48
010032400E700000,"二ノ国 白き聖灰の女王",services;32-bit,menus,2023-04-16 17:11:06
@@ -3421,4 +3422,4 @@
0100936018EB4000,"牧場物語 Welcomeワンダフルライフ",crash,ingame,2023-04-25 19:43:52
0100F4401940A000,"超探偵事件簿 レインコード (Master Detective Archives: Rain Code)",crash,ingame,2024-02-12 20:58:31
010064801A01C000,"超次元ゲイム ネプテューヌ GameMaker R:Evolution",crash,nothing,2023-10-30 22:37:40
0100F3400332C000,"ブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
0100F3400332C000,"ブレイド2",deadlock;amd-vendor-bug,ingame,2024-03-28 14:31:41
1 title_id game_name labels status last_updated
167 01006C40086EA000 AeternoBlade nvdec playable 2020-12-14 20:06:48
168 0100B1C00949A000 AeternoBlade Demo nvdec playable 2021-02-09 14:39:26
169 01009D100EA28000 AeternoBlade II online-broken;UE4;vulkan-backend-bug playable 2022-09-12 21:11:18
170 0100B1C00949A000 AeternoBlade II Demo Version gpu;nvdec ingame 2021-02-09 15:10:19
171 01001B400D334000 AFL Evolution 2 slow;online-broken;UE4 playable 2022-12-07 12:45:56
172 0100DB100BBCE000 Afterparty playable 2022-09-22 12:23:19
173 010087C011C4E000 Agatha Christie - The ABC Murders playable 2020-10-27 17:08:23
477 010020700DE04000 Bear With Me: The Lost Robots nvdec playable 2021-02-27 14:20:10
478 010024200E97E800 Bear With Me: The Lost Robots Demo nvdec playable 2021-02-12 22:38:12
479 0100C0E014A4E000 Bear's Restaurant playable 2024-08-11 21:26:59
480 010045F00BF64000 BEAST Darling! ~Kemomimi Danshi to Himitsu no Ryou~ crash menus 2020-10-04 06:12:08
481 01009C300BB4C000 Beat Cop playable 2021-01-06 19:26:48
482 01002D20129FC000 Beat Me! online-broken playable 2022-10-16 21:59:26
483 01006B0014590000 BEAUTIFUL DESOLATION gpu;nvdec ingame 2022-10-26 10:34:38
703 01006A30124CA000 Chocobo GP gpu;crash ingame 2022-06-04 14:52:18
704 0100BF600BF26000 Chocobo's Mystery Dungeon EVERY BUDDY! slow playable 2020-05-26 13:53:13
705 01000BA0132EA000 Choices That Matter: And The Sun Went Out playable 2020-12-17 15:44:08
706 0100A1200CA3C000 Chou no Doku Hana no Kusari: Taishou Irokoi Ibun gpu;nvdec ingame 2020-09-28 17:58:04
707 010039A008E76000 ChromaGun playable 2020-05-26 12:56:42
708 010006800E13A000 Chronos: Before the Ashes UE4;gpu;nvdec ingame 2020-12-11 22:16:35
709 010039700BA7E000 Circle of Sumo playable 2020-05-22 12:45:21
769 0100CCB01B1A0000 COSMIC FANTASY COLLECTION ingame 2024-05-21 17:56:37
770 010067C00A776000 Cosmic Star Heroine playable 2021-02-20 14:30:47
771 01003DD00F94A000 COTTOn Reboot! [ コットン リブート! ] playable 2022-05-24 16:29:24
772 010077001526E000 Cotton/Guardian Saturn Tribute Games gpu boots 2022-11-27 21:00:51
773 01000E301107A000 Couch Co-Op Bundle Vol. 2 nvdec playable 2022-10-02 12:04:21
774 0100C1E012A42000 Country Tales playable 2021-06-17 16:45:39
775 01003370136EA000 Cozy Grove gpu ingame 2023-07-30 22:22:19
830 01003ED0099B0000 Danger Mouse: The Danger Games crash;online boots 2022-07-22 15:49:45
831 0100EFA013E7C000 Danger Scavenger nvdec playable 2021-04-17 15:53:04
832 0100417007F78000 Danmaku Unlimited 3 playable 2020-11-15 00:48:35
833 01000330105BE000 Darius Cozmic Collection playable 2021-02-19 20:59:06
834 010059C00BED4000 Darius Cozmic Collection Special Edition playable 2022-07-22 16:26:50
835 010015800F93C000 Dariusburst - Another Chronicle EX+ online playable 2021-04-05 14:21:43
836 01003D301357A000 Dark Arcana: The Carnival gpu;slow ingame 2022-02-19 08:52:28
859 010095A011A14000 Deadly Days playable 2020-11-27 13:38:55
860 0100BAC011928000 Deadly Premonition 2: A Blessing In Disguise playable 2021-06-15 14:12:36
861 0100EBE00F22E000 Deadly Premonition Origins 32-bit;nvdec playable 2024-03-25 12:47:46
862 010015600D814000 Dear Magi - Mahou Shounen Gakka - playable 2020-11-22 16:45:16
863 01000D60126B6000 Death and Taxes playable 2020-12-15 20:27:49
864 010012B011AB2000 Death Come True nvdec playable 2021-06-10 22:30:49
865 0100F3B00CF32000 Death Coming crash nothing 2022-02-06 07:43:03
902 010023600C704000 Deponia nvdec playable 2021-01-26 17:17:19
903 0100ED700469A000 Deru - The Art of Cooperation playable 2021-01-07 16:59:59
904 0100D4600D0E4000 Descenders gpu ingame 2020-12-10 15:22:36
905 0100D870102BC000 Desire remaster ver. crash boots 2021-01-17 02:34:37
906 010069500DD86000 Destiny Connect: Tick-Tock Travelers UE4;gpu;nvdec ingame 2020-12-16 12:20:36
907 01008BB011ED6000 Destrobots playable 2021-03-06 14:37:05
908 01009E701356A000 Destroy All Humans! gpu;nvdec;UE4 ingame 2023-01-14 22:23:53
909 010030600E65A000 Detective Dolittle playable 2021-03-02 14:03:59
910 01009C0009842000 Detective Gallo nvdec playable 2022-07-24 11:51:04
911 01002D400B0F6000 Detective Jinguji Saburo Prism of Eyes playable 2020-10-02 21:54:41
912 010007500F27C000 Detective Pikachu™ Returns playable 2023-10-07 10:24:59
913 010031B00CF66000 Devil Engine playable 2021-06-04 11:54:30
914 01002F000E8F2000 Devil Kingdom playable 2023-01-31 08:58:44
1057 01004F000B716000 Edna & Harvey: The Breakout – Anniversary Edition crash;nvdec ingame 2022-08-01 16:59:56
1058 01002550129F0000 Effie playable 2022-10-27 14:36:39
1059 0100CC0010A46000 Ego Protocol: Remastered nvdec playable 2020-12-16 20:16:35
1060 01004CC00B352000 Eiga Sumikko Gurashi Tobidasu Ehon to Himitsu no Ko Game de Asobo Ehon no Sekai playable 2020-11-12 00:11:50
1061 01003AD013BD2000 Eight Dragons nvdec playable 2022-10-27 14:47:28
1062 010020A01209C000 El Hijo - A Wild West Tale nvdec playable 2021-04-19 17:44:08
1063 0100B5B00EF38000 Elden: Path of the Forgotten playable 2020-12-15 00:33:19
1070 010017B0102A8000 Emma: Lost in Memories nvdec playable 2021-01-28 16:19:10
1071 010068300E08E000 Enchanted in the Moonlight - Kiryu, Chikage & Yukinojo - gpu;nvdec ingame 2022-11-20 16:18:45
1072 01007A4008486000 Enchanting Mahjong Match gpu ingame 2020-04-17 22:01:31
1073 0100EF901E552000 ENDER MAGNOLIA: Bloom in the Mist deadlock boots 2025-01-22 17:59:00
1074 01004F3011F92000 Endless Fables: Dark Moor gpu;nvdec ingame 2021-03-07 15:31:03
1075 010067B017588000 Endless Ocean™ Luminous services-horizon;crash ingame 2024-05-30 02:05:57
1076 0100B8700BD14000 Energy Cycle Edge services ingame 2021-11-30 05:02:31
1124 01005C10136CA000 Fantasy Tavern Sextet -Vol.2 Adventurer's Days- gpu;slow;crash ingame 2021-11-06 02:57:29
1125 010022700E7D6000 FAR: Lone Sails playable 2022-09-06 16:33:05
1126 0100C9E00FD62000 Farabel playable 2020-08-03 17:47:28
1127 0100ECD00C806000 Farm Expert 2019 for Nintendo Switch playable 2020-07-09 21:42:57
1128 01000E400ED98000 Farm Mystery nvdec playable 2022-09-06 16:46:47
1129 010086B00BB50000 Farm Together playable 2021-01-19 20:01:19
1130 0100EB600E914000 Farming Simulator 20 nvdec playable 2021-06-13 10:52:44
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 playable 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
1253 0100EAD007E98000 FUZE4 Nintendo Switch vulkan-backend-bug playable 2022-09-06 19:25:01
1254 010067600F1A0000 FuzzBall crash nothing 2021-03-29 20:13:21
1255 0100275011e54000 G-MODE Archives 06 The strongest ever Julia Miyamoto playable 2020-10-15 13:06:26
1256 0100EB10108EA000 G.I. Joe: Operation Blackout UE4;crash boots 2020-11-21 12:37:44
1257 010048600B14E000 Gal Metal playable 2022-07-27 20:57:48
1258 010024700901A000 Gal*Gun 2 nvdec;UE4 playable 2022-07-27 12:45:37
1371 01006F80082E4000 GUILTY GEAR XX ACCENT CORE PLUS R nvdec playable 2021-01-13 09:28:33
1372 01003C6008940000 GUNBIRD for Nintendo Switch 32-bit playable 2021-06-04 19:16:01
1373 0100BCB00AE98000 GUNBIRD2 for Nintendo Switch playable 2020-10-10 14:41:16
1374 01003FF010312000 Gunka o haita neko gpu;nvdec ingame 2020-08-25 12:37:56
1375 010061000D318000 Gunman Clive HD Collection playable 2020-10-09 12:17:35
1376 01006D4003BCE000 Guns, Gore and Cannoli 2 online playable 2021-01-06 18:43:59
1377 01008C800E654000 Gunvolt Chronicles Luminous Avenger iX - Retail Version playable 2020-06-16 22:47:07
1565 0100BDC00A664000 KAMEN RIDER CLIMAX SCRAMBLE nvdec;ldn-untested playable 2024-07-03 08:51:11
1566 0100A9801180E000 KAMEN RIDER memory of heroez / Premium Sound Edition playable 2022-12-06 03:14:26
1567 010085300314E000 KAMIKO playable 2020-05-13 12:48:57
1568 010042C011736000 Kangokuto Mary Skelter Finale audio;crash ingame 2021-01-09 22:39:28
1569 01007FD00DB20000 Katakoi Contrast - collection of branch - nvdec playable 2022-12-09 09:41:26
1570 0100D7000C2C6000 Katamari Damacy REROLL playable 2022-08-02 21:35:05
1571 0100F9800EDFA000 KATANA KAMI: A Way of the Samurai Story slow playable 2022-04-09 10:40:16
1582 0100FB400D832000 KILL la KILL -IF playable 2020-06-09 14:47:08
1583 010011B00910C000 Kill The Bad Guy playable 2020-05-12 22:16:10
1584 0100F2900B3E2000 Killer Queen Black ldn-untested;online playable 2021-04-08 12:46:18
1585 010014A00C5E0000 Kin'iro no Corda Octave playable 2020-09-22 13:23:12
1586 010089000F0E8000 Kine UE4 playable 2022-09-14 14:28:37
1587 0100E6B00FFBA000 King Lucas playable 2022-09-21 19:43:23
1588 0100B1300783E000 King Oddball playable 2020-05-13 13:47:57
1613 01009EF00DDB4000 Knockout City™ services;online-broken boots 2022-12-09 09:48:58
1614 0100C57019BA2000 Koa and the Five Pirates of Mara gpu ingame 2024-07-11 16:14:44
1615 01001E500401C000 Koi DX playable 2020-05-11 21:37:51
1616 010052300F612000 Koi no Hanasaku Hyakkaen 32-bit;gpu;nvdec ingame 2020-10-03 14:17:10
1617 01005D200C9AA000 Koloro playable 2022-08-03 12:34:02
1618 0100464009294000 Kona playable 2022-08-03 12:48:19
1619 010016C011AAA000 Kono Subarashii Sekai ni Shukufuku o Kono Yokubo no Isho ni Choai o playable 2023-04-26 09:51:08
1780 0100EC000CE24000 Mech Rage playable 2020-11-18 12:30:16
1781 0100C4F005EB4000 Mecho Tales playable 2022-08-04 17:03:19
1782 0100E4600D31A000 Mechstermination Force playable 2024-07-04 05:39:15
1783 01007580124C0000 Medarot Classics Plus Kabuto Ver playable 2020-11-21 11:31:18
1784 0100228012682000 Medarot Classics Plus Kuwagata Ver playable 2020-11-21 11:30:40
1785 0100BBC00CB9A000 Mega Mall Story slow playable 2022-08-04 17:10:58
1786 0100B0C0086B0000 Mega Man 11 playable 2021-04-26 12:07:53
1787 010038E016264000 Mega Man Battle Network Legacy Collection Vol. 1 playable 2023-04-25 03:55:57
1798 0100B360068B2000 Mekorama gpu boots 2021-06-17 16:37:21
1799 01000FA010340000 Melbits World nvdec;online menus 2021-11-26 13:51:22
1800 0100F68019636000 Melon Journey playable 2023-04-23 21:20:01
1801 010079C012896000 Memories Off -Innocent Fille- for Dearest playable 2020-08-04 07:31:22
1802 010062F011E7C000 Memory Lane UE4 playable 2022-10-05 14:31:03
1803 0100EBE00D5B0000 Meow Motors UE4;gpu ingame 2020-12-18 00:24:01
1804 0100273008FBC000 Mercenaries Saga Chronicles playable 2021-01-10 12:48:19
1874 010093A01305C000 Monster Hunter Rise Demo online-broken;ldn-works;demo playable 2022-10-18 23:04:17
1875 0100E21011446000 Monster Hunter Stories 2: Wings of Ruin services ingame 2022-07-10 19:27:30
1876 010042501329E000 MONSTER HUNTER STORIES 2: WINGS OF RUIN Trial Version demo playable 2022-11-13 22:20:26
1877 0100C51003B46000 Monster Hunter XX Demo 32-bit;cpu nothing 2020-03-22 10:12:28
1878 0100C3800049C000 Monster Hunter XX Nintendo Switch Ver ( Double Cross ) playable 2024-07-21 14:08:09
1879 010088400366E000 Monster Jam Crush It! UE4;nvdec;online playable 2021-04-08 19:29:27
1880 010095C00F354000 Monster Jam Steel Titans crash;nvdec;UE4 menus 2021-11-14 09:45:38
1918 010035901046C000 Mushroom Quest playable 2020-05-17 13:07:08
1919 0100700006EF6000 Mushroom Wars 2 nvdec playable 2020-09-28 15:26:08
1920 010046400F310000 Music Racer playable 2020-08-10 08:51:23
1921 0100153006300000 Musou Orochi 2 Ultimate crash;nvdec boots 2021-04-09 19:39:16
1922 0100F6000EAA8000 Must Dash Amigos playable 2022-09-20 16:45:56
1923 01007B6006092000 MUSYNX playable 2020-05-08 14:24:43
1924 0100C3E00ACAA000 Mutant Football League: Dynasty Edition online-broken playable 2022-08-05 17:01:51
1949 0100A6F00AC70000 NAIRI: Tower of Shirin nvdec playable 2020-08-09 19:49:12
1950 010002F001220000 NAMCO MUSEUM ldn-untested playable 2024-08-13 07:52:21
1951 0100DAA00AEE6000 NAMCO MUSEUM™ ARCADE PAC™ playable 2021-06-07 21:44:50
1952 010039F010E14000 NAMCOT COLLECTION audio playable 2020-06-25 13:35:22
1953 010072B00BDDE000 Narcos: Rise of the Cartels UE4;crash;nvdec boots 2021-03-22 13:18:47
1954 01006BB00800A000 NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst nvdec playable 2024-06-16 14:58:05
1955 010084D00CF5E000 NARUTO SHIPPUDEN™: Ultimate Ninja® STORM 4 ROAD TO BORUTO playable 2024-06-29 13:04:22
2090 0100F9D00C186000 Olympia Soiree playable 2022-12-04 21:07:12
2091 0100A8B00E14A000 Olympic Games Tokyo 2020 – The Official Video Game™ ldn-untested;nvdec;online playable 2021-01-06 01:20:24
2092 01001D600E51A000 Omega Labyrinth Life playable 2021-02-23 21:03:03
2093 01005DE00CA34000 Omega Vampire nvdec playable 2020-10-17 19:15:35
2094 0100CDC00C40A000 Omensight: Definitive Edition UE4;crash;nvdec ingame 2020-07-26 01:45:14
2095 01006DB00D970000 OMG Zombies! 32-bit playable 2021-04-12 18:04:45
2096 010014E017B14000 OMORI playable 2023-01-07 20:21:02
2097 0100A5F011800000 Once Upon A Coma nvdec playable 2020-08-01 12:09:39
2098 0100BD3006A02000 One More Dungeon playable 2021-01-06 09:10:58
2099 010076600FD64000 One Person Story playable 2020-07-14 11:51:02
2100 0100774009CF6000 ONE PIECE Pirate Warriors 3 Deluxe Edition nvdec playable 2020-05-10 06:23:52
2185 010062B01525C000 Persona 4 Golden playable 2024-08-07 17:48:07
2186 01005CA01580E000 Persona 5 Royal gpu ingame 2024-08-17 21:45:15
2187 010087701B092000 Persona 5 Tactica playable 2024-04-01 22:21:03
2188 0100E4F010D92000 Persona 5: Scramble deadlock boots 2020-10-04 03:22:29
2189 0100801011C3E000 Persona® 5 Strikers nvdec;mac-bug playable 2023-09-26 09:36:01
2190 010044400EEAE000 Petoons Party nvdec playable 2021-03-02 21:07:58
2191 010053401147C000 PGA TOUR 2K21 deadlock;nvdec ingame 2022-10-05 21:53:50
2274 0100D1C01C194000 Powerful Pro Baseball 2024-2025 gpu ingame 2024-08-25 06:40:48
2275 01008E100E416000 PowerSlave Exhumed gpu ingame 2023-07-31 23:19:10
2276 010054F01266C000 Prehistoric Dude gpu ingame 2020-10-12 12:38:48
2277 0100DB200D3E4000 Pretty Princess Magical Coordinate playable 2020-10-15 11:43:41
2278 01007F00128CC000 Pretty Princess Party playable 2022-10-19 17:23:58
2279 010009300D278000 Preventive Strike nvdec playable 2022-10-06 10:55:51
2280 0100210019428000 Prince of Persia The Lost Crown crash ingame 2024-06-08 21:31:58
2295 0100ACE00DAB6000 Project Nimbus: Complete Edition nvdec;UE4;vulkan-backend-bug playable 2022-08-10 17:35:43
2296 01002980140F6000 Project TRIANGLE STRATEGY™ Debut Demo UE4;demo playable 2022-10-24 21:40:27
2297 0100BDB01150E000 Project Warlock playable 2020-06-16 10:50:41
2298 01009F100BC52000 Psikyo Collection Vol 1 32-bit playable 2020-10-11 13:18:47
2299 0100A2300DB78000 Psikyo Collection Vol. 3 ingame 2021-06-07 02:46:23
2300 01009D400C4A8000 Psikyo Collection Vol.2 32-bit playable 2021-06-07 03:22:07
2301 01007A200F2E2000 Psikyo Shooting Stars Alpha 32-bit playable 2021-04-13 12:03:43
2302 0100D7400F2E4000 Psikyo Shooting Stars Bravo 32-bit playable 2021-06-14 12:09:07
2303 0100EC100A790000 PSYVARIAR DELTA nvdec playable 2021-01-20 13:01:46
2304 0100AE700F184000 Puchitto kurasutā Need-Update;crash;services menus 2020-07-04 16:44:28
2305 0100D61010526000 Pulstario playable 2022-10-06 11:02:01
2306 01009AE00B788000 Pumped BMX Pro nvdec;online-broken playable 2022-09-20 17:40:50
2307 01006C10131F6000 Pumpkin Jack nvdec;UE4 playable 2022-10-13 12:52:32
2326 0100DCF00F13A000 Queen's Quest 4: Sacred Truce nvdec playable 2022-10-13 12:59:21
2327 0100492012378000 Quell gpu ingame 2021-06-11 15:59:53
2328 01001DE005012000 Quest of Dungeons playable 2021-06-07 10:29:22
2329 010067D011E68000 QuietMansion2 playable 2020-09-03 14:59:35
2330 0100AF100EE76000 Quiplash 2 InterLASHional: The Say Anything Party Game! online-working playable 2022-10-19 17:43:45
2331 0100E5400BE64000 R-Type Dimensions EX playable 2020-10-09 12:04:43
2332 0100F930136B6000 R-Type® Final 2 slow;nvdec;UE4 ingame 2022-10-30 21:46:29
2384 01007A800D520000 Refunct UE4 playable 2020-12-15 22:46:21
2385 0100FDF0083A6000 Regalia: Of Men and Monarchs - Royal Edition playable 2022-08-11 12:24:01
2386 01005FD00F15A000 Regions of Ruin playable 2020-08-05 11:38:58
2387 0100B5800C0E4000 Reine des Fleurs cpu;crash boots 2020-09-27 18:50:39
2388 0100F1900B144000 REKT! High Octane Stunts online playable 2020-09-28 12:33:56
2389 01002AD013C52000 Relicta nvdec;UE4 playable 2022-10-31 12:48:33
2390 010095900B436000 RemiLore playable 2021-06-03 18:58:15
2496 01002DF00F76C000 SAMURAI SHODOWN UE4;crash;nvdec menus 2020-09-06 02:17:00
2497 0100F6800F48E000 SAMURAI SHODOWN NEOGEO COLLECTION nvdec playable 2021-06-14 17:12:56
2498 0100B6501A360000 Samurai Warrior playable 2023-02-27 18:42:38
2499 01000EA00B23C000 Sangoku Rensenki ~Otome no Heihou!~ gpu;nvdec ingame 2020-10-17 19:13:14
2500 0100A4700BC98000 Satsujin Tantei Jack the Ripper playable 2021-06-21 16:32:54
2501 0100F0000869C000 Saturday Morning RPG nvdec playable 2022-08-12 12:41:50
2502 01006EE00380C000 Sausage Sports Club gpu ingame 2021-01-10 05:37:17
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 nothing 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
2539 0100E0C00ADAC000 SENRAN KAGURA Reflexions playable 2020-03-23 19:15:23
2586 0100B2E00F13E000 Shipped playable 2020-11-21 14:22:32
2587 01000E800FCB4000 Ships playable 2021-06-11 16:14:37
2588 01007430122D0000 Shiren the Wanderer: The Tower of Fortune and the Dice of Fate nvdec playable 2022-10-20 11:44:36
2589 010027300A660000 Shiritsu Berubara Gakuen ~Versailles no Bara Re*imagination~ cpu;crash boots 2020-09-27 19:01:25
2590 01000244016BAE00 Shiro0 gpu ingame 2024-01-13 08:54:39
2591 0100CCE00DDB6000 Shoot 1UP DX playable 2020-12-13 12:32:47
2592 01001180021FA000 Shovel Knight: Specter of Torment playable 2020-05-30 08:34:17
2627 0100C52011460000 Sky: Children of the Light cpu;online-broken nothing 2023-02-23 10:57:10
2628 010041C01014E000 Skybolt Zack playable 2021-04-12 18:28:00
2629 0100A0A00D1AA000 SKYHILL playable 2021-03-05 15:19:11
2630 0100CCC0002E6000 Skylanders Imaginators crash;services boots 2020-05-30 18:49:18
2631 010021A00ABEE000 SKYPEACE playable 2020-05-29 14:14:30
2632 0100EA400BF44000 SkyScrappers playable 2020-05-28 22:11:25
2633 0100F3C00C400000 SkyTime slow ingame 2020-05-30 09:24:51
2682 01005EA01C0FC000 SONIC X SHADOW GENERATIONS crash ingame 2025-01-07 04:20:45
2683 010064F00C212000 Soul Axiom Rebooted nvdec;slow ingame 2020-09-04 12:41:01
2684 0100F2100F0B2000 Soul Searching playable 2020-07-09 18:39:07
2685 01008F2005154000 South Park™: The Fractured but Whole™ - Standard Edition slow;online-broken slow;online-broken;vulkan-backend-bug;gpu playable ingame 2024-07-08 17:47:28 2025-01-21 17:35:10
2686 0100B9F00C162000 Space Blaze playable 2020-08-30 16:18:05
2687 010005500E81E000 Space Cows UE4;crash menus 2020-06-15 11:33:20
2688 0100707011722000 Space Elite Force playable 2020-11-27 15:21:05
2798 0100681011B56000 Struggling playable 2020-10-15 20:37:03
2799 0100AF000B4AE000 Stunt Kite Party nvdec playable 2021-01-25 17:16:56
2800 0100C5500E7AE000 STURMWIND EX audio;32-bit playable 2022-09-16 12:01:39
2801 01001C1009892000 Subarashiki Kono Sekai -Final Remix- services;slow ingame 2020-02-10 16:21:51
2802 010001400E474000 Subdivision Infinity DX UE4;crash boots 2021-03-03 14:26:46
2803 0100E6400BCE8000 Sublevel Zero Redux playable 2022-09-16 12:30:03
2804 0100EDA00D866000 Submerged nvdec;UE4;vulkan-backend-bug playable 2022-08-16 15:17:01
2847 0100284007D6C000 Super One More Jump playable 2022-08-17 16:47:47
2848 01001F90122B2000 Super Punch Patrol playable 2024-07-12 19:49:02
2849 0100331005E8E000 Super Putty Squad gpu;32-bit ingame 2024-04-29 15:51:54
2850 01006C900CC60000 SUPER ROBOT WARS T online playable 2021-03-25 11:00:40
2851 0100CA400E300000 SUPER ROBOT WARS V online playable 2020-06-23 12:56:37
2852 010026800E304000 SUPER ROBOT WARS X online playable 2020-08-05 19:18:51
2853 01004CF00A60E000 Super Saurio Fly nvdec playable 2020-08-06 13:12:14
2854 010039700D200000 Super Skelemania playable 2020-06-07 22:59:50
2855 01006A800016E000 Super Smash Bros.™ Ultimate gpu;crash;nvdec;ldn-works;intel-vendor-bug ingame 2024-09-14 23:05:21
3015 010085A00C5E8000 The Lord of the Rings: Adventure Card Game - Definitive Edition online-broken menus 2022-09-16 15:19:32
3016 01008A000A404000 The Lost Child nvdec playable 2021-02-23 15:44:20
3017 0100BAB00A116000 The Low Road playable 2021-02-26 13:23:22
3018 01005F3006AFE000 The Mahjong Needs Update;crash;services nothing 2021-04-01 22:06:22
3019 0100DC300AC78000 The Messenger playable 2020-03-22 13:51:37
3020 0100DEC00B2BC000 The Midnight Sanctuary nvdec;UE4;vulkan-backend-bug playable 2022-10-03 17:17:32
3021 0100F1B00B456000 The MISSING: J.J. Macfield and the Island of Memories playable 2022-08-22 19:36:18
3061 010064E00ECBC000 The Unicorn Princess playable 2022-09-16 16:20:56
3062 0100BCF00E970000 The Vanishing of Ethan Carter UE4 playable 2021-06-09 17:14:47
3063 0100D0500B0A6000 The VideoKid nvdec playable 2021-01-06 09:28:24
3064 01008CF00BA38000 The Voice services menus 2020-07-28 20:48:49
3065 010056E00B4F4000 The Walking Dead: A New Frontier playable 2022-09-21 13:40:48
3066 010099100B6AC000 The Walking Dead: Season Two playable 2020-08-09 12:57:06
3067 010029200B6AA000 The Walking Dead: The Complete First Season playable 2021-06-04 13:10:56
3349 01001C400482C000 Wunderling DX audio;crash ingame 2022-09-10 13:20:12
3350 01003B401148E000 Wurroom playable 2020-10-07 22:46:21
3351 010081700EDF4000 WWE 2K Battlegrounds nvdec;online-broken;UE4 playable 2022-10-07 12:44:40
3352 010009800203E000 WWE 2K18 nvdec nvdec;online-broken playable ingame 2023-10-21 17:22:01 2025-01-17 11:36:56
3353 0100DF100B97C000 X-Morph: Defense playable 2020-06-22 11:05:31
3354 0100D0B00FB74000 XCOM® 2 Collection gpu;crash ingame 2022-10-04 09:38:30
3355 0100CC9015360000 XEL gpu ingame 2022-10-03 10:19:39
3377 010022F00DA66000 Yooka-Laylee and the Impossible Lair playable 2021-03-05 17:32:21
3378 01006000040C2000 Yoshi’s Crafted World™ gpu;audout ingame 2021-08-30 13:25:51
3379 0100AE800C9C6000 Yoshi’s Crafted World™ Demo gpu boots 2020-12-16 14:57:40
3380 0100BBA00B23E000 Yoshiwara Higanbana Kuon no Chigiri nvdec playable 2020-10-17 19:14:46
3381 01003A400C3DA800 YouTube playable 2024-06-08 05:24:10
3382 00100A7700CCAA40 Youtubers Life00 nvdec playable 2022-09-03 14:56:19
3383 0100E390124D8000 Ys IX: Monstrum Nox playable 2022-06-12 04:14:42
3387 01002D60188DE000 Yu-Gi-Oh! Rush Duel: Dawn of the Battle Royale!! Let's Go! Go Rush!! crash ingame 2023-03-17 01:54:01
3388 010037D00DBDC000 YU-NO: A girl who chants love at the bound of this world. nvdec playable 2021-01-26 17:03:52
3389 0100B56011502000 Yumeutsutsu Re:After playable 2022-11-20 16:09:06
3390 0100DE200C0DA000 Yunohana Spring! - Mellow Times - audio;crash menus 2020-09-27 19:27:40
3391 0100307011C44000 Yuppie Psycho: Executive Edition crash ingame 2020-12-11 10:37:06
3392 0100FC900963E000 Yuri playable 2021-06-11 13:08:50
3393 010092400A678000 Zaccaria Pinball online-broken playable 2022-09-03 15:44:28
3398 0100AAC00E692000 Zenith playable 2022-09-17 09:57:02
3399 0100A6A00894C000 ZERO GUNNER 2- for Nintendo Switch playable 2021-01-04 20:17:14
3400 01004B001058C000 Zero Strain services;UE4 menus 2021-11-10 07:48:32
3401 010021300F69E000 Zettai kaikyu gakuen gpu;nvdec ingame 2020-08-25 15:15:54
3402 0100D7B013DD0000 Ziggy the Chaser playable 2021-02-04 20:34:27
3403 010086700EF16000 ZikSquare gpu ingame 2021-11-06 02:02:48
3404 010069C0123D8000 Zoids Wild Blast Unleashed nvdec playable 2022-10-15 11:26:59
3410 0100CD300A1BA000 Zombillie playable 2020-07-23 17:42:23
3411 01001EE00A6B0000 Zotrix: Solar Division playable 2021-06-07 20:34:05
3412 0100B9B00C6A4000 この世の果てで恋を唄う少女YU-NO audio ingame 2021-01-22 07:00:16
3413 0100E8600C504000 スーパーファミコン Nintendo Switch Online slow ingame 2020-03-14 05:48:38
3414 01000BB01CB8A000 トラブル・マギア ~訳アリ少女は未来を勝ち取るために異国の魔法学校へ留学します~(Trouble Magia ~Wakeari Shoujo wa Mirai o Kachitoru Tame ni Ikoku no Mahou Gakkou e Ryuugaku Shimasu~) nothing 2024-09-28 07:03:14
3415 010065500B218000 メモリーズオフ - Innocent Fille playable 2022-12-02 17:36:48
3416 010032400E700000 二ノ国 白き聖灰の女王 services;32-bit menus 2023-04-16 17:11:06
3422 0100936018EB4000 牧場物語 Welcome!ワンダフルライフ crash ingame 2023-04-25 19:43:52
3423 0100F4401940A000 超探偵事件簿 レインコード (Master Detective Archives: Rain Code) crash ingame 2024-02-12 20:58:31
3424 010064801A01C000 超次元ゲイム ネプテューヌ GameMaker R:Evolution crash nothing 2023-10-30 22:37:40
3425 0100F3400332C000 ゼノブレイド2 deadlock;amd-vendor-bug ingame 2024-03-28 14:31:41

View File

@@ -78,5 +78,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// Controller Rumble Settings
/// </summary>
public RumbleConfigController Rumble { get; set; }
/// <summary>
/// Controller LED Settings
/// </summary>
public LedConfigController Led { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
namespace Ryujinx.Common.Configuration.Hid.Controller
{
public class LedConfigController
{
/// <summary>
/// Enable LED color changing by the emulator
/// </summary>
public bool EnableLed { get; set; }
/// <summary>
/// Ignores the color and disables the LED entirely.
/// </summary>
public bool TurnOffLed { get; set; }
/// <summary>
/// Ignores the color and uses the rainbow color functionality for the LED.
/// </summary>
public bool UseRainbow { get; set; }
/// <summary>
/// Packed RGB int of the color
/// </summary>
public uint LedColor { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable InconsistentNaming
namespace Ryujinx.Common.Helper
{
public static class RunningPlatform
{
public static bool IsMacOS => OperatingSystem.IsMacOS();
public static bool IsWindows => OperatingSystem.IsWindows();
public static bool IsLinux => OperatingSystem.IsLinux();
public static bool IsIntelMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.X64;
public static bool IsArmMac => IsMacOS && RuntimeInformation.OSArchitecture is Architecture.Arm64;
public static bool IsX64Windows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmWindows => IsWindows && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
public static bool IsX64Linux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.X64);
public static bool IsArmLinux => IsLinux && (RuntimeInformation.OSArchitecture is Architecture.Arm64);
}
}

View File

@@ -1,5 +1,6 @@
using Gommon;
using Gommon;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using System;
using System.Linq;
using System.Runtime.InteropServices;
@@ -8,19 +9,20 @@ namespace Ryujinx.Common
{
public static class TitleIDs
{
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new();
public static ReactiveObject<Optional<string>> CurrentApplication { get; } = new();
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{
switch (currentBackend)
{
case GraphicsBackend.Metal when !OperatingSystem.IsMacOS():
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
return GraphicsBackend.Vulkan;
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
return currentBackend;
}
if (!(OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture is Architecture.Arm64))
if (!RunningPlatform.IsArmMac)
return GraphicsBackend.Vulkan;
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan;
@@ -28,18 +30,28 @@ namespace Ryujinx.Common
public static readonly string[] GreatMetalTitles =
[
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"010076f0049a2000", // Bayonetta
"0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5
"0100187003A36000", // Pokémon: Let's Go, Evoli!
"010075a016a3a000", // Persona 4 Arena Ultimax
"0100187003A36000", // Pokémon: Let's Go, Eevee!
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
// These ones have small issues, but those happen on Vulkan as well:
"01006f8002326000", // Animal Crossings: New Horizons
"01009bf0072d4000", // Captain Toad: Treasure Tracker
"01009510001ca000", // Fast RMX
"01005CA01580E000", // Persona 5 Royale
"0100000000010000", // Super Mario Odyssey
//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:
"010015100b514000", // Super Mario Bros. Wonder
];
public static string GetDiscordGameAsset(string titleId)
@@ -47,93 +59,117 @@ namespace Ryujinx.Common
public static readonly string[] DiscordGameAssetKeys =
[
"010055d009f78000", // Fire Emblem: Three Houses
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
//All games are in Alphabetical order by Game name.
//Dragon Quest Franchise
"010008900705c000", // Dragon Quest Builders
"010042000a986000", // Dragon Quest Builders 2
//Fire Emblem Franchise
"0100a6301214e000", // Fire Emblem Engage
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
"010055d009f78000", // Fire Emblem: Three Houses
"0100f15003e64000", // Fire Emblem Warriors
"010071f0143ea000", // Fire Emblem Warriors: Three Hopes
"01007e3006dda000", // Kirby Star Allies
//Kirby Franchise
"01004d300c5ae000", // Kirby and the Forgotten Land
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01003fb00c5a8000", // Super Kirby Clash
"0100227010460000", // Kirby Fighters 2
"0100a8e016236000", // Kirby's Dream Buffet
"0100227010460000", // Kirby Fighters 2
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
"01007e3006dda000", // Kirby Star Allies
"01003fb00c5a8000", // Super Kirby Clash
//The Zelda Franchise
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
"01002da013484000", // The Legend of Zelda: Skyward Sword HD
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
"01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom
"01000b900d8b0000", // Cadence of Hyrule
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
//Luigi Franchise
"010048701995e000", // Luigi's Mansion 2 HD
"0100dca0064a6000", // Luigi's Mansion 3
//Metroid Franchise
"010093801237c000", // Metroid Dread
"010012101468c000", // Metroid Prime Remastered
"0100000000010000", // SUPER MARIO ODYSSEY
"0100ea80032ea000", // Super Mario Bros. U Deluxe
"01009b90006dc000", // Super Mario Maker 2
"010049900f546000", // Super Mario 3D All-Stars
"010049900F546001", // ^ 64
"010049900F546002", // ^ Sunshine
"010049900F546003", // ^ Galaxy
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010015100b514000", // Super Mario Bros. Wonder
"0100152000022000", // Mario Kart 8 Deluxe
"010036b0034e4000", // Super Mario Party
"01006fe013472000", // Mario Party Superstars
"0100965017338000", // Super Mario Party Jamboree
//Monster Hunter Franchise
"0100770008dd8000", // Monster Hunter Generations Ultimate
"0100b04011742000", // Monster Hunter Rise
//Mario Franchise
"01006d0017f7a000", // Mario & Luigi: Brothership
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"010067300059a000", // Mario + Rabbids: Kingdom Battle
"0100317013770000", // Mario + Rabbids: Sparks of Hope
"0100c9c00e25c000", // Mario Golf: Super Rush
"0100152000022000", // Mario Kart 8 Deluxe
"01006fe013472000", // Mario Party Superstars
"010019401051c000", // Mario Strikers: Battle League
"0100bde00862a000", // Mario Tennis Aces
"0100b99019412000", // Mario vs. Donkey Kong
"010049900f546000", // Super Mario 3D All-Stars
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
"010049900F546001", // Super Mario 64
"0100ea80032ea000", // Super Mario Bros. U Deluxe
"010015100b514000", // Super Mario Bros. Wonder
"010049900F546003", // Super Mario Galaxy
"01009b90006dc000", // Super Mario Maker 2
"0100000000010000", // SUPER MARIO ODYSSEY
"010036b0034e4000", // Super Mario Party
"0100965017338000", // Super Mario Party Jamboree
"0100bc0018138000", // Super Mario RPG
"010049900F546002", // Super Mario Sunshine
"0100a3900c3e2000", // Paper Mario: The Origami King
"0100ecd018ebe000", // Paper Mario: The Thousand-Year Door
"0100bc0018138000", // Super Mario RPG
"0100bde00862a000", // Mario Tennis Aces
"0100c9c00e25c000", // Mario Golf: Super Rush
"010019401051c000", // Mario Strikers: Battle League
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
"0100b99019412000", // Mario vs. Donkey Kong
//Pikmin Franchise
"0100aa80194b0000", // Pikmin 1
"0100d680194b2000", // Pikmin 2
"0100f4c009322000", // Pikmin 3 Deluxe
"0100b7c00933a000", // Pikmin 4
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"0100187003a36000", // Pokémon: Let's Go Eevee!
"0100abf008968000", // Pokémon Sword
"01008db008c2c000", // Pokémon Shield
//The Pokémon Franchise
"0100f4300bf2c000", // New Pokémon Snap
"0100000011d90000", // Pokémon Brilliant Diamond
"010018e011d92000", // Pokémon Shining Pearl
"01001f5010dfa000", // Pokémon Legends: Arceus
"01003d200baa2000", // Pokémon Mystery Dungeon - Rescue Team DX
"0100a3d008c5c000", // Pokémon Scarlet
"01008db008c2c000", // Pokémon Shield
"010018e011d92000", // Pokémon Shining Pearl
"0100abf008968000", // Pokémon Sword
"01008f6008c5e000", // Pokémon Violet
"0100b3f000be2000", // Pokkén Tournament DX
"0100f4300bf2c000", // New Pokémon Snap
"0100187003a36000", // Pokémon: Let's Go Eevee!
"010003f003a34000", // Pokémon: Let's Go Pikachu!
"01003bc0000a0000", // Splatoon 2 (US)
//Splatoon Franchise
"0100f8f0000a2000", // Splatoon 2 (EU)
"01003c700009c000", // Splatoon 2 (JP)
"01003bc0000a0000", // Splatoon 2 (US)
"0100c2500fc20000", // Splatoon 3
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
"010040600c5ce000", // Tetris 99
"0100277011f1a000", // Super Mario Bros. 35
"0100ad9012510000", // PAC-MAN 99
//NSO Membership games
"0100ccf019c8c000", // F-ZERO 99
"0100d870045b6000", // NES - Nintendo Switch Online
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100c62011050000", // GB - Nintendo Switch Online
"010012f017576000", // GBA - Nintendo Switch Online
"0100c9a00ece6000", // N64 - Nintendo Switch Online
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
"0100d870045b6000", // NES - Nintendo Switch Online
"0100ad9012510000", // PAC-MAN 99
"010040600c5ce000", // Tetris 99
"01008d300c50c000", // SNES - Nintendo Switch Online
"0100277011f1a000", // Super Mario Bros. 35
//Misc Nintendo 1st party games
"01000320000cc000", // 1-2 Switch
"0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp
"01006f8002326000", // Animal Crossing: New Horizons
@@ -148,33 +184,44 @@ namespace Ryujinx.Common
"01006a800016e000", // Super Smash Bros. Ultimate
"0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore
//Bayonetta Franchise
"010076f0049a2000", // Bayonetta
"01007960049a0000", // Bayonetta 2
"01004a4010fea000", // Bayonetta 3
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
//Persona Franchise
"0100dcd01525a000", // Persona 3 Portable
"010062b01525c000", // Persona 4 Golden
"010075a016a3a000", // Persona 4 Arena Ultimax
"010062b01525c000", // Persona 4 Golden
"01005ca01580e000", // Persona 5 Royal
"0100801011c3e000", // Persona 5 Strikers
"010087701b092000", // Persona 5 Tactica
"01009aa000faa000", // Sonic Mania
//Sonic Franchise
"01004ad014bf0000", // Sonic Frontiers
"01009aa000faa000", // Sonic Mania
"01005ea01c0fc000", // SONIC X SHADOW GENERATIONS
"01005ea01c0fc001", // ^
//Xenoblade Franchise
"0100ff500e34a000", // Xenoblade Chronicles - Definitive Edition
"0100e95004038000", // Xenoblade Chronicles 2
"010074f013262000", // Xenoblade Chronicles 3
//Misc Games
"010056e00853a000", // A Hat in Time
"0100fd1014726000", // Baldurs Gate: Dark Alliance
"0100dbf01000a000", // Burnout Paradise Remastered
"0100744001588000", // Cars 3: Driven to Win
"0100b41013c82000", // Cruis'n Blast
"010085900337e000", // Death Squared
"01001b300b9be000", // Diablo III: Eternal Collection
"01008c8012920000", // Dying Light Platinum Edition
"01001cc01b2d4000", // Goat Simulator 3
"01003620068ea000", // Hand of Fate 2
"010085500130a000", // Lego City: Undercover
"010073c01af34000", // LEGO Horizon Adventures
"0100770008dd8000", // Monster Hunter Generations Ultimate
"0100b04011742000", // Monster Hunter Rise
"0100853015e86000", // No Man's Sky
"01007bb017812000", // Portal
"0100abd01785c000", // Portal 2
@@ -190,6 +237,8 @@ namespace Ryujinx.Common
"01000a10041ea000", // The Elder Scrolls V: Skyrim
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
"010080b00ad66000", // Undertale
"010069401adb8000", // Unicorn Overlord
"0100534009ff2000", // Yonder - The cloud catcher chronicles
];
}
}

View File

@@ -0,0 +1,110 @@
using Gommon;
using System;
using System.Drawing;
using System.Threading.Tasks;
namespace Ryujinx.Common.Utilities
{
public static class Rainbow
{
public static bool CyclingEnabled { get; set; }
public static void Enable()
{
if (!CyclingEnabled)
{
CyclingEnabled = true;
Executor.ExecuteBackgroundAsync(async () =>
{
while (CyclingEnabled)
{
await Task.Delay(15);
Tick();
}
});
}
}
public static void Disable()
{
CyclingEnabled = false;
}
public static float Speed { get; set; } = 1;
public static Color Color { get; private set; } = Color.Blue;
public static void Tick()
{
Color = HsbToRgb((Color.GetHue() + Speed) / 360);
UpdatedHandler.Call(Color.ToArgb());
}
public static void Reset()
{
Color = Color.Blue;
UpdatedHandler.Clear();
}
public static event Action<int> Updated
{
add => UpdatedHandler.Add(value);
remove => UpdatedHandler.Remove(value);
}
internal static Event<int> UpdatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{
int r = 0, g = 0, b = 0;
if (saturation == 0)
{
r = g = b = (int)(brightness * 255.0f + 0.5f);
}
else
{
float h = (hue - (float)Math.Floor(hue)) * 6.0f;
float f = h - (float)Math.Floor(h);
float p = brightness * (1.0f - saturation);
float q = brightness * (1.0f - saturation * f);
float t = brightness * (1.0f - (saturation * (1.0f - f)));
switch ((int)h)
{
case 0:
r = (int)(brightness * 255.0f + 0.5f);
g = (int)(t * 255.0f + 0.5f);
b = (int)(p * 255.0f + 0.5f);
break;
case 1:
r = (int)(q * 255.0f + 0.5f);
g = (int)(brightness * 255.0f + 0.5f);
b = (int)(p * 255.0f + 0.5f);
break;
case 2:
r = (int)(p * 255.0f + 0.5f);
g = (int)(brightness * 255.0f + 0.5f);
b = (int)(t * 255.0f + 0.5f);
break;
case 3:
r = (int)(p * 255.0f + 0.5f);
g = (int)(q * 255.0f + 0.5f);
b = (int)(brightness * 255.0f + 0.5f);
break;
case 4:
r = (int)(t * 255.0f + 0.5f);
g = (int)(p * 255.0f + 0.5f);
b = (int)(brightness * 255.0f + 0.5f);
break;
case 5:
r = (int)(brightness * 255.0f + 0.5f);
g = (int)(p * 255.0f + 0.5f);
b = (int)(q * 255.0f + 0.5f);
break;
}
}
return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
}
}
}

View File

@@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
private static string GetDiskCachePath()
{
return GraphicsConfig.EnableShaderCache && GraphicsConfig.TitleId != null
? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId, "cache", "shader")
? Path.Combine(AppDataManager.GamesDirPath, GraphicsConfig.TitleId.ToLower(), "cache", "shader")
: null;
}

View File

@@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Bits10 = 10, // < 10 bits
Bits12 = 12, // < 12 bits
}
}
}

View File

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

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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)]
@@ -56,4 +56,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
return numValues > 0 ? GetMsb(numValues) + 1 : 0;
}
}
}
}

View File

@@ -51,6 +51,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
{
Marshal.FreeHGlobal(item.Pointer);
}
item.Pointer = ptr;
item.Length = lengthInBytes;
break;
@@ -58,7 +59,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
}
}
return new ArrayPtr<T>(ptr, length);
ArrayPtr<T> allocation = new ArrayPtr<T>(ptr, length);
allocation.AsSpan().Fill(default);
return allocation;
}
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged

View File

@@ -20,4 +20,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
new Span<T>(ptr, length).Fill(value);
}
}
}
}

View File

@@ -1,8 +1,10 @@
using Ryujinx.Graphics.Nvdec.Vp9.Types;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class Constants
{
public const int Vp9InterpExtend = 4;
public const int InterpExtend = 4;
public const int MaxMbPlane = 3;
@@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* Segment Feature Masks */
public const int MaxMvRefCandidates = 2;
public const int IntraInterContexts = 4;
public const int CompInterContexts = 5;
public const int RefContexts = 5;
@@ -32,12 +35,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int EightTapSmooth = 1;
public const int EightTapSharp = 2;
public const int SwitchableFilters = 3; /* Number of switchable filters */
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
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 Class0Bits = 1; /* bits at integer precision for class 0 */
@@ -48,9 +65,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int MvLow = -(1 << MvInUseBits);
// 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 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 PivotNode = 2;
@@ -65,5 +82,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int SegmentAbsData = 1;
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

@@ -0,0 +1,47 @@
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class DSubExp
{
public static int InvRecenterNonneg(int v, int m)
{
if (v > 2 * m)
{
return v;
}
return (v & 1) != 0 ? m - ((v + 1) >> 1) : m + (v >> 1);
}
private static readonly byte[] InvMapTable =
{
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 1, 2, 3, 4,
5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114,
115, 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205,
206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 253
};
public static int InvRemapProb(int v, int m)
{
Debug.Assert(v < InvMapTable.Length / sizeof(byte));
v = InvMapTable[v];
m--;
if (m << 1 <= Prob.MaxProb)
{
return 1 + InvRecenterNonneg(v, m);
}
return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m);
}
}
}

File diff suppressed because it is too large Load Diff

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.Types;
using Ryujinx.Graphics.Video;
@@ -10,11 +10,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class DecodeMv
{
private const int MvrefNeighbours = 8;
private const int RefNeighbours = 8;
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
{
return (PredictionMode)r.ReadTree(Luts.Vp9IntraModeTree, p);
return (PredictionMode)r.ReadTree(Luts.IntraModeTree, p);
}
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
@@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
{
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
int mode = r.ReadTree(Luts.InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.InterMode[ctx][mode];
@@ -52,22 +52,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
{
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
return r.ReadTree(Luts.SegmentTree, segTreeProbs.AsSpan());
}
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
{
switch (maxTxSize)
{
case TxSize.Tx8x8:
return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx16x16:
return fc.Tx16x16Prob[ctx].AsSpan();
case TxSize.Tx32x32:
return fc.Tx32x32Prob[ctx].AsSpan();
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
default:
Debug.Assert(false, "Invalid maxTxSize.");
return ReadOnlySpan<byte>.Empty;
}
}
@@ -76,15 +72,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
switch (maxTxSize)
{
case TxSize.Tx8x8:
return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx16x16:
return counts.Tx16x16[ctx].AsSpan();
case TxSize.Tx32x32:
return counts.Tx32x32[ctx].AsSpan();
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
default:
Debug.Assert(false, "Invalid maxTxSize.");
return Span<uint>.Empty;
}
}
@@ -124,34 +116,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
}
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis,
int yMis)
{
int x, y, segmentId = int.MaxValue;
int segmentId = int.MaxValue;
for (y = 0; y < yMis; y++)
for (int y = 0; y < yMis; y++)
{
for (x = 0; x < xMis; x++)
for (int x = 0; x < xMis; x++)
{
segmentId = Math.Min(segmentId, segmentIds[miOffset + y * cm.MiCols + x]);
segmentId = Math.Min(segmentId, segmentIds[miOffset + (y * cm.MiCols) + x]);
}
}
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
return 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);
for (y = 0; y < yMis; y++)
for (int y = 0; y < yMis; y++)
{
for (x = 0; x < xMis; x++)
for (int x = 0; x < xMis; x++)
{
cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
cm.CurrentFrameSegMap[miOffset + (y * cm.MiCols) + x] = (byte)segmentId;
}
}
}
@@ -164,13 +154,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int xMis,
int yMis)
{
int x, y;
for (y = 0; y < yMis; y++)
for (int y = 0; y < yMis; y++)
{
for (x = 0; x < xMis; x++)
for (int x = 0; x < xMis; x++)
{
currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
currentSegmentIds[miOffset + (y * cm.MiCols) + x] = (byte)(!lastSegmentIds.IsNull
? lastSegmentIds[miOffset + (y * cm.MiCols) + x]
: 0);
}
}
}
@@ -188,13 +178,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.UpdateMap)
{
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return 0;
}
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
return segmentId;
}
@@ -210,7 +198,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Segmentation seg = ref cm.Seg;
ref ModeInfo mi = ref xd.Mi[0].Value;
int predictedSegmentId, segmentId;
int miOffset = miRow * cm.MiCols + miCol;
int miOffset = (miRow * cm.MiCols) + miCol;
if (!seg.Enabled)
{
@@ -224,7 +212,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.UpdateMap)
{
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return predictedSegmentId;
}
@@ -232,20 +219,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
mi.SegIdPredicted = (sbyte)r.Read(predProb);
segmentId = mi.SegIdPredicted != 0 ? predictedSegmentId : ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
segmentId = mi.SegIdPredicted != 0
? predictedSegmentId
: ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
}
else
{
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;
}
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
{
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlSkip) != 0)
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.Skip) != 0)
{
return 1;
}
@@ -260,12 +249,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return skip;
}
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
private static int ReadComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
{
int mag, d, fr, hp;
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
bool class0 = mvClass == MvClassType.MvClass0;
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.MvClassTree, fc.Classes[mvcomp].AsSpan());
bool class0 = mvClass == MvClassType.Class0;
// Integer part
if (class0)
@@ -275,11 +264,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
int i;
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
d = 0;
for (i = 0; i < n; ++i)
for (int i = 0; i < n; ++i)
{
d |= r.Read(fc.Bits[mvcomp][i]) << i;
}
@@ -288,40 +276,39 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
// Fractional part
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
fr = r.ReadTree(Luts.MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
// High precision part (if hp is not used, the default value of the hp is 1)
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
// Result
mag += ((d << 3) | (fr << 1) | hp) + 1;
return sign ? -mag : mag;
}
private static void ReadMv(
private static void Read(
ref Reader r,
ref Mv mv,
ref Mv refr,
ref Vp9EntropyProbs fc,
Ptr<Vp9BackwardUpdates> counts,
bool allowHP)
bool allowHp)
{
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
bool useHP = allowHP && refr.UseMvHp();
MvJointType jointType = (MvJointType)r.ReadTree(Luts.MvJointTree, fc.Joints.AsSpan());
bool useHp = allowHp && refr.UseHp();
Mv diff = new();
if (Mv.MvJointVertical(jointType))
if (Mv.JointVertical(jointType))
{
diff.Row = (short)ReadMvComponent(ref r, ref fc, 0, useHP);
diff.Row = (short)ReadComponent(ref r, ref fc, 0, useHp);
}
if (Mv.MvJointHorizontal(jointType))
if (Mv.JointHorizontal(jointType))
{
diff.Col = (short)ReadMvComponent(ref r, ref fc, 1, useHP);
diff.Col = (short)ReadComponent(ref r, ref fc, 1, useHp);
}
diff.IncMv(counts);
diff.Inc(counts);
mv.Row = (short)(refr.Row + diff.Row);
mv.Col = (short)(refr.Col + diff.Col);
@@ -329,7 +316,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
{
if (cm.ReferenceMode == ReferenceMode.ReferenceModeSelect)
if (cm.ReferenceMode == ReferenceMode.Select)
{
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
@@ -354,15 +341,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
{
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame);
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame);
refFrame[1] = Constants.None;
}
else
{
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
if (mode == ReferenceMode.CompoundReference)
if (mode == ReferenceMode.Compound)
{
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
@@ -375,7 +362,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
refFrame[idx] = cm.CompFixedRef;
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
}
else if (mode == ReferenceMode.SingleReference)
else if (mode == ReferenceMode.Single)
{
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
@@ -412,7 +399,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
{
int ctx = xd.GetPredContextSwitchableInterp();
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
byte type = (byte)r.ReadTree(Luts.SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.SwitchableInterp[ctx][type];
@@ -424,12 +411,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
{
BlockSize bsize = mi.SbType;
int i;
switch (bsize)
{
case BlockSize.Block4x4:
for (i = 0; i < 4; ++i)
for (int i = 0; i < 4; ++i)
{
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
}
@@ -459,27 +446,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mi.RefFrame[1] = Constants.None;
}
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)
private static void CopyPair(ref Array2<Mv> dst, ref Array2<Mv> src)
{
dst[0] = src[0];
dst[1] = src[1];
}
private static void ZeroMvPair(ref Array2<Mv> dst)
private static void ZeroPair(ref Array2<Mv> dst)
{
dst[0] = new Mv();
dst[1] = new Mv();
}
private static bool AssignMv(
private static bool Assign(
ref Vp9Common cm,
ref MacroBlockD xd,
PredictionMode mode,
@@ -487,45 +466,45 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Array2<Mv> refMv,
ref Array2<Mv> nearNearestMv,
int isCompound,
bool allowHP,
bool allowHp,
ref Reader r)
{
int i;
bool ret = true;
switch (mode)
{
case PredictionMode.NewMv:
{
for (i = 0; i < 1 + isCompound; ++i)
for (int i = 0; i < 1 + isCompound; ++i)
{
ReadMv(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHP);
ret = ret && IsMvValid(ref mv[i]);
Read(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHp);
ret = ret && mv[i].IsValid();
}
break;
}
case PredictionMode.NearMv:
case PredictionMode.NearestMv:
{
CopyMvPair(ref mv, ref nearNearestMv);
CopyPair(ref mv, ref nearNearestMv);
break;
}
case PredictionMode.ZeroMv:
{
ZeroMvPair(ref mv);
ZeroPair(ref mv);
break;
}
default:
return false;
default: return false;
}
return ret;
}
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
{
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
{
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame) != Constants.IntraFrame;
}
int ctx = xd.GetIntraInterContext();
@@ -538,33 +517,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return isInter;
}
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
private static void DecFindBestRefs(bool allowHp, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
{
int i;
// Make sure all the candidates are properly clamped etc
for (i = 0; i < refmvCount; ++i)
for (int i = 0; i < refmvCount; ++i)
{
mvlist[i].LowerMvPrecision(allowHP);
mvlist[i].LowerPrecision(allowHp);
bestMv = mvlist[i];
}
}
private static bool AddMvRefListEb(Mv mv, ref int refMvCount, Span<Mv> mvRefList, bool earlyBreak)
private static bool AddRefListEb(Mv mv, ref int refCount, Span<Mv> mvRefList, bool earlyBreak)
{
if (refMvCount != 0)
if (refCount != 0)
{
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
{
mvRefList[refMvCount] = mv;
refMvCount++;
mvRefList[refCount] = mv;
refCount++;
return true;
}
}
else
{
mvRefList[refMvCount++] = mv;
mvRefList[refCount++] = mv;
if (earlyBreak)
{
return true;
@@ -574,19 +550,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return false;
}
// 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(
private static bool IsDiffRefFrameAddEb(
ref ModeInfo mbmi,
sbyte refFrame,
ref Array4<sbyte> refSignBias,
@@ -598,26 +562,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
if (mbmi.RefFrame[0] != refFrame)
{
if (AddMvRefListEb(ScaleMv(ref mbmi, 0, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
{
return true;
}
}
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame && Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
{
if (AddMvRefListEb(ScaleMv(ref mbmi, 1, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(mbmi.ScaleMv(0, refFrame, ref refSignBias), ref refmvCount, mvRefList,
earlyBreak))
{
return true;
}
}
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame &&
Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
{
if (AddRefListEb(mbmi.ScaleMv(1, refFrame, ref refSignBias), ref refmvCount, mvRefList,
earlyBreak))
{
return true;
}
}
}
return false;
}
// This function searches the neighborhood of a given MB/SB
// to try and find candidate reference vectors.
private static int DecFindMvRefs(
private static int DecFindRefs(
ref Vp9Common cm,
ref MacroBlockD xd,
PredictionMode mode,
@@ -627,22 +595,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int miRow,
int miCol,
int block,
int isSub8X8)
int isSub8x8)
{
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
int i, refmvCount = 0;
bool differentRefFound = false;
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs ? new Ptr<MvRef>(ref cm.PrevFrameMvs[miRow * cm.MiCols + miCol]) : Ptr<MvRef>.Null;
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs
? new Ptr<MvRef>(ref cm.PrevFrameMvs[(miRow * cm.MiCols) + miCol])
: Ptr<MvRef>.Null;
ref TileInfo tile = ref xd.Tile;
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
// searching after the first mv is found.
bool earlyBreak = mode != PredictionMode.NearMv;
// Blank the reference vector list
mvRefList[..Constants.MaxMvRefCandidates].Clear();
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
i = 0;
if (isSub8X8 != 0)
if (isSub8x8 != 0)
{
// If the size < 8x8 we get the mv from the bmi substructure for the
// nearest two blocks.
@@ -651,19 +621,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Position mvRef = ref mvRefSearch[i];
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;
if (candidateMi.RefFrame[0] == refFrame)
{
if (AddMvRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount,
mvRefList, earlyBreak))
{
goto Done;
}
}
else if (candidateMi.RefFrame[1] == refFrame)
{
if (AddMvRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount,
mvRefList, earlyBreak))
{
goto Done;
}
@@ -675,24 +647,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 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
// mode counts.
for (; i < MvrefNeighbours; ++i)
for (; i < RefNeighbours; ++i)
{
ref Position mvRef = ref mvRefSearch[i];
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;
if (candidate.RefFrame[0] == refFrame)
{
if (AddMvRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
}
else if (candidate.RefFrame[1] == refFrame)
{
if (AddMvRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
@@ -705,14 +677,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
{
if (AddMvRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
}
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
{
if (AddMvRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
@@ -724,15 +696,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// different reference frames.
if (differentRefFound)
{
for (i = 0; i < MvrefNeighbours; ++i)
for (i = 0; i < RefNeighbours; ++i)
{
ref Position mvRef = ref mvRefSearch[i];
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 (IsDiffRefFrameAddMvEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, earlyBreak))
if (IsDiffRefFrameAddEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList,
earlyBreak))
{
goto Done;
}
@@ -751,7 +724,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mv.Row *= -1;
mv.Col *= -1;
}
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
@@ -759,7 +733,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
prevFrameMvs.Value.RefFrame[1] != refFrame &&
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) != Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) !=
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
{
Mv mv = prevFrameMvs.Value.Mv[1];
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
@@ -767,7 +742,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mv.Row *= -1;
mv.Col *= -1;
}
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
{
goto Done;
}
@@ -784,17 +760,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
refmvCount = 1;
}
Done:
Done:
// Clamp vectors
for (i = 0; i < refmvCount; ++i)
{
mvRefList[i].ClampMvRef(ref xd);
mvRefList[i].ClampRef(ref xd);
}
return refmvCount;
}
private static void AppendSub8x8MvsForIdx(
private static void AppendSub8x8ForIdx(
ref Vp9Common cm,
ref MacroBlockD xd,
Span<Position> mvRefSearch,
@@ -808,12 +784,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
ref ModeInfo mi = ref xd.Mi[0].Value;
ref Array4<BModeInfo> bmi = ref mi.Bmi;
int n;
int refmvCount;
Debug.Assert(Constants.MaxMvRefCandidates == 2);
refmvCount = DecFindMvRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, block, 1);
refmvCount = DecFindRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol,
block, 1);
switch (block)
{
@@ -829,7 +805,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
bestSub8x8 = new Mv();
for (n = 0; n < refmvCount; ++n)
for (int n = 0; n < refmvCount; ++n)
{
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
{
@@ -838,6 +814,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
}
break;
case 3:
if (bMode == PredictionMode.NearestMv)
@@ -852,7 +829,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
candidates[2] = mvList[0];
candidates[3] = mvList[1];
bestSub8x8 = new Mv();
for (n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
for (int n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
{
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
{
@@ -861,6 +838,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
}
break;
default:
Debug.Assert(false, "Invalid block index.");
@@ -868,19 +846,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, int miCol)
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow,
int miCol)
{
int i;
int contextCounter = 0;
ref TileInfo tile = ref xd.Tile;
// Get mode count from nearest 2 blocks
for (i = 0; i < 2; ++i)
for (int i = 0; i < 2; ++i)
{
ref Position mvRef = ref mvRefSearch[i];
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.
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
}
@@ -898,7 +876,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Reader r)
{
BlockSize bsize = mi.SbType;
bool allowHP = cm.AllowHighPrecisionMv;
bool allowHp = cm.AllowHighPrecisionMv;
Array2<Mv> bestRefMvs = new();
int refr, isCompound;
byte interModeCtx;
@@ -908,13 +886,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
isCompound = mi.HasSecondRef() ? 1 : 0;
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.SegLvlSkip) != 0)
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.Skip) != 0)
{
mi.Mode = PredictionMode.ZeroMv;
if (bsize < BlockSize.Block8x8)
{
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
xd.ErrorInfo.Value.InternalError(CodecErr.UnsupBitstream,
"Invalid usage of segement feature on small blocks");
return;
}
}
@@ -942,53 +920,58 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
sbyte frame = mi.RefFrame[refr];
int refmvCount;
refmvCount = DecFindMvRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, -1, 0);
refmvCount = DecFindRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol,
-1, 0);
DecFindBestRefMvs(allowHP, tmpMvs, ref bestRefMvs[refr], refmvCount);
DecFindBestRefs(allowHp, tmpMvs, ref bestRefMvs[refr], refmvCount);
}
}
}
mi.InterpFilter = (cm.InterpFilter == Constants.Switchable) ? ReadSwitchableInterpFilter(ref cm, ref xd, ref r) : cm.InterpFilter;
mi.InterpFilter = cm.InterpFilter == Constants.Switchable
? ReadSwitchableInterpFilter(ref cm, ref xd, ref r)
: cm.InterpFilter;
if (bsize < BlockSize.Block8x8)
{
int num4X4W = 1 << xd.BmodeBlocksWl;
int num4X4H = 1 << xd.BmodeBlocksHl;
int num4x4W = 1 << xd.BmodeBlocksWl;
int num4x4H = 1 << xd.BmodeBlocksHl;
int idx, idy;
PredictionMode bMode = 0;
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
// if isCompound is false.
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = InvalidMv;
for (idy = 0; idy < 2; idy += num4X4H)
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = invalidMv;
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);
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
{
for (refr = 0; refr < 1 + isCompound; ++refr)
{
AppendSub8x8MvsForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, ref bestSub8x8[refr]);
AppendSub8x8ForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol,
ref bestSub8x8[refr]);
}
}
if (!AssignMv(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, isCompound, allowHP, ref r))
if (!Assign(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8,
isCompound, allowHp, ref r))
{
xd.Corrupted |= true;
break;
}
if (num4X4H == 2)
if (num4x4H == 2)
{
mi.Bmi[j + 2] = mi.Bmi[j];
}
if (num4X4W == 2)
if (num4x4W == 2)
{
mi.Bmi[j + 1] = mi.Bmi[j];
}
@@ -997,11 +980,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mi.Mode = bMode;
CopyMvPair(ref mi.Mv, ref mi.Bmi[3].Mv);
CopyPair(ref mi.Mv, ref mi.Bmi[3].Mv);
}
else
{
xd.Corrupted |= !AssignMv(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, isCompound, allowHP, ref r);
xd.Corrupted |= !Assign(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs,
isCompound, allowHp, ref r);
}
}
@@ -1045,7 +1029,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
Debug.Assert(b == 1 || b == 3);
return curMi.Value.Bmi[b - 1].Mode;
}
@@ -1062,7 +1045,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
Debug.Assert(b == 2 || b == 3);
return curMi.Value.Bmi[b - 2].Mode;
}
@@ -1075,7 +1057,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
PredictionMode left = LeftBlockMode(mi, leftMi, block);
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
}
@@ -1092,8 +1073,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Ptr<ModeInfo> aboveMi = xd.AboveMi;
Ptr<ModeInfo> leftMi = xd.LeftMi;
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.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
@@ -1104,7 +1085,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (bsize)
{
case BlockSize.Block4x4:
for (i = 0; i < 4; ++i)
for (int i = 0; i < 4; ++i)
{
mi.Value.Bmi[i].Mode =
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
@@ -1149,8 +1130,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Reader r = ref twd.BitReader;
ref MacroBlockD xd = ref twd.Xd;
ref ModeInfo mi = ref xd.Mi[0].Value;
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice(miRow * cm.MiCols + miCol);
int w, h;
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice((miRow * cm.MiCols) + miCol);
if (cm.FrameIsIntraOnly())
{
@@ -1160,17 +1140,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
for (h = 0; h < yMis; ++h)
for (int h = 0; h < yMis; ++h)
{
for (w = 0; w < xMis; ++w)
for (int w = 0; w < xMis; ++w)
{
ref MvRef mv = ref frameMvs[w];
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
CopyMvPair(ref mv.Mv, ref mi.Mv);
CopyPair(ref mv.Mv, ref mi.Mv);
}
frameMvs = frameMvs.Slice(cm.MiCols);
}
}
}
}
}
}

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.Types;
using Ryujinx.Graphics.Video;
@@ -12,14 +12,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private readonly MemoryAllocator _allocator = new();
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
public ISurface CreateSurface(int width, int height)
{
return new Surface(width, height);
}
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(
@@ -29,25 +29,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ReadOnlySpan<Vp9MvRef> mvsIn,
Span<Vp9MvRef> mvsOut)
{
Vp9Common cm = new()
{
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
IntraOnly = pictureInfo.IntraOnly,
Vp9Common cm = new();
Width = output.Width,
Height = output.Height,
SubsamplingX = 1,
SubsamplingY = 1,
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
cm.IntraOnly = pictureInfo.IntraOnly;
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
cm.Width = output.Width;
cm.Height = output.Height;
cm.SubsamplingX = 1;
cm.SubsamplingY = 1;
RefFrameSignBias = pictureInfo.RefFrameSignBias,
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
BaseQindex = pictureInfo.BaseQIndex,
YDcDeltaQ = pictureInfo.YDcDeltaQ,
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
};
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
cm.BaseQindex = pictureInfo.BaseQIndex;
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
cm.Mb.Lossless = pictureInfo.Lossless;
cm.Mb.Bd = 8;
@@ -68,6 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.CompFixedRef = pictureInfo.CompFixedRef;
cm.CompVarRef = pictureInfo.CompVarRef;
cm.BitDepth = BitDepth.Bits8;
cm.Log2TileCols = pictureInfo.Log2TileCols;
cm.Log2TileRows = pictureInfo.Log2TileRows;
@@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
cm.Lf.FilterLevel = pictureInfo.LoopFilterLevel;
cm.Lf.SharpnessLevel = pictureInfo.LoopFilterSharpnessLevel;
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
@@ -105,7 +108,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.SetupSegmentationDequant();
cm.SetupScaleFactors();
SetMvs(ref cm, mvsIn);
cm.SetMvs(mvsIn);
if (cm.Lf.FilterLevel != 0 && cm.SkipLoopFilter == 0)
{
LoopFilter.LoopFilterFrameInit(ref cm, cm.Lf.FilterLevel);
}
fixed (byte* dataPtr = bitstream)
{
@@ -114,10 +122,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
{
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
{
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)
@@ -126,7 +151,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
GetMvs(ref cm, mvsOut);
cm.GetMvs(mvsOut);
cm.FreeTileWorkerData(_allocator);
cm.FreeContextBuffers(_allocator);
@@ -134,48 +159,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return true;
}
private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
public void 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];
}
_allocator.Dispose();
}
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.Types;
using Ryujinx.Graphics.Video;
@@ -17,26 +17,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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]] + 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;
return (1 + tokenCache[neighbors[(maxNeighbors * c) + 0]] +
tokenCache[neighbors[(maxNeighbors * c) + 1]]) >> 1;
}
private static int DecodeCoefs(
@@ -58,13 +42,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
Span<byte> tokenCache = stackalloc byte[32 * 32];
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
int dqShift = txSize == TxSize.Tx32x32 ? 1 : 0;
int v;
short dqv = dq[0];
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
? Luts.Vp9Cat6ProbHigh12
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
ReadOnlySpan<byte> cat6Prob = xd.Bd == 12
? Luts.Cat6ProbHigh12
: xd.Bd == 10
? Luts.Cat6ProbHigh12.Slice(2)
: Luts.Cat6Prob;
int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14;
// Keep value, range, and count as locals. The compiler produces better
// results with the locals than using r directly.
ulong value = r.Value;
@@ -75,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int val = -1;
band = bandTranslate[0];
bandTranslate = bandTranslate[1..];
bandTranslate = bandTranslate.Slice(1);
ref Array3<byte> prob = ref coefProbs[band][ctx];
if (!xd.Counts.IsNull)
{
@@ -107,18 +93,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value;
r.Range = range;
r.Count = count;
return c; // Zero tokens at the end (no eob token)
}
ctx = GetCoefContext(nb, tokenCache, c);
band = bandTranslate[0];
bandTranslate = bandTranslate[1..];
bandTranslate = bandTranslate.Slice(1);
prob = ref coefProbs[band][ctx];
}
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
{
ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[prob[Constants.PivotNode] - 1];
ReadOnlySpan<byte> p = Luts.Pareto8Full[prob[Constants.PivotNode] - 1];
if (!xd.Counts.IsNull)
{
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
@@ -133,20 +119,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
{
val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range);
val = Constants.Cat6MinVal + r.ReadCoeff(cat6Prob, cat6Bits, ref value,
ref count, ref range);
}
else
{
val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range);
val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value,
ref count, ref range);
}
}
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
{
val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range);
val = Constants.Cat4MinVal + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count,
ref range);
}
else
{
val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range);
val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count,
ref range);
}
}
else
@@ -154,13 +144,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tokenCache[scan[c]] = 4;
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
{
val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range);
val = Constants.Cat2MinVal + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count,
ref range);
}
else
{
val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range);
val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count,
ref range);
}
}
// Val may use 18-bits
v = (int)(((long)val * dqv) >> dqShift);
}
@@ -188,7 +181,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tokenCache[scan[c]] = 1;
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;
ctx = GetCoefContext(nb, tokenCache, c);
dqv = dq[1];
@@ -197,11 +192,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value;
r.Range = range;
r.Count = count;
return c;
}
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks)
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y,
uint txSizeInBlocks)
{
if (xd.MaxBlocksWide != 0)
{
@@ -210,6 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
}
}
if (xd.MaxBlocksHigh != 0)
{
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
@@ -238,8 +234,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane];
ref Array2<short> dequant = ref pd.SegDequant[segId];
int eob;
Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
int ctx;
int ctxShiftA = 0;
int ctxShiftL = 0;
@@ -324,4 +320,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return eob;
}
}
}
}

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -75,17 +75,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Vector128<int> zero = Vector128<int>.Zero;
Vector128<int> const64 = Vector128.Create(64);
ulong x, y;
src -= SubpelTaps / 2 - 1;
src -= (SubpelTaps / 2) - 1;
fixed (Array8<short>* xFilter = xFilters)
{
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + (uint)(x0Q4 & SubpelMask) * 8);
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + ((uint)(x0Q4 & SubpelMask) * 8));
for (y = 0; y < (uint)h; ++y)
for (ulong y = 0; y < (uint)h; ++y)
{
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
for (x = 0; x < (uint)w; x += 4)
for (ulong x = 0; x < (uint)w; x += 4)
{
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
@@ -94,8 +93,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
Sse.StoreScalar((float*)&dst[x],
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
}
src += srcStride;
dst += dstStride;
}
@@ -117,22 +118,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
{
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
return;
}
int x, y;
src -= SubpelTaps / 2 - 1;
src -= (SubpelTaps / 2) - 1;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
int xQ4 = x0Q4;
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
byte* srcX = &src[xQ4 >> SubpelBits];
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcX[k] * xFilter[k];
}
@@ -140,6 +139,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
xQ4 += xStepQ4;
}
src += srcStride;
dst += dstStride;
}
@@ -156,25 +156,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w,
int h)
{
int x, y;
src -= SubpelTaps / 2 - 1;
src -= (SubpelTaps / 2) - 1;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
int xQ4 = x0Q4;
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
byte* srcX = &src[xQ4 >> SubpelBits];
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcX[k] * xFilter[k];
}
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
dst[x] = (byte)BitUtils.RoundPowerOfTwo(
dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
xQ4 += xStepQ4;
}
src += srcStride;
dst += dstStride;
}
@@ -203,18 +204,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
srcStride * 6,
srcStride * 7);
ulong x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
src -= srcStride * ((SubpelTaps / 2) - 1);
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;
for (y = 0; y < (uint)h; ++y)
for (ulong y = 0; y < (uint)h; ++y)
{
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
for (x = 0; x < (uint)w; x += 4)
for (ulong x = 0; x < (uint)w; x += 4)
{
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
@@ -240,8 +240,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
Sse.StoreScalar((float*)&dst[x],
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
}
dst += dstStride;
}
}
@@ -262,22 +264,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
{
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
return;
}
int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
src -= srcStride * ((SubpelTaps / 2) - 1);
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
int yQ4 = y0Q4;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcY[k * srcStride] * yFilter[k];
}
@@ -285,6 +285,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
yQ4 += yStepQ4;
}
++src;
++dst;
}
@@ -301,18 +302,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w,
int h)
{
int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
src -= srcStride * ((SubpelTaps / 2) - 1);
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
int yQ4 = y0Q4;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcY[k * srcStride] * yFilter[k];
}
@@ -321,6 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
yQ4 += yStepQ4;
}
++src;
++dst;
}
@@ -420,15 +421,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
// big enough.
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(h <= 64);
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
Debug.Assert(xStepQ4 <= 64);
ConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight);
ConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
ConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4, w,
intermediateHeight);
ConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
}
public static unsafe void Convolve8Avg(
@@ -489,11 +491,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int w,
int h)
{
int x, y;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
}
@@ -611,18 +611,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
int bd)
{
int x, y;
src -= SubpelTaps / 2 - 1;
src -= (SubpelTaps / 2) - 1;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
int xQ4 = x0Q4;
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
ushort* srcX = &src[xQ4 >> SubpelBits];
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcX[k] * xFilter[k];
}
@@ -630,6 +629,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
xQ4 += xStepQ4;
}
src += srcStride;
dst += dstStride;
}
@@ -647,25 +647,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
int bd)
{
int x, y;
src -= SubpelTaps / 2 - 1;
src -= (SubpelTaps / 2) - 1;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
int xQ4 = x0Q4;
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
ushort* srcX = &src[xQ4 >> SubpelBits];
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcX[k] * xFilter[k];
}
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(
dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
xQ4 += xStepQ4;
}
src += srcStride;
dst += dstStride;
}
@@ -683,18 +684,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
int bd)
{
int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
src -= srcStride * ((SubpelTaps / 2) - 1);
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
int yQ4 = y0Q4;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcY[k * srcStride] * yFilter[k];
}
@@ -702,6 +702,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
yQ4 += yStepQ4;
}
++src;
++dst;
}
@@ -719,26 +720,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
int bd)
{
int x, y;
src -= srcStride * (SubpelTaps / 2 - 1);
src -= srcStride * ((SubpelTaps / 2) - 1);
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
int yQ4 = y0Q4;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
int k, sum = 0;
for (k = 0; k < SubpelTaps; ++k)
int sum = 0;
for (int k = 0; k < SubpelTaps; ++k)
{
sum += srcY[k * srcStride] * yFilter[k];
}
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd),
1);
yQ4 += yStepQ4;
}
++src;
++dst;
}
@@ -771,15 +773,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
// --((64 - 1) * 32 + 15) >> 4 + 8 = 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(h <= 64);
Debug.Assert(yStepQ4 <= 32);
Debug.Assert(xStepQ4 <= 32);
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
HighbdConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4,
w, intermediateHeight, bd);
HighbdConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h,
bd);
}
public static unsafe void HighbdConvolve8Horiz(
@@ -928,11 +932,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
int bd)
{
int x, y;
for (y = 0; y < h; ++y)
for (int y = 0; y < h; ++y)
{
for (x = 0; x < w; ++x)
for (int x = 0; x < w; ++x)
{
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
}
@@ -942,4 +944,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
}
}
}
}

View File

@@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public const int SubpelShifts = 1 << SubpelBits;
public const int SubpelTaps = 8;
}
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,4 +1,5 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using System.Buffers.Binary;
@@ -6,18 +7,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
internal struct Reader
{
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,
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, 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, 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 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, 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, 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,
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;
// This is meant to be a large, positive constant that can still be efficiently
@@ -36,16 +37,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
return true;
}
else
{
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0;
Count = -8;
Range = 255;
Fill();
return ReadBit() != 0; // Marker bit
}
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0;
Count = -8;
Range = 255;
Fill();
return ReadBit() != 0; // Marker bit
}
private void Fill()
@@ -65,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
nv = bigEndianValues >> (BdValueSize - bits);
count += bits;
buffer = buffer[(bits >> 3)..];
buffer = buffer.Slice(bits >> 3);
value = Value | (nv << (shift & 0x7));
}
else
@@ -84,7 +82,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
count += 8;
value |= (ulong)buffer[0] << shift;
buffer = buffer[1..];
buffer = buffer.Slice(1);
shift -= 8;
}
}
@@ -98,7 +96,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count;
}
public readonly bool HasError()
public bool HasError()
{
// Check if we have reached the end of the buffer.
//
@@ -124,7 +122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigsplit;
int count;
uint range;
uint split = (Range * (uint)prob + (256 - (uint)prob)) >> 8;
uint split = ((Range * (uint)prob) + (256 - (uint)prob)) >> 8;
if (Count < 0)
{
@@ -146,7 +144,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
@@ -188,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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);
if (count < 0)
@@ -202,19 +200,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit)
{
range -= split;
value -= bigsplit;
range = range - split;
value = value - bigsplit;
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
}
return 1;
}
range = split;
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
@@ -230,7 +229,82 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count -= 8;
_buffer = _buffer.Slice(-1);
}
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)
// 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)
public const short CosPi1_64 = 16364;
public const short CosPi2_64 = 16305;
public const short CosPi3_64 = 16207;
public const short CosPi4_64 = 16069;
public const short CosPi5_64 = 15893;
public const short CosPi6_64 = 15679;
public const short CosPi7_64 = 15426;
public const short CosPi8_64 = 15137;
public const short CosPi9_64 = 14811;
public const short CosPi10_64 = 14449;
public const short CosPi11_64 = 14053;
public const short CosPi12_64 = 13623;
public const short CosPi13_64 = 13160;
public const short CosPi14_64 = 12665;
public const short CosPi15_64 = 12140;
public const short CosPi16_64 = 11585;
public const short CosPi17_64 = 11003;
public const short CosPi18_64 = 10394;
public const short CosPi19_64 = 9760;
public const short CosPi20_64 = 9102;
public const short CosPi21_64 = 8423;
public const short CosPi22_64 = 7723;
public const short CosPi23_64 = 7005;
public const short CosPi24_64 = 6270;
public const short CosPi25_64 = 5520;
public const short CosPi26_64 = 4756;
public const short CosPi27_64 = 3981;
public const short CosPi28_64 = 3196;
public const short CosPi29_64 = 2404;
public const short CosPi30_64 = 1606;
public const short CosPi31_64 = 804;
public const short CosPi164 = 16364;
public const short CosPi264 = 16305;
public const short CosPi364 = 16207;
public const short CosPi464 = 16069;
public const short CosPi564 = 15893;
public const short CosPi664 = 15679;
public const short CosPi764 = 15426;
public const short CosPi864 = 15137;
public const short CosPi964 = 14811;
public const short CosPi1064 = 14449;
public const short CosPi1164 = 14053;
public const short CosPi1264 = 13623;
public const short CosPi1364 = 13160;
public const short CosPi1464 = 12665;
public const short CosPi1564 = 12140;
public const short CosPi1664 = 11585;
public const short CosPi1764 = 11003;
public const short CosPi1864 = 10394;
public const short CosPi1964 = 9760;
public const short CosPi2064 = 9102;
public const short CosPi2164 = 8423;
public const short CosPi2264 = 7723;
public const short CosPi2364 = 7005;
public const short CosPi2464 = 6270;
public const short CosPi2564 = 5520;
public const short CosPi2664 = 4756;
public const short CosPi2764 = 3981;
public const short CosPi2864 = 3196;
public const short CosPi2964 = 2404;
public const short CosPi3064 = 1606;
public const short CosPi3164 = 804;
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
public const short SinPi1_9 = 5283;
public const short SinPi2_9 = 9929;
public const short SinPi3_9 = 13377;
public const short SinPi4_9 = 15212;
public const short SinPi19 = 5283;
public const short SinPi29 = 9929;
public const short SinPi39 = 13377;
public const short SinPi49 = 15212;
}
}
}

View File

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

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

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

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

View File

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

View File

@@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
throw new InternalErrorException(message);
}
}
}
}

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.Types;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
@@ -13,7 +13,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // both edges available
{
// both edges available
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
{
// Neither edge uses comp pred (0/1)
@@ -23,12 +24,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else if (!xd.AboveMi.Value.HasSecondRef())
{
// One of two edges uses comp pred (2/3)
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock()
? 1
: 0);
}
else if (!xd.LeftMi.Value.HasSecondRef())
{
// One of two edges uses comp pred (2/3)
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
ctx = 2 +
(xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
}
else // Both edges use comp pred (4)
{
@@ -36,7 +40,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available
{
// One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.HasSecondRef())
@@ -51,11 +56,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (1)
{
// No edges available (1)
ctx = 1;
}
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx;
}
@@ -71,29 +77,33 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra (2)
{
// Intra/Intra (2)
predContext = 2;
}
else if (aboveIntra || leftIntra)
{ // Intra/Inter
{
// Intra/Inter
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) // single pred (1/3)
{
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
predContext = 1 + (2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0));
}
else // Comp pred (1/3)
{
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
predContext = 1 + (2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0));
}
}
else
{ // Inter/Inter
{
// Inter/Inter
bool lSg = !xd.LeftMi.Value.HasSecondRef();
bool aSg = !xd.AboveMi.Value.HasSecondRef();
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
@@ -104,7 +114,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 0;
}
else if (lSg && aSg)
{ // Single/Single
{
// Single/Single
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
{
@@ -120,7 +131,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (lSg || aSg)
{ // Single/Comp
{
// Single/Comp
sbyte vrfc = lSg ? vrfa : vrfl;
sbyte rfs = aSg ? vrfa : vrfl;
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
@@ -137,7 +149,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (vrfa == vrfl)
{ // Comp/Comp
{
// Comp/Comp
predContext = 4;
}
else
@@ -147,7 +160,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available
{
// One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock())
@@ -167,11 +181,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (2)
{
// No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@@ -183,16 +198,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra
{
// Intra/Intra
predContext = 2;
}
else if (aboveIntra || leftIntra)
{ // Intra/Inter or Inter/Intra
{
// Intra/Inter or Inter/Intra
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef())
{
@@ -201,11 +219,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
}
}
else
{ // Inter/Inter
{
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -216,7 +237,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (aboveHasSecond && leftHasSecond)
{
predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
left0 == Constants.LastFrame || left1 == Constants.LastFrame ? 1 : 0);
left0 == Constants.LastFrame || left1 == Constants.LastFrame
? 1
: 0);
}
else if (aboveHasSecond || leftHasSecond)
{
@@ -230,24 +253,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
predContext = crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0;
}
}
else
{
predContext = 2 * (above0 == Constants.LastFrame ? 1 : 0) + 2 * (left0 == Constants.LastFrame ? 1 : 0);
predContext = (2 * (above0 == Constants.LastFrame ? 1 : 0)) +
(2 * (left0 == Constants.LastFrame ? 1 : 0));
}
}
}
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available
{
// One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock())
{ // Intra
{
// Intra
predContext = 2;
}
else
{ // Inter
{
// Inter
if (!edgeMi.HasSecondRef())
{
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
@@ -255,16 +282,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
}
}
}
else
{ // No edges available
{
// No edges available
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@@ -277,16 +307,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra
{
// Intra/Intra
predContext = 2;
}
else if (aboveIntra || leftIntra)
{ // Intra/Inter or Inter/Intra
{
// Intra/Inter or Inter/Intra
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef())
{
@@ -301,12 +334,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
predContext = 1 + (2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0));
}
}
else
{ // Inter/Inter
{
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -319,7 +355,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (above0 == left0 && above1 == left1)
{
predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame ? 1 : 0);
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame
? 1
: 0);
}
else
{
@@ -342,7 +380,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
predContext =
1 + (2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0));
}
}
else
@@ -353,18 +392,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
{
sbyte edge0 = (above0 == Constants.LastFrame) ? left0 : above0;
sbyte edge0 = above0 == Constants.LastFrame ? left0 : above0;
predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
}
else
{
predContext = 2 * (above0 == Constants.GoldenFrame ? 1 : 0) + 2 * (left0 == Constants.GoldenFrame ? 1 : 0);
predContext = (2 * (above0 == Constants.GoldenFrame ? 1 : 0)) +
(2 * (left0 == Constants.GoldenFrame ? 1 : 0));
}
}
}
}
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available
{
// One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
@@ -378,16 +419,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0);
}
}
else
{ // No edges available (2)
{
// No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
}
}
}

View File

@@ -0,0 +1,94 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
public static class Prob
{
public const int MaxProb = 255;
private static byte GetProb(uint num, uint den)
{
Debug.Assert(den != 0);
{
int p = (int)((((ulong)num * 256) + (den >> 1)) / den);
// (p > 255) ? 255 : (p < 1) ? 1 : p;
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
return (byte)clippedProb;
}
}
private static byte GetBinaryProb(uint n0, uint n1)
{
uint den = n0 + n1;
if (den == 0)
{
return 128;
}
return GetProb(n0, den);
}
/* This function assumes prob1 and prob2 are already within [1,255] range. */
public static byte WeightedProb(int prob1, int prob2, int factor)
{
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
}
public static byte MergeProbs(byte preProb, ref Array2<uint> ct, uint countSat, uint maxUpdateFactor)
{
byte prob = GetBinaryProb(ct[0], ct[1]);
uint count = Math.Min(ct[0] + ct[1], countSat);
uint factor = maxUpdateFactor * count / countSat;
return WeightedProb(preProb, prob, (int)factor);
}
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
private static readonly uint[] CountToUpdateFactor =
{
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, 70, 76, 83, 89, 96, 102, 108, 115, 121, 128
};
private const int ModeMvCountSat = 20;
public static byte ModeMvMergeProbs(byte preProb, ref Array2<uint> ct)
{
uint den = ct[0] + ct[1];
if (den == 0)
{
return preProb;
}
uint count = Math.Min(den, ModeMvCountSat);
uint factor = CountToUpdateFactor[(int)count];
byte prob = GetProb(ct[0], den);
return WeightedProb(preProb, prob, (int)factor);
}
private static uint TreeMergeProbsImpl(
uint i,
sbyte[] tree,
ReadOnlySpan<byte> preProbs,
ReadOnlySpan<uint> counts,
Span<byte> probs)
{
int l = tree[i];
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
int r = tree[i + 1];
uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
Array2<uint> ct = new();
ct[0] = leftCount;
ct[1] = rightCount;
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], ref ct);
return leftCount + rightCount;
}
public static void VpxTreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
Span<byte> probs)
{
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
}
}
}

View File

@@ -1,172 +1,127 @@
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class QuantCommon
{
public const int MinQ = 0;
public const int MaxQ = 255;
public const int QindexBits = 8;
private static readonly short[] _dcQlookup = {
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53,
54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65,
66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76,
77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110,
111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164,
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202,
205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300,
304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364,
369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549,
559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736,
755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139,
1184, 1232, 1282, 1336,
private static readonly short[] DcQlookup =
{
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29,
30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51,
52, 53, 53, 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72,
73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, 93, 95, 96, 98, 99,
101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182,
185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330,
335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626,
640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098,
1139, 1184, 1232, 1282, 1336
};
private static readonly short[] _dcQlookup10 = {
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182,
185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230,
233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276,
280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321,
324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387,
394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466,
472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567,
576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687,
698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831,
844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001,
1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202,
1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436,
1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717,
1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088,
2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675,
2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823,
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
private static readonly short[] DcQlookup10 =
{
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163,
166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241,
244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314,
317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424,
430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576,
584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782,
795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045,
1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323,
1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670,
1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159,
2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347
};
private static readonly short[] _dcQlookup12 = {
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752,
768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919,
934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080,
1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234,
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419,
1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692,
1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957,
1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334,
2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746,
2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226,
3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788,
3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153,
5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984,
6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966,
7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214,
8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031,
10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118,
13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949,
19718, 20521, 21387,
private static readonly short[] DcQlookup12 =
{
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 251,
266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, 904,
919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165,
1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444,
1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862,
1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400,
2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076,
3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013,
5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319,
6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085,
8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946,
11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943,
17575, 18237, 18949, 19718, 20521, 21387
};
private static readonly short[] _acQlookup = {
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118,
120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144,
146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179,
182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280,
285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353,
359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448,
456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571,
582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729,
743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933,
951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196,
1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537,
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
private static readonly short[] AcQlookup =
{
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114,
116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158,
161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227,
231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329,
335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483,
492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715,
729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046,
1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451,
1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828
};
private static readonly short[] _acQlookup10 = {
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208,
213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267,
271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324,
328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379,
384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466,
474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571,
579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713,
725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889,
905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118,
1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411,
1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791,
1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283,
2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915,
2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731,
3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784,
4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148,
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
private static readonly short[] AcQlookup10 =
{
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186,
190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280,
284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371,
375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514,
523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725,
737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018,
1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895,
1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603,
2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591,
3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972,
5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900,
7036, 7172, 7312
};
private static readonly short[] _acQlookup12 = {
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865,
884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067,
1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264,
1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457,
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693,
1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052,
2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411,
2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555,
3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310,
4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256,
5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867,
8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660,
9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885,
12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637,
14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062,
18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334,
22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599,
28143, 28687, 29247,
private static readonly short[] AcQlookup12 =
{
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 280,
297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030,
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335,
1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660,
1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216,
2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941,
4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352,
5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290,
7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309,
13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726,
18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662,
24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247
};
public static short DcQuant(int qindex, int delta, BitDepth bitDepth)
{
switch (bitDepth)
{
case BitDepth.Bits8:
return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10:
return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12:
return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits8: return DcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
default:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
return -1;
}
}
@@ -175,30 +130,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
switch (bitDepth)
{
case BitDepth.Bits8:
return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10:
return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12:
return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits8: return AcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
default:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
return -1;
}
}
public static int GetQIndex(ref Segmentation seg, int segmentId, int baseQIndex)
{
if (seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlAltQ) != 0)
{
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
return Math.Clamp(segQIndex, 0, MaxQ);
}
return baseQIndex;
}
}
}
}

View File

@@ -0,0 +1,84 @@
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
public ref struct ReadBitBuffer
{
public ReadOnlySpan<byte> BitBuffer;
public ulong BitOffset;
public object ErrorHandlerData;
public int DecodeUnsignedMax(int max)
{
int data = ReadLiteral(BitUtils.GetUnsignedBits((uint)max));
return data > max ? max : data;
}
public ulong BytesRead()
{
return (BitOffset + 7) >> 3;
}
public int ReadBit()
{
ulong off = BitOffset;
ulong p = off >> 3;
int q = 7 - (int)(off & 0x7);
if (p < (ulong)BitBuffer.Length)
{
int bit = (BitBuffer[(int)p] >> q) & 1;
BitOffset = off + 1;
return bit;
}
return 0;
}
public int ReadLiteral(int bits)
{
int value = 0, bit;
for (bit = bits - 1; bit >= 0; bit--)
{
value |= ReadBit() << bit;
}
return value;
}
public int ReadSignedLiteral(int bits)
{
int value = ReadLiteral(bits);
return ReadBit() != 0 ? -value : value;
}
public int ReadInvSignedLiteral(int bits)
{
return ReadSignedLiteral(bits);
}
public int ReadDeltaQ()
{
return ReadBit() != 0 ? ReadSignedLiteral(4) : 0;
}
public void ReadFrameSize(out int width, out int height)
{
width = ReadLiteral(16) + 1;
height = ReadLiteral(16) + 1;
}
public BitstreamProfile ReadProfile()
{
int profile = ReadBit();
profile |= ReadBit() << 1;
if (profile > 2)
{
profile += ReadBit();
}
return (BitstreamProfile)profile;
}
}
}

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using System.Diagnostics;
@@ -77,65 +77,38 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
bd);
}
private static int RoundMvCompQ4(int value)
public static int RoundMvCompQ4(int value)
{
return (value < 0 ? value - 2 : value + 2) / 4;
}
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
{
return new Mv
{
Row = (short)RoundMvCompQ4(
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
Col = (short)RoundMvCompQ4(
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col),
};
}
private static int RoundMvCompQ2(int value)
public static int RoundMvCompQ2(int value)
{
return (value < 0 ? value - 1 : value + 1) / 2;
}
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
{
return new Mv
{
Row = (short)RoundMvCompQ2(
mi.Bmi[block0].Mv[idx].Row +
mi.Bmi[block1].Mv[idx].Row),
Col = (short)RoundMvCompQ2(
mi.Bmi[block0].Mv[idx].Col +
mi.Bmi[block1].Mv[idx].Col),
};
}
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
{
// If the MV points so far into the UMV border that no visible pixels
// are used for reconstruction, the subpel part of the MV can be
// discarded and the MV limited to 16 pixels with equivalent results.
int spelLeft = (Constants.Vp9InterpExtend + bw) << SubpelBits;
int spelLeft = (Constants.InterpExtend + bw) << SubpelBits;
int spelRight = spelLeft - SubpelShifts;
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
int spelTop = (Constants.InterpExtend + bh) << SubpelBits;
int spelBottom = spelTop - SubpelShifts;
Mv clampedMv = new()
{
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
Col = (short)(srcMv.Col * (1 << (1 - ssX))),
Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX)))
};
Debug.Assert(ssX <= 1);
Debug.Assert(ssY <= 1);
clampedMv.ClampMv(
xd.MbToLeftEdge * (1 << (1 - ssX)) - spelLeft,
xd.MbToRightEdge * (1 << (1 - ssX)) + spelRight,
xd.MbToTopEdge * (1 << (1 - ssY)) - spelTop,
xd.MbToBottomEdge * (1 << (1 - ssY)) + spelBottom);
clampedMv.Clamp(
(xd.MbToLeftEdge * (1 << (1 - ssX))) - spelLeft,
(xd.MbToRightEdge * (1 << (1 - ssX))) + spelRight,
(xd.MbToTopEdge * (1 << (1 - ssY))) - spelTop,
(xd.MbToBottomEdge * (1 << (1 - ssY))) + spelBottom);
return clampedMv;
}
@@ -150,18 +123,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
res = mi.Bmi[block].Mv[refr];
break;
case 1:
res = MiMvPredQ2(ref mi, refr, block, block + 2);
res = mi.MvPredQ2(refr, block, block + 2);
break;
case 2:
res = MiMvPredQ2(ref mi, refr, block, block + 1);
res = mi.MvPredQ2(refr, block, block + 1);
break;
case 3:
res = MiMvPredQ4(ref mi, refr);
res = mi.MvPredQ4(refr);
break;
default:
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
break;
}
return res;
}
@@ -169,8 +143,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
return y * stride + x;
return (y * stride) + x;
}
private static void SetupPredPlanes(
@@ -203,12 +176,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
strides[0] = src.Stride;
strides[1] = src.UvStride;
strides[2] = src.UvStride;
int i;
for (i = 0; i < Constants.MaxMbPlane; ++i)
for (int i = 0; i < Constants.MaxMbPlane; ++i)
{
ref MacroBlockDPlane pd = ref planes[i];
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null, pd.SubsamplingX, pd.SubsamplingY);
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null,
pd.SubsamplingX, pd.SubsamplingY);
}
}
@@ -230,14 +203,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
strides[0] = src.Stride;
strides[1] = src.UvStride;
strides[2] = src.UvStride;
int i;
for (i = 0; i < Constants.MaxMbPlane; ++i)
for (int i = 0; i < Constants.MaxMbPlane; ++i)
{
ref MacroBlockDPlane pd = ref xd.Plane[i];
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX, pd.SubsamplingY);
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX,
pd.SubsamplingY);
}
}
}
}
}
}

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 System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred;
@@ -7,7 +7,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class ReconIntra
{
public static readonly TxType[] IntraModeToTxTypeLookup = {
public static readonly TxType[] IntraModeToTxTypeLookup =
{
TxType.DctDct, // DC
TxType.AdstDct, // V
TxType.DctAdst, // H
@@ -17,7 +18,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
TxType.DctAdst, // D153
TxType.DctAdst, // D207
TxType.AdstDct, // D63
TxType.AdstAdst, // TM
TxType.AdstAdst // TM
};
private const int NeedLeft = 1 << 1;
@@ -35,231 +36,123 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
NeedLeft | NeedAbove, // D153
NeedLeft, // D207
NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM
NeedLeft | NeedAbove // TM
};
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
private static readonly unsafe IntraPredFn[][] _pred = {
new IntraPredFn[]
{
null,
null,
null,
null,
},
new IntraPredFn[]
{
VPredictor4x4,
VPredictor8x8,
VPredictor16x16,
VPredictor32x32,
},
new IntraPredFn[]
{
HPredictor4x4,
HPredictor8x8,
HPredictor16x16,
HPredictor32x32,
},
new IntraPredFn[]
{
D45Predictor4x4,
D45Predictor8x8,
D45Predictor16x16,
D45Predictor32x32,
},
new IntraPredFn[]
{
D135Predictor4x4,
D135Predictor8x8,
D135Predictor16x16,
D135Predictor32x32,
},
new IntraPredFn[]
{
D117Predictor4x4,
D117Predictor8x8,
D117Predictor16x16,
D117Predictor32x32,
},
new IntraPredFn[]
{
D153Predictor4x4,
D153Predictor8x8,
D153Predictor16x16,
D153Predictor32x32,
},
new IntraPredFn[]
{
D207Predictor4x4,
D207Predictor8x8,
D207Predictor16x16,
D207Predictor32x32,
},
new IntraPredFn[]
{
D63Predictor4x4,
D63Predictor8x8,
D63Predictor16x16,
D63Predictor32x32,
},
new IntraPredFn[]
{
TMPredictor4x4,
TMPredictor8x8,
TMPredictor16x16,
TMPredictor32x32,
},
private static readonly unsafe IntraPredFn[][] Pred =
{
new IntraPredFn[] { null, null, null, null },
new IntraPredFn[] { VPredictor4x4, VPredictor8x8, VPredictor16x16, VPredictor32x32 },
new IntraPredFn[] { HPredictor4x4, HPredictor8x8, HPredictor16x16, HPredictor32x32 },
new IntraPredFn[] { D45Predictor4x4, D45Predictor8x8, D45Predictor16x16, D45Predictor32x32 },
new IntraPredFn[] { D135Predictor4x4, D135Predictor8x8, D135Predictor16x16, D135Predictor32x32 },
new IntraPredFn[] { D117Predictor4x4, D117Predictor8x8, D117Predictor16x16, D117Predictor32x32 },
new IntraPredFn[] { D153Predictor4x4, D153Predictor8x8, D153Predictor16x16, D153Predictor32x32 },
new IntraPredFn[] { D207Predictor4x4, D207Predictor8x8, D207Predictor16x16, D207Predictor32x32 },
new IntraPredFn[] { D63Predictor4x4, D63Predictor8x8, D63Predictor16x16, D63Predictor32x32 },
new IntraPredFn[] { TmPredictor4x4, TmPredictor8x8, TmPredictor16x16, TmPredictor32x32 }
};
private static readonly unsafe IntraPredFn[][][] _dcPred = {
private static readonly unsafe IntraPredFn[][][] DcPred =
{
new[]
{
new IntraPredFn[]
{
Dc128Predictor4x4,
Dc128Predictor8x8,
Dc128Predictor16x16,
Dc128Predictor32x32,
Dc128Predictor4x4, Dc128Predictor8x8, Dc128Predictor16x16, Dc128Predictor32x32
},
new IntraPredFn[]
{
DcTopPredictor4x4,
DcTopPredictor8x8,
DcTopPredictor16x16,
DcTopPredictor32x32,
},
DcTopPredictor4x4, DcTopPredictor8x8, DcTopPredictor16x16, DcTopPredictor32x32
}
},
new[]
{
new IntraPredFn[]
{
DcLeftPredictor4x4,
DcLeftPredictor8x8,
DcLeftPredictor16x16,
DcLeftPredictor32x32,
DcLeftPredictor4x4, DcLeftPredictor8x8, DcLeftPredictor16x16, DcLeftPredictor32x32
},
new IntraPredFn[]
{
DcPredictor4x4,
DcPredictor8x8,
DcPredictor16x16,
DcPredictor32x32,
},
},
new IntraPredFn[] { DcPredictor4x4, DcPredictor8x8, DcPredictor16x16, DcPredictor32x32 }
}
};
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
private static readonly unsafe IntraHighPredFn[][] _predHigh = {
private static readonly unsafe IntraHighPredFn[][] PredHigh =
{
new IntraHighPredFn[] { null, null, null, null },
new IntraHighPredFn[]
{
null,
null,
null,
null,
HighbdVPredictor4x4, HighbdVPredictor8x8, HighbdVPredictor16x16, HighbdVPredictor32x32
},
new IntraHighPredFn[]
{
HighbdVPredictor4x4,
HighbdVPredictor8x8,
HighbdVPredictor16x16,
HighbdVPredictor32x32,
HighbdHPredictor4x4, HighbdHPredictor8x8, HighbdHPredictor16x16, HighbdHPredictor32x32
},
new IntraHighPredFn[]
{
HighbdHPredictor4x4,
HighbdHPredictor8x8,
HighbdHPredictor16x16,
HighbdHPredictor32x32,
HighbdD45Predictor4x4, HighbdD45Predictor8x8, HighbdD45Predictor16x16, HighbdD45Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD45Predictor4x4,
HighbdD45Predictor8x8,
HighbdD45Predictor16x16,
HighbdD45Predictor32x32,
HighbdD135Predictor4x4, HighbdD135Predictor8x8, HighbdD135Predictor16x16,
HighbdD135Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD135Predictor4x4,
HighbdD135Predictor8x8,
HighbdD135Predictor16x16,
HighbdD135Predictor32x32,
HighbdD117Predictor4x4, HighbdD117Predictor8x8, HighbdD117Predictor16x16,
HighbdD117Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD117Predictor4x4,
HighbdD117Predictor8x8,
HighbdD117Predictor16x16,
HighbdD117Predictor32x32,
HighbdD153Predictor4x4, HighbdD153Predictor8x8, HighbdD153Predictor16x16,
HighbdD153Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD153Predictor4x4,
HighbdD153Predictor8x8,
HighbdD153Predictor16x16,
HighbdD153Predictor32x32,
HighbdD207Predictor4x4, HighbdD207Predictor8x8, HighbdD207Predictor16x16,
HighbdD207Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD207Predictor4x4,
HighbdD207Predictor8x8,
HighbdD207Predictor16x16,
HighbdD207Predictor32x32,
HighbdD63Predictor4x4, HighbdD63Predictor8x8, HighbdD63Predictor16x16, HighbdD63Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD63Predictor4x4,
HighbdD63Predictor8x8,
HighbdD63Predictor16x16,
HighbdD63Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdTMPredictor4x4,
HighbdTMPredictor8x8,
HighbdTMPredictor16x16,
HighbdTMPredictor32x32,
},
HighbdTmPredictor4x4, HighbdTmPredictor8x8, HighbdTmPredictor16x16, HighbdTmPredictor32x32
}
};
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
private static readonly unsafe IntraHighPredFn[][][] DcPredHigh =
{
new[]
{
new IntraHighPredFn[]
{
HighbdDc128Predictor4x4,
HighbdDc128Predictor8x8,
HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32,
HighbdDc128Predictor4x4, HighbdDc128Predictor8x8, HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32
},
new IntraHighPredFn[]
{
HighbdDcTopPredictor4x4,
HighbdDcTopPredictor8x8,
HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32,
},
HighbdDcTopPredictor4x4, HighbdDcTopPredictor8x8, HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32
}
},
new[]
{
new IntraHighPredFn[]
{
HighbdDcLeftPredictor4x4,
HighbdDcLeftPredictor8x8,
HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32,
HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32
},
new IntraHighPredFn[]
{
HighbdDcPredictor4x4,
HighbdDcPredictor8x8,
HighbdDcPredictor16x16,
HighbdDcPredictor32x32,
},
},
HighbdDcPredictor4x4, HighbdDcPredictor8x8, HighbdDcPredictor16x16,
HighbdDcPredictor32x32
}
}
};
private static unsafe void BuildIntraPredictorsHigh(
@@ -327,7 +220,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
else
@@ -335,12 +228,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
for (; i < bs; ++i)
{
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
}
}
}
@@ -349,7 +242,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* faster path if the block does not need extension */
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
}
@@ -391,6 +284,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
MemoryUtil.Copy(aboveRow, aboveRef, bs);
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
}
else
@@ -409,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0)
{
/* slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth)
if (x0 + (2 * bs) <= frameWidth)
{
if (rightAvailable != 0 && bs == 4)
{
@@ -427,7 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4)
{
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
else
{
@@ -439,8 +333,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
}
else
@@ -476,11 +371,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict
if (mode == PredictionMode.DcPred)
{
_dcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
DcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
}
else
{
_predHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
PredHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
}
}
@@ -544,7 +439,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
else
@@ -552,12 +447,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
for (; i < bs; ++i)
{
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
}
}
}
@@ -566,7 +461,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* Faster path if the block does not need extension */
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
}
@@ -608,6 +503,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
MemoryUtil.Copy(aboveRow, aboveRef, bs);
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
}
else
@@ -626,7 +522,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0)
{
/* Slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth)
if (x0 + (2 * bs) <= frameWidth)
{
if (rightAvailable != 0 && bs == 4)
{
@@ -644,7 +540,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4)
{
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
else
{
@@ -656,7 +552,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
}
else
@@ -679,6 +575,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
}
else
@@ -691,11 +588,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict
if (mode == PredictionMode.DcPred)
{
_dcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
DcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
}
else
{
_pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
Pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
}
}
@@ -716,7 +613,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int txw = 1 << (int)txSize;
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
int haveLeft = aoff != 0 || !xd.LeftMi.IsNull ? 1 : 0;
int haveRight = (aoff + txw) < bw ? 1 : 0;
int haveRight = aoff + txw < bw ? 1 : 0;
int x = aoff * 4;
int y = loff * 4;
@@ -736,9 +633,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
x,
y,
plane);
return;
}
BuildIntraPredictors(
ref xd,
refr,
@@ -755,4 +652,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
plane);
}
}
}
}

View File

@@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public ArrayPtr<byte> Data;
public int Size;
}
}
}

View File

@@ -12,9 +12,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public int BufEnd;
public Reader BitReader;
public Vp9BackwardUpdates Counts;
public MacroBlockD Xd;
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
public Array32<Array32<int>> Dqcoeff;
public InternalErrorInfo ErrorInfo;
public int DecPartitionPlaneContext(int miRow, int miCol, int bsl)
{
ref sbyte aboveCtx = ref Xd.AboveSegContext[miCol];
ref sbyte leftCtx = ref Xd.LeftSegContext[miRow & Constants.MiMask];
int above = (aboveCtx >> bsl) & 1, left = (leftCtx >> bsl) & 1;
return (left * 2) + above + (bsl * Constants.PartitionPloffset);
}
}
}
}

View File

@@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public PredictionMode Mode;
public Array2<Mv> Mv; // First, second inter predictor motion vectors
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
public enum BitstreamProfile
{
Profile0,
Profile1,
Profile2,
Profile3,
MaxProfiles
}
}

View File

@@ -1,21 +1,21 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum BlockSize
{
Block4x4 = 0,
Block4x8 = 1,
Block8x4 = 2,
Block8x8 = 3,
Block8x16 = 4,
Block16x8 = 5,
Block16x16 = 6,
Block16x32 = 7,
Block32x16 = 8,
Block32x32 = 9,
Block32x64 = 10,
Block64x32 = 11,
Block64x64 = 12,
BlockSizes = 13,
BlockInvalid = BlockSizes,
Block4x4,
Block4x8,
Block8x4,
Block8x8,
Block8x16,
Block16x8,
Block16x16,
Block16x32,
Block32x16,
Block32x32,
Block32x64,
Block64x32,
Block64x64,
BlockSizes,
BlockInvalid = BlockSizes
}
}
}

View File

@@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<byte> Buf;
public int Stride;
}
}
}

View File

@@ -0,0 +1,18 @@
using Ryujinx.Common.Memory;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct BufferPool
{
// Private data associated with the frame buffer callbacks.
public Ptr<InternalFrameBufferList> CbPriv;
// vpx_get_frame_buffer_cb_fn_t get_fb_cb;
// vpx_release_frame_buffer_cb_fn_t release_fb_cb;
public Array12<RefCntBuffer> FrameBufs;
// Frame buffers allocated internally by the codec.
public InternalFrameBufferList IntFrameBuffers;
}
}

View File

@@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
KeyFrame = 0,
InterFrame = 1,
}
}
}

View File

@@ -23,5 +23,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<LoopFilterMask> Lfm;
public int LfmStride;
public void SetDefaultLfDeltas()
{
ModeRefDeltaEnabled = true;
ModeRefDeltaUpdate = true;
RefDeltas[Constants.IntraFrame] = 1;
RefDeltas[Constants.LastFrame] = 0;
RefDeltas[Constants.GoldenFrame] = -1;
RefDeltas[Constants.AltRefFrame] = -1;
ModeDeltas[0] = 0;
ModeDeltas[1] = 0;
}
}
}
}

View File

@@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Array64<LoopFilterThresh> Lfthr;
public Array8<Array4<Array2<byte>>> Lvl;
}
}
}

View File

@@ -21,4 +21,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ushort Int4x4Uv;
public Array64<byte> LflY;
}
}
}

View File

@@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Array16<byte> HevThr;
#pragma warning restore CS0649
}
}
}

View File

@@ -1,4 +1,5 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Video;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
@@ -54,7 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Ptr<InternalErrorInfo> ErrorInfo;
public readonly int GetPredContextSegId()
public int GetPredContextSegId()
{
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
@@ -62,15 +63,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return aboveSip + leftSip;
}
public readonly int GetSkipContext()
public int GetSkipContext()
{
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
return aboveSkip + leftSkip;
}
public readonly int GetPredContextSwitchableInterp()
public int GetPredContextSwitchableInterp()
{
// Note:
// The mode info data structure has a one element border above and to the
@@ -83,18 +83,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
return leftType;
}
else if (leftType == Constants.SwitchableFilters)
if (leftType == Constants.SwitchableFilters)
{
return aboveType;
}
else if (aboveType == Constants.SwitchableFilters)
if (aboveType == Constants.SwitchableFilters)
{
return leftType;
}
else
{
return Constants.SwitchableFilters;
}
return Constants.SwitchableFilters;
}
// The mode info data structure has a one element border above and to the
@@ -104,20 +104,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// 1 - intra/inter, inter/intra
// 2 - intra/--, --/intra
// 3 - intra/intra
public readonly int GetIntraInterContext()
public int GetIntraInterContext()
{
if (!AboveMi.IsNull && !LeftMi.IsNull)
{ // Both edges available
{
// Both edges available
bool aboveIntra = !AboveMi.Value.IsInterBlock();
bool leftIntra = !LeftMi.Value.IsInterBlock();
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
return leftIntra && aboveIntra ? 3 : leftIntra || aboveIntra ? 1 : 0;
}
if (!AboveMi.IsNull || !LeftMi.IsNull)
{ // One edge available
{
// One edge available
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
}
return 0;
}
@@ -125,11 +127,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real blocks.
// The prediction flags in these dummy entries are initialized to 0.
public readonly int GetTxSizeContext()
public int GetTxSizeContext()
{
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
int leftCtx = (!LeftMi.IsNull && LeftMi.Value.Skip == 0) ? (int)LeftMi.Value.TxSize : maxTxSize;
int aboveCtx = !AboveMi.IsNull && AboveMi.Value.Skip == 0 ? (int)AboveMi.Value.TxSize : maxTxSize;
int leftCtx = !LeftMi.IsNull && LeftMi.Value.Skip == 0 ? (int)LeftMi.Value.TxSize : maxTxSize;
if (LeftMi.IsNull)
{
leftCtx = aboveCtx;
@@ -140,14 +142,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
aboveCtx = leftCtx;
}
return (aboveCtx + leftCtx) > maxTxSize ? 1 : 0;
return aboveCtx + leftCtx > maxTxSize ? 1 : 0;
}
public void SetupBlockPlanes(int ssX, int ssY)
{
int i;
for (i = 0; i < Constants.MaxMbPlane; i++)
for (int i = 0; i < Constants.MaxMbPlane; i++)
{
Plane[i].SubsamplingX = i != 0 ? ssX : 0;
Plane[i].SubsamplingY = i != 0 ? ssY : 0;
@@ -158,25 +158,36 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
int aboveIdx = miCol * 2;
int leftIdx = (miRow * 2) & 15;
int i;
for (i = 0; i < Constants.MaxMbPlane; ++i)
for (int i = 0; i < Constants.MaxMbPlane; ++i)
{
ref MacroBlockDPlane pd = ref Plane[i];
pd.AboveContext = AboveContext[i].Slice(aboveIdx >> pd.SubsamplingX);
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY], 16 - (leftIdx >> pd.SubsamplingY));
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY],
16 - (leftIdx >> pd.SubsamplingY));
}
}
internal void SetMiRowCol(ref TileInfo tile, int miRow, int bh, int miCol, int bw, int miRows, int miCols)
{
MbToTopEdge = -((miRow * Constants.MiSize) * 8);
MbToBottomEdge = ((miRows - bh - miRow) * Constants.MiSize) * 8;
MbToLeftEdge = -((miCol * Constants.MiSize) * 8);
MbToRightEdge = ((miCols - bw - miCol) * Constants.MiSize) * 8;
MbToTopEdge = -(miRow * Constants.MiSize * 8);
MbToBottomEdge = (miRows - bh - miRow) * Constants.MiSize * 8;
MbToLeftEdge = -(miCol * Constants.MiSize * 8);
MbToRightEdge = (miCols - bw - miCol) * Constants.MiSize * 8;
// Are edges available for intra prediction?
AboveMi = (miRow != 0) ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
LeftMi = (miCol > tile.MiColStart) ? Mi[-1] : Ptr<ModeInfo>.Null;
AboveMi = miRow != 0 ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
LeftMi = miCol > tile.MiColStart ? Mi[-1] : Ptr<ModeInfo>.Null;
}
public unsafe void DecResetSkipContext()
{
for (int i = 0; i < Constants.MaxMbPlane; i++)
{
ref MacroBlockDPlane pd = ref Plane[i];
MemoryUtil.Fill(pd.AboveContext.ToPointer(), (sbyte)0, pd.N4W);
MemoryUtil.Fill(pd.LeftContext.ToPointer(), (sbyte)0, pd.N4H);
}
}
}
}
}

View File

@@ -15,7 +15,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// Number of 4x4s in current block
public ushort N4W, N4H;
// Log2 of N4W, N4H
public byte N4Wl, N4Hl;
}
}
}

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
@@ -32,11 +32,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
}
public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd)
public TxSize GetUvTxSize(ref MacroBlockDPlane pd)
{
Debug.Assert(SbType < BlockSize.Block8x8 ||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
}
@@ -50,8 +49,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return RefFrame[1] > Constants.IntraFrame;
}
private static readonly int[][] _idxNColumnToSubblock = {
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
private static readonly int[][] IdxNColumnToSubblock =
{
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 }
};
// This function returns either the appropriate sub block or block's mv
@@ -59,8 +59,49 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
{
return blockIdx >= 0 && SbType < BlockSize.Block8x8
? Bmi[_idxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
? Bmi[IdxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
: Mv[whichMv];
}
public Mv MvPredQ4(int idx)
{
Mv res = new()
{
Row = (short)ReconInter.RoundMvCompQ4(
Bmi[0].Mv[idx].Row + Bmi[1].Mv[idx].Row +
Bmi[2].Mv[idx].Row + Bmi[3].Mv[idx].Row),
Col = (short)ReconInter.RoundMvCompQ4(
Bmi[0].Mv[idx].Col + Bmi[1].Mv[idx].Col +
Bmi[2].Mv[idx].Col + Bmi[3].Mv[idx].Col)
};
return res;
}
public Mv MvPredQ2(int idx, int block0, int block1)
{
Mv res = new()
{
Row = (short)ReconInter.RoundMvCompQ2(
Bmi[block0].Mv[idx].Row +
Bmi[block1].Mv[idx].Row),
Col = (short)ReconInter.RoundMvCompQ2(
Bmi[block0].Mv[idx].Col +
Bmi[block1].Mv[idx].Col)
};
return res;
}
// Performs mv sign inversion if indicated by the reference frame combination.
public Mv ScaleMv(int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
{
Mv mv = Mv[refr];
if (refSignBias[RefFrame[refr]] != refSignBias[thisRefFrame])
{
mv.Row *= -1;
mv.Col *= -1;
}
return mv;
}
}
}
}

View File

@@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
BothIntra = 6,
InvalidCase = 9,
}
}
}

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Video;
using System;
using System.Diagnostics;
@@ -12,96 +12,86 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static ReadOnlySpan<byte> LogInBase2 => new byte[]
{
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,
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
};
public readonly bool UseMvHp()
public bool UseHp()
{
const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh;
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
}
public static bool MvJointVertical(MvJointType type)
public static bool JointVertical(MvJointType type)
{
return type == MvJointType.MvJointHzvnz || type == MvJointType.MvJointHnzvnz;
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
}
public static bool MvJointHorizontal(MvJointType type)
public static bool JointHorizontal(MvJointType type)
{
return type == MvJointType.MvJointHnzvz || type == MvJointType.MvJointHnzvnz;
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
}
private static int MvClassBase(MvClassType c)
private static int ClassBase(MvClassType c)
{
return c != 0 ? Constants.Class0Size << ((int)c + 2) : 0;
}
private static MvClassType GetMvClass(int z, Ptr<int> offset)
private static MvClassType GetClass(int z, Ptr<int> offset)
{
MvClassType c = (z >= Constants.Class0Size * 4096) ? MvClassType.MvClass10 : (MvClassType)LogInBase2[z >> 3];
MvClassType c = z >= Constants.Class0Size * 4096 ? MvClassType.Class10 : (MvClassType)LogInBase2[z >> 3];
if (!offset.IsNull)
{
offset.Value = z - MvClassBase(c);
offset.Value = z - ClassBase(c);
}
return c;
}
private static void IncMvComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
private static void IncComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
{
int s, z, c, o = 0, d, e, f;
int o = 0;
Debug.Assert(v != 0); /* Should not be zero */
s = v < 0 ? 1 : 0;
int s = v < 0 ? 1 : 0;
counts.Sign[comp][s] += (uint)incr;
z = (s != 0 ? -v : v) - 1; /* Magnitude - 1 */
int z = (s != 0 ? -v : v) - 1 /* Magnitude - 1 */;
c = (int)GetMvClass(z, new Ptr<int>(ref o));
int c = (int)GetClass(z, new Ptr<int>(ref o));
counts.Classes[comp][c] += (uint)incr;
d = (o >> 3); /* Int mv data */
f = (o >> 1) & 3; /* Fractional pel mv data */
e = (o & 1); /* High precision mv data */
int d = o >> 3 /* Int mv data */;
int f = (o >> 1) & 3 /* Fractional pel mv data */;
int e = o & 1 /* High precision mv data */;
if (c == (int)MvClassType.MvClass0)
if (c == (int)MvClassType.Class0)
{
counts.Class0[comp][d] += (uint)incr;
counts.Class0Fp[comp][d][f] += (uint)incr;
@@ -109,11 +99,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
}
else
{
int i;
int b = c + Constants.Class0Bits - 1; // Number of bits
for (i = 0; i < b; ++i)
for (int i = 0; i < b; ++i)
{
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
counts.Bits[comp][i][(d >> i) & 1] += (uint)incr;
}
counts.Fp[comp][f] += (uint)incr;
@@ -121,56 +110,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
}
}
private readonly MvJointType GetMvJoint()
public MvJointType GetJoint()
{
if (Row == 0)
{
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
return Col == 0 ? MvJointType.Zero : MvJointType.Hnzvz;
}
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
return Col == 0 ? MvJointType.Hzvnz : MvJointType.Hnzvnz;
}
internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts)
internal void Inc(Ptr<Vp9BackwardUpdates> counts)
{
if (!counts.IsNull)
{
MvJointType j = GetMvJoint();
MvJointType j = GetJoint();
++counts.Value.Joints[(int)j];
if (MvJointVertical(j))
if (JointVertical(j))
{
IncMvComponent(Row, ref counts.Value, 0, 1, 1);
IncComponent(Row, ref counts.Value, 0, 1, 1);
}
if (MvJointHorizontal(j))
if (JointHorizontal(j))
{
IncMvComponent(Col, ref counts.Value, 1, 1, 1);
IncComponent(Col, ref counts.Value, 1, 1, 1);
}
}
}
public void ClampMv(int minCol, int maxCol, int minRow, int maxRow)
public void Clamp(int minCol, int maxCol, int minRow, int maxRow)
{
Col = (short)Math.Clamp(Col, minCol, maxCol);
Row = (short)Math.Clamp(Row, minRow, maxRow);
}
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
private const int Border = 16 << 3; // Allow 16 pels in 1/8th pel units
public void ClampMvRef(ref MacroBlockD xd)
public void ClampRef(ref MacroBlockD xd)
{
ClampMv(
xd.MbToLeftEdge - MvBorder,
xd.MbToRightEdge + MvBorder,
xd.MbToTopEdge - MvBorder,
xd.MbToBottomEdge + MvBorder);
Clamp(
xd.MbToLeftEdge - Border,
xd.MbToRightEdge + Border,
xd.MbToTopEdge - Border,
xd.MbToBottomEdge + Border);
}
public void LowerMvPrecision(bool allowHP)
public void LowerPrecision(bool allowHp)
{
bool useHP = allowHP && UseMvHp();
if (!useHP)
bool useHp = allowHp && UseHp();
if (!useHp)
{
if ((Row & 1) != 0)
{
@@ -183,5 +172,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
}
}
}
public bool IsValid()
{
return Row is > Constants.MvLow and < Constants.MvUpp &&
Col is > Constants.MvLow and < Constants.MvUpp;
}
}
}
}

View File

@@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public int Row;
public int Col;
}
}
}

View File

@@ -2,16 +2,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum MvClassType
{
MvClass0 = 0, /* (0, 2] integer pel */
MvClass1 = 1, /* (2, 4] integer pel */
MvClass2 = 2, /* (4, 8] integer pel */
MvClass3 = 3, /* (8, 16] integer pel */
MvClass4 = 4, /* (16, 32] integer pel */
MvClass5 = 5, /* (32, 64] integer pel */
MvClass6 = 6, /* (64, 128] integer pel */
MvClass7 = 7, /* (128, 256] integer pel */
MvClass8 = 8, /* (256, 512] integer pel */
MvClass9 = 9, /* (512, 1024] integer pel */
MvClass10 = 10, /* (1024,2048] integer pel */
Class0, /* (0, 2] integer pel */
Class1, /* (2, 4] integer pel */
Class2, /* (4, 8] integer pel */
Class3, /* (8, 16] integer pel */
Class4, /* (16, 32] integer pel */
Class5, /* (32, 64] integer pel */
Class6, /* (64, 128] integer pel */
Class7, /* (128, 256] integer pel */
Class8, /* (256, 512] integer pel */
Class9, /* (512, 1024] integer pel */
Class10 /* (1024,2048] integer pel */
}
}
}

View File

@@ -2,9 +2,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum MvJointType
{
MvJointZero = 0, /* Zero vector */
MvJointHnzvz = 1, /* Vert zero, hor nonzero */
MvJointHzvnz = 2, /* Hor zero, vert nonzero */
MvJointHnzvnz = 3, /* Both components nonzero */
Zero, /* Zero vector */
Hnzvz, /* Vert zero, hor nonzero */
Hzvnz, /* Hor zero, vert nonzero */
Hnzvnz /* Both components nonzero */
}
}
}

View File

@@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Array2<Mv> Mv;
public Array2<sbyte> RefFrame;
}
}
}

View File

@@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
PartitionTypes,
PartitionInvalid = PartitionTypes,
}
}
}

View File

@@ -1,9 +1,9 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum PlaneType
{
Y = 0,
Uv = 1,
PlaneTypes,
Y,
Uv,
PlaneTypes
}
}
}

View File

@@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Col = col;
}
}
}
}

View File

@@ -1,21 +1,21 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum PredictionMode
{
DcPred = 0, // Average of above and left pixels
VPred = 1, // Vertical
HPred = 2, // Horizontal
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
D135Pred = 4, // Directional 135 deg = 180 - 45
D117Pred = 5, // Directional 117 deg = 180 - 63
D153Pred = 6, // Directional 153 deg = 180 - 27
D207Pred = 7, // Directional 207 deg = 180 + 27
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
TmPred = 9, // True-motion
NearestMv = 10,
NearMv = 11,
ZeroMv = 12,
NewMv = 13,
MbModeCount = 14,
DcPred, // Average of above and left pixels
VPred, // Vertical
HPred, // Horizontal
D45Pred, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
D135Pred, // Directional 135 deg = 180 - 45
D117Pred, // Directional 117 deg = 180 - 63
D153Pred, // Directional 153 deg = 180 - 27
D207Pred, // Directional 207 deg = 180 + 27
D63Pred, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
TmPred, // True-motion
NearestMv,
NearMv,
ZeroMv,
NewMv,
MbModeCount
}
}
}

View File

@@ -2,7 +2,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct RefBuffer
{
public const int InvalidIdx = -1; // Invalid buffer index.
public int Idx;
public Surface Buf;
public ScaleFactors Sf;
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct RefCntBuffer
{
public int RefCount;
public int MiRows;
public int MiCols;
public byte Released;
public VpxCodecFrameBuffer RawFrameBuffer;
public Surface Buf;
}
}

View File

@@ -1,10 +1,10 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum ReferenceMode
{
SingleReference = 0,
CompoundReference = 1,
ReferenceModeSelect = 2,
ReferenceModes = 3,
Single,
Compound,
Select,
ReferenceModes
}
}
}

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter;
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal struct ScaleFactors
{
private const int RefScaleShift = 14;
private const int RefNoScale = (1 << RefScaleShift);
private const int RefNoScale = 1 << RefScaleShift;
private const int RefInvalidScale = -1;
private unsafe delegate void ConvolveFn(
@@ -38,255 +38,114 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int h,
int bd);
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 =
{
new[]
{
new ConvolveFn[]
{
ConvolveCopy,
ConvolveAvg,
},
new ConvolveFn[]
{
Convolve8Vert,
Convolve8AvgVert,
},
new ConvolveFn[] { ConvolveCopy, ConvolveAvg },
new ConvolveFn[] { Convolve8Vert, Convolve8AvgVert }
},
new[]
{
new ConvolveFn[]
{
Convolve8Horiz,
Convolve8AvgHoriz,
},
new ConvolveFn[]
{
Convolve8,
Convolve8Avg,
},
},
new ConvolveFn[] { Convolve8Horiz, Convolve8AvgHoriz },
new ConvolveFn[] { Convolve8, Convolve8Avg }
}
};
private static readonly unsafe ConvolveFn[][][] _predictX16 = {
private static readonly unsafe ConvolveFn[][][] PredictX16 =
{
new[]
{
new ConvolveFn[]
{
ScaledVert,
ScaledAvgVert,
},
new ConvolveFn[]
{
ScaledVert,
ScaledAvgVert,
},
},
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[] { ScaledVert, ScaledAvgVert }, new ConvolveFn[] { ScaledVert, ScaledAvgVert }
},
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
};
private static readonly unsafe ConvolveFn[][][] _predictY16 = {
new[]
{
new ConvolveFn[]
{
ScaledHoriz,
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
new[]
{
new ConvolveFn[]
{
ScaledHoriz,
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
private static readonly unsafe ConvolveFn[][][] PredictY16 =
{
new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
};
private static readonly unsafe ConvolveFn[][][] _predict = {
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
private static readonly unsafe ConvolveFn[][][] Predict =
{
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
};
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 =
{
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolveCopy,
HighbdConvolveAvg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
new HighbdConvolveFn[] { HighbdConvolveCopy, HighbdConvolveAvg },
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
},
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
}
};
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 =
{
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert },
new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
},
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
}
};
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 =
{
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
},
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
}
};
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict =
{
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
},
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
}
};
public int XScaleFP; // Horizontal fixed point scale factor
public int YScaleFP; // Vertical fixed point scale factor
public int XScaleFp; // Horizontal fixed point scale factor
public int YScaleFp; // Vertical fixed point scale factor
public int XStepQ4;
public int YStepQ4;
public readonly int ScaleValueX(int val)
public int ScaleValueX(int val)
{
return IsScaled() ? ScaledX(val) : val;
}
public readonly int ScaleValueY(int val)
public int ScaleValueY(int val)
{
return IsScaled() ? ScaledY(val) : val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe void InterPredict(
public unsafe void InterPredict(
int horiz,
int vert,
int avg,
@@ -307,12 +166,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in either direction.
_predictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
h);
}
else
{
// No scaling in x direction. Must always scale in the y direction.
_predictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
h);
}
}
else
@@ -320,18 +181,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in the y direction. Must always scale in the x direction.
_predictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
h);
}
else
{
// Must always scale in both directions.
_predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe void HighbdInterPredict(
public unsafe void HighbdInterPredict(
int horiz,
int vert,
int avg,
@@ -353,12 +215,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in either direction.
_highbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY,
ys, w, h, bd);
}
else
{
// No scaling in x direction. Must always scale in the y direction.
_highbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys,
w, h, bd);
}
}
else
@@ -366,24 +230,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in the y direction. Must always scale in the x direction.
_highbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys,
w, h, bd);
}
else
{
// Must always scale in both directions.
_highbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w,
h, bd);
}
}
}
private readonly int ScaledX(int val)
private int ScaledX(int val)
{
return (int)((long)val * XScaleFP >> RefScaleShift);
return (int)(((long)val * XScaleFp) >> RefScaleShift);
}
private readonly int ScaledY(int val)
private int ScaledY(int val)
{
return (int)((long)val * YScaleFP >> RefScaleShift);
return (int)(((long)val * YScaleFp) >> RefScaleShift);
}
private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
@@ -399,23 +265,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
Mv32 res = new()
{
Row = ScaledY(mv.Row) + yOffQ4,
Col = ScaledX(mv.Col) + xOffQ4,
};
Mv32 res = new() { Row = ScaledY(mv.Row) + yOffQ4, Col = ScaledX(mv.Col) + xOffQ4 };
return res;
}
public readonly bool IsValidScale()
public bool IsValidScale()
{
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
return XScaleFp != RefInvalidScale && YScaleFp != RefInvalidScale;
}
public readonly bool IsScaled()
public bool IsScaled()
{
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
return IsValidScale() && (XScaleFp != RefNoScale || YScaleFp != RefNoScale);
}
public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
@@ -430,16 +291,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
{
XScaleFP = RefInvalidScale;
YScaleFP = RefInvalidScale;
XScaleFp = RefInvalidScale;
YScaleFp = RefInvalidScale;
return;
}
XScaleFP = GetFixedPointScaleFactor(otherW, thisW);
YScaleFP = GetFixedPointScaleFactor(otherH, thisH);
XScaleFp = GetFixedPointScaleFactor(otherW, thisW);
YScaleFp = GetFixedPointScaleFactor(otherH, thisH);
XStepQ4 = ScaledX(16);
YStepQ4 = ScaledY(16);
}
}
}
}

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum SegLvlFeatures
{
SegLvlAltQ = 0, // Use alternate Quantizer ....
SegLvlAltLf = 1, // Use alternate loop filter value...
SegLvlRefFrame = 2, // Optional Segment reference frame
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
SegLvlMax = 4, // Number of features supported
AltQ, // Use alternate Quantizer ....
AltLf, // Use alternate loop filter value...
RefFrame, // Optional Segment reference frame
Skip, // Optional Segment (0,0) + skip mode
Max // Number of features supported
}
}
}

View File

@@ -1,4 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Video;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
@@ -6,8 +8,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct Segmentation
{
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
public const int SegmentDeltadata = 0;
public const int SegmentAbsdata = 1;
public const int MaxSegments = 8;
public const int SegTreeProbs = MaxSegments - 1;
public const int PredictionProbs = 3;
private static readonly int[] SegFeatureDataSigned = { 1, 1, 0, 0 };
private static readonly int[] SegFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
public bool Enabled;
public bool UpdateMap;
@@ -38,21 +48,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal static int FeatureDataMax(SegLvlFeatures featureId)
{
return _segFeatureDataMax[(int)featureId];
return SegFeatureDataMax[(int)featureId];
}
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
{
return _segFeatureDataSigned[(int)featureId];
return SegFeatureDataSigned[(int)featureId];
}
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
{
Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]);
Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]);
if (segData < 0)
{
Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]);
Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]);
}
FeatureData[segmentId][(int)featureId] = (short)segData;
@@ -67,5 +77,88 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
return FeatureData[segmentId][(int)featureId];
}
public int GetQIndex(int segmentId, int baseQIndex)
{
if (IsSegFeatureActive(segmentId, SegLvlFeatures.AltQ) != 0)
{
int data = GetSegData(segmentId, SegLvlFeatures.AltQ);
int segQIndex = AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
return Math.Clamp(segQIndex, 0, QuantCommon.MaxQ);
}
return baseQIndex;
}
public void SetupSegmentation(ref Vp9EntropyProbs fc, ref ReadBitBuffer rb)
{
UpdateMap = false;
UpdateData = 0;
Enabled = rb.ReadBit() != 0;
if (!Enabled)
{
return;
}
// Segmentation map update
UpdateMap = rb.ReadBit() != 0;
if (UpdateMap)
{
for (int i = 0; i < SegTreeProbs; i++)
{
fc.SegTreeProb[i] = rb.ReadBit() != 0
? (byte)rb.ReadLiteral(8)
: (byte)Prob.MaxProb;
}
TemporalUpdate = rb.ReadBit() != 0;
if (TemporalUpdate)
{
for (int i = 0; i < PredictionProbs; i++)
{
fc.SegPredProb[i] = rb.ReadBit() != 0
? (byte)rb.ReadLiteral(8)
: (byte)Prob.MaxProb;
}
}
else
{
for (int i = 0; i < PredictionProbs; i++)
{
fc.SegPredProb[i] = Prob.MaxProb;
}
}
}
// Segmentation data update
UpdateData = (byte)rb.ReadBit();
if (UpdateData != 0)
{
AbsDelta = (byte)rb.ReadBit();
ClearAllSegFeatures();
for (int i = 0; i < Constants.MaxSegments; i++)
{
for (int j = 0; j < (int)SegLvlFeatures.Max; j++)
{
int data = 0;
int featureEnabled = rb.ReadBit();
if (featureEnabled != 0)
{
EnableSegFeature(i, (SegLvlFeatures)j);
data = rb.DecodeUnsignedMax(FeatureDataMax((SegLvlFeatures)j));
if (IsSegFeatureSigned((SegLvlFeatures)j) != 0)
{
data = rb.ReadBit() != 0 ? -data : data;
}
}
SetSegData(i, (SegLvlFeatures)j, data);
}
}
}
}
}
}
}

View File

@@ -1,12 +1,24 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Video;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal delegate int VpxGetFrameBufferCbFnT(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv,
ulong minSize, ref VpxCodecFrameBuffer fb);
internal struct Surface : ISurface
{
public const int Innerborderinpixels = 96;
public const int InterpExtend = 4;
public const int EncBorderInPixels = 160;
public const int DecBorderInPixels = 32;
public const int Yv12FlagHighbitdepth = 8;
public ArrayPtr<byte> YBuffer;
public ArrayPtr<byte> UBuffer;
public ArrayPtr<byte> VBuffer;
@@ -15,43 +27,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public readonly unsafe Plane UPlane => new((nint)UBuffer.ToPointer(), UBuffer.Length);
public readonly unsafe Plane VPlane => new((nint)VBuffer.ToPointer(), VBuffer.Length);
public readonly FrameField Field => FrameField.Progressive;
public FrameField Field => FrameField.Progressive;
public int Width { get; }
public int Height { get; }
public int AlignedWidth { get; }
public int AlignedHeight { get; }
public int Stride { get; }
public int UvWidth { get; }
public int UvHeight { get; }
public int UvAlignedWidth { get; }
public int UvAlignedHeight { get; }
public int UvStride { get; }
public int Width { get; private set; }
public int Height { get; private set; }
public int AlignedWidth { get; private set; }
public int AlignedHeight { get; private set; }
public int Stride { get; private set; }
public int UvWidth { get; private set; }
public int UvHeight { get; private set; }
public int UvAlignedWidth { get; private set; }
public int UvAlignedHeight { get; private set; }
public int UvStride { get; private set; }
public bool HighBd { get; private set; }
public bool HighBd { get; }
public int FrameSize { get; private set; }
public int Border { get; private set; }
public int YCropWidth => Width;
public int YCropHeight => Height;
public int UvCropWidth => UvWidth;
public int UvCropHeight => UvHeight;
public ArrayPtr<byte> BufferAlloc;
public int BufferAllocSz;
public int SubsamplingX;
public int SubsamplingY;
public uint BitDepth;
public VpxColorSpace ColorSpace;
public VpxColorRange ColorRange;
public int RenderWidth;
public int RenderHeight;
public int Corrupted;
public int Flags;
private readonly nint _pointer;
public Surface(int width, int height)
{
HighBd = false;
const int Border = 32;
const int SsX = 1;
const int SsY = 1;
const int border = 32;
const int ssX = 1;
const int ssY = 1;
const bool highbd = false;
int alignedWidth = (width + 7) & ~7;
int alignedHeight = (height + 7) & ~7;
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
int yplaneSize = (alignedHeight + 2 * Border) * yStride;
int uvWidth = alignedWidth >> SsX;
int uvHeight = alignedHeight >> SsY;
int uvStride = yStride >> SsX;
int uvBorderW = Border >> SsX;
int uvBorderH = Border >> SsY;
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
int yStride = (alignedWidth + (2 * border) + 31) & ~31;
int yplaneSize = (alignedHeight + (2 * border)) * yStride;
int uvWidth = alignedWidth >> ssX;
int uvHeight = alignedHeight >> ssY;
int uvStride = yStride >> ssX;
int uvBorderW = border >> ssX;
int uvBorderH = border >> ssY;
int uvplaneSize = (uvHeight + (2 * uvBorderH)) * uvStride;
int frameSize = (HighBd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
int frameSize = (highbd ? 2 : 1) * (yplaneSize + (2 * uvplaneSize));
nint pointer = Marshal.AllocHGlobal(frameSize);
_pointer = pointer;
@@ -60,25 +91,150 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
AlignedWidth = alignedWidth;
AlignedHeight = alignedHeight;
Stride = yStride;
UvWidth = (width + SsX) >> SsX;
UvHeight = (height + SsY) >> SsY;
UvWidth = (width + ssX) >> ssX;
UvHeight = (height + ssY) >> ssY;
UvAlignedWidth = uvWidth;
UvAlignedHeight = uvHeight;
UvStride = uvStride;
ArrayPtr<byte> NewPlane(int start, int size, int planeBorder)
ArrayPtr<byte> NewPlane(int start, int size, int border)
{
return new ArrayPtr<byte>(pointer + start + planeBorder, size - planeBorder);
return new ArrayPtr<byte>(pointer + start + border, size - border);
}
YBuffer = NewPlane(0, yplaneSize, (Border * yStride) + Border);
YBuffer = NewPlane(0, yplaneSize, (border * yStride) + border);
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
}
public readonly void Dispose()
public unsafe int ReallocFrameBuffer(
MemoryAllocator allocator,
int width,
int height,
int ssX,
int ssY,
bool useHighbitdepth,
int border,
int byteAlignment,
Ptr<VpxCodecFrameBuffer> fb,
VpxGetFrameBufferCbFnT cb,
Ptr<InternalFrameBufferList> cbPriv)
{
int byteAlign = byteAlignment == 0 ? 1 : byteAlignment; // TODO: Is it safe to ignore the alignment?
int alignedWidth = (width + 7) & ~7;
int alignedHeight = (height + 7) & ~7;
int yStride = (alignedWidth + (2 * border) + 31) & ~31;
ulong yplaneSize =
((ulong)(alignedHeight + (2 * border)) * (ulong)yStride) + (ulong)byteAlignment;
int uvWidth = alignedWidth >> ssX;
int uvHeight = alignedHeight >> ssY;
int uvStride = yStride >> ssX;
int uvBorderW = border >> ssX;
int uvBorderH = border >> ssY;
ulong uvplaneSize =
((ulong)(uvHeight + (2 * uvBorderH)) * (ulong)uvStride) + (ulong)byteAlignment;
ulong frameSize = (ulong)(1 + (useHighbitdepth ? 1 : 0)) * (yplaneSize + (2 * uvplaneSize));
ArrayPtr<byte> buf = ArrayPtr<byte>.Null;
// frame_size is stored in buffer_alloc_sz, which is an int. If it won't
// fit, fail early.
if (frameSize > int.MaxValue)
{
return -1;
}
if (cb != null)
{
const int alignAddrExtraSize = 31;
ulong externalFrameSize = frameSize + alignAddrExtraSize;
Debug.Assert(!fb.IsNull);
// Allocation to hold larger frame, or first allocation.
if (cb(allocator, cbPriv, externalFrameSize, ref fb.Value) < 0)
{
return -1;
}
if (fb.Value.Data.IsNull || (ulong)fb.Value.Data.Length < externalFrameSize)
{
return -1;
}
BufferAlloc = fb.Value.Data;
}
else if (frameSize > (ulong)BufferAllocSz)
{
// Allocation to hold larger frame, or first allocation.
allocator.Free(BufferAlloc);
BufferAlloc = ArrayPtr<byte>.Null;
BufferAlloc = allocator.Allocate<byte>((int)frameSize);
if (BufferAlloc.IsNull)
{
return -1;
}
BufferAllocSz = (int)frameSize;
// This memset is needed for fixing valgrind error from C loop filter
// due to access uninitialized memory in frame border. It could be
// removed if border is totally removed.
MemoryUtil.Fill(BufferAlloc.ToPointer(), (byte)0, BufferAllocSz);
}
/* Only support allocating buffers that have a border that's a multiple
* of 32. The border restriction is required to get 16-byte alignment of
* the start of the chroma rows without introducing an arbitrary gap
* between planes, which would break the semantics of things like
* vpx_img_set_rect(). */
if ((border & 0x1f) != 0)
{
return -3;
}
Width = width;
Height = height;
AlignedWidth = alignedWidth;
AlignedHeight = alignedHeight;
Stride = yStride;
UvWidth = (width + ssX) >> ssX;
UvHeight = (height + ssY) >> ssY;
UvAlignedWidth = uvWidth;
UvAlignedHeight = uvHeight;
UvStride = uvStride;
Border = border;
FrameSize = (int)frameSize;
SubsamplingX = ssX;
SubsamplingY = ssY;
buf = BufferAlloc;
if (useHighbitdepth)
{
// Store uint16 addresses when using 16bit framebuffers
buf = BufferAlloc;
Flags = Yv12FlagHighbitdepth;
}
else
{
Flags = 0;
}
YBuffer = buf.Slice((border * yStride) + border);
UBuffer = buf.Slice((int)yplaneSize + (uvBorderH * uvStride) + uvBorderW);
VBuffer = buf.Slice((int)yplaneSize + (int)uvplaneSize + (uvBorderH * uvStride) + uvBorderW);
Corrupted = 0; /* assume not corrupted by errors */
return 0;
}
public void Dispose()
{
Marshal.FreeHGlobal(_pointer);
}
}
}
}

View File

@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static int GetMinLog2TileCols(int sb64Cols)
{
int minLog2 = 0;
while ((MaxTileWidthB64 << minLog2) < sb64Cols)
while (MaxTileWidthB64 << minLog2 < sb64Cols)
{
++minLog2;
}
@@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static int GetMaxLog2TileCols(int sb64Cols)
{
int maxLog2 = 1;
while ((sb64Cols >> maxLog2) >= MinTileWidthB64)
while (sb64Cols >> maxLog2 >= MinTileWidthB64)
{
++maxLog2;
}
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return maxLog2 - 1;
}
public static void GetTileNBits(int miCols, ref int minLog2TileCols, ref int maxLog2TileCols)
public static void GetTileNBits(int miCols, out int minLog2TileCols, out int maxLog2TileCols)
{
int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
minLog2TileCols = GetMinLog2TileCols(sb64Cols);
@@ -83,4 +83,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Debug.Assert(minLog2TileCols <= maxLog2TileCols);
}
}
}
}

View File

@@ -1,12 +1,12 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
public enum TxMode
{
Only4X4 = 0, // Only 4x4 transform used
Allow8X8 = 1, // Allow block transform size up to 8x8
Allow16X16 = 2, // Allow block transform size up to 16x16
Allow32X32 = 3, // Allow block transform size up to 32x32
TxModeSelect = 4, // Transform specified for each block
TxModes = 5,
Only4x4, // Only 4x4 transform used
Allow8x8, // Allow block transform size up to 8x8
Allow16x16, // Allow block transform size up to 16x16
Allow32x32, // Allow block transform size up to 32x32
TxModeSelect, // Transform specified for each block
TxModes
}
}
}

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
public enum TxSize
{
Tx4x4 = 0, // 4x4 transform
Tx8x8 = 1, // 8x8 transform
Tx16x16 = 2, // 16x16 transform
Tx32x32 = 3, // 32x32 transform
TxSizes = 4,
Tx4x4, // 4x4 transform
Tx8x8, // 8x8 transform
Tx16x16, // 16x16 transform
Tx32x32, // 32x32 transform
TxSizes
}
}
}

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum TxType
{
DctDct = 0, // DCT in both horizontal and vertical
AdstDct = 1, // ADST in vertical, DCT in horizontal
DctAdst = 2, // DCT in vertical, ADST in horizontal
AdstAdst = 3, // ADST in both directions
TxTypes = 4,
DctDct, // DCT in both horizontal and vertical
AdstDct, // ADST in vertical, DCT in horizontal
DctAdst, // DCT in vertical, ADST in horizontal
AdstAdst, // ADST in both directions
TxTypes
}
}
}

View File

@@ -1,6 +1,8 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
using Ryujinx.Graphics.Video;
using System;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
@@ -9,27 +11,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public MacroBlockD Mb;
public ArrayPtr<TileWorkerData> TileWorkerData;
public int TotalTiles;
public InternalErrorInfo Error;
public VpxColorSpace ColorSpace;
public VpxColorRange ColorRange;
public int Width;
public int Height;
public int RenderWidth;
public int RenderHeight;
public int LastWidth;
public int LastHeight;
public int SubsamplingX;
public int SubsamplingY;
public bool UseHighBitDepth;
public ArrayPtr<MvRef> PrevFrameMvs;
public ArrayPtr<MvRef> CurFrameMvs;
public Ptr<Surface> FrameToShow;
public Ptr<RefCntBuffer> PrevFrame;
public Ptr<RefCntBuffer> CurFrame;
public Array8<int> RefFrameMap; /* maps fb_idx to reference slot */
// Prepare ref_frame_map for the next frame.
// Only used in frame parallel decode.
public Array8<int> NextRefFrameMap;
public Array3<RefBuffer> FrameRefs;
public int NewFbIdx;
public int CurShowFrameFbIdx;
public FrameType LastFrameType;
public FrameType FrameType;
public int ShowFrame;
public int LastShowFrame;
public int ShowExistingFrame;
// Flag signaling that the frame is encoded using only Intra modes.
public bool IntraOnly;
public bool LastIntraOnly;
public bool AllowHighPrecisionMv;
public int ResetFrameContext;
// MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
// ModeInfo (8-pixel) units.
public int MBs;
@@ -49,8 +86,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
/* We allocate a ModeInfo struct for each macroblock, together with
an extra row on top and column on the left to simplify prediction. */
public int MiAllocSize;
public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
// prev_mip and prev_mi will only be allocated in VP9 encoder.
public Ptr<ModeInfo> PrevMip; /* MODE_INFO array 'mip' from last decoded frame */
public Ptr<ModeInfo> PrevMi; /* 'mi' from last frame (points into prev_mip) */
public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
@@ -70,6 +112,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public LoopFilterInfoN LfInfo;
public int RefreshFrameContext; /* Two state 0 = NO, 1 = YES */
public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
public LoopFilter Lf;
@@ -81,22 +125,37 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ReferenceMode ReferenceMode;
public Ptr<Vp9EntropyProbs> Fc;
public ArrayPtr<Vp9EntropyProbs> FrameContexts; // FRAME_CONTEXTS
public uint FrameContextIdx; /* Context to use/update */
public Ptr<Vp9BackwardUpdates> Counts;
public uint CurrentVideoFrame;
public BitstreamProfile Profile;
public BitDepth BitDepth;
public BitDepth DequantBitDepth; // bit_depth of current dequantizer
public int ErrorResilientMode;
public int FrameParallelDecodingMode;
public int Log2TileCols, Log2TileRows;
public int ByteAlignment;
public int SkipLoopFilter;
public Ptr<BufferPool> BufferPool;
public ArrayPtr<sbyte> AboveSegContext;
public ArrayPtr<sbyte> AboveContext;
public readonly bool FrameIsIntraOnly()
public bool FrameIsIntraOnly()
{
return FrameType == FrameType.KeyFrame || IntraOnly;
}
public bool CompoundReferenceAllowed()
{
int i;
for (i = 1; i < Constants.RefsPerFrame; ++i)
for (int i = 1; i < Constants.RefsPerFrame; ++i)
{
if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
{
@@ -107,6 +166,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return false;
}
public ref Surface GetFrameNewBuffer()
{
return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf;
}
public int GetFreeFb()
{
ref Array12<RefCntBuffer> frameBufs = ref BufferPool.Value.FrameBufs;
int i;
for (i = 0; i < Constants.FrameBuffers; ++i)
{
if (frameBufs[i].RefCount == 0)
{
break;
}
}
if (i != Constants.FrameBuffers)
{
frameBufs[i].RefCount = 1;
}
else
{
// Reset i to be INVALID_IDX to indicate no free buffer found.
i = RefBuffer.InvalidIdx;
}
return i;
}
public void SwapCurrentAndLastSegMap()
{
// Swap indices.
(SegMapIdx, PrevSegMapIdx) = (PrevSegMapIdx, SegMapIdx);
CurrentFrameSegMap = SegMapArray[SegMapIdx];
LastFrameSegMap = SegMapArray[PrevSegMapIdx];
}
private static int CalcMiSize(int len)
{
// Len is in mi units.
@@ -129,19 +229,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
{
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
TileWorkerData =
allocator.Allocate<TileWorkerData>((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0));
}
public readonly void FreeTileWorkerData(MemoryAllocator allocator)
public void FreeTileWorkerData(MemoryAllocator allocator)
{
allocator.Free(TileWorkerData);
}
private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
{
int i;
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
{
SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
}
@@ -156,9 +255,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private void FreeSegMap(MemoryAllocator allocator)
{
int i;
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
{
allocator.Free(SegMapArray[i]);
SegMapArray[i] = ArrayPtr<byte>.Null;
@@ -194,6 +291,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
allocator.Free(CurFrameMvs);
CurFrameMvs = ArrayPtr<MvRef>.Null;
if (UsePrevFrameMvs)
{
allocator.Free(PrevFrameMvs);
@@ -209,7 +307,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
}
public void AllocContextBuffers(MemoryAllocator allocator, int width, int height)
public bool AllocContextBuffers(MemoryAllocator allocator, int width, int height)
{
SetMbMi(width, height);
int newMiSize = MiStride * CalcMiSize(MiRows);
@@ -239,6 +337,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
}
return false;
}
private unsafe void DecSetupMi()
@@ -257,7 +357,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
}
}
private readonly void SetPartitionProbs(ref MacroBlockD xd)
private void SetPartitionProbs(ref MacroBlockD xd)
{
xd.PartitionProbs = FrameIsIntraOnly()
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
@@ -266,9 +366,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
{
int i;
for (i = 0; i < Constants.MaxMbPlane; ++i)
for (int i = 0; i < Constants.MaxMbPlane; ++i)
{
xd.Plane[i].DqCoeff = dqcoeff;
xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
@@ -281,6 +379,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
}
xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
}
@@ -293,29 +392,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void SetupSegmentationDequant()
{
const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
// Build y/uv dequant values based on segmentation.
if (Seg.Enabled)
{
int i;
for (i = 0; i < Constants.MaxSegments; ++i)
for (int i = 0; i < Constants.MaxSegments; ++i)
{
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
int qindex = Seg.GetQIndex(i, BaseQindex);
YDequant[i][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
}
}
else
{
int qIndex = BaseQindex;
int qindex = BaseQindex;
// When segmentation is disabled, only the first value is used. The
// remaining are don't cares.
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
YDequant[0][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
}
}
@@ -327,5 +424,576 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
}
}
public void ReadFrameReferenceModeProbs(ref Reader r)
{
ref Vp9EntropyProbs fc = ref Fc.Value;
if (ReferenceMode == ReferenceMode.Select)
{
for (int i = 0; i < Constants.CompInterContexts; ++i)
{
r.DiffUpdateProb(ref fc.CompInterProb[i]);
}
}
if (ReferenceMode != ReferenceMode.Compound)
{
for (int i = 0; i < Constants.RefContexts; ++i)
{
r.DiffUpdateProb(ref fc.SingleRefProb[i][0]);
r.DiffUpdateProb(ref fc.SingleRefProb[i][1]);
}
}
if (ReferenceMode != ReferenceMode.Single)
{
for (int i = 0; i < Constants.RefContexts; ++i)
{
r.DiffUpdateProb(ref fc.CompRefProb[i]);
}
}
}
public ReferenceMode ReadFrameReferenceMode(ref Reader r)
{
if (CompoundReferenceAllowed())
{
return r.ReadBit() != 0
? r.ReadBit() != 0 ? ReferenceMode.Select : ReferenceMode.Compound
: ReferenceMode.Single;
}
return ReferenceMode.Single;
}
public void SetupCompoundReferenceMode()
{
if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.GoldenFrame])
{
CompFixedRef = Constants.AltRefFrame;
CompVarRef[0] = Constants.LastFrame;
CompVarRef[1] = Constants.GoldenFrame;
}
else if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.AltRefFrame])
{
CompFixedRef = Constants.GoldenFrame;
CompVarRef[0] = Constants.LastFrame;
CompVarRef[1] = Constants.AltRefFrame;
}
else
{
CompFixedRef = Constants.LastFrame;
CompVarRef[0] = Constants.GoldenFrame;
CompVarRef[1] = Constants.AltRefFrame;
}
}
public void InitMvProbs()
{
Fc.Value.Joints[0] = 32;
Fc.Value.Joints[1] = 64;
Fc.Value.Joints[2] = 96;
Fc.Value.Sign[0] = 128;
Fc.Value.Classes[0][0] = 224;
Fc.Value.Classes[0][1] = 144;
Fc.Value.Classes[0][2] = 192;
Fc.Value.Classes[0][3] = 168;
Fc.Value.Classes[0][4] = 192;
Fc.Value.Classes[0][5] = 176;
Fc.Value.Classes[0][6] = 192;
Fc.Value.Classes[0][7] = 198;
Fc.Value.Classes[0][8] = 198;
Fc.Value.Classes[0][9] = 245;
Fc.Value.Class0[0][0] = 216;
Fc.Value.Bits[0][0] = 136;
Fc.Value.Bits[0][1] = 140;
Fc.Value.Bits[0][2] = 148;
Fc.Value.Bits[0][3] = 160;
Fc.Value.Bits[0][4] = 176;
Fc.Value.Bits[0][5] = 192;
Fc.Value.Bits[0][6] = 224;
Fc.Value.Bits[0][7] = 234;
Fc.Value.Bits[0][8] = 234;
Fc.Value.Bits[0][9] = 240;
Fc.Value.Class0Fp[0][0][0] = 128;
Fc.Value.Class0Fp[0][0][1] = 128;
Fc.Value.Class0Fp[0][0][2] = 64;
Fc.Value.Class0Fp[0][1][0] = 96;
Fc.Value.Class0Fp[0][1][1] = 112;
Fc.Value.Class0Fp[0][1][2] = 64;
Fc.Value.Fp[0][0] = 64;
Fc.Value.Fp[0][1] = 96;
Fc.Value.Fp[0][2] = 64;
Fc.Value.Class0Hp[0] = 160;
Fc.Value.Hp[0] = 128;
Fc.Value.Sign[1] = 128;
Fc.Value.Classes[1][0] = 216;
Fc.Value.Classes[1][1] = 128;
Fc.Value.Classes[1][2] = 176;
Fc.Value.Classes[1][3] = 160;
Fc.Value.Classes[1][4] = 176;
Fc.Value.Classes[1][5] = 176;
Fc.Value.Classes[1][6] = 192;
Fc.Value.Classes[1][7] = 198;
Fc.Value.Classes[1][8] = 198;
Fc.Value.Classes[1][9] = 208;
Fc.Value.Class0[1][0] = 208;
Fc.Value.Bits[1][0] = 136;
Fc.Value.Bits[1][1] = 140;
Fc.Value.Bits[1][2] = 148;
Fc.Value.Bits[1][3] = 160;
Fc.Value.Bits[1][4] = 176;
Fc.Value.Bits[1][5] = 192;
Fc.Value.Bits[1][6] = 224;
Fc.Value.Bits[1][7] = 234;
Fc.Value.Bits[1][8] = 234;
Fc.Value.Bits[1][9] = 240;
Fc.Value.Class0Fp[1][0][0] = 128;
Fc.Value.Class0Fp[1][0][1] = 128;
Fc.Value.Class0Fp[1][0][2] = 64;
Fc.Value.Class0Fp[1][1][0] = 96;
Fc.Value.Class0Fp[1][1][1] = 112;
Fc.Value.Class0Fp[1][1][2] = 64;
Fc.Value.Fp[1][0] = 64;
Fc.Value.Fp[1][1] = 96;
Fc.Value.Fp[1][2] = 64;
Fc.Value.Class0Hp[1] = 160;
Fc.Value.Hp[1] = 128;
}
public void AdaptMvProbs(bool allowHp)
{
ref Vp9EntropyProbs fc = ref Fc.Value;
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
ref Vp9BackwardUpdates counts = ref Counts.Value;
Prob.VpxTreeMergeProbs(
EntropyMv.JointTree,
preFc.Joints.AsSpan(),
counts.Joints.AsSpan(),
fc.Joints.AsSpan());
for (int i = 0; i < 2; ++i)
{
fc.Sign[i] = Prob.ModeMvMergeProbs(preFc.Sign[i], ref counts.Sign[i]);
Prob.VpxTreeMergeProbs(
EntropyMv.ClassTree,
preFc.Classes[i].AsSpan(),
counts.Classes[i].AsSpan(),
fc.Classes[i].AsSpan());
Prob.VpxTreeMergeProbs(
EntropyMv.Class0Tree,
preFc.Class0[i].AsSpan(),
counts.Class0[i].AsSpan(),
fc.Class0[i].AsSpan());
for (int j = 0; j < EntropyMv.OffsetBits; ++j)
{
fc.Bits[i][j] = Prob.ModeMvMergeProbs(preFc.Bits[i][j], ref counts.Bits[i][j]);
}
for (int j = 0; j < EntropyMv.Class0Size; ++j)
{
Prob.VpxTreeMergeProbs(
EntropyMv.FpTree,
preFc.Class0Fp[i][j].AsSpan(),
counts.Class0Fp[i][j].AsSpan(),
fc.Class0Fp[i][j].AsSpan());
}
Prob.VpxTreeMergeProbs(EntropyMv.FpTree, preFc.Fp[i].AsSpan(), counts.Fp[i].AsSpan(),
fc.Fp[i].AsSpan());
if (allowHp)
{
fc.Class0Hp[i] = Prob.ModeMvMergeProbs(preFc.Class0Hp[i], ref counts.Class0Hp[i]);
fc.Hp[i] = Prob.ModeMvMergeProbs(preFc.Hp[i], ref counts.Hp[i]);
}
}
}
public void ResizeContextBuffers(MemoryAllocator allocator, int width, int height)
{
if (Width != width || Height != height)
{
int newMiRows = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
int newMiCols = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
// Allocations in AllocContextBuffers() depend on individual
// dimensions as well as the overall size.
if (newMiCols > MiCols || newMiRows > MiRows)
{
if (AllocContextBuffers(allocator, width, height))
{
// The Mi* values have been cleared and any existing context
// buffers have been freed. Clear Width and Height to be
// consistent and to force a realloc next time.
Width = 0;
Height = 0;
Error.InternalError(CodecErr.MemError, "Failed to allocate context buffers");
}
}
else
{
SetMbMi(width, height);
}
InitContextBuffers();
Width = width;
Height = height;
}
if (CurFrameMvs.IsNull ||
MiRows > CurFrame.Value.MiRows ||
MiCols > CurFrame.Value.MiCols)
{
ResizeMvBuffer(allocator);
}
}
public void CheckMemError<T>(ref ArrayPtr<T> lval, ArrayPtr<T> expr)
where T : unmanaged
{
lval = expr;
if (lval.IsNull)
{
Error.InternalError(CodecErr.MemError, "Failed to allocate");
}
}
private void ResizeMvBuffer(MemoryAllocator allocator)
{
allocator.Free(CurFrameMvs);
CurFrame.Value.MiRows = MiRows;
CurFrame.Value.MiCols = MiCols;
CheckMemError(ref CurFrameMvs, allocator.Allocate<MvRef>(MiRows * MiCols));
}
public void CheckMemError<T>(ref Ptr<T> lval, Ptr<T> expr) where T : unmanaged
{
lval = expr;
if (lval.IsNull)
{
Error.InternalError(CodecErr.MemError, "Failed to allocate");
}
}
public void SetupTileInfo(ref ReadBitBuffer rb)
{
int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes;
TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols);
// columns
maxOnes = maxLog2TileCols - minLog2TileCols;
Log2TileCols = minLog2TileCols;
while (maxOnes-- != 0 && rb.ReadBit() != 0)
{
Log2TileCols++;
}
if (Log2TileCols > 6)
{
Error.InternalError(CodecErr.CorruptFrame, "Invalid number of tile columns");
}
// rows
Log2TileRows = rb.ReadBit();
if (Log2TileRows != 0)
{
Log2TileRows += rb.ReadBit();
}
}
public void ReadBitdepthColorspaceSampling(ref ReadBitBuffer rb)
{
if (Profile >= BitstreamProfile.Profile2)
{
BitDepth = rb.ReadBit() != 0 ? BitDepth.Bits12 : BitDepth.Bits10;
UseHighBitDepth = true;
}
else
{
BitDepth = BitDepth.Bits8;
UseHighBitDepth = false;
}
ColorSpace = (VpxColorSpace)rb.ReadLiteral(3);
if (ColorSpace != VpxColorSpace.Srgb)
{
ColorRange = (VpxColorRange)rb.ReadBit();
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
{
SubsamplingX = rb.ReadBit();
SubsamplingY = rb.ReadBit();
if (SubsamplingX == 1 && SubsamplingY == 1)
{
Error.InternalError(CodecErr.UnsupBitstream,
"4:2:0 color not supported in profile 1 or 3");
}
if (rb.ReadBit() != 0)
{
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
}
}
else
{
SubsamplingY = SubsamplingX = 1;
}
}
else
{
ColorRange = VpxColorRange.Full;
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
{
// Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed.
// 4:2:2 or 4:4:0 chroma sampling is not allowed.
SubsamplingY = SubsamplingX = 0;
if (rb.ReadBit() != 0)
{
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
}
}
else
{
Error.InternalError(CodecErr.UnsupBitstream, "4:4:4 color not supported in profile 0 or 2");
}
}
}
public void AdaptModeProbs()
{
ref Vp9EntropyProbs fc = ref Fc.Value;
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
ref Vp9BackwardUpdates counts = ref Counts.Value;
for (int i = 0; i < Constants.IntraInterContexts; i++)
{
fc.IntraInterProb[i] = Prob.ModeMvMergeProbs(preFc.IntraInterProb[i], ref counts.IntraInter[i]);
}
for (int i = 0; i < Constants.CompInterContexts; i++)
{
fc.CompInterProb[i] = Prob.ModeMvMergeProbs(preFc.CompInterProb[i], ref counts.CompInter[i]);
}
for (int i = 0; i < Constants.RefContexts; i++)
{
fc.CompRefProb[i] = Prob.ModeMvMergeProbs(preFc.CompRefProb[i], ref counts.CompRef[i]);
}
for (int i = 0; i < Constants.RefContexts; i++)
{
for (int j = 0; j < 2; j++)
{
fc.SingleRefProb[i][j] =
Prob.ModeMvMergeProbs(preFc.SingleRefProb[i][j], ref counts.SingleRef[i][j]);
}
}
for (int i = 0; i < Constants.InterModeContexts; i++)
{
Prob.VpxTreeMergeProbs(
EntropyMode.InterModeTree,
preFc.InterModeProb[i].AsSpan(),
counts.InterMode[i].AsSpan(),
fc.InterModeProb[i].AsSpan());
}
for (int i = 0; i < EntropyMode.BlockSizeGroups; i++)
{
Prob.VpxTreeMergeProbs(
EntropyMode.IntraModeTree,
preFc.YModeProb[i].AsSpan(),
counts.YMode[i].AsSpan(),
fc.YModeProb[i].AsSpan());
}
for (int i = 0; i < Constants.IntraModes; ++i)
{
Prob.VpxTreeMergeProbs(
EntropyMode.IntraModeTree,
preFc.UvModeProb[i].AsSpan(),
counts.UvMode[i].AsSpan(),
fc.UvModeProb[i].AsSpan());
}
for (int i = 0; i < Constants.PartitionContexts; i++)
{
Prob.VpxTreeMergeProbs(
EntropyMode.PartitionTree,
preFc.PartitionProb[i].AsSpan(),
counts.Partition[i].AsSpan(),
fc.PartitionProb[i].AsSpan());
}
if (InterpFilter == Constants.Switchable)
{
for (int i = 0; i < Constants.SwitchableFilterContexts; i++)
{
Prob.VpxTreeMergeProbs(
EntropyMode.SwitchableInterpTree,
preFc.SwitchableInterpProb[i].AsSpan(),
counts.SwitchableInterp[i].AsSpan(),
fc.SwitchableInterpProb[i].AsSpan());
}
}
if (TxMode == TxMode.TxModeSelect)
{
Array1<Array2<uint>> branchCt8x8P = new();
Array2<Array2<uint>> branchCt16x16P = new();
Array3<Array2<uint>> branchCt32x32P = new();
for (int i = 0; i < EntropyMode.TxSizeContexts; ++i)
{
EntropyMode.TxCountsToBranchCounts8x8(counts.Tx8x8[i].AsSpan(), ref branchCt8x8P);
for (int j = 0; j < (int)TxSize.TxSizes - 3; ++j)
{
fc.Tx8x8Prob[i][j] = Prob.ModeMvMergeProbs(preFc.Tx8x8Prob[i][j], ref branchCt8x8P[j]);
}
EntropyMode.TxCountsToBranchCounts16x16(counts.Tx16x16[i].AsSpan(), ref branchCt16x16P);
for (int j = 0; j < (int)TxSize.TxSizes - 2; ++j)
{
fc.Tx16x16Prob[i][j] =
Prob.ModeMvMergeProbs(preFc.Tx16x16Prob[i][j], ref branchCt16x16P[j]);
}
EntropyMode.TxCountsToBranchCounts32x32(counts.Tx32x32[i].AsSpan(), ref branchCt32x32P);
for (int j = 0; j < (int)TxSize.TxSizes - 1; ++j)
{
fc.Tx32x32Prob[i][j] =
Prob.ModeMvMergeProbs(preFc.Tx32x32Prob[i][j], ref branchCt32x32P[j]);
}
}
}
for (int i = 0; i < Constants.SkipContexts; ++i)
{
fc.SkipProb[i] = Prob.ModeMvMergeProbs(preFc.SkipProb[i], ref counts.Skip[i]);
}
}
public void AdaptCoefProbs()
{
byte t;
uint countSat, updateFactor;
if (FrameIsIntraOnly())
{
updateFactor = Entropy.CoefMaxUpdateFactorKey;
countSat = Entropy.CoefCountSatKey;
}
else if (LastFrameType == FrameType.KeyFrame)
{
updateFactor = Entropy.CoefMaxUpdateFactorAfterKey; /* adapt quickly */
countSat = Entropy.CoefCountSatAfterKey;
}
else
{
updateFactor = Entropy.CoefMaxUpdateFactor;
countSat = Entropy.CoefCountSat;
}
for (t = (int)TxSize.Tx4x4; t <= (int)TxSize.Tx32x32; t++)
{
AdaptCoefProbs(t, countSat, updateFactor);
}
}
public void SetMvs(ReadOnlySpan<Vp9MvRef> mvs)
{
if (mvs.Length > PrevFrameMvs.Length)
{
throw new ArgumentException(
$"Size mismatch, expected: {PrevFrameMvs.Length}, but got: {mvs.Length}.");
}
for (int i = 0; i < mvs.Length; i++)
{
ref MvRef mv = ref 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];
}
}
public void GetMvs(Span<Vp9MvRef> mvs)
{
if (mvs.Length > CurFrameMvs.Length)
{
throw new ArgumentException(
$"Size mismatch, expected: {CurFrameMvs.Length}, but got: {mvs.Length}.");
}
for (int i = 0; i < mvs.Length; i++)
{
ref MvRef mv = ref 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];
}
}
private void AdaptCoefProbs(byte txSize, uint countSat, uint updateFactor)
{
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> probs = ref Fc.Value.CoefProbs[txSize];
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> preProbs = ref preFc.CoefProbs[txSize];
ref Array2<Array2<Array6<Array6<Array4<uint>>>>> counts = ref Counts.Value.Coef[txSize];
ref Array2<Array2<Array6<Array6<uint>>>> eobCounts = ref Counts.Value.EobBranch[txSize];
for (int i = 0; i < Constants.PlaneTypes; ++i)
{
for (int j = 0; j < Entropy.RefTypes; ++j)
{
for (int k = 0; k < Entropy.CoefBands; ++k)
{
for (int l = 0; l < Entropy.BAND_COEFF_CONTEXTS(k); ++l)
{
int n0 = (int)counts[i][j][k][l][Entropy.ZeroToken];
int n1 = (int)counts[i][j][k][l][Entropy.OneToken];
int n2 = (int)counts[i][j][k][l][Entropy.TwoToken];
int neob = (int)counts[i][j][k][l][Entropy.EobModelToken];
Array3<Array2<uint>> branchCt = new();
branchCt[0][0] = (uint)neob;
branchCt[0][1] = (uint)(eobCounts[i][j][k][l] - neob);
branchCt[1][0] = (uint)n0;
branchCt[1][1] = (uint)(n1 + n2);
branchCt[2][0] = (uint)n1;
branchCt[2][1] = (uint)n2;
for (int m = 0; m < Entropy.UnconstrainedNodes; ++m)
{
probs[i][j][k][l][m] = Prob.MergeProbs(preProbs[i][j][k][l][m], ref branchCt[m],
countSat, updateFactor);
}
}
}
}
}
}
public void DefaultCoefProbs()
{
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4x4], Entropy.DefaultCoefProbs4x4);
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8x8], Entropy.DefaultCoefProbs8x8);
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx16x16], Entropy.DefaultCoefProbs16x16);
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32x32], Entropy.DefaultCoefProbs32x32);
}
}
}
}

View File

@@ -0,0 +1,410 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Video;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct Vp9Decoder
{
public Vp9Common Common;
public int ReadyForNewData;
public int RefreshFrameFlags;
public int NeedResync; // Wait for key/intra-only frame.
public int HoldRefBuf; // Hold the reference buffer.
private static void DecreaseRefCount(int idx, ref Array12<RefCntBuffer> frameBufs, ref BufferPool pool)
{
if (idx >= 0 && frameBufs[idx].RefCount > 0)
{
--frameBufs[idx].RefCount;
// A worker may only get a free framebuffer index when calling GetFreeFb.
// But the private buffer is not set up until finish decoding header.
// So any error happens during decoding header, the frame_bufs will not
// have valid priv buffer.
if (frameBufs[idx].Released == 0 && frameBufs[idx].RefCount == 0 &&
!frameBufs[idx].RawFrameBuffer.Priv.IsNull)
{
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[idx].RawFrameBuffer);
frameBufs[idx].Released = 1;
}
}
}
public void Create(MemoryAllocator allocator, ref BufferPool pool)
{
ref Vp9Common cm = ref Common;
cm.CheckMemError(ref cm.Fc,
new Ptr<Vp9EntropyProbs>(ref allocator.Allocate<Vp9EntropyProbs>(1)[0]));
cm.CheckMemError(ref cm.FrameContexts,
allocator.Allocate<Vp9EntropyProbs>(Constants.FrameContexts));
for (int i = 0; i < EntropyMode.KfYModeProb.Length; i++)
{
for (int j = 0; j < EntropyMode.KfYModeProb[i].Length; j++)
{
for (int k = 0; k < EntropyMode.KfYModeProb[i][j].Length; k++)
{
cm.Fc.Value.KfYModeProb[i][j][k] = EntropyMode.KfYModeProb[i][j][k];
}
}
}
for (int i = 0; i < EntropyMode.KfUvModeProb.Length; i++)
{
for (int j = 0; j < EntropyMode.KfUvModeProb[i].Length; j++)
{
cm.Fc.Value.KfUvModeProb[i][j] = EntropyMode.KfUvModeProb[i][j];
}
}
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
};
for (int i = 0; i < KfPartitionProbs.Length; i++)
{
for (int j = 0; j < KfPartitionProbs[i].Length; j++)
{
cm.Fc.Value.KfPartitionProb[i][j] = KfPartitionProbs[i][j];
}
}
cm.Counts = new Ptr<Vp9BackwardUpdates>(ref allocator.Allocate<Vp9BackwardUpdates>(1)[0]);
NeedResync = 1;
// Initialize the references to not point to any frame buffers.
for (int i = 0; i < 8; i++)
{
cm.RefFrameMap[i] = -1;
cm.NextRefFrameMap[i] = -1;
}
cm.CurrentVideoFrame = 0;
ReadyForNewData = 1;
Common.BufferPool = new Ptr<BufferPool>(ref pool);
cm.BitDepth = BitDepth.Bits8;
cm.DequantBitDepth = BitDepth.Bits8;
// vp9_loop_filter_init(ref cm);
}
/* If any buffer updating is signaled it should be done here. */
private void SwapFrameBuffers()
{
int refIndex = 0, mask;
ref Vp9Common cm = ref Common;
ref BufferPool pool = ref cm.BufferPool.Value;
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
for (mask = RefreshFrameFlags; mask != 0; mask >>= 1)
{
int oldIdx = cm.RefFrameMap[refIndex];
// Current thread releases the holding of reference frame.
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
// Release the reference frame in reference map.
if ((mask & 1) != 0)
{
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
}
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
++refIndex;
}
// Current thread releases the holding of reference frame.
for (; refIndex < Constants.RefFrames && cm.ShowExistingFrame == 0; ++refIndex)
{
int oldIdx = cm.RefFrameMap[refIndex];
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
}
HoldRefBuf = 0;
cm.FrameToShow = new Ptr<Surface>(ref cm.GetFrameNewBuffer());
--frameBufs[cm.NewFbIdx].RefCount;
// Invalidate these references until the next frame starts.
for (refIndex = 0; refIndex < 3; refIndex++)
{
cm.FrameRefs[refIndex].Idx = RefBuffer.InvalidIdx;
}
}
public CodecErr ReceiveCompressedData(MemoryAllocator allocator, ulong size, ref ArrayPtr<byte> psource)
{
ref Vp9Common cm = ref Common;
ref BufferPool pool = ref cm.BufferPool.Value;
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
ArrayPtr<byte> source = psource;
CodecErr retcode = 0;
cm.Error.ErrorCode = CodecErr.Ok;
if (size == 0)
{
// This is used to signal that we are missing frames.
// We do not know if the missing frame(s) was supposed to update
// any of the reference buffers, but we act conservative and
// mark only the last buffer as corrupted.
if (cm.FrameRefs[0].Idx > 0)
{
cm.FrameRefs[0].Buf.Corrupted = 1;
}
}
ReadyForNewData = 0;
// Check if the previous frame was a frame without any references to it.
if (cm.NewFbIdx >= 0 && frameBufs[cm.NewFbIdx].RefCount == 0 &&
frameBufs[cm.NewFbIdx].Released == 0)
{
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[cm.NewFbIdx].RawFrameBuffer);
frameBufs[cm.NewFbIdx].Released = 1;
}
// Find a free frame buffer. Return error if can not find any.
cm.NewFbIdx = cm.GetFreeFb();
if (cm.NewFbIdx == RefBuffer.InvalidIdx)
{
ReadyForNewData = 1;
cm.Error.InternalError(CodecErr.MemError, "Unable to find free frame buffer");
return cm.Error.ErrorCode;
}
// Assign a MV array to the frame buffer.
cm.CurFrame = new Ptr<RefCntBuffer>(ref pool.FrameBufs[cm.NewFbIdx]);
HoldRefBuf = 0;
DecodeFrame.Decode(allocator, ref this, new ArrayPtr<byte>(ref source[0], (int)size), out psource);
SwapFrameBuffers();
// vpx_clear_system_state();
if (cm.ShowExistingFrame == 0)
{
cm.LastShowFrame = cm.ShowFrame;
cm.PrevFrame = cm.CurFrame;
if (cm.PrevFrameMvs.IsNull || cm.PrevFrameMvs.Length != cm.CurFrameMvs.Length)
{
allocator.Free(cm.PrevFrameMvs);
cm.PrevFrameMvs = allocator.Allocate<MvRef>(cm.CurFrameMvs.Length);
}
cm.CurFrameMvs.AsSpan().CopyTo(cm.PrevFrameMvs.AsSpan());
if (cm.Seg.Enabled)
{
cm.SwapCurrentAndLastSegMap();
}
}
if (cm.ShowFrame != 0)
{
cm.CurShowFrameFbIdx = cm.NewFbIdx;
}
// Update progress in frame parallel decode.
cm.LastWidth = cm.Width;
cm.LastHeight = cm.Height;
if (cm.ShowFrame != 0)
{
cm.CurrentVideoFrame++;
}
return retcode;
}
public int GetRawFrame(ref Surface sd)
{
ref Vp9Common cm = ref Common;
int ret = -1;
if (ReadyForNewData == 1)
{
return ret;
}
ReadyForNewData = 1;
if (cm.ShowFrame == 0)
{
return ret;
}
ReadyForNewData = 1;
sd = cm.FrameToShow.Value;
ret = 0;
return ret;
}
public CodecErr Decode(MemoryAllocator allocator, ArrayPtr<byte> data)
{
ArrayPtr<byte> dataStart = data;
CodecErr res;
Array8<uint> frameSizes = new();
int frameCount = 0;
res = Types.Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out frameCount);
if (res != CodecErr.Ok)
{
return res;
}
// Decode in serial mode.
if (frameCount > 0)
{
for (int i = 0; i < frameCount; ++i)
{
ArrayPtr<byte> dataStartCopy = dataStart;
uint frameSize = frameSizes[i];
if (frameSize > (uint)dataStart.Length)
{
return CodecErr.CorruptFrame;
}
res = ReceiveCompressedData(allocator, frameSize, ref dataStartCopy);
if (res != CodecErr.Ok)
{
return res;
}
dataStart = dataStart.Slice((int)frameSize);
}
}
else
{
while (dataStart.Length != 0)
{
uint frameSize = (uint)dataStart.Length;
res = ReceiveCompressedData(allocator, frameSize, ref dataStart);
if (res != CodecErr.Ok)
{
return res;
}
// Account for suboptimal termination by the encoder.
while (dataStart.Length != 0)
{
byte marker = Types.Decoder.ReadMarker(dataStart);
if (marker != 0)
{
break;
}
dataStart = dataStart.Slice(1);
}
}
}
return res;
}
}
internal static class Decoder
{
public static byte ReadMarker(ArrayPtr<byte> data)
{
return data[0];
}
public static CodecErr ParseSuperframeIndex(ArrayPtr<byte> data, ulong dataSz, ref Array8<uint> sizes, out int count)
{
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
// it is a super frame index. If the last byte of real video compression
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
// not the associated matching marker byte at the front of the index we have
// an invalid bitstream and need to return an error.
byte marker;
Debug.Assert(dataSz != 0);
marker = ReadMarker(data.Slice((int)dataSz - 1));
count = 0;
if ((marker & 0xe0) == 0xc0)
{
uint frames = (uint)(marker & 0x7) + 1;
uint mag = (uint)((marker >> 3) & 0x3) + 1;
ulong indexSz = 2 + (mag * frames);
// This chunk is marked as having a superframe index but doesn't have
// enough data for it, thus it's an invalid superframe index.
if (dataSz < indexSz)
{
return CodecErr.CorruptFrame;
}
{
byte marker2 = ReadMarker(data.Slice((int)(dataSz - indexSz)));
// This chunk is marked as having a superframe index but doesn't have
// the matching marker byte at the front of the index therefore it's an
// invalid chunk.
if (marker != marker2)
{
return CodecErr.CorruptFrame;
}
}
{
// Found a valid superframe index.
ArrayPtr<byte> x = data.Slice((int)(dataSz - indexSz + 1));
for (int i = 0; i < frames; ++i)
{
uint thisSz = 0;
for (int j = 0; j < mag; ++j)
{
thisSz |= (uint)x[0] << j * 8;
x = x.Slice(1);
}
sizes[i] = thisSz;
}
count = (int)frames;
}
}
return CodecErr.Ok;
}
}
}

View File

@@ -0,0 +1,10 @@
using Ryujinx.Common.Memory;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct VpxCodecFrameBuffer
{
public ArrayPtr<byte> Data;
public Ptr<InternalFrameBuffer> Priv;
}
}

View File

@@ -0,0 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum VpxColorRange
{
// Y [16..235], UV [16..240]
Studio,
// YUV/RGB [0..255]
Full
}
}

View File

@@ -0,0 +1,29 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal enum VpxColorSpace
{
// Unknown
Unknown,
// BT.601
Bt601,
// BT.709
Bt709,
// SMPTE.170
Smpte170,
// SMPTE.240
Smpte240,
// BT.2020
Bt2020,
// Reserved
Reserved,
// sRGB
Srgb
}
}

View File

@@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Nvdec.Types.Vp9
Flags.HasFlag(FrameFlags.LastShowFrame) &&
!Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
RefFrameSignBias = RefFrameSignBias,
LoopFilterLevel = FirstLevel,
LoopFilterSharpnessLevel = SharpnessLevel,
BaseQIndex = BaseQIndex,
YDcDeltaQ = YDcDeltaQ,
UvDcDeltaQ = UvDcDeltaQ,

View File

@@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Video
public bool IsKeyFrame;
public bool IntraOnly;
public Array4<sbyte> RefFrameSignBias;
public int LoopFilterLevel;
public int LoopFilterSharpnessLevel;
public int BaseQIndex;
public int YDcDeltaQ;
public int UvDcDeltaQ;
@@ -36,4 +38,4 @@ namespace Ryujinx.Graphics.Video
public Vp9EntropyProbs Entropy;
public Vp9BackwardUpdates BackwardUpdateCounts;
}
}
}

View File

@@ -710,9 +710,8 @@ namespace Ryujinx.HLE.FileSystem
{
updateNcasItem.Add((nca.Header.ContentType, entry.FullName));
}
else
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
{
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName));
}
}
@@ -898,9 +897,8 @@ namespace Ryujinx.HLE.FileSystem
{
updateNcasItem.Add((nca.Header.ContentType, entry.FullPath));
}
else
else if (updateNcas.TryAdd(nca.Header.TitleId, new List<(NcaContentType, string)>()))
{
updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>());
updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullPath));
}

View File

@@ -26,10 +26,20 @@ namespace Ryujinx.HLE.HOS.Applets
{
_normalSession = normalSession;
_interactiveSession = interactiveSession;
// TODO(jduncanator): Parse PlayerSelectConfig from input data
_normalSession.Push(BuildResponse());
UserProfile selected = _system.Device.UIHandler.ShowPlayerSelectDialog();
if (selected == null)
{
_normalSession.Push(BuildResponse());
}
else if (selected.UserId == new UserId("00000000000000000000000000000080"))
{
_normalSession.Push(BuildGuestResponse());
}
else
{
_normalSession.Push(BuildResponse(selected));
}
AppletStateChanged?.Invoke(this, null);
_system.ReturnFocus();
@@ -37,16 +47,34 @@ namespace Ryujinx.HLE.HOS.Applets
return ResultCode.Success;
}
private byte[] BuildResponse()
private byte[] BuildResponse(UserProfile selectedUser)
{
UserProfile currentUser = _system.AccountManager.LastOpenedUser;
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write((ulong)PlayerSelectResult.Success);
currentUser.UserId.Write(writer);
selectedUser.UserId.Write(writer);
return stream.ToArray();
}
private byte[] BuildGuestResponse()
{
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write(new byte());
return stream.ToArray();
}
private byte[] BuildResponse()
{
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
using BinaryWriter writer = new(stream);
writer.Write((ulong)PlayerSelectResult.Failure);
return stream.ToArray();
}

View File

@@ -176,9 +176,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
if (isApplication && lowestCpuCore == 0 && highestCpuCore != 2)
Ryujinx.Common.Logging.Logger.Error?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}! Report this to @LotP on the Ryujinx/Ryubing discord server (discord.gg/ryujinx)!");
else if (isApplication)
if (isApplication)
Ryujinx.Common.Logging.Logger.Info?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}");
break;

View File

@@ -56,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
ProfilesJson profilesJson = JsonHelper.DeserializeFromFile(_profilesJsonPath, _serializerContext.ProfilesJson);
return profilesJson.Profiles
.FindFirst(profile => profile.AccountState == AccountState.Open)
.FindFirst(profile => profile.UserId == profilesJson.LastOpened)
.Convert(profileJson => new UserProfile(new UserId(profileJson.UserId), profileJson.Name,
profileJson.Image, profileJson.LastModifiedTimestamp));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -659,7 +659,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
if (string.IsNullOrWhiteSpace(filePath))
{
throw new InvalidSystemResourceException("JIT (010000000000003B) system title not found! The JIT will not work, provide the system archive to fix this error. (See https://github.com/GreemDev/Ryujinx#requirements for more information)");
throw new InvalidSystemResourceException("JIT (010000000000003B) system title not found! The JIT will not work, provide the system archive to fix this error. (See https://github.com/Ryubing/Ryujinx#requirements for more information)");
}
context.Device.LoadNca(filePath);

View File

@@ -105,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
titleName = "Unknown";
}
throw new InvalidSystemResourceException($"{titleName} ({fontTitle:x8}) system title not found! This font will not work, provide the system archive to fix this error. (See https://github.com/GreemDev/Ryujinx#requirements for more information)");
throw new InvalidSystemResourceException($"{titleName} ({fontTitle:x8}) system title not found! This font will not work, provide the system archive to fix this error. (See https://github.com/Ryubing/Ryujinx#requirements for more information)");
}
}
else

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