aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/nx2.h
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 04:56:16 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 04:56:16 -0400
commit2c6d8f03aadb3c9d900909bd4af64bbb18614d6d (patch)
treef7ae707fd278434de8ced86a266d43a6752dc827 /src/video_core/nx2.h
parent64c91974f4455a63a025149a4ba8e2c46894bdc7 (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.h17
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;