From f6c3f1cdfdb9145634be3bfc54400f0d408f36dd Mon Sep 17 00:00:00 2001 From: riperiperi Date: Mon, 25 Sep 2023 22:07:03 +0100 Subject: GPU: Discard data when getting texture before full clear (#5719) * GPU: Discard data when getting texture before full clear * Fix rules and order of clear checks * Fix formatting --- src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 62 ++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs') diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index 3f215a4a..55000ac6 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -311,7 +311,7 @@ namespace Ryujinx.Graphics.Gpu.Image flags |= TextureSearchFlags.NoCreate; } - Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0); + Texture texture = FindOrCreateTexture(memoryManager, flags, info, 0, sizeHint: sizeHint); texture?.SynchronizeMemory(); @@ -324,6 +324,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// GPU memory manager where the texture is mapped /// Color buffer texture to find or create /// Indicates if the texture might be accessed with a non-zero layer index + /// Indicates that the sizeHint region's data will be overwritten /// Number of samples in the X direction, for MSAA /// Number of samples in the Y direction, for MSAA /// A hint indicating the minimum used size for the texture @@ -332,6 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Image MemoryManager memoryManager, RtColorState colorState, bool layered, + bool discard, int samplesInX, int samplesInY, Size sizeHint) @@ -398,7 +400,14 @@ namespace Ryujinx.Graphics.Gpu.Image int layerSize = !isLinear ? colorState.LayerSize * 4 : 0; - Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, layerSize); + var flags = TextureSearchFlags.WithUpscale; + + if (discard) + { + flags |= TextureSearchFlags.DiscardData; + } + + Texture texture = FindOrCreateTexture(memoryManager, flags, info, layerSize, sizeHint: sizeHint); texture?.SynchronizeMemory(); @@ -412,6 +421,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// Depth-stencil buffer texture to find or create /// Size of the depth-stencil texture /// Indicates if the texture might be accessed with a non-zero layer index + /// Indicates that the sizeHint region's data will be overwritten /// Number of samples in the X direction, for MSAA /// Number of samples in the Y direction, for MSAA /// A hint indicating the minimum used size for the texture @@ -421,6 +431,7 @@ namespace Ryujinx.Graphics.Gpu.Image RtDepthStencilState dsState, Size3D size, bool layered, + bool discard, int samplesInX, int samplesInY, Size sizeHint) @@ -465,7 +476,14 @@ namespace Ryujinx.Graphics.Gpu.Image target, formatInfo); - Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.WithUpscale, info, dsState.LayerSize * 4); + var flags = TextureSearchFlags.WithUpscale; + + if (discard) + { + flags |= TextureSearchFlags.DiscardData; + } + + Texture texture = FindOrCreateTexture(memoryManager, flags, info, dsState.LayerSize * 4, sizeHint: sizeHint); texture?.SynchronizeMemory(); @@ -500,6 +518,37 @@ namespace Ryujinx.Graphics.Gpu.Image return Math.Clamp(widthAligned - alignment + 1, minimumWidth, widthAligned); } + /// + /// Determines if texture data should be fully discarded + /// based on the size hint region and whether it is set to be discarded. + /// + /// Whether the size hint region should be discarded + /// The texture being discarded + /// A hint indicating the minimum used size for the texture + /// True if the data should be discarded, false otherwise + private static bool ShouldDiscard(bool discard, Texture texture, Size? sizeHint) + { + return discard && + texture.Info.DepthOrLayers == 1 && + sizeHint != null && + texture.Width <= sizeHint.Value.Width && + texture.Height <= sizeHint.Value.Height; + } + + /// + /// Discards texture data if requested and possible. + /// + /// Whether the size hint region should be discarded + /// The texture being discarded + /// A hint indicating the minimum used size for the texture + private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHint) + { + if (ShouldDiscard(discard, texture, sizeHint)) + { + texture.DiscardData(); + } + } + /// /// Tries to find an existing texture, or create a new one if not found. /// @@ -507,6 +556,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The texture search flags, defines texture comparison rules /// Texture information of the texture to be found or created /// Size in bytes of a single texture layer + /// A hint indicating the minimum used size for the texture /// Optional ranges of physical memory where the texture data is located /// The texture public Texture FindOrCreateTexture( @@ -514,9 +564,11 @@ namespace Ryujinx.Graphics.Gpu.Image TextureSearchFlags flags, TextureInfo info, int layerSize = 0, + Size? sizeHint = null, MultiRange? range = null) { bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0; + bool discard = (flags & TextureSearchFlags.DiscardData) != 0; TextureScaleMode scaleMode = IsUpscaleCompatible(info, (flags & TextureSearchFlags.WithUpscale) != 0); @@ -612,6 +664,8 @@ namespace Ryujinx.Graphics.Gpu.Image if (texture != null) { + DiscardIfNeeded(discard, texture, sizeHint); + texture.SynchronizeMemory(); return texture; @@ -907,7 +961,7 @@ namespace Ryujinx.Graphics.Gpu.Image // We need to synchronize before copying the old view data to the texture, // otherwise the copied data would be overwritten by a future synchronization. - texture.InitializeData(false, setData); + texture.InitializeData(false, setData && !ShouldDiscard(discard, texture, sizeHint)); texture.Group.InitializeOverlaps(); -- cgit v1.2.3