diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 62 |
1 files changed, 58 insertions, 4 deletions
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 /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> /// <param name="colorState">Color buffer texture to find or create</param> /// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param> + /// <param name="discard">Indicates that the sizeHint region's data will be overwritten</param> /// <param name="samplesInX">Number of samples in the X direction, for MSAA</param> /// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param> /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> @@ -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 /// <param name="dsState">Depth-stencil buffer texture to find or create</param> /// <param name="size">Size of the depth-stencil texture</param> /// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param> + /// <param name="discard">Indicates that the sizeHint region's data will be overwritten</param> /// <param name="samplesInX">Number of samples in the X direction, for MSAA</param> /// <param name="samplesInY">Number of samples in the Y direction, for MSAA</param> /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> @@ -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(); @@ -501,12 +519,44 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Determines if texture data should be fully discarded + /// based on the size hint region and whether it is set to be discarded. + /// </summary> + /// <param name="discard">Whether the size hint region should be discarded</param> + /// <param name="texture">The texture being discarded</param> + /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> + /// <returns>True if the data should be discarded, false otherwise</returns> + 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; + } + + /// <summary> + /// Discards texture data if requested and possible. + /// </summary> + /// <param name="discard">Whether the size hint region should be discarded</param> + /// <param name="texture">The texture being discarded</param> + /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> + private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHint) + { + if (ShouldDiscard(discard, texture, sizeHint)) + { + texture.DiscardData(); + } + } + + /// <summary> /// Tries to find an existing texture, or create a new one if not found. /// </summary> /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> /// <param name="flags">The texture search flags, defines texture comparison rules</param> /// <param name="info">Texture information of the texture to be found or created</param> /// <param name="layerSize">Size in bytes of a single texture layer</param> + /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param> /// <param name="range">Optional ranges of physical memory where the texture data is located</param> /// <returns>The texture</returns> 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(); |