diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 30137d0646..2646a75b7c 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -685,14 +685,28 @@ namespace Ryujinx.Graphics.Gpu.Image
{
Texture overlap = _textureOverlaps[index];
- bool rangeMatches = range != null ? overlap.Range.Equals(range.Value) : overlap.Info.GpuAddress == info.GpuAddress;
- if (!rangeMatches)
- {
- continue;
- }
-
TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags);
+ if (matchQuality != TextureMatchQuality.NoMatch)
+ {
+ // If the parameters match, we need to make sure the texture is mapped to the same memory regions.
+
+ // If a range of memory was supplied, just check if the ranges match.
+ if (range != null && !overlap.Range.Equals(range.Value))
+ {
+ continue;
+ }
+
+ // If no range was supplied, we can check if the GPU virtual address match. If they do,
+ // we know the textures are located at the same memory region.
+ // If they don't, it may still be mapped to the same physical region, so we
+ // do a more expensive check to tell if they are mapped into the same physical regions.
+ if (overlap.Info.GpuAddress != info.GpuAddress && !_context.MemoryManager.CompareRange(overlap.Range, info.GpuAddress))
+ {
+ continue;
+ }
+ }
+
if (matchQuality == TextureMatchQuality.Perfect)
{
texture = overlap;
diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
index 7021cd2090..5776836c72 100644
--- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
@@ -343,6 +343,39 @@ namespace Ryujinx.Graphics.Gpu.Memory
return new MultiRange(regions.ToArray());
}
+ ///
+ /// Checks if a given GPU virtual memory range is mapped to the same physical regions
+ /// as the specified physical memory multi-range.
+ ///
+ /// Physical memory multi-range
+ /// GPU virtual memory address
+ /// True if the virtual memory region is mapped into the specified physical one, false otherwise
+ public bool CompareRange(MultiRange range, ulong va)
+ {
+ va &= ~PageMask;
+
+ for (int i = 0; i < range.Count; i++)
+ {
+ MemoryRange currentRange = range.GetSubRange(i);
+
+ ulong address = currentRange.Address & ~PageMask;
+ ulong endAddress = (currentRange.EndAddress + PageMask) & ~PageMask;
+
+ while (address < endAddress)
+ {
+ if (Translate(va) != address)
+ {
+ return false;
+ }
+
+ va += PageSize;
+ address += PageSize;
+ }
+ }
+
+ return true;
+ }
+
///
/// Validates a GPU virtual address.
///