<feed xmlns='http://www.w3.org/2005/Atom'>
<title>eglantine-cirakg/src/video_core/buffer_cache/buffer_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-03T06:29:23+00:00</updated>
<entry>
<title>nx2: fewer render pass splits on tiled GPUs, log failed GPU waits (Pokopia) (#361)</title>
<updated>2026-11-03T06:29:23+00:00</updated>
<author>
<name>Alex</name>
<email>78863999+Sssnowyyy@users.noreply.github.com</email>
</author>
<published>2026-11-03T06:29:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=f50099038ee4c95901821e137471a8ce87bf52a4'/>
<id>urn:sha1:f50099038ee4c95901821e137471a8ce87bf52a4</id>
<content type='text'>
* buffer_cache: don't end the render pass after mapped buffer uploads

Every upload set any_buffer_uploaded, and the next draw or dispatch then
recorded a transfer-to-shader barrier outside the render pass. On Vulkan
the uploads are mapped: each copy either records its own barriers
(CopyBuffer with barrier set) or goes to the upload command buffer,
which ends with a barrier before the frame's commands run. The extra
barrier only ended the render pass.

On tiled GPUs every such split writes the attachments out and reads
them back. Pokopia's first gameplay scene had ~50 of these splits a
frame. Without them, an M3 MacBook Air (MoltenVK, 1x docked) goes from
~35 to ~29.5 ms of GPU time a frame and from 28.5 to 32 fps.

OpenGL uploads immediately and keeps the barrier.

Assisted-by: Claude Opus 5.5 (profiling, implementation and commit message)

* vulkan: log a failed GPU wait before it ends the process

When the device is lost, vkWaitSemaphores in MasterSemaphore::Wait
returns VK_ERROR_DEVICE_LOST and the exception goes uncaught on the
fence thread or the GPU thread, so the process aborts without a line in
the log: ReportLoss is only reached from submit and present. A Pokopia
crash on macOS left the log ending a second before the abort, with no
hint that the GPU was lost.

Log the wait's result before rethrowing. On macOS, MoltenVK prints the
Metal reason (a GPU hang or page fault) to stderr only.

Assisted-by: Claude Opus 5.5 (diagnosis, implementation and commit message)</content>
</entry>
<entry>
<title>Merge pull request #334 from snowstormxd/codex/upstream-mkw-test</title>
<updated>2026-11-02T22:36:01+00:00</updated>
<author>
<name>Jonas</name>
<email>104419015+jojo-chaechae@users.noreply.github.com</email>
</author>
<published>2026-11-02T22:36:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=8362c44ff835d7be73d2adad9ce3e2d4467a6aeb'/>
<id>urn:sha1:8362c44ff835d7be73d2adad9ce3e2d4467a6aeb</id>
<content type='text'>
MKW performance improvements</content>
</entry>
<entry>
<title>nx2: rearm clean read areas when the GPU writes them again</title>
<updated>2026-11-02T20:51:11+00:00</updated>
<author>
<name>snowstormxd</name>
<email>214507868+snowstormxd@users.noreply.github.com</email>
</author>
<published>2026-11-01T14:21:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=06e211e0d0a1634d16f1d74d75682092fc92a5de'/>
<id>urn:sha1:06e211e0d0a1634d16f1d74d75682092fc92a5de</id>
<content type='text'>
Port the coherency changes from alarok/Eglantine 77fc365f2 without its diagnostic framework or shutdown changes. Only GPU-dirty CPU reads become permanently preflushable, clean areas can be trapped on the next write, non-core readers avoid indexing core arrays, and collected CPU writes precede readback.

Assisted-by: Codex (source review, selective integration and verification)
(cherry picked from commit b64e211957180aa218ec6d9a3bcb020332279c3f)
</content>
</entry>
<entry>
<title>buffer_cache: fix the already-disabled check for uniform buffers</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:39:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=8556e27015ded665ca9a5522071cdeeec20a1575'/>
<id>urn:sha1:8556e27015ded665ca9a5522071cdeeec20a1575</id>
<content type='text'>
DisableGraphicsUniformBuffer tested !current.buffer_id to detect a
binding that is already NULL_BINDING. SlotId converts to true unless it
is the invalid id, and NULL_BUFFER_ID is BufferId{0}, so the check was
false for NULL_BINDING and the early return never triggered. Compare
against NULL_BUFFER_ID instead.

Follow-up to 46b2577bf7.

Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
</content>
</entry>
<entry>
<title>vulkan: repack 69-byte vertices only when needed</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:38:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=13fc5fda26e6b5a9af67f5a654e831187bfa1962'/>
<id>urn:sha1:13fc5fda26e6b5a9af67f5a654e831187bfa1962</id>
<content type='text'>
SetVertexRepackLayout returned old_mask | new_mask, which stays non-zero
on every draw that uses a 69-byte binding. PrepareDraw then re-dirtied the
vertex buffers and vertex input each time, so the repack compute pass ran
and the render pass ended once per draw, which is costly on tiled GPUs.

Return old_mask ^ new_mask so only a layout change re-dirties the
bindings. The repacked copy only stays valid while the source data is
unchanged, so the buffer cache now flags the vertex buffers overlapping a
CPU write, inline or DMA write, or GPU write, and re-dirties the repacked
ones before binding. Command buffer submission already invalidates all
vertex buffer state, which keeps the staging copy within its tick.

Also pass the source buffer size to the repack pass and clamp the
word-rounded storage descriptor range to it; it could run up to three
bytes past the end of the buffer. A binding that does not fit is skipped
like one over the device limits.

Follow-up to e38b738b84.

Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
</content>
</entry>
<entry>
<title>video_core/buffer_cache: reuse unchanged small uniform buffers within command buffer</title>
<updated>2026-11-02T18:58:38+00:00</updated>
<author>
<name>gabrielskaminski</name>
<email>gabriel.skaminski@gmail.com</email>
</author>
<published>2026-11-01T04:49:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=202c6b0356e1fa9366e5b9000df35a63f1eb9dc0'/>
<id>urn:sha1:202c6b0356e1fa9366e5b9000df35a63f1eb9dc0</id>
<content type='text'>
(cherry picked from commit 4aa5cd89fd1862751b3297036f2d21a0dc924b23)
(cherry picked from commit f1bdd5b13a1bdca81243b4aa1d8529f0485d3671)
</content>
</entry>
<entry>
<title>nx2: read GPU-written command lists from copies instead of draining</title>
<updated>2026-11-02T16:24:19+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-11-02T16:24:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=8f1435f8db104351fa3388551eee9d12d2043b40'/>
<id>urn:sha1:8f1435f8db104351fa3388551eee9d12d2043b40</id>
<content type='text'>
The trees fix (#52) drains the split and flushes for every command list
on a GPU-written page: in a Mario Kart World race ~13,500 lists and ~400
GPU round trips a second, during which the back has nothing to do. The
replay ran at ~40 fps instead of ~45.

The front now marks the pages those lists are on. The buffer cache notes
writes to them; after a compute dispatch or DMA copy that writes one it
copies the page into host memory and submits. The front waits for the
back only up to the last compute or copy work it sent (not everything
queued), then reads the copy once the GPU is done with it.

Pages the GPU wrote once, long before, and the CPU now writes lists to
have no copy: their first list drains and flushes the whole page, which
is then read from guest memory until GPU work writes it again. CPU
writes and inline uploads reach guest memory, so they keep such a page
synced but make a copy stale. A page a draw writes always drains.

Mario Kart World time-trial replay, Radeon 780M: ~40 -&gt; ~45 fps, trees
drawn, no list drains left.
</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/buffer_cache: fast-guard stage buffer updates and uniform buffer disable (#264)</title>
<updated>2026-11-02T07:41:15+00:00</updated>
<author>
<name>ymatrix1</name>
<email>10088631+ymatrix1@users.noreply.github.com</email>
</author>
<published>2026-11-02T07:41:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=46b2577bf78870ed85cbb790a9dc3c82cc77f4a7'/>
<id>urn:sha1:46b2577bf78870ed85cbb790a9dc3c82cc77f4a7</id>
<content type='text'>
</content>
</entry>
</feed>
