From 3d1cf7b28e2553358526d4eefa51a618f74ef95e Mon Sep 17 00:00:00 2001
From: pineappleEA <pineaea@gmail.com>
Date: Sun, 27 Mar 2022 08:08:12 +0200
Subject: [PATCH] early-access version 2613

---
 README.md                         |  2 +-
 src/video_core/memory_manager.cpp | 25 ++++++++++++++++---------
 src/video_core/memory_manager.h   |  1 +
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 9d70f021a..ab4e1bcbb 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 yuzu emulator early access
 =============
 
-This is the source code for early-access 2612.
+This is the source code for early-access 2613.
 
 ## Legal Notice
 
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 722ebd9ad..d7011b3b4 100755
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -39,7 +39,22 @@ GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std
     return gpu_addr;
 }
 
+void MemoryManager::UnmapSubmappedRanges(GPUVAddr gpu_addr, std::size_t size) {
+    const auto submapped_ranges = GetSubmappedRange(gpu_addr, size);
+    for (const auto& [map_addr, map_size] : submapped_ranges) {
+        // Flush and invalidate through the GPU interface, to be asynchronous if possible.
+        const std::optional<VAddr> cpu_vaddr = GpuToCpuAddress(map_addr);
+        if (!cpu_vaddr) {
+            continue;
+        }
+        rasterizer->UnmapMemory(*cpu_vaddr, map_size);
+    }
+}
+
 GPUVAddr MemoryManager::Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size) {
+    // Unmap any pre-existing rasterizer memory in this range
+    UnmapSubmappedRanges(gpu_addr, size);
+
     const auto it = std::ranges::lower_bound(map_ranges, gpu_addr, {}, &MapRange::first);
     if (it != map_ranges.end() && it->first == gpu_addr) {
         it->second = size;
@@ -70,16 +85,8 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) {
     } else {
         UNREACHABLE_MSG("Unmapping non-existent GPU address=0x{:x}", gpu_addr);
     }
-    const auto submapped_ranges = GetSubmappedRange(gpu_addr, size);
-
-    for (const auto& [map_addr, map_size] : submapped_ranges) {
-        // Flush and invalidate through the GPU interface, to be asynchronous if possible.
-        const std::optional<VAddr> cpu_addr = GpuToCpuAddress(map_addr);
-        ASSERT(cpu_addr);
-
-        rasterizer->UnmapMemory(*cpu_addr, map_size);
-    }
 
+    UnmapSubmappedRanges(gpu_addr, size);
     UpdateRange(gpu_addr, PageEntry::State::Unmapped, size);
 }
 
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 61bfe47c7..ebeea7a40 100755
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -149,6 +149,7 @@ private:
     [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const;
     void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size);
     GPUVAddr UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size);
+    void UnmapSubmappedRanges(GPUVAddr gpu_addr, std::size_t size);
     [[nodiscard]] std::optional<GPUVAddr> FindFreeRange(std::size_t size, std::size_t align,
                                                         bool start_32bit_address = false) const;