From a2a97e1b11d38b51231e05a1da5202481cdf4df8 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Tue, 3 Oct 2023 19:43:11 -0300
Subject: Implement textureSamples texture query shader instruction (#5750)

* Implement textureSamples texture query shader instruction

* Shader cache version bump
---
 .../Shader/DiskCache/DiskCacheHostStorage.cs       |  2 +-
 .../CodeGen/Glsl/Instructions/InstGen.cs           |  7 +-
 .../CodeGen/Glsl/Instructions/InstGenHelper.cs     |  3 +-
 .../CodeGen/Glsl/Instructions/InstGenMemory.cs     | 28 +++++++-
 .../CodeGen/Spirv/Instructions.cs                  | 34 ++++++++-
 .../Instructions/InstEmitTexture.cs                | 83 +++++++++++++++++-----
 .../IntermediateRepresentation/Instruction.cs      |  7 +-
 .../StructuredIr/InstructionInfo.cs                |  3 +-
 .../Translation/EmitterContextInsts.cs             | 18 ++++-
 .../Optimizations/BindlessElimination.cs           |  7 +-
 .../Translation/ResourceManager.cs                 |  4 +-
 .../Translation/Transforms/TexturePass.cs          | 48 ++++++++-----
 12 files changed, 186 insertions(+), 58 deletions(-)

(limited to 'src')

diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index b46ceb4f..1420096e 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
         private const ushort FileFormatVersionMajor = 1;
         private const ushort FileFormatVersionMinor = 2;
         private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
-        private const uint CodeGenVersion = 5682;
+        private const uint CodeGenVersion = 5750;
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index 796eb441..6b02f2bf 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -184,8 +184,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
                     case Instruction.TextureSample:
                         return TextureSample(context, operation);
 
-                    case Instruction.TextureSize:
-                        return TextureSize(context, operation);
+                    case Instruction.TextureQuerySamples:
+                        return TextureQuerySamples(context, operation);
+
+                    case Instruction.TextureQuerySize:
+                        return TextureQuerySize(context, operation);
 
                     case Instruction.UnpackDouble2x32:
                         return UnpackDouble2x32(context, operation);
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index eb194c20..5c2d16f4 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -118,7 +118,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
             Add(Instruction.Subtract,                 InstType.OpBinary,       "-",               2);
             Add(Instruction.SwizzleAdd,               InstType.CallTernary,    HelperFunctionNames.SwizzleAdd);
             Add(Instruction.TextureSample,            InstType.Special);
-            Add(Instruction.TextureSize,              InstType.Special);
+            Add(Instruction.TextureQuerySamples,      InstType.Special);
+            Add(Instruction.TextureQuerySize,         InstType.Special);
             Add(Instruction.Truncate,                 InstType.CallUnary,      "trunc");
             Add(Instruction.UnpackDouble2x32,         InstType.Special);
             Add(Instruction.UnpackHalf2x16,           InstType.Special);
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index a1f92d11..7510e887 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -517,7 +517,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
             return texCall;
         }
 
-        public static string TextureSize(CodeGenContext context, AstOperation operation)
+        public static string TextureQuerySamples(CodeGenContext context, AstOperation operation)
+        {
+            AstTextureOperation texOp = (AstTextureOperation)operation;
+
+            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
+
+            // TODO: Bindless texture support. For now we just return 0.
+            if (isBindless)
+            {
+                return NumberFormatter.FormatInt(0);
+            }
+
+            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
+
+            string indexExpr = null;
+
+            if (isIndexed)
+            {
+                indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
+            }
+
+            string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
+
+            return $"textureSamples({samplerName})";
+        }
+
+        public static string TextureQuerySize(CodeGenContext context, AstOperation operation)
         {
             AstTextureOperation texOp = (AstTextureOperation)operation;
 
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
index 719ccf0c..771723c2 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
@@ -134,7 +134,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             Add(Instruction.Subtract,                 GenerateSubtract);
             Add(Instruction.SwizzleAdd,               GenerateSwizzleAdd);
             Add(Instruction.TextureSample,            GenerateTextureSample);
-            Add(Instruction.TextureSize,              GenerateTextureSize);
+            Add(Instruction.TextureQuerySamples,      GenerateTextureQuerySamples);
+            Add(Instruction.TextureQuerySize,         GenerateTextureQuerySize);
             Add(Instruction.Truncate,                 GenerateTruncate);
             Add(Instruction.UnpackDouble2x32,         GenerateUnpackDouble2x32);
             Add(Instruction.UnpackHalf2x16,           GenerateUnpackHalf2x16);
@@ -1492,7 +1493,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             return new OperationResult(swizzledResultType, result);
         }
 
-        private static OperationResult GenerateTextureSize(CodeGenContext context, AstOperation operation)
+        private static OperationResult GenerateTextureQuerySamples(CodeGenContext context, AstOperation operation)
+        {
+            AstTextureOperation texOp = (AstTextureOperation)operation;
+
+            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
+
+            // TODO: Bindless texture support. For now we just return 0.
+            if (isBindless)
+            {
+                return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
+            }
+
+            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
+
+            if (isIndexed)
+            {
+                context.GetS32(texOp.GetSource(0));
+            }
+
+            (var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
+
+            var image = context.Load(sampledImageType, sampledImageVariable);
+            image = context.Image(imageType, image);
+
+            SpvInstruction result = context.ImageQuerySamples(context.TypeS32(), image);
+
+            return new OperationResult(AggregateType.S32, result);
+        }
+
+        private static OperationResult GenerateTextureQuerySize(CodeGenContext context, AstOperation operation)
         {
             AstTextureOperation texOp = (AstTextureOperation)operation;
 
diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index bbac8038..5a231079 100644
--- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -1094,7 +1094,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
 
             if (isBindless)
             {
-                type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
+                if (query == TexQuery.TexHeaderTextureType)
+                {
+                    type = SamplerType.Texture2D | SamplerType.Multisample;
+                }
+                else
+                {
+                    type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
+                }
             }
             else
             {
@@ -1102,31 +1109,69 @@ namespace Ryujinx.Graphics.Shader.Instructions
             }
 
             TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
+            int binding;
 
-            int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
-                Instruction.TextureSize,
-                type,
-                TextureFormat.Unknown,
-                flags,
-                TextureOperation.DefaultCbufSlot,
-                imm);
-
-            for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
+            switch (query)
             {
-                if ((compMask & 1) != 0)
-                {
-                    Operand d = GetDest();
+                case TexQuery.TexHeaderDimension:
+                    binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
+                        Instruction.TextureQuerySize,
+                        type,
+                        TextureFormat.Unknown,
+                        flags,
+                        TextureOperation.DefaultCbufSlot,
+                        imm);
 
-                    if (d == null)
+                    for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                     {
-                        break;
+                        if ((compMask & 1) != 0)
+                        {
+                            Operand d = GetDest();
+
+                            if (d == null)
+                            {
+                                break;
+                            }
+
+                            context.Copy(d, context.TextureQuerySize(type, flags, binding, compIndex, sources));
+                        }
                     }
+                    break;
 
-                    // TODO: Validate and use query parameter.
-                    Operand res = context.TextureSize(type, flags, binding, compIndex, sources);
+                case TexQuery.TexHeaderTextureType:
+                    binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
+                        Instruction.TextureQuerySamples,
+                        type,
+                        TextureFormat.Unknown,
+                        flags,
+                        TextureOperation.DefaultCbufSlot,
+                        imm);
 
-                    context.Copy(d, res);
-                }
+                    if ((componentMask & 4) != 0)
+                    {
+                        // Skip first 2 components if necessary.
+                        if ((componentMask & 1) != 0)
+                        {
+                            GetDest();
+                        }
+
+                        if ((componentMask & 2) != 0)
+                        {
+                            GetDest();
+                        }
+
+                        Operand d = GetDest();
+
+                        if (d != null)
+                        {
+                            context.Copy(d, context.TextureQuerySamples(type, flags, binding, sources));
+                        }
+                    }
+                    break;
+
+                default:
+                    context.TranslatorContext.GpuAccessor.Log($"Invalid or unsupported query type \"{query}\".");
+                    break;
             }
         }
 
diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
index 808cc7ed..e5695ebc 100644
--- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
+++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs
@@ -1,10 +1,8 @@
 using System;
-using System.Diagnostics.CodeAnalysis;
 
 namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
 {
     [Flags]
-    [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
     enum Instruction
     {
         Absolute = 1,
@@ -118,7 +116,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
         Subtract,
         SwizzleAdd,
         TextureSample,
-        TextureSize,
+        TextureQuerySamples,
+        TextureQuerySize,
         Truncate,
         UnpackDouble2x32,
         UnpackHalf2x16,
@@ -160,7 +159,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
         public static bool IsTextureQuery(this Instruction inst)
         {
             inst &= Instruction.Mask;
-            return inst == Instruction.Lod || inst == Instruction.TextureSize;
+            return inst == Instruction.Lod || inst == Instruction.TextureQuerySamples || inst == Instruction.TextureQuerySize;
         }
     }
 }
diff --git a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs
index 1169512e..72d0e989 100644
--- a/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs
+++ b/src/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs
@@ -124,7 +124,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
             Add(Instruction.Subtract,                 AggregateType.Scalar, AggregateType.Scalar,  AggregateType.Scalar);
             Add(Instruction.SwizzleAdd,               AggregateType.FP32,   AggregateType.FP32,    AggregateType.FP32,    AggregateType.S32);
             Add(Instruction.TextureSample,            AggregateType.FP32);
-            Add(Instruction.TextureSize,              AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
+            Add(Instruction.TextureQuerySamples,      AggregateType.S32,    AggregateType.S32);
+            Add(Instruction.TextureQuerySize,         AggregateType.S32,    AggregateType.S32,     AggregateType.S32);
             Add(Instruction.Truncate,                 AggregateType.Scalar, AggregateType.Scalar);
             Add(Instruction.UnpackDouble2x32,         AggregateType.U32,    AggregateType.FP64);
             Add(Instruction.UnpackHalf2x16,           AggregateType.FP32,   AggregateType.U32);
diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
index afa830de..9e314c62 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs
@@ -897,7 +897,21 @@ namespace Ryujinx.Graphics.Shader.Translation
             context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
         }
 
-        public static Operand TextureSize(
+        public static Operand TextureQuerySamples(
+            this EmitterContext context,
+            SamplerType type,
+            TextureFlags flags,
+            int binding,
+            Operand[] sources)
+        {
+            Operand dest = Local();
+
+            context.Add(new TextureOperation(Instruction.TextureQuerySamples, type, TextureFormat.Unknown, flags, binding, 0, new[] { dest }, sources));
+
+            return dest;
+        }
+
+        public static Operand TextureQuerySize(
             this EmitterContext context,
             SamplerType type,
             TextureFlags flags,
@@ -907,7 +921,7 @@ namespace Ryujinx.Graphics.Shader.Translation
         {
             Operand dest = Local();
 
-            context.Add(new TextureOperation(Instruction.TextureSize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
+            context.Add(new TextureOperation(Instruction.TextureQuerySize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
 
             return dest;
         }
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
index 43d98d3c..19b7999a 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
@@ -27,9 +27,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
                     continue;
                 }
 
-                if (texOp.Inst == Instruction.Lod ||
-                    texOp.Inst == Instruction.TextureSample ||
-                    texOp.Inst == Instruction.TextureSize)
+                if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
                 {
                     Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
 
@@ -40,7 +38,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
                     // as long bindless elimination is successful and we know where the texture descriptor is located.
                     bool rewriteSamplerType =
                         texOp.Type == SamplerType.TextureBuffer ||
-                        texOp.Inst == Instruction.TextureSize;
+                        texOp.Inst == Instruction.TextureQuerySamples ||
+                        texOp.Inst == Instruction.TextureQuerySize;
 
                     if (bindlessHandle.Type == OperandType.ConstantBuffer)
                     {
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
index 9c487c46..83332711 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs
@@ -232,8 +232,8 @@ namespace Ryujinx.Graphics.Shader.Translation
             inst &= Instruction.Mask;
             bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
             bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
-            bool accurateType = inst != Instruction.Lod && inst != Instruction.TextureSize;
-            bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
+            bool accurateType = !inst.IsTextureQuery();
+            bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureQuerySize;
             bool coherent = flags.HasFlag(TextureFlags.Coherent);
 
             if (!isImage)
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs
index 2479d85f..dbfe6269 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Transforms/TexturePass.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
                 {
                     node = InsertCoordNormalization(context.Hfm, node, context.ResourceManager, context.GpuAccessor, context.Stage);
                     node = InsertCoordGatherBias(node, context.ResourceManager, context.GpuAccessor);
-                    node = InsertConstOffsets(node, context.ResourceManager, context.GpuAccessor);
+                    node = InsertConstOffsets(node, context.GpuAccessor, context.Stage);
 
                     if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
                     {
@@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
             bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
             bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
 
-            if (texOp.Inst == Instruction.TextureSize &&
+            if (texOp.Inst == Instruction.TextureQuerySize &&
                 texOp.Index < 2 &&
                 !isBindless &&
                 !isIndexed &&
@@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
                 }
 
                 LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
-                    Instruction.TextureSize,
+                    Instruction.TextureQuerySize,
                     texOp.Type,
                     texOp.Format,
                     texOp.Flags,
@@ -259,7 +259,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
                 }
 
                 node.List.AddBefore(node, new TextureOperation(
-                    Instruction.TextureSize,
+                    Instruction.TextureQuerySize,
                     texOp.Type,
                     texOp.Format,
                     texOp.Flags,
@@ -287,7 +287,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
             return node;
         }
 
-        private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, ResourceManager resourceManager, IGpuAccessor gpuAccessor)
+        private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, IGpuAccessor gpuAccessor, ShaderStage stage)
         {
             // Non-constant texture offsets are not allowed (according to the spec),
             // however some GPUs does support that.
@@ -440,7 +440,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
 
                 sources.CopyTo(newSources, 0);
 
-                Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
+                Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
 
                 int destIndex = 0;
 
@@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
                 }
                 else
                 {
-                    Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
+                    Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
 
                     for (int index = 0; index < coordsCount; index++)
                     {
@@ -554,21 +554,31 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
             TextureOperation texOp,
             Operand[] lodSources,
             Operand bindlessHandle,
-            int coordsCount)
+            int coordsCount,
+            ShaderStage stage)
         {
             Operand[] texSizes = new Operand[coordsCount];
 
-            Operand lod = Local();
+            Operand lod;
+
+            if (stage == ShaderStage.Fragment)
+            {
+                lod = Local();
 
-            node.List.AddBefore(node, new TextureOperation(
-                Instruction.Lod,
-                texOp.Type,
-                texOp.Format,
-                texOp.Flags,
-                texOp.Binding,
-                0,
-                new[] { lod },
-                lodSources));
+                node.List.AddBefore(node, new TextureOperation(
+                    Instruction.Lod,
+                    texOp.Type,
+                    texOp.Format,
+                    texOp.Flags,
+                    texOp.Binding,
+                    0,
+                    new[] { lod },
+                    lodSources));
+            }
+            else
+            {
+                lod = Const(0);
+            }
 
             for (int index = 0; index < coordsCount; index++)
             {
@@ -586,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
                 }
 
                 node.List.AddBefore(node, new TextureOperation(
-                    Instruction.TextureSize,
+                    Instruction.TextureQuerySize,
                     texOp.Type,
                     texOp.Format,
                     texOp.Flags,
-- 
cgit v1.2.3-70-g09d2