Compare commits

..

486 Commits

Author SHA1 Message Date
Evan Husted c8b12ee3ec .NET 9 2024-12-23 20:15:36 -06:00
Evan Husted 4937b9ee7f Merge branch 'master' into metal 2024-12-23 20:12:55 -06:00
Daenorth 3094df54dd Update Norwegian Translation (#418)
swiggybobo
2024-12-23 17:03:33 -06:00
Evan Husted 278fe9d4f0 Add buildvalidationtasks project to infra label 2024-12-23 16:16:48 -06:00
GabCoolGuy a560d2efdb UI: Added missing french locales/Translated french locales (#415)
Custom refresh rate locales and fixed a couple others too
2024-12-23 15:43:06 -06:00
asfasagag a270dc721c UI: Option to resize window to 1440p, 2160p (#432)
Minor but useful quality of life addition
2024-12-22 22:49:40 -06:00
Evan Husted 23b0b22400 UI: Ensure last played date & time are always on 2 separate lines, for consistency. 2024-12-22 16:08:12 -06:00
Evan Husted 3dfbf55611 Merge remote-tracking branch 'origin/master' 2024-12-22 16:01:19 -06:00
Evan Husted cb355f504d UI: Rearrange help menu item & merge wiki page link buttons into a "category" button. 2024-12-22 16:01:09 -06:00
Marco Carvalho b5483d8fe0 Prefer generic overload when type is known (#430) 2024-12-22 13:23:35 -06:00
Evan Husted 8259f790d7 misc: Cleanup locale validator 2024-12-22 13:19:10 -06:00
Evan Husted 1ea345faa7 UI: Move Match PC Time to next to the time selector & change label & tooltip to clarify behavior further. 2024-12-22 12:53:48 -06:00
Marco Carvalho 5913ceda40 Avoid zero-length array allocations (#427) 2024-12-22 11:36:05 -06:00
Marco Carvalho decd37ce6d Add missing "yield return" (#424) 2024-12-21 23:28:31 -06:00
Hack茶ん 67ec10feea Korean translation update (#422) 2024-12-21 22:46:57 -06:00
Evan Husted 4c7cb54ec6 misc: I may be stupid 2024-12-21 21:52:04 -06:00
Evan Husted f898a5ecf4 Remove code references to having a flatpak version 2024-12-21 20:06:59 -06:00
Evan Husted 2fac0f4db1 Specify it's date & time 2024-12-21 20:00:16 -06:00
Evan Husted 0f18df982f UI: localize the button & make it smaller 2024-12-21 19:59:16 -06:00
Evan Husted d9fe0da345 UI: Button to set emulator time based on system time in settings, under the time settings.
Partially resolves #355. I think that wanted automatic. If automatic functionality is still desired even with this change then that will be considered.
2024-12-21 19:43:40 -06:00
Evan Husted 1f0fa525a3 UI: some languages did already say Firmware version oddly enough 2024-12-21 19:03:08 -06:00
Evan Husted e15a207656 misc: Improve broken locale.json crash message 2024-12-21 18:58:53 -06:00
Evan Husted 77ef82d92a misc: Cache LocalesJson when loading locale 2024-12-21 18:57:05 -06:00
Evan Husted ba199f4325 UI: Change "System Version" to "Firmware Version" and change 0.0 when firmware is not installed to NaN 2024-12-21 18:34:07 -06:00
Evan Husted 4171913baf misc: One additional usage of Lock & comment why it's not used on the others. 2024-12-21 17:05:55 -06:00
Evan Husted 5b36a9cf9f chore: small cleanups 2024-12-21 17:05:55 -06:00
GabCoolGuy a460eda195 UI: Fixed some light theme colors (#420)
Closes #419
2024-12-21 11:19:29 -06:00
sunshineinabox c77c1acd08 Resolve Image Usage Validation Error (#296)
This was a missed change that would resolve Image Usage validation error
that is created fairly frequently.

``VUID-VkImageViewCreateInfo-pNext-02662(ERROR / SPEC): msgNum:
-55646969 - Validation Error: [ VUID-VkImageViewCreateInfo-pNext-02662 ]
Object 0: handle = 0x260b9d1f6b8, type = VK_OBJECT_TYPE_IMAGE; |
MessageID = 0xfcaee507 | vkCreateImageView():
pCreateInfo->pNext<VkImageViewUsageCreateInfo>.usage
(VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_STORAGE_BIT) must not include
any bits that were not set in VkImageCreateInfo::usage
(VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
of the image. The Vulkan spec states: If the pNext chain includes a
VkImageViewUsageCreateInfo structure, and image was not created with a
VkImageStencilUsageCreateInfo structure included in the pNext chain of
VkImageCreateInfo, its usage member must not include any bits that were
not set in the usage member of the VkImageCreateInfo structure used to
create image
(https://vulkan.lunarg.com/doc/view/1.3.290.0/windows/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-pNext-02662)
    Objects: 1
        [0] 0x260b9d1f6b8, type: 10, name: NULL
``
2024-12-20 16:31:05 -06:00
Evan Husted d68295e57d infra: remove duplicate tables, I think this is ignored entirely anyways due to omitBodyDuringUpdate. 2024-12-20 16:03:03 -06:00
Evan Husted bb3d95722e infra: fix casing in release artifact tables 2024-12-20 15:51:24 -06:00
Evan Husted 2fa3a7bfa1 HLE: rename AmiiboDecrypter to AmiiboDecryptor 2024-12-20 15:44:01 -06:00
Evan Husted 381921390a UI: Only show Amiibo bin scan menu item if the key file exists 2024-12-20 15:41:18 -06:00
Jacobwasbeast 221524d879 Added Support for 532-Byte Amiibo BIN Files (#412)
Added functionality to load 532-byte Amiibo BIN files, commonly used in
Tagmo and similar tools. These files were missing the following pages.
*    133 (85h) PWD
*    134 (86h) PACK RFUI
These pages can be added as null bytes if not present. The system seems
to function correctly without them.
2024-12-20 13:54:27 -06:00
LotP1 9cddf3b66b Unified locales (#391)
Use 1 locales file instead of individual files for each langauge.
This makes it easier to keep track of what is missing.
The PR will automatically fix missing locales and throw an error if
anything is incorrect, by running the emulator. That way the person
adding a new locale or new language can just run the emulator once to
populate all the fields, so they can easily begin translating.
2024-12-20 13:27:11 -06:00
Jacobwasbeast 0adaa4cb96 Adds the ability to read and write to amiibo bin files (#348)
This introduces the ability to read and write game data and model
information from an Amiibo dump file (BIN format). Note that this
functionality requires the presence of a key_retail.bin file. For the
option to appear and function in the UI, ensure that the key_retail.bin
file is located in the <RyujinxData>/system folder.
2024-12-19 22:36:46 -06:00
Marco Carvalho ff6628149d Migrate to .NET 9 (#198) 2024-12-19 18:52:25 -06:00
Evan Husted 8db5a7e98b UI: Fix logo aliasing 2024-12-17 21:20:49 -06:00
GabCoolGuy 8e00cb5232 UI: Add faq, setup and multiplayer guides to the Help dropdown (#383) 2024-12-15 10:45:37 -06:00
Evan Husted 362f62cd39 Revamp README header 2024-12-14 08:41:44 -06:00
Evan Husted 2cd54d0da0 Remove icon padding 2024-12-14 08:03:17 -06:00
Evan Husted b97b8ca8f5 Logo from PR #381 everywhere 2024-12-14 07:27:07 -06:00
Matteo Forlani d7d4225e0d New macOS icon (#381) 2024-12-14 07:23:47 -06:00
Evan Husted a9e0fac9dc fix changelogs in canary release 2024-12-13 19:28:34 -06:00
Daenorth 1b9656e960 Norwegian Translation (#338) 2024-12-13 03:56:20 -06:00
Hack茶ん 8994e7476c Korean Former Maintainers & About description translations (#371) 2024-12-13 03:54:07 -06:00
rrondo b3944a18b7 Some changes to Ukrainian localization (uk_UA.json) (#356)
I made some small corrections and translated the lines that didn’t have
translations.
2024-12-10 11:58:53 -06:00
GabCoolGuy 18c957f90b infra: Add a table to the releases (#363)
This adds a table making it clearer what artifacts are needed for what
platform.

Nogui builds are not provided in the table as per Greem's request.

MAINTAINER EDIT: reasoning for above is due to the Headless in Avalonia
PR; nogui builds are going away.

Tested for both canary and release builds and everything works fine:


[Canary](https://github.com/GabCoolDude/Ryujinx-Canary/releases/tag/1.2.6)
[Release](https://github.com/GabCoolDude/Ryujinx/releases/tag/1.2.2)

For release, the damn appimage messed everything up, but thanks to
macOS, you can still test if it works.
2024-12-10 11:02:18 -06:00
Evan Husted 1a005f96e7 Merge remote-tracking branch 'origin/master' 2024-12-08 13:05:47 -06:00
Evan Husted 072cd2824a misc: chore: Simplify Updater version parsing. 2024-12-08 13:05:35 -06:00
Evan Husted 9da97bc911 misc: chore: Collapse XCIFileTrimmerLog implementations into a single class. 2024-12-08 13:05:09 -06:00
Evan Husted 39252b7267 UI: Update About window with the current status of the project. 2024-12-08 13:04:01 -06:00
Evan Husted ec11bf2af9 i18n: Clean out old translations and reset outdated ones 2024-12-07 08:53:23 -06:00
bangfire 8ae72c1a00 Fix Windows Terminal hide/show functions (#342)
https://stackoverflow.com/a/78577080
2024-12-07 07:17:39 -06:00
Evan Husted 06abba25c1 UI: Adapt accent color to the user's system.
https://amwx.github.io/FluentAvaloniaDocs/pages/FATheme/Accents#using-the-systems-accent-color
2024-12-07 06:22:46 -06:00
Evan Husted de00a71690 UI: Fix missing total DLC count.
Fixes #347.
2024-12-07 05:48:11 -06:00
Evan Husted 315a1819c0 Attempt #2 2024-12-07 05:31:37 -06:00
Evan Husted 4ffb8aef12 Try and fix nullref 2024-12-07 05:21:16 -06:00
Evan Husted 290a6ad5de HLE: extract custom NACP data functionality into a static helper for generic reuse elsewhere, and clarify magic numbers. 2024-12-07 04:30:04 -06:00
Evan Husted eda4f4349b headless: Actually log the command line errors 2024-12-07 04:06:22 -06:00
Evan Husted 5fbcb1f3a7 misc: chore: Cleanups & unused parameter removal 2024-12-07 04:06:22 -06:00
WilliamWsyHK d00754477e Add Firmware keyword in log if it is indeed firmware (#343)
Co-authored-by: LotP1 <rasmus.stilling.pedersen1@gmail.com>
2024-12-07 04:03:01 -06:00
maxdlpee 0bc1eddaeb Update Spanish translation (#332)
- Added translations for XCI trimmer
- Added translations for Cabinet applet
- Added translations for Keys installer
- Other miscellaneous translations added
2024-12-06 21:57:35 -06:00
Luke Warner baad1e313f Stub Ldn.Lp2p.ISfService: 776 (DestroyGroup) (#353)
This prevents a crash in Mario Kart Live: Home Circuit that would occur
after exiting the kart pairing screen.
2024-12-06 14:43:31 -06:00
Hack茶ん a1e6d11dcb Update Korean translation (#352) 2024-12-06 09:18:09 -06:00
Evan Husted 3d168a8bfa direct errored updates to ryujinx.app 2024-12-06 08:18:24 -06:00
Evan Husted 000c1756de version 1.2 in Info.plist 2024-12-06 08:17:04 -06:00
Evan Husted 1d0152b961 UI: Move Shader Compilation hint, graphics backend, and GPU manufacturer to the right side of the status bar, next to firmware version.
Removed the "Game:" prefix in front of FPS.
2024-12-04 03:37:21 -06:00
Evan Husted 07690e4527 chore: applets: Cleanup redundant ReadStruct implementations & provide a default implementation for IApplet#GetResult. 2024-12-04 02:24:40 -06:00
Jacobwasbeast 08b7257be5 Add the Cabinet Applet (#340)
This adds the missing Cabinet Applet, which allows for formatting
Amiibos and changing their names.
2024-12-02 23:40:02 -06:00
Luke Warner 17483aad24 ARMeilleure: Allow TPIDR2_EL0 to be set properly (#339) 2024-12-02 14:42:07 -06:00
Luke Warner 6b5cb151c3 Implement and stub services required for Mario Kart Live: Home Circuit (#331)
These changes allow Mario Kart Live: Home Circuit (v2.0.0) to boot into
menus. Kart functionality has not been implemented and will not work.

Version 1.0.0 is currently unsupported due to unimplemented ARM
registers. I plan on addressing this issue at a later date.


### Here is a list of the implemented and stubbed services in this PR:
#### Implemented:
Ldn.Lp2p.IServiceCreator: 0 (CreateNetworkService)
Ldn.Lp2p.IServiceCreator: 8 (CreateNetworkServiceMonitor)
Ldn.Lp2p.ISfService: 0 (Initialize)
Ldn.Lp2p.ISfServiceMonitor: 0 (Initialize)
Ldn.Lp2p.ISfServiceMonitor: 256 (AttachNetworkInterfaceStateChangeEvent)
Ldn.Lp2p.ISfServiceMonitor: 328 (AttachJoinEvent)
#### Stubbed:
Ldn.Lp2p.ISfService: 768 (CreateGroup)
Ldn.Lp2p.ISfService: 1536 (SendToOtherGroup)
Ldn.Lp2p.ISfService: 1544 (RecvFromOtherGroup)
Ldn.Lp2p.ISfServiceMonitor: 288 (GetGroupInfo)
Ldn.Lp2p.ISfServiceMonitor: 296 (GetGroupInfo2)
Ldn.Lp2p.ISfServiceMonitor: 312 (GetIpConfig)
2024-11-30 17:20:48 -06:00
Piplup 3680df6092 Fix for missing text with specific system locale encoding (#330) 2024-11-30 17:17:30 -06:00
LotP1 facc12a94a JIT Sparse Function Table random crash fix (#319)
A couple of games have random crashing with the JIT Sparse Ftable changes, and it seems to have been caused by an insufficient int size returned by `AddressTableLevel#GetValue(ulong address)`.
It was 32 bits (Int32), but the GiantBlock (which is the current address table impl) uses potentially 36 bits for the first level.
2024-11-29 16:32:55 -06:00
Hack茶ん 8e55e6d6d7 Korean translation for key install tool (#329) 2024-11-29 15:39:11 -06:00
Nicola 346dfe9542 Added Tool for installing keys (#233)
#232 

![image](https://github.com/user-attachments/assets/5ae6118d-3857-4005-8392-5398c8fa91d5)
2024-11-28 17:32:07 -06:00
Jonas Henriksson 8a2b56cae6 Fix logic surrounding PushDescriptors in Vulkan (#257) 2024-11-28 17:00:12 -06:00
TheToid baf179efdb ignore macos attribute files (#302) 2024-11-28 16:55:51 -06:00
Evan Husted 2a72fb2088 UI: RPC: Add Diablo III 2024-11-26 17:15:11 -06:00
Luke Warner 0caeab2270 Remove 'Enter' hotkey in settings menu (#95)
This allows the Enter key to be bound to a button when using the
Avalonia UI.
2024-11-25 13:46:41 -06:00
GabCoolGuy f72d2c1b2b UI: Add Mii Edit Applet Locale (#311)
This allows the "Mii Edit Applet" dropdown to be localized ( I already
went ahead and localized French )
2024-11-25 13:43:01 -06:00
Hack茶ん a18cecbc30 Korean "Show Changelog" translation (#313) 2024-11-25 13:40:39 -06:00
Keaton 2e6794e69b Add custom refresh rate mode to VSync option (#238)
Rebased @jcm93's refreshinterval branch:
https://github.com/jcm93/Ryujinx/tree/refreshinterval

The option is placed under System/Hacks. Disabled, it's the default
Ryujinx behavior. Enabled, the behavior is shown in the attached
screenshots. If a framerate is too high or low, you can adjust the value
where you normally toggle VSync on and off. It will also cycle through
the default on/off toggles.

Also, in order to reduce clutter, I made an adjustment to remove the
target FPS and only show the percentage.

---------

Co-authored-by: jcm <6864788+jcm93@users.noreply.github.com>
2024-11-25 13:39:09 -06:00
GabCoolGuy 7e16fccfc1 UI: Fix icons getting cutoff in the About window (#310)
Before:


![image](https://github.com/user-attachments/assets/c8d6b7d5-487b-4ab9-83e3-9489eaa0a076)

After:


![image](https://github.com/user-attachments/assets/18ea6360-f6ee-48e6-9a0a-cd8d88a0cf51)
2024-11-24 11:33:53 -06:00
Daniel Zauner a81212bbf1 Fix window decorations being too wide (#309) 2024-11-24 09:49:44 -06:00
Evan Husted e8d3ad4d8b UI: RPC: TSUKIHIME -A piece of blue glass moon- asset image 2024-11-23 13:10:53 -06:00
Evan Husted 3b6731a351 infra: Undo packing native libraries into executable. 2024-11-22 17:51:44 -06:00
LotP1 e653848a2c JIT Sparse Function Table (#250)
More up to date build of the JIT Sparse PR for continued development.
JIT Sparse Function Table was originally developed by riperiperi for the
original Ryujinx project, and decreased the amount of layers in the
Function Table structure, to decrease lookup times at the cost of
slightly higher RAM usage.
This PR rebalances the JIT Sparse Function Table to be a bit more RAM
intensive, but faster in workloads where the JIT Function Table is a
bottleneck. Faster RAM will see a bigger impact and slower RAM (DDR3 and
potentially slow DDR4) will see a slight performance decrease.
This PR also implements a base for a PPTC profile system that could
allow for PPTC with ExeFS mods enabled in the future.
This PR also potentially fixes a strange issue where Avalonia would time
out in some rare instances, e.g. when running ExeFS mods with TotK and a
strange controller configuration.

---------

Co-authored-by: Evan Husted <gr33m11@gmail.com>
2024-11-22 15:33:44 -06:00
Evan Husted 5534001152 UI: Always save screenshots to the Ryujinx data directory. 2024-11-22 15:08:24 -06:00
Evan Husted e05875a079 UI: It's called "live testing." 2024-11-22 14:52:56 -06:00
Evan Husted 49eeb26b6f UI: I may be stupid. Primary button result is Ok, not Yes. 2024-11-22 14:46:10 -06:00
Evan Husted f8d63f9a2f UI: Add a show changelog button in the Updater, for new updates & when you're on the latest version. 2024-11-22 14:38:58 -06:00
GabCoolGuy e2b7738465 Add all the missing locales from XCI Trimmer and LDN merge (#281)
Hello any fellow developers that may be reading this. Whenever you add
any new locales to `en_US.json`, please make sure to add them to the
rest of the locale files. I will not always be there to add them myself.
2024-11-22 11:07:47 -06:00
GabCoolGuy 1d42c29335 Add more mentions of canary (#258)
This should hopefully make it clearer whether or not you're using
canary.

Changelog:
- Changed github workflows to have "canary" in the zip files
- Added `App.FullAppName` in the about section, so that it's clear in
there too
- Changed log name for canary builds to
`Ryujinx_Canary_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log`
(normal builds should still be
"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log)
2024-11-21 12:34:53 -06:00
Evan Husted c2de5cc700 Fix really obvious typo, lol 2024-11-21 10:16:13 -06:00
GabCoolGuy aaaf60b7a4 Change headless to nogui in the release artifacts (#285)
This makes it so that instead of the files you download being
`sdl2-ryujinx-headless` they are now `nogui-ryujinx`in the release (and
canary) artifacts
2024-11-20 12:20:38 -06:00
GabCoolGuy 150e06e0de Add documentation and ldn labels to labeler.yml (#282)
This should make it so that any changes made to ldn and documentation
related files should be auto-labeled
2024-11-20 11:52:16 -06:00
Luke Warner c0a4d95c5d ARMeilleure: Implement TPIDR2_EL0 (#280)
This is an implementation of the TPIDR2_EL0 register. There may be more
potential use-cases for this register not included in this PR, but this
implements the use-case seen in SuperTuxKart.
2024-11-19 13:02:24 -06:00
Evan Husted c3831428e0 Try and fix weird nullref 2024-11-19 10:22:11 -06:00
Evan Husted fda79efed4 Fix Windows builds not being uploaded 2024-11-19 09:31:22 -06:00
Nicola 8444e4dca0 Fixed mime types button not updating after install/uninstall (#241) 2024-11-19 02:16:15 -06:00
Narugakuruga 008d908c5a Update Chinese locale missing line (#259) 2024-11-19 01:59:56 -06:00
Pitchoune 722953211d Add Zelda Echoes of Wisdom Amiibos informations (#262)
This adds missing informations about Zelda Echoes of Wisdom Amiibos.
2024-11-19 01:59:00 -06:00
Nicola df5002bdbf Created bool to store if the "Avilable Update" should be hidden on startup (--hide-updates) (#272)
fixes #263
2024-11-19 01:52:51 -06:00
GabCoolGuy f4b757c584 Add XCITrimmerTrim and XCITrimmerUntrim Locales (#273) 2024-11-18 15:05:00 -06:00
GabCoolGuy 25d69079cb Fix a couple dead links and spotty wording in docs (#260)
Made it clearer that building is for contributors only in `COMPILING.md`

Fixed 2 dead links in `CONTRIBUTING.md`, that were caused by separating
`COMPILING.md` and file structure changed to `pr-guide.md`
2024-11-17 04:35:37 -06:00
Evan Husted 2e1ede5348 Merge remote-tracking branch 'origin/master' 2024-11-17 00:58:10 -06:00
Evan Husted 52f42d450f try 1: Fix IndexOutOfBounds in SDL2GamepadDriver.cs 2024-11-17 00:57:56 -06:00
jzumaran 11416e2167 i18n: es_ES: Added missing translations and minor fixes (#242)
Added missing translations and fixed a few spelling mistakes.
2024-11-17 00:17:56 -06:00
Nicola e5d076a1b2 Fixed some broken urls (#249) 2024-11-17 00:16:05 -06:00
Nicola d394dd769a Updated IT translation file (#243) 2024-11-17 00:15:06 -06:00
Evan Husted 6de3afc43d misc: chore: Move build instructions into its own markdown file; remove compatibility section since there's no games list. 2024-11-15 06:02:26 -06:00
EmulationEnjoyer 9b90e81817 Fix window sizing when "Show Title Bar" is enabled (#247)
Fixes a bug that causes the main window to not size properly when the
TitleBar is enabled (i.e.: when the TitleBar and MenuStrip are separate
entities). Corrects the size for main window startup and when a user
clicks a "View > Window Size > *Resolution Here*" MenuStripItem

Prior to this fix if a user selects 720p/1080p and "Show Title Bar" is
enabled, the window would be sized smaller than intended and display
black bars on the sides of the render area
2024-11-15 01:26:35 -06:00
Evan Husted 1e53a17041 misc: Add LEGO Horizon Adventures image asset to Discord RPC 2024-11-15 01:18:00 -06:00
GabCoolGuy 0c23104792 Add mention of canary to README.md (#236) 2024-11-15 00:24:18 -06:00
Isaac Marovitz 1c6636d3cd Make resource encoding less stupid 2024-09-30 17:52:07 +02:00
Isaac Marovitz e60b90fc47 Set correct maximum supported anisotropy 2024-09-29 01:17:21 +02:00
Isaac Marovitz cedc8e00df GAL Changes 2024-09-29 01:06:10 +02:00
Isaac Marovitz 0ca4c03af4 Updates 2024-09-28 19:03:01 -04:00
Isaac Marovitz 7d86cb8d7f GAL Changes 2024-09-28 19:03:01 -04:00
Isaac Marovitz f58920b944 Check for null resources before declaring them resident 2024-09-28 19:03:01 -04:00
Isaac Marovitz ca30248d97 Fix null sampler crash 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6fed9b51b5 Fix counted indirect draws
Fixes Monster Hunter Rise and Apollo Justice
2024-09-28 19:03:01 -04:00
Isaac Marovitz bb917a4aa4 Program hash set 2024-09-28 19:03:01 -04:00
Isaac Marovitz 7245193f08 Auto-backed samplers 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2f0235fc37 Refactor binding logic + Bind image arrays 2024-09-28 19:03:01 -04:00
Isaac Marovitz 04c0090653 Fix primitive id in shader gen
Fixes Dark Souls
2024-09-28 19:03:01 -04:00
Isaac Marovitz d5502b02b1 Fix cubemap array length
Fixes crash in Sonic Frontiers
2024-09-28 19:03:01 -04:00
Isaac Marovitz 691b0de6e1 Properly create stencil views of combined formats
Fixes Link’s Awakening
2024-09-28 19:03:01 -04:00
Isaac Marovitz b43ff78ba1 Add missing set texture for depth stencil blit
Mostly fixes Sonic Frontiers & Link’s Awakening
2024-09-28 19:03:01 -04:00
Isaac Marovitz 16eb005e8b Fix typo in stride change shader
Fixes Castlevania Dominus Collection
2024-09-28 19:03:01 -04:00
Isaac Marovitz ce23bff285 Fix invalid depth stencil state when no depth stencil is present
Partially fixes Sonic Frontiers and Castlevania Dominus Collection
2024-09-28 19:03:01 -04:00
Isaac Marovitz 6b2bc16dc3 Style 2024-09-28 19:03:01 -04:00
Isaac Marovitz 302ee73f34 Metal: Unsupported topology indexed draw conversion (#40)
* Convert unsupported indexed buffer topologies

* Fix index count and dispatch size

* Cleanup

* Fix typos
2024-09-28 19:03:01 -04:00
Isaac Marovitz 6a46943af9 Fix null resources breaking arg buffer alignment 2024-09-28 19:03:01 -04:00
Isaac Marovitz a968ec71fd Remove RenderPipelineDescriptorResult 2024-09-28 19:03:01 -04:00
Isaac Marovitz d7c71c8a7b D32FS8 to D24S8 Conversion 2024-09-28 19:03:01 -04:00
Isaac Marovitz f06c869df1 Upstream changes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8a579b64be Logic Operations 2024-09-28 19:03:01 -04:00
Isaac Marovitz e928ec9708 Fix array size query 2024-09-28 19:03:01 -04:00
Isaac Marovitz c7c80dc2fb Debug Groups 2024-09-28 19:03:01 -04:00
Isaac Marovitz fc581cf707 IaIndexing
Fixes shader problems in Donkey Kong Country Tropical Freeze, and Fire Emblem: Three Houses
2024-09-28 19:03:01 -04:00
Isaac Marovitz bdb00f3981 Rasterizer Discard + Multisample State 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6e3aaa6360 Metal: Argument Buffer Pre-Pass (#38)
* Init

* Fix missing flags

* Cleanup
2024-09-28 19:03:01 -04:00
riperiperi fff3a4f8f8 Patch some leaks and only perform copies on valid textures (#37) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 01f41b8b0e Get render command encoder after finalising buffers
Fixes crash in Fire Emblem: Houses
2024-09-28 19:03:01 -04:00
Isaac Marovitz 080af8db24 Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 29e6f17978 Fix non atomic image loads again 2024-09-28 19:03:01 -04:00
Isaac Marovitz 068a83bdfb Finally fix (most) image atomics 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8fa8f3a390 Precise Float Fixes
Fixes artifacts in TOTK
2024-09-28 19:03:01 -04:00
Isaac Marovitz 3360740250 Fix image atomics 2024-09-28 19:03:01 -04:00
Isaac Marovitz c77f3b90a9 Fix Non-Float Textures + Image Read + FSI Buffers
Fixes Mario Party Superstars
2024-09-28 19:03:01 -04:00
Isaac Marovitz d5e19a70bd Image Constant Fixes
Allows Mario Party Superstars to boot
2024-09-28 19:03:01 -04:00
Isaac Marovitz 245778bc7e Helper Shader fixes for non float formats 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4cd15cb1a6 Shader Extra Set Support + Cleanup (#36)
Separate samplers are now supported and arrays in constant sets are bound
2024-09-28 19:03:01 -04:00
Isaac Marovitz d9025904a7 InstGenMemory Refactor + Bindless Support 2024-09-28 19:03:01 -04:00
Isaac Marovitz 47b99e6bc3 TextureArray & ImageArray Creation + State 2024-09-28 19:03:01 -04:00
Isaac Marovitz d07f6ed38e Fix hex number type ambiguity
Fixes cutscenes in Super Mario Sunshine
2024-09-28 19:03:01 -04:00
Isaac Marovitz 7490afbdc3 Use RGBA8Unorm for R4G4B4A4Unorm
Gets SM64 to boot
2024-09-28 19:03:01 -04:00
Isaac Marovitz 62b8d25315 Dual Source Blend Support in Shader
Fixes Super Mario Galaxy and The Legend of Zelda: Skyward Sword HD
2024-09-28 19:03:01 -04:00
Isaac Marovitz 911389db63 Get Tomb Raider working 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4f6860cfd4 Remove DummyBufferTextures
Mostly gets VTG on Compute working again
2024-09-28 19:03:01 -04:00
Isaac Marovitz e8dda2d5ef Properly register TextureBuffer usage + Store Auto ref 2024-09-28 19:03:01 -04:00
Isaac Marovitz 810b5792a8 Partial indirect draw support 2024-09-28 19:03:01 -04:00
Gabriel A 1b9377023a Fixes 2024-09-28 19:03:01 -04:00
Gabriel A 29cca80d9f Start building more accurate vertex as compute usage info 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3214a4cf8e Bind TextureBuffers 2024-09-28 19:03:01 -04:00
Isaac Marovitz 62602e58b7 Remove ClearSegments for now
Currently unimplemented and issues are arising with building BindingSegments in general.
2024-09-28 19:03:01 -04:00
Isaac Marovitz 997e8d11f7 Fix compute generation failure in NieR 2024-09-28 19:03:01 -04:00
Isaac Marovitz 42c6611563 Some debug improvements 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3d12f7ef74 Stop complaining about clip distance 2024-09-28 19:03:01 -04:00
Isaac Marovitz e42e4931a8 Shader Gen Fixes
Fixes Luigi’s Mansion 2 HD
2024-09-28 19:03:01 -04:00
Isaac Marovitz 3a04d72686 DepthStencil Blits 2024-09-28 19:03:01 -04:00
Isaac Marovitz aa6e87e8a6 Multisample Blits
Partially fixes Sonic Colors Ultimate
2024-09-28 19:03:01 -04:00
Isaac Marovitz b434cae2c2 Fix image bindings 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2b919493e3 FSI (with raster order groups) 2024-09-28 19:03:01 -04:00
Isaac Marovitz fdf7578928 SwizzleAdd (NOT TESTED) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 558752594c Consolodate barriers 2024-09-28 19:03:01 -04:00
Isaac Marovitz a31e461db8 Shader Memory Barriers
Fixes some of the shader generation failures in Sonic Frontiers
2024-09-28 19:03:01 -04:00
Isaac Marovitz 650f309b58 Image binding support
Kirby still has a problem with NaN 3D Texture
2024-09-28 19:03:01 -04:00
Isaac Marovitz 4e5cf38009 Image shader gen support 2024-09-28 19:03:01 -04:00
Isaac Marovitz b44167d12a Shader cache support 2024-09-28 19:03:01 -04:00
Isaac Marovitz eb2dae561f Make dotnet format happy 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1287098b8b GAL ResourceUsage Changes
TODO: Guest Barrier Defer
2024-09-28 19:03:01 -04:00
Isaac Marovitz 9f2c99fcfa Better vertex buffer management 2024-09-28 19:03:01 -04:00
Isaac Marovitz a6f5f2f82b Fix LOD 2024-09-28 19:03:01 -04:00
Isaac Marovitz 655823ecc7 Better index buffer management 2024-09-28 19:03:01 -04:00
Isaac Marovitz 18a1741348 Formatting cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz b734c81683 Formatting 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6e80cc6caa Update binding model description comment 2024-09-28 19:03:01 -04:00
riperiperi ea30e543e6 Fix preload cbs optimization (for real) (#34)
* Mostly fix preload cbs. There seems to be some random flickering...

* fix index buffer usage range

* fix missing preflush submit before present
2024-09-28 19:03:01 -04:00
Isaac Marovitz e3468d35b6 Fix invariant position not doing its job 2024-09-28 19:03:01 -04:00
riperiperi d22feff1d2 implement compressed/uncompressed copy, fix other copies, fix int/uint output shaders (#33) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 9d866ff282 Fix blend state optimisation breaking attachments
Fixes SM3DW
2024-09-28 19:03:01 -04:00
riperiperi fd0329f2eb Fix warnings 2024-09-28 19:03:01 -04:00
riperiperi 468ab8242f Maintain identity swizzle view of textures for rendering 2024-09-28 19:03:01 -04:00
riperiperi 7b9b23e500 Fix a bunch of issues with texture copy and flush (#32)
* Fix a bunch of issues with texture copy and flush

* TextureCopy helper class, fix clear bug
2024-09-28 19:03:01 -04:00
Isaac Marovitz 0c1acb5107 Cleanup + Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8e8dcf0d7f Fix trying to reserve size 0 in staging buffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz 9f0a468f55 Fix zero buff not being reset 2024-09-28 19:03:01 -04:00
Isaac Marovitz ab79959975 Dirty Arg Buffers on Program Change 2024-09-28 19:03:01 -04:00
Isaac Marovitz de5bf3a141 Least allocations in the west 2024-09-28 19:03:01 -04:00
Isaac Marovitz 5e8606c89a Don’t use Enum.HasFlag 2024-09-28 19:03:01 -04:00
Isaac Marovitz daee63c451 Metal: Better Bindings (#29)
* Tell GAL to use Vk model (and break everything)

* ResourceBindingSegments

* Set information on backend caps

* Get ready to break everything

* Refactor EncoderStateManager

* Remove padding from helper shaders

* Fix ref array sizes

* Seperate vert & frag buffers

* Shader-side changes

* Fixes

* Fix some helper shader resource layouts

* Sort by binding id

* Fix helper shader layouts

* Don’t do inline vertex buffer updates

* Check for null storage
2024-09-28 19:03:01 -04:00
Isaac Marovitz 971c270bcf Update comment for Metal 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6aff6401fb Don’t do inline vertex buffer updates
Somehow broke zero buff MTLVertexDescriptor, but fixes broken geoemtry so I’m pushing anyway
2024-09-28 19:03:01 -04:00
riperiperi 6f6ccb7898 Create command buffers when rented rather than in advance (#31)
* Make it less likely to freeze, but the creation of the command buffer should probably be moved

* Create command buffers as they're rented rather than in advance
2024-09-28 19:03:01 -04:00
riperiperi 2511bf1e4c Preload command speedup, Texture/buffer data flush, blit shader fix (#30)
* Move encoder state to be tied to command buffer, so preload and background cbs have their own encoder state

* Texture buffer/data flush, blit shader fix
2024-09-28 19:03:01 -04:00
Isaac Marovitz 80f9a5d0da Dont bind images in texture slots 2024-09-28 19:03:01 -04:00
Isaac Marovitz ed4f7a5602 Stop depth/stencil blits from crashing everything 2024-09-28 19:03:01 -04:00
riperiperi edceb1607f Fix Geometry/TFB on compute, Buffer Textures, add Window Resizing (#28) 2024-09-28 19:03:01 -04:00
riperiperi e02df72323 State and cache optimization (#27)
* WIP pipeline/depth state cache rework

* Fix some issues

* Fix some more default values

* Reduce allocations for state changes

* fix helpershader stuff

* explanation comment

* fix depth bias
2024-09-28 19:03:01 -04:00
Isaac Marovitz 9d26aa8d06 Fragment input interpolation qualifiers
Fixes Mario’s shadow in SMO
2024-09-28 19:03:01 -04:00
Isaac Marovitz c8c4fd730d CommandBufferBarrier 2024-09-28 19:03:01 -04:00
riperiperi e27ade5aee Add constrained border colours to samplers (#26) 2024-09-28 19:03:01 -04:00
Isaac Marovitz b33c1ae22f Don’t bind byte format converted index buffers at requested index 2024-09-28 19:03:01 -04:00
Isaac Marovitz 242fcc2481 Render target deduplication
not sure if this is working
2024-09-28 19:03:01 -04:00
Isaac Marovitz ef4a2fb3b5 Fix CBP not doing its job
Thanks peri (again)
2024-09-28 19:03:01 -04:00
Isaac Marovitz c4731c0555 Fix blend descriptors not dirting render pipeline
Thanks peri
2024-09-28 19:03:01 -04:00
Isaac Marovitz 0c562a2c50 Support non-index quad draws
Fixes Deltarune
2024-09-28 19:03:01 -04:00
Isaac Marovitz ab1e02c56a Be better about memory 2024-09-28 19:03:01 -04:00
Isaac Marovitz a264d9273d Fix stencil clears 2024-09-28 19:03:01 -04:00
Isaac Marovitz 05189c7749 Enable Alpha Test workaround on Metal 2024-09-28 19:03:01 -04:00
Isaac Marovitz b7ddb693bc Fix Cull FrontAndBack 2024-09-28 19:03:01 -04:00
Isaac Marovitz a60643620d Warning about host map buffer creation 2024-09-28 19:03:01 -04:00
Isaac Marovitz 113e721cce Fix fragment point_coord in 2024-09-28 19:03:01 -04:00
Isaac Marovitz c8308d27f1 Argument Buffers (#24)
* Stuff

* More arg buffer stuff

* Fixes

* Rebase

* Pass storage buffers to inline functions

* Fix binding

* Fix typo + Fix a couple shaders

* Enforce ids

* Dispose

* Mark used buffers as resident

* Update depth clear shader

* Fix non-contiguous struct defs

* Update ChangeBufferStride

* Fix StorageBuffer assignments

* Fix odyssey crash

* Retain buffer bindings

* Pad Std140

* Set texture data with safe buffers

* Clone buffers

* Always declare vert in

* Stop clears from breaking OpenGL games

* Fix depth clear

* Use invariant position

* Horribly inefficient texture & sampler arg buffers

* Fix missing struct access

* Minimise rebinds as much as possible

* Build arg buffers on staging buffer
2024-09-28 19:03:01 -04:00
Isaac Marovitz a71b5f1a3a VoteAllEqual, FindLSB/MSB 2024-09-28 19:03:01 -04:00
Isaac Marovitz b094d34575 Fix vertex “built-ins”
Only declare main func out in main

Fix simd_ballot

Fix thread_index_in_simdgroup outside of compute

Fix atomic operations

instance_index
2024-09-28 19:03:01 -04:00
Isaac Marovitz 4578ee53d3 Actually clear the right render target 2024-09-28 19:03:01 -04:00
Isaac Marovitz 72cbb41609 Big GetData()
Co-authored-by: riperiperi <rhy3756547@hotmail.com>
2024-09-28 19:03:01 -04:00
Isaac Marovitz e7fab91c69 Fix Animal Crossing Crash 2024-09-28 19:03:01 -04:00
Isaac Marovitz 97a36298fa Instruction.Barrier
Whoops

Fix inline functions in compute stage

Fix regression

Declare SharedMemories + Only Declare Memories on Main Func

Lowecase struct

Avoid magic strings

Make function signatures readable

Change how unsized arrays are indexed

Use string builder

Fix shuffle instructions

Cleanup NumberFormater

Bunch of Subgroup I/O Vars

Will probably need further refinement

Fix point_coord type

Fix support buffer declaration

Fix point_coord
2024-09-28 19:03:01 -04:00
Isaac Marovitz 03161d8048 PreloadCbs + FlushCommandsIfWeightExceeding 2024-09-28 19:03:01 -04:00
Isaac Marovitz b1928461bb Cleanup Pipeline
Housekeeping

More housekeeping
2024-09-28 19:03:01 -04:00
Isaac Marovitz 30b50a99e4 PersistentFlushBuffer + BackgroundResources 2024-09-28 19:03:01 -04:00
Isaac Marovitz a638060dee Match S8UintD24Unorm to Depth24UnormStencil8
Kind of works for es2gears
2024-09-28 19:03:01 -04:00
Isaac Marovitz 49781fde65 Fix FEZ not showing anything
Does not fix the underlying shortcomings of the cache system
2024-09-28 19:03:01 -04:00
Isaac Marovitz 84f3b4a3e1 Clear cached converted buffers on signaled write 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2c511cdf4f FIx regression 2024-09-28 19:03:01 -04:00
Isaac Marovitz 17cfcf07d2 Helper shader cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz 410287aba2 Use buffer manager for color blit 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6ebe5bb406 Buffer Conversions (#23)
* Why is this not working

* Revert helper shader changes for now

* Byte Index Buffer Restride
2024-09-28 19:03:01 -04:00
riperiperi 02de48a6f2 don't recreate render pipeline unless we're about to draw, pass view depth properly (#22) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 58b3e2e82b Metal: Buffers Take 2 (#21)
* Basic BufferManager

* Start Scoped Command Buffers

* Fences stuff

* Remember to cleanup sync manager

* Auto, Command Buffer Dependants

* Cleanup

* Cleanup + Fix Texture->Buffer Copies

* Slow buffer upload

* Cleanup + Rework TextureBuffer

* Don’t get unsafe

* Cleanup

* Goddamn it

* Staging Buffer + Interrupt Action + Flush
2024-09-28 19:03:01 -04:00
Isaac Marovitz d0946213fa Log failed format conversions 2024-09-28 19:03:01 -04:00
Isaac Marovitz 66e2533c90 Print shader code involved in failed linking 2024-09-28 19:03:01 -04:00
Isaac Marovitz b821cb1739 Don’t use DidModifyRange 2024-09-28 19:03:01 -04:00
Isaac Marovitz 122f0f45c8 Fix sample compare 2024-09-28 19:03:01 -04:00
Isaac Marovitz 9a6759d1e5 Depth Bias 2024-09-28 19:03:01 -04:00
Isaac Marovitz e97c9bc959 Map R5G5B5A1Unorm 2024-09-28 19:03:01 -04:00
Samuliak bc5df02d7d override Equals for render pipeline hash 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1c5937c40b Disable scaled vertex formats 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4bb736d70a Disable Vector Indexing Bug Workaround 2024-09-28 19:03:01 -04:00
Isaac Marovitz efb7baf15c Fix modulo operator
Support sample offsets

Include FragmentIn as additional arg

Always declare frag output struct

SubgroupLaneId
2024-09-28 19:03:01 -04:00
Isaac Marovitz fad653c12e Workaround for Wonder 2024-09-28 19:03:01 -04:00
Isaac Marovitz bb4cb531f2 Fix 3D -> 3D Texture Copies 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3c188718c4 Fix Clear Viewport 2024-09-28 19:03:01 -04:00
Isaac Marovitz 362672ae12 Fix sample-less reads with lod 2024-09-28 19:03:01 -04:00
Isaac Marovitz 970914e2b4 Fix Pack and UnpackHalf2x16 2024-09-28 19:03:01 -04:00
Isaac Marovitz f7e97a30af Handle Array Format SetData 2024-09-28 19:03:01 -04:00
Isaac Marovitz aae9dc0c2e Cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz b0ba5d5da1 Implement IoVariable.FrontFacing 2024-09-28 19:03:01 -04:00
Isaac Marovitz a6de2c9274 Fix LOD sample typo 2024-09-28 19:03:01 -04:00
Isaac Marovitz d323a8d44a Rebase Changes 2024-09-28 19:03:01 -04:00
Isaac Marovitz ba07a8c603 More cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz 362746887e Cleanup + Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz b064d76a4f Metal: Compute Shaders (#19)
* check for too bix texture bindings

* implement lod query

* print shader stage name

* always have fragment input

* resolve merge conflicts

* fix: lod query

* fix: casting texture coords

* support non-array memories

* use structure types for buffers

* implement compute pipeline cache

* compute dispatch

* improve error message

* rebind compute state

* bind compute textures

* pass local size as an argument to dispatch

* implement texture buffers

* hack: change vertex index to vertex id

* pass support buffer as an argument to every function

* return at the end of function

* fix: certain missing compute bindings

* implement texture base

* improve texture binding system

* remove useless exception

* move texture handle to texture base

* fix: segfault when using disposed textures

---------

Co-authored-by: Samuliak <samuliak77@gmail.com>
Co-authored-by: SamoZ256 <96914946+SamoZ256@users.noreply.github.com>
2024-09-28 19:03:01 -04:00
Isaac Marovitz 131ab75d55 Handle stride 0 on regular buffers 2024-09-28 19:03:01 -04:00
Isaac Marovitz 65149cfe9f Buffer Descriptor Step Functions 2024-09-28 19:03:01 -04:00
Isaac Marovitz a435d94fae Sample LOD Level 2024-09-28 19:03:01 -04:00
Isaac Marovitz 88dd2984be Fix FragmentOutputColor Type 2024-09-28 19:03:01 -04:00
Isaac Marovitz 43460186a8 Stencil Ref Value 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0a6f11d247 Stencil Fixes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1b86360a61 RenderTargetColorMasks 2024-09-28 19:03:01 -04:00
Isaac Marovitz dc01de61cd Make dotnet format happy 2024-09-28 19:03:01 -04:00
SamoZ256 e423f81155 Zero vertex buffer (#17)
* cast src size to float

* implement zero buffers
2024-09-28 19:03:01 -04:00
Isaac Marovitz 35f68c1b31 Implement Texture CopyTo 2024-09-28 19:03:01 -04:00
Isaac Marovitz cb8fdeafbc Cleanup present 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1f29a76ea3 Metal: Advanced Present (#6)
* Initial DrawTexture support & Advanced Present

* TODO: Get Scissors Working

* Chnage scissor state management

* Rebase problems…

* Rebase fixes again

* Update DrawTexture + Fix Topology

* Fix flipping

* Add clear action support

* Cleanup
2024-09-28 19:03:01 -04:00
SamoZ256 1f91c74a95 Clone the state & flip viewport vertically (#16)
* implement texture get data

* reset all state before blit & clone state

* format

* support blit regions

* implement source region for blit

* replace bottom with top

* account for 0 size

* support image flipping

* revert presentation fixes & y flip

* revert

* flip viewport vertically

* switch face winding

* comment

* use SetBytes for texture clear

* implement missing compute builtins

* change storage and texture buffer alignment

* correct compute builtins

* don't use nullable for textures and samplers

* remove incorrect texture get data implementation

* Cleanup IntPtrs

---------

Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
2024-09-28 19:03:01 -04:00
SamoZ256 20b1f6a6ee Fix Scott Pilgrim (#15)
* check for null vertex functions

* format

* Format

---------

Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
2024-09-28 19:03:01 -04:00
Isaac Marovitz 8b7ac4e87f Suppress GC Finalize on StateCache 2024-09-28 19:03:01 -04:00
Isaac Marovitz bbcd05aacf Use Stack instead of List 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0e095c778a Whitespace formatting 2024-09-28 19:03:01 -04:00
Samuliak 2833642858 dispose all temporary buffers 2024-09-28 19:03:01 -04:00
Samuliak f470430c2f dispose temporary metal buffer 2024-09-28 19:03:01 -04:00
Samuliak 051bd144e1 dispose drawable texture view 2024-09-28 19:03:01 -04:00
Samuliak 68f6c08287 implement texture get data 2024-09-28 19:03:01 -04:00
Samuliak 704a78c11f fix: don't dispose stencil state before using 2024-09-28 19:03:01 -04:00
Samuliak acce02bdf5 allow null depth stencil render targets 2024-09-28 19:03:01 -04:00
Samuliak 8d7be4fe25 reset certain state before doing blit or clear 2024-09-28 19:03:01 -04:00
Samuliak 57a173a671 reset viewport before blit 2024-09-28 19:03:01 -04:00
Samuliak e6e898b297 dispose encoder state manager 2024-09-28 19:03:01 -04:00
Samuliak 7654f0b16c dispose all objects in encoder state manager 2024-09-28 19:03:01 -04:00
Samuliak c26df1f7a3 dispose caches 2024-09-28 19:03:01 -04:00
Samuliak 41fb433495 warn about barriers 2024-09-28 19:03:01 -04:00
Samuliak 1a0b928c35 do memory barriers 2024-09-28 19:03:01 -04:00
Samuliak 17334b2131 remove useless parameters 2024-09-28 19:03:01 -04:00
Samuliak be9f5dcf69 set the inline state after restoring state 2024-09-28 19:03:01 -04:00
Samuliak f08d6c1cad make states private 2024-09-28 19:03:01 -04:00
Samuliak 8eba42447f fix: incorrect merge stuff 2024-09-28 19:03:01 -04:00
Samuliak 3ec45f73f4 don't interrupt render pass before color clear 2024-09-28 19:03:01 -04:00
Samuliak b475a44941 implement save and restore state system 2024-09-28 19:03:01 -04:00
Samuliak 295845e6e3 revert deferred clears 2024-09-28 19:03:01 -04:00
Samuliak 79acae3709 prepare for deferred clears 2024-09-28 19:03:01 -04:00
Samuliak d423a53595 resolve merge conflicts 2024-09-28 19:03:01 -04:00
Isaac Marovitz f4190bd95a Rebase 2024-09-28 19:03:01 -04:00
Isaac Marovitz 997393bc65 Cleanup + Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 937d84018e Start Proper Dispose 2024-09-28 19:03:01 -04:00
Samuliak 4bbf7b67d4 do texture barrier tiled 2024-09-28 19:03:01 -04:00
Samuliak b1549be8c3 do texture barrier 2024-09-28 19:03:01 -04:00
Samuliak 0d15f0fc90 implement depth stencil cache 2024-09-28 19:03:01 -04:00
Isaac Marovitz 20beb2e250 Fix typo in SamplerType.TextureBuffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz e1279f67fe Fix StoreActions & Don’t Clamp Scissor for Now 2024-09-28 19:03:01 -04:00
Isaac Marovitz bd3df5f26a Depth Clear 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8feee9c005 Shitty Clears + Inline Buffer Improvements? 2024-09-28 19:03:01 -04:00
Isaac Marovitz 087bf71a13 FragmentOutputDepth Fixes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3e1f624308 Depth Sampler Fixes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8b2cc4ccf1 Revert position changes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1aa2b793eb Nvm it should be in.position 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6f44dcc416 More shader fixes 2024-09-28 19:03:01 -04:00
Samuliak bd14efb220 fix: incorrect layer count of texture view 2024-09-28 19:03:01 -04:00
Samuliak f5cffa0b46 don't use mask on size query 2024-09-28 19:03:01 -04:00
Samuliak 979da4c1ab declare local memory 2024-09-28 19:03:01 -04:00
Samuliak f08d3a7517 support multiple render targets & fix: incorrect texture name 2024-09-28 19:03:01 -04:00
Samuliak 21029e895a put render pipeline cache into a separate file 2024-09-28 19:03:01 -04:00
Samuliak bab9542020 implement pipeline cache 2024-09-28 19:03:01 -04:00
Isaac Marovitz f2490347af Use return value of BeginRenderPass 2024-09-28 19:03:01 -04:00
Isaac Marovitz 684e025d61 Cleanup 2024-09-28 19:03:01 -04:00
Samuliak 7983bc062b remove outdated comment 2024-09-28 19:03:01 -04:00
Isaac Marovitz fe2337d61a Fix table 2024-09-28 19:03:01 -04:00
Isaac Marovitz e72c69cf19 Dont hardcode Vertex Format 2024-09-28 19:03:01 -04:00
Samuliak 9ecaacc977 style 2024-09-28 19:03:01 -04:00
Samuliak d04e24c382 bring back inline updates for some state 2024-09-28 19:03:01 -04:00
Samuliak bb425bf640 fix: don't rebind pipeline unless dirty 2024-09-28 19:03:01 -04:00
Samuliak 0444e43654 don't bind null vertex buffers 2024-09-28 19:03:01 -04:00
Samuliak ccce85e1bb mark state as dirty 2024-09-28 19:03:01 -04:00
Samuliak 348a37a355 add todo notice 2024-09-28 19:03:01 -04:00
Samuliak 918e1c16b7 don't end render pass when not neccessary 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2abadbd649 Remove rebase garbage 2024-09-28 19:03:01 -04:00
Isaac Marovitz 14c58f62eb Be smart and use a bitmask not a list 2024-09-28 19:03:01 -04:00
Isaac Marovitz 102c87e623 Cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz a7e5c26011 Fix Vertex Attributes in Wonder & Kirby 2024-09-28 19:03:01 -04:00
Isaac Marovitz 20e1d1cd33 Implement SetDepthClamp 2024-09-28 19:03:01 -04:00
Isaac Marovitz f98d9bae24 Implement SetBlendState 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1db8decd12 Be consistent with things that lack support 2024-09-28 19:03:01 -04:00
Isaac Marovitz 71ccb7eaef Ignore SetDepthMode 2024-09-28 19:03:01 -04:00
Isaac Marovitz e6c2e5873c Make Texture Volatile on dispose 2024-09-28 19:03:01 -04:00
Isaac Marovitz c97e7d621b Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 45b533b23b Fix present 2024-09-28 19:03:01 -04:00
Isaac Marovitz fbe275204b Fix Depth/Stencil attachments 2024-09-28 19:03:01 -04:00
Isaac Marovitz 738227519d Break everything :D 2024-09-28 19:03:01 -04:00
Isaac Marovitz de86f20b94 Clamp ScissorRect 2024-09-28 19:03:01 -04:00
Isaac Marovitz fcc7cb55df Set DepthAttachmentPixelFormat 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4e6abb0191 Set Depth Attachment Texture 2024-09-28 19:03:01 -04:00
Isaac Marovitz 35b0436a2b Clamp Viewport ZNear & ZFar 2024-09-28 19:03:01 -04:00
Samuliak e99f9e2af0 format 2024-09-28 19:03:01 -04:00
Samuliak bc3fd22f05 use 0 instead of undef 2024-09-28 19:03:01 -04:00
Samuliak fefdabf257 fix: pass array index as an additional argument to sample 2024-09-28 19:03:01 -04:00
Samuliak 73bb0712a8 don't declare samplers for separate textures 2024-09-28 19:03:01 -04:00
Samuliak 75781ba698 don't hardcode texture type 2024-09-28 19:03:01 -04:00
Samuliak 262452f586 offset storage buffer bindings by 15 2024-09-28 19:03:01 -04:00
Samuliak f56117a5c7 fix: incorrect abs instruction 2024-09-28 19:03:01 -04:00
Samuliak aff8fdb2f8 add: vertex and instance id arguments 2024-09-28 19:03:01 -04:00
Samuliak 3651e8ea32 determine type of buffer by its field types 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2d609ad57b Rebase + Format 2024-09-28 19:03:01 -04:00
Samuliak 559122f591 use unknown texture usage 2024-09-28 19:03:01 -04:00
Samuliak 64005ba9ee don't hardcode render pipeline attachments 2024-09-28 19:03:01 -04:00
Samuliak a11247b72d create GetSwizzle helper function 2024-09-28 19:03:01 -04:00
Samuliak 320c317113 add: textures and samplers as shader arguments & fix: issue with casting 2024-09-28 19:03:01 -04:00
Samuliak 6295153a28 support fragment coord as an input to a shader 2024-09-28 19:03:01 -04:00
Samuliak e638172753 support texture views 2024-09-28 19:03:01 -04:00
Isaac Marovitz 32db6cc281 Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 722aa4e45d Rebase + GAL Changes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 00b99770a2 Remove TODOs 2024-09-28 19:03:01 -04:00
Isaac Marovitz df6821d023 Fix Scissor/Viewport state & Validation Error 2024-09-28 19:03:01 -04:00
Isaac Marovitz 17aa3c6d0f Require Argument Buffers Tier 2 2024-09-28 19:03:01 -04:00
Isaac Marovitz 5a320cca19 Buffer bindings in shader…
Will need to be reworked
2024-09-28 19:03:01 -04:00
Isaac Marovitz 192a84aa2d Bind Uniform & Storage Buffers 2024-09-28 19:03:01 -04:00
Isaac Marovitz ebc53d7961 Fix buffer access syntax 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4d063f80b8 Dispose pipeline before window 2024-09-28 19:03:01 -04:00
Isaac Marovitz 316fea1fa9 Set scissors & viewports 2024-09-28 19:03:01 -04:00
Isaac Marovitz a9db9f5b27 Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 009f791879 Format 2024-09-28 19:03:01 -04:00
Isaac Marovitz c0bb55cf5e Fix some crashes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 54c8dabadc Fix Cubemap & Array Texture Creation 2024-09-28 19:03:01 -04:00
Isaac Marovitz 04ca284e14 Properly check for 3D 2024-09-28 19:03:01 -04:00
Isaac Marovitz d58f79ae0f Fix swizzle for certain formats 2024-09-28 19:03:01 -04:00
Isaac Marovitz cd7d62542a Blit at the end of the render 2024-09-28 19:03:01 -04:00
Isaac Marovitz 72209ba2a6 Load attachments 2024-09-28 19:03:01 -04:00
Isaac Marovitz 70ba3506b0 Cleanup Shader I/O 2024-09-28 19:03:01 -04:00
Isaac Marovitz 35cc208435 Fix fragment shader bindings 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8dca53685a Fix VertexBuffers
Naive non-managed approach
2024-09-28 19:03:01 -04:00
Isaac Marovitz e517cfeb8f Fix some shader gen problems… 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4a30b58e0b Formatting 2024-09-28 19:03:01 -04:00
Isaac Marovitz bdd9ede4fd Make TypeConversion failure an error 2024-09-28 19:03:01 -04:00
Isaac Marovitz 84a8edf675 Fix MSL Reinterpret Casts 2024-09-28 19:03:01 -04:00
Isaac Marovitz e8a2637d46 Dont set Vertex Attributes for now 2024-09-28 19:03:01 -04:00
Isaac Marovitz e4a14dd23a Remove capture code 2024-09-28 19:03:01 -04:00
Isaac Marovitz ffb7423260 Bind Textures & Samplers 2024-09-28 19:03:01 -04:00
Isaac Marovitz 80340c98d3 Revise ISampler 2024-09-28 19:03:01 -04:00
Isaac Marovitz b8c60e993a Try again 2024-09-28 19:03:01 -04:00
Isaac Marovitz d88314424b Resolve warning 2024-09-28 19:03:01 -04:00
Isaac Marovitz df8fca012f Formatting 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3d897c4f9a FIx build 2024-09-28 19:03:01 -04:00
Isaac Marovitz 62bf395970 Fix some rebase errors 2024-09-28 19:03:01 -04:00
Isaac Marovitz bb742f64c6 End Pass on Dispose 2024-09-28 19:03:01 -04:00
Isaac Marovitz a669592651 Don’t change Render State if Vertex Function is Invalid 2024-09-28 19:03:01 -04:00
Isaac Marovitz eb5fa2b546 “Report” Driver 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8e99199e19 Adjust function signature 2024-09-28 19:03:01 -04:00
Isaac Marovitz b439a52ac7 Get it building again 2024-09-28 19:03:01 -04:00
Isaac Marovitz b9c4a23f22 Render Targets 2024-09-28 19:03:01 -04:00
Isaac Marovitz 64c95bd8d8 format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 264742f085 Formatting 2024-09-28 19:03:01 -04:00
Isaac Marovitz 64d12e8d23 smh 2024-09-28 19:03:01 -04:00
Isaac Marovitz a9e9819b33 Dont specify [[stage_in]] on fragment 2024-09-28 19:03:01 -04:00
Isaac Marovitz a58d1cffe4 If one shader fails, whole program fails 2024-09-28 19:03:01 -04:00
Isaac Marovitz 511db833db Fix fragment shaders (and fuck everything up) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 2890fc1069 Vertex buffer data 2024-09-28 19:03:01 -04:00
Isaac Marovitz 7f41e7dbd4 Dont be stupid 2024-09-28 19:03:01 -04:00
Isaac Marovitz c58cc76b39 Dont set 0 attributes 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8232ce7d72 Reset Descriptor instead of making a new object 2024-09-28 19:03:01 -04:00
Isaac Marovitz db9de66437 Set Vertex Descriptor properly 2024-09-28 19:03:01 -04:00
Isaac Marovitz 5c9d1bd0da Start vertex descriptor work 2024-09-28 19:03:01 -04:00
Isaac Marovitz fb5402ce81 Implement CreateProgram 2024-09-28 19:03:01 -04:00
Isaac Marovitz ed11cdda8d Fix fragment output color 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6017c225b2 Set TargetLanguage for Metal to MSL 2024-09-28 19:03:01 -04:00
Isaac Marovitz 98e2ab5a49 Fix IoMap variable names
Output struct

Lazy Vertex IO

Output fixes

Fix output struct definition

MSL Binding Model description

Might need tweaks/adjustments

Cleanup

Typo + Format
2024-09-28 19:03:01 -04:00
Isaac Marovitz d5758cb310 Fix ETC2 PTA formats
Format
2024-09-28 19:03:01 -04:00
Isaac Marovitz 81b1ae4bcf Partial TextureQuerySamples 2024-09-28 19:03:01 -04:00
Isaac Marovitz ce5f383f5d Fix instructions 2024-09-28 19:03:01 -04:00
Isaac Marovitz d2ec22a01b LDR ASTC 2024-09-28 19:03:01 -04:00
Isaac Marovitz 53b886d893 Get build working again (values likely wrong) 2024-09-28 19:03:01 -04:00
Isaac Marovitz 29ef76f153 dotnet format 2024-09-28 19:03:01 -04:00
Isaac Marovitz a1b314acd2 Back to where we were
First special instruction

Start Load/Store implementation

Start TextureSample

Sample progress

I/O Load/Store Progress

Rest of load/store

TODO: Currently, the generator still assumes the GLSL style of I/O attributres. On MSL, the vertex function should output a struct which contains a float4 with the required position attribute.

TextureSize and VectorExtract

Fix UserDefined IO Vars

Fix stage input struct names
2024-09-28 19:03:01 -04:00
Isaac Marovitz 5198fcb881 Boot TOTK 2024-09-28 19:03:01 -04:00
Isaac Marovitz b37c109673 Boot Sonic Mania 2024-09-28 19:03:01 -04:00
Isaac Marovitz 163be0a159 Update for new Shader IR format 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1f8ae7e5b1 Update src/Ryujinx.Graphics.Metal/Pipeline.cs
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-09-28 19:03:01 -04:00
Isaac Marovitz bbc2ac2e9b Vertex Input Attributes 2024-09-28 19:03:01 -04:00
Isaac Marovitz f07327166c More Shader Gen Stuff
Mostly copied from GLSL since in terms of syntax within blocks they’re pretty similar. Likely the result will need tweaking…

Isn’t that conveniant?

“Do the simd_shuffle”

atomics

Remaining instructions

Remove removed special instructions

Getting somewhere…
2024-09-28 19:03:01 -04:00
Isaac Marovitz 1790050a14 Fix Metal Validation Error 2024-09-28 19:03:01 -04:00
Isaac Marovitz f2c090fe55 SDL2 Headless Metal Backend support 2024-09-28 19:03:01 -04:00
Isaac Marovitz fd0eaaafc1 Easier capture stuff 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0233a0d35a Define MaxFramesPerCapture 2024-09-28 19:03:01 -04:00
Isaac Marovitz 61910fe342 Cleanup encoder getting + Fix capture overflow 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1cb2ec7ebc Formatting 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4ec37d1798 Start of MSL instructions
Remaining functions
2024-09-28 19:03:01 -04:00
Isaac Marovitz 27effab989 Warn when generating unsupported shader 2024-09-28 19:03:01 -04:00
Isaac Marovitz d0d5c76f06 Pass sampler to Blit shader 2024-09-28 19:03:01 -04:00
Isaac Marovitz a03471a8ab Shader comments 2024-09-28 19:03:01 -04:00
Isaac Marovitz 93c71110e1 HelperShaders class 2024-09-28 19:03:01 -04:00
Isaac Marovitz 00fce5a51d Undertale boots 2024-09-28 19:03:01 -04:00
Isaac Marovitz ce5f5a6442 Check if packed depth is supported 2024-09-28 19:03:01 -04:00
Isaac Marovitz 541cdfebb7 Fix RGB Seizure 2024-09-28 19:03:01 -04:00
Isaac Marovitz 07be20c369 Barry is here mashallah 2024-09-28 19:03:01 -04:00
Isaac Marovitz aaa140e510 Seizure my beloved is working 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6d722d83ba SetData 2024-09-28 19:03:01 -04:00
Isaac Marovitz 6c3435aaac Look ma no crash 2024-09-28 19:03:01 -04:00
Isaac Marovitz 425177a876 Whitespace 2024-09-28 19:03:01 -04:00
Isaac Marovitz e3da359acf TODO 2024-09-28 19:03:01 -04:00
Isaac Marovitz 96bbc86331 BeginComputePass 2024-09-28 19:03:01 -04:00
Isaac Marovitz 3d42543f03 SetDepthTest 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0f52165e86 SetStencilTest 2024-09-28 19:03:01 -04:00
Isaac Marovitz 628772f685 Forgot depth 2024-09-28 19:03:01 -04:00
Isaac Marovitz 118d10bc32 Texture usage 2024-09-28 19:03:01 -04:00
Isaac Marovitz 33a986317b CopyBuffer to Buffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz 7a2ab77b4d CopyTo Buffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz 08126b26b1 SetData without region 2024-09-28 19:03:01 -04:00
Isaac Marovitz abcd2b2754 Rewrite SetData for GPU 2024-09-28 19:03:01 -04:00
Isaac Marovitz d076a70816 Clear Buffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz 28da4248ae Use Ryujinx Logger 2024-09-28 19:03:01 -04:00
Isaac Marovitz f4aea9b7ec One encoder at a time 2024-09-28 19:03:01 -04:00
Isaac Marovitz e269d1605d Fix byte alignment 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8b21447018 Finish SetData /w region 2024-09-28 19:03:01 -04:00
Isaac Marovitz 66d575965c Spoof Counters 2024-09-28 19:03:01 -04:00
Isaac Marovitz 4104af65a3 BufferAccess 2024-09-28 19:03:01 -04:00
Isaac Marovitz 8da7c42cf8 Delete and Get Data from Buffer 2024-09-28 19:03:01 -04:00
Isaac Marovitz da9a194023 Bump SharpMetal 2024-09-28 19:03:01 -04:00
Isaac Marovitz 5dd444f605 Start Texture region-based CopyTo 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0f3358b931 IoMap 2024-09-28 19:03:01 -04:00
Isaac Marovitz 177303d223 Fix error 2024-09-28 19:03:01 -04:00
Isaac Marovitz 0eaee442c7 Renderer cleanup 2024-09-28 19:03:01 -04:00
Isaac Marovitz 70f54f23c9 Texture Copys 2024-09-28 19:03:01 -04:00
Isaac Marovitz 1e36815713 Texture, Pipeline, Sample, Renderer Improvements 2024-09-28 19:03:01 -04:00
Isaac Marovitz ebaf1d8258 Start Metal Backend
Revert build yml changes
2024-09-28 19:03:01 -04:00
436 changed files with 42341 additions and 16229 deletions
+9 -1
View File
@@ -32,4 +32,12 @@ kernel:
infra: infra:
- changed-files: - changed-files:
- any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props'] - any-glob-to-any-file: ['.github/**', 'distribution/**', 'Directory.Packages.props', 'src/Ryujinx.BuildValidationTasks/**']
documentation:
- changed-files:
- any-glob-to-any-file: 'docs/**'
ldn:
- changed-files:
- any-glob-to-any-file: 'src/Ryujinx.HLE/HOS/Services/Ldn/**'
+2 -2
View File
@@ -122,7 +122,7 @@ jobs:
- name: Upload Ryujinx.Headless.SDL2 artifact - name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }} name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.platform.zip_os_name }}
path: publish_sdl2_headless path: publish_sdl2_headless
if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13' if: github.event_name == 'pull_request' && matrix.platform.os != 'macos-13'
@@ -185,6 +185,6 @@ jobs:
- name: Upload Ryujinx.Headless.SDL2 artifact - name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal name: nogui-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_headless/*.tar.gz" path: "publish_headless/*.tar.gz"
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
+35 -11
View File
@@ -54,7 +54,19 @@ jobs:
with: with:
name: "Canary ${{ steps.version_info.outputs.build_version }}" name: "Canary ${{ steps.version_info.outputs.build_version }}"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}" body: |
# Canary builds:
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/${{ github.repository }}/releases/latest) instead if that sounds like something you don't want to deal with.
| Platform | Artifact |
|--|--|
| Windows 64-bit | [Canary Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
| Linux 64-bit | [Canary Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Canary Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Canary macOS artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
@@ -103,20 +115,20 @@ 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 -p:IncludeNativeLibrariesForSelfExtract=true 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_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained -p:IncludeNativeLibrariesForSelfExtract=true dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless/publish -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --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_ava
rm publish/libarmeilleure-jitsupport.dylib rm publish/libarmeilleure-jitsupport.dylib
7z a ../release_output/ryujinx-${{ 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
pushd publish_sdl2_headless pushd publish_sdl2_headless
rm publish/libarmeilleure-jitsupport.dylib rm publish/libarmeilleure-jitsupport.dylib
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish 7z a ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip publish
popd popd
shell: bash shell: bash
@@ -126,13 +138,13 @@ jobs:
pushd publish_ava pushd publish_ava
rm publish/libarmeilleure-jitsupport.dylib rm publish/libarmeilleure-jitsupport.dylib
chmod +x publish/Ryujinx.sh publish/Ryujinx chmod +x publish/Ryujinx.sh publish/Ryujinx
tar -czvf ../release_output/ryujinx-${{ 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
pushd publish_sdl2_headless pushd publish_sdl2_headless
rm publish/libarmeilleure-jitsupport.dylib rm publish/libarmeilleure-jitsupport.dylib
chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2 chmod +x publish/Ryujinx.sh publish/Ryujinx.Headless.SDL2
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish tar -czvf ../release_output/nogui-ryujinx-canary-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz publish
popd popd
shell: bash shell: bash
@@ -181,7 +193,19 @@ jobs:
artifacts: "release_output/*.tar.gz,release_output/*.zip" artifacts: "release_output/*.tar.gz,release_output/*.zip"
#artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*" #artifacts: "release_output/*.tar.gz,release_output/*.zip/*AppImage*"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}" body: |
# Canary builds:
These builds are experimental and may sometimes not work, use [regular builds](https://github.com/GreemDev/Ryujinx/releases/latest) instead if that sounds like something you don't want to deal with.
| Platform | Artifact |
|--|--|
| Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
| Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
| Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
| macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-canary-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
"**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_SOURCE_REPO }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -236,11 +260,11 @@ jobs:
- name: Publish macOS Ryujinx - name: Publish macOS Ryujinx
run: | run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish_ava ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
- name: Publish macOS Ryujinx.Headless.SDL2 - name: Publish macOS Ryujinx.Headless.SDL2
run: | run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release ./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 1
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
@@ -248,7 +272,7 @@ jobs:
name: "Canary ${{ steps.version_info.outputs.build_version }}" name: "Canary ${{ steps.version_info.outputs.build_version }}"
artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz" artifacts: "publish_ava/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/Canary-${{ steps.version_info.outputs.prev_build_version }}...Canary-${{ steps.version_info.outputs.build_version }}" body: ""
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
+2 -2
View File
@@ -38,12 +38,12 @@ jobs:
return core.error(`No artifacts found`); return core.error(`No artifacts found`);
} }
let body = `Download the artifacts for this pull request:\n`; let body = `Download the artifacts for this pull request:\n`;
let hidden_headless_artifacts = `\n\n <details><summary>GUI-less (SDL2)</summary>\n`; let hidden_headless_artifacts = `\n\n <details><summary>GUI-less</summary>\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) {
if(art.name.includes('Debug')) { if(art.name.includes('Debug')) {
hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; hidden_debug_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else if(art.name.includes('sdl2-ryujinx-headless')) { } else if(art.name.includes('nogui-ryujinx')) {
hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; hidden_headless_artifacts += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
} else { } else {
body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; body += `\n* [${art.name}](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`;
+28 -10
View File
@@ -53,7 +53,16 @@ jobs:
with: with:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}" body: |
# Regular builds:
| Platform | Artifact |
|--|--|
| Windows 64-bit | [Release Windows Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip) |
| Linux 64-bit | [Release Linux Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz) |
| Linux ARM 64-bit | [Release Linux ARM Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz) |
| macOS | [Release macOS Artifact](https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz) |
**Full Changelog**: https://github.com/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}/${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }} owner: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_OWNER }}
repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }} repo: ${{ env.RYUJINX_TARGET_RELEASE_CHANNEL_REPO }}
@@ -102,8 +111,8 @@ jobs:
- name: Publish - name: Publish
run: | run: |
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 -p:IncludeNativeLibrariesForSelfExtract=true 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
dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained -p:IncludeNativeLibrariesForSelfExtract=true dotnet publish -c Release -r "${{ matrix.platform.name }}" -o ./publish_sdl2_headless -p:Version="${{ steps.version_info.outputs.build_version }}" -p:SourceRevisionId="${{ steps.version_info.outputs.git_short_hash }}" -p:DebugType=embedded src/Ryujinx.Headless.SDL2 --self-contained
- name: Packing Windows builds - name: Packing Windows builds
if: matrix.platform.os == 'windows-latest' if: matrix.platform.os == 'windows-latest'
@@ -115,7 +124,7 @@ jobs:
pushd publish_sdl2_headless pushd publish_sdl2_headless
rm libarmeilleure-jitsupport.dylib rm libarmeilleure-jitsupport.dylib
7z a ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish 7z a ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.zip ../publish
popd popd
shell: bash shell: bash
@@ -166,7 +175,7 @@ jobs:
pushd publish_sdl2_headless pushd publish_sdl2_headless
chmod +x Ryujinx.sh Ryujinx.Headless.SDL2 chmod +x Ryujinx.sh Ryujinx.Headless.SDL2
tar -czvf ../release_output/sdl2-ryujinx-headless-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish tar -czvf ../release_output/nogui-ryujinx-${{ steps.version_info.outputs.build_version }}-${{ matrix.platform.zip_os_name }}.tar.gz ../publish
popd popd
shell: bash shell: bash
@@ -174,9 +183,18 @@ jobs:
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/*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: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}" body: |
# Regular builds:
| Platform | Artifact |
|--|--|
| Windows 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-win_x64.zip |
| Linux 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_x64.tar.gz |
| Linux ARM 64-bit | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-linux_arm64.tar.gz |
| macOS | https://github.com/${{ github.repository }}/releases/download/${{ steps.version_info.outputs.build_version }}/ryujinx-${{ steps.version_info.outputs.build_version }}-macos_universal.app.tar.gz |
"**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}"
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
@@ -231,11 +249,11 @@ jobs:
- name: Publish macOS Ryujinx - name: Publish macOS Ryujinx
run: | run: |
./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release ./distribution/macos/create_macos_build_ava.sh . publish_tmp_ava publish ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
- name: Publish macOS Ryujinx.Headless.SDL2 - name: Publish macOS Ryujinx.Headless.SDL2
run: | run: |
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release ./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ steps.version_info.outputs.build_version }}" "${{ steps.version_info.outputs.git_short_hash }}" Release 0
- name: Pushing new release - name: Pushing new release
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
@@ -243,7 +261,7 @@ jobs:
name: ${{ steps.version_info.outputs.build_version }} name: ${{ steps.version_info.outputs.build_version }}
artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz" artifacts: "publish/*.tar.gz, publish_headless/*.tar.gz"
tag: ${{ steps.version_info.outputs.build_version }} tag: ${{ steps.version_info.outputs.build_version }}
body: "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.version_info.outputs.prev_build_version }}...${{ steps.version_info.outputs.build_version }}" body: ""
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
allowUpdates: true allowUpdates: true
replacesArtifacts: true replacesArtifacts: true
+3
View File
@@ -175,3 +175,6 @@ PublishProfiles/
# Glade backup files # Glade backup files
*.glade~ *.glade~
# Ignore MacOS Attribute Files
._*
+23
View File
@@ -0,0 +1,23 @@
## Compilation
Building the project is for users that want to contribute code only.
If you wish to build the emulator yourself, follow these steps:
### Step 1
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2
Either use `git clone https://github.com/GreemDev/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3
To build Ryujinx, open a command prompt inside the project directory.
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
Then type the following command: `dotnet build -c Release -o build`
the built files will be found in the newly created build directory.
Ryujinx system files are stored in the `Ryujinx` folder.
This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
+2 -2
View File
@@ -74,7 +74,7 @@ We use and recommend the following workflow:
3. In your fork, create a branch off of main (`git checkout -b mybranch`). 3. In your fork, create a branch off of main (`git checkout -b mybranch`).
- Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork. - Branches are useful since they isolate your changes from incoming changes from upstream. They also enable you to create multiple PRs from the same fork.
4. Make and commit your changes to your branch. 4. Make and commit your changes to your branch.
- [Build Instructions](https://github.com/GreemDev/Ryujinx#building) explains how to build and test. - [Build Instructions](https://github.com/GreemDev/Ryujinx/blob/master/COMPILING.md) explains how to build and test.
- Commit messages should be clear statements of action and intent. - Commit messages should be clear statements of action and intent.
6. Build the repository with your changes. 6. Build the repository with your changes.
- Make sure that the builds are clean. - Make sure that the builds are clean.
@@ -83,7 +83,7 @@ We use and recommend the following workflow:
- State in the description what issue or improvement your change is addressing. - State in the description what issue or improvement your change is addressing.
- Check if all the Continuous Integration checks are passing. Refer to [Actions](https://github.com/GreemDev/Ryujinx/actions) to check for outstanding errors. - Check if all the Continuous Integration checks are passing. Refer to [Actions](https://github.com/GreemDev/Ryujinx/actions) to check for outstanding errors.
8. Wait for feedback or approval of your changes from the core development team 8. Wait for feedback or approval of your changes from the core development team
- Details about the pull request [review procedure](docs/workflow/ci/pr-guide.md). - Details about the pull request [review procedure](docs/workflow/pr-guide.md).
9. When the team members have signed off, and all checks are green, your PR will be merged. 9. When the team members have signed off, and all checks are green, your PR will be merged.
- The next official build will automatically include your change. - The next official build will automatically include your change.
- You can delete the branch you used for making the change. - You can delete the branch you used for making the change.
+6
View File
@@ -0,0 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>
+8 -4
View File
@@ -10,6 +10,9 @@
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" /> <PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.10" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg" Version="11.0.0.18" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" /> <PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.18" />
<PackageVersion Include="Microsoft.Build.Framework" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.4.0" /> <PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.4.0" />
<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"/>
@@ -38,9 +41,10 @@
<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.6.5" /> <PackageVersion Include="Gommon" Version="2.6.8" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpMetal" Version="1.0.0-preview20" />
<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.21.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
@@ -48,8 +52,8 @@
<PackageVersion Include="SkiaSharp" Version="2.88.7" /> <PackageVersion Include="SkiaSharp" Version="2.88.7" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
<PackageVersion Include="SPB" Version="0.0.4-build32" /> <PackageVersion Include="SPB" Version="0.0.4-build32" />
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" /> <PackageVersion Include="System.IO.Hashing" Version="9.0.0" />
<PackageVersion Include="System.Management" Version="8.0.0" /> <PackageVersion Include="System.Management" Version="9.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+29 -65
View File
@@ -1,35 +1,26 @@
<h1 align="center"> <table align="center">
<tr>
<td align="center" width="25%">
<img src="https://raw.githubusercontent.com/GreemDev/ryuassets/refs/heads/main/RyujinxApp_1024.png" alt="Ryujinx" >
</td>
<td align="center" width="75%">
# Ryujinx
[![Release workflow](https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml/badge.svg)](https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml)
[![Latest release](https://img.shields.io/github/v/release/GreemDev/Ryujinx)](https://github.com/GreemDev/Ryujinx/releases/latest)
<br> <br>
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/master/distribution/misc/Logo.svg" alt="Ryujinx" width="150"></a> [![Canary workflow](https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml/badge.svg)](https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml)
<br> [![Latest canary release](https://img.shields.io/github/v/release/GreemDev/Ryujinx-Canary?label=canary)](https://github.com/GreemDev/Ryujinx-Canary/releases/latest)
<b>Ryujinx</b> </td>
<br> </tr>
<sub><sup><b>(REE-YOU-JINX)</b></sup></sub> </table>
<br>
<a href="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml">
<img src="https://github.com/GreemDev/Ryujinx/actions/workflows/release.yml/badge.svg"
alt="">
</a>
<a href="https://github.com/GreemDev/Ryujinx/releases/latest">
<img src="https://img.shields.io/github/v/release/GreemDev/Ryujinx"
alt="Latest Release">
</a>
<br>
<a href="https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml">
<img src="https://github.com/GreemDev/Ryujinx/actions/workflows/canary.yml/badge.svg"
alt="">
</a>
<a href="https://github.com/GreemDev/Ryujinx-Canary/releases/latest">
<img src="https://img.shields.io/github/v/release/GreemDev/Ryujinx-Canary?label=canary"
alt="Latest Canary Release">
</a>
</h1>
<p align="center"> <p align="center">
Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#. Ryujinx is an open-source Nintendo Switch emulator, originally created by gdkchan, written in C#.
This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds. This emulator aims at providing excellent accuracy and performance, a user-friendly interface and consistent builds.
It was written from scratch and development on the project began in September 2017. It was written from scratch and development on the project began in September 2017.
Ryujinx is available on Github under the <a href="https://github.com/GreemDev/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>. Ryujinx is available on GitHub under the <a href="https://github.com/GreemDev/Ryujinx/blob/master/LICENSE.txt" target="_blank">MIT license</a>.
<br /> <br />
</p> </p>
<p align="center"> <p align="center">
@@ -42,7 +33,7 @@
Guides and documentation can be found on the <a href="https://github.com/GreemDev/Ryujinx/wiki">Wiki tab</a>. Guides and documentation can be found on the <a href="https://github.com/GreemDev/Ryujinx/wiki">Wiki tab</a>.
</p> </p>
<p align="center"> <p align="center">
If you would like a version more preservative fork of Ryujinx, check out <a href="https://github.com/ryujinx-mirror/ryujinx">ryujinx-mirror</a>. If you would like a more preservative fork of Ryujinx, check out <a href="https://github.com/ryujinx-mirror/ryujinx">ryujinx-mirror</a>.
</p> </p>
<p align="center"> <p align="center">
@@ -56,55 +47,28 @@
<img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png"> <img src="https://raw.githubusercontent.com/GreemDev/Ryujinx/refs/heads/master/docs/shell.png">
</p> </p>
## Compatibility
As of May 2024, Ryujinx has been tested on approximately 4,300 titles;
over 4,100 boot past menus and into gameplay, with roughly 3,550 of those being considered playable.
Anyone is free to submit a new game test or update an existing game test entry;
simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue.
Use the search function to see if a game has been tested already!
## Usage ## Usage
To run this emulator, your PC must be equipped with at least 8GiB of RAM; To run this emulator, your PC must be equipped with at least 8GiB of RAM;
failing to meet this requirement may result in a poor gameplay experience or unexpected crashes. failing to meet this requirement may result in a poor gameplay experience or unexpected crashes.
## Latest release ## Latest build
Releases are compiled automatically for each commit on the master branch. Stable builds are made every so often onto a separate "release" branch that then gets put into the releases you know and love.
While we strive to ensure optimal stability and performance prior to pushing an update, our automated builds **may be unstable or completely broken**. These stable builds exist so that the end user can get a more **enjoyable and stable experience**.
You can find the latest release [here](https://github.com/GreemDev/Ryujinx/releases/latest). You can find the latest stable release [here](https://github.com/GreemDev/Ryujinx/releases/latest).
Canary builds are compiled automatically for each commit on the master branch.
While we strive to ensure optimal stability and performance prior to pushing an update, these builds **may be unstable or completely broken**.
These canary builds are only recommended for experienced users.
You can find the latest canary release [here](https://github.com/GreemDev/Ryujinx-Canary/releases/latest).
## Documentation ## Documentation
If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md). If you are planning to contribute or just want to learn more about this project please read through our [documentation](docs/README.md).
## Building
Building the project is for advanced users.
If you wish to build the emulator yourself, follow these steps:
### Step 1
Install the [.NET 8.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/8.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2
Either use `git clone https://github.com/GreemDev/Ryujinx` on the command line to clone the repository or use Code --> Download zip button to get the files.
### Step 3
To build Ryujinx, open a command prompt inside the project directory.
You can quickly access it on Windows by holding shift in File Explorer, then right clicking and selecting `Open command window here`.
Then type the following command: `dotnet build -c Release -o build`
the built files will be found in the newly created build directory.
Ryujinx system files are stored in the `Ryujinx` folder.
This folder is located in the user folder, which can be accessed by clicking `Open Ryujinx Folder` under the File menu in the GUI.
## Features ## Features
- **Audio** - **Audio**
@@ -118,7 +82,7 @@ This folder is located in the user folder, which can be accessed by clicking `Op
It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code. It translates the ARM code to a custom IR, performs a few optimizations, and turns that into x86 code.
There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster). There are three memory manager options available depending on the user's preference, leveraging both software-based (slower) and host-mapped modes (much faster).
The fastest option (host, unchecked) is set by default. The fastest option (host, unchecked) is set by default.
Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads. Ryujinx also features an optional Profiled Persistent Translation Cache, which essentially caches translated functions so that they do not need to be translated every time the game loads.
The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game. The net result is a significant reduction in load times (the amount of time between launching a game and arriving at the title screen) for nearly every game.
NOTE: This feature is enabled by default in the Options menu > System tab. NOTE: This feature is enabled by default in the Options menu > System tab.
You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch! You must launch the game at least twice to the title screen or beyond before performance improvements are unlocked on the third launch!
+16 -3
View File
@@ -80,16 +80,22 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
ProjectSection(ProjectDependencies) = postProject
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
.github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props Directory.Packages.props = Directory.Packages.props
.github/workflows/release.yml = .github/workflows/release.yml .github\workflows\release.yml = .github\workflows\release.yml
.github/workflows/canary.yml = .github/workflows/canary.yml
.github/workflows/build.yml = .github/workflows/build.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -252,6 +258,13 @@ Global
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+450 -2
View File
@@ -707,6 +707,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010300", "head": "01010300",
@@ -3526,6 +3542,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01400000", "head": "01400000",
@@ -4160,6 +4192,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -5848,6 +5896,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -6126,6 +6190,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -8341,6 +8421,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -9020,6 +9116,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000100", "head": "01000100",
@@ -9496,6 +9608,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010000", "head": "01010000",
@@ -9833,6 +9961,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -14667,6 +14811,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01030000", "head": "01030000",
@@ -16119,6 +16279,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01050000", "head": "01050000",
@@ -16717,6 +16893,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01070000", "head": "01070000",
@@ -19745,6 +19937,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01080000", "head": "01080000",
@@ -20503,6 +20711,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010000", "head": "01010000",
@@ -21805,6 +22029,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -22340,6 +22580,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01020100", "head": "01020100",
@@ -22990,6 +23246,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -23440,6 +23712,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -24660,6 +24948,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01410000", "head": "01410000",
@@ -24954,6 +25258,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01060000", "head": "01060000",
@@ -25286,6 +25606,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -29114,6 +29450,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010000", "head": "01010000",
@@ -32512,6 +32864,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -32928,6 +33296,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000100", "head": "01000100",
@@ -34800,6 +35184,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Red Tunic",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01000000", "head": "01000000",
@@ -37569,6 +37969,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010100", "head": "01010100",
@@ -41293,6 +41709,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Black Cat Clothes",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01020100", "head": "01020100",
@@ -45153,6 +45585,22 @@
"0100F2C0115B6000" "0100F2C0115B6000"
], ],
"gameName": "The Legend of Zelda: Tears of the Kingdom" "gameName": "The Legend of Zelda: Tears of the Kingdom"
},
{
"amiiboUsage": [
{
"Usage": "Receive the Blue Attire",
"write": false
},
{
"Usage": "Receive random materials",
"write": false
}
],
"gameID": [
"01008CF01BAAC000"
],
"gameName": "The Legend of Zelda: Echoes of Wisdom"
} }
], ],
"head": "01010000", "head": "01010000",
@@ -47896,5 +48344,5 @@
"type": "Figure" "type": "Figure"
} }
], ],
"lastUpdated": "2024-10-01T00:00:25.035619" "lastUpdated": "2024-11-17T15:28:47.035619"
} }
+1 -1
View File
@@ -14,7 +14,7 @@ if [ -z "$RYUJINX_BIN" ]; then
exit 1 exit 1
fi fi
COMMAND="env DOTNET_EnableAlternateStackCheck=1" COMMAND="env LANG=C.UTF-8 DOTNET_EnableAlternateStackCheck=1"
if command -v gamemoderun > /dev/null 2>&1; then if command -v gamemoderun > /dev/null 2>&1; then
COMMAND="$COMMAND gamemoderun" COMMAND="$COMMAND gamemoderun"
+2 -2
View File
@@ -40,11 +40,11 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.1</string> <string>1.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.1.0</string> <string>1.2.0</string>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>
Binary file not shown.
+7 -6
View File
@@ -2,8 +2,8 @@
set -e set -e
if [ "$#" -lt 7 ]; then if [ "$#" -lt 8 ]; then
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <EXTRA_ARGS>" echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <CANARY>"
exit 1 exit 1
fi fi
@@ -18,10 +18,11 @@ ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
VERSION=$5 VERSION=$5
SOURCE_REVISION_ID=$6 SOURCE_REVISION_ID=$6
CONFIGURATION=$7 CONFIGURATION=$7
EXTRA_ARGS=$8 CANARY=$8
if [ "$VERSION" == "1.1.0" ]; if [ "$CANARY" == "1" ]; then
then RELEASE_TAR_FILE_NAME=ryujinx-canary-$VERSION-macos_universal.app.tar
elif [ "$VERSION" == "1.1.0" ]; then
RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar RELEASE_TAR_FILE_NAME=ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.app.tar
else else
RELEASE_TAR_FILE_NAME=ryujinx-$VERSION-macos_universal.app.tar RELEASE_TAR_FILE_NAME=ryujinx-$VERSION-macos_universal.app.tar
@@ -61,7 +62,7 @@ mkdir -p "$OUTPUT_DIRECTORY"
cp -R "$ARM64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE" cp -R "$ARM64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE"
rm "$UNIVERSAL_APP_BUNDLE/$EXECUTABLE_SUB_PATH" rm "$UNIVERSAL_APP_BUNDLE/$EXECUTABLE_SUB_PATH"
# Make it libraries universal # Make its libraries universal
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_BUNDLE" "$X64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE" "**/*.dylib" python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_APP_BUNDLE" "$X64_APP_BUNDLE" "$UNIVERSAL_APP_BUNDLE" "**/*.dylib"
if ! [ -x "$(command -v lipo)" ]; if ! [ -x "$(command -v lipo)" ];
@@ -2,8 +2,8 @@
set -e set -e
if [ "$#" -lt 7 ]; then if [ "$#" -lt 8 ]; then
echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <EXTRA_ARGS>" echo "usage <BASE_DIR> <TEMP_DIRECTORY> <OUTPUT_DIRECTORY> <ENTITLEMENTS_FILE_PATH> <VERSION> <SOURCE_REVISION_ID> <CONFIGURATION> <CANARY>"
exit 1 exit 1
fi fi
@@ -18,13 +18,14 @@ ENTITLEMENTS_FILE_PATH=$(readlink -f "$4")
VERSION=$5 VERSION=$5
SOURCE_REVISION_ID=$6 SOURCE_REVISION_ID=$6
CONFIGURATION=$7 CONFIGURATION=$7
EXTRA_ARGS=$8 CANARY=$8
if [ "$VERSION" == "1.1.0" ]; if [ "$CANARY" == "1" ]; then
then RELEASE_TAR_FILE_NAME=nogui-ryujinx-canary-$VERSION-macos_universal.tar
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar elif [ "$VERSION" == "1.1.0" ]; then
RELEASE_TAR_FILE_NAME=nogui-ryujinx-$CONFIGURATION-$VERSION+$SOURCE_REVISION_ID-macos_universal.tar
else else
RELEASE_TAR_FILE_NAME=sdl2-ryujinx-headless-$VERSION-macos_universal.tar RELEASE_TAR_FILE_NAME=nogui-ryujinx-$VERSION-macos_universal.tar
fi fi
ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64" ARM64_OUTPUT="$TEMP_DIRECTORY/publish_arm64"
@@ -56,7 +57,7 @@ mkdir -p "$OUTPUT_DIRECTORY"
cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT" cp -R "$ARM64_OUTPUT/" "$UNIVERSAL_OUTPUT"
rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH" rm "$UNIVERSAL_OUTPUT/$EXECUTABLE_SUB_PATH"
# Make it libraries universal # Make its libraries universal
python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib" python3 "$BASE_DIR/distribution/macos/construct_universal_dylib.py" "$ARM64_OUTPUT" "$X64_OUTPUT" "$UNIVERSAL_OUTPUT" "**/*.dylib"
if ! [ -x "$(command -v lipo)" ]; if ! [ -x "$(command -v lipo)" ];
+2 -2
View File
@@ -17,7 +17,7 @@ error_handler() {
set the button_pressed to the button returned of the result set the button_pressed to the button returned of the result
if the button_pressed is \"Open Download Page\" then if the button_pressed is \"Open Download Page\" then
open location \"https://ryujinx.org/download\" open location \"https://ryujinx.app/download\"
end if end if
""" """
@@ -54,4 +54,4 @@ if [ "$#" -le 3 ]; then
open -a "$INSTALL_DIRECTORY" open -a "$INSTALL_DIRECTORY"
else else
open -a "$INSTALL_DIRECTORY" --args "${APP_ARGUMENTS[@]}" open -a "$INSTALL_DIRECTORY" --args "${APP_ARGUMENTS[@]}"
fi fi
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

+1 -1
View File
@@ -9,7 +9,7 @@ To merge pull requests, you must have write permissions in the repository.
## Quick Code Review Rules ## Quick Code Review Rules
* Do not mix unrelated changes in one pull request. For example, a code style change should never be mixed with a bug fix. * Do not mix unrelated changes in one pull request. For example, a code style change should never be mixed with a bug fix.
* All changes should follow the existing code style. You can read more about our code style at [docs/coding-guidelines](../coding-guidelines/coding-style.md). * All changes should follow the existing code style. You can read more about our code style at [docs/coding-style](../coding-guidelines/coding-style.md).
* Adding external dependencies is to be avoided unless not doing so would introduce _significant_ complexity. Any dependency addition should be justified and discussed before merge. * Adding external dependencies is to be avoided unless not doing so would introduce _significant_ complexity. Any dependency addition should be justified and discussed before merge.
* Use Draft pull requests for changes you are still working on but want early CI loop feedback. When you think your changes are ready for review, [change the status](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request) of your pull request. * Use Draft pull requests for changes you are still working on but want early CI loop feedback. When you think your changes are ready for review, [change the status](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request) of your pull request.
* Rebase your changes when required or directly requested. Changes should always be commited on top of the upstream branch, not the other way around. * Rebase your changes when required or directly requested. Changes should always be commited on top of the upstream branch, not the other way around.
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "8.0.100", "version": "9.0.100",
"rollForward": "latestFeature" "rollForward": "latestFeature"
} }
} }
+1 -1
View File
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
-252
View File
@@ -1,252 +0,0 @@
using ARMeilleure.Diagnostics;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ARMeilleure.Common
{
/// <summary>
/// Represents a table of guest address to a value.
/// </summary>
/// <typeparam name="TEntry">Type of the value</typeparam>
public unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
{
/// <summary>
/// Represents a level in an <see cref="AddressTable{TEntry}"/>.
/// </summary>
public readonly struct Level
{
/// <summary>
/// Gets the index of the <see cref="Level"/> in the guest address.
/// </summary>
public int Index { get; }
/// <summary>
/// Gets the length of the <see cref="Level"/> in the guest address.
/// </summary>
public int Length { get; }
/// <summary>
/// Gets the mask which masks the bits used by the <see cref="Level"/>.
/// </summary>
public ulong Mask => ((1ul << Length) - 1) << Index;
/// <summary>
/// Initializes a new instance of the <see cref="Level"/> structure with the specified
/// <paramref name="index"/> and <paramref name="length"/>.
/// </summary>
/// <param name="index">Index of the <see cref="Level"/></param>
/// <param name="length">Length of the <see cref="Level"/></param>
public Level(int index, int length)
{
(Index, Length) = (index, length);
}
/// <summary>
/// Gets the value of the <see cref="Level"/> from the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Value of the <see cref="Level"/> from the specified guest <paramref name="address"/></returns>
public int GetValue(ulong address)
{
return (int)((address & Mask) >> Index);
}
}
private bool _disposed;
private TEntry** _table;
private readonly List<nint> _pages;
/// <summary>
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
public ulong Mask { get; }
/// <summary>
/// Gets the <see cref="Level"/>s used by the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
public Level[] Levels { get; }
/// <summary>
/// Gets or sets the default fill value of newly created leaf pages.
/// </summary>
public TEntry Fill { get; set; }
/// <summary>
/// Gets the base address of the <see cref="EntryTable{TEntry}"/>.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
public nint Base
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_pages)
{
return (nint)GetRootPage();
}
}
}
/// <summary>
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
/// <see cref="Level"/>.
/// </summary>
/// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
public AddressTable(Level[] levels)
{
ArgumentNullException.ThrowIfNull(levels);
if (levels.Length < 2)
{
throw new ArgumentException("Table must be at least 2 levels deep.", nameof(levels));
}
_pages = new List<nint>(capacity: 16);
Levels = levels;
Mask = 0;
foreach (var level in Levels)
{
Mask |= level.Mask;
}
}
/// <summary>
/// Determines if the specified <paramref name="address"/> is in the range of the
/// <see cref="AddressTable{TEntry}"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns>
public bool IsValid(ulong address)
{
return (address & ~Mask) == 0;
}
/// <summary>
/// Gets a reference to the value at the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Reference to the value at the specified guest <paramref name="address"/></returns>
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
public ref TEntry GetValue(ulong address)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (!IsValid(address))
{
throw new ArgumentException($"Address 0x{address:X} is not mapped onto the table.", nameof(address));
}
lock (_pages)
{
return ref GetPage(address)[Levels[^1].GetValue(address)];
}
}
/// <summary>
/// Gets the leaf page for the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Leaf page for the specified guest <paramref name="address"/></returns>
private TEntry* GetPage(ulong address)
{
TEntry** page = GetRootPage();
for (int i = 0; i < Levels.Length - 1; i++)
{
ref Level level = ref Levels[i];
ref TEntry* nextPage = ref page[level.GetValue(address)];
if (nextPage == null)
{
ref Level nextLevel = ref Levels[i + 1];
nextPage = i == Levels.Length - 2 ?
(TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true) :
(TEntry*)Allocate(1 << nextLevel.Length, nint.Zero, leaf: false);
}
page = (TEntry**)nextPage;
}
return (TEntry*)page;
}
/// <summary>
/// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
/// </summary>
/// <returns>Root page of the <see cref="AddressTable{TEntry}"/></returns>
private TEntry** GetRootPage()
{
if (_table == null)
{
_table = (TEntry**)Allocate(1 << Levels[0].Length, fill: nint.Zero, leaf: false);
}
return _table;
}
/// <summary>
/// Allocates a block of memory of the specified type and length.
/// </summary>
/// <typeparam name="T">Type of elements</typeparam>
/// <param name="length">Number of elements</param>
/// <param name="fill">Fill value</param>
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
/// <returns>Allocated block</returns>
private nint Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
{
var size = sizeof(T) * length;
var page = (nint)NativeAllocator.Instance.Allocate((uint)size);
var span = new Span<T>((void*)page, length);
span.Fill(fill);
_pages.Add(page);
TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
return page;
}
/// <summary>
/// Releases all resources used by the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases all unmanaged and optionally managed resources used by the <see cref="AddressTable{TEntry}"/>
/// instance.
/// </summary>
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
foreach (var page in _pages)
{
Marshal.FreeHGlobal(page);
}
_disposed = true;
}
}
/// <summary>
/// Frees resources used by the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
~AddressTable()
{
Dispose(false);
}
}
}
@@ -0,0 +1,44 @@
namespace ARMeilleure.Common
{
/// <summary>
/// Represents a level in an <see cref="IAddressTable{TEntry}"/>.
/// </summary>
public readonly struct AddressTableLevel
{
/// <summary>
/// Gets the index of the <see cref="Level"/> in the guest address.
/// </summary>
public int Index { get; }
/// <summary>
/// Gets the length of the <see cref="AddressTableLevel"/> in the guest address.
/// </summary>
public int Length { get; }
/// <summary>
/// Gets the mask which masks the bits used by the <see cref="AddressTableLevel"/>.
/// </summary>
public ulong Mask => ((1ul << Length) - 1) << Index;
/// <summary>
/// Initializes a new instance of the <see cref="AddressTableLevel"/> structure with the specified
/// <paramref name="index"/> and <paramref name="length"/>.
/// </summary>
/// <param name="index">Index of the <see cref="AddressTableLevel"/></param>
/// <param name="length">Length of the <see cref="AddressTableLevel"/></param>
public AddressTableLevel(int index, int length)
{
(Index, Length) = (index, length);
}
/// <summary>
/// Gets the value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Value of the <see cref="AddressTableLevel"/> from the specified guest <paramref name="address"/></returns>
public long GetValue(ulong address)
{
return (long)((address & Mask) >> Index);
}
}
}
@@ -0,0 +1,75 @@
namespace ARMeilleure.Common
{
public static class AddressTablePresets
{
private static readonly AddressTableLevel[] _levels64Bit =
new AddressTableLevel[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 2, 5),
};
private static readonly AddressTableLevel[] _levels32Bit =
new AddressTableLevel[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 1, 6),
};
private static readonly AddressTableLevel[] _levels64BitSparseTiny =
new AddressTableLevel[]
{
new( 11, 28),
new( 2, 9),
};
private static readonly AddressTableLevel[] _levels32BitSparseTiny =
new AddressTableLevel[]
{
new( 10, 22),
new( 1, 9),
};
private static readonly AddressTableLevel[] _levels64BitSparseGiant =
new AddressTableLevel[]
{
new( 38, 1),
new( 2, 36),
};
private static readonly AddressTableLevel[] _levels32BitSparseGiant =
new AddressTableLevel[]
{
new( 31, 1),
new( 1, 30),
};
//high power will run worse on DDR3 systems and some DDR4 systems due to the higher ram utilization
//low power will never run worse than non-sparse, but for most systems it won't be necessary
//high power is always used, but I've left low power in here for future reference
public static AddressTableLevel[] GetArmPreset(bool for64Bits, bool sparse, bool lowPower = false)
{
if (sparse)
{
if (lowPower)
{
return for64Bits ? _levels64BitSparseTiny : _levels32BitSparseTiny;
}
else
{
return for64Bits ? _levels64BitSparseGiant : _levels32BitSparseGiant;
}
}
else
{
return for64Bits ? _levels64Bit : _levels32Bit;
}
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ using System;
namespace ARMeilleure.Common namespace ARMeilleure.Common
{ {
unsafe abstract class Allocator : IDisposable public unsafe abstract class Allocator : IDisposable
{ {
public T* Allocate<T>(ulong count = 1) where T : unmanaged public T* Allocate<T>(ulong count = 1) where T : unmanaged
{ {
+51
View File
@@ -0,0 +1,51 @@
using System;
namespace ARMeilleure.Common
{
public interface IAddressTable<TEntry> : IDisposable where TEntry : unmanaged
{
/// <summary>
/// True if the address table's bottom level is sparsely mapped.
/// This also ensures the second bottom level is filled with a dummy page rather than 0.
/// </summary>
bool Sparse { get; }
/// <summary>
/// Gets the bits used by the <see cref="Levels"/> of the <see cref="IAddressTable{TEntry}"/> instance.
/// </summary>
ulong Mask { get; }
/// <summary>
/// Gets the <see cref="AddressTableLevel"/>s used by the <see cref="IAddressTable{TEntry}"/> instance.
/// </summary>
AddressTableLevel[] Levels { get; }
/// <summary>
/// Gets or sets the default fill value of newly created leaf pages.
/// </summary>
TEntry Fill { get; set; }
/// <summary>
/// Gets the base address of the <see cref="EntryTable{TEntry}"/>.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
nint Base { get; }
/// <summary>
/// Determines if the specified <paramref name="address"/> is in the range of the
/// <see cref="IAddressTable{TEntry}"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns><see langword="true"/> if is valid; otherwise <see langword="false"/></returns>
bool IsValid(ulong address);
/// <summary>
/// Gets a reference to the value at the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Reference to the value at the specified guest <paramref name="address"/></returns>
/// <exception cref="ObjectDisposedException"><see cref="EntryTable{TEntry}"/> instance was disposed</exception>
/// <exception cref="ArgumentException"><paramref name="address"/> is not mapped</exception>
ref TEntry GetValue(ulong address);
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
namespace ARMeilleure.Common namespace ARMeilleure.Common
{ {
unsafe sealed class NativeAllocator : Allocator public unsafe sealed class NativeAllocator : Allocator
{ {
public static NativeAllocator Instance { get; } = new(); public static NativeAllocator Instance { get; } = new();
+2 -1
View File
@@ -1,4 +1,5 @@
using ARMeilleure.Common; using ARMeilleure.Common;
using System;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
@@ -149,7 +150,7 @@ namespace ARMeilleure.Decoders
return (((long)opCode << 45) >> 48) & ~3; return (((long)opCode << 45) >> 48) & ~3;
} }
public static bool VectorArgumentsInvalid(bool q, params int[] args) public static bool VectorArgumentsInvalid(bool q, params ReadOnlySpan<int> args)
{ {
if (q) if (q)
{ {
@@ -193,6 +193,8 @@ namespace ARMeilleure.Instructions
Operand hostAddress; Operand hostAddress;
var table = context.FunctionTable;
// If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback // If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback
// onto the dispatch stub. // onto the dispatch stub.
if (guestAddress.Kind == OperandKind.Constant && context.FunctionTable.IsValid(guestAddress.Value)) if (guestAddress.Kind == OperandKind.Constant && context.FunctionTable.IsValid(guestAddress.Value))
@@ -203,6 +205,30 @@ namespace ARMeilleure.Instructions
hostAddress = context.Load(OperandType.I64, hostAddressAddr); hostAddress = context.Load(OperandType.I64, hostAddressAddr);
} }
else if (table.Sparse)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
// Deliberately attempts to avoid branches.
Operand tableBase = !context.HasPtc ?
Const(table.Base) :
Const(table.Base, Ptc.FunctionTableSymbol);
hostAddress = tableBase;
for (int i = 0; i < table.Levels.Length; i++)
{
var level = table.Levels[i];
int clearBits = 64 - (level.Index + level.Length);
Operand index = context.ShiftLeft(
context.ShiftRightUI(context.ShiftLeft(guestAddress, Const(clearBits)), Const(clearBits + level.Index)),
Const(3)
);
hostAddress = context.Load(OperandType.I64, context.Add(hostAddress, index));
}
}
else else
{ {
hostAddress = !context.HasPtc ? hostAddress = !context.HasPtc ?
@@ -49,6 +49,9 @@ namespace ARMeilleure.Instructions
case 0b11_011_1101_0000_011: case 0b11_011_1101_0000_011:
EmitGetTpidrroEl0(context); EmitGetTpidrroEl0(context);
return; return;
case 0b11_011_1101_0000_101:
EmitGetTpidr2El0(context);
return;
case 0b11_011_1110_0000_000: case 0b11_011_1110_0000_000:
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0));
break; break;
@@ -84,6 +87,9 @@ namespace ARMeilleure.Instructions
case 0b11_011_1101_0000_010: case 0b11_011_1101_0000_010:
EmitSetTpidrEl0(context); EmitSetTpidrEl0(context);
return; return;
case 0b11_011_1101_0000_101:
EmitSetTpidr2El0(context);
return;
default: default:
throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
@@ -213,6 +219,17 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rt, result); SetIntOrZR(context, op.Rt, result);
} }
private static void EmitGetTpidr2El0(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
Operand result = context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidr2El0Offset())));
SetIntOrZR(context, op.Rt, result);
}
private static void EmitSetNzcv(ArmEmitterContext context) private static void EmitSetNzcv(ArmEmitterContext context)
{ {
OpCodeSystem op = (OpCodeSystem)context.CurrOp; OpCodeSystem op = (OpCodeSystem)context.CurrOp;
@@ -274,5 +291,16 @@ namespace ARMeilleure.Instructions
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value); context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value);
} }
private static void EmitSetTpidr2El0(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
Operand value = GetIntOrZR(context, op.Rt);
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidr2El0Offset())), value);
}
} }
} }
+1 -1
View File
@@ -264,7 +264,7 @@ namespace ARMeilleure.Instructions
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3); return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
} }
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params V128[] tb) private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{ {
byte[] res = new byte[16]; byte[] res = new byte[16];
@@ -337,7 +337,7 @@ namespace ARMeilleure.IntermediateRepresentation
return result; return result;
} }
public static Operation Operation(Intrinsic intrin, Operand dest, params Operand[] srcs) public static Operation Operation(Intrinsic intrin, Operand dest, params ReadOnlySpan<Operand> srcs)
{ {
Operation result = Make(Instruction.Extended, 0, srcs.Length); Operation result = Make(Instruction.Extended, 0, srcs.Length);
@@ -8,7 +8,7 @@ namespace ARMeilleure.Signal
{ {
public static class NativeSignalHandlerGenerator public static class NativeSignalHandlerGenerator
{ {
public const int MaxTrackedRanges = 8; public const int MaxTrackedRanges = 16;
private const int StructAddressOffset = 0; private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4; private const int StructWriteOffset = 4;
+9
View File
@@ -21,6 +21,7 @@ namespace ARMeilleure.State
public ulong ExclusiveValueLow; public ulong ExclusiveValueLow;
public ulong ExclusiveValueHigh; public ulong ExclusiveValueHigh;
public int Running; public int Running;
public long Tpidr2El0;
} }
private static NativeCtxStorage _dummyStorage = new(); private static NativeCtxStorage _dummyStorage = new();
@@ -176,6 +177,9 @@ namespace ARMeilleure.State
public long GetTpidrroEl0() => GetStorage().TpidrroEl0; public long GetTpidrroEl0() => GetStorage().TpidrroEl0;
public void SetTpidrroEl0(long value) => GetStorage().TpidrroEl0 = value; public void SetTpidrroEl0(long value) => GetStorage().TpidrroEl0 = value;
public long GetTpidr2El0() => GetStorage().Tpidr2El0;
public void SetTpidr2El0(long value) => GetStorage().Tpidr2El0 = value;
public int GetCounter() => GetStorage().Counter; public int GetCounter() => GetStorage().Counter;
public void SetCounter(int value) => GetStorage().Counter = value; public void SetCounter(int value) => GetStorage().Counter = value;
@@ -232,6 +236,11 @@ namespace ARMeilleure.State
return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrroEl0); return StorageOffset(ref _dummyStorage, ref _dummyStorage.TpidrroEl0);
} }
public static int GetTpidr2El0Offset()
{
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Tpidr2El0);
}
public static int GetCounterOffset() public static int GetCounterOffset()
{ {
return StorageOffset(ref _dummyStorage, ref _dummyStorage.Counter); return StorageOffset(ref _dummyStorage, ref _dummyStorage.Counter);
@@ -46,7 +46,7 @@ namespace ARMeilleure.Translation
public IMemoryManager Memory { get; } public IMemoryManager Memory { get; }
public EntryTable<uint> CountTable { get; } public EntryTable<uint> CountTable { get; }
public AddressTable<ulong> FunctionTable { get; } public IAddressTable<ulong> FunctionTable { get; }
public TranslatorStubs Stubs { get; } public TranslatorStubs Stubs { get; }
public ulong EntryAddress { get; } public ulong EntryAddress { get; }
@@ -62,7 +62,7 @@ namespace ARMeilleure.Translation
public ArmEmitterContext( public ArmEmitterContext(
IMemoryManager memory, IMemoryManager memory,
EntryTable<uint> countTable, EntryTable<uint> countTable,
AddressTable<ulong> funcTable, IAddressTable<ulong> funcTable,
TranslatorStubs stubs, TranslatorStubs stubs,
ulong entryAddress, ulong entryAddress,
bool highCq, bool highCq,
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading;
namespace ARMeilleure.Translation.Cache namespace ARMeilleure.Translation.Cache
{ {
@@ -26,7 +27,7 @@ namespace ARMeilleure.Translation.Cache
private static readonly List<CacheEntry> _cacheEntries = new(); private static readonly List<CacheEntry> _cacheEntries = new();
private static readonly object _lock = new(); private static readonly Lock _lock = new();
private static bool _initialized; private static bool _initialized;
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
@@ -559,27 +559,27 @@ namespace ARMeilleure.Translation
return dest; return dest;
} }
public Operand AddIntrinsic(Intrinsic intrin, params Operand[] args) public Operand AddIntrinsic(Intrinsic intrin, params ReadOnlySpan<Operand> args)
{ {
return Add(intrin, Local(OperandType.V128), args); return Add(intrin, Local(OperandType.V128), args);
} }
public Operand AddIntrinsicInt(Intrinsic intrin, params Operand[] args) public Operand AddIntrinsicInt(Intrinsic intrin, params ReadOnlySpan<Operand> args)
{ {
return Add(intrin, Local(OperandType.I32), args); return Add(intrin, Local(OperandType.I32), args);
} }
public Operand AddIntrinsicLong(Intrinsic intrin, params Operand[] args) public Operand AddIntrinsicLong(Intrinsic intrin, params ReadOnlySpan<Operand> args)
{ {
return Add(intrin, Local(OperandType.I64), args); return Add(intrin, Local(OperandType.I64), args);
} }
public void AddIntrinsicNoRet(Intrinsic intrin, params Operand[] args) public void AddIntrinsicNoRet(Intrinsic intrin, params ReadOnlySpan<Operand> args)
{ {
Add(intrin, default, args); Add(intrin, default, args);
} }
private Operand Add(Intrinsic intrin, Operand dest, params Operand[] sources) private Operand Add(Intrinsic intrin, Operand dest, params ReadOnlySpan<Operand> sources)
{ {
NewNextBlockIfNeeded(); NewNextBlockIfNeeded();
+12 -7
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 = 6950; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 6997; //! 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";
@@ -41,6 +41,7 @@ namespace ARMeilleure.Translation.PTC
public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1); public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1);
public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2); public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2);
public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3); public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3);
public static readonly Symbol FunctionTableSymbol = new(SymbolType.Special, 4);
private const byte FillingByte = 0x00; private const byte FillingByte = 0x00;
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest; private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
@@ -58,7 +59,7 @@ namespace ARMeilleure.Translation.PTC
private readonly ManualResetEvent _waitEvent; private readonly ManualResetEvent _waitEvent;
private readonly object _lock; private readonly Lock _lock = new();
private bool _disposed; private bool _disposed;
@@ -88,8 +89,6 @@ namespace ARMeilleure.Translation.PTC
_waitEvent = new ManualResetEvent(true); _waitEvent = new ManualResetEvent(true);
_lock = new object();
_disposed = false; _disposed = false;
TitleIdText = TitleIdTextDefault; TitleIdText = TitleIdTextDefault;
@@ -101,7 +100,7 @@ namespace ARMeilleure.Translation.PTC
Disable(); Disable();
} }
public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode) public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode, string cacheSelector)
{ {
Wait(); Wait();
@@ -127,6 +126,8 @@ namespace ARMeilleure.Translation.PTC
DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault;
_memoryMode = memoryMode; _memoryMode = memoryMode;
Logger.Info?.Print(LogClass.Ptc, $"PPTC (v{InternalVersion}) Profile: {DisplayVersion}-{cacheSelector}");
string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir);
string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir);
@@ -140,8 +141,8 @@ namespace ARMeilleure.Translation.PTC
Directory.CreateDirectory(workPathBackup); Directory.CreateDirectory(workPathBackup);
} }
CachePathActual = Path.Combine(workPathActual, DisplayVersion); CachePathActual = Path.Combine(workPathActual, DisplayVersion) + "-" + cacheSelector;
CachePathBackup = Path.Combine(workPathBackup, DisplayVersion); CachePathBackup = Path.Combine(workPathBackup, DisplayVersion) + "-" + cacheSelector;
PreLoad(); PreLoad();
Profiler.PreLoad(); Profiler.PreLoad();
@@ -706,6 +707,10 @@ namespace ARMeilleure.Translation.PTC
{ {
imm = translator.Stubs.DispatchStub; imm = translator.Stubs.DispatchStub;
} }
else if (symbol == FunctionTableSymbol)
{
imm = translator.FunctionTable.Base;
}
if (imm == null) if (imm == null)
{ {
@@ -41,7 +41,7 @@ namespace ARMeilleure.Translation.PTC
private readonly ManualResetEvent _waitEvent; private readonly ManualResetEvent _waitEvent;
private readonly object _lock; private readonly Lock _lock = new();
private bool _disposed; private bool _disposed;
@@ -65,8 +65,6 @@ namespace ARMeilleure.Translation.PTC
_waitEvent = new ManualResetEvent(true); _waitEvent = new ManualResetEvent(true);
_lock = new object();
_disposed = false; _disposed = false;
ProfiledFuncs = new Dictionary<ulong, FuncProfile>(); ProfiledFuncs = new Dictionary<ulong, FuncProfile>();
+5 -25
View File
@@ -22,33 +22,13 @@ namespace ARMeilleure.Translation
{ {
public class Translator public class Translator
{ {
private static readonly AddressTable<ulong>.Level[] _levels64Bit =
new AddressTable<ulong>.Level[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 2, 5),
};
private static readonly AddressTable<ulong>.Level[] _levels32Bit =
new AddressTable<ulong>.Level[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 1, 6),
};
private readonly IJitMemoryAllocator _allocator; private readonly IJitMemoryAllocator _allocator;
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs; private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
private readonly Ptc _ptc; private readonly Ptc _ptc;
internal TranslatorCache<TranslatedFunction> Functions { get; } internal TranslatorCache<TranslatedFunction> Functions { get; }
internal AddressTable<ulong> FunctionTable { get; } internal IAddressTable<ulong> FunctionTable { get; }
internal EntryTable<uint> CountTable { get; } internal EntryTable<uint> CountTable { get; }
internal TranslatorStubs Stubs { get; } internal TranslatorStubs Stubs { get; }
internal TranslatorQueue Queue { get; } internal TranslatorQueue Queue { get; }
@@ -57,7 +37,7 @@ namespace ARMeilleure.Translation
private Thread[] _backgroundTranslationThreads; private Thread[] _backgroundTranslationThreads;
private volatile int _threadCount; private volatile int _threadCount;
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits) public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, IAddressTable<ulong> functionTable)
{ {
_allocator = allocator; _allocator = allocator;
Memory = memory; Memory = memory;
@@ -72,15 +52,15 @@ namespace ARMeilleure.Translation
CountTable = new EntryTable<uint>(); CountTable = new EntryTable<uint>();
Functions = new TranslatorCache<TranslatedFunction>(); Functions = new TranslatorCache<TranslatedFunction>();
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit); FunctionTable = functionTable;
Stubs = new TranslatorStubs(FunctionTable); Stubs = new TranslatorStubs(FunctionTable);
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub; FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
} }
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled) public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
{ {
_ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type); _ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type, cacheSelector);
return _ptc; return _ptc;
} }
@@ -19,7 +19,7 @@ namespace ARMeilleure.Translation
private bool _disposed; private bool _disposed;
private readonly AddressTable<ulong> _functionTable; private readonly IAddressTable<ulong> _functionTable;
private readonly Lazy<nint> _dispatchStub; private readonly Lazy<nint> _dispatchStub;
private readonly Lazy<DispatcherFunction> _dispatchLoop; private readonly Lazy<DispatcherFunction> _dispatchLoop;
private readonly Lazy<WrapperFunction> _contextWrapper; private readonly Lazy<WrapperFunction> _contextWrapper;
@@ -86,7 +86,7 @@ namespace ARMeilleure.Translation
/// </summary> /// </summary>
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param> /// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(AddressTable<ulong> functionTable) public TranslatorStubs(IAddressTable<ulong> functionTable)
{ {
ArgumentNullException.ThrowIfNull(functionTable); ArgumentNullException.ThrowIfNull(functionTable);
@@ -5,6 +5,7 @@ using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace Ryujinx.Audio.Backends.OpenAL namespace Ryujinx.Audio.Backends.OpenAL
{ {
@@ -18,7 +19,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
private ulong _playedSampleCount; private ulong _playedSampleCount;
private float _volume; private float _volume;
private readonly object _lock = new(); private readonly Lock _lock = new();
public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount) public OpenALHardwareDeviceSession(OpenALHardwareDeviceDriver driver, IVirtualMemoryManager memoryManager, SampleFormat requestedSampleFormat, uint requestedSampleRate, uint requestedChannelCount) : base(memoryManager, requestedSampleFormat, requestedSampleRate, requestedChannelCount)
{ {
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Ryujinx.Audio
/// <summary> /// <summary>
/// Lock used to control the waiters registration. /// Lock used to control the waiters registration.
/// </summary> /// </summary>
private readonly object _lock = new(); private readonly Lock _lock = new();
/// <summary> /// <summary>
/// Events signaled when the driver played audio buffers. /// Events signaled when the driver played audio buffers.
@@ -2,6 +2,7 @@ using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers; using System.Buffers;
using System.Threading;
namespace Ryujinx.Audio.Backends.Common namespace Ryujinx.Audio.Backends.Common
{ {
@@ -12,7 +13,7 @@ namespace Ryujinx.Audio.Backends.Common
{ {
private const int RingBufferAlignment = 2048; private const int RingBufferAlignment = 2048;
private readonly object _lock = new(); private readonly Lock _lock = new();
private MemoryOwner<byte> _bufferOwner; private MemoryOwner<byte> _bufferOwner;
private Memory<byte> _buffer; private Memory<byte> _buffer;
+2 -2
View File
@@ -14,12 +14,12 @@ namespace Ryujinx.Audio.Input
/// </summary> /// </summary>
public class AudioInputManager : IDisposable public class AudioInputManager : IDisposable
{ {
private readonly object _lock = new(); private readonly Lock _lock = new();
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private readonly object _sessionLock = new(); private readonly Lock _sessionLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.
+2 -2
View File
@@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Input
/// <summary> /// <summary>
/// The lock of the parent. /// The lock of the parent.
/// </summary> /// </summary>
private readonly object _parentLock; private readonly Lock _parentLock;
/// <summary> /// <summary>
/// The dispose state. /// The dispose state.
@@ -62,7 +62,7 @@ namespace Ryujinx.Audio.Input
/// <param name="parentLock">The lock of the manager</param> /// <param name="parentLock">The lock of the manager</param>
/// <param name="deviceSession">The hardware device session</param> /// <param name="deviceSession">The hardware device session</param>
/// <param name="bufferEvent">The buffer release event of the audio input</param> /// <param name="bufferEvent">The buffer release event of the audio input</param>
public AudioInputSystem(AudioInputManager manager, object parentLock, IHardwareDeviceSession deviceSession, IWritableEvent bufferEvent) public AudioInputSystem(AudioInputManager manager, Lock parentLock, IHardwareDeviceSession deviceSession, IWritableEvent bufferEvent)
{ {
_manager = manager; _manager = manager;
_parentLock = parentLock; _parentLock = parentLock;
@@ -14,12 +14,12 @@ namespace Ryujinx.Audio.Output
/// </summary> /// </summary>
public class AudioOutputManager : IDisposable public class AudioOutputManager : IDisposable
{ {
private readonly object _lock = new(); private readonly Lock _lock = new();
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private readonly object _sessionLock = new(); private readonly Lock _sessionLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.
@@ -48,7 +48,7 @@ namespace Ryujinx.Audio.Output
/// <summary> /// <summary>
/// THe lock of the parent. /// THe lock of the parent.
/// </summary> /// </summary>
private readonly object _parentLock; private readonly Lock _parentLock;
/// <summary> /// <summary>
/// The dispose state. /// The dispose state.
@@ -62,7 +62,7 @@ namespace Ryujinx.Audio.Output
/// <param name="parentLock">The lock of the manager</param> /// <param name="parentLock">The lock of the manager</param>
/// <param name="deviceSession">The hardware device session</param> /// <param name="deviceSession">The hardware device session</param>
/// <param name="bufferEvent">The buffer release event of the audio output</param> /// <param name="bufferEvent">The buffer release event of the audio output</param>
public AudioOutputSystem(AudioOutputManager manager, object parentLock, IHardwareDeviceSession deviceSession, IWritableEvent bufferEvent) public AudioOutputSystem(AudioOutputManager manager, Lock parentLock, IHardwareDeviceSession deviceSession, IWritableEvent bufferEvent)
{ {
_manager = manager; _manager = manager;
_parentLock = parentLock; _parentLock = parentLock;
@@ -26,7 +26,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
public class AudioRenderSystem : IDisposable public class AudioRenderSystem : IDisposable
{ {
private readonly object _lock = new(); private readonly Lock _lock = new();
private AudioRendererRenderingDevice _renderingDevice; private AudioRendererRenderingDevice _renderingDevice;
private AudioRendererExecutionMode _executionMode; private AudioRendererExecutionMode _executionMode;
@@ -19,12 +19,12 @@ namespace Ryujinx.Audio.Renderer.Server
/// <summary> /// <summary>
/// Lock used for session allocation. /// Lock used for session allocation.
/// </summary> /// </summary>
private readonly object _sessionLock = new(); private readonly Lock _sessionLock = new();
/// <summary> /// <summary>
/// Lock used to control the <see cref="AudioProcessor"/> running state. /// Lock used to control the <see cref="AudioProcessor"/> running state.
/// </summary> /// </summary>
private readonly object _audioProcessorLock = new(); private readonly Lock _audioProcessorLock = new();
/// <summary> /// <summary>
/// The session ids allocation table. /// The session ids allocation table.
@@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace Ryujinx.Audio.Renderer.Server.Upsampler namespace Ryujinx.Audio.Renderer.Server.Upsampler
{ {
@@ -16,7 +17,7 @@ namespace Ryujinx.Audio.Renderer.Server.Upsampler
/// <summary> /// <summary>
/// Global lock of the object. /// Global lock of the object.
/// </summary> /// </summary>
private readonly object _lock = new(); private readonly Lock _lock = new();
/// <summary> /// <summary>
/// The upsamplers instances. /// The upsamplers instances.
+1 -1
View File
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -0,0 +1,73 @@
using System;
using Microsoft.Build.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Newtonsoft.Json;
using Microsoft.Build.Framework;
namespace Ryujinx.BuildValidationTasks
{
public class LocaleValidationTask : Task
{
public override bool Execute()
{
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (path.Split(["src"], StringSplitOptions.None).Length == 1)
{
//i assume that we are in a build directory in the solution dir
path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
else
{
path = path.Split(["src"], StringSplitOptions.None)[0];
path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
}
string data;
using (StreamReader sr = new(path))
{
data = sr.ReadToEnd();
}
LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
for (int i = 0; i < json.Locales.Count; i++)
{
LocalesEntry locale = json.Locales[i];
foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
{
locale.Translations.Add(langCode, string.Empty);
Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
}
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
json.Locales[i] = locale;
}
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
using (StreamWriter sw = new(path))
{
sw.Write(jsonString);
}
return true;
}
struct LocalesJson
{
public List<string> Languages { get; set; }
public List<LocalesEntry> Locales { get; set; }
}
struct LocalesEntry
{
public string ID { get; set; }
public Dictionary<string, string> Translations { get; set; }
}
}
}
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Utilities.Core" />
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
<UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
<Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
<LocaleValidationTask />
</Target>
</Project>
@@ -8,5 +8,6 @@ namespace Ryujinx.Common.Configuration
{ {
Vulkan, Vulkan,
OpenGl, OpenGl,
Metal
} }
} }
@@ -1,6 +1,8 @@
namespace Ryujinx.Common.Configuration.Hid.Controller namespace Ryujinx.Common.Configuration.Hid.Controller
{ {
public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged public class JoyconConfigControllerStick<TButton, TStick>
where TButton : unmanaged
where TStick : unmanaged
{ {
public TStick Joystick { get; set; } public TStick Joystick { get; set; }
public bool InvertStickX { get; set; } public bool InvertStickX { get; set; }
@@ -2,7 +2,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
public class KeyboardHotkeys public class KeyboardHotkeys
{ {
public Key ToggleVsync { get; set; } public Key ToggleVSyncMode { get; set; }
public Key Screenshot { get; set; } public Key Screenshot { get; set; }
public Key ShowUI { get; set; } public Key ShowUI { get; set; }
public Key Pause { get; set; } public Key Pause { get; set; }
@@ -11,5 +11,7 @@ namespace Ryujinx.Common.Configuration.Hid
public Key ResScaleDown { get; set; } public Key ResScaleDown { get; set; }
public Key VolumeUp { get; set; } public Key VolumeUp { get; set; }
public Key VolumeDown { get; set; } public Key VolumeDown { get; set; }
public Key CustomVSyncIntervalIncrement { get; set; }
public Key CustomVSyncIntervalDecrement { get; set; }
} }
} }
@@ -0,0 +1,9 @@
namespace Ryujinx.Common.Configuration
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}
@@ -69,9 +69,10 @@ namespace Ryujinx.Common.Logging.Targets
} }
string version = ReleaseInformation.Version; string version = ReleaseInformation.Version;
string appName = ReleaseInformation.IsCanaryBuild ? "Ryujinx_Canary" : "Ryujinx";
// Get path for the current time // Get path for the current time
path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"); path = Path.Combine(logDir.FullName, $"{appName}_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log");
try try
{ {
@@ -124,7 +124,7 @@ namespace Ryujinx.Common.PreciseSleep
} }
} }
private readonly object _lock = new(); private readonly Lock _lock = new();
private readonly List<NanosleepThread> _threads = new(); private readonly List<NanosleepThread> _threads = new();
private readonly List<NanosleepThread> _active = new(); private readonly List<NanosleepThread> _active = new();
private readonly Stack<NanosleepThread> _free = new(); private readonly Stack<NanosleepThread> _free = new();
@@ -50,7 +50,7 @@ namespace Ryujinx.Common.SystemInterop
private long _lastTicks = PerformanceCounter.ElapsedTicks; private long _lastTicks = PerformanceCounter.ElapsedTicks;
private long _lastId; private long _lastId;
private readonly object _lock = new(); private readonly Lock _lock = new();
private readonly List<WaitingObject> _waitingObjects = new(); private readonly List<WaitingObject> _waitingObjects = new();
private WindowsGranularTimer() private WindowsGranularTimer()
+9 -3
View File
@@ -1,3 +1,4 @@
using System;
using System.Reflection; using System.Reflection;
namespace Ryujinx.Common namespace Ryujinx.Common
@@ -5,7 +6,6 @@ namespace Ryujinx.Common
// DO NOT EDIT, filled by CI // DO NOT EDIT, filled by CI
public static class ReleaseInformation public static class ReleaseInformation
{ {
private const string FlatHubChannel = "flathub";
private const string CanaryChannel = "canary"; private const string CanaryChannel = "canary";
private const string ReleaseChannel = "release"; private const string ReleaseChannel = "release";
@@ -28,12 +28,18 @@ namespace Ryujinx.Common
!ReleaseChannelRepo.StartsWith("%%") && !ReleaseChannelRepo.StartsWith("%%") &&
!ConfigFileName.StartsWith("%%"); !ConfigFileName.StartsWith("%%");
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannel);
public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel); public static bool IsCanaryBuild => IsValid && ReleaseChannelName.Equals(CanaryChannel);
public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel); public static bool IsReleaseBuild => IsValid && ReleaseChannelName.Equals(ReleaseChannel);
public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion; public static string Version => IsValid ? BuildVersion : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
public static string GetChangelogUrl(Version currentVersion, Version newVersion) =>
IsCanaryBuild
? $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/compare/Canary-{currentVersion}...Canary-{newVersion}"
: $"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelSourceRepo}/releases/tag/{newVersion}";
public static string GetChangelogForVersion(Version version) =>
$"https://github.com/{ReleaseChannelOwner}/{ReleaseChannelRepo}/releases/tag/{version}";
} }
} }
+1 -1
View File
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants> <DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+8 -2
View File
@@ -1,3 +1,4 @@
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
@@ -27,9 +28,14 @@ namespace Ryujinx.Common.Utilities
ReadCommentHandling = JsonCommentHandling.Skip ReadCommentHandling = JsonCommentHandling.Skip
}; };
public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Serialize(value, typeInfo); public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
=> JsonSerializer.Serialize(value, typeInfo);
public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo) => JsonSerializer.Deserialize(value, typeInfo); public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
=> JsonSerializer.Deserialize(value, typeInfo);
public static T Deserialize<T>(ReadOnlySpan<byte> utf8Value, JsonTypeInfo<T> typeInfo)
=> JsonSerializer.Deserialize<T>(utf8Value, typeInfo);
public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo) public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
{ {
+482
View File
@@ -0,0 +1,482 @@
using ARMeilleure.Memory;
using Ryujinx.Common;
using Ryujinx.Cpu.Signal;
using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using static Ryujinx.Cpu.MemoryEhMeilleure;
namespace ARMeilleure.Common
{
/// <summary>
/// Represents a table of guest address to a value.
/// </summary>
/// <typeparam name="TEntry">Type of the value</typeparam>
public unsafe class AddressTable<TEntry> : IAddressTable<TEntry> where TEntry : unmanaged
{
/// <summary>
/// Represents a page of the address table.
/// </summary>
private readonly struct AddressTablePage
{
/// <summary>
/// True if the allocation belongs to a sparse block, false otherwise.
/// </summary>
public readonly bool IsSparse;
/// <summary>
/// Base address for the page.
/// </summary>
public readonly IntPtr Address;
public AddressTablePage(bool isSparse, IntPtr address)
{
IsSparse = isSparse;
Address = address;
}
}
/// <summary>
/// A sparsely mapped block of memory with a signal handler to map pages as they're accessed.
/// </summary>
private readonly struct TableSparseBlock : IDisposable
{
public readonly SparseMemoryBlock Block;
private readonly TrackingEventDelegate _trackingEvent;
public TableSparseBlock(ulong size, Action<IntPtr> ensureMapped, PageInitDelegate pageInit)
{
var block = new SparseMemoryBlock(size, pageInit, null);
_trackingEvent = (ulong address, ulong size, bool write) =>
{
ulong pointer = (ulong)block.Block.Pointer + address;
ensureMapped((IntPtr)pointer);
return pointer;
};
bool added = NativeSignalHandler.AddTrackedRegion(
(nuint)block.Block.Pointer,
(nuint)(block.Block.Pointer + (IntPtr)block.Block.Size),
Marshal.GetFunctionPointerForDelegate(_trackingEvent));
if (!added)
{
throw new InvalidOperationException("Number of allowed tracked regions exceeded.");
}
Block = block;
}
public void Dispose()
{
NativeSignalHandler.RemoveTrackedRegion((nuint)Block.Block.Pointer);
Block.Dispose();
}
}
private bool _disposed;
private TEntry** _table;
private readonly List<AddressTablePage> _pages;
private TEntry _fill;
private readonly MemoryBlock _sparseFill;
private readonly SparseMemoryBlock _fillBottomLevel;
private readonly TEntry* _fillBottomLevelPtr;
private readonly List<TableSparseBlock> _sparseReserved;
private readonly ReaderWriterLockSlim _sparseLock;
private ulong _sparseBlockSize;
private ulong _sparseReservedOffset;
public bool Sparse { get; }
/// <inheritdoc/>
public ulong Mask { get; }
/// <inheritdoc/>
public AddressTableLevel[] Levels { get; }
/// <inheritdoc/>
public TEntry Fill
{
get
{
return _fill;
}
set
{
UpdateFill(value);
}
}
/// <inheritdoc/>
public IntPtr Base
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
lock (_pages)
{
return (IntPtr)GetRootPage();
}
}
}
/// <summary>
/// Constructs a new instance of the <see cref="AddressTable{TEntry}"/> class with the specified list of
/// <see cref="Level"/>.
/// </summary>
/// <param name="levels">Levels for the address table</param>
/// <param name="sparse">True if the bottom page should be sparsely mapped</param>
/// <exception cref="ArgumentNullException"><paramref name="levels"/> is null</exception>
/// <exception cref="ArgumentException">Length of <paramref name="levels"/> is less than 2</exception>
public AddressTable(AddressTableLevel[] levels, bool sparse)
{
ArgumentNullException.ThrowIfNull(levels);
_pages = new List<AddressTablePage>(capacity: 16);
Levels = levels;
Mask = 0;
foreach (var level in Levels)
{
Mask |= level.Mask;
}
Sparse = sparse;
if (sparse)
{
// If the address table is sparse, allocate a fill block
_sparseFill = new MemoryBlock(268435456ul, MemoryAllocationFlags.Mirrorable); //low Power TC uses size: 65536ul
ulong bottomLevelSize = (1ul << levels.Last().Length) * (ulong)sizeof(TEntry);
_fillBottomLevel = new SparseMemoryBlock(bottomLevelSize, null, _sparseFill);
_fillBottomLevelPtr = (TEntry*)_fillBottomLevel.Block.Pointer;
_sparseReserved = new List<TableSparseBlock>();
_sparseLock = new ReaderWriterLockSlim();
_sparseBlockSize = bottomLevelSize;
}
}
/// <summary>
/// Create an <see cref="AddressTable{TEntry}"/> instance for an ARM function table.
/// Selects the best table structure for A32/A64, taking into account the selected memory manager type.
/// </summary>
/// <param name="for64Bits">True if the guest is A64, false otherwise</param>
/// <param name="type">Memory manager type</param>
/// <returns>An <see cref="AddressTable{TEntry}"/> for ARM function lookup</returns>
public static AddressTable<TEntry> CreateForArm(bool for64Bits, MemoryManagerType type)
{
// Assume software memory means that we don't want to use any signal handlers.
bool sparse = type != MemoryManagerType.SoftwareMmu && type != MemoryManagerType.SoftwarePageTable;
return new AddressTable<TEntry>(AddressTablePresets.GetArmPreset(for64Bits, sparse), sparse);
}
/// <summary>
/// Update the fill value for the bottom level of the table.
/// </summary>
/// <param name="fillValue">New fill value</param>
private void UpdateFill(TEntry fillValue)
{
if (_sparseFill != null)
{
Span<byte> span = _sparseFill.GetSpan(0, (int)_sparseFill.Size);
MemoryMarshal.Cast<byte, TEntry>(span).Fill(fillValue);
}
_fill = fillValue;
}
/// <summary>
/// Signal that the given code range exists.
/// </summary>
/// <param name="address"></param>
/// <param name="size"></param>
public void SignalCodeRange(ulong address, ulong size)
{
AddressTableLevel bottom = Levels.Last();
ulong bottomLevelEntries = 1ul << bottom.Length;
ulong entryIndex = address >> bottom.Index;
ulong entries = size >> bottom.Index;
entries += entryIndex - BitUtils.AlignDown(entryIndex, bottomLevelEntries);
_sparseBlockSize = Math.Max(_sparseBlockSize, BitUtils.AlignUp(entries, bottomLevelEntries) * (ulong)sizeof(TEntry));
}
/// <inheritdoc/>
public bool IsValid(ulong address)
{
return (address & ~Mask) == 0;
}
/// <inheritdoc/>
public ref TEntry GetValue(ulong address)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (!IsValid(address))
{
throw new ArgumentException($"Address 0x{address:X} is not mapped onto the table.", nameof(address));
}
lock (_pages)
{
TEntry* page = GetPage(address);
long index = Levels[^1].GetValue(address);
EnsureMapped((IntPtr)(page + index));
return ref page[index];
}
}
/// <summary>
/// Gets the leaf page for the specified guest <paramref name="address"/>.
/// </summary>
/// <param name="address">Guest address</param>
/// <returns>Leaf page for the specified guest <paramref name="address"/></returns>
private TEntry* GetPage(ulong address)
{
TEntry** page = GetRootPage();
for (int i = 0; i < Levels.Length - 1; i++)
{
ref AddressTableLevel level = ref Levels[i];
ref TEntry* nextPage = ref page[level.GetValue(address)];
if (nextPage == null || nextPage == _fillBottomLevelPtr)
{
ref AddressTableLevel nextLevel = ref Levels[i + 1];
if (i == Levels.Length - 2)
{
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, Fill, leaf: true);
}
else
{
nextPage = (TEntry*)Allocate(1 << nextLevel.Length, GetFillValue(i), leaf: false);
}
}
page = (TEntry**)nextPage;
}
return (TEntry*)page;
}
/// <summary>
/// Ensure the given pointer is mapped in any overlapping sparse reservations.
/// </summary>
/// <param name="ptr">Pointer to be mapped</param>
private void EnsureMapped(IntPtr ptr)
{
if (Sparse)
{
// Check sparse allocations to see if the pointer is in any of them.
// Ensure the page is committed if there's a match.
_sparseLock.EnterReadLock();
try
{
foreach (TableSparseBlock reserved in _sparseReserved)
{
SparseMemoryBlock sparse = reserved.Block;
if (ptr >= sparse.Block.Pointer && ptr < sparse.Block.Pointer + (IntPtr)sparse.Block.Size)
{
sparse.EnsureMapped((ulong)(ptr - sparse.Block.Pointer));
break;
}
}
}
finally
{
_sparseLock.ExitReadLock();
}
}
}
/// <summary>
/// Get the fill value for a non-leaf level of the table.
/// </summary>
/// <param name="level">Level to get the fill value for</param>
/// <returns>The fill value</returns>
private IntPtr GetFillValue(int level)
{
if (_fillBottomLevel != null && level == Levels.Length - 2)
{
return (IntPtr)_fillBottomLevelPtr;
}
else
{
return IntPtr.Zero;
}
}
/// <summary>
/// Lazily initialize and get the root page of the <see cref="AddressTable{TEntry}"/>.
/// </summary>
/// <returns>Root page of the <see cref="AddressTable{TEntry}"/></returns>
private TEntry** GetRootPage()
{
if (_table == null)
{
if (Levels.Length == 1)
_table = (TEntry**)Allocate(1 << Levels[0].Length, Fill, leaf: true);
else
_table = (TEntry**)Allocate(1 << Levels[0].Length, GetFillValue(0), leaf: false);
}
return _table;
}
/// <summary>
/// Initialize a leaf page with the fill value.
/// </summary>
/// <param name="page">Page to initialize</param>
private void InitLeafPage(Span<byte> page)
{
MemoryMarshal.Cast<byte, TEntry>(page).Fill(_fill);
}
/// <summary>
/// Reserve a new sparse block, and add it to the list.
/// </summary>
/// <returns>The new sparse block that was added</returns>
private TableSparseBlock ReserveNewSparseBlock()
{
var block = new TableSparseBlock(_sparseBlockSize, EnsureMapped, InitLeafPage);
_sparseReserved.Add(block);
_sparseReservedOffset = 0;
return block;
}
/// <summary>
/// Allocates a block of memory of the specified type and length.
/// </summary>
/// <typeparam name="T">Type of elements</typeparam>
/// <param name="length">Number of elements</param>
/// <param name="fill">Fill value</param>
/// <param name="leaf"><see langword="true"/> if leaf; otherwise <see langword="false"/></param>
/// <returns>Allocated block</returns>
private IntPtr Allocate<T>(int length, T fill, bool leaf) where T : unmanaged
{
var size = sizeof(T) * length;
AddressTablePage page;
if (Sparse && leaf)
{
_sparseLock.EnterWriteLock();
SparseMemoryBlock block;
if (_sparseReserved.Count == 0)
{
block = ReserveNewSparseBlock().Block;
}
else
{
block = _sparseReserved.Last().Block;
if (_sparseReservedOffset == block.Block.Size)
{
block = ReserveNewSparseBlock().Block;
}
}
page = new AddressTablePage(true, block.Block.Pointer + (IntPtr)_sparseReservedOffset);
_sparseReservedOffset += (ulong)size;
_sparseLock.ExitWriteLock();
}
else
{
var address = (IntPtr)NativeAllocator.Instance.Allocate((uint)size);
page = new AddressTablePage(false, address);
var span = new Span<T>((void*)page.Address, length);
span.Fill(fill);
}
_pages.Add(page);
//TranslatorEventSource.Log.AddressTableAllocated(size, leaf);
return page.Address;
}
/// <summary>
/// Releases all resources used by the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases all unmanaged and optionally managed resources used by the <see cref="AddressTable{TEntry}"/>
/// instance.
/// </summary>
/// <param name="disposing"><see langword="true"/> to dispose managed resources also; otherwise just unmanaged resouces</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
foreach (var page in _pages)
{
if (!page.IsSparse)
{
Marshal.FreeHGlobal(page.Address);
}
}
if (Sparse)
{
foreach (TableSparseBlock block in _sparseReserved)
{
block.Dispose();
}
_sparseReserved.Clear();
_fillBottomLevel.Dispose();
_sparseFill.Dispose();
_sparseLock.Dispose();
}
_disposed = true;
}
}
/// <summary>
/// Frees resources used by the <see cref="AddressTable{TEntry}"/> instance.
/// </summary>
~AddressTable()
{
Dispose(false);
}
}
}
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Ryujinx.Cpu.AppleHv
{ {
} }
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled) public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
{ {
return new DummyDiskCacheLoadState(); return new DummyDiskCacheLoadState();
} }
+14 -20
View File
@@ -230,25 +230,20 @@ namespace Ryujinx.Cpu.AppleHv
{ {
if (size == 0) if (size == 0)
{ {
return Enumerable.Empty<HostMemoryRange>(); yield break;
} }
var guestRegions = GetPhysicalRegionsImpl(va, size); var guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null) if (guestRegions == null)
{ {
return null; yield break;
} }
var regions = new HostMemoryRange[guestRegions.Count]; foreach (var guestRegion in guestRegions)
for (int i = 0; i < regions.Length; i++)
{ {
var guestRegion = guestRegions[i];
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size); nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size); yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
} }
return regions;
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -256,23 +251,24 @@ namespace Ryujinx.Cpu.AppleHv
{ {
if (size == 0) if (size == 0)
{ {
return Enumerable.Empty<MemoryRange>(); yield break;
} }
return GetPhysicalRegionsImpl(va, size); foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
{
yield return physicalRegion;
}
} }
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size) private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
{ {
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size)) if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{ {
return null; yield break;
} }
int pages = GetPagesCount(va, (uint)size, out va); int pages = GetPagesCount(va, (uint)size, out va);
var regions = new List<MemoryRange>();
ulong regionStart = GetPhysicalAddressInternal(va); ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize; ulong regionSize = PageSize;
@@ -280,14 +276,14 @@ namespace Ryujinx.Cpu.AppleHv
{ {
if (!ValidateAddress(va + PageSize)) if (!ValidateAddress(va + PageSize))
{ {
return null; yield break;
} }
ulong newPa = GetPhysicalAddressInternal(va + PageSize); ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa) if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{ {
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa; regionStart = newPa;
regionSize = 0; regionSize = 0;
} }
@@ -296,9 +292,7 @@ namespace Ryujinx.Cpu.AppleHv
regionSize += PageSize; regionSize += PageSize;
} }
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
return regions;
} }
/// <remarks> /// <remarks>
+2 -1
View File
@@ -1,6 +1,7 @@
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading;
namespace Ryujinx.Cpu.AppleHv namespace Ryujinx.Cpu.AppleHv
{ {
@@ -12,7 +13,7 @@ namespace Ryujinx.Cpu.AppleHv
private static int _addressSpaces; private static int _addressSpaces;
private static HvIpaAllocator _ipaAllocator; private static HvIpaAllocator _ipaAllocator;
private static readonly object _lock = new(); private static readonly Lock _lock = new();
public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block) public static (ulong, HvIpaAllocator) CreateAddressSpace(MemoryBlock block)
{ {
+1 -1
View File
@@ -48,7 +48,7 @@ namespace Ryujinx.Cpu
/// <param name="displayVersion">Version of the application</param> /// <param name="displayVersion">Version of the application</param>
/// <param name="enabled">True if the cache should be loaded from disk if it exists, false otherwise</param> /// <param name="enabled">True if the cache should be loaded from disk if it exists, false otherwise</param>
/// <returns>Disk cache load progress reporter and manager</returns> /// <returns>Disk cache load progress reporter and manager</returns>
IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled); IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector);
/// <summary> /// <summary>
/// Indicates that code has been loaded into guest memory, and that it might be executed in the future. /// Indicates that code has been loaded into guest memory, and that it might be executed in the future.
@@ -115,6 +115,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
} }
private readonly AddressIntrusiveRedBlackTree<Mapping> _mappingTree; private readonly AddressIntrusiveRedBlackTree<Mapping> _mappingTree;
// type is not Lock due to the unique usage of this mechanism,
// an arbitrary object is used as the lock passed in by constructor.
private readonly object _lock; private readonly object _lock;
public Block(MemoryTracking tracking, Func<ulong, ulong> readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size) public Block(MemoryTracking tracking, Func<ulong, ulong> readPtCallback, MemoryBlock memory, ulong size, object locker) : base(memory, size)
@@ -174,6 +177,9 @@ namespace Ryujinx.Cpu.Jit.HostTracked
private readonly MemoryTracking _tracking; private readonly MemoryTracking _tracking;
private readonly Func<ulong, ulong> _readPtCallback; private readonly Func<ulong, ulong> _readPtCallback;
// type is not Lock due to the unique usage of this mechanism,
// an arbitrary object is used as the lock passed in by constructor.
private readonly object _lock; private readonly object _lock;
public AddressSpacePartitionAllocator( public AddressSpacePartitionAllocator(
+7 -3
View File
@@ -1,3 +1,4 @@
using ARMeilleure.Common;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using Ryujinx.Cpu.Signal; using Ryujinx.Cpu.Signal;
@@ -9,11 +10,13 @@ namespace Ryujinx.Cpu.Jit
{ {
private readonly ITickSource _tickSource; private readonly ITickSource _tickSource;
private readonly Translator _translator; private readonly Translator _translator;
private readonly AddressTable<ulong> _functionTable;
public JitCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit) public JitCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit)
{ {
_tickSource = tickSource; _tickSource = tickSource;
_translator = new Translator(new JitMemoryAllocator(forJit: true), memory, for64Bit); _functionTable = AddressTable<ulong>.CreateForArm(for64Bit, memory.Type);
_translator = new Translator(new JitMemoryAllocator(forJit: true), memory, _functionTable);
if (memory.Type.IsHostMappedOrTracked()) if (memory.Type.IsHostMappedOrTracked())
{ {
@@ -47,14 +50,15 @@ namespace Ryujinx.Cpu.Jit
} }
/// <inheritdoc/> /// <inheritdoc/>
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled) public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
{ {
return new JitDiskCacheLoadState(_translator.LoadDiskCache(titleIdText, displayVersion, enabled)); return new JitDiskCacheLoadState(_translator.LoadDiskCache(titleIdText, displayVersion, enabled, cacheSelector));
} }
/// <inheritdoc/> /// <inheritdoc/>
public void PrepareCodeRange(ulong address, ulong size) public void PrepareCodeRange(ulong address, ulong size)
{ {
_functionTable.SignalCodeRange(address, size);
_translator.PrepareCodeRange(address, size); _translator.PrepareCodeRange(address, size);
} }
+14 -20
View File
@@ -250,25 +250,20 @@ namespace Ryujinx.Cpu.Jit
{ {
if (size == 0) if (size == 0)
{ {
return Enumerable.Empty<HostMemoryRange>(); yield break;
} }
var guestRegions = GetPhysicalRegionsImpl(va, size); var guestRegions = GetPhysicalRegionsImpl(va, size);
if (guestRegions == null) if (guestRegions == null)
{ {
return null; yield break;
} }
var regions = new HostMemoryRange[guestRegions.Count]; foreach (var guestRegion in guestRegions)
for (int i = 0; i < regions.Length; i++)
{ {
var guestRegion = guestRegions[i];
nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size); nint pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size); yield return new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
} }
return regions;
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -276,23 +271,24 @@ namespace Ryujinx.Cpu.Jit
{ {
if (size == 0) if (size == 0)
{ {
return Enumerable.Empty<MemoryRange>(); yield break;
} }
return GetPhysicalRegionsImpl(va, size); foreach (var physicalRegion in GetPhysicalRegionsImpl(va, size))
{
yield return physicalRegion;
}
} }
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size) private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
{ {
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size)) if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{ {
return null; yield break;
} }
int pages = GetPagesCount(va, (uint)size, out va); int pages = GetPagesCount(va, (uint)size, out va);
var regions = new List<MemoryRange>();
ulong regionStart = GetPhysicalAddressInternal(va); ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize; ulong regionSize = PageSize;
@@ -300,14 +296,14 @@ namespace Ryujinx.Cpu.Jit
{ {
if (!ValidateAddress(va + PageSize)) if (!ValidateAddress(va + PageSize))
{ {
return null; yield break;
} }
ulong newPa = GetPhysicalAddressInternal(va + PageSize); ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa) if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{ {
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa; regionStart = newPa;
regionSize = 0; regionSize = 0;
} }
@@ -316,9 +312,7 @@ namespace Ryujinx.Cpu.Jit
regionSize += PageSize; regionSize += PageSize;
} }
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
return regions;
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -475,17 +475,15 @@ namespace Ryujinx.Cpu.Jit
return GetPhysicalRegionsImpl(va, size); return GetPhysicalRegionsImpl(va, size);
} }
private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size) private IEnumerable<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
{ {
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size)) if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{ {
return null; yield break;
} }
int pages = GetPagesCount(va, (uint)size, out va); int pages = GetPagesCount(va, (uint)size, out va);
var regions = new List<MemoryRange>();
ulong regionStart = GetPhysicalAddressInternal(va); ulong regionStart = GetPhysicalAddressInternal(va);
ulong regionSize = PageSize; ulong regionSize = PageSize;
@@ -493,14 +491,14 @@ namespace Ryujinx.Cpu.Jit
{ {
if (!ValidateAddress(va + PageSize)) if (!ValidateAddress(va + PageSize))
{ {
return null; yield break;
} }
ulong newPa = GetPhysicalAddressInternal(va + PageSize); ulong newPa = GetPhysicalAddressInternal(va + PageSize);
if (GetPhysicalAddressInternal(va) + PageSize != newPa) if (GetPhysicalAddressInternal(va) + PageSize != newPa)
{ {
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
regionStart = newPa; regionStart = newPa;
regionSize = 0; regionSize = 0;
} }
@@ -509,9 +507,7 @@ namespace Ryujinx.Cpu.Jit
regionSize += PageSize; regionSize += PageSize;
} }
regions.Add(new MemoryRange(regionStart, regionSize)); yield return new MemoryRange(regionStart, regionSize);
return regions;
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -140,6 +140,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
bool isTail = false) bool isTail = false)
{ {
int tempRegister; int tempRegister;
int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant &&
funcTable is { Sparse: true };
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {
@@ -153,9 +157,16 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
else else
{ {
asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset);
if (inlineLookup && guestAddress.Value == 0)
{
// X0 will be overwritten. Move the address to a temp register.
tempGuestAddress = regAlloc.AllocateTempGprRegister();
asm.Mov(Register(tempGuestAddress), guestAddress);
}
} }
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1; tempRegister = NextFreeRegister(1, tempGuestAddress);
if (!isTail) if (!isTail)
{ {
@@ -176,6 +187,40 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
asm.Mov(rn, funcPtrLoc & ~0xfffUL); asm.Mov(rn, funcPtrLoc & ~0xfffUL);
asm.LdrRiUn(rn, rn, (int)(funcPtrLoc & 0xfffUL)); asm.LdrRiUn(rn, rn, (int)(funcPtrLoc & 0xfffUL));
} }
else if (inlineLookup)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
ulong tableBase = (ulong)funcTable.Base;
// Index into the table.
asm.Mov(rn, tableBase);
for (int i = 0; i < funcTable.Levels.Length; i++)
{
var level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page.
asm.Add(rn, rn, indexReg);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
}
else else
{ {
asm.Mov(rn, (ulong)funcPtr); asm.Mov(rn, (ulong)funcPtr);
@@ -252,5 +297,20 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{ {
return new Operand(register, RegisterType.Integer, type); return new Operand(register, RegisterType.Integer, type);
} }
private static Operand Const(long value, OperandType type = OperandType.I64)
{
return new Operand(type, (ulong)value);
}
private static int NextFreeRegister(int start, int avoid)
{
if (start == avoid)
{
start++;
}
return start;
}
} }
} }
@@ -478,7 +478,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
bool skipContext, bool skipContext,
int spillBaseOffset, int spillBaseOffset,
int? resultRegister, int? resultRegister,
params ulong[] callArgs) params ReadOnlySpan<ulong> callArgs)
{ {
uint resultMask = 0u; uint resultMask = 0u;
@@ -305,6 +305,10 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
bool isTail = false) bool isTail = false)
{ {
int tempRegister; int tempRegister;
int tempGuestAddress = -1;
bool inlineLookup = guestAddress.Kind != OperandKind.Constant &&
funcTable is { Sparse: true };
if (guestAddress.Kind == OperandKind.Constant) if (guestAddress.Kind == OperandKind.Constant)
{ {
@@ -318,9 +322,16 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
else else
{ {
asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset); asm.StrRiUn(guestAddress, Register(regAlloc.FixedContextRegister), NativeContextOffsets.DispatchAddressOffset);
if (inlineLookup && guestAddress.Value == 0)
{
// X0 will be overwritten. Move the address to a temp register.
tempGuestAddress = regAlloc.AllocateTempGprRegister();
asm.Mov(Register(tempGuestAddress), guestAddress);
}
} }
tempRegister = regAlloc.FixedContextRegister == 1 ? 2 : 1; tempRegister = NextFreeRegister(1, tempGuestAddress);
if (!isTail) if (!isTail)
{ {
@@ -341,6 +352,40 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
asm.Mov(rn, funcPtrLoc & ~0xfffUL); asm.Mov(rn, funcPtrLoc & ~0xfffUL);
asm.LdrRiUn(rn, rn, (int)(funcPtrLoc & 0xfffUL)); asm.LdrRiUn(rn, rn, (int)(funcPtrLoc & 0xfffUL));
} }
else if (inlineLookup)
{
// Inline table lookup. Only enabled when the sparse function table is enabled with 2 levels.
Operand indexReg = Register(NextFreeRegister(tempRegister + 1, tempGuestAddress));
if (tempGuestAddress != -1)
{
guestAddress = Register(tempGuestAddress);
}
ulong tableBase = (ulong)funcTable.Base;
// Index into the table.
asm.Mov(rn, tableBase);
for (int i = 0; i < funcTable.Levels.Length; i++)
{
var level = funcTable.Levels[i];
asm.Ubfx(indexReg, guestAddress, level.Index, level.Length);
asm.Lsl(indexReg, indexReg, Const(3));
// Index into the page.
asm.Add(rn, rn, indexReg);
// Load the page address.
asm.LdrRiUn(rn, rn, 0);
}
if (tempGuestAddress != -1)
{
regAlloc.FreeTempGprRegister(tempGuestAddress);
}
}
else else
{ {
asm.Mov(rn, (ulong)funcPtr); asm.Mov(rn, (ulong)funcPtr);
@@ -372,7 +417,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
nint funcPtr, nint funcPtr,
int spillBaseOffset, int spillBaseOffset,
int? resultRegister, int? resultRegister,
params ulong[] callArgs) params ReadOnlySpan<ulong> callArgs)
{ {
uint resultMask = 0u; uint resultMask = 0u;
@@ -613,5 +658,20 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
return new Operand(register, RegisterType.Integer, type); return new Operand(register, RegisterType.Integer, type);
} }
private static Operand Const(long value, OperandType type = OperandType.I64)
{
return new Operand(type, (ulong)value);
}
private static int NextFreeRegister(int start, int avoid)
{
if (start == avoid)
{
start++;
}
return start;
}
} }
} }
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading;
namespace Ryujinx.Cpu.LightningJit.Cache namespace Ryujinx.Cpu.LightningJit.Cache
{ {
@@ -23,7 +24,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
private static readonly List<CacheEntry> _cacheEntries = new(); private static readonly List<CacheEntry> _cacheEntries = new();
private static readonly object _lock = new(); private static readonly Lock _lock = new();
private static bool _initialized; private static bool _initialized;
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
@@ -4,6 +4,7 @@ using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace Ryujinx.Cpu.LightningJit.Cache namespace Ryujinx.Cpu.LightningJit.Cache
{ {
@@ -104,7 +105,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
private readonly MemoryCache _sharedCache; private readonly MemoryCache _sharedCache;
private readonly MemoryCache _localCache; private readonly MemoryCache _localCache;
private readonly PageAlignedRangeList _pendingMap; private readonly PageAlignedRangeList _pendingMap;
private readonly object _lock; private readonly Lock _lock = new();
class ThreadLocalCacheEntry class ThreadLocalCacheEntry
{ {
@@ -137,7 +138,6 @@ namespace Ryujinx.Cpu.LightningJit.Cache
_sharedCache = new(allocator, SharedCacheSize); _sharedCache = new(allocator, SharedCacheSize);
_localCache = new(allocator, LocalCacheSize); _localCache = new(allocator, LocalCacheSize);
_pendingMap = new(_sharedCache.ReprotectAsRx, RegisterFunction); _pendingMap = new(_sharedCache.ReprotectAsRx, RegisterFunction);
_lock = new();
} }
public unsafe nint Map(nint framePointer, ReadOnlySpan<byte> code, ulong guestAddress, ulong guestSize) public unsafe nint Map(nint framePointer, ReadOnlySpan<byte> code, ulong guestAddress, ulong guestSize)
@@ -8,8 +8,6 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size) public IEnumerable<ulong> GetCallStack(nint framePointer, nint codeRegionStart, int codeRegionSize, nint codeRegion2Start, int codeRegion2Size)
{ {
List<ulong> functionPointers = new();
while (true) while (true)
{ {
nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size); nint functionPointer = Marshal.ReadIntPtr(framePointer, nint.Size);
@@ -20,11 +18,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
break; break;
} }
functionPointers.Add((ulong)functionPointer - 4); yield return (ulong)functionPointer - 4;
framePointer = Marshal.ReadIntPtr(framePointer); framePointer = Marshal.ReadIntPtr(framePointer);
} }
return functionPointers;
} }
} }
} }
@@ -1,3 +1,4 @@
using ARMeilleure.Common;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using Ryujinx.Cpu.Jit; using Ryujinx.Cpu.Jit;
using Ryujinx.Cpu.LightningJit.State; using Ryujinx.Cpu.LightningJit.State;
@@ -8,11 +9,16 @@ namespace Ryujinx.Cpu.LightningJit
{ {
private readonly ITickSource _tickSource; private readonly ITickSource _tickSource;
private readonly Translator _translator; private readonly Translator _translator;
private readonly AddressTable<ulong> _functionTable;
public LightningJitCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit) public LightningJitCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit)
{ {
_tickSource = tickSource; _tickSource = tickSource;
_translator = new Translator(memory, for64Bit);
_functionTable = AddressTable<ulong>.CreateForArm(for64Bit, memory.Type);
_translator = new Translator(memory, _functionTable);
memory.UnmapEvent += UnmapHandler; memory.UnmapEvent += UnmapHandler;
} }
@@ -40,7 +46,7 @@ namespace Ryujinx.Cpu.LightningJit
} }
/// <inheritdoc/> /// <inheritdoc/>
public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled) public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector)
{ {
return new DummyDiskCacheLoadState(); return new DummyDiskCacheLoadState();
} }
@@ -48,6 +54,7 @@ namespace Ryujinx.Cpu.LightningJit
/// <inheritdoc/> /// <inheritdoc/>
public void PrepareCodeRange(ulong address, ulong size) public void PrepareCodeRange(ulong address, ulong size)
{ {
_functionTable.SignalCodeRange(address, size);
} }
public void Dispose() public void Dispose()
+2 -21
View File
@@ -19,25 +19,6 @@ namespace Ryujinx.Cpu.LightningJit
// Should be enabled on platforms that enforce W^X. // Should be enabled on platforms that enforce W^X.
private static bool IsNoWxPlatform => false; private static bool IsNoWxPlatform => false;
private static readonly AddressTable<ulong>.Level[] _levels64Bit =
new AddressTable<ulong>.Level[]
{
new(31, 17),
new(23, 8),
new(15, 8),
new( 7, 8),
new( 2, 5),
};
private static readonly AddressTable<ulong>.Level[] _levels32Bit =
new AddressTable<ulong>.Level[]
{
new(23, 9),
new(15, 8),
new( 7, 8),
new( 1, 6),
};
private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs; private readonly ConcurrentQueue<KeyValuePair<ulong, TranslatedFunction>> _oldFuncs;
private readonly NoWxCache _noWxCache; private readonly NoWxCache _noWxCache;
private bool _disposed; private bool _disposed;
@@ -47,7 +28,7 @@ namespace Ryujinx.Cpu.LightningJit
internal TranslatorStubs Stubs { get; } internal TranslatorStubs Stubs { get; }
internal IMemoryManager Memory { get; } internal IMemoryManager Memory { get; }
public Translator(IMemoryManager memory, bool for64Bits) public Translator(IMemoryManager memory, AddressTable<ulong> functionTable)
{ {
Memory = memory; Memory = memory;
@@ -63,7 +44,7 @@ namespace Ryujinx.Cpu.LightningJit
} }
Functions = new TranslatorCache<TranslatedFunction>(); Functions = new TranslatorCache<TranslatedFunction>();
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit); FunctionTable = functionTable;
Stubs = new TranslatorStubs(FunctionTable, _noWxCache); Stubs = new TranslatorStubs(FunctionTable, _noWxCache);
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub; FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
@@ -23,7 +23,7 @@ namespace Ryujinx.Cpu.LightningJit
private bool _disposed; private bool _disposed;
private readonly AddressTable<ulong> _functionTable; private readonly IAddressTable<ulong> _functionTable;
private readonly NoWxCache _noWxCache; private readonly NoWxCache _noWxCache;
private readonly GetFunctionAddressDelegate _getFunctionAddressRef; private readonly GetFunctionAddressDelegate _getFunctionAddressRef;
private readonly nint _getFunctionAddress; private readonly nint _getFunctionAddress;
@@ -79,7 +79,7 @@ namespace Ryujinx.Cpu.LightningJit
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param> /// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
/// <param name="noWxCache">Cache used on platforms that enforce W^X, otherwise should be null</param> /// <param name="noWxCache">Cache used on platforms that enforce W^X, otherwise should be null</param>
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(AddressTable<ulong> functionTable, NoWxCache noWxCache) public TranslatorStubs(IAddressTable<ulong> functionTable, NoWxCache noWxCache)
{ {
ArgumentNullException.ThrowIfNull(functionTable); ArgumentNullException.ThrowIfNull(functionTable);
+1 -1
View File
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -5,6 +5,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading;
namespace Ryujinx.Cpu.Signal namespace Ryujinx.Cpu.Signal
{ {
@@ -59,7 +60,7 @@ namespace Ryujinx.Cpu.Signal
private static MemoryBlock _codeBlock; private static MemoryBlock _codeBlock;
private static readonly object _lock = new(); private static readonly Lock _lock = new();
private static bool _initialized; private static bool _initialized;
static NativeSignalHandler() static NativeSignalHandler()
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+18
View File
@@ -0,0 +1,18 @@
namespace Ryujinx.Graphics.GAL
{
public readonly struct ComputeSize
{
public readonly static ComputeSize VtgAsCompute = new ComputeSize(32, 32, 1);
public readonly int X;
public readonly int Y;
public readonly int Z;
public ComputeSize(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
}
}
+78
View File
@@ -339,6 +339,84 @@ namespace Ryujinx.Graphics.GAL
return 1; return 1;
} }
/// <summary>
/// Get bytes per element for this format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>Byte size for an element of this format (pixel, vertex attribute, etc)</returns>
public static int GetBytesPerElement(this Format format)
{
int scalarSize = format.GetScalarSize();
switch (format)
{
case Format.R8G8Unorm:
case Format.R8G8Snorm:
case Format.R8G8Uint:
case Format.R8G8Sint:
case Format.R8G8Uscaled:
case Format.R8G8Sscaled:
case Format.R16G16Float:
case Format.R16G16Unorm:
case Format.R16G16Snorm:
case Format.R16G16Uint:
case Format.R16G16Sint:
case Format.R16G16Uscaled:
case Format.R16G16Sscaled:
case Format.R32G32Float:
case Format.R32G32Uint:
case Format.R32G32Sint:
case Format.R32G32Uscaled:
case Format.R32G32Sscaled:
return 2 * scalarSize;
case Format.R8G8B8Unorm:
case Format.R8G8B8Snorm:
case Format.R8G8B8Uint:
case Format.R8G8B8Sint:
case Format.R8G8B8Uscaled:
case Format.R8G8B8Sscaled:
case Format.R16G16B16Float:
case Format.R16G16B16Unorm:
case Format.R16G16B16Snorm:
case Format.R16G16B16Uint:
case Format.R16G16B16Sint:
case Format.R16G16B16Uscaled:
case Format.R16G16B16Sscaled:
case Format.R32G32B32Float:
case Format.R32G32B32Uint:
case Format.R32G32B32Sint:
case Format.R32G32B32Uscaled:
case Format.R32G32B32Sscaled:
return 3 * scalarSize;
case Format.R8G8B8A8Unorm:
case Format.R8G8B8A8Snorm:
case Format.R8G8B8A8Uint:
case Format.R8G8B8A8Sint:
case Format.R8G8B8A8Srgb:
case Format.R8G8B8A8Uscaled:
case Format.R8G8B8A8Sscaled:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
case Format.R16G16B16A16Float:
case Format.R16G16B16A16Unorm:
case Format.R16G16B16A16Snorm:
case Format.R16G16B16A16Uint:
case Format.R16G16B16A16Sint:
case Format.R16G16B16A16Uscaled:
case Format.R16G16B16A16Sscaled:
case Format.R32G32B32A32Float:
case Format.R32G32B32A32Uint:
case Format.R32G32B32A32Sint:
case Format.R32G32B32A32Uscaled:
case Format.R32G32B32A32Sscaled:
return 4 * scalarSize;
}
return scalarSize;
}
/// <summary> /// <summary>
/// Checks if the texture format is a depth or depth-stencil format. /// Checks if the texture format is a depth or depth-stencil format.
/// </summary> /// </summary>
+1 -1
View File
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.GAL
void SetSize(int width, int height); void SetSize(int width, int height);
void ChangeVSyncMode(bool vsyncEnabled); void ChangeVSyncMode(VSyncMode vSyncMode);
void SetAntiAliasing(AntiAliasing antialiasing); void SetAntiAliasing(AntiAliasing antialiasing);
void SetScalingFilter(ScalingFilter type); void SetScalingFilter(ScalingFilter type);
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
public uint ProgramCount { get; set; } = 0; public uint ProgramCount { get; set; } = 0;
private Action _interruptAction; private Action _interruptAction;
private readonly object _interruptLock = new(); private readonly Lock _interruptLock = new();
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_impl.Window.SetSize(width, height); _impl.Window.SetSize(width, height);
} }
public void ChangeVSyncMode(bool vsyncEnabled) { } public void ChangeVSyncMode(VSyncMode vSyncMode) { }
public void SetAntiAliasing(AntiAliasing effect) { } public void SetAntiAliasing(AntiAliasing effect) { }
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+8 -9
View File
@@ -4,23 +4,22 @@ namespace Ryujinx.Graphics.GAL
{ {
public int FragmentOutputMap { get; } public int FragmentOutputMap { get; }
public ResourceLayout ResourceLayout { get; } public ResourceLayout ResourceLayout { get; }
public ComputeSize ComputeLocalSize { get; }
public ProgramPipelineState? State { get; } public ProgramPipelineState? State { get; }
public bool FromCache { get; set; } public bool FromCache { get; set; }
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, ProgramPipelineState state, bool fromCache = false) public ShaderInfo(
int fragmentOutputMap,
ResourceLayout resourceLayout,
ComputeSize computeLocalSize,
ProgramPipelineState? state,
bool fromCache = false)
{ {
FragmentOutputMap = fragmentOutputMap; FragmentOutputMap = fragmentOutputMap;
ResourceLayout = resourceLayout; ResourceLayout = resourceLayout;
ComputeLocalSize = computeLocalSize;
State = state; State = state;
FromCache = fromCache; FromCache = fromCache;
} }
public ShaderInfo(int fragmentOutputMap, ResourceLayout resourceLayout, bool fromCache = false)
{
FragmentOutputMap = fragmentOutputMap;
ResourceLayout = resourceLayout;
State = null;
FromCache = fromCache;
}
} }
} }
+9
View File
@@ -0,0 +1,9 @@
namespace Ryujinx.Graphics.GAL
{
public enum VSyncMode
{
Switch,
Unbounded,
Custom
}
}
@@ -11,8 +11,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
/// </summary> /// </summary>
class VtgAsComputeContext : IDisposable class VtgAsComputeContext : IDisposable
{ {
private const int DummyBufferSize = 16;
private readonly GpuContext _context; private readonly GpuContext _context;
/// <summary> /// <summary>
@@ -48,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
1, 1,
1, 1,
1, 1,
1, format.GetBytesPerElement(),
format, format,
DepthStencilMode.Depth, DepthStencilMode.Depth,
Target.TextureBuffer, Target.TextureBuffer,
@@ -521,21 +519,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size, write); return new BufferRange(_geometryIndexDataBuffer.Handle, offset, size, write);
} }
/// <summary>
/// Gets the range for a dummy 16 bytes buffer, filled with zeros.
/// </summary>
/// <returns>Dummy buffer range</returns>
public BufferRange GetDummyBufferRange()
{
if (_dummyBuffer == BufferHandle.Null)
{
_dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize, BufferAccess.DeviceMemory);
_context.Renderer.Pipeline.ClearBuffer(_dummyBuffer, 0, DummyBufferSize, 0);
}
return new BufferRange(_dummyBuffer, 0, DummyBufferSize);
}
/// <summary> /// <summary>
/// Gets the range for a sequential index buffer, with ever incrementing index values. /// Gets the range for a sequential index buffer, with ever incrementing index values.
/// </summary> /// </summary>
@@ -147,7 +147,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
{ {
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount); _vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0); _vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
SetDummyBufferTexture(_vertexAsCompute.Reservations, index, format);
continue; continue;
} }
@@ -163,15 +162,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
{ {
_vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount); _vacContext.VertexInfoBufferUpdater.SetVertexStride(index, 0, componentsCount);
_vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0); _vacContext.VertexInfoBufferUpdater.SetVertexOffset(index, 0, 0);
SetDummyBufferTexture(_vertexAsCompute.Reservations, index, format);
continue; continue;
} }
int vbStride = vertexBuffer.UnpackStride(); int vbStride = vertexBuffer.UnpackStride();
ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count); ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count);
ulong oldVbSize = vbSize;
ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset(); ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset();
int componentSize = format.GetScalarSize(); int componentSize = format.GetScalarSize();
@@ -345,20 +341,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
return maxOutputVertices / verticesPerPrimitive; return maxOutputVertices / verticesPerPrimitive;
} }
/// <summary>
/// Binds a dummy buffer as vertex buffer into a buffer texture.
/// </summary>
/// <param name="reservations">Shader resource binding reservations</param>
/// <param name="index">Buffer texture index</param>
/// <param name="format">Buffer texture format</param>
private readonly void SetDummyBufferTexture(ResourceReservations reservations, int index, Format format)
{
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
bufferTexture.SetStorage(_vacContext.GetDummyBufferRange());
_context.Renderer.Pipeline.SetTextureAndSampler(ShaderStage.Compute, reservations.GetVertexBufferTextureBinding(index), bufferTexture, null);
}
/// <summary> /// <summary>
/// Binds a vertex buffer into a buffer texture. /// Binds a vertex buffer into a buffer texture.
/// </summary> /// </summary>

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