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
///
public bool IsDisposed { get; private set; }
+ ///
+ /// True if the sampler has sRGB conversion enabled, false otherwise.
+ ///
+ public bool IsSrgb { get; }
+
///
/// Host sampler object.
///
@@ -30,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// The Maxwell sampler descriptor
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);
}
+ ///
+ /// Unpacks the sampler sRGB format flag.
+ ///
+ /// True if the has sampler is sRGB conversion enabled, false otherwise
+ public readonly bool UnpackSrgb()
+ {
+ return (Word0 & (1 << 13)) != 0;
+ }
+
///
/// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
///
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);
}
///
@@ -508,12 +510,12 @@ 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);
+
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, sampler?.IsSrgb ?? true, out Texture texture);
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
- Sampler sampler = samplerPool?.Get(samplerId);
-
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
/// ID of the texture. This is effectively a zero-based index
/// The texture with the given ID
public override Texture Get(int id)
+ {
+ return Get(id, srgbSampler: true);
+ }
+
+ ///
+ /// Gets the texture with the given ID.
+ ///
+ /// ID of the texture. This is effectively a zero-based index
+ /// Whether the texture is being accessed with a sampler that has sRGB conversion enabled
+ /// The texture with the given ID
+ 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.
///
/// ID of the texture. This is effectively a zero-based index
+ /// Whether the texture is being accessed with a sampler that has sRGB conversion enabled
/// The texture with the given ID
/// The texture descriptor with the given ID
- 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);
}