Compare commits

...

166 Commits

Author SHA1 Message Date
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
Evan Husted
01ccd18726 UI: Meant to use that method in another place [ci-skip] 2025-01-16 09:52:35 -06:00
Evan Husted
abfbc6f4bc UI: Prevent desynced RPC when toggling it off/on while in-game 2025-01-16 09:52:01 -06:00
Francesco Saltori
6a4bc02d7a Update Italian translation (#489) 2025-01-16 06:38:36 -06:00
Hack茶ん
814c0526d2 Korean translations for compat list (#502) 2025-01-16 04:57:32 -06:00
Evan Husted
a5a4ef38e6 HLE: Stub IHidServer SetGestureOutputRanges (#524)
Lets "Donkey Kong Country Returns HD" get into main gameplay.
2025-01-16 02:39:39 -06:00
Evan Husted
c17e3bfcdf genuinely dont know how that was still there, i thought i got rid of UI.Common 2025-01-15 03:01:17 -06:00
Evan Husted
017f46f318 HLE: misc: throw a more descriptive error when the loaded processes doesn't contain _latestPid (likely missing FW) 2025-01-15 03:01:17 -06:00
Keaton
fd4d801bfd Various NuGet package updates (#203)
Updates the following packages:

**nuget: bump the avalonia group with 7 updates**

* Bump Avalonia, Avalonia.Controls.DataGrid, Avalonia.Desktop,
Avalonia.Diagnostics, and Avalonia.Markup.Xaml.Loader from 11.0.10 to
11.0.13
* Bump Avalonia.Svg and Avalonia.Svg.Skia from 11.0.0.18 to 11.0.0.19

**nuget: bump non-avalonia packages**

* Bump Concentus from 2.2.0 to 2.2.2
* Bump Microsoft.IdentityModel.JsonWebTokens from 8.1.2 to 8.3.0
* Bump Silk.NET.Vulkan group with 3 updates (2.21.0 to 2.22.0)
* Bump SkiaSharp group with 2 updates (2.88.7 to 2.88.9)
2025-01-13 11:15:05 -06:00
GabCoolGuy
f1dee50275 infra: Update to LLVM 17 (#519)
This fixes macos builds not building correctly because of a missing
LLVM 14 package.
2025-01-12 14:57:57 -06:00
shinyoyo
c2ae49eb47 Add some missing Simplified Chinese translations (#515) 2025-01-12 12:33:27 -06:00
WilliamWsyHK
47c71966d0 Add compat of Xenoblade 2 JP edition same as global edition (#517) 2025-01-12 12:31:58 -06:00
Evan Husted
f9e8f4bc29 docs: compat: Ori and the Will of the Wisps is now ingame, not playable 2025-01-11 06:10:58 -06:00
Evan Husted
7694c8c046 Do not auto release stable 2025-01-11 04:08:11 -06:00
Evan Husted
0dd789e8a5 misc: chore: remove redundant trimming on CompatibilityEntry.GameName init 2025-01-11 01:26:34 -06:00
Evan Husted
4e0aafd005 docs: compat: Trim redundant/duplicate information to save space 2025-01-11 01:18:10 -06:00
Evan Husted
c5091f499e docs: compat: The House of the Dead: Remake Playable 2025-01-11 00:38:32 -06:00
Evan Husted
41c8fd8194 misc: chore: lol this field was misspelled 2025-01-10 23:23:53 -06:00
Evan Husted
d4a7ee25ea misc: chore: use ObservableProperty on input view models 2025-01-10 23:23:05 -06:00
Evan Husted
3141c560fb misc: chore: remove sender parameter from LdnGameData receieved event 2025-01-10 23:15:55 -06:00
Evan Husted
de341b285b misc: use ObservableProperty on HotkeyConfig fields 2025-01-10 23:15:37 -06:00
Evan Husted
cc95e80ee9 misc: chore: Move converters into a directory in Helpers. Namespace unchanged 2025-01-10 20:24:53 -06:00
Evan Husted
d75ce52bd4 UI: Show play time in one time unit, maxing out at hours. 2025-01-10 20:23:47 -06:00
Evan Husted
4a4ea557de UI: compat: show last updated date on entry hover 2025-01-10 01:43:34 -06:00
Evan Husted
33f42adb11 Merge remote-tracking branch 'origin/master' 2025-01-09 22:09:01 -06:00
LotP1
918ec1bde3 cores rework (#505)
This PR changes the core count to be defined in the device instead of
being a const value.
This is mostly a change for future features I want to implement and
should not impact any functionality.
The console will now log the range of cores requested from the
application, and for now, if the requested range is not 0 to 2 (the 3
cores used for application emulation), it will give an error message
which tells the user to contact me on discord. I'm doing this because
I'm interested in finding applications/games that don't use 3 cores and
the error will be removed in the future once I've gotten enough data.
2025-01-09 21:43:18 -06:00
Evan Husted
cca429d46a misc: chore: restore not enable 2025-01-09 21:42:54 -06:00
Evan Husted
845c86f545 misc: chore: cleanup AppletMetadata.CanStart 2025-01-09 21:14:35 -06:00
Evan Husted
27993b789f misc: chore: fix some compile warnings 2025-01-09 20:23:26 -06:00
Evan Husted
bdd890cf6f UI: logger function name 2025-01-09 19:48:11 -06:00
Evan Husted
c5574b41a1 UI: collapse LoadFromStream into static ctor
pass the index get delegate to the struct instead of the entire header
2025-01-09 19:44:24 -06:00
Evan Husted
292e27f0da UI: dispose CSV reader when done + use explicit types 2025-01-09 19:24:48 -06:00
Evan Husted
606e149bd3 UI: Create a ColumnIndices struct and pass it by reference to the row ctor instead of recomputing the column index for every column on every row 2025-01-09 18:48:15 -06:00
Evan Husted
a8c3407d11 missing JP title id 2025-01-09 14:25:16 -06:00
Evan Husted
daa8168985 docs: compat: the final title IDs i could find 2025-01-09 14:03:37 -06:00
Vita Chumakova
f580521e99 Update game data in the compatibility database (#507)
The entries were matched with the game database from
https://github.com/blawar/titledb/blob/master/US.en.json, allowing to
fill missing title IDs and fix game names.
2025-01-09 13:18:27 -06:00
Evan Husted
2226521f6c docs: compat: remove quotes around everything but game titles 2025-01-08 12:36:26 -06:00
Evan Husted
384416953d docs: compat: list title ID column first 2025-01-08 12:30:13 -06:00
Evan Husted
1343fabe41 docs: compat: some more missing title ids 2025-01-08 12:20:20 -06:00
Evan Husted
1e52af5e29 docs: compat: Multiple big changes:
Sort alphabetically,
Remove title IDs in "issue_title" column,
and remove all entries without a playability status.
2025-01-07 20:17:09 -06:00
Evan Husted
672f5df0f9 docs: compat: Remove issue_number & events_count columns
That's mostly for archival purposes; we don't need it.
2025-01-07 18:49:04 -06:00
Evan Husted
804d9c1efe docs: compat: remove invalid dupe 2025-01-07 06:03:35 -06:00
Evan Husted
9270b35648 no. 2025-01-07 05:53:31 -06:00
Evan Husted
5a6d01db3c docs: compat: trine 4 -> nothing
added Soul Reaver 1 & 2
2025-01-07 05:50:30 -06:00
Evan Husted
ef9c1416ec UI: compat: Only use monospaced font for title ID 2025-01-07 04:49:20 -06:00
Evan Husted
5efa7d5dfa UI: compat: remove custom ContentDialog derived type 2025-01-07 04:37:36 -06:00
Evan Husted
a82569d615 docs: compat: LEGO Horizon Adventures 2025-01-07 04:28:10 -06:00
Evan Husted
ed5832ca73 docs: compat: Add new releases to the end of the file 2025-01-07 04:21:33 -06:00
Evan Husted
574aa9ff9c add a couple missing title IDs 2025-01-07 04:21:08 -06:00
Evan Husted
8a29428de2 docs: compat: update hogwarts legacy compat 2025-01-07 03:57:13 -06:00
Evan Husted
f4272b05fa UI: Compat list disclaimer 2025-01-07 03:53:10 -06:00
Evan Husted
d8265f7772 Embed compatibility list into executable
instead of downloading

Co-Authored-By: Vita Chumakova <me@ezhevita.dev>
2025-01-07 03:37:07 -06:00
Evan Husted
259526430c UI: Properly space language menu items instead of prepending a space to the language name 2025-01-07 00:36:22 -06:00
Evan Husted
b5fafb6394 UI: stop using async voids in MainMenuBarView; use RelayCommands 2025-01-06 23:52:20 -06:00
Evan Husted
323c356d9c UI: Widen compatibility list, and make search box take up all space horizontally 2025-01-06 22:03:39 -06:00
Evan Husted
30b22ce6ba UI: fix nullref 2025-01-06 08:02:37 -06:00
Evan Husted
9acecc9eb2 UI: default OnlyShowOwnedGames in compat list to true 2025-01-06 07:53:27 -06:00
Evan Husted
4193a37a91 these files are a little bit needed 2025-01-06 07:38:11 -06:00
Evan Husted
c4cc657b89 UI: Compatibility List Viewer 2025-01-06 07:31:57 -06:00
Evan Husted
9726b0feb0 Use Canary-Releases for AppImage Canary updates 2025-01-06 01:27:37 -06:00
Evan Husted
159ff828a1 give canary appimages the ryujinx-canary name 2025-01-06 01:22:05 -06:00
Evan Husted
6fa2bfc736 fix canary ci 2025-01-06 01:15:39 -06:00
Piplup
2c24df0247 reworked workflows (#497)
this makes `canary.yml` follow the same order of steps as `release.yml`,
adding appimages to the canary versions and i fixed some bugs with the
`build-appimage.sh` mainly fixing linking to the old repo
2025-01-06 01:07:16 -06:00
Evan Husted
13efc3e544 Switch back to nightly.link
I'm pretty sure them not working was due to old links pointing to GreemDev/Ryujinx after the org change
2025-01-06 00:09:48 -06:00
Evan Husted
845dd9a8db vk: regression: potentially fix various random graphical anomalies 2025-01-05 22:25:05 -06:00
Evan Husted
b661bdd997 Revert "infra: feat: XML Solution"
This reverts commit cc84041270.
2025-01-05 16:41:08 -06:00
Evan Husted
cc84041270 infra: feat: XML Solution 2025-01-05 16:33:44 -06:00
Evan Husted
987ab9be41 Fix part 2 2025-01-05 16:03:34 -06:00
Evan Husted
8a2bc3957a UI: fix: new updates not being autoloaded 2025-01-05 15:45:01 -06:00
Evan Husted
850df38f1e cleaup imports 2025-01-04 06:54:46 -06:00
Emmanuel Hansen
c8d598d5ac use UnmanagedCallersOnly for delegates 2025-01-04 06:52:25 -06:00
Evan Husted
3e5b2bda38 UI: RPC: Goat Simulator 3 asset image 2025-01-03 22:25:32 -06:00
Evan Husted
9bb50fc6dd misc: improve unpacking error & add nullability to SelectedIcon 2025-01-03 22:25:32 -06:00
Evan Husted
e956864697 misc: Remove needless AsObservableList 2025-01-03 22:25:32 -06:00
WilliamWsyHK
f43442f774 Include Hack for XC2 JP Edition (#481)
XC2 has 2 editions, one JP and one global. I own the JP version and
suffered from the soft-lock, meanwhile the current hack only works for
global edition, so PR is simply include JP edition from the hack.
2025-01-01 02:15:14 -06:00
Evan Husted
88d11d3d8d misc: some cleanups and fix compile warnings 2025-01-01 02:14:59 -06:00
Evan Husted
391f57bdd2 misc: Headless: Inherit main input config 2025-01-01 01:55:10 -06:00
Evan Husted
fd2b5a7fc1 misc: Remove RendererHost AXAML 2025-01-01 01:55:10 -06:00
Otozinclus
37c165e9fc Only delay shader translation on Metal (#480)
This way the Arbitrary Shader Translation Delay hack will no longer
affect shader loading when using Vulkan.
2025-01-01 00:18:17 -06:00
Daenorth
003a6d322b Update to no_NO Norwegian Translation (#475)
Updated for time resync & auto graphics backend
2025-01-01 00:15:21 -06:00
jozz024
978d2c132b add a keyboard shortcut for opening amiibo .bin files (#461) 2024-12-31 22:45:52 -06:00
Evan Husted
5d63706cea misc: Bake in ValueEqual logic into ReactiveEventArgs
[ci skip]
2024-12-31 22:34:14 -06:00
Evan Husted
732aafd3bb misc: Prevent value change logging when the value is changed to the same thing it was before the value change. 2024-12-31 22:23:08 -06:00
Evan Husted
3fa714bb72 misc: DateTimeOffset Extract extension from Gommon 2024-12-31 21:21:54 -06:00
Evan Husted
7c01633f13 UI: Show the path of the mod on the folder button 2024-12-31 21:15:50 -06:00
Evan Husted
27c5cba10b misc: More Mvvm usage instead of writing out the observable properties 2024-12-31 21:11:57 -06:00
Evan Husted
3525d5ecd4 UI: clean up slider UI for shader translation delay 2024-12-31 20:11:49 -06:00
Evan Husted
6286501550 misc: do not log dirty hack changes if ShowDirtyHacks is disabled 2024-12-31 20:11:44 -06:00
Evan Husted
61ae427a4d misc: Add CommunityToolkit.Mvvm for observable property generation; apply it to MainWindowViewModel for now. 2024-12-31 03:29:08 -06:00
Evan Husted
19d2883a35 UI: Store config migrations in a dictionary and loop through it to do migrations. 2024-12-31 02:51:14 -06:00
Evan Husted
617c03119f misc: clean vsync toggle log 2024-12-31 00:52:39 -06:00
Evan Husted
e43d899e1d misc: Use a few static helpers for Avalonia objects 2024-12-31 00:19:23 -06:00
Evan Husted
0cd09ea0c5 misc: Simplify ControlHolder checks in MainWindowViewModel 2024-12-31 00:04:23 -06:00
Evan Husted
4135d74e4d UI: Only allow right click to create a context menu if a game is selected. 2024-12-30 23:50:55 -06:00
Evan Husted
bd29f658b1 misc: Forgot about OfType [ci skip] 2024-12-30 23:28:32 -06:00
Evan Husted
df150f0788 misc: Significantly reduce duplicated code in ConfigurationState migration logic. 300 lines removed; functionally identical. 2024-12-30 23:14:05 -06:00
Evan Husted
e50198b37d Clarify DramSize XMLdoc 2024-12-30 23:11:59 -06:00
248 changed files with 19177 additions and 6823 deletions

View File

@@ -22,7 +22,7 @@ body:
id: log id: log
attributes: attributes:
label: Log file 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). 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: validations:
required: true required: true

View File

@@ -129,11 +129,11 @@ jobs:
with: with:
global-json-file: global.json global-json-file: global.json
- name: Setup LLVM 14 - name: Setup LLVM 17
run: | run: |
wget https://apt.llvm.org/llvm.sh wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh chmod +x llvm.sh
sudo ./llvm.sh 14 sudo ./llvm.sh 17
- name: Install rcodesign - name: Install rcodesign
run: | run: |

View File

@@ -108,6 +108,7 @@ jobs:
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO\%\%/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs sed -r --in-place 's/\%\%RYUJINX_CONFIG_FILE_NAME\%\%/Config\.json/g;' src/Ryujinx.Common/ReleaseInformation.cs
sed -r --in-place '/^Name=Ryujinx$/s/Name=Ryujinx/Name=Ryujinx-Canary/' distribution/linux/Ryujinx.desktop
shell: bash shell: bash
- name: Create output dir - name: Create output dir
@@ -115,71 +116,69 @@ jobs:
- name: Publish - name: Publish
run: | run: |
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_ava/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx --self-contained
- name: Packing Windows builds - name: Packing Windows builds
if: matrix.platform.os == 'windows-latest' if: matrix.platform.os == 'windows-latest'
run: | run: |
pushd publish_ava pushd publish
rm publish/libarmeilleure-jitsupport.dylib rm libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish 7z a ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd popd
shell: bash shell: bash
- name: Packing Linux builds - name: Packing Linux builds
if: matrix.platform.os == 'ubuntu-latest' if: matrix.platform.os == 'ubuntu-latest'
run: | run: |
pushd publish_ava pushd publish
rm publish/libarmeilleure-jitsupport.dylib rm libarmeilleure-jitsupport.dylib
chmod +x publish/Ryujinx.sh publish/Ryujinx chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish tar -czvf ../release_output/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd popd
shell: bash shell: bash
#- name: Build AppImage (Linux) - name: Build AppImage (Linux)
# if: matrix.platform.os == 'ubuntu-latest' if: matrix.platform.os == 'ubuntu-latest'
# run: | run: |
# BUILD_VERSION="${{ steps.version_info.outputs.build_version }}" BUILD_VERSION="${{ steps.version_info.outputs.build_version }}"
# PLATFORM_NAME="${{ matrix.platform.name }}" PLATFORM_NAME="${{ matrix.platform.name }}"
# sudo apt install -y zsync desktop-file-utils appstream sudo apt install -y zsync desktop-file-utils appstream
# mkdir -p tools mkdir -p tools
# export PATH="$PATH:$(readlink -f tools)" export PATH="$PATH:$(readlink -f tools)"
# Setup appimagetool # Setup appimagetool
# wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" wget -q -O tools/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
# chmod +x tools/appimagetool chmod +x tools/appimagetool
# chmod +x distribution/linux/appimage/build-appimage.sh chmod +x distribution/linux/appimage/build-appimage.sh
# Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name) # Explicitly set $ARCH for appimagetool ($ARCH_NAME is for the file name)
# if [ "$PLATFORM_NAME" = "linux-x64" ]; then if [ "$PLATFORM_NAME" = "linux-x64" ]; then
# ARCH_NAME=x64 ARCH_NAME=x64
# export ARCH=x86_64 export ARCH=x86_64
# elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then elif [ "$PLATFORM_NAME" = "linux-arm64" ]; then
# ARCH_NAME=arm64 ARCH_NAME=arm64
# export ARCH=aarch64 export ARCH=aarch64
# else else
# echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME"" echo "Unexpected PLATFORM_NAME "$PLATFORM_NAME""
# exit 1 exit 1
# fi fi
# export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|${{ github.event.repository.name }}|latest|*-$ARCH_NAME.AppImage.zsync" export UFLAG="gh-releases-zsync|${{ github.repository_owner }}|Canary-Releases|latest|*-$ARCH_NAME.AppImage.zsync"
# BUILDDIR=publish_ava OUTDIR=publish_ava_appimage distribution/linux/appimage/build-appimage.sh BUILDDIR=publish OUTDIR=publish_appimage distribution/linux/appimage/build-appimage.sh
# Add to release output pushd publish_appimage
# pushd publish_ava_appimage mv Ryujinx.AppImage ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage
# mv Ryujinx.AppImage ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage mv Ryujinx.AppImage.zsync ../release_output/ryujinx-canary-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync
# mv Ryujinx.AppImage.zsync ../release_output/ryujinx-$BUILD_VERSION-$ARCH_NAME.AppImage.zsync popd
# popd shell: bash
# shell: bash
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
with: with:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "release_output/*.tar.gz,release_output/*.zip" artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
#artifacts: "release_output/*.tar.gz,release_output/*.zip,release_output/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: | body: |
# Canary builds: # Canary builds:
@@ -203,7 +202,7 @@ jobs:
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -211,11 +210,11 @@ jobs:
with: with:
global-json-file: global.json global-json-file: global.json
- name: Setup LLVM 15 - name: Setup LLVM 17
run: | run: |
wget https://apt.llvm.org/llvm.sh wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh chmod +x llvm.sh
sudo ./llvm.sh 15 sudo ./llvm.sh 17
- name: Install rcodesign - name: Install rcodesign
run: | run: |

View File

@@ -37,11 +37,11 @@ jobs:
if (!artifacts.length) { if (!artifacts.length) {
return core.error(`No artifacts found`); return core.error(`No artifacts found`);
} }
let body = `*You need to be logged into GitHub to download these files.*\n\nDownload the artifacts for this pull request:\n`; let body = `Download the artifacts for this pull request:\n`;
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`; let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
for (const art of artifacts) { for (const art of artifacts) {
const url = `https://github.com/Ryubing/Ryujinx/actions/runs/${run_id}/artifacts/${art.id}`; const url = `https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip`;
if(art.name.includes('Debug')) { if (art.name.includes('Debug')) {
hidden_debug_artifacts += `\n* [${art.name}](${url})`; hidden_debug_artifacts += `\n* [${art.name}](${url})`;
} else { } else {
body += `\n* [${art.name}](${url})`; body += `\n* [${art.name}](${url})`;

View File

@@ -3,16 +3,6 @@ name: Release job
on: on:
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
push:
branches: [ release ]
paths-ignore:
- '.github/**'
- 'docs/**'
- 'assets/**'
- '*.yml'
- '*.json'
- '*.config'
- '*.md'
concurrency: release concurrency: release
@@ -122,6 +112,15 @@ jobs:
popd popd
shell: bash shell: bash
- name: Packing Linux builds
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish
chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
shell: bash
- name: Build AppImage (Linux) - name: Build AppImage (Linux)
if: matrix.platform.os == 'ubuntu-latest' if: matrix.platform.os == 'ubuntu-latest'
run: | run: |
@@ -159,15 +158,6 @@ jobs:
popd popd
shell: bash shell: bash
- name: Packing Linux builds
if: matrix.platform.os == 'ubuntu-latest'
run: |
pushd publish
chmod +x Ryujinx.sh Ryujinx
tar -czvf ../release_output/ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd
shell: bash
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
with: with:
@@ -193,7 +183,7 @@ jobs:
macos_release: macos_release:
name: Release MacOS universal name: Release MacOS universal
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -201,11 +191,11 @@ jobs:
with: with:
global-json-file: global.json global-json-file: global.json
- name: Setup LLVM 15 - name: Setup LLVM 17
run: | run: |
wget https://apt.llvm.org/llvm.sh wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh chmod +x llvm.sh
sudo ./llvm.sh 15 sudo ./llvm.sh 17
- name: Install rcodesign - name: Install rcodesign
run: | run: |

View File

@@ -3,13 +3,13 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="Avalonia" Version="11.0.10" /> <PackageVersion Include="Avalonia" Version="11.0.13" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.10" /> <PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.13" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.10" /> <PackageVersion Include="Avalonia.Desktop" Version="11.0.13" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.10" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.0.13" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" /> <PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.13" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg" Version="11.0.0.19" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.19" />
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" /> <PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" /> <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
@@ -17,7 +17,8 @@
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/> <PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/> <PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="2.2.0" /> <PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
<PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" /> <PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="9.0.4" /> <PackageVersion Include="DynamicData" Version="9.0.4" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" /> <PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
@@ -25,7 +26,7 @@
<PackageVersion Include="LibHac" Version="0.19.0" /> <PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.1.2" /> <PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.3.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
@@ -41,16 +42,17 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.0" /> <PackageVersion Include="Gommon" Version="2.7.0.2" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" /> <PackageVersion Include="SharpMetal" Version="1.0.0-preview21" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" /> <PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
<PackageVersion Include="SkiaSharp" Version="2.88.7" /> <PackageVersion Include="SkiaSharp" Version="2.88.9" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SPB" Version="0.0.4-build32" /> <PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="System.IO.Hashing" Version="9.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
<PackageVersion Include="System.Management" Version="9.0.0" /> <PackageVersion Include="System.Management" Version="9.0.0" />

View File

@@ -6,7 +6,7 @@ cd "$ROOTDIR"
BUILDDIR=${BUILDDIR:-publish} BUILDDIR=${BUILDDIR:-publish}
OUTDIR=${OUTDIR:-publish_appimage} OUTDIR=${OUTDIR:-publish_appimage}
UFLAG=${UFLAG:-"gh-releases-zsync|GreemDev|ryujinx|latest|*-x64.AppImage.zsync"} UFLAG=${UFLAG:-"gh-releases-zsync|Ryubing|ryujinx|latest|*-x64.AppImage.zsync"}
rm -rf AppDir rm -rf AppDir
mkdir -p AppDir/usr/bin mkdir -p AppDir/usr/bin

View File

@@ -19,7 +19,7 @@ if platform.system() == "Darwin":
else: else:
OTOOL = shutil.which("llvm-otool") OTOOL = shutil.which("llvm-otool")
if OTOOL is None: if OTOOL is None:
for llvm_ver in [15, 14, 13]: for llvm_ver in [17, 16, 15, 14, 13]:
otool_path = shutil.which(f"llvm-otool-{llvm_ver}") otool_path = shutil.which(f"llvm-otool-{llvm_ver}")
if otool_path is not None: if otool_path is not None:
OTOOL = otool_path OTOOL = otool_path

View File

@@ -26,7 +26,7 @@ else:
LIPO = shutil.which("llvm-lipo") LIPO = shutil.which("llvm-lipo")
if LIPO is None: if LIPO is None:
for llvm_ver in [15, 14, 13]: for llvm_ver in [17, 16, 15, 14, 13]:
lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}") lipo_path = shutil.which(f"llvm-lipo-{llvm_ver}")
if lipo_path is not None: if lipo_path is not None:
LIPO = lipo_path LIPO = lipo_path

View File

@@ -67,11 +67,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_
if ! [ -x "$(command -v lipo)" ]; if ! [ -x "$(command -v lipo)" ];
then then
if ! [ -x "$(command -v llvm-lipo-14)" ]; if ! [ -x "$(command -v llvm-lipo-17)" ];
then then
LIPO=llvm-lipo LIPO=llvm-lipo
else else
LIPO=llvm-lipo-14 LIPO=llvm-lipo-17
fi fi
else else
LIPO=lipo LIPO=lipo

View File

@@ -62,11 +62,11 @@ python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTP
if ! [ -x "$(command -v lipo)" ]; if ! [ -x "$(command -v lipo)" ];
then then
if ! [ -x "$(command -v llvm-lipo-14)" ]; if ! [ -x "$(command -v llvm-lipo-17)" ];
then then
LIPO=llvm-lipo LIPO=llvm-lipo
else else
LIPO=llvm-lipo-14 LIPO=llvm-lipo-17
fi fi
else else
LIPO=lipo LIPO=lipo

View File

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

3425
docs/compatibility.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -406,7 +406,7 @@ namespace ARMeilleure.Instructions
{ {
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2); Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
return EmitUnaryMathCall(context, nameof(Math.Abs), res); return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
}); });
} }
} }
@@ -451,7 +451,7 @@ namespace ARMeilleure.Instructions
{ {
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2); Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
return EmitUnaryMathCall(context, nameof(Math.Abs), res); return EmitUnaryMathCall(context, nameof(MathHelper.Abs), res);
}); });
} }
} }
@@ -483,7 +483,7 @@ namespace ARMeilleure.Instructions
{ {
EmitScalarUnaryOpF(context, (op1) => EmitScalarUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Abs), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
}); });
} }
} }
@@ -522,7 +522,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpF(context, (op1) => EmitVectorUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Abs), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1);
}); });
} }
} }
@@ -2246,7 +2246,7 @@ namespace ARMeilleure.Instructions
{ {
EmitScalarUnaryOpF(context, (op1) => EmitScalarUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Floor), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
}); });
} }
} }
@@ -2265,7 +2265,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpF(context, (op1) => EmitVectorUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Floor), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1);
}); });
} }
} }
@@ -2322,7 +2322,7 @@ namespace ARMeilleure.Instructions
{ {
EmitScalarUnaryOpF(context, (op1) => EmitScalarUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
}); });
} }
} }
@@ -2341,7 +2341,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpF(context, (op1) => EmitVectorUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1);
}); });
} }
} }
@@ -2390,7 +2390,7 @@ namespace ARMeilleure.Instructions
{ {
EmitScalarUnaryOpF(context, (op1) => EmitScalarUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
}); });
} }
} }
@@ -2409,7 +2409,7 @@ namespace ARMeilleure.Instructions
{ {
EmitVectorUnaryOpF(context, (op1) => EmitVectorUnaryOpF(context, (op1) =>
{ {
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1); return EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1);
}); });
} }
} }

View File

@@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1)); EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
} }
} }
@@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1)); EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Abs), op1));
} }
} }
else else

View File

@@ -726,8 +726,8 @@ namespace ARMeilleure.Instructions
if (absolute) if (absolute)
{ {
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne); ne = EmitUnaryMathCall(context, nameof(MathHelper.Abs), ne);
me = EmitUnaryMathCall(context, nameof(Math.Abs), me); me = EmitUnaryMathCall(context, nameof(MathHelper.Abs), me);
} }
Operand e = EmitSoftFloatCall(context, name, ne, me); Operand e = EmitSoftFloatCall(context, name, ne, me);

View File

@@ -333,7 +333,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1)); EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
} }
} }
@@ -349,7 +349,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1), signed: true, scalar: false); EmitFcvt(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1), signed: true, scalar: false);
} }
} }
@@ -365,7 +365,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1)); EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), op1));
} }
} }
@@ -538,7 +538,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1)); EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
} }
} }
@@ -554,7 +554,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1)); EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op1));
} }
} }

View File

@@ -357,10 +357,10 @@ namespace ARMeilleure.Instructions
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break; break;
case 0b10: // Towards positive infinity case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert); toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
break; break;
case 0b11: // Towards negative infinity case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert); toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
break; break;
} }
@@ -494,10 +494,10 @@ namespace ARMeilleure.Instructions
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert); toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
break; break;
case 0b10: // Towards positive infinity case 0b10: // Towards positive infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert); toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), toConvert);
break; break;
case 0b11: // Towards negative infinity case 0b11: // Towards negative infinity
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert); toConvert = EmitUnaryMathCall(context, nameof(MathHelper.Floor), toConvert);
break; break;
} }
@@ -534,7 +534,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m)); EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Floor), m));
} }
} }
@@ -574,7 +574,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m)); EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), m));
} }
} }
@@ -613,7 +613,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1)); EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op1));
} }
} }

View File

@@ -460,8 +460,8 @@ namespace ARMeilleure.Instructions
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
MethodInfo info = (op.Size & 1) == 0 MethodInfo info = (op.Size & 1) == 0
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) }) ? typeof(MathHelperF).GetMethod(name, new Type[] { typeof(float) })
: typeof(Math).GetMethod(name, new Type[] { typeof(double) }); : typeof(MathHelper).GetMethod(name, new Type[] { typeof(double) });
return context.Call(info, n); return context.Call(info, n);
} }
@@ -470,11 +470,11 @@ namespace ARMeilleure.Instructions
{ {
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
string name = nameof(Math.Round); string name = nameof(MathHelper.Round);
MethodInfo info = (op.Size & 1) == 0 MethodInfo info = (op.Size & 1) == 0
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) }) ? typeof(MathHelperF).GetMethod(name, new Type[] { typeof(float), typeof(int) })
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) }); : typeof(MathHelper).GetMethod(name, new Type[] { typeof(double), typeof(int) });
return context.Call(info, n, Const((int)roundMode)); return context.Call(info, n, Const((int)roundMode));
} }
@@ -510,16 +510,16 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lbl1); context.MarkLabel(lbl1);
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual); context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op)); context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Ceiling), op));
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lbl2); context.MarkLabel(lbl2);
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual); context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op)); context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Floor), op));
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lbl3); context.MarkLabel(lbl3);
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op)); context.Copy(res, EmitUnaryMathCall(context, nameof(MathHelper.Truncate), op));
context.Branch(lblEnd); context.Branch(lblEnd);
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);

View File

@@ -0,0 +1,71 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class MathHelper
{
[UnmanagedCallersOnly]
public static double Abs(double value)
{
return Math.Abs(value);
}
[UnmanagedCallersOnly]
public static double Ceiling(double value)
{
return Math.Ceiling(value);
}
[UnmanagedCallersOnly]
public static double Floor(double value)
{
return Math.Floor(value);
}
[UnmanagedCallersOnly]
public static double Round(double value, int mode)
{
return Math.Round(value, (MidpointRounding)mode);
}
[UnmanagedCallersOnly]
public static double Truncate(double value)
{
return Math.Truncate(value);
}
}
static class MathHelperF
{
[UnmanagedCallersOnly]
public static float Abs(float value)
{
return MathF.Abs(value);
}
[UnmanagedCallersOnly]
public static float Ceiling(float value)
{
return MathF.Ceiling(value);
}
[UnmanagedCallersOnly]
public static float Floor(float value)
{
return MathF.Floor(value);
}
[UnmanagedCallersOnly]
public static float Round(float value, int mode)
{
return MathF.Round(value, (MidpointRounding)mode);
}
[UnmanagedCallersOnly]
public static float Truncate(float value)
{
return MathF.Truncate(value);
}
}
}

View File

@@ -2,6 +2,7 @@ using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@@ -34,6 +35,7 @@ namespace ARMeilleure.Instructions
Context = null; Context = null;
} }
[UnmanagedCallersOnly]
public static void Break(ulong address, int imm) public static void Break(ulong address, int imm)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -43,6 +45,7 @@ namespace ARMeilleure.Instructions
Statistics.ResumeTimer(); Statistics.ResumeTimer();
} }
[UnmanagedCallersOnly]
public static void SupervisorCall(ulong address, int imm) public static void SupervisorCall(ulong address, int imm)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -52,6 +55,7 @@ namespace ARMeilleure.Instructions
Statistics.ResumeTimer(); Statistics.ResumeTimer();
} }
[UnmanagedCallersOnly]
public static void Undefined(ulong address, int opCode) public static void Undefined(ulong address, int opCode)
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -62,26 +66,31 @@ namespace ARMeilleure.Instructions
} }
#region "System registers" #region "System registers"
[UnmanagedCallersOnly]
public static ulong GetCtrEl0() public static ulong GetCtrEl0()
{ {
return GetContext().CtrEl0; return GetContext().CtrEl0;
} }
[UnmanagedCallersOnly]
public static ulong GetDczidEl0() public static ulong GetDczidEl0()
{ {
return GetContext().DczidEl0; return GetContext().DczidEl0;
} }
[UnmanagedCallersOnly]
public static ulong GetCntfrqEl0() public static ulong GetCntfrqEl0()
{ {
return GetContext().CntfrqEl0; return GetContext().CntfrqEl0;
} }
[UnmanagedCallersOnly]
public static ulong GetCntpctEl0() public static ulong GetCntpctEl0()
{ {
return GetContext().CntpctEl0; return GetContext().CntpctEl0;
} }
[UnmanagedCallersOnly]
public static ulong GetCntvctEl0() public static ulong GetCntvctEl0()
{ {
return GetContext().CntvctEl0; return GetContext().CntvctEl0;
@@ -89,26 +98,31 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Read" #region "Read"
[UnmanagedCallersOnly]
public static byte ReadByte(ulong address) public static byte ReadByte(ulong address)
{ {
return GetMemoryManager().ReadGuest<byte>(address); return GetMemoryManager().ReadGuest<byte>(address);
} }
[UnmanagedCallersOnly]
public static ushort ReadUInt16(ulong address) public static ushort ReadUInt16(ulong address)
{ {
return GetMemoryManager().ReadGuest<ushort>(address); return GetMemoryManager().ReadGuest<ushort>(address);
} }
[UnmanagedCallersOnly]
public static uint ReadUInt32(ulong address) public static uint ReadUInt32(ulong address)
{ {
return GetMemoryManager().ReadGuest<uint>(address); return GetMemoryManager().ReadGuest<uint>(address);
} }
[UnmanagedCallersOnly]
public static ulong ReadUInt64(ulong address) public static ulong ReadUInt64(ulong address)
{ {
return GetMemoryManager().ReadGuest<ulong>(address); return GetMemoryManager().ReadGuest<ulong>(address);
} }
[UnmanagedCallersOnly]
public static V128 ReadVector128(ulong address) public static V128 ReadVector128(ulong address)
{ {
return GetMemoryManager().ReadGuest<V128>(address); return GetMemoryManager().ReadGuest<V128>(address);
@@ -116,47 +130,56 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Write" #region "Write"
[UnmanagedCallersOnly]
public static void WriteByte(ulong address, byte value) public static void WriteByte(ulong address, byte value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
[UnmanagedCallersOnly]
public static void WriteUInt16(ulong address, ushort value) public static void WriteUInt16(ulong address, ushort value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
[UnmanagedCallersOnly]
public static void WriteUInt32(ulong address, uint value) public static void WriteUInt32(ulong address, uint value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
[UnmanagedCallersOnly]
public static void WriteUInt64(ulong address, ulong value) public static void WriteUInt64(ulong address, ulong value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
[UnmanagedCallersOnly]
public static void WriteVector128(ulong address, V128 value) public static void WriteVector128(ulong address, V128 value)
{ {
GetMemoryManager().WriteGuest(address, value); GetMemoryManager().WriteGuest(address, value);
} }
#endregion #endregion
[UnmanagedCallersOnly]
public static void EnqueueForRejit(ulong address) public static void EnqueueForRejit(ulong address)
{ {
Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode); Context.Translator.EnqueueForRejit(address, GetContext().ExecutionMode);
} }
public static void SignalMemoryTracking(ulong address, ulong size, bool write) [UnmanagedCallersOnly]
public static void SignalMemoryTracking(ulong address, ulong size, byte write)
{ {
GetMemoryManager().SignalMemoryTracking(address, size, write); GetMemoryManager().SignalMemoryTracking(address, size, write == 1);
} }
[UnmanagedCallersOnly]
public static void ThrowInvalidMemoryAccess(ulong address) public static void ThrowInvalidMemoryAccess(ulong address)
{ {
throw new InvalidAccessException(address); throw new InvalidAccessException(address);
} }
[UnmanagedCallersOnly]
public static ulong GetFunctionAddress(ulong address) public static ulong GetFunctionAddress(ulong address)
{ {
TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode); TranslatedFunction function = Context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
@@ -164,12 +187,14 @@ namespace ARMeilleure.Instructions
return (ulong)function.FuncPointer.ToInt64(); return (ulong)function.FuncPointer.ToInt64();
} }
[UnmanagedCallersOnly]
public static void InvalidateCacheLine(ulong address) public static void InvalidateCacheLine(ulong address)
{ {
Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes); Context.Translator.InvalidateJitCacheRegion(address, InstEmit.DczSizeInBytes);
} }
public static bool CheckSynchronization() [UnmanagedCallersOnly]
public static byte CheckSynchronization()
{ {
Statistics.PauseTimer(); Statistics.PauseTimer();
@@ -179,7 +204,7 @@ namespace ARMeilleure.Instructions
Statistics.ResumeTimer(); Statistics.ResumeTimer();
return context.Running; return (byte)(context.Running ? 1 : 0);
} }
public static ExecutionContext GetContext() public static ExecutionContext GetContext()

View File

@@ -1,11 +1,13 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
static class SoftFallback static class SoftFallback
{ {
#region "ShrImm64" #region "ShrImm64"
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift) public static long SignedShrImm64(long value, long roundConst, int shift)
{ {
if (roundConst == 0L) if (roundConst == 0L)
@@ -48,6 +50,7 @@ namespace ARMeilleure.Instructions
} }
} }
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift) public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{ {
if (roundConst == 0L) if (roundConst == 0L)
@@ -92,6 +95,7 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Saturation" #region "Saturation"
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value) public static int SatF32ToS32(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -103,6 +107,7 @@ namespace ARMeilleure.Instructions
value <= int.MinValue ? int.MinValue : (int)value; value <= int.MinValue ? int.MinValue : (int)value;
} }
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value) public static long SatF32ToS64(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -114,6 +119,7 @@ namespace ARMeilleure.Instructions
value <= long.MinValue ? long.MinValue : (long)value; value <= long.MinValue ? long.MinValue : (long)value;
} }
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value) public static uint SatF32ToU32(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -125,6 +131,7 @@ namespace ARMeilleure.Instructions
value <= uint.MinValue ? uint.MinValue : (uint)value; value <= uint.MinValue ? uint.MinValue : (uint)value;
} }
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value) public static ulong SatF32ToU64(float value)
{ {
if (float.IsNaN(value)) if (float.IsNaN(value))
@@ -136,6 +143,7 @@ namespace ARMeilleure.Instructions
value <= ulong.MinValue ? ulong.MinValue : (ulong)value; value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
} }
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value) public static int SatF64ToS32(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -147,6 +155,7 @@ namespace ARMeilleure.Instructions
value <= int.MinValue ? int.MinValue : (int)value; value <= int.MinValue ? int.MinValue : (int)value;
} }
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value) public static long SatF64ToS64(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -158,6 +167,7 @@ namespace ARMeilleure.Instructions
value <= long.MinValue ? long.MinValue : (long)value; value <= long.MinValue ? long.MinValue : (long)value;
} }
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value) public static uint SatF64ToU32(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -169,6 +179,7 @@ namespace ARMeilleure.Instructions
value <= uint.MinValue ? uint.MinValue : (uint)value; value <= uint.MinValue ? uint.MinValue : (uint)value;
} }
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value) public static ulong SatF64ToU64(double value)
{ {
if (double.IsNaN(value)) if (double.IsNaN(value))
@@ -182,6 +193,7 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Count" #region "Count"
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {
value ^= value >> 1; value ^= value >> 1;
@@ -201,6 +213,7 @@ namespace ARMeilleure.Instructions
private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.). public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{ {
if (value == 0ul) if (value == 0ul)
@@ -224,41 +237,49 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Table" #region "Table"
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0) public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{ {
return TblOrTbx(default, vector, bytes, tb0); return TblOrTbx(default, vector, bytes, tb0);
} }
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1) public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1); return TblOrTbx(default, vector, bytes, tb0, tb1);
} }
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2); return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
} }
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{ {
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3); return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
} }
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0) public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{ {
return TblOrTbx(dest, vector, bytes, tb0); return TblOrTbx(dest, vector, bytes, tb0);
} }
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1) public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1); return TblOrTbx(dest, vector, bytes, tb0, tb1);
} }
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2) public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2); return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
} }
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3) public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{ {
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3); return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
@@ -300,14 +321,22 @@ namespace ARMeilleure.Instructions
private const uint Crc32RevPoly = 0xedb88320; private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78; private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value); public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value); public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value); public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value); public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value); public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value); public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value); public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value); public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val) private static uint Crc32h(uint crc, uint poly, ushort val)
@@ -358,21 +387,25 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Aes" #region "Aes"
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey) public static V128 Decrypt(V128 value, V128 roundKey)
{ {
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey)); return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
} }
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey) public static V128 Encrypt(V128 value, V128 roundKey)
{ {
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey)); return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
} }
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value) public static V128 InverseMixColumns(V128 value)
{ {
return CryptoHelper.AesInvMixColumns(value); return CryptoHelper.AesInvMixColumns(value);
} }
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value) public static V128 MixColumns(V128 value)
{ {
return CryptoHelper.AesMixColumns(value); return CryptoHelper.AesMixColumns(value);
@@ -380,6 +413,7 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Sha1" #region "Sha1"
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -400,11 +434,13 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e) public static uint FixedRotate(uint hash_e)
{ {
return hash_e.Rol(30); return hash_e.Rol(30);
} }
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -425,6 +461,7 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk) public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{ {
for (int e = 0; e <= 3; e++) for (int e = 0; e <= 3; e++)
@@ -445,6 +482,7 @@ namespace ARMeilleure.Instructions
return hash_abcd; return hash_abcd;
} }
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11) public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{ {
ulong t2 = w4_7.Extract<ulong>(0); ulong t2 = w4_7.Extract<ulong>(0);
@@ -455,6 +493,7 @@ namespace ARMeilleure.Instructions
return result ^ (w0_3 ^ w8_11); return result ^ (w0_3 ^ w8_11);
} }
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15) public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{ {
V128 t = tw0_3 ^ (w12_15 >> 32); V128 t = tw0_3 ^ (w12_15 >> 32);
@@ -499,16 +538,19 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Sha256" #region "Sha256"
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk) public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{ {
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true); return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
} }
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk) public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{ {
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false); return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
} }
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7) public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{ {
V128 result = new(); V128 result = new();
@@ -527,6 +569,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15) public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{ {
V128 result = new(); V128 result = new();
@@ -628,6 +671,7 @@ namespace ARMeilleure.Instructions
} }
#endregion #endregion
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2) public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{ {
V128 result = V128.Zero; V128 result = V128.Zero;

View File

@@ -1,6 +1,7 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
@@ -312,6 +313,7 @@ namespace ARMeilleure.Instructions
static class SoftFloat16_32 static class SoftFloat16_32
{ {
[UnmanagedCallersOnly]
public static float FPConvert(ushort valueBits) public static float FPConvert(ushort valueBits)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -487,6 +489,7 @@ namespace ARMeilleure.Instructions
static class SoftFloat16_64 static class SoftFloat16_64
{ {
[UnmanagedCallersOnly]
public static double FPConvert(ushort valueBits) public static double FPConvert(ushort valueBits)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -662,6 +665,7 @@ namespace ARMeilleure.Instructions
static class SoftFloat32_16 static class SoftFloat32_16
{ {
[UnmanagedCallersOnly]
public static ushort FPConvert(float value) public static ushort FPConvert(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -781,12 +785,19 @@ namespace ARMeilleure.Instructions
static class SoftFloat32 static class SoftFloat32
{ {
[UnmanagedCallersOnly]
public static float FPAdd(float value1, float value2) public static float FPAdd(float value1, float value2)
{ {
return FPAddFpscr(value1, value2, false); return FPAddFpscrImpl(value1, value2, false);
} }
public static float FPAddFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPAddFpscr(float value1, float value2, byte standardFpscr)
{
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPAddFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -837,7 +848,8 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
public static int FPCompare(float value1, float value2, bool signalNaNs) [UnmanagedCallersOnly]
public static int FPCompare(float value1, float value2, byte signalNaNs)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = context.Fpcr; FPCR fpcr = context.Fpcr;
@@ -851,7 +863,7 @@ namespace ARMeilleure.Instructions
{ {
result = 0b0011; result = 0b0011;
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs) if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
{ {
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr); SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
} }
@@ -875,12 +887,13 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPCompareEQ(float value1, float value2) public static float FPCompareEQ(float value1, float value2)
{ {
return FPCompareEQFpscr(value1, value2, false); return FPCompareEQFpscrImpl(value1, value2, false);
} }
public static float FPCompareEQFpscr(float value1, float value2, bool standardFpscr) private static float FPCompareEQFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -907,12 +920,25 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
public static float FPCompareGE(float value1, float value2) [UnmanagedCallersOnly]
public static float FPCompareEQFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGEFpscr(value1, value2, false); return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
} }
public static float FPCompareGEFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPCompareGE(float value1, float value2)
{
return FPCompareGEFpscrImpl(value1, value2, false);
}
[UnmanagedCallersOnly]
public static float FPCompareGEFpscr(float value1, float value2, byte standardFpscr)
{
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPCompareGEFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -936,12 +962,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPCompareGT(float value1, float value2) public static float FPCompareGT(float value1, float value2)
{ {
return FPCompareGTFpscr(value1, value2, false); return FPCompareGTFpscrImpl(value1, value2, false);
} }
public static float FPCompareGTFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPCompareGTFpscr(float value1, float value2, byte standardFpscr)
{
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPCompareGTFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -965,26 +998,31 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPCompareLE(float value1, float value2) public static float FPCompareLE(float value1, float value2)
{ {
return FPCompareGE(value2, value1); return FPCompareGEFpscrImpl(value2, value1, false);
} }
[UnmanagedCallersOnly]
public static float FPCompareLT(float value1, float value2) public static float FPCompareLT(float value1, float value2)
{ {
return FPCompareGT(value2, value1); return FPCompareGTFpscrImpl(value2, value1, false);
} }
public static float FPCompareLEFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPCompareLEFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGEFpscr(value2, value1, standardFpscr); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
public static float FPCompareLTFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPCompareLTFpscr(float value1, float value2, byte standardFpscr)
{ {
return FPCompareGTFpscr(value2, value1, standardFpscr); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
[UnmanagedCallersOnly]
public static float FPDiv(float value1, float value2) public static float FPDiv(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1037,12 +1075,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPMax(float value1, float value2) public static float FPMax(float value1, float value2)
{ {
return FPMaxFpscr(value1, value2, false); return FPMaxFpscrImpl(value1, value2, false);
} }
public static float FPMaxFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMaxFpscr(float value1, float value2, byte standardFpscr)
{
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPMaxFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1103,12 +1148,13 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPMaxNum(float value1, float value2) public static float FPMaxNum(float value1, float value2)
{ {
return FPMaxNumFpscr(value1, value2, false); return FPMaxNumFpscrImpl(value1, value2, false);
} }
public static float FPMaxNumFpscr(float value1, float value2, bool standardFpscr) private static float FPMaxNumFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1125,15 +1171,28 @@ namespace ARMeilleure.Instructions
value2 = FPInfinity(true); value2 = FPInfinity(true);
} }
return FPMaxFpscr(value1, value2, standardFpscr); return FPMaxFpscrImpl(value1, value2, standardFpscr);
} }
[UnmanagedCallersOnly]
public static float FPMaxNumFpscr(float value1, float value2, byte standardFpscr)
{
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
}
[UnmanagedCallersOnly]
public static float FPMin(float value1, float value2) public static float FPMin(float value1, float value2)
{ {
return FPMinFpscr(value1, value2, false); return FPMinFpscrImpl(value1, value2, false);
} }
public static float FPMinFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMinFpscr(float value1, float value2, byte standardFpscr)
{
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPMinFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1194,12 +1253,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPMinNum(float value1, float value2) public static float FPMinNum(float value1, float value2)
{ {
return FPMinNumFpscr(value1, value2, false); return FPMinNumFpscrImpl(value1, value2, false);
} }
public static float FPMinNumFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMinNumFpscr(float value1, float value2, byte standardFpscr)
{
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPMinNumFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1216,15 +1282,22 @@ namespace ARMeilleure.Instructions
value2 = FPInfinity(false); value2 = FPInfinity(false);
} }
return FPMinFpscr(value1, value2, standardFpscr); return FPMinFpscrImpl(value1, value2, standardFpscr);
} }
[UnmanagedCallersOnly]
public static float FPMul(float value1, float value2) public static float FPMul(float value1, float value2)
{ {
return FPMulFpscr(value1, value2, false); return FPMulFpscrImpl(value1, value2, false);
} }
public static float FPMulFpscr(float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMulFpscr(float value1, float value2, byte standardFpscr)
{
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
}
private static float FPMulFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1271,12 +1344,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPMulAdd(float valueA, float value1, float value2) public static float FPMulAdd(float valueA, float value1, float value2)
{ {
return FPMulAddFpscr(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
public static float FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMulAddFpscr(float valueA, float value1, float value2, byte standardFpscr)
{
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
}
private static float FPMulAddFpscrImpl(float valueA, float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1342,20 +1422,23 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPMulSub(float valueA, float value1, float value2) public static float FPMulSub(float valueA, float value1, float value2)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
public static float FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPMulSubFpscr(float valueA, float value1, float value2, byte standardFpscr)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAddFpscr(valueA, value1, value2, standardFpscr); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
} }
[UnmanagedCallersOnly]
public static float FPMulX(float value1, float value2) public static float FPMulX(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1401,27 +1484,36 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPNegMulAdd(float valueA, float value1, float value2) public static float FPNegMulAdd(float valueA, float value1, float value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
[UnmanagedCallersOnly]
public static float FPNegMulSub(float valueA, float value1, float value2) public static float FPNegMulSub(float valueA, float value1, float value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
[UnmanagedCallersOnly]
public static float FPRecipEstimate(float value) public static float FPRecipEstimate(float value)
{ {
return FPRecipEstimateFpscr(value, false); return FPRecipEstimateFpscrImpl(value, false);
} }
public static float FPRecipEstimateFpscr(float value, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPRecipEstimateFpscr(float value, byte standardFpscr)
{
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
}
private static float FPRecipEstimateFpscrImpl(float value, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1508,6 +1600,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRecipStep(float value1, float value2) public static float FPRecipStep(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1533,15 +1626,16 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
product = FPMulFpscr(value1, value2, true); product = FPMulFpscrImpl(value1, value2, true);
} }
result = FPSubFpscr(FPTwo(false), product, true); result = FPSubFpscrImpl(FPTwo(false), product, true);
} }
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRecipStepFused(float value1, float value2) public static float FPRecipStepFused(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1585,6 +1679,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRecpX(float value) public static float FPRecpX(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1610,12 +1705,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRSqrtEstimate(float value) public static float FPRSqrtEstimate(float value)
{ {
return FPRSqrtEstimateFpscr(value, false); return FPRSqrtEstimateFpscrImpl(value, false);
} }
public static float FPRSqrtEstimateFpscr(float value, bool standardFpscr) [UnmanagedCallersOnly]
public static float FPRSqrtEstimateFpscr(float value, byte standardFpscr)
{
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
}
private static float FPRSqrtEstimateFpscrImpl(float value, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -1729,6 +1831,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRSqrtStep(float value1, float value2) public static float FPRSqrtStep(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1754,7 +1857,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
product = FPMulFpscr(value1, value2, true); product = FPMulFpscrImpl(value1, value2, true);
} }
result = FPHalvedSub(FPThree(false), product, context, fpcr); result = FPHalvedSub(FPThree(false), product, context, fpcr);
@@ -1763,6 +1866,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPRSqrtStepFused(float value1, float value2) public static float FPRSqrtStepFused(float value1, float value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1806,6 +1910,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPSqrt(float value) public static float FPSqrt(float value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -1848,12 +1953,13 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static float FPSub(float value1, float value2) public static float FPSub(float value1, float value2)
{ {
return FPSubFpscr(value1, value2, false); return FPSubFpscrImpl(value1, value2, false);
} }
public static float FPSubFpscr(float value1, float value2, bool standardFpscr) private static float FPSubFpscrImpl(float value1, float value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2094,6 +2200,7 @@ namespace ARMeilleure.Instructions
static class SoftFloat64_16 static class SoftFloat64_16
{ {
[UnmanagedCallersOnly]
public static ushort FPConvert(double value) public static ushort FPConvert(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2213,12 +2320,19 @@ namespace ARMeilleure.Instructions
static class SoftFloat64 static class SoftFloat64
{ {
[UnmanagedCallersOnly]
public static double FPAdd(double value1, double value2) public static double FPAdd(double value1, double value2)
{ {
return FPAddFpscr(value1, value2, false); return FPAddFpscrImpl(value1, value2, false);
} }
public static double FPAddFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPAddFpscr(double value1, double value2, byte standardFpscr)
{
return FPAddFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPAddFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2269,7 +2383,8 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
public static int FPCompare(double value1, double value2, bool signalNaNs) [UnmanagedCallersOnly]
public static int FPCompare(double value1, double value2, byte signalNaNs)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = context.Fpcr; FPCR fpcr = context.Fpcr;
@@ -2283,7 +2398,7 @@ namespace ARMeilleure.Instructions
{ {
result = 0b0011; result = 0b0011;
if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs) if (type1 == FPType.SNaN || type2 == FPType.SNaN || signalNaNs == 1)
{ {
SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr); SoftFloat.FPProcessException(FPException.InvalidOp, context, fpcr);
} }
@@ -2307,12 +2422,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPCompareEQ(double value1, double value2) public static double FPCompareEQ(double value1, double value2)
{ {
return FPCompareEQFpscr(value1, value2, false); return FPCompareEQFpscrImpl(value1, value2, false);
} }
public static double FPCompareEQFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPCompareEQFpscr(double value1, double value2, byte standardFpscr)
{
return FPCompareEQFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPCompareEQFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2339,12 +2461,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPCompareGE(double value1, double value2) public static double FPCompareGE(double value1, double value2)
{ {
return FPCompareGEFpscr(value1, value2, false); return FPCompareGEFpscrImpl(value1, value2, false);
} }
public static double FPCompareGEFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPCompareGEFpscr(double value1, double value2, byte standardFpscr)
{
return FPCompareGEFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPCompareGEFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2368,12 +2497,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPCompareGT(double value1, double value2) public static double FPCompareGT(double value1, double value2)
{ {
return FPCompareGTFpscr(value1, value2, false); return FPCompareGTFpscrImpl(value1, value2, false);
} }
public static double FPCompareGTFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPCompareGTFpscr(double value1, double value2, byte standardFpscr)
{
return FPCompareGTFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPCompareGTFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2397,26 +2533,31 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPCompareLE(double value1, double value2) public static double FPCompareLE(double value1, double value2)
{ {
return FPCompareGE(value2, value1); return FPCompareGEFpscrImpl(value2, value1, false);
} }
[UnmanagedCallersOnly]
public static double FPCompareLT(double value1, double value2) public static double FPCompareLT(double value1, double value2)
{ {
return FPCompareGT(value2, value1); return FPCompareGTFpscrImpl(value2, value1, false);
} }
public static double FPCompareLEFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPCompareLEFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGEFpscr(value2, value1, standardFpscr); return FPCompareGEFpscrImpl(value2, value1, standardFpscr == 1);
} }
public static double FPCompareLTFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPCompareLTFpscr(double value1, double value2, byte standardFpscr)
{ {
return FPCompareGTFpscr(value2, value1, standardFpscr); return FPCompareGTFpscrImpl(value2, value1, standardFpscr == 1);
} }
[UnmanagedCallersOnly]
public static double FPDiv(double value1, double value2) public static double FPDiv(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2469,12 +2610,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPMax(double value1, double value2) public static double FPMax(double value1, double value2)
{ {
return FPMaxFpscr(value1, value2, false); return FPMaxFpscrImpl(value1, value2, false);
} }
public static double FPMaxFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMaxFpscr(double value1, double value2, byte standardFpscr)
{
return FPMaxFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPMaxFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2535,12 +2683,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPMaxNum(double value1, double value2) public static double FPMaxNum(double value1, double value2)
{ {
return FPMaxNumFpscr(value1, value2, false); return FPMaxNumFpscrImpl(value1, value2, false);
} }
public static double FPMaxNumFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMaxNumFpscr(double value1, double value2, byte standardFpscr)
{
return FPMaxNumFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPMaxNumFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2557,15 +2712,22 @@ namespace ARMeilleure.Instructions
value2 = FPInfinity(true); value2 = FPInfinity(true);
} }
return FPMaxFpscr(value1, value2, standardFpscr); return FPMaxFpscrImpl(value1, value2, standardFpscr);
} }
[UnmanagedCallersOnly]
public static double FPMin(double value1, double value2) public static double FPMin(double value1, double value2)
{ {
return FPMinFpscr(value1, value2, false); return FPMinFpscrImpl(value1, value2, false);
} }
public static double FPMinFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMinFpscr(double value1, double value2, byte standardFpscr)
{
return FPMinFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPMinFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2626,12 +2788,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPMinNum(double value1, double value2) public static double FPMinNum(double value1, double value2)
{ {
return FPMinNumFpscr(value1, value2, false); return FPMinNumFpscrImpl(value1, value2, false);
} }
public static double FPMinNumFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMinNumFpscr(double value1, double value2, byte standardFpscr)
{
return FPMinNumFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPMinNumFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2648,15 +2817,22 @@ namespace ARMeilleure.Instructions
value2 = FPInfinity(false); value2 = FPInfinity(false);
} }
return FPMinFpscr(value1, value2, standardFpscr); return FPMinFpscrImpl(value1, value2, standardFpscr);
} }
[UnmanagedCallersOnly]
public static double FPMul(double value1, double value2) public static double FPMul(double value1, double value2)
{ {
return FPMulFpscr(value1, value2, false); return FPMulFpscrImpl(value1, value2, false);
} }
public static double FPMulFpscr(double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMulFpscr(double value1, double value2, byte standardFpscr)
{
return FPMulFpscrImpl(value1, value2, standardFpscr == 1);
}
private static double FPMulFpscrImpl(double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2703,12 +2879,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPMulAdd(double valueA, double value1, double value2) public static double FPMulAdd(double valueA, double value1, double value2)
{ {
return FPMulAddFpscr(valueA, value1, value2, false); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
public static double FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMulAddFpscr(double valueA, double value1, double value2, byte standardFpscr)
{
return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
}
private static double FPMulAddFpscrImpl(double valueA, double value1, double value2, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2774,20 +2957,23 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPMulSub(double valueA, double value1, double value2) public static double FPMulSub(double valueA, double value1, double value2)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
public static double FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPMulSubFpscr(double valueA, double value1, double value2, byte standardFpscr)
{ {
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAddFpscr(valueA, value1, value2, standardFpscr); return FPMulAddFpscrImpl(valueA, value1, value2, standardFpscr == 1);
} }
[UnmanagedCallersOnly]
public static double FPMulX(double value1, double value2) public static double FPMulX(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2833,27 +3019,36 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPNegMulAdd(double valueA, double value1, double value2) public static double FPNegMulAdd(double valueA, double value1, double value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
value1 = value1.FPNeg(); value1 = value1.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
[UnmanagedCallersOnly]
public static double FPNegMulSub(double valueA, double value1, double value2) public static double FPNegMulSub(double valueA, double value1, double value2)
{ {
valueA = valueA.FPNeg(); valueA = valueA.FPNeg();
return FPMulAdd(valueA, value1, value2); return FPMulAddFpscrImpl(valueA, value1, value2, false);
} }
[UnmanagedCallersOnly]
public static double FPRecipEstimate(double value) public static double FPRecipEstimate(double value)
{ {
return FPRecipEstimateFpscr(value, false); return FPRecipEstimateFpscrImpl(value, false);
} }
public static double FPRecipEstimateFpscr(double value, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPRecipEstimateFpscr(double value, byte standardFpscr)
{
return FPRecipEstimateFpscrImpl(value, standardFpscr == 1);
}
private static double FPRecipEstimateFpscrImpl(double value, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -2940,6 +3135,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRecipStep(double value1, double value2) public static double FPRecipStep(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -2965,7 +3161,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
product = FPMulFpscr(value1, value2, true); product = FPMulFpscrImpl(value1, value2, true);
} }
result = FPSubFpscr(FPTwo(false), product, true); result = FPSubFpscr(FPTwo(false), product, true);
@@ -2974,6 +3170,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRecipStepFused(double value1, double value2) public static double FPRecipStepFused(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3017,6 +3214,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRecpX(double value) public static double FPRecpX(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3042,12 +3240,19 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRSqrtEstimate(double value) public static double FPRSqrtEstimate(double value)
{ {
return FPRSqrtEstimateFpscr(value, false); return FPRSqrtEstimateFpscrImpl(value, false);
} }
public static double FPRSqrtEstimateFpscr(double value, bool standardFpscr) [UnmanagedCallersOnly]
public static double FPRSqrtEstimateFpscr(double value, byte standardFpscr)
{
return FPRSqrtEstimateFpscrImpl(value, standardFpscr == 1);
}
private static double FPRSqrtEstimateFpscrImpl(double value, bool standardFpscr)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr; FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
@@ -3161,6 +3366,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRSqrtStep(double value1, double value2) public static double FPRSqrtStep(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3186,7 +3392,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
product = FPMulFpscr(value1, value2, true); product = FPMulFpscrImpl(value1, value2, true);
} }
result = FPHalvedSub(FPThree(false), product, context, fpcr); result = FPHalvedSub(FPThree(false), product, context, fpcr);
@@ -3195,6 +3401,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPRSqrtStepFused(double value1, double value2) public static double FPRSqrtStepFused(double value1, double value2)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3238,6 +3445,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPSqrt(double value) public static double FPSqrt(double value)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@@ -3280,6 +3488,7 @@ namespace ARMeilleure.Instructions
return result; return result;
} }
[UnmanagedCallersOnly]
public static double FPSub(double value1, double value2) public static double FPSub(double value1, double value2)
{ {
return FPSubFpscr(value1, value2, false); return FPSubFpscr(value1, value2, false);

View File

@@ -4,15 +4,9 @@ namespace ARMeilleure.Translation
{ {
class DelegateInfo class DelegateInfo
{ {
#pragma warning disable IDE0052 // Remove unread private member public nint FuncPtr { get; private set; }
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected. public DelegateInfo(nint funcPtr)
#pragma warning restore IDE0052
public nint FuncPtr { get; }
public DelegateInfo(Delegate dlg, nint funcPtr)
{ {
_dlg = dlg;
FuncPtr = funcPtr; FuncPtr = funcPtr;
} }
} }

View File

@@ -1,9 +1,7 @@
using ARMeilleure.Instructions; using ARMeilleure.Instructions;
using ARMeilleure.State;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
@@ -35,20 +33,6 @@ namespace ARMeilleure.Translation
return _delegates.Values[index].FuncPtr; // O(1). return _delegates.Values[index].FuncPtr; // O(1).
} }
public static nint GetDelegateFuncPtr(MethodInfo info)
{
ArgumentNullException.ThrowIfNull(info);
string key = GetKey(info);
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo)) // O(log(n)).
{
throw new KeyNotFoundException($"({nameof(key)} = {key})");
}
return dlgInfo.FuncPtr;
}
public static int GetDelegateIndex(MethodInfo info) public static int GetDelegateIndex(MethodInfo info)
{ {
ArgumentNullException.ThrowIfNull(info); ArgumentNullException.ThrowIfNull(info);
@@ -65,11 +49,11 @@ namespace ARMeilleure.Translation
return index; return index;
} }
private static void SetDelegateInfo(Delegate dlg, nint funcPtr) private static void SetDelegateInfo(MethodInfo method)
{ {
string key = GetKey(dlg.Method); string key = GetKey(method);
_delegates.Add(key, new DelegateInfo(dlg, funcPtr)); // ArgumentException (key). _delegates.Add(key, new DelegateInfo(method.MethodHandle.GetFunctionPointer())); // ArgumentException (key).
} }
private static string GetKey(MethodInfo info) private static string GetKey(MethodInfo info)
@@ -83,528 +67,179 @@ namespace ARMeilleure.Translation
{ {
_delegates = new SortedList<string, DelegateInfo>(); _delegates = new SortedList<string, DelegateInfo>();
var dlgMathAbs = new MathAbs(Math.Abs); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Abs)));
var dlgMathCeiling = new MathCeiling(Math.Ceiling); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Ceiling)));
var dlgMathFloor = new MathFloor(Math.Floor); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Floor)));
var dlgMathRound = new MathRound(Math.Round); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Round)));
var dlgMathTruncate = new MathTruncate(Math.Truncate); SetDelegateInfo(typeof(MathHelper).GetMethod(nameof(MathHelper.Truncate)));
var dlgMathFAbs = new MathFAbs(MathF.Abs); SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Abs)));
var dlgMathFCeiling = new MathFCeiling(MathF.Ceiling); SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Ceiling)));
var dlgMathFFloor = new MathFFloor(MathF.Floor); SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Floor)));
var dlgMathFRound = new MathFRound(MathF.Round); SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Round)));
var dlgMathFTruncate = new MathFTruncate(MathF.Truncate); SetDelegateInfo(typeof(MathHelperF).GetMethod(nameof(MathHelperF.Truncate)));
var dlgNativeInterfaceBreak = new NativeInterfaceBreak(NativeInterface.Break); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Break)));
var dlgNativeInterfaceCheckSynchronization = new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization)));
var dlgNativeInterfaceEnqueueForRejit = new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.EnqueueForRejit)));
var dlgNativeInterfaceGetCntfrqEl0 = new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)));
var dlgNativeInterfaceGetCntpctEl0 = new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)));
var dlgNativeInterfaceGetCntvctEl0 = new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
var dlgNativeInterfaceGetCtrEl0 = new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
var dlgNativeInterfaceGetDczidEl0 = new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
var dlgNativeInterfaceGetFunctionAddress = new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
var dlgNativeInterfaceInvalidateCacheLine = new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
var dlgNativeInterfaceReadByte = new NativeInterfaceReadByte(NativeInterface.ReadByte); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)));
var dlgNativeInterfaceReadUInt16 = new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)));
var dlgNativeInterfaceReadUInt32 = new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
var dlgNativeInterfaceReadUInt64 = new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
var dlgNativeInterfaceReadVector128 = new NativeInterfaceReadVector128(NativeInterface.ReadVector128); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
var dlgNativeInterfaceSignalMemoryTracking = new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
var dlgNativeInterfaceSupervisorCall = new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));
var dlgNativeInterfaceThrowInvalidMemoryAccess = new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ThrowInvalidMemoryAccess)));
var dlgNativeInterfaceUndefined = new NativeInterfaceUndefined(NativeInterface.Undefined); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined)));
var dlgNativeInterfaceWriteByte = new NativeInterfaceWriteByte(NativeInterface.WriteByte); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)));
var dlgNativeInterfaceWriteUInt16 = new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)));
var dlgNativeInterfaceWriteUInt32 = new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)));
var dlgNativeInterfaceWriteUInt64 = new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
var dlgNativeInterfaceWriteVector128 = new NativeInterfaceWriteVector128(NativeInterface.WriteVector128); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
var dlgSoftFallbackCountLeadingSigns = new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
var dlgSoftFallbackCountLeadingZeros = new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
var dlgSoftFallbackCrc32b = new SoftFallbackCrc32b(SoftFallback.Crc32b); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
var dlgSoftFallbackCrc32cb = new SoftFallbackCrc32cb(SoftFallback.Crc32cb); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cb)));
var dlgSoftFallbackCrc32ch = new SoftFallbackCrc32ch(SoftFallback.Crc32ch); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32ch)));
var dlgSoftFallbackCrc32cw = new SoftFallbackCrc32cw(SoftFallback.Crc32cw); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cw)));
var dlgSoftFallbackCrc32cx = new SoftFallbackCrc32cx(SoftFallback.Crc32cx); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32cx)));
var dlgSoftFallbackCrc32h = new SoftFallbackCrc32h(SoftFallback.Crc32h); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32h)));
var dlgSoftFallbackCrc32w = new SoftFallbackCrc32w(SoftFallback.Crc32w); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
var dlgSoftFallbackCrc32x = new SoftFallbackCrc32x(SoftFallback.Crc32x); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
var dlgSoftFallbackDecrypt = new SoftFallbackDecrypt(SoftFallback.Decrypt); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
var dlgSoftFallbackEncrypt = new SoftFallbackEncrypt(SoftFallback.Encrypt); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
var dlgSoftFallbackFixedRotate = new SoftFallbackFixedRotate(SoftFallback.FixedRotate); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
var dlgSoftFallbackHashChoose = new SoftFallbackHashChoose(SoftFallback.HashChoose); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
var dlgSoftFallbackHashLower = new SoftFallbackHashLower(SoftFallback.HashLower); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
var dlgSoftFallbackHashMajority = new SoftFallbackHashMajority(SoftFallback.HashMajority); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
var dlgSoftFallbackHashParity = new SoftFallbackHashParity(SoftFallback.HashParity); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)));
var dlgSoftFallbackHashUpper = new SoftFallbackHashUpper(SoftFallback.HashUpper); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)));
var dlgSoftFallbackInverseMixColumns = new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
var dlgSoftFallbackMixColumns = new SoftFallbackMixColumns(SoftFallback.MixColumns); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
var dlgSoftFallbackPolynomialMult64_128 = new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
var dlgSoftFallbackSatF32ToS32 = new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
var dlgSoftFallbackSatF32ToS64 = new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
var dlgSoftFallbackSatF32ToU32 = new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
var dlgSoftFallbackSatF32ToU64 = new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64)));
var dlgSoftFallbackSatF64ToS32 = new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32)));
var dlgSoftFallbackSatF64ToS64 = new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64)));
var dlgSoftFallbackSatF64ToU32 = new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32)));
var dlgSoftFallbackSatF64ToU64 = new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64)));
var dlgSoftFallbackSha1SchedulePart1 = new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)));
var dlgSoftFallbackSha1SchedulePart2 = new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
var dlgSoftFallbackSha256SchedulePart1 = new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
var dlgSoftFallbackSha256SchedulePart2 = new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
var dlgSoftFallbackSignedShrImm64 = new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
var dlgSoftFallbackTbl1 = new SoftFallbackTbl1(SoftFallback.Tbl1); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
var dlgSoftFallbackTbl2 = new SoftFallbackTbl2(SoftFallback.Tbl2); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
var dlgSoftFallbackTbl3 = new SoftFallbackTbl3(SoftFallback.Tbl3); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
var dlgSoftFallbackTbl4 = new SoftFallbackTbl4(SoftFallback.Tbl4); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)));
var dlgSoftFallbackTbx1 = new SoftFallbackTbx1(SoftFallback.Tbx1); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)));
var dlgSoftFallbackTbx2 = new SoftFallbackTbx2(SoftFallback.Tbx2); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
var dlgSoftFallbackTbx3 = new SoftFallbackTbx3(SoftFallback.Tbx3); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
var dlgSoftFallbackTbx4 = new SoftFallbackTbx4(SoftFallback.Tbx4); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
var dlgSoftFallbackUnsignedShrImm64 = new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
var dlgSoftFloat16_32FPConvert = new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert); SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
var dlgSoftFloat16_64FPConvert = new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert); SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));
var dlgSoftFloat32FPAdd = new SoftFloat32FPAdd(SoftFloat32.FPAdd); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAdd)));
var dlgSoftFloat32FPAddFpscr = new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPAddFpscr))); // A32 only.
var dlgSoftFloat32FPCompare = new SoftFloat32FPCompare(SoftFloat32.FPCompare); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare)));
var dlgSoftFloat32FPCompareEQ = new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQ)));
var dlgSoftFloat32FPCompareEQFpscr = new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareEQFpscr))); // A32 only.
var dlgSoftFloat32FPCompareGE = new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGE)));
var dlgSoftFloat32FPCompareGEFpscr = new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGEFpscr))); // A32 only.
var dlgSoftFloat32FPCompareGT = new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGT)));
var dlgSoftFloat32FPCompareGTFpscr = new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareGTFpscr))); // A32 only.
var dlgSoftFloat32FPCompareLE = new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLE)));
var dlgSoftFloat32FPCompareLEFpscr = new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLEFpscr))); // A32 only.
var dlgSoftFloat32FPCompareLT = new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLT)));
var dlgSoftFloat32FPCompareLTFpscr = new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompareLTFpscr))); // A32 only.
var dlgSoftFloat32FPDiv = new SoftFloat32FPDiv(SoftFloat32.FPDiv); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPDiv)));
var dlgSoftFloat32FPMax = new SoftFloat32FPMax(SoftFloat32.FPMax); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)));
var dlgSoftFloat32FPMaxFpscr = new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxFpscr))); // A32 only.
var dlgSoftFloat32FPMaxNum = new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)));
var dlgSoftFloat32FPMaxNumFpscr = new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNumFpscr))); // A32 only.
var dlgSoftFloat32FPMin = new SoftFloat32FPMin(SoftFloat32.FPMin); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)));
var dlgSoftFloat32FPMinFpscr = new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinFpscr))); // A32 only.
var dlgSoftFloat32FPMinNum = new SoftFloat32FPMinNum(SoftFloat32.FPMinNum); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)));
var dlgSoftFloat32FPMinNumFpscr = new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNumFpscr))); // A32 only.
var dlgSoftFloat32FPMul = new SoftFloat32FPMul(SoftFloat32.FPMul); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMul)));
var dlgSoftFloat32FPMulFpscr = new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulFpscr))); // A32 only.
var dlgSoftFloat32FPMulAdd = new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAdd)));
var dlgSoftFloat32FPMulAddFpscr = new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulAddFpscr))); // A32 only.
var dlgSoftFloat32FPMulSub = new SoftFloat32FPMulSub(SoftFloat32.FPMulSub); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSub)));
var dlgSoftFloat32FPMulSubFpscr = new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulSubFpscr))); // A32 only.
var dlgSoftFloat32FPMulX = new SoftFloat32FPMulX(SoftFloat32.FPMulX); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMulX)));
var dlgSoftFloat32FPNegMulAdd = new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulAdd)));
var dlgSoftFloat32FPNegMulSub = new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPNegMulSub)));
var dlgSoftFloat32FPRecipEstimate = new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimate)));
var dlgSoftFloat32FPRecipEstimateFpscr = new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipEstimateFpscr))); // A32 only.
var dlgSoftFloat32FPRecipStep = new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStep))); // A32 only.
var dlgSoftFloat32FPRecipStepFused = new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecipStepFused)));
var dlgSoftFloat32FPRecpX = new SoftFloat32FPRecpX(SoftFloat32.FPRecpX); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRecpX)));
var dlgSoftFloat32FPRSqrtEstimate = new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimate)));
var dlgSoftFloat32FPRSqrtEstimateFpscr = new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtEstimateFpscr))); // A32 only.
var dlgSoftFloat32FPRSqrtStep = new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep); // A32 only. SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStep))); // A32 only.
var dlgSoftFloat32FPRSqrtStepFused = new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPRSqrtStepFused)));
var dlgSoftFloat32FPSqrt = new SoftFloat32FPSqrt(SoftFloat32.FPSqrt); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSqrt)));
var dlgSoftFloat32FPSub = new SoftFloat32FPSub(SoftFloat32.FPSub); SetDelegateInfo(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPSub)));
var dlgSoftFloat32_16FPConvert = new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert); SetDelegateInfo(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)));
var dlgSoftFloat64FPAdd = new SoftFloat64FPAdd(SoftFloat64.FPAdd); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAdd)));
var dlgSoftFloat64FPAddFpscr = new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPAddFpscr))); // A32 only.
var dlgSoftFloat64FPCompare = new SoftFloat64FPCompare(SoftFloat64.FPCompare); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare)));
var dlgSoftFloat64FPCompareEQ = new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQ)));
var dlgSoftFloat64FPCompareEQFpscr = new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareEQFpscr))); // A32 only.
var dlgSoftFloat64FPCompareGE = new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGE)));
var dlgSoftFloat64FPCompareGEFpscr = new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGEFpscr))); // A32 only.
var dlgSoftFloat64FPCompareGT = new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGT)));
var dlgSoftFloat64FPCompareGTFpscr = new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareGTFpscr))); // A32 only.
var dlgSoftFloat64FPCompareLE = new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLE)));
var dlgSoftFloat64FPCompareLEFpscr = new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLEFpscr))); // A32 only.
var dlgSoftFloat64FPCompareLT = new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLT)));
var dlgSoftFloat64FPCompareLTFpscr = new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompareLTFpscr))); // A32 only.
var dlgSoftFloat64FPDiv = new SoftFloat64FPDiv(SoftFloat64.FPDiv); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPDiv)));
var dlgSoftFloat64FPMax = new SoftFloat64FPMax(SoftFloat64.FPMax); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMax)));
var dlgSoftFloat64FPMaxFpscr = new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxFpscr))); // A32 only.
var dlgSoftFloat64FPMaxNum = new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNum)));
var dlgSoftFloat64FPMaxNumFpscr = new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMaxNumFpscr))); // A32 only.
var dlgSoftFloat64FPMin = new SoftFloat64FPMin(SoftFloat64.FPMin); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMin)));
var dlgSoftFloat64FPMinFpscr = new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinFpscr))); // A32 only.
var dlgSoftFloat64FPMinNum = new SoftFloat64FPMinNum(SoftFloat64.FPMinNum); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNum)));
var dlgSoftFloat64FPMinNumFpscr = new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMinNumFpscr))); // A32 only.
var dlgSoftFloat64FPMul = new SoftFloat64FPMul(SoftFloat64.FPMul); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMul)));
var dlgSoftFloat64FPMulFpscr = new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulFpscr))); // A32 only.
var dlgSoftFloat64FPMulAdd = new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAdd)));
var dlgSoftFloat64FPMulAddFpscr = new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulAddFpscr))); // A32 only.
var dlgSoftFloat64FPMulSub = new SoftFloat64FPMulSub(SoftFloat64.FPMulSub); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSub)));
var dlgSoftFloat64FPMulSubFpscr = new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulSubFpscr))); // A32 only.
var dlgSoftFloat64FPMulX = new SoftFloat64FPMulX(SoftFloat64.FPMulX); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPMulX)));
var dlgSoftFloat64FPNegMulAdd = new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulAdd)));
var dlgSoftFloat64FPNegMulSub = new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPNegMulSub)));
var dlgSoftFloat64FPRecipEstimate = new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimate)));
var dlgSoftFloat64FPRecipEstimateFpscr = new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipEstimateFpscr))); // A32 only.
var dlgSoftFloat64FPRecipStep = new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStep))); // A32 only.
var dlgSoftFloat64FPRecipStepFused = new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecipStepFused)));
var dlgSoftFloat64FPRecpX = new SoftFloat64FPRecpX(SoftFloat64.FPRecpX); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRecpX)));
var dlgSoftFloat64FPRSqrtEstimate = new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimate)));
var dlgSoftFloat64FPRSqrtEstimateFpscr = new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtEstimateFpscr))); // A32 only.
var dlgSoftFloat64FPRSqrtStep = new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep); // A32 only. SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStep))); // A32 only.
var dlgSoftFloat64FPRSqrtStepFused = new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPRSqrtStepFused)));
var dlgSoftFloat64FPSqrt = new SoftFloat64FPSqrt(SoftFloat64.FPSqrt); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSqrt)));
var dlgSoftFloat64FPSub = new SoftFloat64FPSub(SoftFloat64.FPSub); SetDelegateInfo(typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPSub)));
var dlgSoftFloat64_16FPConvert = new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert); SetDelegateInfo(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)));
SetDelegateInfo(dlgMathAbs, Marshal.GetFunctionPointerForDelegate<MathAbs>(dlgMathAbs));
SetDelegateInfo(dlgMathCeiling, Marshal.GetFunctionPointerForDelegate<MathCeiling>(dlgMathCeiling));
SetDelegateInfo(dlgMathFloor, Marshal.GetFunctionPointerForDelegate<MathFloor>(dlgMathFloor));
SetDelegateInfo(dlgMathRound, Marshal.GetFunctionPointerForDelegate<MathRound>(dlgMathRound));
SetDelegateInfo(dlgMathTruncate, Marshal.GetFunctionPointerForDelegate<MathTruncate>(dlgMathTruncate));
SetDelegateInfo(dlgMathFAbs, Marshal.GetFunctionPointerForDelegate<MathFAbs>(dlgMathFAbs));
SetDelegateInfo(dlgMathFCeiling, Marshal.GetFunctionPointerForDelegate<MathFCeiling>(dlgMathFCeiling));
SetDelegateInfo(dlgMathFFloor, Marshal.GetFunctionPointerForDelegate<MathFFloor>(dlgMathFFloor));
SetDelegateInfo(dlgMathFRound, Marshal.GetFunctionPointerForDelegate<MathFRound>(dlgMathFRound));
SetDelegateInfo(dlgMathFTruncate, Marshal.GetFunctionPointerForDelegate<MathFTruncate>(dlgMathFTruncate));
SetDelegateInfo(dlgNativeInterfaceBreak, Marshal.GetFunctionPointerForDelegate<NativeInterfaceBreak>(dlgNativeInterfaceBreak));
SetDelegateInfo(dlgNativeInterfaceCheckSynchronization, Marshal.GetFunctionPointerForDelegate<NativeInterfaceCheckSynchronization>(dlgNativeInterfaceCheckSynchronization));
SetDelegateInfo(dlgNativeInterfaceEnqueueForRejit, Marshal.GetFunctionPointerForDelegate<NativeInterfaceEnqueueForRejit>(dlgNativeInterfaceEnqueueForRejit));
SetDelegateInfo(dlgNativeInterfaceGetCntfrqEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntfrqEl0>(dlgNativeInterfaceGetCntfrqEl0));
SetDelegateInfo(dlgNativeInterfaceGetCntpctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntpctEl0>(dlgNativeInterfaceGetCntpctEl0));
SetDelegateInfo(dlgNativeInterfaceGetCntvctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntvctEl0>(dlgNativeInterfaceGetCntvctEl0));
SetDelegateInfo(dlgNativeInterfaceGetCtrEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCtrEl0>(dlgNativeInterfaceGetCtrEl0));
SetDelegateInfo(dlgNativeInterfaceGetDczidEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetDczidEl0>(dlgNativeInterfaceGetDczidEl0));
SetDelegateInfo(dlgNativeInterfaceGetFunctionAddress, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetFunctionAddress>(dlgNativeInterfaceGetFunctionAddress));
SetDelegateInfo(dlgNativeInterfaceInvalidateCacheLine, Marshal.GetFunctionPointerForDelegate<NativeInterfaceInvalidateCacheLine>(dlgNativeInterfaceInvalidateCacheLine));
SetDelegateInfo(dlgNativeInterfaceReadByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadByte>(dlgNativeInterfaceReadByte));
SetDelegateInfo(dlgNativeInterfaceReadUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt16>(dlgNativeInterfaceReadUInt16));
SetDelegateInfo(dlgNativeInterfaceReadUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt32>(dlgNativeInterfaceReadUInt32));
SetDelegateInfo(dlgNativeInterfaceReadUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt64>(dlgNativeInterfaceReadUInt64));
SetDelegateInfo(dlgNativeInterfaceReadVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadVector128>(dlgNativeInterfaceReadVector128));
SetDelegateInfo(dlgNativeInterfaceSignalMemoryTracking, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSignalMemoryTracking>(dlgNativeInterfaceSignalMemoryTracking));
SetDelegateInfo(dlgNativeInterfaceSupervisorCall, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSupervisorCall>(dlgNativeInterfaceSupervisorCall));
SetDelegateInfo(dlgNativeInterfaceThrowInvalidMemoryAccess, Marshal.GetFunctionPointerForDelegate<NativeInterfaceThrowInvalidMemoryAccess>(dlgNativeInterfaceThrowInvalidMemoryAccess));
SetDelegateInfo(dlgNativeInterfaceUndefined, Marshal.GetFunctionPointerForDelegate<NativeInterfaceUndefined>(dlgNativeInterfaceUndefined));
SetDelegateInfo(dlgNativeInterfaceWriteByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteByte>(dlgNativeInterfaceWriteByte));
SetDelegateInfo(dlgNativeInterfaceWriteUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt16>(dlgNativeInterfaceWriteUInt16));
SetDelegateInfo(dlgNativeInterfaceWriteUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt32>(dlgNativeInterfaceWriteUInt32));
SetDelegateInfo(dlgNativeInterfaceWriteUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt64>(dlgNativeInterfaceWriteUInt64));
SetDelegateInfo(dlgNativeInterfaceWriteVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteVector128>(dlgNativeInterfaceWriteVector128));
SetDelegateInfo(dlgSoftFallbackCountLeadingSigns, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingSigns>(dlgSoftFallbackCountLeadingSigns));
SetDelegateInfo(dlgSoftFallbackCountLeadingZeros, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingZeros>(dlgSoftFallbackCountLeadingZeros));
SetDelegateInfo(dlgSoftFallbackCrc32b, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32b>(dlgSoftFallbackCrc32b));
SetDelegateInfo(dlgSoftFallbackCrc32cb, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cb>(dlgSoftFallbackCrc32cb));
SetDelegateInfo(dlgSoftFallbackCrc32ch, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32ch>(dlgSoftFallbackCrc32ch));
SetDelegateInfo(dlgSoftFallbackCrc32cw, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cw>(dlgSoftFallbackCrc32cw));
SetDelegateInfo(dlgSoftFallbackCrc32cx, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cx>(dlgSoftFallbackCrc32cx));
SetDelegateInfo(dlgSoftFallbackCrc32h, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32h>(dlgSoftFallbackCrc32h));
SetDelegateInfo(dlgSoftFallbackCrc32w, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32w>(dlgSoftFallbackCrc32w));
SetDelegateInfo(dlgSoftFallbackCrc32x, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32x>(dlgSoftFallbackCrc32x));
SetDelegateInfo(dlgSoftFallbackDecrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackDecrypt>(dlgSoftFallbackDecrypt));
SetDelegateInfo(dlgSoftFallbackEncrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackEncrypt>(dlgSoftFallbackEncrypt));
SetDelegateInfo(dlgSoftFallbackFixedRotate, Marshal.GetFunctionPointerForDelegate<SoftFallbackFixedRotate>(dlgSoftFallbackFixedRotate));
SetDelegateInfo(dlgSoftFallbackHashChoose, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashChoose>(dlgSoftFallbackHashChoose));
SetDelegateInfo(dlgSoftFallbackHashLower, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashLower>(dlgSoftFallbackHashLower));
SetDelegateInfo(dlgSoftFallbackHashMajority, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashMajority>(dlgSoftFallbackHashMajority));
SetDelegateInfo(dlgSoftFallbackHashParity, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashParity>(dlgSoftFallbackHashParity));
SetDelegateInfo(dlgSoftFallbackHashUpper, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashUpper>(dlgSoftFallbackHashUpper));
SetDelegateInfo(dlgSoftFallbackInverseMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackInverseMixColumns>(dlgSoftFallbackInverseMixColumns));
SetDelegateInfo(dlgSoftFallbackMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackMixColumns>(dlgSoftFallbackMixColumns));
SetDelegateInfo(dlgSoftFallbackPolynomialMult64_128, Marshal.GetFunctionPointerForDelegate<SoftFallbackPolynomialMult64_128>(dlgSoftFallbackPolynomialMult64_128));
SetDelegateInfo(dlgSoftFallbackSatF32ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS32>(dlgSoftFallbackSatF32ToS32));
SetDelegateInfo(dlgSoftFallbackSatF32ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS64>(dlgSoftFallbackSatF32ToS64));
SetDelegateInfo(dlgSoftFallbackSatF32ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU32>(dlgSoftFallbackSatF32ToU32));
SetDelegateInfo(dlgSoftFallbackSatF32ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU64>(dlgSoftFallbackSatF32ToU64));
SetDelegateInfo(dlgSoftFallbackSatF64ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS32>(dlgSoftFallbackSatF64ToS32));
SetDelegateInfo(dlgSoftFallbackSatF64ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS64>(dlgSoftFallbackSatF64ToS64));
SetDelegateInfo(dlgSoftFallbackSatF64ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU32>(dlgSoftFallbackSatF64ToU32));
SetDelegateInfo(dlgSoftFallbackSatF64ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU64>(dlgSoftFallbackSatF64ToU64));
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart1>(dlgSoftFallbackSha1SchedulePart1));
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart2>(dlgSoftFallbackSha1SchedulePart2));
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart1>(dlgSoftFallbackSha256SchedulePart1));
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart2>(dlgSoftFallbackSha256SchedulePart2));
SetDelegateInfo(dlgSoftFallbackSignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSignedShrImm64>(dlgSoftFallbackSignedShrImm64));
SetDelegateInfo(dlgSoftFallbackTbl1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl1>(dlgSoftFallbackTbl1));
SetDelegateInfo(dlgSoftFallbackTbl2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl2>(dlgSoftFallbackTbl2));
SetDelegateInfo(dlgSoftFallbackTbl3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl3>(dlgSoftFallbackTbl3));
SetDelegateInfo(dlgSoftFallbackTbl4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl4>(dlgSoftFallbackTbl4));
SetDelegateInfo(dlgSoftFallbackTbx1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx1>(dlgSoftFallbackTbx1));
SetDelegateInfo(dlgSoftFallbackTbx2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx2>(dlgSoftFallbackTbx2));
SetDelegateInfo(dlgSoftFallbackTbx3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx3>(dlgSoftFallbackTbx3));
SetDelegateInfo(dlgSoftFallbackTbx4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx4>(dlgSoftFallbackTbx4));
SetDelegateInfo(dlgSoftFallbackUnsignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackUnsignedShrImm64>(dlgSoftFallbackUnsignedShrImm64));
SetDelegateInfo(dlgSoftFloat16_32FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_32FPConvert>(dlgSoftFloat16_32FPConvert));
SetDelegateInfo(dlgSoftFloat16_64FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_64FPConvert>(dlgSoftFloat16_64FPConvert));
SetDelegateInfo(dlgSoftFloat32FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAdd>(dlgSoftFloat32FPAdd));
SetDelegateInfo(dlgSoftFloat32FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAddFpscr>(dlgSoftFloat32FPAddFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompare>(dlgSoftFloat32FPCompare));
SetDelegateInfo(dlgSoftFloat32FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQ>(dlgSoftFloat32FPCompareEQ));
SetDelegateInfo(dlgSoftFloat32FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQFpscr>(dlgSoftFloat32FPCompareEQFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGE>(dlgSoftFloat32FPCompareGE));
SetDelegateInfo(dlgSoftFloat32FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGEFpscr>(dlgSoftFloat32FPCompareGEFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGT>(dlgSoftFloat32FPCompareGT));
SetDelegateInfo(dlgSoftFloat32FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGTFpscr>(dlgSoftFloat32FPCompareGTFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLE>(dlgSoftFloat32FPCompareLE));
SetDelegateInfo(dlgSoftFloat32FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLEFpscr>(dlgSoftFloat32FPCompareLEFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLT>(dlgSoftFloat32FPCompareLT));
SetDelegateInfo(dlgSoftFloat32FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLTFpscr>(dlgSoftFloat32FPCompareLTFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPDiv>(dlgSoftFloat32FPDiv));
SetDelegateInfo(dlgSoftFloat32FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMax>(dlgSoftFloat32FPMax));
SetDelegateInfo(dlgSoftFloat32FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxFpscr>(dlgSoftFloat32FPMaxFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNum>(dlgSoftFloat32FPMaxNum));
SetDelegateInfo(dlgSoftFloat32FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNumFpscr>(dlgSoftFloat32FPMaxNumFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMin>(dlgSoftFloat32FPMin));
SetDelegateInfo(dlgSoftFloat32FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinFpscr>(dlgSoftFloat32FPMinFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNum>(dlgSoftFloat32FPMinNum));
SetDelegateInfo(dlgSoftFloat32FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNumFpscr>(dlgSoftFloat32FPMinNumFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMul>(dlgSoftFloat32FPMul));
SetDelegateInfo(dlgSoftFloat32FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulFpscr>(dlgSoftFloat32FPMulFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAdd>(dlgSoftFloat32FPMulAdd));
SetDelegateInfo(dlgSoftFloat32FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAddFpscr>(dlgSoftFloat32FPMulAddFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSub>(dlgSoftFloat32FPMulSub));
SetDelegateInfo(dlgSoftFloat32FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSubFpscr>(dlgSoftFloat32FPMulSubFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulX>(dlgSoftFloat32FPMulX));
SetDelegateInfo(dlgSoftFloat32FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulAdd>(dlgSoftFloat32FPNegMulAdd));
SetDelegateInfo(dlgSoftFloat32FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulSub>(dlgSoftFloat32FPNegMulSub));
SetDelegateInfo(dlgSoftFloat32FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimate>(dlgSoftFloat32FPRecipEstimate));
SetDelegateInfo(dlgSoftFloat32FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimateFpscr>(dlgSoftFloat32FPRecipEstimateFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStep>(dlgSoftFloat32FPRecipStep)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStepFused>(dlgSoftFloat32FPRecipStepFused));
SetDelegateInfo(dlgSoftFloat32FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecpX>(dlgSoftFloat32FPRecpX));
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimate>(dlgSoftFloat32FPRSqrtEstimate));
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimateFpscr>(dlgSoftFloat32FPRSqrtEstimateFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStep>(dlgSoftFloat32FPRSqrtStep)); // A32 only.
SetDelegateInfo(dlgSoftFloat32FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStepFused>(dlgSoftFloat32FPRSqrtStepFused));
SetDelegateInfo(dlgSoftFloat32FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSqrt>(dlgSoftFloat32FPSqrt));
SetDelegateInfo(dlgSoftFloat32FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSub>(dlgSoftFloat32FPSub));
SetDelegateInfo(dlgSoftFloat32_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat32_16FPConvert>(dlgSoftFloat32_16FPConvert));
SetDelegateInfo(dlgSoftFloat64FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAdd>(dlgSoftFloat64FPAdd));
SetDelegateInfo(dlgSoftFloat64FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAddFpscr>(dlgSoftFloat64FPAddFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompare>(dlgSoftFloat64FPCompare));
SetDelegateInfo(dlgSoftFloat64FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQ>(dlgSoftFloat64FPCompareEQ));
SetDelegateInfo(dlgSoftFloat64FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQFpscr>(dlgSoftFloat64FPCompareEQFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGE>(dlgSoftFloat64FPCompareGE));
SetDelegateInfo(dlgSoftFloat64FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGEFpscr>(dlgSoftFloat64FPCompareGEFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGT>(dlgSoftFloat64FPCompareGT));
SetDelegateInfo(dlgSoftFloat64FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGTFpscr>(dlgSoftFloat64FPCompareGTFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLE>(dlgSoftFloat64FPCompareLE));
SetDelegateInfo(dlgSoftFloat64FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLEFpscr>(dlgSoftFloat64FPCompareLEFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLT>(dlgSoftFloat64FPCompareLT));
SetDelegateInfo(dlgSoftFloat64FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLTFpscr>(dlgSoftFloat64FPCompareLTFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPDiv>(dlgSoftFloat64FPDiv));
SetDelegateInfo(dlgSoftFloat64FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMax>(dlgSoftFloat64FPMax));
SetDelegateInfo(dlgSoftFloat64FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxFpscr>(dlgSoftFloat64FPMaxFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNum>(dlgSoftFloat64FPMaxNum));
SetDelegateInfo(dlgSoftFloat64FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNumFpscr>(dlgSoftFloat64FPMaxNumFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMin>(dlgSoftFloat64FPMin));
SetDelegateInfo(dlgSoftFloat64FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinFpscr>(dlgSoftFloat64FPMinFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNum>(dlgSoftFloat64FPMinNum));
SetDelegateInfo(dlgSoftFloat64FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNumFpscr>(dlgSoftFloat64FPMinNumFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMul>(dlgSoftFloat64FPMul));
SetDelegateInfo(dlgSoftFloat64FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulFpscr>(dlgSoftFloat64FPMulFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAdd>(dlgSoftFloat64FPMulAdd));
SetDelegateInfo(dlgSoftFloat64FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAddFpscr>(dlgSoftFloat64FPMulAddFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSub>(dlgSoftFloat64FPMulSub));
SetDelegateInfo(dlgSoftFloat64FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSubFpscr>(dlgSoftFloat64FPMulSubFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulX>(dlgSoftFloat64FPMulX));
SetDelegateInfo(dlgSoftFloat64FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulAdd>(dlgSoftFloat64FPNegMulAdd));
SetDelegateInfo(dlgSoftFloat64FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulSub>(dlgSoftFloat64FPNegMulSub));
SetDelegateInfo(dlgSoftFloat64FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimate>(dlgSoftFloat64FPRecipEstimate));
SetDelegateInfo(dlgSoftFloat64FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimateFpscr>(dlgSoftFloat64FPRecipEstimateFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStep>(dlgSoftFloat64FPRecipStep)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStepFused>(dlgSoftFloat64FPRecipStepFused));
SetDelegateInfo(dlgSoftFloat64FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecpX>(dlgSoftFloat64FPRecpX));
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimate>(dlgSoftFloat64FPRSqrtEstimate));
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimateFpscr>(dlgSoftFloat64FPRSqrtEstimateFpscr)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStep>(dlgSoftFloat64FPRSqrtStep)); // A32 only.
SetDelegateInfo(dlgSoftFloat64FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStepFused>(dlgSoftFloat64FPRSqrtStepFused));
SetDelegateInfo(dlgSoftFloat64FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSqrt>(dlgSoftFloat64FPSqrt));
SetDelegateInfo(dlgSoftFloat64FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSub>(dlgSoftFloat64FPSub));
SetDelegateInfo(dlgSoftFloat64_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat64_16FPConvert>(dlgSoftFloat64_16FPConvert));
} }
private delegate double MathAbs(double value);
private delegate double MathCeiling(double a);
private delegate double MathFloor(double d);
private delegate double MathRound(double value, MidpointRounding mode);
private delegate double MathTruncate(double d);
private delegate float MathFAbs(float x);
private delegate float MathFCeiling(float x);
private delegate float MathFFloor(float x);
private delegate float MathFRound(float x, MidpointRounding mode);
private delegate float MathFTruncate(float x);
private delegate void NativeInterfaceBreak(ulong address, int imm);
private delegate bool NativeInterfaceCheckSynchronization();
private delegate void NativeInterfaceEnqueueForRejit(ulong address);
private delegate ulong NativeInterfaceGetCntfrqEl0();
private delegate ulong NativeInterfaceGetCntpctEl0();
private delegate ulong NativeInterfaceGetCntvctEl0();
private delegate ulong NativeInterfaceGetCtrEl0();
private delegate ulong NativeInterfaceGetDczidEl0();
private delegate ulong NativeInterfaceGetFunctionAddress(ulong address);
private delegate void NativeInterfaceInvalidateCacheLine(ulong address);
private delegate byte NativeInterfaceReadByte(ulong address);
private delegate ushort NativeInterfaceReadUInt16(ulong address);
private delegate uint NativeInterfaceReadUInt32(ulong address);
private delegate ulong NativeInterfaceReadUInt64(ulong address);
private delegate V128 NativeInterfaceReadVector128(ulong address);
private delegate void NativeInterfaceSignalMemoryTracking(ulong address, ulong size, bool write);
private delegate void NativeInterfaceSupervisorCall(ulong address, int imm);
private delegate void NativeInterfaceThrowInvalidMemoryAccess(ulong address);
private delegate void NativeInterfaceUndefined(ulong address, int opCode);
private delegate void NativeInterfaceWriteByte(ulong address, byte value);
private delegate void NativeInterfaceWriteUInt16(ulong address, ushort value);
private delegate void NativeInterfaceWriteUInt32(ulong address, uint value);
private delegate void NativeInterfaceWriteUInt64(ulong address, ulong value);
private delegate void NativeInterfaceWriteVector128(ulong address, V128 value);
private delegate ulong SoftFallbackCountLeadingSigns(ulong value, int size);
private delegate ulong SoftFallbackCountLeadingZeros(ulong value, int size);
private delegate uint SoftFallbackCrc32b(uint crc, byte value);
private delegate uint SoftFallbackCrc32cb(uint crc, byte value);
private delegate uint SoftFallbackCrc32ch(uint crc, ushort value);
private delegate uint SoftFallbackCrc32cw(uint crc, uint value);
private delegate uint SoftFallbackCrc32cx(uint crc, ulong value);
private delegate uint SoftFallbackCrc32h(uint crc, ushort value);
private delegate uint SoftFallbackCrc32w(uint crc, uint value);
private delegate uint SoftFallbackCrc32x(uint crc, ulong value);
private delegate V128 SoftFallbackDecrypt(V128 value, V128 roundKey);
private delegate V128 SoftFallbackEncrypt(V128 value, V128 roundKey);
private delegate uint SoftFallbackFixedRotate(uint hash_e);
private delegate V128 SoftFallbackHashChoose(V128 hash_abcd, uint hash_e, V128 wk);
private delegate V128 SoftFallbackHashLower(V128 hash_abcd, V128 hash_efgh, V128 wk);
private delegate V128 SoftFallbackHashMajority(V128 hash_abcd, uint hash_e, V128 wk);
private delegate V128 SoftFallbackHashParity(V128 hash_abcd, uint hash_e, V128 wk);
private delegate V128 SoftFallbackHashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk);
private delegate V128 SoftFallbackInverseMixColumns(V128 value);
private delegate V128 SoftFallbackMixColumns(V128 value);
private delegate V128 SoftFallbackPolynomialMult64_128(ulong op1, ulong op2);
private delegate int SoftFallbackSatF32ToS32(float value);
private delegate long SoftFallbackSatF32ToS64(float value);
private delegate uint SoftFallbackSatF32ToU32(float value);
private delegate ulong SoftFallbackSatF32ToU64(float value);
private delegate int SoftFallbackSatF64ToS32(double value);
private delegate long SoftFallbackSatF64ToS64(double value);
private delegate uint SoftFallbackSatF64ToU32(double value);
private delegate ulong SoftFallbackSatF64ToU64(double value);
private delegate V128 SoftFallbackSha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11);
private delegate V128 SoftFallbackSha1SchedulePart2(V128 tw0_3, V128 w12_15);
private delegate V128 SoftFallbackSha256SchedulePart1(V128 w0_3, V128 w4_7);
private delegate V128 SoftFallbackSha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15);
private delegate long SoftFallbackSignedShrImm64(long value, long roundConst, int shift);
private delegate V128 SoftFallbackTbl1(V128 vector, int bytes, V128 tb0);
private delegate V128 SoftFallbackTbl2(V128 vector, int bytes, V128 tb0, V128 tb1);
private delegate V128 SoftFallbackTbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
private delegate V128 SoftFallbackTbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
private delegate V128 SoftFallbackTbx1(V128 dest, V128 vector, int bytes, V128 tb0);
private delegate V128 SoftFallbackTbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1);
private delegate V128 SoftFallbackTbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2);
private delegate V128 SoftFallbackTbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3);
private delegate ulong SoftFallbackUnsignedShrImm64(ulong value, long roundConst, int shift);
private delegate float SoftFloat16_32FPConvert(ushort valueBits);
private delegate double SoftFloat16_64FPConvert(ushort valueBits);
private delegate float SoftFloat32FPAdd(float value1, float value2);
private delegate float SoftFloat32FPAddFpscr(float value1, float value2, bool standardFpscr);
private delegate int SoftFloat32FPCompare(float value1, float value2, bool signalNaNs);
private delegate float SoftFloat32FPCompareEQ(float value1, float value2);
private delegate float SoftFloat32FPCompareEQFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPCompareGE(float value1, float value2);
private delegate float SoftFloat32FPCompareGEFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPCompareGT(float value1, float value2);
private delegate float SoftFloat32FPCompareGTFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPCompareLE(float value1, float value2);
private delegate float SoftFloat32FPCompareLEFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPCompareLT(float value1, float value2);
private delegate float SoftFloat32FPCompareLTFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPDiv(float value1, float value2);
private delegate float SoftFloat32FPMax(float value1, float value2);
private delegate float SoftFloat32FPMaxFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMaxNum(float value1, float value2);
private delegate float SoftFloat32FPMaxNumFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMin(float value1, float value2);
private delegate float SoftFloat32FPMinFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMinNum(float value1, float value2);
private delegate float SoftFloat32FPMinNumFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMul(float value1, float value2);
private delegate float SoftFloat32FPMulFpscr(float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMulAdd(float valueA, float value1, float value2);
private delegate float SoftFloat32FPMulAddFpscr(float valueA, float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMulSub(float valueA, float value1, float value2);
private delegate float SoftFloat32FPMulSubFpscr(float valueA, float value1, float value2, bool standardFpscr);
private delegate float SoftFloat32FPMulX(float value1, float value2);
private delegate float SoftFloat32FPNegMulAdd(float valueA, float value1, float value2);
private delegate float SoftFloat32FPNegMulSub(float valueA, float value1, float value2);
private delegate float SoftFloat32FPRecipEstimate(float value);
private delegate float SoftFloat32FPRecipEstimateFpscr(float value, bool standardFpscr);
private delegate float SoftFloat32FPRecipStep(float value1, float value2);
private delegate float SoftFloat32FPRecipStepFused(float value1, float value2);
private delegate float SoftFloat32FPRecpX(float value);
private delegate float SoftFloat32FPRSqrtEstimate(float value);
private delegate float SoftFloat32FPRSqrtEstimateFpscr(float value, bool standardFpscr);
private delegate float SoftFloat32FPRSqrtStep(float value1, float value2);
private delegate float SoftFloat32FPRSqrtStepFused(float value1, float value2);
private delegate float SoftFloat32FPSqrt(float value);
private delegate float SoftFloat32FPSub(float value1, float value2);
private delegate ushort SoftFloat32_16FPConvert(float value);
private delegate double SoftFloat64FPAdd(double value1, double value2);
private delegate double SoftFloat64FPAddFpscr(double value1, double value2, bool standardFpscr);
private delegate int SoftFloat64FPCompare(double value1, double value2, bool signalNaNs);
private delegate double SoftFloat64FPCompareEQ(double value1, double value2);
private delegate double SoftFloat64FPCompareEQFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPCompareGE(double value1, double value2);
private delegate double SoftFloat64FPCompareGEFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPCompareGT(double value1, double value2);
private delegate double SoftFloat64FPCompareGTFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPCompareLE(double value1, double value2);
private delegate double SoftFloat64FPCompareLEFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPCompareLT(double value1, double value2);
private delegate double SoftFloat64FPCompareLTFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPDiv(double value1, double value2);
private delegate double SoftFloat64FPMax(double value1, double value2);
private delegate double SoftFloat64FPMaxFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMaxNum(double value1, double value2);
private delegate double SoftFloat64FPMaxNumFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMin(double value1, double value2);
private delegate double SoftFloat64FPMinFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMinNum(double value1, double value2);
private delegate double SoftFloat64FPMinNumFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMul(double value1, double value2);
private delegate double SoftFloat64FPMulFpscr(double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMulAdd(double valueA, double value1, double value2);
private delegate double SoftFloat64FPMulAddFpscr(double valueA, double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMulSub(double valueA, double value1, double value2);
private delegate double SoftFloat64FPMulSubFpscr(double valueA, double value1, double value2, bool standardFpscr);
private delegate double SoftFloat64FPMulX(double value1, double value2);
private delegate double SoftFloat64FPNegMulAdd(double valueA, double value1, double value2);
private delegate double SoftFloat64FPNegMulSub(double valueA, double value1, double value2);
private delegate double SoftFloat64FPRecipEstimate(double value);
private delegate double SoftFloat64FPRecipEstimateFpscr(double value, bool standardFpscr);
private delegate double SoftFloat64FPRecipStep(double value1, double value2);
private delegate double SoftFloat64FPRecipStepFused(double value1, double value2);
private delegate double SoftFloat64FPRecpX(double value);
private delegate double SoftFloat64FPRSqrtEstimate(double value);
private delegate double SoftFloat64FPRSqrtEstimateFpscr(double value, bool standardFpscr);
private delegate double SoftFloat64FPRSqrtStep(double value1, double value2);
private delegate double SoftFloat64FPRSqrtStepFused(double value1, double value2);
private delegate double SoftFloat64FPSqrt(double value);
private delegate double SoftFloat64FPSub(double value1, double value2);
private delegate ushort SoftFloat64_16FPConvert(double value);
} }
} }

View File

@@ -97,7 +97,7 @@ namespace ARMeilleure.Translation
public virtual Operand Call(MethodInfo info, params Operand[] callArgs) public virtual Operand Call(MethodInfo info, params Operand[] callArgs)
{ {
nint funcPtr = Delegates.GetDelegateFuncPtr(info); nint funcPtr = info.MethodHandle.GetFunctionPointer();
OperandType returnType = GetOperandType(info.ReturnType); OperandType returnType = GetOperandType(info.ReturnType);

View File

@@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 6997; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 6998; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@@ -25,7 +25,7 @@ namespace Ryujinx.Common.Configuration
{ {
var unpackedFields = packedHack.UnpackBitFields(PackedFormat); var unpackedFields = packedHack.UnpackBitFields(PackedFormat);
if (unpackedFields is not [var hack, var value]) if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack)); throw new Exception("The unpack operation on the integer resulted in an invalid unpacked result.");
return new EnabledDirtyHack((DirtyHack)hack, (int)value); return new EnabledDirtyHack((DirtyHack)hack, (int)value);
} }

View File

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

View File

@@ -0,0 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid.Controller
{
public class LedConfigController
{
/// <summary>
/// Packed RGB int of the color
/// </summary>
public uint LedColor { get; set; }
/// <summary>
/// Enable LED color changing by the emulator
/// </summary>
public bool EnableLed { get; set; }
}
}

View File

@@ -53,6 +53,9 @@ namespace Ryujinx.Common
{ {
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName) public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
{ {
if (eventArgs.AreValuesEqual)
return;
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}"); string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
Logger.Info?.Print(logClass, message); Logger.Info?.Print(logClass, message);
@@ -65,5 +68,22 @@ namespace Ryujinx.Common
{ {
public T OldValue { get; } = oldValue; public T OldValue { get; } = oldValue;
public T NewValue { get; } = newValue; public T NewValue { get; } = newValue;
public bool AreValuesEqual
{
get
{
if (OldValue == null && NewValue == null)
return true;
if (OldValue == null && NewValue != null)
return false;
if (OldValue != null && NewValue == null)
return false;
return OldValue!.Equals(NewValue);
}
}
} }
} }

View File

@@ -0,0 +1,10 @@
using System;
namespace Ryujinx.Common
{
public class RyujinxException : Exception
{
public RyujinxException(string message) : base(message)
{ }
}
}

View File

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

View File

@@ -367,7 +367,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay)) if (_context.Capabilities.Api == TargetApi.Metal && _context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay))
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]); Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte ClipPixel(int val) public static byte ClipPixel(int val)
{ {
return (byte)((val > 255) ? 255 : (val < 0) ? 0 : val); return (byte)(val > 255 ? 255 : val < 0 ? 0 : val);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

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

View File

@@ -1,8 +1,10 @@
using Ryujinx.Graphics.Nvdec.Vp9.Types;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal static class Constants internal static class Constants
{ {
public const int Vp9InterpExtend = 4; public const int InterpExtend = 4;
public const int MaxMbPlane = 3; public const int MaxMbPlane = 3;
@@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* Segment Feature Masks */ /* Segment Feature Masks */
public const int MaxMvRefCandidates = 2; public const int MaxMvRefCandidates = 2;
public const int IntraInterContexts = 4;
public const int CompInterContexts = 5; public const int CompInterContexts = 5;
public const int RefContexts = 5; public const int RefContexts = 5;
@@ -32,12 +35,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int EightTapSmooth = 1; public const int EightTapSmooth = 1;
public const int EightTapSharp = 2; public const int EightTapSharp = 2;
public const int SwitchableFilters = 3; /* Number of switchable filters */ public const int SwitchableFilters = 3; /* Number of switchable filters */
public const int Bilinear = 3; public const int Bilinear = 3;
public const int Switchable = 4; /* should be the last one */
// The codec can operate in four possible inter prediction filter mode:
// 8-tap, 8-tap-smooth, 8-tap-sharp, and switching between the three.
public const int SwitchableFilterContexts = SwitchableFilters + 1;
public const int Switchable = 4; /* Should be the last one */
// Frame // Frame
public const int RefsPerFrame = 3; public const int RefsPerFrame = 3;
public const int RefFramesLog2 = 3;
public const int RefFrames = 1 << RefFramesLog2;
// 1 scratch frame for the new frame, 3 for scaled references on the encoder.
public const int FrameBuffers = RefFrames + 4;
public const int FrameContextsLog2 = 2;
public const int FrameContexts = 1 << FrameContextsLog2;
public const int NumPingPongBuffers = 2; public const int NumPingPongBuffers = 2;
public const int Class0Bits = 1; /* bits at integer precision for class 0 */ public const int Class0Bits = 1; /* bits at integer precision for class 0 */
@@ -65,5 +82,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int SegmentAbsData = 1; public const int SegmentAbsData = 1;
public const int MaxSegments = 8; public const int MaxSegments = 8;
public const int PartitionTypes = (int)PartitionType.PartitionTypes;
public const int PartitionPlOffset = 4; // Number of probability models per block size
public const int PartitionContexts = 4 * PartitionPlOffset;
public const int PlaneTypes = (int)PlaneType.PlaneTypes;
public const int IntraModes = (int)PredictionMode.TmPred + 1;
public const int InterModes = 1 + (int)PredictionMode.NewMv - (int)PredictionMode.NearestMv;
public const int SkipContexts = 3;
public const int InterModeContexts = 7;
} }
} }

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

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Common; using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
@@ -12,14 +12,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private readonly MemoryAllocator _allocator = new(); private readonly MemoryAllocator _allocator = new();
public ISurface CreateSurface(int width, int height) => new Surface(width, height); public ISurface CreateSurface(int width, int height)
{
return new Surface(width, height);
}
private static ReadOnlySpan<byte> LiteralToFilter => new byte[] private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
{ {
Constants.EightTapSmooth, Constants.EightTapSmooth, Constants.EightTap, Constants.EightTapSharp, Constants.Bilinear
Constants.EightTap,
Constants.EightTapSharp,
Constants.Bilinear,
}; };
public unsafe bool Decode( public unsafe bool Decode(
@@ -29,25 +29,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ReadOnlySpan<Vp9MvRef> mvsIn, ReadOnlySpan<Vp9MvRef> mvsIn,
Span<Vp9MvRef> mvsOut) Span<Vp9MvRef> mvsOut)
{ {
Vp9Common cm = new() Vp9Common cm = new();
{
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
IntraOnly = pictureInfo.IntraOnly,
Width = output.Width, cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
Height = output.Height, cm.IntraOnly = pictureInfo.IntraOnly;
SubsamplingX = 1,
SubsamplingY = 1,
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs, cm.Width = output.Width;
cm.Height = output.Height;
cm.SubsamplingX = 1;
cm.SubsamplingY = 1;
RefFrameSignBias = pictureInfo.RefFrameSignBias, cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
BaseQindex = pictureInfo.BaseQIndex, cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
YDcDeltaQ = pictureInfo.YDcDeltaQ,
UvAcDeltaQ = pictureInfo.UvAcDeltaQ, cm.BaseQindex = pictureInfo.BaseQIndex;
UvDcDeltaQ = pictureInfo.UvDcDeltaQ, cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
}; cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
cm.Mb.Lossless = pictureInfo.Lossless; cm.Mb.Lossless = pictureInfo.Lossless;
cm.Mb.Bd = 8; cm.Mb.Bd = 8;
@@ -68,6 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.CompFixedRef = pictureInfo.CompFixedRef; cm.CompFixedRef = pictureInfo.CompFixedRef;
cm.CompVarRef = pictureInfo.CompVarRef; cm.CompVarRef = pictureInfo.CompVarRef;
cm.BitDepth = BitDepth.Bits8;
cm.Log2TileCols = pictureInfo.Log2TileCols; cm.Log2TileCols = pictureInfo.Log2TileCols;
cm.Log2TileRows = pictureInfo.Log2TileRows; cm.Log2TileRows = pictureInfo.Log2TileRows;
@@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable; cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData; cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
cm.Lf.FilterLevel = pictureInfo.LoopFilterLevel;
cm.Lf.SharpnessLevel = pictureInfo.LoopFilterSharpnessLevel;
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled; cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
cm.Lf.RefDeltas = pictureInfo.RefDeltas; cm.Lf.RefDeltas = pictureInfo.RefDeltas;
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas; cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
@@ -105,7 +108,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
cm.SetupSegmentationDequant(); cm.SetupSegmentationDequant();
cm.SetupScaleFactors(); cm.SetupScaleFactors();
SetMvs(ref cm, mvsIn); cm.SetMvs(mvsIn);
if (cm.Lf.FilterLevel != 0 && cm.SkipLoopFilter == 0)
{
LoopFilter.LoopFilterFrameInit(ref cm, cm.Lf.FilterLevel);
}
fixed (byte* dataPtr = bitstream) fixed (byte* dataPtr = bitstream)
{ {
@@ -114,10 +122,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (maxThreads > 1 && tileRows == 1 && tileCols > 1) if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
{ {
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads); DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
LoopFilter.LoopFilterFrameMt(
ref cm.Mb.CurBuf,
ref cm,
ref cm.Mb,
cm.Lf.FilterLevel,
false,
false,
maxThreads);
} }
else else
{ {
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length)); DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
LoopFilter.LoopFilterFrame(
ref cm.Mb.CurBuf,
ref cm,
ref cm.Mb,
cm.Lf.FilterLevel,
false,
false);
} }
} }
catch (InternalErrorException) catch (InternalErrorException)
@@ -126,7 +151,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
GetMvs(ref cm, mvsOut); cm.GetMvs(mvsOut);
cm.FreeTileWorkerData(_allocator); cm.FreeTileWorkerData(_allocator);
cm.FreeContextBuffers(_allocator); cm.FreeContextBuffers(_allocator);
@@ -134,48 +159,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return true; return true;
} }
private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs) public void Dispose()
{ {
if (mvs.Length > cm.PrevFrameMvs.Length) _allocator.Dispose();
{
throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
} }
for (int i = 0; i < mvs.Length; i++)
{
ref var mv = ref cm.PrevFrameMvs[i];
mv.Mv[0].Row = mvs[i].Mvs[0].Row;
mv.Mv[0].Col = mvs[i].Mvs[0].Col;
mv.Mv[1].Row = mvs[i].Mvs[1].Row;
mv.Mv[1].Col = mvs[i].Mvs[1].Col;
mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
}
}
private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
{
if (mvs.Length > cm.CurFrameMvs.Length)
{
throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
}
for (int i = 0; i < mvs.Length; i++)
{
ref var mv = ref cm.CurFrameMvs[i];
mvs[i].Mvs[0].Row = mv.Mv[0].Row;
mvs[i].Mvs[0].Col = mv.Mv[0].Col;
mvs[i].Mvs[1].Row = mv.Mv[1].Row;
mvs[i].Mvs[1].Col = mv.Mv[1].Col;
mvs[i].RefFrames[0] = mv.RefFrame[0];
mvs[i].RefFrames[1] = mv.RefFrame[1];
}
}
public void Dispose() => _allocator.Dispose();
} }
} }

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Dsp; using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
@@ -17,26 +17,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c) private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
{ {
const int MaxNeighbors = 2; const int maxNeighbors = 2;
return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1; return (1 + tokenCache[neighbors[(maxNeighbors * c) + 0]] +
} tokenCache[neighbors[(maxNeighbors * c) + 1]]) >> 1;
private static int ReadCoeff(
ref Reader r,
ReadOnlySpan<byte> probs,
int n,
ref ulong value,
ref int count,
ref uint range)
{
int i, val = 0;
for (i = 0; i < n; ++i)
{
val = (val << 1) | r.ReadBool(probs[i], ref value, ref count, ref range);
}
return val;
} }
private static int DecodeCoefs( private static int DecodeCoefs(
@@ -58,13 +42,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr]; ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
Span<byte> tokenCache = stackalloc byte[32 * 32]; Span<byte> tokenCache = stackalloc byte[32 * 32];
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize); ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0; int dqShift = txSize == TxSize.Tx32x32 ? 1 : 0;
int v; int v;
short dqv = dq[0]; short dqv = dq[0];
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12) ReadOnlySpan<byte> cat6Prob = xd.Bd == 12
? Luts.Vp9Cat6ProbHigh12 ? Luts.Cat6ProbHigh12
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob; : xd.Bd == 10
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14; ? Luts.Cat6ProbHigh12.Slice(2)
: Luts.Cat6Prob;
int cat6Bits = xd.Bd == 12 ? 18 : xd.Bd == 10 ? 16 : 14;
// Keep value, range, and count as locals. The compiler produces better // Keep value, range, and count as locals. The compiler produces better
// results with the locals than using r directly. // results with the locals than using r directly.
ulong value = r.Value; ulong value = r.Value;
@@ -75,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int val = -1; int val = -1;
band = bandTranslate[0]; band = bandTranslate[0];
bandTranslate = bandTranslate[1..]; bandTranslate = bandTranslate.Slice(1);
ref Array3<byte> prob = ref coefProbs[band][ctx]; ref Array3<byte> prob = ref coefProbs[band][ctx];
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
@@ -107,18 +93,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value; r.Value = value;
r.Range = range; r.Range = range;
r.Count = count; r.Count = count;
return c; // Zero tokens at the end (no eob token) return c; // Zero tokens at the end (no eob token)
} }
ctx = GetCoefContext(nb, tokenCache, c); ctx = GetCoefContext(nb, tokenCache, c);
band = bandTranslate[0]; band = bandTranslate[0];
bandTranslate = bandTranslate[1..]; bandTranslate = bandTranslate.Slice(1);
prob = ref coefProbs[band][ctx]; prob = ref coefProbs[band][ctx];
} }
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0) if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
{ {
ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[prob[Constants.PivotNode] - 1]; ReadOnlySpan<byte> p = Luts.Pareto8Full[prob[Constants.PivotNode] - 1];
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken]; ++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
@@ -133,20 +119,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0) if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
{ {
val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range); val = Constants.Cat6MinVal + r.ReadCoeff(cat6Prob, cat6Bits, ref value,
ref count, ref range);
} }
else else
{ {
val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range); val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value,
ref count, ref range);
} }
} }
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0) else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
{ {
val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range); val = Constants.Cat4MinVal + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count,
ref range);
} }
else else
{ {
val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range); val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count,
ref range);
} }
} }
else else
@@ -154,13 +144,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tokenCache[scan[c]] = 4; tokenCache[scan[c]] = 4;
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0) if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
{ {
val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range); val = Constants.Cat2MinVal + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count,
ref range);
} }
else else
{ {
val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range); val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count,
ref range);
} }
} }
// Val may use 18-bits // Val may use 18-bits
v = (int)(((long)val * dqv) >> dqShift); v = (int)(((long)val * dqv) >> dqShift);
} }
@@ -188,7 +181,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tokenCache[scan[c]] = 1; tokenCache[scan[c]] = 1;
v = dqv >> dqShift; v = dqv >> dqShift;
} }
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v, xd.Bd);
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v,
xd.Bd);
++c; ++c;
ctx = GetCoefContext(nb, tokenCache, c); ctx = GetCoefContext(nb, tokenCache, c);
dqv = dq[1]; dqv = dq[1];
@@ -197,11 +192,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value; r.Value = value;
r.Range = range; r.Range = range;
r.Count = count; r.Count = count;
return c; return c;
} }
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks) private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y,
uint txSizeInBlocks)
{ {
if (xd.MaxBlocksWide != 0) if (xd.MaxBlocksWide != 0)
{ {
@@ -210,6 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8; ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
} }
} }
if (xd.MaxBlocksHigh != 0) if (xd.MaxBlocksHigh != 0)
{ {
if (txSizeInBlocks + y > xd.MaxBlocksHigh) if (txSizeInBlocks + y > xd.MaxBlocksHigh)
@@ -238,8 +234,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane]; ref MacroBlockDPlane pd = ref xd.Plane[plane];
ref Array2<short> dequant = ref pd.SegDequant[segId]; ref Array2<short> dequant = ref pd.SegDequant[segId];
int eob; int eob;
Span<sbyte> a = pd.AboveContext.AsSpan()[x..]; Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
Span<sbyte> l = pd.LeftContext.AsSpan()[y..]; Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
int ctx; int ctx;
int ctxShiftA = 0; int ctxShiftA = 0;
int ctxShiftL = 0; int ctxShiftL = 0;

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -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;
using System.Diagnostics; using System.Diagnostics;
@@ -12,10 +12,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
Debug.Assert(den != 0); Debug.Assert(den != 0);
{ {
int p = (int)(((ulong)num * 256 + (den >> 1)) / den); int p = (int)((((ulong)num * 256) + (den >> 1)) / den);
// (p > 255) ? 255 : (p < 1) ? 1 : p; // (p > 255) ? 255 : (p < 1) ? 1 : p;
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0); int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
return (byte)clippedProb; return (byte)clippedProb;
} }
} }
@@ -23,13 +22,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
/* This function assumes prob1 and prob2 are already within [1,255] range. */ /* This function assumes prob1 and prob2 are already within [1,255] range. */
public static byte WeightedProb(int prob1, int prob2, int factor) public static byte WeightedProb(int prob1, int prob2, int factor)
{ {
return (byte)BitUtils.RoundPowerOfTwo(prob1 * (256 - factor) + prob2 * factor, 8); return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
} }
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT; // MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
private static readonly uint[] _countToUpdateFactor = { private static readonly uint[] CountToUpdateFactor =
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, {
70, 76, 83, 89, 96, 102, 108, 115, 121, 128, 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; private const int ModeMvCountSat = 20;
@@ -41,15 +40,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
return preProb; return preProb;
} }
else
{
uint count = Math.Min(den, ModeMvCountSat);
uint factor = _countToUpdateFactor[(int)count];
byte prob = GetProb(ct0, den);
uint count = Math.Min(den, ModeMvCountSat);
uint factor = CountToUpdateFactor[(int)count];
byte prob = GetProb(ct0, den);
return WeightedProb(preProb, prob, (int)factor); return WeightedProb(preProb, prob, (int)factor);
} }
}
private static uint TreeMergeProbsImpl( private static uint TreeMergeProbsImpl(
uint i, uint i,
@@ -59,15 +55,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<byte> probs) Span<byte> probs)
{ {
int l = tree[i]; int l = tree[i];
uint leftCount = (l <= 0) ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs); uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
int r = tree[i + 1]; int r = tree[i + 1];
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs); uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount); probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
return leftCount + rightCount; return leftCount + rightCount;
} }
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, Span<byte> probs) public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
Span<byte> probs)
{ {
TreeMergeProbsImpl(0, tree, preProbs, counts, 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;
using System.Buffers.Binary; using System.Buffers.Binary;
@@ -6,18 +7,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
internal struct Reader internal struct Reader
{ {
private static readonly byte[] _norm = { private static readonly byte[] Norm =
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, {
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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}; };
private const int BdValueSize = sizeof(ulong) * 8; private const int BdValueSize = sizeof(ulong) * 8;
// This is meant to be a large, positive constant that can still be efficiently // This is meant to be a large, positive constant that can still be efficiently
@@ -36,17 +37,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
return true; return true;
} }
else
{
_buffer = new ArrayPtr<byte>(ref buffer[0], size); _buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0; Value = 0;
Count = -8; Count = -8;
Range = 255; Range = 255;
Fill(); Fill();
return ReadBit() != 0; // Marker bit return ReadBit() != 0; // Marker bit
} }
}
private void Fill() private void Fill()
{ {
@@ -65,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer); ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
nv = bigEndianValues >> (BdValueSize - bits); nv = bigEndianValues >> (BdValueSize - bits);
count += bits; count += bits;
buffer = buffer[(bits >> 3)..]; buffer = buffer.Slice(bits >> 3);
value = Value | (nv << (shift & 0x7)); value = Value | (nv << (shift & 0x7));
} }
else else
@@ -84,7 +82,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
count += 8; count += 8;
value |= (ulong)buffer[0] << shift; value |= (ulong)buffer[0] << shift;
buffer = buffer[1..]; buffer = buffer.Slice(1);
shift -= 8; shift -= 8;
} }
} }
@@ -98,7 +96,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count; Count = count;
} }
public readonly bool HasError() public bool HasError()
{ {
// Check if we have reached the end of the buffer. // Check if we have reached the end of the buffer.
// //
@@ -124,7 +122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigsplit; ulong bigsplit;
int count; int count;
uint range; uint range;
uint split = (Range * (uint)prob + (256 - (uint)prob)) >> 8; uint split = ((Range * (uint)prob) + (256 - (uint)prob)) >> 8;
if (Count < 0) if (Count < 0)
{ {
@@ -146,7 +144,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
{ {
int shift = _norm[range]; int shift = Norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -188,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public int ReadBool(int prob, ref ulong value, ref int count, ref uint range) public int ReadBool(int prob, ref ulong value, ref int count, ref uint range)
{ {
uint split = (range * (uint)prob + (256 - (uint)prob)) >> 8; uint split = ((range * (uint)prob) + (256 - (uint)prob)) >> 8;
ulong bigsplit = (ulong)split << (BdValueSize - 8); ulong bigsplit = (ulong)split << (BdValueSize - 8);
if (count < 0) if (count < 0)
@@ -202,19 +200,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit) if (value >= bigsplit)
{ {
range -= split; range = range - split;
value -= bigsplit; value = value - bigsplit;
{ {
int shift = _norm[range]; int shift = Norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
} }
return 1; return 1;
} }
range = split; range = split;
{ {
int shift = _norm[range]; int shift = Norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -230,7 +229,82 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count -= 8; Count -= 8;
_buffer = _buffer.Slice(-1); _buffer = _buffer.Slice(-1);
} }
return _buffer; return _buffer;
} }
private int DecodeUniform()
{
const int l = 8;
const int m = (1 << l) - 191;
int v = ReadLiteral(l - 1);
return v < m ? v : (v << 1) - m + ReadBit();
}
public int DecodeTermSubexp()
{
if (ReadBit() == 0)
{
return ReadLiteral(4);
}
if (ReadBit() == 0)
{
return ReadLiteral(4) + 16;
}
if (ReadBit() == 0)
{
return ReadLiteral(5) + 32;
}
return DecodeUniform() + 64;
}
public TxMode ReadTxMode()
{
TxMode txMode = (TxMode)ReadLiteral(2);
if (txMode == TxMode.Allow32x32)
{
txMode += ReadBit();
}
return txMode;
}
public int ReadCoeff(
ReadOnlySpan<byte> probs,
int n,
ref ulong value,
ref int count,
ref uint range)
{
int val = 0;
for (int i = 0; i < n; ++i)
{
val = (val << 1) | ReadBool(probs[i], ref value, ref count, ref range);
}
return val;
}
public void DiffUpdateProb(ref byte p)
{
if (Read(Entropy.DiffUpdateProb) != 0)
{
p = (byte)DSubExp.InvRemapProb(DecodeTermSubexp(), p);
}
}
public void UpdateMvProbs(Span<byte> p, int n)
{
for (int i = 0; i < n; ++i)
{
if (Read(EntropyMv.UpdateProb) != 0)
{
p[i] = (byte)((ReadLiteral(7) << 1) | 1);
}
}
}
} }
} }

View File

@@ -13,42 +13,42 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// for (int i = 1; i < 32; ++i) // for (int i = 1; i < 32; ++i)
// Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64))); // Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64)));
// Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64) // Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64)
public const short CosPi1_64 = 16364; public const short CosPi164 = 16364;
public const short CosPi2_64 = 16305; public const short CosPi264 = 16305;
public const short CosPi3_64 = 16207; public const short CosPi364 = 16207;
public const short CosPi4_64 = 16069; public const short CosPi464 = 16069;
public const short CosPi5_64 = 15893; public const short CosPi564 = 15893;
public const short CosPi6_64 = 15679; public const short CosPi664 = 15679;
public const short CosPi7_64 = 15426; public const short CosPi764 = 15426;
public const short CosPi8_64 = 15137; public const short CosPi864 = 15137;
public const short CosPi9_64 = 14811; public const short CosPi964 = 14811;
public const short CosPi10_64 = 14449; public const short CosPi1064 = 14449;
public const short CosPi11_64 = 14053; public const short CosPi1164 = 14053;
public const short CosPi12_64 = 13623; public const short CosPi1264 = 13623;
public const short CosPi13_64 = 13160; public const short CosPi1364 = 13160;
public const short CosPi14_64 = 12665; public const short CosPi1464 = 12665;
public const short CosPi15_64 = 12140; public const short CosPi1564 = 12140;
public const short CosPi16_64 = 11585; public const short CosPi1664 = 11585;
public const short CosPi17_64 = 11003; public const short CosPi1764 = 11003;
public const short CosPi18_64 = 10394; public const short CosPi1864 = 10394;
public const short CosPi19_64 = 9760; public const short CosPi1964 = 9760;
public const short CosPi20_64 = 9102; public const short CosPi2064 = 9102;
public const short CosPi21_64 = 8423; public const short CosPi2164 = 8423;
public const short CosPi22_64 = 7723; public const short CosPi2264 = 7723;
public const short CosPi23_64 = 7005; public const short CosPi2364 = 7005;
public const short CosPi24_64 = 6270; public const short CosPi2464 = 6270;
public const short CosPi25_64 = 5520; public const short CosPi2564 = 5520;
public const short CosPi26_64 = 4756; public const short CosPi2664 = 4756;
public const short CosPi27_64 = 3981; public const short CosPi2764 = 3981;
public const short CosPi28_64 = 3196; public const short CosPi2864 = 3196;
public const short CosPi29_64 = 2404; public const short CosPi2964 = 2404;
public const short CosPi30_64 = 1606; public const short CosPi3064 = 1606;
public const short CosPi31_64 = 804; public const short CosPi3164 = 804;
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3 // 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
public const short SinPi1_9 = 5283; public const short SinPi19 = 5283;
public const short SinPi2_9 = 9929; public const short SinPi29 = 9929;
public const short SinPi3_9 = 13377; public const short SinPi39 = 13377;
public const short SinPi4_9 = 15212; 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 Ryujinx.Graphics.Nvdec.Vp9.Types;
using System; using System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.InvTxfm;
@@ -8,11 +8,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
internal static class Idct internal static class Idct
{ {
private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output); private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output);
private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd); private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd);
private struct Transform2D private struct Transform2D
{ {
public 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) public Transform2D(Transform1D cols, Transform1D rows)
{ {
@@ -23,7 +25,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct HighbdTransform2D 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) 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(Idct4, Idct4), // DCT_DCT = 0
new(Iadst4, Idct4), // ADST_DCT = 1 new(Iadst4, Idct4), // ADST_DCT = 1
new(Idct4, Iadst4), // DCT_ADST = 2 new(Idct4, Iadst4), // DCT_ADST = 2
new(Iadst4, Iadst4), // ADST_ADST = 3 new(Iadst4, Iadst4) // ADST_ADST = 3
}; };
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[4 * 4]; Span<int> output = stackalloc int[4 * 4];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[4]; Span<int> tempIn = stackalloc int[4];
Span<int> tempOut = stackalloc int[4]; Span<int> tempOut = stackalloc int[4];
// Inverse transform row vectors // Inverse transform row vectors
for (i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
_iht4[txType].Rows(input, outptr); Iht4[txType].Rows(input, outptr);
input = input[4..]; input = input.Slice(4);
outptr = outptr[4..]; outptr = outptr.Slice(4);
} }
// Inverse transform column vectors // 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); Iht4[txType].Cols(tempIn, tempOut);
for (j = 0; j < 4; ++j) 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(Idct8, Idct8), // DCT_DCT = 0
new(Iadst8, Idct8), // ADST_DCT = 1 new(Iadst8, Idct8), // ADST_DCT = 1
new(Idct8, Iadst8), // DCT_ADST = 2 new(Idct8, Iadst8), // DCT_ADST = 2
new(Iadst8, Iadst8), // ADST_ADST = 3 new(Iadst8, Iadst8) // ADST_ADST = 3
}; };
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[8 * 8]; Span<int> output = stackalloc int[8 * 8];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
Transform2D ht = _iht8[txType]; Transform2D ht = Iht8[txType];
// Inverse transform row vectors // Inverse transform row vectors
for (i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input[8..]; input = input.Slice(8);
outptr = outptr[8..]; outptr = outptr.Slice(8);
} }
// Inverse transform column vectors // 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); 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(Idct16, Idct16), // DCT_DCT = 0
new(Iadst16, Idct16), // ADST_DCT = 1 new(Iadst16, Idct16), // ADST_DCT = 1
new(Idct16, Iadst16), // DCT_ADST = 2 new(Idct16, Iadst16), // DCT_ADST = 2
new(Iadst16, Iadst16), // ADST_ADST = 3 new(Iadst16, Iadst16) // ADST_ADST = 3
}; };
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType) public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
{ {
int i, j;
Span<int> output = stackalloc int[16 * 16]; Span<int> output = stackalloc int[16 * 16];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
Transform2D ht = _iht16[txType]; Transform2D ht = Iht16[txType];
// Rows // Rows
for (i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input[16..]; input = input.Slice(16);
outptr = outptr[16..]; outptr = outptr.Slice(16);
} }
// Columns // 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); 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));
} }
} }
} }
@@ -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(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1 new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2 new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3 new(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
}; };
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd) public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
{ {
int i, j;
Span<int> output = stackalloc int[4 * 4]; Span<int> output = stackalloc int[4 * 4];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[4]; Span<int> tempIn = stackalloc int[4];
Span<int> tempOut = stackalloc int[4]; Span<int> tempOut = stackalloc int[4];
// Inverse transform row vectors. // Inverse transform row vectors.
for (i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
_highbdIht4[txType].Rows(input, outptr, bd); HighbdIht4[txType].Rows(input, outptr, bd);
input = input[4..]; input = input.Slice(4);
outptr = outptr[4..]; outptr = outptr.Slice(4);
} }
// Inverse transform column vectors. // 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); HighbdIht4[txType].Cols(tempIn, tempOut, bd);
for (j = 0; j < 4; ++j) 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(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1 new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2 new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3 new(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
}; };
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd) public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
{ {
int i, j;
Span<int> output = stackalloc int[8 * 8]; Span<int> output = stackalloc int[8 * 8];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
HighbdTransform2D ht = _highIht8[txType]; HighbdTransform2D ht = HighIht8[txType];
// Inverse transform row vectors. // Inverse transform row vectors.
for (i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input[8..]; input = input.Slice(8);
outptr = output[8..]; outptr = output.Slice(8);
} }
// Inverse transform column vectors. // 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); 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(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1 new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2 new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3 new(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
}; };
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, 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> output = stackalloc int[16 * 16];
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
HighbdTransform2D ht = _highIht16[txType]; HighbdTransform2D ht = HighIht16[txType];
// Rows // Rows
for (i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input[16..]; input = input.Slice(16);
outptr = output[16..]; outptr = output.Slice(16);
} }
// Columns // 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); 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 // DC only DCT coefficient
if (eob == 1) if (eob == 1)
{ {
Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd); VpxHighbdidct8x81AddC(input, dest, stride, bd);
} }
else if (eob <= 12) else if (eob <= 12)
{ {
@@ -491,7 +501,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
// Iht // 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) 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) 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) if (txType == TxType.DctDct)
{ {

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
@@ -13,7 +13,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // both edges available {
// both edges available
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef()) if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
{ {
// Neither edge uses comp pred (0/1) // Neither edge uses comp pred (0/1)
@@ -23,12 +24,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else if (!xd.AboveMi.Value.HasSecondRef()) else if (!xd.AboveMi.Value.HasSecondRef())
{ {
// One of two edges uses comp pred (2/3) // 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()) else if (!xd.LeftMi.Value.HasSecondRef())
{ {
// One of two edges uses comp pred (2/3) // 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) else // Both edges use comp pred (4)
{ {
@@ -36,7 +40,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) 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; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
@@ -51,11 +56,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available (1) {
// No edges available (1)
ctx = 1; ctx = 1;
} }
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx; return ctx;
} }
@@ -71,29 +77,33 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int varRefIdx = fixRefIdx == 0 ? 1 : 0; int varRefIdx = fixRefIdx == 0 ? 1 : 0;
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available {
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra (2) {
// Intra/Intra (2)
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) else if (aboveIntra || leftIntra)
{ // Intra/Inter {
// Intra/Inter
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) // single pred (1/3) 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) 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 else
{ // Inter/Inter {
// Inter/Inter
bool lSg = !xd.LeftMi.Value.HasSecondRef(); bool lSg = !xd.LeftMi.Value.HasSecondRef();
bool aSg = !xd.AboveMi.Value.HasSecondRef(); bool aSg = !xd.AboveMi.Value.HasSecondRef();
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx]; sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
@@ -104,7 +114,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 0; predContext = 0;
} }
else if (lSg && aSg) else if (lSg && aSg)
{ // Single/Single {
// Single/Single
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) || if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0])) (vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
{ {
@@ -120,7 +131,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (lSg || aSg) else if (lSg || aSg)
{ // Single/Comp {
// Single/Comp
sbyte vrfc = lSg ? vrfa : vrfl; sbyte vrfc = lSg ? vrfa : vrfl;
sbyte rfs = aSg ? vrfa : vrfl; sbyte rfs = aSg ? vrfa : vrfl;
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1]) if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
@@ -137,7 +149,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (vrfa == vrfl) else if (vrfa == vrfl)
{ // Comp/Comp {
// Comp/Comp
predContext = 4; predContext = 4;
} }
else else
@@ -147,7 +160,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) 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; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock()) if (!edgeMi.IsInterBlock())
@@ -167,11 +181,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available (2) {
// No edges available (2)
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -183,16 +198,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available {
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra {
// Intra/Intra
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) 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; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
@@ -201,11 +219,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else else
{ {
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame || predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0); edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
} }
} }
else else
{ // Inter/Inter {
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef(); bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef(); bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0]; sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -216,7 +237,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (aboveHasSecond && leftHasSecond) if (aboveHasSecond && leftHasSecond)
{ {
predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame || 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) else if (aboveHasSecond || leftHasSecond)
{ {
@@ -230,24 +253,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
else else
{ {
predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0); predContext = crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0;
} }
} }
else 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) 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; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock()) if (!edgeMi.IsInterBlock())
{ // Intra {
// Intra
predContext = 2; predContext = 2;
} }
else else
{ // Inter {
// Inter
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0); predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
@@ -255,16 +282,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else else
{ {
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame || predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0); edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
} }
} }
} }
else else
{ // No edges available {
// No edges available
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -277,16 +307,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available {
// Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra {
// Intra/Intra
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) 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; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
@@ -301,12 +334,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
else else
{ {
predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame || predContext = 1 + (2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0); edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0));
} }
} }
else else
{ // Inter/Inter {
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef(); bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef(); bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0]; sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -319,7 +355,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (above0 == left0 && above1 == left1) if (above0 == left0 && above1 == left1)
{ {
predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame || 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 else
{ {
@@ -342,7 +380,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
else else
{ {
predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0); predContext =
1 + (2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0));
} }
} }
else else
@@ -353,18 +392,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame) 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); predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
} }
else 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) 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; 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())) if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
@@ -378,15 +419,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else else
{ {
predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame || predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0); edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0);
} }
} }
else else
{ // No edges available (2) {
// No edges available (2)
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; 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; using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal static class QuantCommon internal static class QuantCommon
{ {
public const int MinQ = 0;
public const int MaxQ = 255; public const int MaxQ = 255;
public const int QindexBits = 8;
private static readonly short[] _dcQlookup = { 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, 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,
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, 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,
43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 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,
54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 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,
66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, 185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134, 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330,
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626,
205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247, 640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098,
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 1139, 1184, 1232, 1282, 1336
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 = { 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, 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, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, 136, 140, 143, 147, 151, 155, 159, 163,
136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, 166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241,
185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314,
233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424,
280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, 430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576,
324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782,
394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, 795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045,
472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323,
576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670,
698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831, 1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159,
844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347
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 = { 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, 4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 251,
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
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,
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165,
768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919, 1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444,
934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862,
1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, 1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400,
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076,
1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013,
1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319,
2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085,
2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, 8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946,
3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943,
3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 17575, 18237, 18949, 19718, 20521, 21387
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 = { 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, 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,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 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,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 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,
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227,
98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329,
120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483,
146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715,
182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046,
227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451,
285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, 1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828
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 = { 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, 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, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, 154, 158, 163, 168, 172, 177, 181, 186,
154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, 190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280,
213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371,
271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514,
328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, 523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725,
384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018,
474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571, 1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895,
725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603,
905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118, 2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591,
1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972,
1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900,
1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 7036, 7172, 7312
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 = { 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, 4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 280,
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
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,
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335,
884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660,
1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216,
1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693, 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941,
1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352,
2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290,
2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943, 7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309,
3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, 13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726,
4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662,
5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247
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) public static short DcQuant(int qindex, int delta, BitDepth bitDepth)
{ {
switch (bitDepth) switch (bitDepth)
{ {
case BitDepth.Bits8: case BitDepth.Bits8: return DcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10: case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12:
return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
default: 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; return -1;
} }
} }
@@ -175,30 +130,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (bitDepth) switch (bitDepth)
{ {
case BitDepth.Bits8: case BitDepth.Bits8: return AcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits10: case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12:
return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
default: 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; 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 Ryujinx.Graphics.Nvdec.Vp9.Types;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
@@ -77,65 +77,38 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
bd); bd);
} }
private static int RoundMvCompQ4(int value) public static int RoundMvCompQ4(int value)
{ {
return (value < 0 ? value - 2 : value + 2) / 4; return (value < 0 ? value - 2 : value + 2) / 4;
} }
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx) public static int RoundMvCompQ2(int value)
{
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)
{ {
return (value < 0 ? value - 1 : value + 1) / 2; 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) 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 // 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 // are used for reconstruction, the subpel part of the MV can be
// discarded and the MV limited to 16 pixels with equivalent results. // 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 spelRight = spelLeft - SubpelShifts;
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits; int spelTop = (Constants.InterpExtend + bh) << SubpelBits;
int spelBottom = spelTop - SubpelShifts; int spelBottom = spelTop - SubpelShifts;
Mv clampedMv = new() Mv clampedMv = new()
{ {
Row = (short)(srcMv.Row * (1 << (1 - ssY))), Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX)))
Col = (short)(srcMv.Col * (1 << (1 - ssX))),
}; };
Debug.Assert(ssX <= 1); Debug.Assert(ssX <= 1);
Debug.Assert(ssY <= 1); Debug.Assert(ssY <= 1);
clampedMv.ClampMv( clampedMv.Clamp(
xd.MbToLeftEdge * (1 << (1 - ssX)) - spelLeft, (xd.MbToLeftEdge * (1 << (1 - ssX))) - spelLeft,
xd.MbToRightEdge * (1 << (1 - ssX)) + spelRight, (xd.MbToRightEdge * (1 << (1 - ssX))) + spelRight,
xd.MbToTopEdge * (1 << (1 - ssY)) - spelTop, (xd.MbToTopEdge * (1 << (1 - ssY))) - spelTop,
xd.MbToBottomEdge * (1 << (1 - ssY)) + spelBottom); (xd.MbToBottomEdge * (1 << (1 - ssY))) + spelBottom);
return clampedMv; return clampedMv;
} }
@@ -150,18 +123,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
res = mi.Bmi[block].Mv[refr]; res = mi.Bmi[block].Mv[refr];
break; break;
case 1: case 1:
res = MiMvPredQ2(ref mi, refr, block, block + 2); res = mi.MvPredQ2(refr, block, block + 2);
break; break;
case 2: case 2:
res = MiMvPredQ2(ref mi, refr, block, block + 1); res = mi.MvPredQ2(refr, block, block + 1);
break; break;
case 3: case 3:
res = MiMvPredQ4(ref mi, refr); res = mi.MvPredQ4(refr);
break; break;
default: default:
Debug.Assert(ssIdx <= 3 && ssIdx >= 0); Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
break; break;
} }
return res; return res;
} }
@@ -169,8 +143,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset; int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset; int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
return (y * stride) + x;
return y * stride + x;
} }
private static void SetupPredPlanes( private static void SetupPredPlanes(
@@ -203,12 +176,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
strides[0] = src.Stride; strides[0] = src.Stride;
strides[1] = src.UvStride; strides[1] = src.UvStride;
strides[2] = 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]; 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,12 +203,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
strides[0] = src.Stride; strides[0] = src.Stride;
strides[1] = src.UvStride; strides[1] = src.UvStride;
strides[2] = 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]; 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 Ryujinx.Graphics.Nvdec.Vp9.Types;
using System; using System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred;
@@ -7,7 +7,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal static class ReconIntra internal static class ReconIntra
{ {
public static readonly TxType[] IntraModeToTxTypeLookup = { public static readonly TxType[] IntraModeToTxTypeLookup =
{
TxType.DctDct, // DC TxType.DctDct, // DC
TxType.AdstDct, // V TxType.AdstDct, // V
TxType.DctAdst, // H TxType.DctAdst, // H
@@ -17,7 +18,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
TxType.DctAdst, // D153 TxType.DctAdst, // D153
TxType.DctAdst, // D207 TxType.DctAdst, // D207
TxType.AdstDct, // D63 TxType.AdstDct, // D63
TxType.AdstAdst, // TM TxType.AdstAdst // TM
}; };
private const int NeedLeft = 1 << 1; private const int NeedLeft = 1 << 1;
@@ -35,231 +36,123 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
NeedLeft | NeedAbove, // D153 NeedLeft | NeedAbove, // D153
NeedLeft, // D207 NeedLeft, // D207
NeedAboveRight, // D63 NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM NeedLeft | NeedAbove // TM
}; };
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left); private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
private static readonly unsafe IntraPredFn[][] _pred = { private static readonly unsafe IntraPredFn[][] Pred =
new IntraPredFn[]
{ {
null, new IntraPredFn[] { null, null, null, null },
null, new IntraPredFn[] { VPredictor4x4, VPredictor8x8, VPredictor16x16, VPredictor32x32 },
null, new IntraPredFn[] { HPredictor4x4, HPredictor8x8, HPredictor16x16, HPredictor32x32 },
null, new IntraPredFn[] { D45Predictor4x4, D45Predictor8x8, D45Predictor16x16, D45Predictor32x32 },
}, new IntraPredFn[] { D135Predictor4x4, D135Predictor8x8, D135Predictor16x16, D135Predictor32x32 },
new IntraPredFn[] new IntraPredFn[] { D117Predictor4x4, D117Predictor8x8, D117Predictor16x16, D117Predictor32x32 },
{ new IntraPredFn[] { D153Predictor4x4, D153Predictor8x8, D153Predictor16x16, D153Predictor32x32 },
VPredictor4x4, new IntraPredFn[] { D207Predictor4x4, D207Predictor8x8, D207Predictor16x16, D207Predictor32x32 },
VPredictor8x8, new IntraPredFn[] { D63Predictor4x4, D63Predictor8x8, D63Predictor16x16, D63Predictor32x32 },
VPredictor16x16, new IntraPredFn[] { TmPredictor4x4, TmPredictor8x8, TmPredictor16x16, TmPredictor32x32 }
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[]
{ {
new IntraPredFn[] new IntraPredFn[]
{ {
Dc128Predictor4x4, Dc128Predictor4x4, Dc128Predictor8x8, Dc128Predictor16x16, Dc128Predictor32x32
Dc128Predictor8x8,
Dc128Predictor16x16,
Dc128Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
DcTopPredictor4x4, DcTopPredictor4x4, DcTopPredictor8x8, DcTopPredictor16x16, DcTopPredictor32x32
DcTopPredictor8x8, }
DcTopPredictor16x16,
DcTopPredictor32x32,
},
}, },
new[] new[]
{ {
new IntraPredFn[] new IntraPredFn[]
{ {
DcLeftPredictor4x4, DcLeftPredictor4x4, DcLeftPredictor8x8, DcLeftPredictor16x16, DcLeftPredictor32x32
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 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[] new IntraHighPredFn[]
{ {
null, HighbdVPredictor4x4, HighbdVPredictor8x8, HighbdVPredictor16x16, HighbdVPredictor32x32
null,
null,
null,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdVPredictor4x4, HighbdHPredictor4x4, HighbdHPredictor8x8, HighbdHPredictor16x16, HighbdHPredictor32x32
HighbdVPredictor8x8,
HighbdVPredictor16x16,
HighbdVPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdHPredictor4x4, HighbdD45Predictor4x4, HighbdD45Predictor8x8, HighbdD45Predictor16x16, HighbdD45Predictor32x32
HighbdHPredictor8x8,
HighbdHPredictor16x16,
HighbdHPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD45Predictor4x4, HighbdD135Predictor4x4, HighbdD135Predictor8x8, HighbdD135Predictor16x16,
HighbdD45Predictor8x8, HighbdD135Predictor32x32
HighbdD45Predictor16x16,
HighbdD45Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD135Predictor4x4, HighbdD117Predictor4x4, HighbdD117Predictor8x8, HighbdD117Predictor16x16,
HighbdD135Predictor8x8, HighbdD117Predictor32x32
HighbdD135Predictor16x16,
HighbdD135Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD117Predictor4x4, HighbdD153Predictor4x4, HighbdD153Predictor8x8, HighbdD153Predictor16x16,
HighbdD117Predictor8x8, HighbdD153Predictor32x32
HighbdD117Predictor16x16,
HighbdD117Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD153Predictor4x4, HighbdD207Predictor4x4, HighbdD207Predictor8x8, HighbdD207Predictor16x16,
HighbdD153Predictor8x8, HighbdD207Predictor32x32
HighbdD153Predictor16x16,
HighbdD153Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD207Predictor4x4, HighbdD63Predictor4x4, HighbdD63Predictor8x8, HighbdD63Predictor16x16, HighbdD63Predictor32x32
HighbdD207Predictor8x8,
HighbdD207Predictor16x16,
HighbdD207Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD63Predictor4x4, HighbdTmPredictor4x4, HighbdTmPredictor8x8, HighbdTmPredictor16x16, HighbdTmPredictor32x32
HighbdD63Predictor8x8, }
HighbdD63Predictor16x16,
HighbdD63Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdTMPredictor4x4,
HighbdTMPredictor8x8,
HighbdTMPredictor16x16,
HighbdTMPredictor32x32,
},
}; };
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = { private static readonly unsafe IntraHighPredFn[][][] DcPredHigh =
{
new[] new[]
{ {
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDc128Predictor4x4, HighbdDc128Predictor4x4, HighbdDc128Predictor8x8, HighbdDc128Predictor16x16,
HighbdDc128Predictor8x8, HighbdDc128Predictor32x32
HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcTopPredictor4x4, HighbdDcTopPredictor4x4, HighbdDcTopPredictor8x8, HighbdDcTopPredictor16x16,
HighbdDcTopPredictor8x8, HighbdDcTopPredictor32x32
HighbdDcTopPredictor16x16, }
HighbdDcTopPredictor32x32,
},
}, },
new[] new[]
{ {
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor32x32
HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcPredictor4x4, HighbdDcPredictor4x4, HighbdDcPredictor8x8, HighbdDcPredictor16x16,
HighbdDcPredictor8x8, HighbdDcPredictor32x32
HighbdDcPredictor16x16, }
HighbdDcPredictor32x32, }
},
},
}; };
private static unsafe void BuildIntraPredictorsHigh( private static unsafe void BuildIntraPredictorsHigh(
@@ -327,7 +220,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
for (i = 0; i < bs; ++i) for (i = 0; i < bs; ++i)
{ {
leftCol[i] = refr[i * refStride - 1]; leftCol[i] = refr[(i * refStride) - 1];
} }
} }
else else
@@ -335,12 +228,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0; int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i) for (i = 0; i < extendBottom; ++i)
{ {
leftCol[i] = refr[i * refStride - 1]; leftCol[i] = refr[(i * refStride) - 1];
} }
for (; i < bs; ++i) 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 */ /* faster path if the block does not need extension */
for (i = 0; i < bs; ++i) 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); MemoryUtil.Copy(aboveRow, aboveRef, bs);
} }
} }
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1); aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
} }
else else
@@ -409,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0) if (xd.MbToRightEdge < 0)
{ {
/* slower path if the block needs border extension */ /* slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth) if (x0 + (2 * bs) <= frameWidth)
{ {
if (rightAvailable != 0 && bs == 4) if (rightAvailable != 0 && bs == 4)
{ {
@@ -427,7 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4) if (rightAvailable != 0 && bs == 4)
{ {
MemoryUtil.Copy(aboveRow, aboveRef, r); 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 else
{ {
@@ -439,8 +333,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int r = frameWidth - x0; int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r); 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); aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
} }
else else
@@ -476,11 +371,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict // Predict
if (mode == PredictionMode.DcPred) 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 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) for (i = 0; i < bs; ++i)
{ {
leftCol[i] = refr[i * refStride - 1]; leftCol[i] = refr[(i * refStride) - 1];
} }
} }
else else
@@ -552,12 +447,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0; int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i) for (i = 0; i < extendBottom; ++i)
{ {
leftCol[i] = refr[i * refStride - 1]; leftCol[i] = refr[(i * refStride) - 1];
} }
for (; i < bs; ++i) 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 */ /* Faster path if the block does not need extension */
for (i = 0; i < bs; ++i) 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); MemoryUtil.Copy(aboveRow, aboveRef, bs);
} }
} }
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129; aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
} }
else else
@@ -626,7 +522,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0) if (xd.MbToRightEdge < 0)
{ {
/* Slower path if the block needs border extension */ /* Slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth) if (x0 + (2 * bs) <= frameWidth)
{ {
if (rightAvailable != 0 && bs == 4) if (rightAvailable != 0 && bs == 4)
{ {
@@ -644,7 +540,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4) if (rightAvailable != 0 && bs == 4)
{ {
MemoryUtil.Copy(aboveRow, aboveRef, r); 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 else
{ {
@@ -656,7 +552,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int r = frameWidth - x0; int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r); 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 else
@@ -679,6 +575,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
} }
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129; aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
} }
else else
@@ -691,11 +588,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict // Predict
if (mode == PredictionMode.DcPred) if (mode == PredictionMode.DcPred)
{ {
_dcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol); DcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
} }
else 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 txw = 1 << (int)txSize;
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0; int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
int haveLeft = aoff != 0 || !xd.LeftMi.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 x = aoff * 4;
int y = loff * 4; int y = loff * 4;
@@ -736,9 +633,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
x, x,
y, y,
plane); plane);
return; return;
} }
BuildIntraPredictors( BuildIntraPredictors(
ref xd, ref xd,
refr, refr,

View File

@@ -12,9 +12,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public int BufEnd; public int BufEnd;
public Reader BitReader; public Reader BitReader;
public Vp9BackwardUpdates Counts; public Vp9BackwardUpdates Counts;
public MacroBlockD Xd; public MacroBlockD Xd;
/* dqcoeff are shared by all the planes. So planes must be decoded serially */ /* dqcoeff are shared by all the planes. So planes must be decoded serially */
public Array32<Array32<int>> Dqcoeff; public Array32<Array32<int>> Dqcoeff;
public InternalErrorInfo ErrorInfo; 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

@@ -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 internal enum BlockSize
{ {
Block4x4 = 0, Block4x4,
Block4x8 = 1, Block4x8,
Block8x4 = 2, Block8x4,
Block8x8 = 3, Block8x8,
Block8x16 = 4, Block8x16,
Block16x8 = 5, Block16x8,
Block16x16 = 6, Block16x16,
Block16x32 = 7, Block16x32,
Block32x16 = 8, Block32x16,
Block32x32 = 9, Block32x32,
Block32x64 = 10, Block32x64,
Block64x32 = 11, Block64x32,
Block64x64 = 12, Block64x64,
BlockSizes = 13, BlockSizes,
BlockInvalid = BlockSizes, BlockInvalid = BlockSizes
} }
} }

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

@@ -23,5 +23,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<LoopFilterMask> Lfm; public ArrayPtr<LoopFilterMask> Lfm;
public int LfmStride; 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

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

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types namespace Ryujinx.Graphics.Nvdec.Vp9.Types
@@ -32,11 +32,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode; 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 || 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]; 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; return RefFrame[1] > Constants.IntraFrame;
} }
private static readonly int[][] _idxNColumnToSubblock = { private static readonly int[][] IdxNColumnToSubblock =
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 }, {
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 }
}; };
// This function returns either the appropriate sub block or block's mv // 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) public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
{ {
return blockIdx >= 0 && SbType < BlockSize.Block8x8 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]; : 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

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
@@ -12,96 +12,86 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static ReadOnlySpan<byte> LogInBase2 => new byte[] 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, 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,
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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
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, 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,
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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 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,
7, 7, 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,
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, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 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,
8, 8, 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,
8, 8, 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,
8, 8, 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,
8, 8, 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,
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, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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 const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh; 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; 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) if (!offset.IsNull)
{ {
offset.Value = z - MvClassBase(c); offset.Value = z - ClassBase(c);
} }
return 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 */ 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; 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; counts.Classes[comp][c] += (uint)incr;
d = (o >> 3); /* Int mv data */ int d = o >> 3 /* Int mv data */;
f = (o >> 1) & 3; /* Fractional pel mv data */ int f = (o >> 1) & 3 /* Fractional pel mv data */;
e = (o & 1); /* High precision 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.Class0[comp][d] += (uint)incr;
counts.Class0Fp[comp][d][f] += (uint)incr; counts.Class0Fp[comp][d][f] += (uint)incr;
@@ -109,11 +99,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
} }
else else
{ {
int i;
int b = c + Constants.Class0Bits - 1; // Number of bits 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; 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) 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) if (!counts.IsNull)
{ {
MvJointType j = GetMvJoint(); MvJointType j = GetJoint();
++counts.Value.Joints[(int)j]; ++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); Col = (short)Math.Clamp(Col, minCol, maxCol);
Row = (short)Math.Clamp(Row, minRow, maxRow); 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( Clamp(
xd.MbToLeftEdge - MvBorder, xd.MbToLeftEdge - Border,
xd.MbToRightEdge + MvBorder, xd.MbToRightEdge + Border,
xd.MbToTopEdge - MvBorder, xd.MbToTopEdge - Border,
xd.MbToBottomEdge + MvBorder); xd.MbToBottomEdge + Border);
} }
public void LowerMvPrecision(bool allowHP) public void LowerPrecision(bool allowHp)
{ {
bool useHP = allowHP && UseMvHp(); bool useHp = allowHp && UseHp();
if (!useHP) if (!useHp)
{ {
if ((Row & 1) != 0) 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

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
internal struct RefBuffer internal struct RefBuffer
{ {
public const int InvalidIdx = -1; // Invalid buffer index.
public int Idx;
public Surface Buf; public Surface Buf;
public ScaleFactors Sf; 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 internal enum ReferenceMode
{ {
SingleReference = 0, Single,
CompoundReference = 1, Compound,
ReferenceModeSelect = 2, Select,
ReferenceModes = 3, ReferenceModes
} }
} }

View File

@@ -1,4 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter; using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter;
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal struct ScaleFactors internal struct ScaleFactors
{ {
private const int RefScaleShift = 14; private const int RefScaleShift = 14;
private const int RefNoScale = (1 << RefScaleShift); private const int RefNoScale = 1 << RefScaleShift;
private const int RefInvalidScale = -1; private const int RefInvalidScale = -1;
private unsafe delegate void ConvolveFn( private unsafe delegate void ConvolveFn(
@@ -38,255 +38,114 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int h, int h,
int bd); int bd);
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = { private static readonly unsafe ConvolveFn[][][] PredictX16Y16 =
{
new[] new[]
{ {
new ConvolveFn[] new ConvolveFn[] { ConvolveCopy, ConvolveAvg },
{ new ConvolveFn[] { Convolve8Vert, Convolve8AvgVert }
ConvolveCopy,
ConvolveAvg,
},
new ConvolveFn[]
{
Convolve8Vert,
Convolve8AvgVert,
},
}, },
new[] new[]
{ {
new ConvolveFn[] new ConvolveFn[] { Convolve8Horiz, Convolve8AvgHoriz },
{ new ConvolveFn[] { Convolve8, Convolve8Avg }
Convolve8Horiz, }
Convolve8AvgHoriz,
},
new ConvolveFn[]
{
Convolve8,
Convolve8Avg,
},
},
}; };
private static readonly unsafe ConvolveFn[][][] _predictX16 = { private static readonly unsafe ConvolveFn[][][] PredictX16 =
{
new[] new[]
{ {
new ConvolveFn[] new ConvolveFn[] { ScaledVert, ScaledAvgVert }, new ConvolveFn[] { ScaledVert, ScaledAvgVert }
{
ScaledVert,
ScaledAvgVert,
},
new ConvolveFn[]
{
ScaledVert,
ScaledAvgVert,
},
},
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
}, },
new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
}; };
private static readonly unsafe ConvolveFn[][][] _predictY16 = { private static readonly unsafe ConvolveFn[][][] PredictY16 =
new[]
{ {
new ConvolveFn[] new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
{ new[] { new ConvolveFn[] { ScaledHoriz, ScaledAvgHoriz }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
ScaledHoriz,
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
new[]
{
new ConvolveFn[]
{
ScaledHoriz,
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
}; };
private static readonly unsafe ConvolveFn[][][] _predict = { private static readonly unsafe ConvolveFn[][][] Predict =
new[]
{ {
new ConvolveFn[] new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } },
{ new[] { new ConvolveFn[] { Scaled2D, ScaledAvg2D }, new ConvolveFn[] { Scaled2D, ScaledAvg2D } }
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[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolveCopy, HighbdConvolveAvg },
{ new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
HighbdConvolveCopy,
HighbdConvolveAvg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
}, },
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8Horiz, }
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
}; };
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = { private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 =
{
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert },
{ new HighbdConvolveFn[] { HighbdConvolve8Vert, HighbdConvolve8AvgVert }
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert,
},
}, },
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8, }
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
}; };
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = { private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 =
{
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
}, },
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8Horiz, }
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
}; };
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = { private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict =
{
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
}, },
new[] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg },
{ new HighbdConvolveFn[] { HighbdConvolve8, HighbdConvolve8Avg }
HighbdConvolve8, }
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
}; };
public int XScaleFP; // Horizontal fixed point scale factor public int XScaleFp; // Horizontal fixed point scale factor
public int YScaleFP; // Vertical fixed point scale factor public int YScaleFp; // Vertical fixed point scale factor
public int XStepQ4; public int XStepQ4;
public int YStepQ4; public int YStepQ4;
public readonly int ScaleValueX(int val) public int ScaleValueX(int val)
{ {
return IsScaled() ? ScaledX(val) : val; return IsScaled() ? ScaledX(val) : val;
} }
public readonly int ScaleValueY(int val) public int ScaleValueY(int val)
{ {
return IsScaled() ? ScaledY(val) : val; return IsScaled() ? ScaledY(val) : val;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe void InterPredict( public unsafe void InterPredict(
int horiz, int horiz,
int vert, int vert,
int avg, int avg,
@@ -307,12 +166,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in either direction. // 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 else
{ {
// No scaling in x direction. Must always scale in the y direction. // 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 else
@@ -320,18 +181,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in the y direction. Must always scale in the x direction. // 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 else
{ {
// Must always scale in both directions. // 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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe void HighbdInterPredict( public unsafe void HighbdInterPredict(
int horiz, int horiz,
int vert, int vert,
int avg, int avg,
@@ -353,12 +215,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in either direction. // 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 else
{ {
// No scaling in x direction. Must always scale in the y direction. // 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 else
@@ -366,24 +230,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in the y direction. Must always scale in the x direction. // 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 else
{ {
// Must always scale in both directions. // 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) 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 xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask; int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
Mv32 res = new() Mv32 res = new() { Row = ScaledY(mv.Row) + yOffQ4, Col = ScaledX(mv.Col) + xOffQ4 };
{
Row = ScaledY(mv.Row) + yOffQ4,
Col = ScaledX(mv.Col) + xOffQ4,
};
return res; 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) public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
@@ -430,14 +291,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
if (!ValidRefFrameSize(otherW, otherH, thisW, thisH)) if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
{ {
XScaleFP = RefInvalidScale; XScaleFp = RefInvalidScale;
YScaleFP = RefInvalidScale; YScaleFp = RefInvalidScale;
return; return;
} }
XScaleFP = GetFixedPointScaleFactor(otherW, thisW); XScaleFp = GetFixedPointScaleFactor(otherW, thisW);
YScaleFP = GetFixedPointScaleFactor(otherH, thisH); YScaleFp = GetFixedPointScaleFactor(otherH, thisH);
XStepQ4 = ScaledX(16); XStepQ4 = ScaledX(16);
YStepQ4 = ScaledY(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 internal enum SegLvlFeatures
{ {
SegLvlAltQ = 0, // Use alternate Quantizer .... AltQ, // Use alternate Quantizer ....
SegLvlAltLf = 1, // Use alternate loop filter value... AltLf, // Use alternate loop filter value...
SegLvlRefFrame = 2, // Optional Segment reference frame RefFrame, // Optional Segment reference frame
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode Skip, // Optional Segment (0,0) + skip mode
SegLvlMax = 4, // Number of features supported 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.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -6,8 +8,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
internal struct Segmentation internal struct Segmentation
{ {
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 }; public const int SegmentDeltadata = 0;
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 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 Enabled;
public bool UpdateMap; public bool UpdateMap;
@@ -38,21 +48,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal static int FeatureDataMax(SegLvlFeatures featureId) internal static int FeatureDataMax(SegLvlFeatures featureId)
{ {
return _segFeatureDataMax[(int)featureId]; return SegFeatureDataMax[(int)featureId];
} }
internal static int IsSegFeatureSigned(SegLvlFeatures featureId) internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
{ {
return _segFeatureDataSigned[(int)featureId]; return SegFeatureDataSigned[(int)featureId];
} }
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData) internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
{ {
Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]); Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]);
if (segData < 0) if (segData < 0)
{ {
Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0); Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]); Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]);
} }
FeatureData[segmentId][(int)featureId] = (short)segData; FeatureData[segmentId][(int)featureId] = (short)segData;
@@ -67,5 +77,88 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
return FeatureData[segmentId][(int)featureId]; 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 Ryujinx.Graphics.Video;
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
internal delegate int VpxGetFrameBufferCbFnT(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv,
ulong minSize, ref VpxCodecFrameBuffer fb);
internal struct Surface : ISurface 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> YBuffer;
public ArrayPtr<byte> UBuffer; public ArrayPtr<byte> UBuffer;
public ArrayPtr<byte> VBuffer; 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 UPlane => new((nint)UBuffer.ToPointer(), UBuffer.Length);
public readonly unsafe Plane VPlane => new((nint)VBuffer.ToPointer(), VBuffer.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 Width { get; private set; }
public int Height { get; } public int Height { get; private set; }
public int AlignedWidth { get; } public int AlignedWidth { get; private set; }
public int AlignedHeight { get; } public int AlignedHeight { get; private set; }
public int Stride { get; } public int Stride { get; private set; }
public int UvWidth { get; } public int UvWidth { get; private set; }
public int UvHeight { get; } public int UvHeight { get; private set; }
public int UvAlignedWidth { get; } public int UvAlignedWidth { get; private set; }
public int UvAlignedHeight { get; } public int UvAlignedHeight { get; private set; }
public int UvStride { get; } 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; private readonly nint _pointer;
public Surface(int width, int height) public Surface(int width, int height)
{ {
HighBd = false; const int border = 32;
const int ssX = 1;
const int Border = 32; const int ssY = 1;
const int SsX = 1; const bool highbd = false;
const int SsY = 1;
int alignedWidth = (width + 7) & ~7; int alignedWidth = (width + 7) & ~7;
int alignedHeight = (height + 7) & ~7; int alignedHeight = (height + 7) & ~7;
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31; int yStride = (alignedWidth + (2 * border) + 31) & ~31;
int yplaneSize = (alignedHeight + 2 * Border) * yStride; int yplaneSize = (alignedHeight + (2 * border)) * yStride;
int uvWidth = alignedWidth >> SsX; int uvWidth = alignedWidth >> ssX;
int uvHeight = alignedHeight >> SsY; int uvHeight = alignedHeight >> ssY;
int uvStride = yStride >> SsX; int uvStride = yStride >> ssX;
int uvBorderW = Border >> SsX; int uvBorderW = border >> ssX;
int uvBorderH = Border >> SsY; int uvBorderH = border >> ssY;
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride; 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); nint pointer = Marshal.AllocHGlobal(frameSize);
_pointer = pointer; _pointer = pointer;
@@ -60,23 +91,148 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
AlignedWidth = alignedWidth; AlignedWidth = alignedWidth;
AlignedHeight = alignedHeight; AlignedHeight = alignedHeight;
Stride = yStride; Stride = yStride;
UvWidth = (width + SsX) >> SsX; UvWidth = (width + ssX) >> ssX;
UvHeight = (height + SsY) >> SsY; UvHeight = (height + ssY) >> ssY;
UvAlignedWidth = uvWidth; UvAlignedWidth = uvWidth;
UvAlignedHeight = uvHeight; UvAlignedHeight = uvHeight;
UvStride = uvStride; 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); UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
VBuffer = NewPlane(yplaneSize + uvplaneSize, 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); Marshal.FreeHGlobal(_pointer);
} }

View File

@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static int GetMinLog2TileCols(int sb64Cols) private static int GetMinLog2TileCols(int sb64Cols)
{ {
int minLog2 = 0; int minLog2 = 0;
while ((MaxTileWidthB64 << minLog2) < sb64Cols) while (MaxTileWidthB64 << minLog2 < sb64Cols)
{ {
++minLog2; ++minLog2;
} }
@@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private static int GetMaxLog2TileCols(int sb64Cols) private static int GetMaxLog2TileCols(int sb64Cols)
{ {
int maxLog2 = 1; int maxLog2 = 1;
while ((sb64Cols >> maxLog2) >= MinTileWidthB64) while (sb64Cols >> maxLog2 >= MinTileWidthB64)
{ {
++maxLog2; ++maxLog2;
} }
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return maxLog2 - 1; 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; int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
minLog2TileCols = GetMinLog2TileCols(sb64Cols); minLog2TileCols = GetMinLog2TileCols(sb64Cols);

View File

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

View File

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

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Graphics.Nvdec.Vp9.Types namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
internal enum TxType internal enum TxType
{ {
DctDct = 0, // DCT in both horizontal and vertical DctDct, // DCT in both horizontal and vertical
AdstDct = 1, // ADST in vertical, DCT in horizontal AdstDct, // ADST in vertical, DCT in horizontal
DctAdst = 2, // DCT in vertical, ADST in horizontal DctAdst, // DCT in vertical, ADST in horizontal
AdstAdst = 3, // ADST in both directions AdstAdst, // ADST in both directions
TxTypes = 4, 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.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
using System;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
@@ -9,27 +11,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public MacroBlockD Mb; public MacroBlockD Mb;
public ArrayPtr<TileWorkerData> TileWorkerData; public ArrayPtr<TileWorkerData> TileWorkerData;
public int TotalTiles;
public InternalErrorInfo Error; public InternalErrorInfo Error;
public VpxColorSpace ColorSpace;
public VpxColorRange ColorRange;
public int Width; public int Width;
public int Height; public int Height;
public int RenderWidth;
public int RenderHeight;
public int LastWidth;
public int LastHeight;
public int SubsamplingX; public int SubsamplingX;
public int SubsamplingY; public int SubsamplingY;
public bool UseHighBitDepth;
public ArrayPtr<MvRef> PrevFrameMvs; public ArrayPtr<MvRef> PrevFrameMvs;
public ArrayPtr<MvRef> CurFrameMvs; 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 Array3<RefBuffer> FrameRefs;
public int NewFbIdx;
public int CurShowFrameFbIdx;
public FrameType LastFrameType;
public FrameType FrameType; public FrameType FrameType;
public int ShowFrame;
public int LastShowFrame;
public int ShowExistingFrame;
// Flag signaling that the frame is encoded using only Intra modes. // Flag signaling that the frame is encoded using only Intra modes.
public bool IntraOnly; public bool IntraOnly;
public bool LastIntraOnly;
public bool AllowHighPrecisionMv; public bool AllowHighPrecisionMv;
public int ResetFrameContext;
// MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in // MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
// ModeInfo (8-pixel) units. // ModeInfo (8-pixel) units.
public int MBs; public int MBs;
@@ -49,9 +86,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
/* We allocate a ModeInfo struct for each macroblock, together with /* We allocate a ModeInfo struct for each macroblock, together with
an extra row on top and column on the left to simplify prediction. */ 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> 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>> MiGridBase;
public ArrayPtr<Ptr<ModeInfo>> MiGridVisible; public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
@@ -70,6 +112,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public LoopFilterInfoN LfInfo; public LoopFilterInfoN LfInfo;
public int RefreshFrameContext; /* Two state 0 = NO, 1 = YES */
public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */ public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
public LoopFilter Lf; public LoopFilter Lf;
@@ -81,22 +125,37 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ReferenceMode ReferenceMode; public ReferenceMode ReferenceMode;
public Ptr<Vp9EntropyProbs> Fc; public Ptr<Vp9EntropyProbs> Fc;
public ArrayPtr<Vp9EntropyProbs> FrameContexts; // FRAME_CONTEXTS
public uint FrameContextIdx; /* Context to use/update */
public Ptr<Vp9BackwardUpdates> Counts; 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 Log2TileCols, Log2TileRows;
public int ByteAlignment;
public int SkipLoopFilter;
public Ptr<BufferPool> BufferPool;
public ArrayPtr<sbyte> AboveSegContext; public ArrayPtr<sbyte> AboveSegContext;
public ArrayPtr<sbyte> AboveContext; public ArrayPtr<sbyte> AboveContext;
public readonly bool FrameIsIntraOnly() public bool FrameIsIntraOnly()
{ {
return FrameType == FrameType.KeyFrame || IntraOnly; return FrameType == FrameType.KeyFrame || IntraOnly;
} }
public bool CompoundReferenceAllowed() public bool CompoundReferenceAllowed()
{ {
int i; for (int i = 1; i < Constants.RefsPerFrame; ++i)
for (i = 1; i < Constants.RefsPerFrame; ++i)
{ {
if (RefFrameSignBias[i + 1] != RefFrameSignBias[1]) if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
{ {
@@ -107,6 +166,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return false; 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) private static int CalcMiSize(int len)
{ {
// Len is in mi units. // 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) 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); allocator.Free(TileWorkerData);
} }
private void AllocSegMap(MemoryAllocator allocator, int segMapSize) private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
{ {
int i; for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
{ {
SegMapArray[i] = allocator.Allocate<byte>(segMapSize); SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
} }
@@ -156,9 +255,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
private void FreeSegMap(MemoryAllocator allocator) private void FreeSegMap(MemoryAllocator allocator)
{ {
int i; for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
{ {
allocator.Free(SegMapArray[i]); allocator.Free(SegMapArray[i]);
SegMapArray[i] = ArrayPtr<byte>.Null; SegMapArray[i] = ArrayPtr<byte>.Null;
@@ -194,6 +291,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Lf.Lfm = ArrayPtr<LoopFilterMask>.Null; Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
allocator.Free(CurFrameMvs); allocator.Free(CurFrameMvs);
CurFrameMvs = ArrayPtr<MvRef>.Null; CurFrameMvs = ArrayPtr<MvRef>.Null;
if (UsePrevFrameMvs) if (UsePrevFrameMvs)
{ {
allocator.Free(PrevFrameMvs); 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); 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); SetMbMi(width, height);
int newMiSize = MiStride * CalcMiSize(MiRows); int newMiSize = MiStride * CalcMiSize(MiRows);
@@ -239,6 +337,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols); PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
} }
return false;
} }
private unsafe void DecSetupMi() 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() xd.PartitionProbs = FrameIsIntraOnly()
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16) ? 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) internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
{ {
int i; for (int i = 0; i < Constants.MaxMbPlane; ++i)
for (i = 0; i < Constants.MaxMbPlane; ++i)
{ {
xd.Plane[i].DqCoeff = dqcoeff; xd.Plane[i].DqCoeff = dqcoeff;
xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols)); 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); MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
} }
xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value); xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
} }
@@ -293,29 +392,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void SetupSegmentationDequant() public void SetupSegmentationDequant()
{ {
const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
// Build y/uv dequant values based on segmentation. // Build y/uv dequant values based on segmentation.
if (Seg.Enabled) if (Seg.Enabled)
{ {
int i; for (int i = 0; i < Constants.MaxSegments; ++i)
for (i = 0; i < Constants.MaxSegments; ++i)
{ {
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex); int qindex = Seg.GetQIndex(i, BaseQindex);
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth); YDequant[i][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth); YDequant[i][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth); UvDequant[i][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth); UvDequant[i][1] = QuantCommon.AcQuant(qindex, UvAcDeltaQ, BitDepth);
} }
} }
else else
{ {
int qIndex = BaseQindex; int qindex = BaseQindex;
// When segmentation is disabled, only the first value is used. The // When segmentation is disabled, only the first value is used. The
// remaining are don't cares. // remaining are don't cares.
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth); YDequant[0][0] = QuantCommon.DcQuant(qindex, YDcDeltaQ, BitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth); YDequant[0][1] = QuantCommon.AcQuant(qindex, 0, BitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth); UvDequant[0][0] = QuantCommon.DcQuant(qindex, UvDcDeltaQ, BitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, 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); 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.LastShowFrame) &&
!Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame), !Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
RefFrameSignBias = RefFrameSignBias, RefFrameSignBias = RefFrameSignBias,
LoopFilterLevel = FirstLevel,
LoopFilterSharpnessLevel = SharpnessLevel,
BaseQIndex = BaseQIndex, BaseQIndex = BaseQIndex,
YDcDeltaQ = YDcDeltaQ, YDcDeltaQ = YDcDeltaQ,
UvDcDeltaQ = UvDcDeltaQ, UvDcDeltaQ = UvDcDeltaQ,

View File

@@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Video
public bool IsKeyFrame; public bool IsKeyFrame;
public bool IntraOnly; public bool IntraOnly;
public Array4<sbyte> RefFrameSignBias; public Array4<sbyte> RefFrameSignBias;
public int LoopFilterLevel;
public int LoopFilterSharpnessLevel;
public int BaseQIndex; public int BaseQIndex;
public int YDcDeltaQ; public int YDcDeltaQ;
public int UvDcDeltaQ; public int UvDcDeltaQ;

View File

@@ -168,14 +168,16 @@ namespace Ryujinx.Graphics.Vulkan
return BinarySearch(list, offset, size) >= 0; return BinarySearch(list, offset, size) >= 0;
} }
public readonly IEnumerable<Range> FindOverlaps(int offset, int size) public readonly List<Range> FindOverlaps(int offset, int size)
{ {
var list = _ranges; var list = _ranges;
if (list == null) if (list == null)
{ {
yield break; return null;
} }
List<Range> result = null;
int index = BinarySearch(list, offset, size); int index = BinarySearch(list, offset, size);
if (index >= 0) if (index >= 0)
@@ -187,10 +189,12 @@ namespace Ryujinx.Graphics.Vulkan
do do
{ {
yield return list[index++]; (result ??= []).Add(list[index++]);
} }
while (index < list.Count && list[index].OverlapsWith(offset, size)); while (index < list.Count && list[index].OverlapsWith(offset, size));
} }
return result;
} }
private static int BinarySearch(List<Range> list, int offset, int size) private static int BinarySearch(List<Range> list, int offset, int size)

View File

@@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Vulkan
DriverId.MesaDozen => "Dozen", DriverId.MesaDozen => "Dozen",
DriverId.MesaNvk => "NVK", DriverId.MesaNvk => "NVK",
DriverId.ImaginationOpenSourceMesa => "Imagination (Open)", DriverId.ImaginationOpenSourceMesa => "Imagination (Open)",
DriverId.MesaAgxv => "Honeykrisp", DriverId.MesaHoneykrisp => "Honeykrisp",
_ => id.ToString(), _ => id.ToString(),
}; };
} }

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