Spring 2020 Progress Report

It's been awhile since our last progress report, and we apologize for the long delay, but today we want to show some nice improvements we had in the past few months. These include advancements in compatibility, graphical fixes, and more!

Spring 2020 Progress Report

News: various developments & enhanced compatibility

It's been awhile since our last progress report, and we apologize for the long delay, but today we want to show some nice improvements we had in the past few months. These include advancements in compatibility, graphical fixes, and more!

GPU emulation improvements:

· Super Smash Bros Ultimate T-Pose bug

SSBU had a long-standing bug where most of the characters wouldn't have proper animation. Instead, they were rendered in their standard "T-Pose" positions. After some analysis, gdkchan discovered that the problem was caused by a bug in one of the compute shaders responsible for doing the animation; the bug was just a wrong instruction. After fixing it, the animations now work!

· Corruption of some texture mipmap levels

As some of you may be aware, Astral Chain has been working on Ryujinx since last year. It did have, however, some very odd graphical issues. While investigating some texture issues in other games, gdkchan discovered a bug that affected mipmap levels of some textures. The offset of the levels was not being calculated correctly in some cases, causing it to load the data from the wrong memory location for some textures, thus making them appear "corrupted" in the game.

The image below shows this issue pretty well:

As you can see, there are quite a few things wrong here. Yoseph is yellow with blue hair, the floor is blue, the police uniform is rendered incorrectly, and the list goes on. You may also notice these issues only occur on things rendered from a distance. This happens because while the issue affects some mipmap levels of the texture, the base level is not affected.

Fixing the issue required some reverse engineering of NVN code, to help us understand how the GPU is supposed to behave with those textures. And after a little bit of work, the issue was fixed:

As you can see, the scene now renders properly and is visually indistinguishable from a real Switch.

· Texture buffers

Texture buffers are basically like 1D textures, but they are more limited in some aspects and use buffer instead of texture storage. Most notably, they are used by Unreal Engine 4 games for model animation, which means that without proper support for this GPU feature, animated models are not going to render at all on those games.

One of the games that improved with this change was The Caligula Effect: Overdose, one of the Switch Unreal Engine 4 ports.


Inverted colors are a separate issue, and are caused by the lack of BGRA texture support on OpenGL.

· Conditional rendering

Conditional rendering is a GPU feature that allows rendering to be enabled or disabled based on some internal GPU conditions. It is generally an optimization that will stop the GPU from rendering things that don’t matter (because they are out of view for example). Lack of support for conditional rendering is generally not an issue, but some games do strangely make use of it, and won't render without basic support. These games are Super Mario Maker 2 and Animal Crossing: New Horizons.

Here we can see Super Mario Maker 2 now working properly with the conditional rendering implementation.

Initial support for conditional rendering was implemented by gdkchan. Riperiperi optimized it afterwards, and also optimized GPU queries. This brought a significant performance improvement to Super Mario Odyssey and Splatoon 2.

· Depth clamping

This feature can be used to change how depth values are handled on the GPU, and it restricts the depth value to a given range at the end (this is what is called clamping). Thanks to mageven, depth clamping is now supported. It resolves some graphical issues on games like The Legend of Zelda: Breath of the Wild.


· Shader interpolation improvement

Shader allows the interpolation method of the values that are passed to the pixel shader stage (called varyings). On NVIDIA, the interpolation is done with an instruction called IPA. Ryujinx’s implementation of this instruction was not fully correct, and this caused issues on some games as the values were not properly interpolated.

One of these games was Animal Crossing: New Horizons, wherein particles didn't render at certain angles, as seen on the image below:

With a better implementation of the IPA instruction, the game now renders much better:

This also fixed other games suffering from interpolation issues. For example, the image below demonstrates the lack of perspective correction caused by the wrong interpolation qualifier being used on shaders:

Which now renders properly:

This issue was fixed by gdkchan.

· Face culling

One of the more notable bugs we mentioned at the start of the year was a bug that caused geometry to appear to be inside out on games like Xenoblade Chronicles 2. This bug was caused by wrong face culling, and also affected games like Disgaea 4 Complete. After some deeper investigation, gdkchan was finally able to find and fix the issue. Now both of these games render properly! And of course, the fix also improved other games with similar issues.



· Bindless textures

Another item that was teased on the first progress report of the year was support for some games that previously didn't render anything, like Metro 2033 Redux and Spyro Reignited Trilogy. Those games use bindless textures, a feature that basically allows any texture that has been "registered" on the GPU to be used on a shader, without having to explicitly bind them and call out "Hey, I will use this texture on this draw call". Supporting bindless textures on an emulator has a number of issues, but fortunately, we don't need to do so for these games. At their core, these games are doing something that is possible on Direct3D (and NVN as well, of course), but not OpenGL. They combine arbitrary texture and samplers on the shader. Since we can't do that on OpenGL, the approach we used was doing code analysis techniques to find all the possible texture and sampler combinations that the game might use on the shader code, and bind them all beforehand.

As a result, these games now render and are a step closer to full playability.

· Shadow clipping

One long standing GPU issue was recently fixed by one of our newest GPU code contributors. A shadow issue used to plague a few games, including titles like Super Mario Odyssey and ARMS. These issues manifested themselves in strange ways as seen in the screenshot below:

Pay close attention to the shadow being cast from the odyssey.

Thanks to the shadow clipping implementation from mageven, the shadow is now properly cast on the ground:

· Shantae and the Seven Sirens softlock at boot fix

Upon launch, this new entry in the Shantae series had an issue that prevented the game from even reaching the title screen. It turned out to be a GPU issue; the game was waiting until one of the GPU semaphores was incremented, but that didn't happen because it was not implemented at all. Fortunately, the issue was fairly easy to diagnose. And after fixing it, the game is perfectly playable! Well, except for the missing cutscenes of course...

Above you can see Shantae, dancing through the danger.

· Xenoblade Chronicles: Definitive Edition odd stencil issue

Xenoblade was one of the big game releases in April; it is a remake of an old Wii game. The game booted since day 1 on the emulator, but certainly not without some issues. One of the most noticeable examples was that most of the geometry was completely black, as if it didn't render at all. The issue was caused by a missing depth-stencil texture format which, thankfully, is something easy to spot and fix.


XC:DE also has other GPU emulation bugs that we will talk about later.

· Regression fixes

Also worth noting are some regressions that were discovered and fixed during that time. The fast queries optimization caused a regression on the game Yo-kai Watch 4, where it would freeze when attempting to start a new game. Some changes in the way global memory is handled on compute shaders also caused a regression on Tokyo Mirage Session FE #Encore. Both regressions are now fixed, and the games are back to working as they had been before.

CPU emulation improvements:

· FMAXNMV instruction

The 64-bit ISA support on our CPU is fairly complete. However, every now and then, we come across a missing instruction that prevents some game from getting in-game or working at all. The FMAXNMV instruction, which basically takes the maximum number between two vectors, was required by a few games, like World of Final Fantasy Maxima and GRID. Thanks to the hard work from LDj3SNuD, the instruction is now implemented, and these games are now playable! See for yourself.

·   PPTC

PPTC stands for "Profiled Persistent Translation Cache". It's somewhat similar to AOT (Ahead of Time compilation). As you may know, most modern emulators achieve higher performance on CPU emulation by "recompiling" the code to something that the target CPU can understand, and execute directly. This process is what we call "translation", as it effectively translating code from one CPU to another. This new feature saves the generated code on disk, eliminating the need to recompile it on the next run, saving significant time. This can speed up loading of the games noticeably.

These changes were implemented by LDj3SNuD, and have been in the works for quite some time. We are proud that this month it was finally completed and merged!

We announced PPTC rather recently so if you would like to read more about this new feature, we heartily recommend reading the article on either Patreon or our main blog at https://blog.ryujinx.org

HLE improvements:

· Kernel memory allocator bug

There was a bug in the kernel memory allocation that caused it to not be able to take all available memory into account. This caused some system calls to return an out of memory error, even when some memory was still available. The bug only affected a few games that use very specific system calls, and that performed a lot of heap allocation. The only game that is known to be affected is Super Smash Bros Ultimate. The fix allowed older versions of SSBU to finally get in-game. This bug was fixed by gdkchan.

· GPU syncpoints

Syncpoints (which is an abbreviation of synchronization points) are basically the method used to synchronize operations between the CPU and the GPU, or within the GPU. Conceptually, it is very simple: you assign to each operation an ever-incrementing number. Every time this operation completes, the GPU will increment the syncpoint value. Then, one can check if the operation completed by simply validating the current syncpoint value.

This support was implemented by Thog, and reduces glitches in many games, as GPU operations are now properly synchronized.

· Surface flinger rewrite

Surface flinger is the service responsible for image presentation. Essentially, it is the service that games use to present the final picture produced by the GPU to your monitor screen. It is also responsible for things like locking the frame rate (the game can pass a swap interval value that indicates the target frame rate), and can also do basic transforms with the final picture like flipping, scaling and more.

The previous implementation had several issues, including the lack of proper frame rate locking (which caused 30 fps games to run at up to double the speed), but the most noticeable issue was odd flickering on a small number of games, including Super Smash Bros Ultimate. This bug rendered the game unplayable, but thanks to Thog’s work, the issue is now fixed and these games no longer flicker.

Another game that suffered from the flickering issue was Taiko no Tatsujin. Now it runs much better, and can get in-game. However, it is not yet playable due to the lack of motion controls support.

· Updates and DLC

One notable feature that Ryujinx has lacked is support for game updates. XploitR implemented support for updates by using Libhac (a C# library that implements most of the Switch OS filesystem service functionality, maintained by Moosehunter, one of our contributors).

After that, mageven added support for game DLC, which includes additional contents to the game. Some games ship with built-in DLC, and as such require DLC support on the emulator to even boot. An example of such game is Dragon Marked For Death, where each character pack is a separate DLC. The first pack comes built into the game, while the second one is meant to be purchased separately.

On the image above, we can see Dragon Marked for Death in-game with the DLC support! It also suffers from the BGRA issue mentioned earlier.

· HID improvements

HID stands for Human Interface Device, and includes things like joycon controller emulation and other input methods (such as touch controls). Mageven fixed several problems with the HID implementation. One of these issues caused games to just hang forever due to one of the events never being signaled. This prevented games like Zelda Link's Awakening and Beyblade Burst Battle Zero from having functional input, rendering them unplayable.

Seen above is Beyblade now in-game with the HID fixes.

Another game with HID issues was Kirby Star Allies. It had a weird bug where Kirby would only walk to the left, regardless of the direction being applied by the controller. As it turns out, the game was reading information from something called DebugPad from memory. DebugPad is some kind of special controller used strictly during development which the game, for some reason, was trying to access. Making the necessary implementation changes to properly initialize HID resolved the issue, and as a result Kirby Star Allies is now playable!

A few other games had the same issue and are also now playable. One example of such a game is Sega Ages: Phantasy Star.

· NVIDIA driver GetStatus function

This function was required by a few games. Thanks to the partial implementation made by Ac_K, those games now go further, with some being fully playable. Examples of games that required it are Hyrule Warriors and Undertale.

On the image above, we can see Undertale working with the GetStatus implementation.

GUI improvements:

· Multiple controllers support

One thing that was long overdue was the support for full controller mapping on the UI, and support for multiple controllers (allowing "couch co-op"). Thanks to the work from Xploitr, this is now supported. Controllers can be mapped directly from the GUI, which means that the early days of manual configuration file editing are now a thing of the past.

The GUI allows configuring up to 8 controllers, which is the maximum that the Switch supports.

Game of the month (April):

A fun Nintendo Switch exclusive game that was released in April was Picross S4, aptly named due to being the 4th Picross S entry in the series. Picross S4 is a nonogram puzzle game in which the puzzle must be completed as quickly as possible.

The game is emulated very well in Ryujinx; the only noticeable issue it may encounter is a far-reaching and randomly occurring softlock that is currently under investigation by the dev team.

Game of the month (May):

The big release of the month was Xenoblade Chronicles: Definitive Edition, a remaster of a game originally released on the Nintendo Wii. We already talked earlier about issues that this game had on launch, and also mentioned other issues that would be discussed later. Now the time has come.

Initially, we are presented with this screen that renders really well. The first notable issue when starting a new game is that cutscenes are not rendered. This is caused due to the lack of NVDEC support, so video playback with hardware accelerated decoding doesn't work. The cutscene is split in two parts, and the second part is actually rendered in-engine. Luckily, we can skip all that and go directly to the gameplay.

Once in-game, we are presented with something that looks like the above screenshot. As you may have noticed, something seems off here. Those weird black lines all over the place are actually supposed to be grass, but it's not currently rendered properly. There are other graphical issues that can get better or worse depending on where you are, so it varies from slightly annoying bugs to jarring game stoppers. However, none of the bugs prevent the game from being played through!

Other areas without grass render graphics much more faithfully though, some of them being nearly flawless.

In the audio department, the game does well. We didn't notice any major audio issue or something that would negatively affect the enjoyment or that would make you want to mute it.

To sum it up, there are still some major graphical issues in some areas, but overall, XC:DE runs pretty well, especially considering that the game was only released a few weeks ago. More fixes to come!

Game of the month (June):

Burnout: Paradise Remastered a remake of the original Burnout: Paradise game from 2008, re-released on modern consoles and finally the Switch in June of this year.

This game has not been able to get past early menus in our official master build, but with a little work from mageven, a yet-unmerged implementation has allowed this title to finally go in-game. The FPS fluctuates wildly but it is able to be played through, with some patience.

As you can see, there are some visible issues with blur effects and framerate, but we will take a closer look at these items and hopefully get this game’s overall playability up to a satisfactory level soon.

Closing words, and what's next:

As always, we'd like to thank everyone contributing to make this project what it is today. Your continued support is important to help developers buy better hardware and other resources to work with, and also to cover server expenses. I would like to also especially thank everyone who has been supporting us with feedback, incentives, and testing. It means a lot to us :)

We should have some big things to show soon. A full audio rewrite (codenamed Amadeus) is in the works, and should fix many irritating audio related bugs in a number of games (like Animal Crossing). For now, we must draw the curtain; we’re looking forward to what’s next!