Written by GoldenX86 and CaptV0rt3x on February 10 2024
Welcome to 2024, yuz-ers! What better way to begin the year than to do major code refactors resulting in almost full applet support. We present this, and plenty more, to you today! Remember to right click and unmute the embedded videos.
Converting a single process emulator into a multiprocess one is no simple task.
2024 started out quite busy thanks to the combined efforts of byte[], german77, Blinkhawk, and Maide in implementing multiprocess support, taking advantage of it in multiple areas (heh, get it?) including GPU, input, services, and applet emulation, and fixing long standing problems along the way.
As of writing, multiprocess support is not yet merged, but fixes in the GPU, input, and other modules (implemented by byte[], Blinkhawk, and german77) have already been staged and released, allowing full support to be added in parts.
Implementing the requirements to support multiprocess in yuzu led us to make five significant changes in the past month:
We start off with a big one: Blinkhawk implemented device memory mapping emulation and rewrote the GPU implementation with support for the SMMU, or for desktop enthusiasts/Linux VM users/UEFI lurkers, its other common name, IOMMU.
The ARM System Memory Management Unit handles memory mapping for peripheral devices like the GPU.
It’s a hardware component on the Switch in charge of translating device virtual memory addresses into physical memory addresses.
The GPU adds an MMU of its own, GMMU
, an additional layer that maps over the SMMU.
The emulator already had a performant memory translation layer for the GMMU, but it could only handle a single program using the GPU at a time, unable to share it with other processes. And support for multiple processes was needed.
The main benefits of this rewrite are:
One downside of this change was how it increased debugging complexity, which led to more development time spent with every bug found on its implementation. For example, games on Android getting stuck at 0 FPS randomly, breaking compatibility with NCE, or running out of memory on some game engines. This led to a couple of fixes implemented first by byte[] and then Blinkhawk himself, with more on the way.
This change opened the floodgates to applet emulation and is the starting point to implement Direct Memory Import sometime in the future — but let’s slow down a bit, there’s more to cover.
Time to launch another program, GPU!
german77 had to adapt his input rewrite, Project Leviathan
to the requirements of multiprocess too. The rewrite is still ongoing, with more parts planned.
But just in January, the following changes, either specifically for multiprocess or more generally as part of the rewrite, were implemented:
While this leads to us being able to load the native controller applet (among others) and have fun with it, it doesn’t have much use for emulation.
Just for fun
Besides the emulated GPU, presentation to screen also needed some work to support running applets — without it, none of the benefits could actually be displayed. If there is no multi-layer composition in place, there is no applet fun.
byte[] rewrote almost all of the presentation code to support layer overlays and blending, taking special care to not break the existing filtering and antialiasing options. FSR in particular was converted from a compute shader to a fragment shader, so proper blending could be enabled. The end result is the same, with no image quality changes — but now FSR can be used while games display the native inline keyboard, for example.
That transparency behind the keyboard wasn’t free.
Another critical service that required a rewrite to have proper multiprocess support is AM
, the Applet Manager.
AM has now been almost completely refactored to track state for every applet individually, properly allowing it to support running more than one at the same time.
Help is only one button press away (Super Smash Bros. Ultimate)
While byte[] got the rewrite up and running, german77 fixed an issue
causing The Battle Cats Unite
to softlock past the starting loading screen.
Maide was responsible for making audio emulation compatible with multiprocess. Games should be able to share audio playback with applets, right? Sharing is caring.
Special menus included (Super Mario 3D All-Stars).
The serialization and deserialization of service calls from programs is one of the most important tasks yuzu must perform when interacting with guest programs. Communication between programs and the Switch system modules uses a special binary format with custom parsers. Interacting with guest processes required tedious and error-prone layout calculations for every single interface method yuzu needed to implement, wasting a lot of development time on error checking and maintenance.
With the increased involvement in service implementations and the exponential growth of complexity you’ve seen so far, byte[] aims to automate and simplify serialization by using a template-based approach that automatically generates the code needed for the method.
So far, the work on multiprocess has taken over twenty thousands lines of code and continues growing. All you have to do now to enjoy your native applets is to dump your firmware. The minimum required version to get the applets running is firmware 14.0.0.
Here’s a toast to Maide for fixing one of the longest standing bugs in yuzu: the passage of time in games like Pokémon Sword/Shield
and Pokémon Quest
.
In the past, while time tracked during saving, some game events like Dens or Pokéjobs wouldn’t reset, forcing users to manually advance time with the custom RTC option. It was quite bothersome.
It took an entire rewrite of the time services to resolve the issue, “only” about nine thousand lines of code. The new implementation is much more accurate, allowing Pokéjobs and other timed events to finally be enjoyed normally in this low-poly, almost-always-30-FPS masterpiece.
Get to work! (Pokémon Sword)
Continuing this work, Maide removed some old workarounds that were no longer needed in the time services, and fixed network clock to local clock
synchronisation on every game boot.
This fixed time progression in Pokémon Quest
.
No longer a Time Quest.
To close the section, byte[] fixed how the AOC service
lists available DLC for multi-program applications, allowing Assassin’s Creed Rogue
to boot with its DLC installed.
Just like the Navy intended.
Unforeseen issues are one of the signature “comes with the job” moments of emulation — you never know from where a new problem will arise, so we’ll have to start this section with a PSA.
PSA: If yuzu has recently started showing Microsoft as the GPU vendor for you, and you can no longer play any game, uninstall the package named OpenCL™, OpenGL®, and Vulkan® Compatibility Pack
, or if you prefer to keep it, go to Emulation > Configure… > Graphics > Device
and change the GPU to your correct model, without “Microsoft Direct3D 12” at the start of its name.
AMD and Intel users running Windows 11 suddenly started having their hardware completely incapable of launching any games while using Vulkan. The reason is something none of us expected at all, Microsoft… And Mesa! Please lower those pitchforks.
Microsoft decided to roll out an install of this package, which allows incapable hardware to run the mentioned APIs if no proper driver was provided from the hardware vendor, or just if the hardware is incapable of running it.
The project used to achieve this is Mesa Dozen
, which runs Vulkan atop a Direct3D 12 interface.
The intended purpose is to offer Vulkan support to devices that only ship a Direct3D 12 driver, for example, Qualcomm ARM laptops.
We don’t know why Microsoft decided to silently test this feature on x86-64 PCs that already ship hardware capable of proper Vulkan support, but here we are.
Those new devices generated by Dozen
are added to the Vulkan devices available to the OS, named “Microsoft Direct3D 12 (GPU model name)”, and conflict with how yuzu orders its device list.
To ensure the best GPU is selected by default on yuzu, three sorts are performed in order:
Did you notice it? The last point is the problem. Dozen
devices share the same identical features as the real Vulkan device but change the name.
Since the list is ordered in inverse alphabetical order, a device named “Microsoft” will take priority over an identical one named AMD or Intel.
The issue is simple enough to solve: detect when a device is Dozen
and demote it to the bottom of the list.
Even if Dozen
was capable of running yuzu, we would prefer not to run a layered implementation by default.
Sadly, Dozen
isn’t compatible with yuzu for the moment — it lacks multiple mandatory extensions and has some issues your writer enjoyed reporting to its devs while testing this.
Fixes for multiple of them arrived in just a couple of days. Mesa devs are built differently.
This could be an interesting experiment for Fermi users or other end-of-life hardware once Dozen
is suitable for yuzu.
The fun testing for multiprocess revealed a graphical issue when opening the web applet help page in Super Smash Bros. Ultimate
.
One fix for pitch linear reading and writing
in the software blitter code later, and Blinkhawk resolved the issue.
Da Rules (Super Smash Bros. Ultimate)
Android users have regularly reminded us that Mortal Kombat 11
is unable to boot.
After his enthusiastic walk through the code, byte[] found that 8-bit and 16-bit storage writes
in shaders were completely broken on hardware which did not support them.
The problem, at least one of them, was lack of hardware support for shaderInt8
and shaderInt16
, something the big three, NVIDIA (the Switch included, of course), AMD (and by extension, Xclipse), and Intel, have full support for with up-to-date drivers, but Android devices with Adreno and Mali GPUs don’t.
Mali moment #1, along with Adreno.
The solution byte[] implemented to solve this specific issue is the usual for the lack of hardware support. If you can’t run it, emulate it! Those are very enthusiastic walks. These platforms support storage atomics, so by performing a compare-and-swap loop to atomically (in the thread safety sense, not radioactive) write a value to a memory location, 8-bit and 16-bit values can be written to larger 32-bit memory words without tearing the value seen by other threads.
This emulation incurs a small performance loss, but beggars can’t be choosers. Mobile GPUs are very stingy with their feature sets, which frequently holds our development back and necessitates adding workarounds.
We doubt only Mortal Kombat 11
is affected — this change improved many unknown games that were crashing on Android devices or for people running outdated GPU drivers on desktop/laptop PCs.
Sadly, this change alone isn’t enough to make the game playable on Android devices.
This issue exposed other shader problems related to lack of support for StorageImageExtendedFormats
, but that’s homework for later, most likely for future byte[].
Switching to the other Linux kernel equipped OS (erm, Linux), Tuxusers reported garbled rendering issues when resizing the yuzu window while on Wayland.
The solution was thankfully simple, reverting an unnecessary change in one of the previous DMA fixes. By forcing a recreation of the swapchain each time the window frame size changes, the issue is gone.
Proper tear-free gameplay with safe window management shall return to Wayland. HDR support when, Linux?
Newcomer shinra-electric updated the MoltenVK dependency to its latest version. Thank you!
While the update brings tons of improvements and many Vulkan extensions are now supported, there are no new changes to report in rendering or compatibility on Apple devices. But hey, no reported regressions is good news!
t895 kicked off the new year with a flurry of changes to improve yuzu Android. While one of these changes enhances the overall app performance, the majority are quality-of-life (QoL) fixes that some of our users have been anticipating.
As many of you might already be aware, yuzu Android supports exporting user data and saves in ZIP format to transfer between different versions of the app. ZIP compression, in most cases, can result in a reduction of file size compared to the original size of files on disk. However, applying compression overtop of encrypted data is almost always a waste of time.
t895 observed that when compression was turned on, these ZIP exports were excessively slow, while still resulting in negligible size reduction gains, as the largest files in the user data are NCAs, and those are encrypted. Therefore, he disabled compression for these ZIP exports, exhibiting up to a 3x decrease in export times.
Moving on to the QoL fixes, t895 extended support for custom screen orientations. With this change, yuzu now supports a total of seven orientation styles, listed below.
Next up is the improved global save manager. There are two possible save directories for games, and the original global save manager was only checking one of them. So, t895 removed this broken feature a while back and has now reintroduced an improved version of the same.
With this improved version, you can now also use exports made with the global save manager in the per-game save manager and vice versa.
Following that are the new uninstall add-on buttons. t895 added an uninstall button for every kind of add-on in the Android app. yuzers can now easily uninstall any updates, DLCs, mods, and cheats that they might have installed. Note: Currently, yuzu on PC doesn’t have UI support for uninstalling mods or cheats.
Ever spend a long time copying over your dumps or installing content to NAND, only to have them fail to work?
Look no further: t895 brings the PC version’s integrity check features to Android.
You can now easily verify the file integrity of your game dumps and your NAND contents.
To verify a game dump, simply go to your game’s properties and under Info
, select Verify Integrity
.
There is also a separate, self-explanatory button within Settings
labelled Verify Installed Content
.
Great for peace of mind after experiencing a game crash
How many times have you accidentally opened the in-game menu when using the left thumbstick area? Well, you can now lock the in-game menu so as to avoid accidentally triggering it. When locked, you can still bring up the in-game menu by using the “back” button or gesture on your device.
Now, let’s delve into game shortcuts on your home screen. With Android’s dynamic shortcuts feature, apps can now provide users with quick access to specific actions or content within an app directly from the home screen. Although this feature was introduced back in 2016, it seems that some Android launchers do not yet support it.
While this feature is already supported on yuzu and works perfectly, it becomes pretty tedious when you have to launch each and every game to get a shortcut for it, especially after a reinstall. As a one-size-fits-all solution to this problem, t895 implemented a button in the game properties activity that allows you to easily add a shortcut to any game to your home screen without needing to launch the game first.
t895 followed that up with some controller focus optimizations. Android controller focus is the highlight you see over buttons indicating that you can select it. These changes fix a few issues observed when using a controller to navigate the yuzu app UI and solved an issue where the emulation surface would appear gray.
In his quest to bring feature parity between yuzu on PC and yuzu on Android, t895 implemented the ’encryption keys missing’ warning on Android. You will now get this warning on app startup if you don’t have the keys required to decrypt games/firmware.
t895 also implemented support for multi-program app switching.
This feature allows for game compilations like Super Mario 3D All-Stars
and Klonoa: Phantasy Reverie Series
to switch between games within the bundle.
Multi-game drifting! (Klonoa: Phantasy Reverie Series)
He also made some minor UI improvements like:
And that’s not all. Newcomer Emma implemented basic support for the game dashboard feature found on Pixel devices. Thank you!
Resident AMD tester Moonlacer noticed that Samsung mobile devices with the new RDNA-based Xclipse GPUs had the same wireframe issues in various Pokémon games,
that plague the PC AMD Vulkan drivers.
With some help from byte[], a fix for these Xclipse GPU drivers was implemented
by considering these devices as AMD, gaining access to the same old workarounds Radeon cards benefit from.
Thanks to user no.kola
on discord for testing these!
Xclipse moment #1. We have some bad news for Xclipse users we’ll discuss in the hardware section.
One notable standing issue with yuzu is profile corruption, when after a badly-timed crash, the emulator creates a new profile and leaves all user data in the old one, forcing the user to manually move their saves back to the newly created active profile. Thankfully, german77 fixes user profile corruption issues by only saving profile data when contents change.
While NCE has been with us for some time now, that doesn’t mean it’s entirely stable yet.
As an Android user pointed out, some hardcore mods like Luminescent Platinum
for Pokémon Brilliant Diamond/Shining Pearl
would get stuck in a black screen while using NCE.
After the detective work was finished by byte[], the reason was found to be in how some mods make assumptions about the module layout, and yuzu would try to give each module a dedicated patch section. To alleviate this bottleneck, GPUCode modified the NCE loader to try to use the same patch section for as many sequential modules as possible.
This should allow mods for other games that make assumptions about module layout to work under NCE as well.
Jumping to a bit of input changes, german77 was notified that a user tried to dump their Amiibos, but yuzu failed to generate any dump because the Amiibos were mounted as read-only and no backup was available. The solution? Dump Amiibos if no backup exists, no questions asked.
Resident helper anpilley decided it was time to improve the available command-line arguments for the yuzu binaries, adding the use of -u
to specify a user to load
and suppress the user selector from showing.
Thank you!
Back for more, FearlessTobi decides to tackle a few problems with the virtual file system emulation, or VFS
.
Since Project Gaia is in indefinite hiatus, priorities have shifted into patching as much of the current implementation as possible.
The list of changes is long: it includes moving files, unifying error code naming for ease of debugging, making file system definitions more consistent with current reverse engineering information available, and leaving the overall structure prepared for future code additions. Never hurts to improve an area that was designed back when there was little information available.
The boss of Dynarmic herself, merryhime, updated the bundled build in yuzu to the latest version, bringing some new changes and fixes with it. There are some instruction emulation optimizations, more 32-bit ARM instructions were added, and the startup times of games on Android was improved — it’s not as fast as NCE, but it’s considerably faster for those games that must run on JIT.
To close this section and move to an interesting hardware discussion, t895 has one last gift for us this month, per-game audio settings. One of the missing settings that could be set on a per-game basis, and it includes the full set, output engine, output device, input device, etc.
The more you’re able to choose, the better, right?
As promised last month, we’ll talk about frame generation, and the new tools available to take advantage of it in yuzu. But first, one last HDR example for NVIDIA users.
With the 551.XX series of drivers, NVIDIA introduced the option to auto-generate an HDR output for any video displayed on a Chromium-based browser (Google Chrome, Microsoft Edge, Brave, etc). It didn’t take long for the community to come up with plug-ins to take advantage of this change in local video players, but that’s not the only application outside NVIDIA’s official intended use.
Enter NvTrueHDR, an alternative to Windows AutoHDR and Special K HDR. Always fun to have more options to pick from!
Lossless Scaling, a program intended for resolution scaling, recently introduced a generic frame generation option, making it the first vendor agnostic implementation.
Simply set Frame Generation on the right to LSFG
. If you’re an Intel iGPU user, set Legacy capture API to enabled, open yuzu, enable Scale, and switch back to playing your game, or press the default hotkey Ctrl + Alt + S
while in-game. Exclusive fullscreen is recommended.
The results are good on smaller displays, but on larger monitors (such as 27 inch displays), the artifacts of the generated frames are too noticeable, making this tool more suitable for laptops and handhelds than for desktop or TV gameplay. Still, it’s a cheap way of improving perceived framerates and bypassing CPU bottlenecks on any GPU vendor without driver or hardware restrictions.
Below you can see comparison videos between native 30 FPS and Lossless Scaling generating frames to 60 FPS in The Legend of Zelda: Breath of the Wild
.
Due to YouTube only supporting 60FPS video, you won’t see the true 120 FPS framegen examples.
The above videos demonstrate native 30 FPS vs Lossless Scaling generating frames from a 30 FPS base. You can see with so little information, artifacts are common. Lossless Scaling doesn’t handle scene transitions.
The above videos demonstrate native 60 FPS vs Lossless Scaling generating frames from a 60 FPS base. With more information to play with, Lossless Scaling does a better job. Scene transitions are still an issue.
While the quality is not perfect, it’s a simple and harmless way of improving the experience on any hardware — especially on ugly 30 FPS games like the Pokémon series, or cinematic experiences like the Xenoblade saga. No double standards here.
Still, for those with recent AMD GPUs (RDNA2 and RDNA3 so far), there’s a better option available now:
Driver release 24.1.1 introduced the first public release of AFMF, AMD’s game-independent frame generation algorithm.
“But writer, AFMF is only for Direct3D 11 and 12 games!” you say. That’s where you’re wrong. You see, the Guru3D forums has some fantastic information, AFMF can be run on Vulkan, OpenGL, and Direct3D 9/10 too, it only needs a registry edit:
[HKEY_LOCAL_MACHINE\SOFTWARE\AMD\DVR]
"GFGEnableAPI"=dword:00000007
Manually make this change with regedit, reboot Windows if needed, add yuzu to the Radeon Software, set Wait for Vertical Refresh
to Disabled
, enable AMD Fluid Motion Frames:
In the performance tab, you can set the overlay to show the generated frames’ performance (it won’t show up on regular apps or yuzu, as it isn’t informed by the game engine), along with latency and stuttering.
Open yuzu, set Fullscreen Mode to Exclusive Fullscreen:
And that’s it, start a game, go into fullscreen by pressing F11 or the hotkey assigned to your controller, and enjoy 2x to 3x the perceived framerate.
Note that, while the image quality is much better than the result from Lossless Scaling, AMD disables AFMF if there is too much variance between one frame and the next in order to avoid smoothing out scene transitions like camera changes or opening the menu. This leads to a noticeable frametime inconsistency when a lot of action is happening on screen. We hope AMD adds an option in the future to toggle the sensitivity of this behaviour.
The above videos demonstrate native 30 FPS vs AFMF generating frames from a 30 FPS base. While a better result than Lossless Scaling at 30 FPS, artifacts are still noticeable in faster movements, especially on vegetation. Scene transitions are clear and there is less shimmering around the player.
The above videos demonstrate native 60 FPS vs AFMF generating frames from a 60 FPS base. And at 60 FPS, the results are great! Allowing for smoother gameplay on 120-180Hz displays.
No performance graphs are included because your writer doesn’t consider perceived framerate as real performance, but to provide an example, The Legend of Zelda: Tears of the Kingdom
, which produces solid 60 FPS in open world with a 5600X and an RTX 3060 Ti, can produce 170-180 “FPS” with AFMF enabled, and with little to no distortion visible.
The games can be rendered with an NVIDIA or Intel GPU while still generating frames with AFMF, although the experience is slightly worse than just using the AMD card directly due to the added latency of transmitting the finished frames over PCIe. The only requisite for AFMF to work is to have the display connected to the compatible AMD GPU, any other GPU can do the actual rendering after that. Time to invest in an RX 6400? Smash must look amazing at 240 FPS.
As promised, Intel fixed their crashes while building geometry shaders, starting with driver version 31.0.101.5186/5234.
While this allows for games like Xenoblade Chronicles 3
to finally get in-game on integrated GPUs and ARC dedicated cards, it seems like there are other areas where the driver needs to mature to produce proper rendering:
On the flip side, The Legend of Zelda: Tears of the Kingdom
improved stability with this driver fix, so Intel Windows specific rendering issues aside, the game should be quite playable now.
K11MCH1’s driver releases continue to flow out, improving performance and compatibility for Adreno users. We strongly recommend staying up-to-date.
While there have been new releases of the proprietary driver, nothing of value has been added or fixed yet.
Total Adreno moments count this month: 1.
Why together? Because we found some interesting limitations in the Exynos hardware that reminds us of the existential crisis Mali suffers. Besides the AMD specific issue we previously mentioned, Exynos’ Xclipse GPU series shares a quality with Mali: total lack of support for BC4 to BC7 texture decoding.
While this is fine for native Android games (developers just have to scratch their head at the decision to skip basic texture support, and use an alternative like ASTC), Switch games do use BCn textures, extensively in some cases, and adding the extra CPU work of having to decode those textures into something the GPU can handle (RGBA8) will limit performance and increase memory usage. This is one of the main reasons these GPUs are not on par with Adreno in terms of feature support.
So:
Total Xclipse moments count this month: 2.
Total Mali moments count this month: 2.
Certain distributions like SteamOS, Fedora since version 39, and any distro with a linux-zen package available (Arch Linux for example), have significantly increased their default vm.max_map_count
values, leading to much more stable out-of-box experiences when running Unreal engine games on yuzu.
Progress feels so good! You could learn a little, Windows.
Work on multiprocess support is far from over. We’re aiming to support QLaunch
, meaning being able to boot the native game launcher, launch games from there, close them, suspend them, launch a different game, the whole deal.
QLaunching in 3, 2, 1!
Resuming a game works too.
Back and forth.
The work on applets and multiprocess is exposing a lot of hidden bugs in multiple areas — the accuracy improvements are a very welcome addition; we’re having so much fun testing and running the applets.
That’s all folks! Thank you for reaching the end of this progress report. We hope to see you next time!
Advertisement
Advertisement