Repository navigation
Eglantine smileytatsu/dev-rebased build 17 (28b674c)
Pre-releaseASTC 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.