diff --git a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
index 48464f832..cad2341b2 100644
--- a/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
+++ b/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 = 4703;
+        private const uint CodeGenVersion = 4707;
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 11f7085d3..e1ab93278 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -449,7 +449,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
                         if (translatorContexts[i] != null)
                         {
                             translatorContexts[i].SetGeometryShaderLayerInputAttribute(info.GpLayerInputAttribute);
-                            translatorContexts[i].SetLastInVertexPipeline(translatorContexts[5] != null);
+                            translatorContexts[i].SetLastInVertexPipeline();
                             break;
                         }
                     }
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 9032ca59e..5e53d62a1 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -569,7 +569,23 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
             if (context.Config.TransformFeedbackEnabled && context.Config.Stage == ShaderStage.Fragment)
             {
-                for (int c = 0; c < 4; c++)
+                int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
+                int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
+
+                if (components > 1)
+                {
+                    string type = components switch
+                    {
+                        2 => "vec2",
+                        3 => "vec3",
+                        4 => "vec4",
+                        _ => "float"
+                    };
+
+                    context.AppendLine($"layout (location = {attr}) in {type} {name};");
+                }
+
+                for (int c = components > 1 ? components : 0; c < 4; c++)
                 {
                     char swzMask = "xyzw"[c];
 
@@ -642,7 +658,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             if (context.Config.TransformFeedbackEnabled && context.Config.LastInVertexPipeline)
             {
                 int attrOffset = AttributeConsts.UserAttributeBase + attr * 16;
-                int components = context.Config.LastInPipeline ? context.Info.GetTransformFeedbackOutputComponents(attrOffset) : 1;
+                int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
 
                 if (components > 1)
                 {
@@ -664,22 +680,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
                     context.AppendLine($"layout (location = {attr}{xfb}) out {type} {name};");
                 }
-                else
+
+                for (int c = components > 1 ? components : 0; c < 4; c++)
                 {
-                    for (int c = 0; c < 4; c++)
+                    char swzMask = "xyzw"[c];
+
+                    string xfb = string.Empty;
+
+                    var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset + c * 4);
+                    if (tfOutput.Valid)
                     {
-                        char swzMask = "xyzw"[c];
-
-                        string xfb = string.Empty;
-
-                        var tfOutput = context.Info.GetTransformFeedbackOutput(attrOffset + c * 4);
-                        if (tfOutput.Valid)
-                        {
-                            xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
-                        }
-
-                        context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
+                        xfb = $", xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}";
                     }
+
+                    context.AppendLine($"layout (location = {attr}, component = {c}{xfb}) out float {name}_{swzMask};");
                 }
             }
             else
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index ce1ab50e0..ec761fa66 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                     ((config.LastInVertexPipeline && isOutAttr) ||
                     (config.Stage == ShaderStage.Fragment && !isOutAttr)))
                 {
-                    int components = config.LastInPipeline ? context.Info.GetTransformFeedbackOutputComponents(attrOffset) : 1;
+                    int components = context.Info.GetTransformFeedbackOutputComponents(attrOffset);
                     string name = components > 1 ? $"{prefix}{(value >> 4)}" : $"{prefix}{(value >> 4)}_{swzMask}";
 
                     if (AttributeInfo.IsArrayAttributeGlsl(config.Stage, isOutAttr))
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
index 41afdf188..e693307da 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
@@ -341,7 +341,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
                 attrOffset = attr;
                 type = elemType;
 
-                if (Config.LastInPipeline && isOutAttr)
+                if (isOutAttr)
                 {
                     int components = Info.GetTransformFeedbackOutputComponents(attr);
 
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
index df42a13cb..fdca5e890 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
@@ -673,7 +673,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             int components = 1;
             var type = attrInfo.Type & AggregateType.ElementTypeMask;
 
-            if (context.Config.LastInPipeline && isOutAttr)
+            if (isOutAttr)
             {
                 components = context.Info.GetTransformFeedbackOutputComponents(attr);
 
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
index ec989cca5..b8d38fa65 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
@@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
                 context.LeaveFunction();
             }
 
-            if (config.TransformFeedbackEnabled && config.LastInVertexPipeline)
+            if (config.TransformFeedbackEnabled && (config.LastInVertexPipeline || config.Stage == ShaderStage.Fragment))
             {
                 for (int tfbIndex = 0; tfbIndex < 4; tfbIndex++)
                 {
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index 2caa8f638..15eb7ed1f 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -17,7 +17,6 @@ namespace Ryujinx.Graphics.Shader.Translation
         public ShaderStage Stage { get; }
 
         public bool GpPassthrough { get; }
-        public bool LastInPipeline { get; private set; }
         public bool LastInVertexPipeline { get; private set; }
 
         public bool HasLayerInputAttribute { get; private set; }
@@ -145,7 +144,6 @@ namespace Ryujinx.Graphics.Shader.Translation
             OmapSampleMask           = header.OmapSampleMask;
             OmapDepth                = header.OmapDepth;
             TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
-            LastInPipeline           = true;
             LastInVertexPipeline     = header.Stage < ShaderStage.Fragment;
         }
 
@@ -253,13 +251,8 @@ namespace Ryujinx.Graphics.Shader.Translation
             GpLayerInputAttribute = attr;
         }
 
-        public void SetLastInVertexPipeline(bool hasFragment)
+        public void SetLastInVertexPipeline()
         {
-            if (!hasFragment)
-            {
-                LastInPipeline = true;
-            }
-
             LastInVertexPipeline = true;
         }
 
@@ -331,8 +324,6 @@ namespace Ryujinx.Graphics.Shader.Translation
                 config._perPatchAttributeLocations = locationsMap;
             }
 
-            LastInPipeline = false;
-
             // We don't consider geometry shaders using the geometry shader passthrough feature
             // as being the last because when this feature is used, it can't actually modify any of the outputs,
             // so the stage that comes before it is the last one that can do modifications.
diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
index 3b88fdbab..856b16b7d 100644
--- a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
@@ -143,9 +143,9 @@ namespace Ryujinx.Graphics.Shader.Translation
             _config.SetGeometryShaderLayerInputAttribute(attr);
         }
 
-        public void SetLastInVertexPipeline(bool hasFragment)
+        public void SetLastInVertexPipeline()
         {
-            _config.SetLastInVertexPipeline(hasFragment);
+            _config.SetLastInVertexPipeline();
         }
 
         public ShaderProgram Translate(TranslatorContext other = null)