Progress Report June 2021
June brought with it scads of graphics optimizations, bug fixes, some quality-of-life GUI enhancements, and a nice bump in overall game compatibility. Project No Name also landed, providing native Mii applet support, marking the first time a Switch system applet has been successfully emulated!
But before plunging into the deep end, let’s review the state of Ryujinx’s Patreon goals and deliverables:
Amiibo Emulation - merged into the main build in March 2021.
While compatibility is now almost perfect, there are still some improvements to come for Amiibo which can be tracked on the associated Github issue here: https://github.com/Ryujinx/Ryujinx/issues/2122
Custom User Profiles - merged into the main build in April 2021.
Vulkan GPU Backend - still in progress, working to deliver a public test build as soon as possible. See below for a more in-depth report on the progress of this feature.
ARB Shaders - Goal reached in April 2021. Work on ARB shaders will begin as soon as Vulkan is finished.
ARB shaders will further reduce stuttering on first-run by improving the shader compilation speed on NVIDIA GPUs using the OpenGL API.
$2000/month - Texture Packs / Replacement Capabilities - Almost there!
This will facilitate the replacement of in-game graphics textures which enables custom texture enhancements, alternate controller button graphics, and more.
ETA once goal is reached: ~3-4 weeks
$2500/month - One full-time developer - Not yet met
This amount of monthly donations will allow the project's founder, gdkchan, to work full-time on developing Ryujinx.
$5000/month - Additional full-time developer - Not yet met
This amount of monthly donations will allow an additional Ryujinx team developer to work full-time on the project.
The Vulkan initial release has been delayed a few months from the projected time frame due to unexpected issues that we found during tests. As we mentioned before, the latest AMD driver updates brought regressions and the amount of developers we have with an AMD GPU is limited, so it was not fixed yet. In order to avoid further delaying it, we have decided to make the code public as-is to allow users to follow the progress live, and also test it if they wish to. This will also allow external contributors to give input on it (suggestions or direct improvements). The PR should be available in July.
Meanwhile, you can check out more recent Vulkan tests below.
The graphical glitches were caused by a recent change to buffer updates, but it seems to be a driver bug.
The boat textures are rendered correctly on Vulkan, they are currently broken on OpenGL.
Note: The Monster Hunter Rise tests doesn't contain any of the improvements on LDN 2.3, this is just master + Vulkan.
All tests above were performed on a laptop with a i7-9750H CPU, dedicated GTX 1660 Ti GPU, and 8GB of RAM, running Windows 10.
Vulkan FAQ (Updated)
Will Vulkan include a shader cache?
The main goal right now is getting Vulkan delivered in a good working state. If this is done quickly enough and there's still enough time left for a shader cache implementation, then shader cache could be added. Otherwise, it will be left as a follow-up task and will be implemented after the Vulkan implementation is merged into the master branch of the emulator. To clarify, our ETAs of these Patreon goal features is the estimated time to develop the feature and submit the PR (pull request) for public testing & review. Actual merge dates into the main build may vary and do not have ETAs.
Will Vulkan include async shader compilation?
No, for the same reason it is not implemented in OpenGL. The async shader compilation feature implemented on other emulators come with compromises like visual glitches while shaders compile, some of them being persistent until emulation is stopped. It also does not fully eliminate stutter as some shaders cannot be compiled asynchronously. For those reasons, the current Ryujinx GPU emulation developers are not interested in implementing it. We are not opposed to an external contributor implementing this feature, however.
Will Vulkan support resolution scaling?
Yes. The goal is having feature parity with OpenGL upon release.
What kind of improvement can I expect?
AMD and Intel GPU users should expect a significant improvement in compatibility, performance and, especially for Intel GPU users, a major reduction in graphical glitches. NVIDIA users can expect a small performance improvement in a few titles (we will defer saying which ones until after the Vulkan implementation is properly optimized and tested). All GPU vendors should benefit from faster shader compilation and less stuttering on Vulkan.
AMD pls… - Avoid clearing alpha channel by handle when presenting
While not known for having the greatest OpenGL support in Windows, AMD GPUs had at least been able to display graphics on most games in the emulator up until the release of their 21.4.1 graphics driver. With the release of this driver came a new show-stopping bug that made all AMD GPUs in the Ryujinx Windows client simply display a black screen when booting a game.
The issue was caused by the method that the emulator uses to draw the image on the screen. Some games produces an output image that have semi-transparent pixels, which should be ignored when presenting it to the screen, otherwise it may show whatever is behind the emulator window (such as the user desktop). To prevent that from happening, the alpha channel is cleared before bliting the texture, something that used to work on older AMD driver versions, but not on the new one. Making it work on the newer driver required using a slightly different method to clear the alpha channel, using a function that clears the currently bound framebuffer, rather than the one specified by handle. Now AMD GPU users don’t have to worry about downgrading drivers in order to use the emulator.
Fixed on (#2323) by Thog
Maximum Overdrive - Use Quads on OpenGL host when supported
In keeping with last month’s theme, June started off with yet another performance upgrade, this time affecting FAST RMX and the Xenoblade series of games. To do this, a deprecated but still valid method of fast-drawing primitives called “quads” was employed. Without quads, every rectangle/parallelogram needs to be split into two triangles; naturally, being able to process rectangles natively without splitting them into triangles saves some overhead.
This update institutes a check for quads support and uses them if the GPU in question can perform them; if not, it will use the triangles method. In practice this seems to benefit NVIDIA GPUs the most, with games that use significant amounts of rectangles reaping the largest rewards.
Implemented on (#2331) by riperiperi
Can’t see $#@!, Captain - Fix texture blit off-by-one errors
NVN (a custom graphics API developed by NVIDIA used by many games on the Switch) adds an offset to the source X/Y coordinates of the blit, in order to ensure that the blit will be "centered" (sampling from the center of the pixel rather than the corner). This change removes said offset by subtracting the offset value from the coordinates.
The result of this change fixes some off-by-one errors that caused the destination textures to have a black border. When used to blit mipmap levels, this could propagate and cause the whole texture to be black in the end, as it would usually use the previous level as source. This only affects copies between regions of different sizes, as when the sizes are equal, the offset is 0.5 (which is truncated to 0).
The most glaring example of a game fixed by this update is Fast RMX, which suffered from almost a pure white rendering when the in-game “Dynamic Camera Exposure” graphics option was enabled.
However, it also fixed incorrect rendering of Mii faces in Mario Kart 8 Deluxe (note the black line down the middle of the face).
Fixed on (#2335) by gdkchan & riperiperi
Fix shaders with mixed PBK and SSY addresses on the stack
This update fixes a bug involving shaders that makes use of the PBK & SSY instructions that could trigger the BRK instruction to jump to an incorrect address. The way how it is supposed to work is that the PBK instruction pushes an address on the stack, and the BRK instruction pops the address from the top of the stack and jumps to it. The SSY and SYNC instruciton pair works the same way, but there's a catch. BRK should only use the address pushed by PBK, and SYNC should only use the address pushed by SSY, if there's another address in-between, it should be simply discarded. Before this change, they were not being discarded, which caused the shader to jump to the wrong location. The only known instance of the bug being triggered was in Dead or Alive Xtreme 3, causing the sky to be rendered a deep pink color.
With this fix the correct address is fed to the BRK instruction, and the sky is correctly rendered.
Fixed on (#2329) by gdkchan
Support bindless textures with separate constant buffers for texture and sampler, Fix separate bindless sampler at offset 0
Some games, such as Final Fantasy XII, store the handles on different constant buffers, which was previously not supported. This first update extends the shader bindless elimination to support this case, and also extends the GPU emulation to support reading the handles from different buffers.
Without the update Final Fantasy XII rendered nothing, though the game could be heard booting otherwise normally. After the update, the game booted and rendered most graphics normally.
As you can see above, the texture on the floor toward the top of the screenshot wasn’t quite right.
When the (separate) sampler bindless handle comes from the offset 0 of the constant buffer, it was being ignored which caused the wrong sampler to be used. The second update here corrected this bug by adding 1 to the offset on the shader translator, and then subtracting 1 on the GPU emulator to ensure that it is never 0 if a separate bindless sampler is used.
And now the floor is rendered properly.
Implemented on (#2339, #2360) by gdkchan
You’ve got to ask yourself: do I feel lucky? - Do not clear GPU subchannel state on BindChannel
The advent of GPU syncpoints, added to the emulator in early 2020, greatly increased accuracy of GPU operations and brought them closer to how they are processed on original hardware. However, it seems a single game suffered a serious regression due to the implementation, only discovered many months later: New Super Lucky’s Tale, prior to GPU syncpoints, was able to boot and go in-game though it was plagued with vertex explosions and slow gameplay. After GPU syncpoints, the game simply did not boot at all.
The fix for this bug was to *not* clear gpu subchannel state on BindChannel functions, as was done previously. Combined with all of the other updates in the last year+, the game now renders and plays perfectly.
Fixed on (#2348) by Thog
End shader decoding when reaching a block that starts with an infinite loop
The NVIDIA shader compiler puts infinite loops at the end of shaders. The emulator takes advantage of this on shaders that includes a BRX instruction, as the emulator continues decoding past all exits in order to catch potential branch targets. Before, this would terminate when it encountered a 0, but some shaders did not have a 0 at the end and therefore ended up decoding forever; this was possibly because the shader data did end at the infinite loop, and the "instruction" afterwards was just leftover data from earlier rather than 0.
This update fixes Dark Devotion booting to a pure white screen while generating ungodly amounts of log spam. The game now boots with accurate game graphics, though the rendered frame is upside down.
Fixed on (#2367) by riperiperi
Pass all inputs when geometry shader passthrough is enabled
Previously, geometry shaders weren’t passing all inputs to the next stage, causing possible shader linking issues. This resulted in missing graphics.
With this change the shader translator now passes all inputs of geometry shaders when needed, fixing some missing graphics in Game Builder Garage.
Fixed on (#2362) by gdkchan
Inherit buffer tracking handles rather than recreating on resize
Previously the GPU buffer tracking system recreated memory handles for the CPU side when a buffer was resized by a game. This was a large bottleneck in games that constantly resize GPU buffers, such as Super Mario 3D All-Stars, Hyrule Warriors: Age of Calamity, or many UE4 games. This was addressed by reusing memory handles from previous buffers that were allocated in that memory range, and the associated games have seen a reduction in slowdowns.
Fixed on (#2330) by riperiperi
Fix texture sampling with depth compare and LOD level or bias
Early after Mario Golf Super Rush’s release, a shader compilation error revealed an oversight in the emulator’s shader code generation. This update fixed that oversight by activating a missing GLSL extension on GPUs supporting it, or by discarding the level of detail parameter if the GPU doesn’t support it. Thanks to this quick fix, Mario Golf: Super Rush was playable very quickly after release!
Fixed on (#2404) by gdkchan
Fix shader texture LOD query
A bug in Mario+Rabbids Kingdom Battle causing blurred title text was resolved. An inverted component order was causing the game to use the wrong LOD value, resulting in what you can see below.
And with the update, the title looks as it should.
Fixed on (#2397) by gdkchan
Initial support for GPU channels
NVIDIA GPUs are well known to be technological works of art; the specific GPU used on the Switch is no exception. Operations on these GPUs are divided into multiple specialised register blocks handling, for example, 3D or 2D operations. When a game wishes to interact with any of these blocks it creates a channel, associates the blocks to various subchannels and finally sends commands to perform operations with them. However, a game can also choose to have multiple channels to separate workloads on the GPU. Until now, Ryujinx only had one global channel that was receiving all operations, which was possibly causing some games to crash or hang. With this update, the emulator now has initial support for multiple channels, allowing it to be closer to how the original hardware behaves. Thanks to this new support, various games that were previously crashing are now able to go in-game!
Implemented on (#2372) by gdkchan
Initial support for separate GPU address spaces
As a continuation of the initial support of GPU channels, gdkchan added support for multiple GPU address spaces in the emulator. This allows the GPU virtual memory emulation to be more accurate and behave more closely to how the Switch GPU handles it.
With this update Super Smash Bros. Ultimate story mode/World of Light, thus far off-limits in the realm of Switch emulation, is finally playable!
Implemented on (#2394) by gdkchan
Oh, THERE you are! - Fix default value for unwritten shader outputs
Monster Hunter Stories 2: Wings of Ruin demo was released this month, and ran almost perfectly in the emulator on day one; just one graphical issue was evident. This manifested as some characters’ bodies being almost completely invisible, as you can see in the below screenshot.
This missing geometry was due to a bug in which the W component of the default output values for shader outputs were set to 0, when they should be set to 1.
With the six-line fix in place, characters render as they should
However, there is at least one game that may have benefitted from this update even more than Monster Hunter Stories 2: Wings of Ruin.
Resident Evil 6, while performant at a playable speed for a while now, has suffered a variety of graphical issues since it first became bootable. gdkchan’s shader output fix resolved all known visual bugs in this game, as we’ll explore below.
Some background info: upon starting a new game you are greeted with a scripted intro showing opening credits, then on to a cutscene with baddies where you escape under the searchlight of a helicopter, and finally on into gameplay with the protagonist. Each phase of the above steps had noticeable issues that have been fixed by this update.
As the opening credits are shown, there are three things wrong with the below image. The “insect” on the steering wheel has incorrect textures; the credit text blobs themselves are completely missing; and the background visuals rendered behind the windshield are mostly failing to render as well.
After the fix, all three of these elements are displayed correctly:
As the cutscene continues, prior to this update, the bad guys running around fighting in the street looked like chickens quite literally running around with their heads cut off. Below you can see the outline of what appear to be several human bodies silhouetted against the fire behind them. But how can you be certain, since their heads are missing?
And again, with the update, the graphics are now rendered correctly.
As the cutscene ends you are shown a frontal view of our would-be heroes, who used to look completely normal except all of their hair was missing. This bug was one that continued on into playing the game and was quite distracting if not immersion-breaking.
Once again, after the fix, graphics are rendered correctly and our heroes’ perfectly coiffed hair can really shine.
Who knew a simple change from 0 to 1 would resolve so many issues?!
Fixed on (#2412) by gdkchan
CPU & Kernel Improvements
Implement VORN (register) Arm32 instruction
A rarely used CPU instruction was identified as unimplemented, and was preventing MushihimeSama from booting. This update implements VORN (register variant) and includes automated unit tests. MushihimeSama is now able to boot further, however a controller applet issue prevents it from being playable.
Implemented on (#2396) by gdkchan
hid/irs: Stub IsFirmwareUpdateAvailableForSixAxisSensor and CheckFirmwareVersion
A couple of the lesser used hid & irs services was preventing the Nintendo Labo Toy-Con 03: Vehicle Kit application from booting unless the “Ignore Missing Services” hack was enabled. This update stubs a couple of these services, as their functionality (related to operation of the six axis sensor and infrared sensor) is not fully needed for the successful usage of the Toy-Con app.
With the update, the “game” boots as it should without needing to enable any hacks.
Implemented on (#2371) by LukeFZ
account: Fix wrong condition in TrySelectUserWithoutInteraction
Since the introduction of multiple user profile support, many users have enjoyed the flexibility of customizing their profile name and picture. One game, Shantae Half Genie Hero, seemed to have a problem with the multiple user profiles: if multiple profiles were present, the game would softlock after pressing A at the title screen.
The issue was due to an incorrect condition specified in TrySelectUserWithoutInteraction. Correcting the condition fixed the bug, and now the game is able to use multiple profiles without issues.
Fixed on (#2384) by AcK77
ipc: Remove size checks for buffer type 0x21/0x22
This was a case where Ryujinx was performing an unnecessary size check on a buffer, causing some unexpected behavior in certain games and homebrew applications. As this check is not performed on original hardware, this function was removed. Knockout City is now bootable (though unable to be played as it requires an online connection.)
Fixed on (#2384) by AcK77
Down the rabbit hole - hid: Cleanup and implement some calls
AcK77 put in some heavy lifting this month with several updates adding missing service calls. However the one most easily appreciated is the service call `IsVibrationDeviceMounted`. This service is called on Super Mario Odyssey version 1.3.0 when Mario jumps down a pipe in Sand Kingdom for PowerMoon 52. Unless the “Ignore Missing Services” hack was enabled, this would cause a crash in the emulator. Now users no longer have to enable this option to get past this part of the game!
Implemented on (#2041) by AcK77
aoc/am: Cleanup aoc service and stub am calls
AcK77 delivered another boost with this update that cleaned up the add-on content manager service (used for game DLC) and implemented associated service calls both for aoc and am services. With these changes, Tony Hawk’s Pro Skater 1 and 2 is now playable.
Implemented on (#2414) by AcK77
no name: Mii Editor applet support
One of the main goals in the Ryujinx project, from the very beginning, has been to strive for the highest accuracy possible (that is, faithful recreation of how things run on original hardware) while maintaining the objective of games being emulated at a playable speed. “Why?“ some may ask. The most apparent reason would be to facilitate high game compatibility, but there is much more to it than that. With some comprehensive reverse engineering and a bit of elbow grease, AcK77 has made it possible to manage your Mii in Ryujinx; no need to fire up your Switch! This allows games like Miitopia, and other games requiring personalized system Miis, to be playable. With “no name”, so called as a tongue-in-cheek reference to the lack of ability to create your own Miis in the emulator up until now, you can finally run a system applet natively for the first time in Switch emulation; this is but a foretaste of the possibilities that lie ahead...
Implemented on (#2419) by AcK77
We can go higher - Increase height of Settings Window
This one-line change increases the height of the Settings Window in the emulator options menu so that scrolling is no longer necessary, and all options can be immediately set as desired.
Implemented on (#2355) by EmulationFanatic
Well...there it is - Improve gameTable search
The game list search has been enhanced to find results not only by game title, but now also by title ID. This added flexibility can be especially useful in situations where one has a large game library and a keyword search may return too many undesired results.
Implemented on (#2398) by ooa113y
Unbind input on middle click
The emulator’s input support has vastly improved this year, but until now there was no way to individually unbind a particular button mapping. With this update, middle click (or mouse wheel click) will unbind the selected mapping, if you wish.
Implemented on (#2358) by ooa113y
Reduce number of dlls on distribution with single file publish
It shouldn’t come as a surprise to anyone by now, but Ryujinx’s releases contain quite a few files in the root folder…or should we say they used to! Thanks to this update, which takes advantage of .NET 5’s single file publish feature, every new Ryujinx release now contains far fewer files and the ZIP archive itself has had its size reduced.
Implemented on (#2211) by gdkchan
The ability to take screenshots within the emulator, requested by many users over the last year+, is finally here! It is now possible to take screenshots at the specified rendering resolution by pressing F8 while in-game. This means that every screenshot you take will respect the resolution scaling setting, and output an image of the actual size of the scaled resolution (i.e. a 4x scaled screenshot on a 1080p game will result in an 8K image). You can find generated screenshots in your Pictures directory under a new “Ryujinx” subdirectory. Caution: screenshots taken with a high resolution scaling setting may be rather large!
Implemented on (#2354) by emmauss
Game Compatibility - Q2 2021 Update
At the end of March, the state of tested game compatibility was:
3242 titles tested
58% playable - no visible bugs; no crashes or deadlocks; fast enough to enjoy on an average PC
26% in-game - goes past menus but suffers from visible bugs, crashes, deadlocks, or is too slow
6% menus - boots and goes past the title screen but does not reach main gameplay
5% boots - boots but does not advance past the title screen
5% nothing - does not boot/shows no signs of life
With recent bug fixes and May’s POWER update, plus an exhaustive re-testing effort to update games that were due (or overdue) for re-testing, overall compatibility in Q2 2021 has again seen a significant jump:
3382 titles tested - (140 new additions)
69% playable - no visible bugs; no crashes or deadlocks; fast enough to enjoy on an average PC
20% in-game - goes past menus but suffers from visible bugs, crashes, deadlocks, or is too slow
3% menus - boots and goes past the title screen but does not reach main gameplay
4% boots - boots but does not advance past the title screen
4% nothing - does not boot/shows no signs of life
With POWER increasing performance across the board in Q2, the game compatibility list is now applicable to systems sporting much lower specs than previously. Users with slower systems who may have given up on Ryujinx long ago because their hardware was deemed “too slow” are encouraged to try again.
We look forward to sharing continued compatibility improvements this year!
New code contributors June 2021:
Thanks to all those that have supported Ryujinx so far, be it via Patreon donations, code contributions, testing games in the emulator, or simply being an active member of our community: you’ve helped make this emulator what it is today!
We have an active Patreon campaign with specific goals and restructured subscriber benefits/tiers, so please consider becoming a patron to help push Ryujinx forward!