diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index a7daea766..d2388673e 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -76,6 +76,7 @@ union Attribute {
         Position = 7,
         Attribute_0 = 8,
         Attribute_31 = 39,
+        PointCoord = 46,
         // 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.
@@ -246,6 +247,17 @@ enum class TextureType : u64 {
 enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 };
 enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
 
+struct IpaMode {
+    IpaInterpMode interpolation_mode;
+    IpaSampleMode sampling_mode;
+    inline bool operator==(const IpaMode& a) {
+        return (a.interpolation_mode == interpolation_mode) && (a.sampling_mode == sampling_mode);
+    }
+    inline bool operator!=(const IpaMode& a) {
+        return !((*this) == a);
+    }
+};
+
 union Instruction {
     Instruction& operator=(const Instruction& instr) {
         value = instr.value;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index d3e8f5078..781ddb073 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -247,6 +247,7 @@ public:
                         const Maxwell3D::Regs::ShaderStage& stage, const std::string& suffix)
         : shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix} {
         BuildRegisterList();
+        BuildInputList();
     }
 
     /**
@@ -343,9 +344,10 @@ public:
      * @param elem The element to use for the operation.
      * @param attribute The input attribute to use as the source value.
      */
-    void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) {
+    void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
+                                    const Tegra::Shader::IpaMode& input_mode) {
         std::string dest = GetRegisterAsFloat(reg);
-        std::string src = GetInputAttribute(attribute) + GetSwizzle(elem);
+        std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem);
         shader.AddLine(dest + " = " + src + ';');
     }
 
@@ -412,12 +414,13 @@ public:
         }
         declarations.AddNewLine();
 
-        for (const auto& index : declr_input_attribute) {
+        for (const auto element : declr_input_attribute) {
             // TODO(bunnei): Use proper number of elements for these
-            declarations.AddLine("layout(location = " +
-                                 std::to_string(static_cast<u32>(index) -
-                                                static_cast<u32>(Attribute::Index::Attribute_0)) +
-                                 ") in vec4 " + GetInputAttribute(index) + ';');
+            u32 idx =
+                static_cast<u32>(element.first) - static_cast<u32>(Attribute::Index::Attribute_0);
+            declarations.AddLine("layout(location = " + std::to_string(idx) + ")" +
+                                 GetInputFlags(element.first) + "in vec4 " +
+                                 GetInputAttribute(element.first, element.second) + ';');
         }
         declarations.AddNewLine();
 
@@ -532,11 +535,24 @@ private:
         }
     }
 
+    void BuildInputList() {
+        const u32 size = static_cast<u32>(Attribute::Index::Attribute_31) -
+                         static_cast<u32>(Attribute::Index::Attribute_0) + 1;
+        declr_input_attribute.reserve(size);
+    }
+
     /// Generates code representing an input attribute register.
-    std::string GetInputAttribute(Attribute::Index attribute) {
+    std::string GetInputAttribute(Attribute::Index attribute,
+                                  const Tegra::Shader::IpaMode& input_mode) {
         switch (attribute) {
         case Attribute::Index::Position:
-            return "position";
+            if (stage != Maxwell3D::Regs::ShaderStage::Fragment) {
+                return "position";
+            } else {
+                return "vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)";
+            }
+        case Attribute::Index::PointCoord:
+            return "vec4(gl_PointCoord.x, gl_PointCoord.y, 0, 0)";
         case Attribute::Index::TessCoordInstanceIDVertexID:
             // TODO(Subv): Find out what the values are for the first two elements when inside a
             // vertex shader, and what's the value of the fourth element when inside a Tess Eval
@@ -552,7 +568,14 @@ private:
                             static_cast<u32>(Attribute::Index::Attribute_0)};
             if (attribute >= Attribute::Index::Attribute_0 &&
                 attribute <= Attribute::Index::Attribute_31) {
-                declr_input_attribute.insert(attribute);
+                if (declr_input_attribute.count(attribute) == 0) {
+                    declr_input_attribute[attribute] = input_mode;
+                } else {
+                    if (declr_input_attribute[attribute] != input_mode) {
+                        LOG_CRITICAL(HW_GPU, "Same Input multiple input modes");
+                        UNREACHABLE();
+                    }
+                }
                 return "input_attribute_" + std::to_string(index);
             }
 
@@ -563,6 +586,49 @@ private:
         return "vec4(0, 0, 0, 0)";
     }
 
+    std::string GetInputFlags(const Attribute::Index attribute) {
+        const Tegra::Shader::IpaSampleMode sample_mode =
+            declr_input_attribute[attribute].sampling_mode;
+        const Tegra::Shader::IpaInterpMode interp_mode =
+            declr_input_attribute[attribute].interpolation_mode;
+        std::string out;
+        switch (interp_mode) {
+        case Tegra::Shader::IpaInterpMode::Flat: {
+            out += "flat ";
+            break;
+        }
+        case Tegra::Shader::IpaInterpMode::Linear: {
+            out += "noperspective ";
+            break;
+        }
+        case Tegra::Shader::IpaInterpMode::Perspective: {
+            // Default, Smooth
+            break;
+        }
+        default: {
+            LOG_CRITICAL(HW_GPU, "Unhandled Ipa InterpMode: {}", static_cast<u32>(interp_mode));
+            UNREACHABLE();
+        }
+        }
+        switch (sample_mode) {
+        case Tegra::Shader::IpaSampleMode::Centroid: {
+            // Note not implemented, it can be implemented with the "centroid " keyword in glsl;
+            LOG_CRITICAL(HW_GPU, "Ipa Sampler Mode: centroid, not implemented");
+            UNREACHABLE();
+            break;
+        }
+        case Tegra::Shader::IpaSampleMode::Default: {
+            // Default, n/a
+            break;
+        }
+        default: {
+            LOG_CRITICAL(HW_GPU, "Unhandled Ipa SampleMode: {}", static_cast<u32>(sample_mode));
+            UNREACHABLE();
+        }
+        }
+        return out;
+    }
+
     /// Generates code representing an output attribute register.
     std::string GetOutputAttribute(Attribute::Index attribute) {
         switch (attribute) {
@@ -593,7 +659,7 @@ private:
     ShaderWriter& shader;
     ShaderWriter& declarations;
     std::vector<GLSLRegister> regs;
-    std::set<Attribute::Index> declr_input_attribute;
+    std::unordered_map<Attribute::Index, Tegra::Shader::IpaMode> declr_input_attribute;
     std::set<Attribute::Index> declr_output_attribute;
     std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers;
     std::vector<SamplerEntry> used_samplers;
@@ -1634,8 +1700,12 @@ private:
             switch (opcode->GetId()) {
             case OpCode::Id::LD_A: {
                 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
+                // Note: Shouldn't this be interp mode flat? As in no interpolation made.
+
+                Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective,
+                                                  Tegra::Shader::IpaSampleMode::Default};
                 regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element,
-                                                instr.attribute.fmt20.index);
+                                                instr.attribute.fmt20.index, input_mode);
                 break;
             }
             case OpCode::Id::LD_C: {
@@ -2127,42 +2197,11 @@ private:
             case OpCode::Id::IPA: {
                 const auto& attribute = instr.attribute.fmt28;
                 const auto& reg = instr.gpr0;
-                ASSERT_MSG(instr.ipa.sample_mode == Tegra::Shader::IpaSampleMode::Default,
-                           "Unhandled IPA sample mode: {}",
-                           static_cast<u32>(instr.ipa.sample_mode.Value()));
                 ASSERT_MSG(instr.ipa.saturate == 0, "IPA saturate not implemented");
-                switch (instr.ipa.interp_mode) {
-                case Tegra::Shader::IpaInterpMode::Linear:
-                    if (stage == Maxwell3D::Regs::ShaderStage::Fragment &&
-                        attribute.index == Attribute::Index::Position) {
-                        switch (attribute.element) {
-                        case 0:
-                            shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.x;");
-                            break;
-                        case 1:
-                            shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.y;");
-                            break;
-                        case 2:
-                            shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.z;");
-                            break;
-                        case 3:
-                            shader.AddLine(regs.GetRegisterAsFloat(reg) + " = 1.0;");
-                            break;
-                        }
-                    } else {
-                        regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index);
-                    }
-                    break;
-                case Tegra::Shader::IpaInterpMode::Perspective:
-                    regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index);
-                    break;
-                default:
-                    LOG_CRITICAL(HW_GPU, "Unhandled IPA mode: {}",
-                                 static_cast<u32>(instr.ipa.interp_mode.Value()));
-                    UNREACHABLE();
-                    regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index);
-                }
-
+                Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(),
+                                                  instr.ipa.sample_mode.Value()};
+                regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index,
+                                                input_mode);
                 break;
             }
             case OpCode::Id::SSY: {