diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 32 | ||||
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 7 | ||||
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 5 |
3 files changed, 42 insertions, 2 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 0a083ebc..c9c3c59a 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -9,6 +9,7 @@ using Ryujinx.Memory.Range; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace Ryujinx.Graphics.Gpu.Image { @@ -1296,6 +1297,37 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Determine if any of this texture's data overlaps with another. + /// </summary> + /// <param name="texture">The texture to check against</param> + /// <returns>True if any slice of the textures overlap, false otherwise</returns> + public bool DataOverlaps(Texture texture) + { + if (texture._sizeInfo.AllOffsets.Length == 1 && _sizeInfo.AllOffsets.Length == 1) + { + return Range.OverlapsWith(texture.Range); + } + + MultiRange otherRange = texture.Range; + + IEnumerable<MultiRange> regions = _sizeInfo.AllRegions().Select((region) => Range.GetSlice((ulong)region.Offset, (ulong)region.Size)); + IEnumerable<MultiRange> otherRegions = texture._sizeInfo.AllRegions().Select((region) => otherRange.GetSlice((ulong)region.Offset, (ulong)region.Size)); + + foreach (MultiRange region in regions) + { + foreach (MultiRange otherRegion in otherRegions) + { + if (region.OverlapsWith(otherRegion)) + { + return true; + } + } + } + + return false; + } + + /// <summary> /// Increments the texture reference count. /// </summary> public void IncrementReferenceCount() diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index 37682b65..44c974e8 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -636,6 +636,13 @@ namespace Ryujinx.Graphics.Gpu.Image continue; } + if (!texture.DataOverlaps(overlap)) + { + // Allow textures to overlap if their data does not actually overlap. + // This typically happens when mip level subranges of a layered texture are used. (each texture fills the gaps of the others) + continue; + } + // The overlap texture is going to contain garbage data after we draw, or is generally incompatible. // If the texture cannot be entirely contained in the new address space, and one of its view children is compatible with us, // it must be flushed before removal, so that the data is not lost. diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index bcce443c..5b5c5ab0 100644 --- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -85,8 +85,9 @@ namespace Ryujinx.Graphics.Gpu.Image TextureDescriptor descriptor = GetDescriptor(id); - int width = descriptor.UnpackWidth(); - int height = descriptor.UnpackHeight(); + int baseLevel = descriptor.UnpackBaseLevel(); + int width = Math.Max(1, descriptor.UnpackWidth() >> baseLevel); + int height = Math.Max(1, descriptor.UnpackHeight() >> baseLevel); if (texture.Info.Width != width || texture.Info.Height != height) { |