Progress Report July 2021
We’re off and running in Q3 and already there have been dozens of bug fixes, performance optimizations, and quality of life improvements for end users. The month of July also brought a refactoring of the GPU 3D engine not only making the code behave closer to the original hardware but also fixing many rendering issues a few games suffered from.
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, a public test build is delivered. 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.
Vulkan Progress
As promised on the last month, there is now a Pull Request open with the Vulkan implementation. What that means is that the code is now public, and anyone can test it if they wish. It is not complete yet, so please do not interpret this as a feature announcement, there is still quite a lot of work to be done before it can be considered better than the OpenGL backend overall.
So let's start with where we stand today. Most of the functionality was already implemented, and only a few things remains unimplemented. Those include alpha test and multisampling (using the OpenGL backend as baseline here). There's still a number of bugs that needs to be fixed. Since the code was made public, users tested it and bugs were reported. Some of them were already fixed, but we still have a considerable amount to go through. Most of them only affects AMD or Intel, with a few affecting all vendors.
In terms of performance, AMD is a lot faster on Vulkan than OpenGL, as expected. Depending on the game, an improvement of about 2x or more on the frame rate can be seen. Intel is a mixed bag, with a few games being faster, but most seems to be slightly slower or the same speed as OpenGL. NVIDIA is still considerably slower than OpenGL in most games, however some users reported a few games being faster, Bayonetta being one of them.
Some graphical issues that existed on OpenGL were also fixed on Vulkan.
One example of such issue is the water on Paper Mario, that used to be black on OpenGL, but renders correctly on Vulkan.
There are a bunch of other issues that were also fixed on Vulkan, such as the lines on Pokémon, some glitches on Super Mario Odyssey, and more. We'll include a more complete compilation when Vulkan is finished and announced.
As for Intel, some games that didn't work, or were not rendering correctly on OpenGL, are working better on Vulkan.
For example, this is how Kirby Star Allies used on render on Intel OpenGL:
And how it renders now on Vulkan:
With Vulkan, the game can be considered playable even with an integrated GPU. And this is an UHD Graphics 630, which is one of the older iGPUs. Vulkan will enable more games to be played with integrated graphics, which means in the not so distant future, a dedicated graphics card probably won't even be needed to emulate most Switch titles. Not really surprising, since the Switch uses mobile hardware, but exciting to see nonetheless.
Two other games that also improved on Intel with Vulkan were Monster Hunter Rise and Hyrule Warriors: Ages of Calamity, which didn't even render anything (other than the UI) on OpenGL:
To a pretty much perfect render of Vulkan (minus minor issues on Monster Hunter Rise):
Performance is not great, but it should improve soon on Intel. It's still very exciting to see those games rendering so well regardless, since they previously didn't even render.
In case you're wondering, yes Monster Hunter Rise now works on AMD too (with Vulkan), although with more graphical issues than Intel (but better performance depending on your hardware, as one would expect).
Xenoblade still has issues on Intel, but it's already progressing further than OpenGL. By the time of the next progress report, it should be sorted out and we should have a nicer screenshot to show, so stay tuned ;)
Other improvements
One improvement that will affect all vendors, is faster shader compilation. Vulkan uses a new shader language called SPIR-V. It is much faster to compile than GLSL for a number of reasons, one of them being the fact that SPIR-V is a binary format, so the code is a lot more compact, and the compiler doesn't have to parse text.
You might be wondering how much faster SPIR-V is compared to GLSL. Below, you can find a recording of Resident Evil Revelations 2 on OpenGL (first) and Vulkan (second), both without any shader cache. The OpenGL compilation is multithreaded, the Vulkan one isn't.
OpenGL:
Vulkan:
Again, the Vulkan one is not multithreaded, which means that it will get even faster than this.
We don't have an exact ETA for this, but we want to get it done as soon as possible. If you want to follow the progress and help with the testing, you can do so here:
https://github.com/Ryujinx/Ryujinx/pull/2518
There is also another one that introduces multithreading to the Vulkan backend, increasing performance considerably on most games:
https://github.com/Ryujinx/Ryujinx/pull/2520
Note: All tests presented above were done without the multithreading.
If you do test it, feel free to submit bug reports on the PRs above or the Discord server. Just make sure the issue was not reported before.
Currently, we only have one developer working part-time on the Vulkan and SPIR-V backend (as well as the progress report!), so things may move a little slowly, but hopefully by the end of the month most of the pending work should be done. However, with your help through Patreon donations, our goal is to be able to pay this developer to work full time on the Ryujinx project, so don't forget to check out some of our other Patreon goals!
GPU
Fix deferred, batched buffer data updates
Not long ago, we released the "POWER" update that brought significant performance improvements to many games. For those not aware, "POWER" made the emulated CPU memory access much faster, by leveraging the host platform memory management hardware and mapping guest memory into the host address space directly. Due to this new approach, we had to change the way how the emulator performs inline buffer updates on the GPU side. Instead of writing data to memory word by word, it was changed to batch those updates and write whole chuncks at a time. Unfortunately, this change caused a regression on a few games. Batching the data updates means that they need to be written at a later time (as it needs to wait until all updates are performed to buffer it up, and then write it all at once), but sometimes "later" was too late, and by the time the data was written, the memory was already unmapped, causing a crash.
The fix was very simple, just forcing all batched data to be written to memory at the end of every command buffer did the trick.
Now the regressed games are working once again.
Implemented on #2407 by gdkchan.
GPU emulation refactoring
Some years ago, NVIDIA started publishing some documentation for their GPUs, including definitions with the name of some GPU registers. While still very incomplete and missing essential information, it can help in some cases. This change basically auto-generates the structures used on the emulator from the official definitions that they published where possible. This change alone doesn't have any user visible effect, but it makes the code neater/cleaner as we now use the official names for the register, and can fill some "gaps" of unknown information. However, this change goes beyond a simple name change.
The emulator now uses a struct to store the engine register state, rather than an array of integers, and the method used to detect state modification and update the host state was also updated, the new method is much more efficient. This alone brought a very small performance improvement in specific areas on some games. In the process, a few bugs were also fixed, including a bug that caused some games using the OpenGL API to be upside down due to the host state not being updated when a specific register was changed, and the behavior of the primitive type override register was also fixed (thanks to bylaws for confirming on hardware with a test homebrew).
Those fixes made a lot of games playable.
First we have Cat Girl Without Salad: Amuse Bouche, a nice shoot 'em up that uses the OpenGL API on the Switch, and suffered from the upside down issue.
Now, it renders correctly!
And can be played from start to end. Yes, we tested!
Other OpenGL Games that improved includes Game Tengoku CruisinMix Special, that went from a black screen...
...to a pretty much perfect render (minus some transparency issues).
A lot of other OpenGL games benefited from this change too, but this is enough to give an idea.
The primitive type override fix improved Turok 2, which had distorted vertices on the menus.
Now it renders as it should.
Implemented on #2422 and #2440 by gdkchan.
Mii applet not rendering on AMD and Intel
We recently announced the support for the mii editor applet, allowing users to create their own miis, and making games that require them to start a new game (such as Mario Golf: Super Rush and Miitopia) ingame/playable. However AMD and Intel users were not able to use it on Windows as the UI was not being rendered.
The problem is that texture views with different formats are not supported due to a bug on the drivers for those GPUs. To make it work, we had to use a different approach on those drivers, that performs a copy of the texture before use instead. However, a bug with the copy caused the texture to be replaced by an earlier version of the same texture, before the UI was rendered.
This bug is now fixed, and the mii editor applet now renders correctly on all the 3 vendors (NVIDIA, AMD and Intel) on Windows. It is worth noting that Linux users are not affected, it was already rendering correctly there on all vendors.
Fixed on #2433 by riperiperi.
Resolution scaling fixes
Last year, we released the resolution scaler, enabling several Switch titles to be played at 4K resolution and beyond on PC. While relatively simple to implement, making resolution scaling work well with all titles is complicated, because nowadays GPUs are quite "flexible", and games uses very different rendering techniques, which the resolution scaler has to take into account.
One game that did have problems with the scaling at launch was Monster Hunter Stories 2: Wings of Ruin. For the most part, it did work correctly. However, in battles, it was not working properly, as you can see on the screenshot below.
The problem was a small inconsistency on the shader. In most cases, when the shader reads the texture size, or reads from the texture with absolute pixel coordinates, the values are scaled or unscaled as appropriate. However, this was not happening when the shader explicitly reads the texture size using the "textureSize" GLSL built-in function. This was fixed by unscaling the sizes returned by this function before using them on the shader, and now the game renders as it should when scaled.
Fixed on #2441 by gdkchan.
Allow draws without a texture or sampler pool
This is a simple change that allows draws to be performed even when there is no texture or sampler pool currently set. Those pools are used to store information about the textures and samplers used by the shaders, but if the shader does not access any texture, then they are not needed. This just relaxes the requirement and allows the draws to happen without crashing in this case.
This allows Tales of Vesperia to work again (it is unknown exactly when it broke).
Fixed on #2476 by gdkchan.
Stay alive - keep some textures on the cache for longer
Legend of Mana has suffered since launch from a issue where portraits becomes black randomly. Aditionally, there is another issue where the player sprite may get corrupted randomly.
As you can see above, what is supposed to be the player portrait is completely black instead.
The problem here was that on buffer to texture copies, it was possible for the texture data to be lost forever, if the texture was removed from the texture pool right after the copy. This was fixed by adding the texture to a small cache to make it live for a bit longer. This cache also automatically writes the texture data back into memory when the texture is naturally removed from the cache, so even when it is eventually removed, the data is still preserved and everything works.
Above you can see how it looks like now. The portrait is now rendered as it should.
Fixed on #2478 by gdkchan.
Skyward Sword HD performance improvements
One of the most awaited releases of the month was The Legend of Zelda: Skyward Sword HD. The game ran relatively well on the emulator at launch, but had some performance issues. Only the most high end systems were able to run it at full speed, something that doesn't feel right for what is essentially a port of a now 10 years old Wii game.
Thanks to some profiling made by riperiperi, the issue was quickly identified as the texture flush operation. It turns out that the game reads the depth buffer from the CPU to do some effects, like the lens flare effect (which is supposed to be occluded if there's something in front of the sun, for example).
Thanks to several optimizations focused on texture flushes, the game now runs much faster. In fact, it can run at full speed even on more modest systems now, and it looks beautiful at 4K!
Other games that does one or more texture flushes per frame, such as Pokémon Sword/Shield, were also significantly improved by those changes.
Implemented on #2481 and #2494 by riperiperi.
HLE
Fix IsDynamicDnsEnabled
Games that uses online features used to call a .NET function called "IsDynamicDnsEnabled". This is not supported on Linux, and would cause a crash. This was fixed by simply returning "false" on Linux.
This allows games like Invisigun Reloaded to be played on Linux.
It is worth noting that even though the emulator has some very basic implementation of network related services, it is not enough to make online functionality work in most games.
Fixed on #2443 by Ac_K.
Restart
Super Smash Bros Ultimate requests an application restart when the language is changed on the game. This was not implemented on the emulator, and would just result in a crash instead.
The required function is now implemented, allowing the language to be changed from the game.
Implemented on #2448 by Ac_K.
Fix out of range virtual memory allocation
A kernel bug caused some games to crash, either at boot, or at some point later. One function responsible for doing virtual memory allocation receives a virtual memory range. It should then find a free region inside this range, and return it. However, it would in some cases, return a free region outside of that range, which is incorrect. This usually does not cause issues, because for the most part, the game usually doesn't care about where things are allocated, so long the region is not already in use. However, there is a SDK function that makes assumptions about the memory layout. It assumes that the memory region that the kernel was (erroneously) using for something else was free.
The issue was, fortunately, very easy to fix. And now a few games that would previously just crash, can now go further, some being fully playable.
For example, Disaster Report 4, that used to crash before showing anything, can now go ingame, although it is not playable due to graphical issues.
Wonder Boy Asha in Monster World is now ingame (possibly playable, needs further testing).
Diablo 3 no longer crashes randomly on the updated version.
...and a few other games were also fixed.
Thanks to kakasita and Leischii for testing.
Fixed on #2464 by gdkchan.
Fix right Joycon motion data not being set
Another problem affecting The Legend of Zelda: Skyward Sword HD, is that the right Joycon data was not set properly. This means that motion was not working correctly on this game, which requires motion from the right Joycon to control the sword. While the game features button only controls, they can be a bit awkward at times, as the sword is controlled with the right stick, and controlling the camera requires pressing another button, so many users prefers to play with motion controls instead.
Now the motion data is properly written to memory, allowing the game to be played with motion.
Fixed on #2488 by emmauss.
GUI
Headless mode
This is a separate build that can be used to launch the emulator without any UI. Most of the things that you would configure on the GUI, is a command line option instead. This is useful for launchers, where you are supposed to configure and then just launch the game directly from it. It is also useful when porting to new platforms, as one does not need the entire GUI working to make tests.
Above you can check out what it looks like. Basically just a window and the game.
Implemented on #2310 by Thog.
Say cheese everywhere
This PR makes it easier for portable users to keep everything in one place. When running in portable mode, screenshots will now be placed inside the "Ryujinx/screenshots" folder instead of the user's Pictures folder. The screenshots are taken using the emulator internal resolution, which means that if you use resolution scaling, they will be taken with the scaled resolution, even if your monitor resolution is lower. This enables users with 1080p monitors to take 4K screenshots, for example. Be aware that high resolution screenshots takes a lot of disk space.
You can take screenshots by pressing the F8 key. In the future, we should make this configurable.
If you want an example of screenshot taken using it, you can just check the pictures on the top of this progress report. We have been using it for announcement and progress report screenshots.
Implemented on #2143 by emmauss.
Implement a "hide UI" option to hide and show the menu and status bar
Until now, the menu and status bar were always visible when playing in windowed mode and hidden in fullscreen mode. This PR adds a new option under the "Actions" menu to hide the menu and status bar. Additionally, it is now possible to show these UI elements in fullscreen mode by hitting the "Alt" key, making it easier to change options without going back to windowed mode.
Note: The key used to show/hide the UI will be changed in the future, as a few problems were reported with the use of the "Alt" key, since this key is already used for a few system and emulator shortcuts.
Implemented on #2411 by ooa113y.
Don't tick "Start Games in Fullscreen Mode" when using the "-f" argument
This PR prevents the "Start Games in Fullscreen Mode" option from being ticked when using the "-f" argument to start Ryujinx. Ticking this option would make it persist even if the "-f" argument was removed.
Fixed on #2424 by mpnico.
New code contributors July 2021:
mpnico
Closing words
We would like to thank everyone that helped the emulator so far, be it through Patreon, code contributions, testing or simply being an active member of our community. You all rock!
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!