<feed xmlns='http://www.w3.org/2005/Atom'>
<title>eglantine-cirakg/src/core/device_memory_manager.inc, 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-02T23:26:48+00:00</updated>
<entry>
<title>Merge pull request #235 from CloudP4bbs/pr/asid-guard</title>
<updated>2026-11-02T23:26:48+00:00</updated>
<author>
<name>Jonas</name>
<email>104419015+jojo-chaechae@users.noreply.github.com</email>
</author>
<published>2026-11-02T23:26:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=59718ed0820132176ead0ebcb29e5b6a0cf93e4f'/>
<id>urn:sha1:59718ed0820132176ead0ebcb29e5b6a0cf93e4f</id>
<content type='text'>
core: do not index registered_processes with an unregistered ASID</content>
</entry>
<entry>
<title>Merge remote-tracking branch 'origin/fix/cold-hint-uploaded-memory' into test/linux-all-prs</title>
<updated>2026-11-01T18:25:46+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-11-01T18:25:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=9ee8d6f6a6900537eccf67e4c3a9bb16248dc6ab'/>
<id>urn:sha1:9ee8d6f6a6900537eccf67e4c3a9bb16248dc6ab</id>
<content type='text'>
</content>
</entry>
<entry>
<title>core: do not index registered_processes with an unregistered ASID</title>
<updated>2026-11-01T18:10:03+00:00</updated>
<author>
<name>Paulo Rossatto</name>
<email>alcinopolis@pm.ms.gov.br</email>
</author>
<published>2026-11-01T18:10:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=3005cc4149a0c9a5d7228d8ec69d5e7e89c4a935'/>
<id>urn:sha1:3005cc4149a0c9a5d7228d8ec69d5e7e89c4a935</id>
<content type='text'>
</content>
</entry>
<entry>
<title>nx2: count a mapped sparse tile as written</title>
<updated>2026-11-01T16:29:56+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-11-01T02:53:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=139b7e5efb7c4181f14e987706eef26ca1f327c0'/>
<id>urn:sha1:139b7e5efb7c4181f14e987706eef26ca1f327c0</id>
<content type='text'>
With remap support Mario Kart World fills nine world-sized masks
(R8 16384x16384, RG16 and R16 8192x8192, one sparse region each) in its
own memory and then maps them in through 216. Nothing writes them through
the sparse region, so its blocks stayed unwritten and the texture cache
kept the images over them without memory, reading zero: the static world
(roads, buildings, rocks, trees) rendered unlit while karts and cars were
lit. Without remap support the game never maps them and lights the world
without them.

A tile map now counts its blocks as written and invalidates the caches
over the tile, so those images get memory and load what the game mapped.
That costs the masks' full size in device memory (about 2.9 GB in Mario
Kart World), which is what they need until the texture cache can back
single images tile by tile. DeviceMemoryManager::Unmap no longer needs
its flag to keep the caches.
</content>
</entry>
<entry>
<title>nx2: map and unmap sparse texture tiles (nx2:gpu 216)</title>
<updated>2026-11-01T16:29:56+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-31T23:10:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=4d6a13e3d9eaa7bf17381fce0e50d5275ac8957e'/>
<id>urn:sha1:4d6a13e3d9eaa7bf17381fce0e50d5275ac8957e</id>
<content type='text'>
Switch 2 games commit and release the memory behind sparse textures by
remapping tiles: nvnMemoryPoolMapVirtual goes through NvRm's remap into
nn::gpu::sdk::ExecuteSparseMapRequests, nx2:gpu sub-session command 216,
a batch of 40-byte requests. A map points a tile at the game's own
GPU-accessible memory (the handle sub 101 returned, plus an offset), an
unmap makes it read zero again; the sparse region itself never has memory.

NvRm only remaps when the GPU characteristics report
NVGPU_GPU_FLAGS_SUPPORT_REMAP (bit 35). Without it every remap failed
before reaching the server, so Mario Kart World streamed its terrain into
unmapped sparse memory and each 4 MiB block it touched got memory that
was never freed (2.5 GB after 10 minutes, still growing).

Report the flag (EDEN_NX2_SPARSE_REMAP=0 leaves it out) and serve 216:

- Sparse regions: a tile's device pages show the game's memory, or are
  unmapped, in GPU thread order, without invalidating the caches over
  them; the region keeps its GPU mapping, so the texture cache keeps its
  images. A region the game maps tiles into gets no more blocks (writes
  outside its tiles are dropped, as on the console), gives back the
  blocks it already had, and marks a block written when the GPU first
  writes it, so array layers it only maps tiles into get no memory or
  uploads.
- GPU-only regions (214 without the sparse flag): the game also sends
  216 for its render targets and, with remap support, for two texture
  arrays (5.8 GB and 1.4 GB). Regions whose memory another GPU-only
  region maps (render-target groups) keep the memory 214 gave them:
  applied, the texture cache flushed and re-uploaded the overlapping
  render targets every frame. Regions 214 backs as they are written
  keep their blocks too, since the texture cache reads an image's memory
  in full when it uploads it, which makes the game's pages resident on
  the host (about 1 GB more 150 s in). The rest get the game's memory
  the way 211 maps it, so writes through the game's own address reach
  the same device pages; an unmap points the range back at the region's
  own memory.

Mario Kart World, 10 minutes: no sparse blocks backed (2.5 GB before),
24.6 presents a second instead of 19.3. 216 totals are logged every 30 s.
</content>
</entry>
<entry>
<title>texture_cache: mark guest memory textures were uploaded from cold</title>
<updated>2026-11-01T13:48:31+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-11-01T04:30:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=e2c512916c6f5042d030fcf1708043233f8df08e'/>
<id>urn:sha1:e2c512916c6f5042d030fcf1708043233f8df08e</id>
<content type='text'>
Once a texture is uploaded the host GPU has its own copy, and the guest
rarely reads that memory again, but it stayed in the emulator's working
set. Every 600 frames the guest ranges of images uploaded since (64 KiB
or more, not GPU-written or sparse) are marked cold through
HostMemory::HintCold, backing and CPU view, from a low-priority worker,
so the OS pages them out before anything else when it needs RAM. Their
contents stay; using them brings them back. Mario Kart World's title
screen at ~10 minutes: game memory in RAM 4.8-5.5 -&gt; 3.6 GB, the
emulator's real RAM 10.6-11.9 -&gt; 9.4 GB, frames over 100 ms not worse.

(cherry picked from commit ea36b2c5ca352f8c8cdcc829a2d3bde9bdc06ece)
</content>
</entry>
<entry>
<title>Gpu buffer readback to cpu. Fixing visible glitches such as missing collision on some object, but can extend to more.</title>
<updated>2026-10-31T19:49:14+00:00</updated>
<author>
<name>néo Luigi</name>
<email>85024393+neoluigi4123@users.noreply.github.com</email>
</author>
<published>2026-10-31T19:08:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=41a81ab5e3d88b53b634ed765385874728634e9f'/>
<id>urn:sha1:41a81ab5e3d88b53b634ed765385874728634e9f</id>
<content type='text'>
Assisted-by: Claude Opus 5.5 (debugging &amp; implementation)
</content>
</entry>
<entry>
<title>core: end device page runs where pages are unmapped or mapped again</title>
<updated>2026-10-30T17:41:49+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-30T17:41:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=ddd367a8152f1c37bfc972475b40afece2da31ac'/>
<id>urn:sha1:ddd367a8152f1c37bfc972475b40afece2da31ac</id>
<content type='text'>
WalkBlock copies a run of physically contiguous device pages at once, using
each page's continuity_tracker. Unmap left the counts as they were, Map
without tracking did not touch them, and the pages before a changed range
kept counting into it. A read starting on such a page then copied the host
memory that followed the old mapping, or, starting on an unmapped page,
zero-filled the whole old run, mapped pages after it included.

Splatoon Raiders lost its dialogue text this way: the glyph vertex shader
reads its corner table from constant buffer 1 (the program's constants, at
device 0x5617d700), and the buffer cache uploaded the range from 0x5617c000,
an unmapped page still counted as the start of a long run, so the table
reached the GPU as zeros and every glyph sampled one empty texel.

Unmap and Map now reset the counts of their pages (Map recounts them when
tracking) and cut the runs of the pages before them at the range start.
</content>
</entry>
<entry>
<title>nx2: give sparse regions memory only where the GPU writes</title>
<updated>2026-10-30T16:27:04+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-30T08:39:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=6380b6687ded27892404c576becd78b7161ba68a'/>
<id>urn:sha1:6380b6687ded27892404c576becd78b7161ba68a</id>
<content type='text'>
nx2:gpu 214 regions with the sparse flag (word 7 bit 0x200) are Mario
Kart World's terrain texture arrays and layer pools, 170 MB to 5.8 GB,
mostly empty. Backed whole they ran the graphics pool dry (26 "could not
allocate" per session, later regions without memory), and backing a
block at a time made the texture cache rebuild the 1.45 GB arrays each
time a block was mapped.

A sparse region now gets a device (SMMU) range of its own when it is
created, mapped for the GPU at once, so its GPU mapping never changes.
Before a GPU-side write lands in it (WriteBlock, Write&lt;T&gt;), the 4 MiB
blocks it touches get memory, cleared, behind their device pages.
Unbacked device pages read zero and drop writes instead of crashing, and
the unmapped-device-access errors are logged 16 times, not once per page.
nx2:gpu 215 releases the device range and the blocks after the GPU is
done with them. The log reports GPU-only memory in use and its peak.

Mario Kart World, 180 s: no allocation failures; ~2.8 GB of terrain
blocks get memory instead of 6.5 GB of whole regions, next to 3 GB of
ordinary GPU-only regions. Terrain renders as before.
</content>
</entry>
<entry>
<title>core: per-thread device memory translation cache</title>
<updated>2026-10-30T00:49:47+00:00</updated>
<author>
<name>Takoroka</name>
<email>137927095+Takoroka@users.noreply.github.com</email>
</author>
<published>2026-10-29T09:46:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cirakg.xyz/eglantine-cirakg/commit/?id=06f294c7e6b305d5d8904d284de70c268cc3f2e0'/>
<id>urn:sha1:06f294c7e6b305d5d8904d284de70c268cc3f2e0</id>
<content type='text'>
DeviceMemoryManager kept one four-entry page translation cache for every thread. Map
(on a guest service thread, e.g. nx2:gpu 211 job mappings) cleared it while the GPU
thread was between its null check of an entry and the copy from it: the GPU thread
then read from address 0 plus the page offset. Title 1 crashed this way in about half
of its 150 s test runs (BindHostGraphicsUniformBuffer -&gt; ReadBlockUnsafe, fault at
0x600). Each thread now keeps its own cache, which Map and Unmap invalidate through a
generation counter. 0 crashes in 6 runs after.
</content>
</entry>
</feed>
