diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 8c20ee6ed..0031afa0a 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -158,7 +158,7 @@ struct PageManager::Impl { const bool is_write = Common::IsWriteError(context); if (is_write && owned_ranges.find(addr) != owned_ranges.end()) { const VAddr addr_aligned = Common::AlignDown(addr, PAGESIZE); - rasterizer->InvalidateMemory(addr_aligned, PAGESIZE); + rasterizer->InvalidateMemory(addr, addr_aligned, PAGESIZE); return true; } return false; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 8dc0771de..e66d12517 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -792,9 +792,9 @@ u32 Rasterizer::ReadDataFromGds(u32 gds_offset) { return value; } -void Rasterizer::InvalidateMemory(VAddr addr, u64 size) { - buffer_cache.InvalidateMemory(addr, size); - texture_cache.InvalidateMemory(addr, size); +void Rasterizer::InvalidateMemory(VAddr addr, VAddr addr_aligned, u64 size) { + buffer_cache.InvalidateMemory(addr_aligned, size); + texture_cache.InvalidateMemory(addr, addr_aligned, size); } void Rasterizer::MapMemory(VAddr addr, u64 size) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 5102cda38..fe8aceba7 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -46,7 +46,7 @@ public: void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds); u32 ReadDataFromGds(u32 gsd_offset); - void InvalidateMemory(VAddr addr, u64 size); + void InvalidateMemory(VAddr addr, VAddr addr_aligned, u64 size); void MapMemory(VAddr addr, u64 size); void UnmapMemory(VAddr addr, u64 size); diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 516c110a4..bf005b15c 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -43,11 +43,17 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& TextureCache::~TextureCache() = default; -void TextureCache::InvalidateMemory(VAddr address, size_t size) { +void TextureCache::InvalidateMemory(VAddr addr, VAddr addr_aligned, size_t size) { std::scoped_lock lock{mutex}; - ForEachImageInRegion(address, size, [&](ImageId image_id, Image& image) { - // Ensure image is reuploaded when accessed again. - image.flags |= ImageFlagBits::CpuDirty; + ForEachImageInRegion(addr_aligned, size, [&](ImageId image_id, Image& image) { + const auto addr_begin = addr; + const auto addr_end = addr + size; + const auto image_begin = image.info.guest_address; + const auto image_end = image.info.guest_address + image.info.guest_size_bytes; + if (addr_begin < image_end && image_begin < addr_end) { + // Ensure image is reuploaded when accessed again. + image.flags |= ImageFlagBits::CpuDirty; + } // Untrack image, so the range is unprotected and the guest can write freely. UntrackImage(image_id); }); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 8ac603f06..fd792bc96 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -95,7 +95,7 @@ public: ~TextureCache(); /// Invalidates any image in the logical page range. - void InvalidateMemory(VAddr address, size_t size); + void InvalidateMemory(VAddr addr, VAddr addr_aligned, size_t size); /// Marks an image as dirty if it exists at the provided address. void InvalidateMemoryFromGPU(VAddr address, size_t max_size);