diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 04:56:16 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 04:56:16 -0400 |
| commit | 2c6d8f03aadb3c9d900909bd4af64bbb18614d6d (patch) | |
| tree | f7ae707fd278434de8ced86a266d43a6752dc827 /src/video_core/nx2.h | |
| parent | 64c91974f4455a63a025149a4ba8e2c46894bdc7 (diff) | |
nx2: unmap GPU memory the game frees
nx2:gpu 213 (NormalUnmapGpuMemory4K) and 102 (destroy GPU-accessible
memory) were no-ops, so Eden kept freed memory mapped for the GPU. Title 4
frees its customization-room memory right after saving and reuses it as
ordinary heap; pending GPU->CPU write-backs for the old buffers then landed on
the new objects, and two threads crashed on garbage pointers ~5 s later
(the post-customization freeze).
Unmap the range from every address space (the GMMU unmap drops cached
buffers/images and their pending downloads), keep the registry's mapping
list in step, re-map 211 requests even at the memory's own address, and
drop freed regions from the semaphore mirror table, which every 8 KiB
allocation used to fill for good after 32 entries.
Diffstat (limited to 'src/video_core/nx2.h')
| -rw-r--r-- | src/video_core/nx2.h | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/video_core/nx2.h b/src/video_core/nx2.h index ef6619df3f..7bbbf14785 100644 --- a/src/video_core/nx2.h +++ b/src/video_core/nx2.h @@ -23,19 +23,32 @@ inline std::array<std::atomic<u64>, Nx2MaxSemaphoreRegions> g_nx2_semaphore_regi inline void Nx2AddSemaphoreRegion(u64 start) { for (auto& region : g_nx2_semaphore_regions) { + if (region.load() == start) { + return; + } + } + for (auto& region : g_nx2_semaphore_regions) { u64 expected = 0; - if (region.load() == start || region.compare_exchange_strong(expected, start)) { + if (region.compare_exchange_strong(expected, start)) { return; } } } +/// The region's memory was destroyed: stop mirroring into it. +inline void Nx2RemoveSemaphoreRegion(u64 start) { + for (auto& region : g_nx2_semaphore_regions) { + u64 expected = start; + region.compare_exchange_strong(expected, 0); + } +} + /// GPU VA in the first page that mirrors a release at `address`, or 0. inline u64 Nx2SemaphoreMirror(u64 address) { for (const auto& region : g_nx2_semaphore_regions) { const u64 start = region.load(std::memory_order_relaxed); if (start == 0) { - break; + continue; } if (address >= start + 0x1000 && address < start + 0x2000) { return address - 0x1000; |
