diff options
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 4 | ||||
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureGroup.cs | 36 | ||||
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs | 36 |
3 files changed, 71 insertions, 5 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 363f0f73..b784a545 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 d9b620aa..b59a9d08 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. /// </summary> /// <param name="views">The views list of the storage texture</param> - public void UpdateViews(List<Texture> views) + /// <param name="texture">The texture that has been added, if that is the only change, otherwise null</param> + public void UpdateViews(List<Texture> 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. + if (texture != null) + { + int offset = FindOffset(texture); - foreach (TextureGroupHandle handle in _handles) + foreach (TextureGroupHandle handle in _handles) + { + handle.AddOverlap(offset, texture); + } + } + else { - handle.RecalculateOverlaps(this, views); + // 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(); } + + /// <summary> + /// Removes a view from the group, removing it from all overlap lists. + /// </summary> + /// <param name="view">View to remove from the group</param> + public void RemoveView(Texture view) + { + int offset = FindOffset(view); + + foreach (TextureGroupHandle handle in _handles) + { + handle.RemoveOverlap(offset, view); + } + } + /// <summary> /// Inherit handle state from an old set of handles, such as modified and dirty flags. /// </summary> diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs index 1b83cb55..ebb4e9ae 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs @@ -160,6 +160,42 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Adds a single texture view as an overlap if its range overlaps. + /// </summary> + /// <param name="offset">The offset of the view in the group</param> + /// <param name="view">The texture to add as an overlap</param> + 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); + } + } + } + + /// <summary> + /// Removes a single texture view as an overlap if its range overlaps. + /// </summary> + /// <param name="offset">The offset of the view in the group</param> + /// <param name="view">The texture to add as an overlap</param> + 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); + } + } + } + + /// <summary> /// Registers a sync action to happen for this handle, and an interim flush action on the tracking handle. /// </summary> /// <param name="context">The GPU context to register a sync action on</param> |