<feed xmlns='http://www.w3.org/2005/Atom'>
<title>eglantine-cirakg/src/video_core/texture_cache/texture_cache.h, branch nx2</title>
<subtitle>Mirror of github.com/cira0100/Eglantine-public nx2, a fork of Djihads80/Eglantine.</subtitle>
<id>https://git.cirakg.xyz/eglantine-cirakg/atom?h=nx2</id>
<link rel='self' href='https://git.cirakg.xyz/eglantine-cirakg/atom?h=nx2'/>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/'/>
<updated>2026-11-03T17:33:16+00:00</updated>
<entry>
<title>video_core: NVIDIA DLSS through NVIDIA Streamline in place of a game's DLSS</title>
<updated>2026-11-03T17:33:16+00:00</updated>
<author>
<name>Duck912</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-03T17:13:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=63e87a22c60394bc4f427ee5f8d6ddbce7b0ac7f'/>
<id>urn:sha1:63e87a22c60394bc4f427ee5f8d6ddbce7b0ac7f</id>
<content type='text'>
Adds a Graphics setting, "Use NVIDIA DLSS in place of a game's DLSS" (nvidia_dlss, off by
default). When it is on, in Windows builds configured with EGLANTINE_STREAMLINE_SDK, the
evaluation Eglantine already replaces with FSR 3.1 goes to NVIDIA DLSS on GeForce RTX cards, with
the same inputs (colour, depth, motion vectors, jitter). When DLSS can't run, FSR 3.1 runs as
before.

Only Streamline's MIT-licensed headers are compiled in; nothing of NVIDIA's is linked or shipped.
At run time Eglantine looks for sl.interposer.dll in the user folder's "streamline" folder (or
EDEN_STREAMLINE_DIR, or "streamline" next to the executable), checks its Streamline signature and
starts Streamline with manual hooking. Streamline's plugins come from that folder or the NVIDIA
app's downloads. DLSS itself is nvngx_dlss.dll in the same folder, else the newest DLSS 310 or
later that the NVIDIA app has downloaded, checked for NVIDIA's Authenticode signature and copied
as streamline/nvidia-app/nvngx_dlss.dll. Like other tools that call DLSS outside a game, it uses
its own fixed project id with the custom engine type.

- Preset K for all modes (EDEN_NX2_DLSS_PRESET overrides it): the default Performance model (M)
  and L draw thin dark horizontal lines in some frames at 2x resolution scale; K doesn't.
- HDR input with auto exposure; the mode follows the render/output ratio.
- Buffer device address stays enabled when DLSS needs it, for DLSS only.
- The upscaler waits for the device instead of submitting when it is destroyed: by then the
  game's channels are released, and a submit read the state tracker's stale flags (a crash when
  stopping a game).

With the setting off, or in builds without the SDK path (the setting is hidden there), nothing
changes.

Testing: Windows 11, RTX 5080, Fire Emblem: Fortune's Weave docked at 1x (720p -&gt; 1440p) and 2x
(1440p -&gt; 2880p), CLI runs and GUI play, stopping and restarting games with DLSS on. Not tested on
other GPUs or games.

Assisted-by: Claude Opus 5.5 (implementation, debugging)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;
</content>
</entry>
<entry>
<title>video_core: cut per-draw work on the GPU back thread in crowded scenes (#374)</title>
<updated>2026-11-03T07:47:54+00:00</updated>
<author>
<name>Duck</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-03T07:47:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=a667551cdf6e9044e43e1d0c37320c3ec82a1213'/>
<id>urn:sha1:a667551cdf6e9044e43e1d0c37320c3ec82a1213</id>
<content type='text'>
* video_core: demote the texture cache's per-draw debug logs to trace

The invalid sampler and image view index messages fire for unused
binding slots on every draw. Filtered LOG_DEBUG messages still cost a
call and argument packing: in a Fire Emblem: Fortune's Weave city scene
(about 2,100 draws per frame) they were 3.1% of the GPUBack thread's
samples. LOG_TRACE compiles them out of release builds.

Assisted-by: Claude Opus 5.5 (profiling, porting and drafting)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;

* texture_cache: read a descriptor with one page lookup

DescriptorTable::Read runs for every texture and sampler of every draw,
and it read each 32-byte TIC/TSC entry through the generic
ReadBlockUnsafe page walk. In a Fire Emblem: Fortune's Weave city scene
(about 2,100 draws per frame) that was 5.0% of the GPUBack thread's
samples. An entry within one page is contiguous in host memory, so it
is now a single page lookup and memcpy. Entries that cross a page and
pages without host memory still take the block read, so unmapped and
unbacked entries still read as zero.

The same change in another Eden-based build cut these reads from 6.4%
to 0.4% of its GPU thread.

Assisted-by: Claude Opus 5.5 (profiling, porting and drafting)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;

---------

Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;</content>
</entry>
<entry>
<title>Merge remote-tracking branch 'origin/nx2' into fe-fsr31</title>
<updated>2026-11-02T23:56:59+00:00</updated>
<author>
<name>Duck912</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-02T23:56:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=9acd36eb9a291e0631346f5b17d69d0e8eb26cc5'/>
<id>urn:sha1:9acd36eb9a291e0631346f5b17d69d0e8eb26cc5</id>
<content type='text'>
# Conflicts:
#	src/video_core/renderer_vulkan/blit_image.cpp
#	src/video_core/renderer_vulkan/blit_image.h
</content>
</entry>
<entry>
<title>video_core: replace Fortune's Weave's DLSS with AMD FSR 3.1</title>
<updated>2026-11-02T21:28:01+00:00</updated>
<author>
<name>Duck912</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-02T21:12:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=11cebf56014a5015db28179a8acc81cad0caf641'/>
<id>urn:sha1:11cebf56014a5015db28179a8acc81cad0caf641</id>
<content type='text'>
Fire Emblem: Fortune's Weave's DLSS network can't run here, and the
temporal stand-in is only an approximation of it. FSR 3.1 takes the
same inputs DLSS does: the jittered colour, motion vectors, the jitter
and the depth, which the game's first DLSS pass reads through
cbuf0+0x298 (Z32, reversed, the colour's size). Kepler compute keeps it
next to the motion vectors.

Fsr3Upscaler ports the host side of the SDK's ffx_fsr3upscaler.cpp: the
eight passes (prepare inputs, luma and shading-change pyramids, shading
change, reactivity, luma instability, accumulate, RCAS), the internal
images and the constants, recorded through the scheduler with the
shaders from externals/FidelityFX-SDK. It takes HDR colour, render-size
motion vectors and reversed depth, computes its own exposure, and uses
the no-wave SPD variants on devices without compute quad operations.
The SDK's GLSL uses separate textures and samplers, so DescriptorBankInfo
gains sampled image and sampler counts (default 0). FSR's RCAS follows
the RCAS Sharpness slider. The result goes to FSR's own RGBA16F image
and is drawn into the game's output, which keeps its format.

TextureCacheRuntime::TemporalUpscale runs FSR 3.1 first. Without the
depth, at mismatched scales, on a device lacking FSR's formats or
features, or if its pipelines fail to build, the stand-in runs instead,
and the bilinear blit stays last. EDEN_NX2_DLSS_REPLACEMENT=standin
forces the stand-in. A gap of more than 250 ms between evaluations
restarts the history.

The BlitColor overload that takes a raw image view transitions its
source to SHADER_READ_ONLY_OPTIMAL but described it as GENERAL in the
descriptor (a validation error); it now describes the layout it uses.

Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;
</content>
</entry>
<entry>
<title>video_core: sharpen the temporal DLSS stand-in</title>
<updated>2026-11-02T21:28:01+00:00</updated>
<author>
<name>Duck912</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-02T21:07:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=960ebcc73d998c7c596c3377b0ec8a1d6eefccf1'/>
<id>urn:sha1:960ebcc73d998c7c596c3377b0ec8a1d6eefccf1</id>
<content type='text'>
Fire Emblem: Fortune's Weave's DLSS input matches Eden's (same 720p
image, same detail), but the stand-in's 1440p output was blurrier than a
plain bilinear 2x of it (Laplacian 0.0066 vs 0.0081; Eden's real DLSS
0.0111), and the image drifted darker over time:

- the sample kernel was about twice too wide for the output resolution;
- the history was kept in the output's B10G11R11 format, whose 5-6 bit
  mantissas round away a frame's 0.03-0.1 share;
- the 1-sigma neighbourhood clip removed detail that only some jitter
  positions sample (railings, thin edges).

The history is now an RGBA16F pair the shader writes as a storage image,
with no per-frame copy. Still pixels use a third of the kernel width and
a 1.5-sigma clip, so detail from many jitter positions accumulates.
Moving pixels keep the old kernel and 1-sigma clip, and so do pixels
that moved recently or whose history falls far outside the
neighbourhood (content that changes without motion vectors), remembered
in the history's alpha. Static output goes from 0.0066 to 0.0102 with
no brightness drift and no new ghosting.

With resolution scaling the stand-in used to fall back to a bilinear
blit. The images are now scaled up as BlitImage does, the jitter is
scaled to host pixels and the history follows the framebuffer's render
area.

RCAS (temporal_sharpen.frag) sharpens a copy of each result, never the
history, in range-compressed space since the output is HDR. Its strength
is the sharpness slider, relabelled "RCAS Sharpness" (0% turns it off).
EDEN_NX2_TEMPORAL_KERNEL, _CLIP, _KERNEL_MOTION, _CLIP_MOTION and
_WEIGHT tune the filter (all four filter values at 1 give the old one),
and EDEN_NX2_TEMPORAL_SHARPEN=&lt;stops&gt;|off overrides the slider.

Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;
</content>
</entry>
<entry>
<title>video_core: read texture handles as header offsets only on Switch 2</title>
<updated>2026-11-02T19:53:47+00:00</updated>
<author>
<name>Sssnowyyy</name>
<email>78863999+Sssnowyyy@users.noreply.github.com</email>
</author>
<published>2026-11-02T16:30:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=e46c6cbfb0f6735ca35f1150338c300f3c9c18fe'/>
<id>urn:sha1:e46c6cbfb0f6735ca35f1150338c300f3c9c18fe</id>
<content type='text'>
049c9633ed made TextureHeaderIndex take index / 32 for any texture index past the
pool that is a multiple of 32, in VisitImageView and in the shader environment.
That was written for Switch 2 handles that hold a header byte offset, but it ran
for Switch 1 games too, where such an out-of-range index used to give a null view
(and fail the shader environment's range check) and now binds an unrelated
header. Pass whether the memory manager uses native tiling, which is how Switch 2
titles are set up, and keep the previous behaviour otherwise.

Follow-up to 049c9633ed.

Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
</content>
</entry>
<entry>
<title>Merge nx2 into nx2-experimental</title>
<updated>2026-11-02T13:43:01+00:00</updated>
<author>
<name>kraibse</name>
<email>33869366+kraibse@users.noreply.github.com</email>
</author>
<published>2026-11-02T12:50:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=c0cb3325e22756edb65c87d33ef298349ade0ad3'/>
<id>urn:sha1:c0cb3325e22756edb65c87d33ef298349ade0ad3</id>
<content type='text'>
Resolved by area:
- audio feature_support.h: nx2's native revision handling.
- fiber.cpp: ours, which also drops the unused rewind stack.
- host_memory.cpp: ours granule bitmap and HintCold, plus nx2's
  fallocate hole punching per whole dirty granule on Linux.
- texture_cache.h: nx2's old-age eviction pass, then our Collect().
- kepler_compute.cpp: shared upscale slots, then Fortune's Weave's,
  then the Kirby Air Riders scan.
- nx2_gsv.h: ours, plus nx2's GetBufferMaxResolution and graphics
  device ids (1-based).
- nvhost_ctrl_gpu.cpp: engine support flag bits 40-44.
- lower_to_maxwell.h: ours as the base, with nx2's seven lowering
  commits applied one at a time. Second texture descriptor buffers
  are read bindless in TEX, TLD.SCR (level zero) and SUST; FSEL
  keeps its operand modifiers; TXD takes any channel mask.

lower_to_maxwell.h lowers 837 Fortune's Weave and 1183 Mario Kart
World shader dumps with the same rejects as nx2 and ours (12 and 0).

Assisted-by: Claude Sonnet 5.5 (conflict analysis and drafting)
</content>
</entry>
<entry>
<title>Linux and AMD: BC3 flashing on RADV, ASTC decode stalls, lower RAM usage, a buffer cache crash (#260)</title>
<updated>2026-11-02T07:45:39+00:00</updated>
<author>
<name>Whovian64</name>
<email>86082882+whovian64@users.noreply.github.com</email>
</author>
<published>2026-11-02T07:45:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=a407703f6d29a5ab73328b4ededb12cf29b2758d'/>
<id>urn:sha1:a407703f6d29a5ab73328b4ededb12cf29b2758d</id>
<content type='text'>
* host_memory: punch holes in the backing on Linux instead of zero filling freed memory

Freeing guest memory zero filled the memfd backing with memset, which
commits every page it touches. fallocate(PUNCH_HOLE) hands the pages back
to the kernel instead, and they read as zero afterwards. Only the partial
pages at the ends are still cleared by hand.

Mario Kart World on Linux (RX 9070 XT, 31 GB): peak RSS 23.1 -&gt; 15.9 GB.
EDEN_PUNCH_HOLE=0 restores the memset.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* fiber: don't zero fill the stacks, untouched pages stay unbacked

The value initialised stack arrays were zero filled when each fiber was
made, which commits the whole stack. Left uninitialised, the pages a
fiber never touches stay unbacked. Together with the descriptor ring
change, about 1.2 GB less RSS in Mario Kart World.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* vulkan: don't zero fill the descriptor update ring

Same as the fiber stacks: make_unique value initialised the whole ring
for every frame in flight. Entries are always written before they are
read, so allocate it without initialising it.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* vulkan: wait for the GPU after an ASTC transcode decode like the other ASTC decodes

TranscodeAstcToBcn (astc_recompression Bc1/Bc3 with GPU decode) was the
only ASTC decode recorded with wait = false. On RADV (RX 9070 XT, Mesa)
Mario Kart World with BC3 flashed heavily all over the screen, while the
uncompressed GPU decode, which waits, did not. CPU decode with BC3 does
not flash either. Waiting after the transcode removes the flashing; full
pipeline barriers around its copy did not, so the wait hides a race
somewhere else rather than fixing one in the transcode itself.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* vulkan: submit after an ASTC decode instead of waiting for the GPU by default

Every ASTC decode ended with scheduler.Finish(). Over a 19 minute Mario
Kart World Grand Prix that stalled the GPU thread 30.7 s in total, up to
1.2 s out of every 5 s while new textures stream in (track sections,
race starts), which is where the hitches were. Flushing keeps the
ordering that stops the BC3 flashing on RADV without the CPU waiting:
no flashing in play, and frames over 100 ms went from dozens to 3 in
about 7 minutes. EDEN_NX2_ASTC_FLUSH=0 restores the wait.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* texture_cache: over the expected use, evict costly images unused for 1800 frames first

The collector never deletes CostlyLoad images outside aggressive mode, so
once a cup moves on, the previous tracks' textures stay resident and the
cache sits over its expected use deleting the cheap images still in use.
When over the expected use, costly images unused for 1800 frames (half a
minute) now go first.

Mario Kart World Grand Prix on an RX 9070 XT: frames over 20 ms 8.8% -&gt;
4.0%, 58.7 fps average. EDEN_NX2_TC_OLD_AGE=&lt;frames&gt; sets the age, 0
turns it off.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)

* buffer_cache: no buffer for device addresses past the page table

FindBuffer indexed page_table, which covers 2^36 bytes, with any address.
Mario Kart World crashed after about 4.5 minutes with a uniform buffer at
0x72253b2f2890 (FindBuffer &lt;- UpdateUniformBuffers &lt;- DrawEnd from a
macro), reading far past the table. Treat such an address as no buffer.
Where that address comes from is still unknown; this only stops the
crash.

Assisted-by: Claude Opus 5.5 (debugging, profiling and code drafts)</content>
</entry>
<entry>
<title>video_core: temporal upscale stand-in for Fortune's Weave's DLSS</title>
<updated>2026-11-02T02:54:49+00:00</updated>
<author>
<name>Duck912</name>
<email>350528965+Duck912@users.noreply.github.com</email>
</author>
<published>2026-11-02T02:43:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=92d49d8a0c3e60894765bc2c332fdc936c87fc45'/>
<id>urn:sha1:92d49d8a0c3e60894765bc2c332fdc936c87fc45</id>
<content type='text'>
The one-frame blit left 3D edges aliased and shaking: the game jitters
its camera every frame for DLSS to accumulate. Fire Emblem: Fortune's
Weave's first DLSS pass (also rejected) has the motion vectors
(cbuf0+0x290, R16G16) and the frame's jitter (+0x1b0/+0x1b4, in input
pixels). Kepler compute keeps them, and the stand-in for the last
network pass now draws temporal_upscale.frag: input samples placed where
the jitter put them and weighted by distance, blended with the previous
result reprojected along the motion vectors (Catmull-Rom) and clipped to
the 3x3 neighbourhood in YCoCg. The history is copied from the result
right after drawing it, so post-processing the game later applies to its
output does not feed back. EDEN_NX2_TEMPORAL_UPSCALE=0 restores the blit.

Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting)
Signed-off-by: Duck912 &lt;350528965+Duck912@users.noreply.github.com&gt;
</content>
</entry>
<entry>
<title>texture_cache: keep the allocator's block slack out of the usable VRAM</title>
<updated>2026-11-01T23:11:26+00:00</updated>
<author>
<name>kraibse</name>
<email>33869366+kraibse@users.noreply.github.com</email>
</author>
<published>2026-11-01T14:38:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=51d798ff0373a40098aa77ef13d54307f39e44ac'/>
<id>urn:sha1:51d798ff0373a40098aa77ef13d54307f39e44ac</id>
<content type='text'>
The collector's usage leaves out the unused part of VMA's blocks, but
the driver counts it and a heap at its budget cannot give it to a new
image. On an RX 7800 XT that slack was 1.06 GiB, the whole 1 GiB margin:
the heap sat at its budget for a minute while the collector saw room,
then images stopped fitting and the process died. Reserve the slack
(capped at 1.5 GiB) on top of the margin: at once when it grows, slowly
when it shrinks, so eviction leaving partly used blocks doesn't chase
the threshold down.

Assisted-by: Claude Sonnet 5.5 (diagnosis and code)
(cherry picked from commit 73fd5a489ea28226fa16a55f5008e622d631b54c)
</content>
</entry>
</feed>
