From e63157cc3355489fa35b952ebd7bb769f6a29ff7 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Tue, 26 Sep 2023 16:37:10 +0100 Subject: [PATCH] GPU: Don't create tracking handles for buffer textures (#5727) * GPU: Don't create tracking handles for buffer textures Buffer texture memory is handled by the buffer cache - the texture shouldn't create any tracking handles as they aren't used. This change simply makes them create and iterate 0 tracking handles, while keeping the rest of the texture group around. This prevents a possible issue where many buffer textures are created as views of overlapping buffer ranges, and virtual regions have many dependant textures that don't actually contribute anything to handle state. Should improve performance in Mortal Kombat 1, possibly certain UE4 games when FIFO raises to 100%. * Fix interval tree bug * Don't check view compatibility for buffer textures --- src/ARMeilleure/Translation/IntervalTree.cs | 2 +- src/Ryujinx.Common/Collections/IntervalTree.cs | 2 +- src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 9 ++++++--- src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs | 14 ++++++++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/ARMeilleure/Translation/IntervalTree.cs b/src/ARMeilleure/Translation/IntervalTree.cs index afd89b930..da29d6a68 100644 --- a/src/ARMeilleure/Translation/IntervalTree.cs +++ b/src/ARMeilleure/Translation/IntervalTree.cs @@ -189,7 +189,7 @@ namespace ARMeilleure.Translation { if (start.CompareTo(node.End) < 0) { - if (overlaps.Length >= overlapCount) + if (overlaps.Length <= overlapCount) { Array.Resize(ref overlaps, overlapCount + ArrayGrowthSize); } diff --git a/src/Ryujinx.Common/Collections/IntervalTree.cs b/src/Ryujinx.Common/Collections/IntervalTree.cs index 2ea260a5f..baab579e7 100644 --- a/src/Ryujinx.Common/Collections/IntervalTree.cs +++ b/src/Ryujinx.Common/Collections/IntervalTree.cs @@ -192,7 +192,7 @@ namespace Ryujinx.Common.Collections { if (start.CompareTo(overlap.End) < 0) { - if (overlaps.Length >= overlapCount) + if (overlaps.Length <= overlapCount) { Array.Resize(ref overlaps, overlapCount + ArrayGrowthSize); } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index 55000ac6e..5048ccca4 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -696,11 +696,14 @@ namespace Ryujinx.Graphics.Gpu.Image } // Find view compatible matches. - int overlapsCount; + int overlapsCount = 0; - lock (_textures) + if (info.Target != Target.TextureBuffer) { - overlapsCount = _textures.FindOverlaps(range.Value, ref _textureOverlaps); + lock (_textures) + { + overlapsCount = _textures.FindOverlaps(range.Value, ref _textureOverlaps); + } } if (_overlapInfo.Length != _textureOverlaps.Length) diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index be33247ce..746a95ffc 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -79,6 +79,7 @@ namespace Ryujinx.Graphics.Gpu.Image private int[] _allOffsets; private int[] _sliceSizes; private readonly bool _is3D; + private readonly bool _isBuffer; private bool _hasMipViews; private bool _hasLayerViews; private readonly int _layers; @@ -118,6 +119,7 @@ namespace Ryujinx.Graphics.Gpu.Image _physicalMemory = physicalMemory; _is3D = storage.Info.Target == Target.Texture3D; + _isBuffer = storage.Info.Target == Target.TextureBuffer; _layers = storage.Info.GetSlices(); _levels = storage.Info.Levels; @@ -794,7 +796,11 @@ namespace Ryujinx.Graphics.Gpu.Image int targetLayerHandles = _hasLayerViews ? slices : 1; int targetLevelHandles = _hasMipViews ? levels : 1; - if (_is3D) + if (_isBuffer) + { + return; + } + else if (_is3D) { // Future mip levels come after all layers of the last mip level. Each mipmap has less layers (depth) than the last. @@ -1327,7 +1333,11 @@ namespace Ryujinx.Graphics.Gpu.Image { TextureGroupHandle[] handles; - if (!(_hasMipViews || _hasLayerViews)) + if (_isBuffer) + { + handles = Array.Empty(); + } + else if (!(_hasMipViews || _hasLayerViews)) { // Single dirty region. var cpuRegionHandles = new RegionHandle[TextureRange.Count];