diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 022a3839f..dca6263aa 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -101,6 +101,11 @@ namespace Ryujinx.Graphics.Gpu.Image
///
public bool AlwaysFlushOnOverlap { get; private set; }
+ ///
+ /// Indicates that the texture was fully unmapped since the modified flag was set, and flushes should be ignored until it is modified again.
+ ///
+ public bool FlushStale { get; private set; }
+
///
/// Increments when the host texture is swapped, or when the texture is removed from all pools.
///
@@ -149,6 +154,7 @@ namespace Ryujinx.Graphics.Gpu.Image
///
public bool HadPoolOwner { get; private set; }
+ ///
/// Physical memory ranges where the texture data is located.
///
public MultiRange Range { get; private set; }
@@ -1411,6 +1417,7 @@ namespace Ryujinx.Graphics.Gpu.Image
///
public void SignalModified()
{
+ FlushStale = false;
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
if (_modifiedStale || Group.HasCopyDependencies)
@@ -1431,6 +1438,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
if (bound)
{
+ FlushStale = false;
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
}
@@ -1695,12 +1703,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// The range of memory being unmapped
public void Unmapped(MultiRange unmapRange)
{
+ if (unmapRange.Contains(Range))
+ {
+ // If this is a full unmap, prevent flushes until the texture is mapped again.
+ FlushStale = true;
+ }
+
ChangedMapping = true;
if (Group.Storage == this)
{
Group.Unmapped();
-
Group.ClearModified(unmapRange);
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 5048ccca4..432b10853 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -107,8 +107,6 @@ namespace Ryujinx.Graphics.Gpu.Image
// Any texture that has been unmapped at any point or is partially unmapped
// should update their pool references after the remap completes.
- MultiRange unmapped = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
-
foreach (var texture in _partiallyMappedTextures)
{
texture.UpdatePoolMappings();
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
index 746a95ffc..21d7939ad 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
@@ -1659,6 +1659,14 @@ namespace Ryujinx.Graphics.Gpu.Image
return;
}
+ // If size is zero, we have nothing to flush.
+ // If the flush is stale, we should ignore it because the texture was unmapped since the modified
+ // flag was set, and flushing it is not safe anymore as the GPU might no longer own the memory.
+ if (size == 0 || Storage.FlushStale)
+ {
+ return;
+ }
+
// There is a small gap here where the action is removed but _actionRegistered is still 1.
// In this case it will skip registering the action, but here we are already handling it,
// so there shouldn't be any issue as it's the same handler for all actions.