From 4c727d0ba82012436dfd4eb1572db5e0882b2766 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Thu, 31 May 2018 22:57:32 -0400
Subject: [PATCH] gl_shader_decompiler: Support multi-destination for TEXS.

---
 src/video_core/engines/shader_bytecode.h      |  5 +++++
 .../renderer_opengl/gl_shader_decompiler.cpp  | 20 +++++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index f32a170571..79adcc5350 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -261,6 +261,11 @@ union Instruction {
         BitField<50, 1, u64> saturate_a;
     } conversion;
 
+    union {
+        // TODO(bunnei): This is just a guess, needs to be verified
+        BitField<52, 1, u64> enable_g_component;
+    } texs;
+
     BitField<61, 1, u64> is_b_imm;
     BitField<60, 1, u64> is_b_gpr;
     BitField<59, 1, u64> is_c_gpr;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 68efe74b8a..f6a60c9204 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -903,9 +903,25 @@ private:
                 ++shader.scope;
                 shader.AddLine(coord);
                 const std::string texture = "texture(" + sampler + ", coords)";
-                for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
-                    regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, elem);
+
+                // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA goes
+                // into gpr28+0 and gpr28+1
+                size_t offset{};
+                for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
+                    for (unsigned elem = 0; elem < 2; ++elem) {
+                        if (dest + elem >= Register::ZeroIndex) {
+                            // Skip invalid register values
+                            break;
+                        }
+                        regs.SetRegisterToFloat(dest, elem + offset, texture, 1, 4, false, elem);
+                        if (!instr.texs.enable_g_component) {
+                            // Skip the second component
+                            break;
+                        }
+                    }
+                    offset += 2;
                 }
+
                 --shader.scope;
                 shader.AddLine("}");
                 break;
-- 
GitLab