From 0b668d5ff355c0ac2c33d40429e6cc6d872d0e4f Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Fri, 10 Aug 2018 12:34:51 -0400
Subject: [PATCH] gl_shader_decompiler: Improve handling of unknown
 input/output attributes.

---
 src/video_core/engines/shader_bytecode.h       |  3 +--
 .../renderer_opengl/gl_shader_decompiler.cpp   | 18 ++++++++++--------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 3e409c2e1..24396c6c9 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -74,12 +74,11 @@ union Attribute {
     enum class Index : u64 {
         Position = 7,
         Attribute_0 = 8,
+        Attribute_31 = 39,
         // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
         // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
         // shader.
         TessCoordInstanceIDVertexID = 47,
-        // TODO(bunnei): Figure out what this is used for. Super Mario Odyssey uses this.
-        Unknown_63 = 63,
     };
 
     union {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 32f06f409..06bfe799c 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -349,7 +349,12 @@ public:
     void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
         std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem);
         std::string src = GetRegisterAsFloat(reg);
-        shader.AddLine(dest + " = " + src + ';');
+
+        if (!dest.empty()) {
+            // Can happen with unknown/unimplemented output attributes, in which case we ignore the
+            // instruction for now.
+            shader.AddLine(dest + " = " + src + ';');
+        }
     }
 
     /// Generates code representing a uniform (C buffer) register, interpreted as the input type.
@@ -525,20 +530,16 @@ private:
             // shader.
             ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
             return "vec4(0, 0, uintBitsToFloat(gl_InstanceID), uintBitsToFloat(gl_VertexID))";
-        case Attribute::Index::Unknown_63:
-            // TODO(bunnei): Figure out what this is used for. Super Mario Odyssey uses this.
-            LOG_CRITICAL(HW_GPU, "Unhandled input attribute Unknown_63");
-            UNREACHABLE();
-            break;
         default:
             const u32 index{static_cast<u32>(attribute) -
                             static_cast<u32>(Attribute::Index::Attribute_0)};
-            if (attribute >= Attribute::Index::Attribute_0) {
+            if (attribute >= Attribute::Index::Attribute_0 &&
+                attribute <= Attribute::Index::Attribute_31) {
                 declr_input_attribute.insert(attribute);
                 return "input_attribute_" + std::to_string(index);
             }
 
-            LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", index);
+            LOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", static_cast<u32>(attribute));
             UNREACHABLE();
         }
 
@@ -560,6 +561,7 @@ private:
 
             LOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index);
             UNREACHABLE();
+            return {};
         }
     }