From 24ee8c39f1fd8ae2dc2d92cda1cdb41e8af45f0a Mon Sep 17 00:00:00 2001 From: gdkchan <gab.dark.100@gmail.com> Date: Thu, 19 Sep 2024 14:38:30 -0300 Subject: Add support for sampler sRGB disable (#7312) --- src/Ryujinx.Graphics.Gpu/Image/Sampler.cs | 7 ++++++ .../Image/SamplerDescriptor.cs | 9 +++++++ .../Image/TextureBindingsManager.cs | 10 ++++---- src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 28 ++++++++++++++++++++-- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Image/Sampler.cs b/src/Ryujinx.Graphics.Gpu/Image/Sampler.cs index d6a3d975..b007c159 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Sampler.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Sampler.cs @@ -13,6 +13,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> public bool IsDisposed { get; private set; } + /// <summary> + /// True if the sampler has sRGB conversion enabled, false otherwise. + /// </summary> + public bool IsSrgb { get; } + /// <summary> /// Host sampler object. /// </summary> @@ -30,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="descriptor">The Maxwell sampler descriptor</param> public Sampler(GpuContext context, SamplerDescriptor descriptor) { + IsSrgb = descriptor.UnpackSrgb(); + MinFilter minFilter = descriptor.UnpackMinFilter(); MagFilter magFilter = descriptor.UnpackMagFilter(); diff --git a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs index e04c31df..836a3260 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs @@ -113,6 +113,15 @@ namespace Ryujinx.Graphics.Gpu.Image return (CompareOp)(((Word0 >> 10) & 7) + 1); } + /// <summary> + /// Unpacks the sampler sRGB format flag. + /// </summary> + /// <returns>True if the has sampler is sRGB conversion enabled, false otherwise</returns> + public readonly bool UnpackSrgb() + { + return (Word0 & (1 << 13)) != 0; + } + /// <summary> /// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering. /// </summary> diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index ad018f15..f96ddfb1 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -187,7 +187,9 @@ namespace Ryujinx.Graphics.Gpu.Image { (TexturePool texturePool, SamplerPool samplerPool) = GetPools(); - return (texturePool.Get(textureId), samplerPool.Get(samplerId)); + Sampler sampler = samplerPool?.Get(samplerId); + + return (texturePool.Get(textureId, sampler?.IsSrgb ?? true), sampler); } /// <summary> @@ -508,11 +510,11 @@ namespace Ryujinx.Graphics.Gpu.Image state.TextureHandle = textureId; state.SamplerHandle = samplerId; - ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, out Texture texture); + Sampler sampler = samplerPool?.Get(samplerId); - specStateMatches &= specState.MatchesTexture(stage, index, descriptor); + ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, sampler?.IsSrgb ?? true, out Texture texture); - Sampler sampler = samplerPool?.Get(samplerId); + specStateMatches &= specState.MatchesTexture(stage, index, descriptor); ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target); ISampler hostSampler = sampler?.GetHostSampler(texture); diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 5f43c182..be7cb0b8 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs @@ -227,6 +227,17 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="id">ID of the texture. This is effectively a zero-based index</param> /// <returns>The texture with the given ID</returns> public override Texture Get(int id) + { + return Get(id, srgbSampler: true); + } + + /// <summary> + /// Gets the texture with the given ID. + /// </summary> + /// <param name="id">ID of the texture. This is effectively a zero-based index</param> + /// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param> + /// <returns>The texture with the given ID</returns> + public Texture Get(int id, bool srgbSampler) { if ((uint)id >= Items.Length) { @@ -240,7 +251,7 @@ namespace Ryujinx.Graphics.Gpu.Image SynchronizeMemory(); } - GetInternal(id, out Texture texture); + GetForBinding(id, srgbSampler, out Texture texture); return texture; } @@ -252,9 +263,10 @@ namespace Ryujinx.Graphics.Gpu.Image /// This method assumes that the pool has been manually synchronized before doing binding. /// </remarks> /// <param name="id">ID of the texture. This is effectively a zero-based index</param> + /// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param> /// <param name="texture">The texture with the given ID</param> /// <returns>The texture descriptor with the given ID</returns> - public ref readonly TextureDescriptor GetForBinding(int id, out Texture texture) + public ref readonly TextureDescriptor GetForBinding(int id, bool srgbSampler, out Texture texture) { if ((uint)id >= Items.Length) { @@ -264,6 +276,18 @@ namespace Ryujinx.Graphics.Gpu.Image // When getting for binding, assume the pool has already been synchronized. + if (!srgbSampler) + { + // If the sampler does not have the sRGB bit enabled, then the texture can't use a sRGB format. + ref readonly TextureDescriptor tempDescriptor = ref GetDescriptorRef(id); + + if (tempDescriptor.UnpackSrgb() && FormatTable.TryGetTextureFormat(tempDescriptor.UnpackFormat(), isSrgb: false, out FormatInfo formatInfo)) + { + // Get a view of the texture with the right format. + return ref GetForBinding(id, formatInfo, out texture); + } + } + return ref GetInternal(id, out texture); } -- cgit v1.2.3-70-g09d2