From 79b3243f54810eb7d449b739c8040af711c0a73c Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Mon, 31 May 2021 16:59:23 -0300
Subject: [PATCH] Do not attempt to normalize SNORM image buffers on shaders
 (#2317)

* Do not attempt to normalize SNORM image buffers on shaders

* Shader cache version bump
---
 .../Image/TextureBindingsManager.cs           |  2 +-
 Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs    |  2 +-
 .../Translation/Rewriter.cs                   | 32 ++++++++++++-------
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index ae610a7669..d86d12032a 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -365,7 +365,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                     }
 
                     _context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
-                } 
+                }
                 else if (isStore)
                 {
                     texture?.SignalModified();
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 9b5440fb22..6221524581 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// <summary>
         /// Version of the codegen (to be changed when codegen or guest format change).
         /// </summary>
-        private const ulong ShaderCodeGenVersion = 2301;
+        private const ulong ShaderCodeGenVersion = 2317;
 
         // Progress reporting helpers
         private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
index 07eeae4828..912d61f1a3 100644
--- a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
@@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Shader.Translation
 
                 for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
                 {
-                    if (!(node.Value is Operation operation))
+                    if (node.Value is not Operation operation)
                     {
                         continue;
                     }
@@ -33,11 +33,11 @@ namespace Ryujinx.Graphics.Shader.Translation
                         if (texOp.Inst == Instruction.TextureSample)
                         {
                             node = RewriteTextureSample(node, config);
-                        }
 
-                        if (texOp.Type == SamplerType.TextureBuffer)
-                        {
-                            node = InsertSnormNormalization(node, config);
+                            if (texOp.Type == SamplerType.TextureBuffer)
+                            {
+                                node = InsertSnormNormalization(node, config);
+                            }
                         }
                     }
                 }
@@ -147,14 +147,15 @@ namespace Ryujinx.Graphics.Shader.Translation
 
             bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QuerySupportsNonConstantTextureOffset();
 
-            bool isRect = config.GpuAccessor.QueryIsTextureRectangle(texOp.Handle, texOp.CbufSlot);
+            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
+
+            bool isRect = !isBindless && config.GpuAccessor.QueryIsTextureRectangle(texOp.Handle, texOp.CbufSlot);
 
             if (!(hasInvalidOffset || isRect))
             {
                 return node;
             }
-
-            bool isBindless     = (texOp.Flags & TextureFlags.Bindless)    != 0;
+            
             bool isGather       = (texOp.Flags & TextureFlags.Gather)      != 0;
             bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
             bool intCoords      = (texOp.Flags & TextureFlags.IntCoords)   != 0;
@@ -442,6 +443,13 @@ namespace Ryujinx.Graphics.Shader.Translation
         {
             TextureOperation texOp = (TextureOperation)node.Value;
 
+            // We can't query the format of a bindless texture,
+            // because the handle is unknown, it can have any format.
+            if (texOp.Flags.HasFlag(TextureFlags.Bindless))
+            {
+                return node;
+            }
+
             TextureFormat format = config.GpuAccessor.QueryTextureFormat(texOp.Handle, texOp.CbufSlot);
 
             int maxPositive = format switch
@@ -455,13 +463,15 @@ namespace Ryujinx.Graphics.Shader.Translation
                 _                               => 0
             };
 
-            // The value being 0 means that the format is not a SNORM format, so there's nothing to do here.
+            // The value being 0 means that the format is not a SNORM format,
+            // so there's nothing to do here.
             if (maxPositive == 0)
             {
                 return node;
             }
 
-            // Do normalization. We assume SINT formats are being used as replacement for SNORM (that is not supported).
+            // Do normalization. We assume SINT formats are being used
+            // as replacement for SNORM (which is not supported).
             INode[] uses = texOp.Dest.UseOps.ToArray();
 
             Operation convOp = new Operation(Instruction.ConvertS32ToFP, Local(), texOp.Dest);
@@ -472,7 +482,7 @@ namespace Ryujinx.Graphics.Shader.Translation
 
             foreach (INode useOp in uses)
             {
-                if (!(useOp is Operation op))
+                if (useOp is not Operation op)
                 {
                     continue;
                 }