diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 363f0f73a7..b784a5455f 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -360,7 +360,7 @@ namespace Ryujinx.Graphics.Gpu.Image
texture._viewStorage = this;
- Group.UpdateViews(_views);
+ Group.UpdateViews(_views, texture);
if (texture.Group != null && texture.Group != Group)
{
@@ -384,6 +384,8 @@ namespace Ryujinx.Graphics.Gpu.Image
{
_views.Remove(texture);
+ Group.RemoveView(texture);
+
texture._viewStorage = texture;
DecrementReferenceCount();
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
index d9b620aae5..b59a9d0860 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs
@@ -989,7 +989,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Update the views in this texture group, rebuilding the memory tracking if required.
///
/// The views list of the storage texture
- public void UpdateViews(List views)
+ /// The texture that has been added, if that is the only change, otherwise null
+ public void UpdateViews(List views, Texture texture)
{
// This is saved to calculate overlapping views for each handle.
_views = views;
@@ -1027,17 +1028,44 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!regionsRebuilt)
{
- // Must update the overlapping views on all handles, but only if they were not just recreated.
-
- foreach (TextureGroupHandle handle in _handles)
+ if (texture != null)
{
- handle.RecalculateOverlaps(this, views);
+ int offset = FindOffset(texture);
+
+ foreach (TextureGroupHandle handle in _handles)
+ {
+ handle.AddOverlap(offset, texture);
+ }
+ }
+ else
+ {
+ // Must update the overlapping views on all handles, but only if they were not just recreated.
+
+ foreach (TextureGroupHandle handle in _handles)
+ {
+ handle.RecalculateOverlaps(this, views);
+ }
}
}
SignalAllDirty();
}
+
+ ///
+ /// Removes a view from the group, removing it from all overlap lists.
+ ///
+ /// View to remove from the group
+ public void RemoveView(Texture view)
+ {
+ int offset = FindOffset(view);
+
+ foreach (TextureGroupHandle handle in _handles)
+ {
+ handle.RemoveOverlap(offset, view);
+ }
+ }
+
///
/// Inherit handle state from an old set of handles, such as modified and dirty flags.
///
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs
index 1b83cb5589..ebb4e9aebe 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs
@@ -159,6 +159,42 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Adds a single texture view as an overlap if its range overlaps.
+ ///
+ /// The offset of the view in the group
+ /// The texture to add as an overlap
+ public void AddOverlap(int offset, Texture view)
+ {
+ // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic.
+
+ if (OverlapsWith(offset, (int)view.Size))
+ {
+ lock (Overlaps)
+ {
+ Overlaps.Add(view);
+ }
+ }
+ }
+
+ ///
+ /// Removes a single texture view as an overlap if its range overlaps.
+ ///
+ /// The offset of the view in the group
+ /// The texture to add as an overlap
+ public void RemoveOverlap(int offset, Texture view)
+ {
+ // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic.
+
+ if (OverlapsWith(offset, (int)view.Size))
+ {
+ lock (Overlaps)
+ {
+ Overlaps.Remove(view);
+ }
+ }
+ }
+
///
/// Registers a sync action to happen for this handle, and an interim flush action on the tracking handle.
///