Repository navigation
Releases
Eglantine smileytatsu/dev-rebased build 20 (864ab41)
Automatic build of smileytatsu/dev-rebased at 864ab41.
Texture cache memory limit
The texture cache used to start evicting at a fixed 5 GiB on every GPU, so a card with more memory than that evicted and decoded again textures that would have fit in it. The cap is now a setting that follows the GPU. This build also carries the changes of the previous one.
What changed
- New setting: Adv. Graphics > Texture Cache Memory Limit (in MiB, also available per game in Properties). Auto (0, the default) uses three quarters of the device's memory budget and follows the driver when the budget changes while a game runs. An explicit value is clamped between 1 GiB and the device's memory.
- The settings page knows the GPU. The maximum is the selected GPU's memory and changes with the device or backend selection. Auto shows the value it resolves to, and a value under the recommendation shows a warning that more textures will be evicted and decoded again, which can stutter. The log carries the same warning at boot.
- Starting thresholds come from the device budget. The collector's thresholds, for Switch 1 and Switch 2 titles alike, are now derived from the driver's memory budget instead of the Conservative VRAM mode figure.
- Safety margins are unchanged. The budget margins, the out-of-memory back-off and the block-slack reserve still apply under the limit, so a limit close to the GPU's memory is never reached.
What it affects
- Every title, on every GPU with a memory budget. Integrated GPUs keep their existing share of system memory.
- Video memory use is higher than before, up to the limit. If you run other GPU-heavy programs next to the emulator, lower the limit.
- A title that streams more texture data than fits still evicts; the change only stops it from doing so earlier than the GPU requires.
Risks
- If the driver's budget shrinks because another program takes video memory, the limit follows it down, but a small margin of garbage or missing textures is possible until the collector catches up. Please report it with the log.
- The effect on frame times has been measured only as the absence of memory pressure in long runs (no out-of-memory events, unbacked images or device loss), not against the old cap on the same route.
Switches
EDEN_NX2_TC_EXPECTED_MIBandEDEN_NX2_TC_CRITICAL_MIBoverride the collector's thresholds and win over the setting.EDEN_NX2_TC_LOG=1logs the cache's device memory against its thresholds every 600 frames (Texture cache: device memorylines).
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 18 (2ff2871)
Automatic build of smileytatsu/dev-rebased at 2ff2871.
Mario Kart World: photo mode in docked mode
In Mario Kart World 1.8.0, photo mode in docked mode showed a black screen with only the UI buttons. Handheld mode was fine. This build fixes it.
What was wrong
Docked, the photo mode renders at 2560x1440 and upscales to 3840x2160 with a network of tensor-core passes. Eglantine cannot run those passes, so the 4K image was never written and only the UI drawn over it showed. Handheld does not use the network, which is why it worked. Eglantine already had a stand-in for such passes (a plain blit of their input to their output), but it only looked at a few fixed places in the pass's constant buffer and, for this game, found nothing useful there.
What changed
- Photo mode shows the scene again in docked mode. After the first rejected pass, the next dispatches are searched for a pass that has a colour image and one 1.5 times its size in its constant buffers, and its result is replaced by a bilinear blit of the first to the second. The pass and the places of the two handles are remembered, so later frames read only those two. The picture is a plain upscale, not the game's network.
- The old fallback no longer blits look-up tables. Its generic search ignores output images under 1024 texels wide, so it stops copying unrelated small textures.
- Titles the old fallback already handled are unchanged. It runs first; the new search only starts when it did not handle the pass, and it stops after a few attempts without a match, so other games do not pay for it.
Handheld mode and games that never hit the tensor-core rejection do not run any of the new code.
Risks
- It looks for an exact 1.5x pair of colour images. If a future game update changes the photo mode's sizes, the stand-in finds nothing and photo mode goes back to the black screen.
- A game whose passes happen to expose a matching pair that is not the upscale could get a wrong blit. It cannot crash, and it can be turned off (below).
- The last two small changes (the search window closing after a few tries, and the old fallback running first) were compiled but not played again after the first working test.
Switch
EDEN_NX2_PHOTO_UPSCALE=0 in nx2_switches.txt turns the stand-in off.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 17 (28b674c)
ASTC textures: cheaper decode and upload
On GPUs that cannot sample ASTC textures themselves (all desktop NVIDIA and AMD cards), Switch 2 ASTC textures are decoded on the GPU, re-compressed to BC and uploaded every time a new texture streams in. This build makes that path cheaper. GPUs with native ASTC (most mobile GPUs, Apple through MoltenVK) skip this path and are not affected.
What changed
- Decode and re-compress in one submit. The decode and the BC encode used to be two GPU submits with an idle gap between them. They are recorded as one now, which removes the gap.
- Temporary decode images are reused much more. Each upload needs a temporary RGBA8 image. Creating one is the single most expensive step of the upload on the CPU side, so the pool now:
- hands a finished image back as soon as a texture asks for one, instead of once per frame;
- when the pool is full, evicts the image used longest ago instead of throwing away the one that just finished;
- lets an image up to twice the texture's size (same mip and layer count) serve a smaller texture, and rounds new images up to a multiple of 64 texels so near sizes share one.
- Faster ASTC decoder shader. The per-block work is computed once per block instead of once per texel, and the colour range search is a bisection. The output is bit-identical to the old decoder: it was compared on a GPU against the old shader on millions of random blocks of every footprint. In a micro-benchmark the decode is 1 to 5% faster.
- Opacity scan reads the guest data in place instead of copying it first (it is copied only when the range is split).
Results
Measured with temporary timing logs (not part of the release), in Mario Kart World, on the same route before and after. These are single runs per build, so treat them as a direction, not a precise figure.
| GTX 1650 (4 GB, no native ASTC) | RTX 5060 Ti (16 GB, no native ASTC) | |
|---|---|---|
| CPU time of ASTC uploads, share of the GPU thread | 9.6% → 4.6% | 2.9% → 1.0% |
| Time to record one upload | 689 µs → 159 µs | 110 µs → 50 µs |
| GPU idle between decode and encode | 6.4% → 0% | 2.5% → 0% |
| Decode images reused | about 40% → 72% | 73% |
| Frames over 100 ms (per 1000 presents) | 29 → 9.5 | 2.1 → 0.4 |
| Longest frame in steady state | 4.1 s → 2.4 s | 0.44 s → 0.17 s |
What to expect:
- Weaker GPUs and CPUs gain the most. On the GTX 1650 the ASTC upload work was a visible part of the GPU thread's time and the long hitches while textures stream in (the start of a lap, a new area) became less frequent and shorter. Run-to-run variation is large on that card: runs of nearly the same code gave anywhere from 5 to 10 frames over 100 ms per 1000 presents.
- Capable GPUs gain little. On the RTX 5060 Ti ASTC was only about 3% of the GPU thread to begin with, so the frame rate does not change measurably. The gain there is the same kind, just small.
- The 4 GB card's biggest remaining cost is creating the game's own textures under video memory pressure, which this build does not touch.
Risks
- More video memory in some cases. A larger image serving a smaller texture, and rounding new images up to a multiple of 64 texels, mean a temporary decode image can be bigger than the texture it holds. The pool of idle images is still capped at 256 MiB, as before; images the GPU is still using are not capped, as before, but can now be a little larger each. Total video memory was not measured. If a 4 GB card runs out of memory sooner, turn off
EDEN_NX2_ASTC_POOL_FITandEDEN_NX2_ASTC_SCRATCH_BUCKETfirst. - Wrong textures, if the ordering were ever wrong. Recording the decode and the encode in one submit changes when the GPU sees the work. The decode image is only read by the encode, which the decode's closing barrier already orders, and no corrupted textures were reported in testing, but this can't be proven for every driver. If you see wrong colours, garbage or blocky edges on ASTC textures, first set
EDEN_NX2_ASTC_ONE_SUBMIT=0, then the other switches below one by one, and report which one fixes it.
Switches (nx2_switches.txt)
All are on by default. Set a switch to 0 to go back to the old behaviour.
| Switch | Turns off |
|---|---|
EDEN_NX2_ASTC_ONE_SUBMIT=0 |
The single submit for decode and encode |
EDEN_NX2_ASTC_SCRATCH_BUCKET=0 |
Rounding decode images up to a multiple of 64 texels |
EDEN_NX2_ASTC_POOL_V2=0 |
Recycling when a texture asks for an image, and evicting the oldest |
EDEN_NX2_ASTC_POOL_FIT=0 |
Serving a texture with a larger image |
Details are in the README.
Automatic build of smileytatsu/dev-rebased at 28b674c.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 16 (22d6be2)
What changed
Mario Kart World's in-game 30 FPS mode now follows the game instead of the pacer.
The game picks a 1- or 2-vblank frame mode from a frame time that already includes the interval it asked for, so a frame held for two vblanks kept reading as too slow and it stayed at 30 FPS for good. The dynamic mode that avoids this was already in the tree but never ran: PaceToVblank recognised the title through the current process, and a present that arrives from a service context has no current game process, so the program id never matched. It now asks for the application process, and the recommended settings for the title switch the mode on.
- Guarded on the loader patch: a title whose instruction sequence does not match is left unchanged, and no other title is affected.
- Takes effect after restarting the game. It can also be switched on per game as Mario Kart World: dynamic FPS.
- It removes the artificial hold, not the frame time: the game still only picks one vblank when a frame fits in one.
README: the engine table lists the change, and a new Ideas section records what is worth doing next (pacer clock, present queue, emulated refresh rate, two frames ahead, texture cache cap, submission batching, range uploads, a host GPU capture, the draw path). The per-image upload idea is replaced by a per-layer one, after a temporary tally showed that no large texture is rewritten every frame: the only images uploaded every frame were the small planes the video decoder writes.
Commits since build-15
0cd801d8nx2: apply Mario Kart World's dynamic frame rate398af04eREADME: list the Mario Kart World pacing change and the ideas22d6be2cREADME: the per-image upload tally found no large texture rewritten every frame
Automatic build of smileytatsu/dev-rebased at 22d6be2.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 15 (662ed6f)
Automatic build of smileytatsu/dev-rebased at 662ed6f.
What changed in this build
This build is the same as build 13 (upstream build-194, 09e539a65c, plus this fork's changes) with one more commit: a revert of upstream b547bda625 ("texture_cache: finish between chunked uploads so staging memory is reused"). The README lists it.
Why: an AMD user got VK_ERROR_DEVICE_LOST (an AMD "driver timeout" popup) on the loading screen of Mario Kart World, about 20 s after the game started loading. It happens on upstream build-194 too. I bisected it on upstream, one build at a time, with the same settings each time:
- Builds up to
93821e84c7andcca4548805: start fine. cca4548805plus073b877965(large 2D images uploaded in 32 MiB chunks): starts fine.- The same plus
b547bda625:VK_ERROR_DEVICE_LOSTat 26 s.
That commit adds a runtime.Finish() (submit and wait for the GPU) between the chunks of a large image upload. I do not know why that wait makes AMD's driver time out; that is a guess, not something I measured. The tester also said that a build with only that commit reverted starts fine; I did not read that log. Each build was run once.
What reverting it costs: the commit wanted the staging memory of a large image (64 MiB and up) to be reused between chunks. Without the wait, the staging buffers of all the chunks stay alive until the next scheduler flush, so a 600 MiB image accumulates its full staging size again. I did not measure how much memory that is in practice.
Tested on:
- GPU: AMD Radeon RX 9070 XT, AMD proprietary driver 2.0.416
- Game: Mario Kart World (title ID
0400C3F00006E000), Windows - Linux (RADV), NVIDIA and other AMD GPUs were not tested with this change.
The binaries below were built by CI; I did not run them. I only compiled vk_texture_cache.cpp on Windows after the revert. The upstream commit is not reported there yet.
The other changes of this fork are listed in the README.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 13 (1d95ef5)
Automatic build of smileytatsu/dev-rebased at 1d95ef5.
What changed in this build
This build is upstream nx2 at 09e539a65c plus the changes of this fork: 10 commits, listed in the README. Upstream has no tag for that commit yet. The last upstream tag in it is build-189 (7adcecc6d2), and nx2 has 103 commits after it, so this build contains 121 upstream commits that build 12 does not (76 without merges). Among them: DLSS through the game's own network, the NUP editor, and several texture cache, buffer cache and DMA pusher changes.
Differences from build 12 in this fork:
- The texture cache descriptor ids commit is gone. Upstream has the same change now (
863730d82e), so this fork uses theirs. The README lists it under "Changes already in upstream", together with the AMD revert. - Everything else of this fork is the same: Switch 2 pipelines kept built, the mesh guard, releasing the guest RAM when a Switch 2 game stops, and the CI change (Linux and Windows only, PGO kept).
Upstream's Linux build was broken on a few recent nx2 commits (an unused variable that GCC turns into an error); 09e539a65c fixed it and this build includes the fix.
Measurements of RAM or performance taken on build 12 or earlier do not compare with this build, because upstream changed a lot in between. I only compiled the files this fork touches on Windows; I have not run these binaries.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 8 (4851038)
Automatic build of smileytatsu/dev-rebased at 4851038.
What changed in this build
This build is rebased onto the latest upstream nx2 (46967a1b84, upstream tag build-177). Upstream changes now included:
- Cheaper per-draw descriptor reads and fewer debug-log calls in the texture cache (Djihads80#374).
- Fewer render pass splits on tiled GPUs, and failed GPU waits are now logged (Djihads80#361).
- Fix for a launch crash on some Intel CPUs (i5-9400F) caused by the measured TSC clock (Djihads80#373).
- Switch 2 programs inside NSP containers are now detected (Djihads80#349). This also means they get this fork's guest RAM release on stop.
--helpand--versionexit successfully in the CLI; Arch Linux package files and CONTRIBUTING updates.
On top of that, this fork keeps its own changes (texture cache descriptor ids, Switch 2 pipelines kept built, no task/mesh pipelines without VK_EXT_mesh_shader, guest RAM release on stop). They are listed in the README, together with the known issues. Nothing of this was measured again after the rebase: the upstream changes and ours were only checked to compile, not tested in a game.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eden's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 6 (9e8da0e)
Automatic build of smileytatsu/dev-rebased at 9e8da0e.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eden's profile); prefer them when your CPU supports it.
What's in this build
Three changes on top of nx2 (68a945d): one fixes shader stutter in Switch 2 titles, one trims CPU work on every draw call, and one avoids a crash on GPUs without mesh shader support.
1. Switch 2 titles: cached shaders stay built (vk_pipeline_cache)
The problem. Eglantine only built the pipelines the last two sessions used when a game booted, and it destroyed any pipeline left unused for about 5 minutes of play (9000 frames). When the game needed one of those again, the shader was translated and compiled again on the GPU thread in the middle of the game. That is the stutter and the skipped draws you could see.
The change. For Switch 2 programs only:
- Every pipeline in the disk cache is built at boot.
- Pipelines are no longer evicted during play.
Switch 1 games take the same code path as before.
What you should notice
- Fewer shaders built mid-game and fewer skipped draws. In my test of one Switch 2 title (RTX 5060 Ti, Ryzen 7 5700X, warm driver cache):
- Runtime pipeline builds: 756 in build 131's first ~6 minutes, 51 in this build's ~4.6 minute run.
- Time spent on the GPU thread building them: 2.2 s, down to 0.11 s.
- Different runs and different caches, so read these as a trend, not a benchmark.
- The first load takes a little longer because more is built up front. About 2.7 s for ~4,600 pipelines on that machine. A cold driver cache (after a driver update) takes longer.
- Brand-new shaders the game has never used before are still built the first time they appear.
Memory. Peak system RAM while emulating was the same as build 131 on that title (about 26 GB total used, 25.9 and 26.0 GB against 26.0 GB). There is no cap on how many pipelines stay built, so a cache that keeps growing across many builds keeps all of them. On a PC with 16 GB of RAM or less, watch memory use.
EDEN_NX2_PRELOAD_ALL_PIPELINES=1 still builds everything at boot for any game, as before.
2. Texture cache: IDs kept next to the descriptors (texture_cache)
The problem. For every draw and every texture or sampler bound, the texture cache looked the ID up in a hash map.
The change. The ID is now stored next to its descriptor, so a lookup is an array read. It uses the same validity rule as before, and it removes a map lookup that was not checked for a missing entry. It also returns early from a debug trace when tracing is off.
What you should notice
- A small drop in CPU time per draw on the GPU thread. I estimate 2 to 4% of that thread's time but did not measure it against a baseline.
- About 2 MB more RAM per descriptor table.
- This affects every game, not just Switch 2.
3. No task/mesh pipelines without VK_EXT_mesh_shader (vk_pipeline_cache)
The rasterizer already skipped task/mesh draws on devices without the extension, but only after the pipeline had been translated and handed to the driver. On such devices (RADV on Vega) the pipeline build workers crashed. No pipeline is returned now, so the draw is skipped as before. I have not tested this on that hardware.
Testing
Mario Kart World (Switch 2), Vulkan backend, on these devices:
| Device | OS | Result |
|---|---|---|
| Ryzen 7 5700X, 32 GB RAM, GeForce RTX 5060 Ti 16 GB (driver 610.88) | Windows 11 25H2 | 29-minute runs against build-131, repeated start and stop of the game. Numbers above. |
| Core i5-9400F, 32 GB RAM, Radeon RX 6600 XT 8 GB (AMD driver 2.0.353) | Windows 11 26H2 | One run hit an out-of-VRAM crash after about 6 minutes (VK_ERROR_OUT_OF_DEVICE_MEMORY). Build-135, without these changes, ran 3 laps without a crash. Treated as a one-off. |
| Ryzen 5 5600GT with Radeon Vega graphics (Renoir) | Linux (Bazzite), Mesa RADV 26.2.4, 4 GiB of video memory | The device where the task/mesh pipeline crash (change 3) was reported. |
The measurements and crash reports above were taken on build 3 (the same three changes on nx2 6221409). This build is rebased on nx2 68a945d and was not re-measured.
Not tested: Switch 1 games, Intel GPUs, macOS.
Eglantine smileytatsu/dev-rebased build 12 (96bdff6)
Automatic build of smileytatsu/dev-rebased at 96bdff6.
What changed in this build
This build is upstream build-187 (14d4c4ee66) plus the changes of this fork: 10 commits, listed in the README. Nothing from upstream after build-187 is in it.
- Compared with build 11, the base moved from upstream
build-177tobuild-187(31 commits). - Upstream
build-187already has the revert of46d1554186(62f2984b89, PR Djihads80#458), so this fork no longer carries its own revert for the AMD black textures. I did not test this build on AMD. - The CI binaries below were not run by me. I only compiled the files this fork touches on Windows.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eglantine's profile); prefer them when your CPU supports it.
Eglantine smileytatsu/dev-rebased build 11 (253108e)
Automatic build of smileytatsu/dev-rebased at 253108e.
What changed in this build
This build reverts upstream commit 46d1554186 ("vulkan: back a sparse tiled image whole when its tiles can't be set up"). The rest is the same as build 8, plus a README row for the revert.
Why: AMD users reported black textures in Mario Kart World, visible from the menu on. They were in build 8 and in upstream build-177 too. I bisected it on upstream, one build at a time, with the same settings each time and a single tester:
427b9abfdc: no black textures.46d1554186: black textures.155bf34fc2(the middle of the range) with only46d1554186reverted: no black textures.- This fork's base with the revert: no black textures.
I do not know why that commit causes it. Reading the diff, its new code only runs when a sparse tile setup fails, and that never happened in any of the test logs.
Warning: possible crash or GPU hang on AMD. That commit was written to avoid a specific problem: when the tiles of a sparse image cannot be set up, AMD drivers cannot sample the image, and the commit backs it with normal memory instead. With the revert, that case goes back to the old behaviour, which the commit message describes as a hang. I did not measure it. In my test logs the case never came up (backing it whole appears 0 times) and nothing crashed, but other games, other AMD GPUs and other drivers were not tested. If you see a crash or a GPU hang on AMD with this build, please report it with the log.
Tested on:
- GPU: AMD Radeon RX 9070, AMD proprietary driver 2.0.416
- CPU: AMD Ryzen 7 7800X3D, 31 GiB RAM
- OS: Windows 11 25H2
- Game: Mario Kart World (title ID
0400C3F00006E000), with ASTC recompression set to Uncompressed - Linux (RADV) and NVIDIA were not tested with this change. Windows only.
The test used a local build of the same code (5c089dcddb). The binaries below were built by CI at 253108ebe0, which only adds the README row; I have not run them.
The other changes of this fork are listed in the README, together with the known issues.
Linux
Linux packages come as an AppImage (self-contained, needs glibc 2.39 or newer: Ubuntu 24.04, Fedora 40, Debian 13, Arch) and a tar.gz (uses your system libraries, so Qt 6 and the usual libraries must be installed).
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 | AppImage · tar.gz | AppImage · tar.gz | Make the AppImage executable (chmod +x) and run it |
| ARM (aarch64) | AppImage · tar.gz | AppImage · tar.gz |
Windows
Windows packages are in-place zip files: extract and run eglantine.exe, or eden-cli.exe from a terminal.
| Build Type | Standard | PGO (Recommended) | Notes |
|---|---|---|---|
| amd64 / x86_64 (MSVC) | MSVC zip | Use if you run into graphical issues on other builds | |
| amd64 / x86_64 (MinGW) | PGO zip | Built with MinGW clang; bundles its own DLLs, no Visual C++ redistributable needed |
The PGO builds are the same programs compiled with profile-guided optimization (clang plus Eden's profile); prefer them when your CPU supports it.