From 5ca63d06757a92fdbd7d75d81f0c9ff1d7ab4e62 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Fri, 22 Feb 2019 03:30:12 -0300
Subject: [PATCH] shader/decode: Remove extras from MetaTexture

---
 src/video_core/engines/shader_bytecode.h      |  8 +--
 .../renderer_opengl/gl_shader_decompiler.cpp  | 56 ++++++++++++-------
 src/video_core/shader/decode/texture.cpp      | 37 +++++++-----
 src/video_core/shader/shader_ir.h             |  4 +-
 4 files changed, 65 insertions(+), 40 deletions(-)

diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d14cd5f20..f62ae8801 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -325,11 +325,11 @@ enum class TextureQueryType : u64 {
 
 enum class TextureProcessMode : u64 {
     None = 0,
-    LZ = 1,  // Unknown, appears to be the same as none.
+    LZ = 1,  // Load LOD of zero.
     LB = 2,  // Load Bias.
-    LL = 3,  // Load LOD (LevelOfDetail)
-    LBA = 6, // Load Bias. The A is unknown, does not appear to differ with LB
-    LLA = 7  // Load LOD. The A is unknown, does not appear to differ with LL
+    LL = 3,  // Load LOD.
+    LBA = 6, // Load Bias. The A is unknown, does not appear to differ with LB.
+    LLA = 7  // Load LOD. The A is unknown, does not appear to differ with LL.
 };
 
 enum class TextureMiscMode : u64 {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 72ff6ac6a..11d1169f0 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -5,7 +5,9 @@
 #include <array>
 #include <string>
 #include <string_view>
+#include <utility>
 #include <variant>
+#include <vector>
 
 #include <fmt/format.h>
 
@@ -717,7 +719,7 @@ private:
     }
 
     std::string GenerateTexture(Operation operation, const std::string& func,
-                                bool is_extra_int = false) {
+                                const std::vector<std::pair<Type, Node>>& extras) {
         constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
 
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
@@ -738,36 +740,47 @@ private:
             expr += Visit(operation[i]);
 
             const std::size_t next = i + 1;
-            if (next < count || has_array || has_shadow)
+            if (next < count)
                 expr += ", ";
         }
         if (has_array) {
-            expr += "float(ftoi(" + Visit(meta->array) + "))";
+            expr += ", float(ftoi(" + Visit(meta->array) + "))";
         }
         if (has_shadow) {
-            if (has_array)
-                expr += ", ";
-            expr += Visit(meta->depth_compare);
+            expr += ", " + Visit(meta->depth_compare);
         }
         expr += ')';
 
-        for (const Node extra : meta->extras) {
+        for (const auto& extra_pair : extras) {
+            const auto [type, operand] = extra_pair;
+            if (operand == nullptr) {
+                continue;
+            }
             expr += ", ";
-            if (is_extra_int) {
-                if (const auto immediate = std::get_if<ImmediateNode>(extra)) {
+
+            switch (type) {
+            case Type::Int:
+                if (const auto immediate = std::get_if<ImmediateNode>(operand)) {
                     // Inline the string as an immediate integer in GLSL (some extra arguments are
                     // required to be constant)
                     expr += std::to_string(static_cast<s32>(immediate->GetValue()));
                 } else {
-                    expr += "ftoi(" + Visit(extra) + ')';
+                    expr += "ftoi(" + Visit(operand) + ')';
                 }
-            } else {
-                expr += Visit(extra);
+                break;
+            case Type::Float:
+                expr += Visit(operand);
+                break;
+            default: {
+                const auto type_int = static_cast<u32>(type);
+                UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int);
+                expr += '0';
+                break;
+            }
             }
         }
 
-        expr += ')';
-        return expr;
+        return expr + ')';
     }
 
     std::string Assign(Operation operation) {
@@ -1146,7 +1159,7 @@ private:
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         ASSERT(meta);
 
-        std::string expr = GenerateTexture(operation, "texture");
+        std::string expr = GenerateTexture(operation, "texture", {{Type::Float, meta->bias}});
         if (meta->sampler.IsShadow()) {
             expr = "vec4(" + expr + ')';
         }
@@ -1157,7 +1170,7 @@ private:
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         ASSERT(meta);
 
-        std::string expr = GenerateTexture(operation, "textureLod");
+        std::string expr = GenerateTexture(operation, "textureLod", {{Type::Float, meta->lod}});
         if (meta->sampler.IsShadow()) {
             expr = "vec4(" + expr + ')';
         }
@@ -1168,7 +1181,8 @@ private:
         const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
         ASSERT(meta);
 
-        return GenerateTexture(operation, "textureGather", !meta->sampler.IsShadow()) +
+        const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
+        return GenerateTexture(operation, "textureGather", {{type, meta->component}}) +
                GetSwizzle(meta->element);
     }
 
@@ -1197,8 +1211,8 @@ private:
         ASSERT(meta);
 
         if (meta->element < 2) {
-            return "itof(int((" + GenerateTexture(operation, "textureQueryLod") + " * vec2(256))" +
-                   GetSwizzle(meta->element) + "))";
+            return "itof(int((" + GenerateTexture(operation, "textureQueryLod", {}) +
+                   " * vec2(256))" + GetSwizzle(meta->element) + "))";
         }
         return "0";
     }
@@ -1224,9 +1238,9 @@ private:
             else if (next < count)
                 expr += ", ";
         }
-        for (std::size_t i = 0; i < meta->extras.size(); ++i) {
+        if (meta->lod) {
             expr += ", ";
-            expr += CastOperand(Visit(meta->extras.at(i)), Type::Int);
+            expr += CastOperand(Visit(meta->lod), Type::Int);
         }
         expr += ')';
 
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 50e2d0584..a99ae19bf 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -119,8 +119,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
             coords.push_back(op_a);
             coords.push_back(op_b);
         }
-        std::vector<Node> extras;
-        extras.push_back(Immediate(static_cast<u32>(instr.tld4s.component)));
+        const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
 
         const auto& sampler =
             GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare);
@@ -128,7 +127,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
         Node4 values;
         for (u32 element = 0; element < values.size(); ++element) {
             auto coords_copy = coords;
-            MetaTexture meta{sampler, {}, {}, extras, element};
+            MetaTexture meta{sampler, {}, {}, {}, {}, component, element};
             values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
         }
 
@@ -153,7 +152,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
                 if (!instr.txq.IsComponentEnabled(element)) {
                     continue;
                 }
-                MetaTexture meta{sampler, {}, {}, {}, element};
+                MetaTexture meta{sampler, {}, {}, {}, {}, {}, element};
                 const Node value =
                     Operation(OperationCode::TextureQueryDimensions, meta, GetRegister(instr.gpr8));
                 SetTemporal(bb, indexer++, value);
@@ -203,7 +202,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
 
         for (u32 element = 0; element < 2; ++element) {
             auto params = coords;
-            MetaTexture meta{sampler, {}, {}, {}, element};
+            MetaTexture meta{sampler, {}, {}, {}, {}, {}, element};
             const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
             SetTemporal(bb, element, value);
         }
@@ -347,25 +346,35 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
           (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow));
 
     const OperationCode read_method =
-        lod_needed && gl_lod_supported ? OperationCode::TextureLod : OperationCode::Texture;
+        (lod_needed && gl_lod_supported) ? OperationCode::TextureLod : OperationCode::Texture;
 
     UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported);
 
-    std::vector<Node> extras;
+    Node bias = {};
+    Node lod = {};
     if (process_mode != TextureProcessMode::None && gl_lod_supported) {
-        if (process_mode == TextureProcessMode::LZ) {
-            extras.push_back(Immediate(0.0f));
-        } else {
+        switch (process_mode) {
+        case TextureProcessMode::LZ:
+            lod = Immediate(0.0f);
+            break;
+        case TextureProcessMode::LB:
             // If present, lod or bias are always stored in the register indexed by the gpr20
             // field with an offset depending on the usage of the other registers
-            extras.push_back(GetRegister(instr.gpr20.Value() + bias_offset));
+            bias = GetRegister(instr.gpr20.Value() + bias_offset);
+            break;
+        case TextureProcessMode::LL:
+            lod = GetRegister(instr.gpr20.Value() + bias_offset);
+            break;
+        default:
+            UNIMPLEMENTED_MSG("Unimplemented process mode={}", static_cast<u32>(process_mode));
+            break;
         }
     }
 
     Node4 values;
     for (u32 element = 0; element < values.size(); ++element) {
         auto copy_coords = coords;
-        MetaTexture meta{sampler, array, depth_compare, extras, element};
+        MetaTexture meta{sampler, array, depth_compare, bias, lod, {}, element};
         values[element] = Operation(read_method, meta, std::move(copy_coords));
     }
 
@@ -462,7 +471,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
     Node4 values;
     for (u32 element = 0; element < values.size(); ++element) {
         auto coords_copy = coords;
-        MetaTexture meta{sampler, GetRegister(array_register), {}, {}, element};
+        MetaTexture meta{sampler, GetRegister(array_register), {}, {}, {}, {}, element};
         values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
     }
 
@@ -498,7 +507,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
     Node4 values;
     for (u32 element = 0; element < values.size(); ++element) {
         auto coords_copy = coords;
-        MetaTexture meta{sampler, array, {}, {lod}, element};
+        MetaTexture meta{sampler, array, {}, {}, lod, {}, element};
         values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
     }
     return values;
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 0548c46f0..5bc3a3900 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -290,7 +290,9 @@ struct MetaTexture {
     const Sampler& sampler;
     Node array{};
     Node depth_compare{};
-    std::vector<Node> extras;
+    Node bias{};
+    Node lod{};
+    Node component{};
     u32 element{};
 };