diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index f0888327f..9ceb7fabc 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -242,7 +242,7 @@ struct Memory::Impl {
             }
             case Common::PageType::RasterizerCachedMemory: {
                 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
-                system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
+                system.GPU().FlushRegion(current_vaddr, copy_amount);
                 std::memcpy(dest_buffer, host_ptr, copy_amount);
                 break;
             }
@@ -290,7 +290,7 @@ struct Memory::Impl {
             }
             case Common::PageType::RasterizerCachedMemory: {
                 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
-                system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount);
+                system.GPU().InvalidateRegion(current_vaddr, copy_amount);
                 std::memcpy(host_ptr, src_buffer, copy_amount);
                 break;
             }
@@ -337,7 +337,7 @@ struct Memory::Impl {
             }
             case Common::PageType::RasterizerCachedMemory: {
                 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
-                system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount);
+                system.GPU().InvalidateRegion(current_vaddr, copy_amount);
                 std::memset(host_ptr, 0, copy_amount);
                 break;
             }
@@ -384,7 +384,7 @@ struct Memory::Impl {
             }
             case Common::PageType::RasterizerCachedMemory: {
                 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
-                system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
+                system.GPU().FlushRegion(current_vaddr, copy_amount);
                 WriteBlock(process, dest_addr, host_ptr, copy_amount);
                 break;
             }
@@ -545,7 +545,7 @@ struct Memory::Impl {
             break;
         case Common::PageType::RasterizerCachedMemory: {
             const u8* const host_ptr = GetPointerFromVMA(vaddr);
-            system.GPU().FlushRegion(ToCacheAddr(host_ptr), sizeof(T));
+            system.GPU().FlushRegion(vaddr, sizeof(T));
             T value;
             std::memcpy(&value, host_ptr, sizeof(T));
             return value;
@@ -587,7 +587,7 @@ struct Memory::Impl {
             break;
         case Common::PageType::RasterizerCachedMemory: {
             u8* const host_ptr{GetPointerFromVMA(vaddr)};
-            system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), sizeof(T));
+            system.GPU().InvalidateRegion(vaddr, sizeof(T));
             std::memcpy(host_ptr, &data, sizeof(T));
             break;
         }
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index ced9d7e28..1a2d747be 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -270,13 +270,13 @@ public:
     virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
 
     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
-    virtual void FlushRegion(CacheAddr addr, u64 size) = 0;
+    virtual void FlushRegion(VAddr addr, u64 size) = 0;
 
     /// Notify rasterizer that any caches of the specified region should be invalidated
-    virtual void InvalidateRegion(CacheAddr addr, u64 size) = 0;
+    virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
 
     /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
-    virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0;
+    virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;
 
 protected:
     virtual void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const = 0;
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp
index 925be8d7b..cc434faf7 100644
--- a/src/video_core/gpu_asynch.cpp
+++ b/src/video_core/gpu_asynch.cpp
@@ -30,15 +30,15 @@ void GPUAsynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
     gpu_thread.SwapBuffers(framebuffer);
 }
 
-void GPUAsynch::FlushRegion(CacheAddr addr, u64 size) {
+void GPUAsynch::FlushRegion(VAddr addr, u64 size) {
     gpu_thread.FlushRegion(addr, size);
 }
 
-void GPUAsynch::InvalidateRegion(CacheAddr addr, u64 size) {
+void GPUAsynch::InvalidateRegion(VAddr addr, u64 size) {
     gpu_thread.InvalidateRegion(addr, size);
 }
 
-void GPUAsynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
+void GPUAsynch::FlushAndInvalidateRegion(VAddr addr, u64 size) {
     gpu_thread.FlushAndInvalidateRegion(addr, size);
 }
 
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h
index 265c62758..03fd0eef0 100644
--- a/src/video_core/gpu_asynch.h
+++ b/src/video_core/gpu_asynch.h
@@ -27,9 +27,9 @@ public:
     void Start() override;
     void PushGPUEntries(Tegra::CommandList&& entries) override;
     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
-    void FlushRegion(CacheAddr addr, u64 size) override;
-    void InvalidateRegion(CacheAddr addr, u64 size) override;
-    void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
+    void FlushRegion(VAddr addr, u64 size) override;
+    void InvalidateRegion(VAddr addr, u64 size) override;
+    void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void WaitIdle() const override;
 
 protected:
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp
index bd5278a5c..6f38a672a 100644
--- a/src/video_core/gpu_synch.cpp
+++ b/src/video_core/gpu_synch.cpp
@@ -26,15 +26,15 @@ void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
     renderer->SwapBuffers(framebuffer);
 }
 
-void GPUSynch::FlushRegion(CacheAddr addr, u64 size) {
+void GPUSynch::FlushRegion(VAddr addr, u64 size) {
     renderer->Rasterizer().FlushRegion(addr, size);
 }
 
-void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) {
+void GPUSynch::InvalidateRegion(VAddr addr, u64 size) {
     renderer->Rasterizer().InvalidateRegion(addr, size);
 }
 
-void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
+void GPUSynch::FlushAndInvalidateRegion(VAddr addr, u64 size) {
     renderer->Rasterizer().FlushAndInvalidateRegion(addr, size);
 }
 
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h
index 866a94c8c..4a6e9a01d 100644
--- a/src/video_core/gpu_synch.h
+++ b/src/video_core/gpu_synch.h
@@ -26,9 +26,9 @@ public:
     void Start() override;
     void PushGPUEntries(Tegra::CommandList&& entries) override;
     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
-    void FlushRegion(CacheAddr addr, u64 size) override;
-    void InvalidateRegion(CacheAddr addr, u64 size) override;
-    void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
+    void FlushRegion(VAddr addr, u64 size) override;
+    void InvalidateRegion(VAddr addr, u64 size) override;
+    void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void WaitIdle() const override {}
 
 protected:
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 270c7ae0d..10cda686b 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -77,15 +77,15 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
     PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt));
 }
 
-void ThreadManager::FlushRegion(CacheAddr addr, u64 size) {
+void ThreadManager::FlushRegion(VAddr addr, u64 size) {
     PushCommand(FlushRegionCommand(addr, size));
 }
 
-void ThreadManager::InvalidateRegion(CacheAddr addr, u64 size) {
+void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
     system.Renderer().Rasterizer().InvalidateRegion(addr, size);
 }
 
-void ThreadManager::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
+void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
     // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
     InvalidateRegion(addr, size);
 }
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index be36c580e..cd74ad330 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -47,26 +47,26 @@ struct SwapBuffersCommand final {
 
 /// Command to signal to the GPU thread to flush a region
 struct FlushRegionCommand final {
-    explicit constexpr FlushRegionCommand(CacheAddr addr, u64 size) : addr{addr}, size{size} {}
+    explicit constexpr FlushRegionCommand(VAddr addr, u64 size) : addr{addr}, size{size} {}
 
-    CacheAddr addr;
+    VAddr addr;
     u64 size;
 };
 
 /// Command to signal to the GPU thread to invalidate a region
 struct InvalidateRegionCommand final {
-    explicit constexpr InvalidateRegionCommand(CacheAddr addr, u64 size) : addr{addr}, size{size} {}
+    explicit constexpr InvalidateRegionCommand(VAddr addr, u64 size) : addr{addr}, size{size} {}
 
-    CacheAddr addr;
+    VAddr addr;
     u64 size;
 };
 
 /// Command to signal to the GPU thread to flush and invalidate a region
 struct FlushAndInvalidateRegionCommand final {
-    explicit constexpr FlushAndInvalidateRegionCommand(CacheAddr addr, u64 size)
+    explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr, u64 size)
         : addr{addr}, size{size} {}
 
-    CacheAddr addr;
+    VAddr addr;
     u64 size;
 };
 
@@ -111,13 +111,13 @@ public:
     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
 
     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
-    void FlushRegion(CacheAddr addr, u64 size);
+    void FlushRegion(VAddr addr, u64 size);
 
     /// Notify rasterizer that any caches of the specified region should be invalidated
-    void InvalidateRegion(CacheAddr addr, u64 size);
+    void InvalidateRegion(VAddr addr, u64 size);
 
     /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
-    void FlushAndInvalidateRegion(CacheAddr addr, u64 size);
+    void FlushAndInvalidateRegion(VAddr addr, u64 size);
 
     // Wait until the gpu thread is idle.
     void WaitIdle() const;
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index f5d33f27a..cddef8d86 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -81,12 +81,11 @@ GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
     ASSERT((gpu_addr & page_mask) == 0);
 
     const u64 aligned_size{Common::AlignUp(size, page_size)};
-    const CacheAddr cache_addr{ToCacheAddr(GetPointer(gpu_addr))};
     const auto cpu_addr = GpuToCpuAddress(gpu_addr);
     ASSERT(cpu_addr);
 
     // Flush and invalidate through the GPU interface, to be asynchronous if possible.
-    system.GPU().FlushAndInvalidateRegion(cache_addr, aligned_size);
+    system.GPU().FlushAndInvalidateRegion(*cpu_addr, aligned_size);
 
     UnmapRange(gpu_addr, aligned_size);
     ASSERT(system.CurrentProcess()
@@ -247,7 +246,7 @@ void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::s
             const u8* src_ptr{page_table.pointers[page_index] + page_offset};
             // Flush must happen on the rasterizer interface, such that memory is always synchronous
             // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
-            rasterizer.FlushRegion(ToCacheAddr(src_ptr), copy_amount);
+            rasterizer.FlushRegion(page_table.backing_addr[page_index] + page_offset, copy_amount);
             std::memcpy(dest_buffer, src_ptr, copy_amount);
             break;
         }
@@ -299,7 +298,8 @@ void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const
             u8* dest_ptr{page_table.pointers[page_index] + page_offset};
             // Invalidate must happen on the rasterizer interface, such that memory is always
             // synchronous when it is written (even when in asynchronous GPU mode).
-            rasterizer.InvalidateRegion(ToCacheAddr(dest_ptr), copy_amount);
+            rasterizer.InvalidateRegion(page_table.backing_addr[page_index] + page_offset,
+                                        copy_amount);
             std::memcpy(dest_ptr, src_buffer, copy_amount);
             break;
         }
@@ -349,7 +349,7 @@ void MemoryManager::CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, const std::
             // Flush must happen on the rasterizer interface, such that memory is always synchronous
             // when it is copied (even when in asynchronous GPU mode).
             const u8* src_ptr{page_table.pointers[page_index] + page_offset};
-            rasterizer.FlushRegion(ToCacheAddr(src_ptr), copy_amount);
+            rasterizer.FlushRegion(page_table.backing_addr[page_index] + page_offset, copy_amount);
             WriteBlock(dest_addr, src_ptr, copy_amount);
             break;
         }
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 1a68e3caa..8ae5b9c4e 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -53,14 +53,14 @@ public:
     virtual void FlushAll() = 0;
 
     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
-    virtual void FlushRegion(CacheAddr addr, u64 size) = 0;
+    virtual void FlushRegion(VAddr addr, u64 size) = 0;
 
     /// Notify rasterizer that any caches of the specified region should be invalidated
-    virtual void InvalidateRegion(CacheAddr addr, u64 size) = 0;
+    virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
 
     /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
     /// and invalidated
-    virtual void FlushAndInvalidateRegion(CacheAddr addr, u64 size) = 0;
+    virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;
 
     /// Notify the rasterizer to send all written commands to the host GPU.
     virtual void FlushCommands() = 0;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 346feeb2f..261738830 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -656,28 +656,30 @@ void RasterizerOpenGL::Query(GPUVAddr gpu_addr, VideoCore::QueryType type,
 
 void RasterizerOpenGL::FlushAll() {}
 
-void RasterizerOpenGL::FlushRegion(CacheAddr addr, u64 size) {
+void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
     MICROPROFILE_SCOPE(OpenGL_CacheManagement);
     if (!addr || !size) {
         return;
     }
-    texture_cache.FlushRegion(addr, size);
-    buffer_cache.FlushRegion(addr, size);
-    query_cache.FlushRegion(addr, size);
+    CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr));
+    texture_cache.FlushRegion(cache_addr, size);
+    buffer_cache.FlushRegion(cache_addr, size);
+    query_cache.FlushRegion(cache_addr, size);
 }
 
-void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) {
+void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
     MICROPROFILE_SCOPE(OpenGL_CacheManagement);
     if (!addr || !size) {
         return;
     }
-    texture_cache.InvalidateRegion(addr, size);
-    shader_cache.InvalidateRegion(addr, size);
-    buffer_cache.InvalidateRegion(addr, size);
-    query_cache.InvalidateRegion(addr, size);
+    CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr));
+    texture_cache.InvalidateRegion(cache_addr, size);
+    shader_cache.InvalidateRegion(cache_addr, size);
+    buffer_cache.InvalidateRegion(cache_addr, size);
+    query_cache.InvalidateRegion(cache_addr, size);
 }
 
-void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
+void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
     if (Settings::values.use_accurate_gpu_emulation) {
         FlushRegion(addr, size);
     }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 2d3be2437..212dad852 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -65,9 +65,9 @@ public:
     void ResetCounter(VideoCore::QueryType type) override;
     void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override;
     void FlushAll() override;
-    void FlushRegion(CacheAddr addr, u64 size) override;
-    void InvalidateRegion(CacheAddr addr, u64 size) override;
-    void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
+    void FlushRegion(VAddr addr, u64 size) override;
+    void InvalidateRegion(VAddr addr, u64 size) override;
+    void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void FlushCommands() override;
     void TickFrame() override;
     bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 58c69b786..0ca72eb45 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -495,20 +495,28 @@ void RasterizerVulkan::Query(GPUVAddr gpu_addr, VideoCore::QueryType type,
 
 void RasterizerVulkan::FlushAll() {}
 
-void RasterizerVulkan::FlushRegion(CacheAddr addr, u64 size) {
-    texture_cache.FlushRegion(addr, size);
-    buffer_cache.FlushRegion(addr, size);
-    query_cache.FlushRegion(addr, size);
+void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) {
+    if (!addr || !size) {
+        return;
+    }
+    CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr));
+    texture_cache.FlushRegion(cache_addr, size);
+    buffer_cache.FlushRegion(cache_addr, size);
+    query_cache.FlushRegion(cache_addr, size);
 }
 
-void RasterizerVulkan::InvalidateRegion(CacheAddr addr, u64 size) {
-    texture_cache.InvalidateRegion(addr, size);
-    pipeline_cache.InvalidateRegion(addr, size);
-    buffer_cache.InvalidateRegion(addr, size);
-    query_cache.InvalidateRegion(addr, size);
+void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size) {
+    if (!addr || !size) {
+        return;
+    }
+    CacheAddr cache_addr = ToCacheAddr(system.Memory().GetPointer(addr));
+    texture_cache.InvalidateRegion(cache_addr, size);
+    pipeline_cache.InvalidateRegion(cache_addr, size);
+    buffer_cache.InvalidateRegion(cache_addr, size);
+    query_cache.InvalidateRegion(cache_addr, size);
 }
 
-void RasterizerVulkan::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
+void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) {
     FlushRegion(addr, size);
     InvalidateRegion(addr, size);
 }
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 3185868e9..f642dde76 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -118,9 +118,9 @@ public:
     void ResetCounter(VideoCore::QueryType type) override;
     void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override;
     void FlushAll() override;
-    void FlushRegion(CacheAddr addr, u64 size) override;
-    void InvalidateRegion(CacheAddr addr, u64 size) override;
-    void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
+    void FlushRegion(VAddr addr, u64 size) override;
+    void InvalidateRegion(VAddr addr, u64 size) override;
+    void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
     void FlushCommands() override;
     void TickFrame() override;
     bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,