diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 033311b2b0..ae9bdb0d9d 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -39,6 +39,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
         private bool _isAnyVbInstanced;
         private bool _vsUsesInstanceId;
+        private byte _vsClipDistancesWritten;
 
         private bool _forceShaderUpdate;
 
@@ -993,7 +994,15 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             ShaderBundle gs = ShaderCache.GetGraphicsShader(state, addresses);
 
-            _vsUsesInstanceId = gs.Shaders[0]?.Info.UsesInstanceId ?? false;
+            byte oldVsClipDistancesWritten = _vsClipDistancesWritten;
+
+            _vsUsesInstanceId       = gs.Shaders[0]?.Info.UsesInstanceId ?? false;
+            _vsClipDistancesWritten = gs.Shaders[0]?.Info.ClipDistancesWritten ?? 0;
+
+            if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
+            {
+                UpdateUserClipState(state);
+            }
 
             int storageBufferBindingsCount = 0;
             int uniformBufferBindingsCount = 0;
@@ -1098,7 +1107,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
         /// <param name="state">Current GPU state</param>
         private void UpdateUserClipState(GpuState state)
         {
-            int clipMask = state.Get<int>(MethodOffset.ClipDistanceEnable);
+            int clipMask = state.Get<int>(MethodOffset.ClipDistanceEnable) & _vsClipDistancesWritten;
 
             for (int i = 0; i < Constants.TotalClipDistances; ++i)
             {
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs
index f592919fc1..b538e2de5a 100644
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntry.cs
@@ -75,7 +75,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
                                                     programInfo.SBuffers.Count,
                                                     programInfo.Textures.Count,
                                                     programInfo.Images.Count,
-                                                    programInfo.UsesInstanceId);
+                                                    programInfo.UsesInstanceId,
+                                                    programInfo.ClipDistancesWritten);
             CBuffers = programInfo.CBuffers.ToArray();
             SBuffers = programInfo.SBuffers.ToArray();
             Textures = programInfo.Textures.ToArray();
@@ -88,7 +89,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
         /// <returns>A new <see cref="ShaderProgramInfo"/> from this instance</returns>
         internal ShaderProgramInfo ToShaderProgramInfo()
         {
-            return new ShaderProgramInfo(CBuffers, SBuffers, Textures, Images, Header.UsesInstanceId);
+            return new ShaderProgramInfo(CBuffers, SBuffers, Textures, Images, Header.UsesInstanceId, Header.ClipDistancesWritten);
         }
 
         /// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs
index 9b1af8fb2c..7f27124ffd 100644
--- a/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/Cache/Definition/HostShaderCacheEntryHeader.cs
@@ -41,10 +41,15 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
         [MarshalAs(UnmanagedType.I1)]
         public bool InUse;
 
+        /// <summary>
+        /// Mask of clip distances that are written to on the shader.
+        /// </summary>
+        public byte ClipDistancesWritten;
+
         /// <summary>
         /// Reserved / unused.
         /// </summary>
-        public short Reserved;
+        public byte Reserved;
 
         /// <summary>
         /// Create a new host shader cache entry header.
@@ -54,14 +59,21 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache.Definition
         /// <param name="texturesCount">Count of texture descriptors</param>
         /// <param name="imagesCount">Count of image descriptors</param>
         /// <param name="usesInstanceId">Set to true if the shader uses instance id</param>
-        public HostShaderCacheEntryHeader(int cBuffersCount, int sBuffersCount, int texturesCount, int imagesCount, bool usesInstanceId) : this()
+        public HostShaderCacheEntryHeader(
+            int cBuffersCount,
+            int sBuffersCount,
+            int texturesCount,
+            int imagesCount,
+            bool usesInstanceId,
+            byte clipDistancesWritten) : this()
         {
-            CBuffersCount  = cBuffersCount;
-            SBuffersCount  = sBuffersCount;
-            TexturesCount  = texturesCount;
-            ImagesCount    = imagesCount;
-            UsesInstanceId = usesInstanceId;
-            InUse          = true;
+            CBuffersCount        = cBuffersCount;
+            SBuffersCount        = sBuffersCount;
+            TexturesCount        = texturesCount;
+            ImagesCount          = imagesCount;
+            UsesInstanceId       = usesInstanceId;
+            ClipDistancesWritten = clipDistancesWritten;
+            InUse                = true;
         }
     }
 }
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index cd20a5a233..59669cb9d2 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// <summary>
         /// Version of the codegen (to be changed when codegen or guest format change).
         /// </summary>
-        private const ulong ShaderCodeGenVersion = 2200;
+        private const ulong ShaderCodeGenVersion = 2217;
 
         // Progress reporting helpers
         private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
index 81d5c7af2e..7afdbf4e1a 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
@@ -53,6 +53,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
 
                 Operand dest = Attribute(op.AttributeOffset + index * 4);
 
+                context.FlagAttributeWritten(dest.Value);
+
                 context.Copy(dest, Register(rd));
             }
         }
diff --git a/Ryujinx.Graphics.Shader/ShaderProgramInfo.cs b/Ryujinx.Graphics.Shader/ShaderProgramInfo.cs
index 2324fac22c..9329442fe9 100644
--- a/Ryujinx.Graphics.Shader/ShaderProgramInfo.cs
+++ b/Ryujinx.Graphics.Shader/ShaderProgramInfo.cs
@@ -11,13 +11,15 @@ namespace Ryujinx.Graphics.Shader
         public ReadOnlyCollection<TextureDescriptor> Images   { get; }
 
         public bool UsesInstanceId { get; }
+        public byte ClipDistancesWritten { get; }
 
         public ShaderProgramInfo(
             BufferDescriptor[]  cBuffers,
             BufferDescriptor[]  sBuffers,
             TextureDescriptor[] textures,
             TextureDescriptor[] images,
-            bool                usesInstanceId)
+            bool                usesInstanceId,
+            byte                clipDistancesWritten)
         {
             CBuffers = Array.AsReadOnly(cBuffers);
             SBuffers = Array.AsReadOnly(sBuffers);
@@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Shader
             Images   = Array.AsReadOnly(images);
 
             UsesInstanceId = usesInstanceId;
+            ClipDistancesWritten = clipDistancesWritten;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
index 2667be1d74..c4d8b85fb0 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
@@ -291,10 +291,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
             {
                 Info.IAttributes.Add(attrIndex);
             }
-            else if (operand.Type == OperandType.Attribute && operand.Value == AttributeConsts.InstanceId)
-            {
-                Info.UsesInstanceId = true;
-            }
             else if (operand.Type == OperandType.ConstantBuffer)
             {
                 Info.CBuffers.Add(operand.GetCbufSlot());
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
index 16a27f51eb..d1619bfa49 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
@@ -12,7 +12,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
         public HashSet<int> IAttributes { get; }
         public HashSet<int> OAttributes { get; }
 
-        public bool UsesInstanceId { get; set; }
         public bool UsesCbIndexing { get; set; }
 
         public HelperFunctionsMask HelperFunctionsMask { get; set; }
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index a4c21c1d8d..9b22017737 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -55,7 +55,11 @@ namespace Ryujinx.Graphics.Shader.Translation
 
         public void FlagAttributeRead(int attribute)
         {
-            if (Config.Stage == ShaderStage.Fragment)
+            if (Config.Stage == ShaderStage.Vertex && attribute == AttributeConsts.InstanceId)
+            {
+                Config.SetUsedFeature(FeatureFlags.InstanceId);
+            }
+            else if (Config.Stage == ShaderStage.Fragment)
             {
                 switch (attribute)
                 {
@@ -67,6 +71,26 @@ namespace Ryujinx.Graphics.Shader.Translation
             }
         }
 
+        public void FlagAttributeWritten(int attribute)
+        {
+            if (Config.Stage == ShaderStage.Vertex)
+            {
+                switch (attribute)
+                {
+                    case AttributeConsts.ClipDistance0:
+                    case AttributeConsts.ClipDistance1:
+                    case AttributeConsts.ClipDistance2:
+                    case AttributeConsts.ClipDistance3:
+                    case AttributeConsts.ClipDistance4:
+                    case AttributeConsts.ClipDistance5:
+                    case AttributeConsts.ClipDistance6:
+                    case AttributeConsts.ClipDistance7:
+                        Config.SetClipDistanceWritten((attribute - AttributeConsts.ClipDistance0) / 4);
+                        break;
+                }
+            }
+        }
+
         public void MarkLabel(Operand label)
         {
             Add(Instruction.MarkLabel, label);
diff --git a/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs b/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs
index d2b53f84d2..1b71289610 100644
--- a/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs
+++ b/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs
@@ -12,9 +12,11 @@ namespace Ryujinx.Graphics.Shader.Translation
         None = 0,
 
         // Affected by resolution scaling.
-        FragCoordXY     = 1 << 1,
         IntegerSampling = 1 << 0,
+        FragCoordXY     = 1 << 1,
 
-        Bindless        = 1 << 2,
+        Bindless = 1 << 2,
+
+        InstanceId = 1 << 3
     }
 }
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index b1fd6470ea..c71a839842 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -28,6 +28,8 @@ namespace Ryujinx.Graphics.Shader.Translation
 
         public int Size { get; private set; }
 
+        public byte ClipDistancesWritten { get; private set; }
+
         public FeatureFlags UsedFeatures { get; private set; }
 
         public HashSet<int> TextureHandlesForCache { get; }
@@ -115,6 +117,11 @@ namespace Ryujinx.Graphics.Shader.Translation
             Size += size;
         }
 
+        public void SetClipDistanceWritten(int index)
+        {
+            ClipDistancesWritten |= (byte)(1 << index);
+        }
+
         public void SetUsedFeature(FeatureFlags flags)
         {
             UsedFeatures |= flags;
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 9f0f9010d4..1c15ccf278 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -94,7 +94,8 @@ namespace Ryujinx.Graphics.Shader.Translation
                 program.SBufferDescriptors,
                 program.TextureDescriptors,
                 program.ImageDescriptors,
-                sInfo.UsesInstanceId);
+                config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
+                config.ClipDistancesWritten);
 
             string glslCode = program.Code;