diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs
index b7da2c2167..c02f84d471 100644
--- a/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -104,6 +104,6 @@ namespace Ryujinx.Graphics.GAL
         bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual);
         void EndHostConditionalRendering();
 
-        void UpdateRenderScale(ShaderStage stage, ReadOnlySpan<float> scales, int textureCount, int imageCount);
+        void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount);
     }
 }
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
index fafb52a872..7e1e66b202 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/UpdateRenderScaleCommand.cs
@@ -6,22 +6,20 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
     struct UpdateRenderScaleCommand : IGALCommand
     {
         public CommandType CommandType => CommandType.UpdateRenderScale;
-        private ShaderStage _stage;
         private SpanRef<float> _scales;
-        private int _textureCount;
-        private int _imageCount;
+        private int _totalCount;
+        private int _fragmentCount;
 
-        public void Set(ShaderStage stage, SpanRef<float> scales, int textureCount, int imageCount)
+        public void Set(SpanRef<float> scales, int totalCount, int fragmentCount)
         {
-            _stage = stage;
             _scales = scales;
-            _textureCount = textureCount;
-            _imageCount = imageCount;
+            _totalCount = totalCount;
+            _fragmentCount = fragmentCount;
         }
 
         public static void Run(ref UpdateRenderScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
         {
-            renderer.Pipeline.UpdateRenderScale(command._stage, command._scales.Get(threaded), command._textureCount, command._imageCount);
+            renderer.Pipeline.UpdateRenderScale(command._scales.Get(threaded), command._totalCount, command._fragmentCount);
             command._scales.Dispose(threaded);
         }
     }
diff --git a/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
index 63a29b1bed..6dc8ef3867 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
@@ -353,9 +353,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
             return false;
         }
 
-        public void UpdateRenderScale(ShaderStage stage, ReadOnlySpan<float> scales, int textureCount, int imageCount)
+        public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
         {
-            _renderer.New<UpdateRenderScaleCommand>().Set(stage, _renderer.CopySpan(scales.Slice(0, textureCount + imageCount)), textureCount, imageCount);
+            _renderer.New<UpdateRenderScaleCommand>().Set(_renderer.CopySpan(scales.Slice(0, totalCount)), totalCount, fragmentCount);
             _renderer.QueueCommand();
         }
     }
diff --git a/Ryujinx.Graphics.GAL/SupportBufferUpdater.cs b/Ryujinx.Graphics.GAL/SupportBufferUpdater.cs
new file mode 100644
index 0000000000..cb24bdd752
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/SupportBufferUpdater.cs
@@ -0,0 +1,93 @@
+using Ryujinx.Graphics.Shader;
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.GAL
+{
+    public class SupportBufferUpdater : IDisposable
+    {
+        public SupportBuffer Data;
+        public BufferHandle Handle;
+
+        private IRenderer _renderer;
+        private int _startOffset = -1;
+        private int _endOffset = -1;
+
+        public SupportBufferUpdater(IRenderer renderer)
+        {
+            _renderer = renderer;
+            Handle = renderer.CreateBuffer(SupportBuffer.RequiredSize);
+        }
+
+        private void MarkDirty(int startOffset, int byteSize)
+        {
+            int endOffset = startOffset + byteSize;
+
+            if (_startOffset == -1)
+            {
+                _startOffset = startOffset;
+                _endOffset = endOffset;
+            }
+            else
+            {
+                if (startOffset < _startOffset)
+                {
+                    _startOffset = startOffset;
+                }
+
+                if (endOffset > _endOffset)
+                {
+                    _endOffset = endOffset;
+                }
+            }
+        }
+
+        public void UpdateFragmentRenderScaleCount(int count)
+        {
+            if (Data.FragmentRenderScaleCount.X != count)
+            {
+                Data.FragmentRenderScaleCount.X = count;
+
+                MarkDirty(SupportBuffer.FragmentRenderScaleCountOffset, sizeof(int));
+            }
+        }
+
+        private void UpdateGenericField<T>(int baseOffset, ReadOnlySpan<T> data, Span<T> target, int offset, int count) where T : unmanaged
+        {
+            data.Slice(0, count).CopyTo(target.Slice(offset));
+
+            int elemSize = Unsafe.SizeOf<T>();
+
+            MarkDirty(baseOffset + offset * elemSize, count * elemSize);
+        }
+
+        public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count)
+        {
+            UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.ToSpan(), offset, count);
+        }
+
+        public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count)
+        {
+            UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.ToSpan(), offset, count);
+        }
+
+        public void Commit()
+        {
+            if (_startOffset != -1)
+            {
+                ReadOnlySpan<byte> data = MemoryMarshal.Cast<SupportBuffer, byte>(MemoryMarshal.CreateSpan(ref Data, 1));
+
+                _renderer.SetBufferData(Handle, _startOffset, data.Slice(_startOffset, _endOffset - _startOffset));
+
+                _startOffset = -1;
+                _endOffset = -1;
+            }
+        }
+
+        public void Dispose()
+        {
+            _renderer.DeleteBuffer(Handle);
+        }
+    }
+}
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index dea918cd42..97a9eee43e 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -232,42 +232,44 @@ namespace Ryujinx.Graphics.Gpu.Image
 
             if ((binding.Flags & TextureUsageFlags.NeedsScaleValue) != 0 && texture != null)
             {
-                switch (stage)
+                if ((binding.Flags & TextureUsageFlags.ResScaleUnsupported) != 0)
                 {
-                    case ShaderStage.Fragment:
-                        if ((binding.Flags & TextureUsageFlags.ResScaleUnsupported) != 0)
-                        {
-                            changed |= texture.ScaleMode != TextureScaleMode.Blacklisted;
-                            texture.BlacklistScale();
-                            break;
-                        }
+                    changed = texture.ScaleMode != TextureScaleMode.Blacklisted;
+                    texture.BlacklistScale();
+                }
+                else
+                {
+                    switch (stage)
+                    {
+                        case ShaderStage.Fragment:
+                            float scale = texture.ScaleFactor;
 
-                        float scale = texture.ScaleFactor;
-
-                        if (scale != 1)
-                        {
-                            Texture activeTarget = _channel.TextureManager.GetAnyRenderTarget();
-
-                            if (activeTarget != null && activeTarget.Info.Width / (float)texture.Info.Width == activeTarget.Info.Height / (float)texture.Info.Height)
+                            if (scale != 1)
                             {
-                                // If the texture's size is a multiple of the sampler size, enable interpolation using gl_FragCoord. (helps "invent" new integer values between scaled pixels)
-                                result = -scale;
-                                break;
+                                Texture activeTarget = _channel.TextureManager.GetAnyRenderTarget();
+
+                                if (activeTarget != null && (activeTarget.Info.Width / (float)texture.Info.Width) == (activeTarget.Info.Height / (float)texture.Info.Height))
+                                {
+                                    // If the texture's size is a multiple of the sampler size, enable interpolation using gl_FragCoord. (helps "invent" new integer values between scaled pixels)
+                                    result = -scale;
+                                    break;
+                                }
                             }
-                        }
 
-                        result = scale;
-                        break;
+                            result = scale;
+                            break;
 
-                    case ShaderStage.Compute:
-                        if ((binding.Flags & TextureUsageFlags.ResScaleUnsupported) != 0)
-                        {
-                            changed |= texture.ScaleMode != TextureScaleMode.Blacklisted;
-                            texture.BlacklistScale();
-                        }
+                        case ShaderStage.Vertex:
+                            int fragmentIndex = (int)ShaderStage.Fragment - 1;
+                            index += _textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex];
 
-                        result = texture.ScaleFactor;
-                        break;
+                            result = texture.ScaleFactor;
+                            break;
+
+                        case ShaderStage.Compute:
+                            result = texture.ScaleFactor;
+                            break;
+                    }
                 }
             }
 
@@ -284,13 +286,29 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <summary>
         /// Uploads texture and image scales to the backend when they are used.
         /// </summary>
-        /// <param name="stage">Current shader stage</param>
-        /// <param name="stageIndex">Shader stage index</param>
-        private void CommitRenderScale(ShaderStage stage, int stageIndex)
+        private void CommitRenderScale()
         {
             if (_scaleChanged)
             {
-                _context.Renderer.Pipeline.UpdateRenderScale(stage, _scales, _textureBindingsCount[stageIndex], _imageBindingsCount[stageIndex]);
+                int fragmentTotal = 0;
+                int total;
+
+                if (!_isCompute)
+                {
+                    int fragmentIndex = (int)ShaderStage.Fragment - 1;
+                    fragmentTotal = _textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex];
+
+                    int vertexIndex = (int)ShaderStage.Vertex - 1;
+                    int vertexTotal = _textureBindingsCount[vertexIndex] + _imageBindingsCount[vertexIndex];
+
+                    total = fragmentTotal + vertexTotal;
+                }
+                else
+                {
+                    total = _textureBindingsCount[0] + _imageBindingsCount[0];
+                }
+
+                _context.Renderer.Pipeline.UpdateRenderScale(_scales, total, fragmentTotal);
 
                 _scaleChanged = false;
             }
@@ -312,8 +330,6 @@ namespace Ryujinx.Graphics.Gpu.Image
             {
                 CommitTextureBindings(texturePool, ShaderStage.Compute, 0);
                 CommitImageBindings  (texturePool, ShaderStage.Compute, 0);
-
-                CommitRenderScale(ShaderStage.Compute, 0);
             }
             else
             {
@@ -323,11 +339,11 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                     CommitTextureBindings(texturePool, stage, stageIndex);
                     CommitImageBindings  (texturePool, stage, stageIndex);
-
-                    CommitRenderScale(stage, stageIndex);
                 }
             }
 
+            CommitRenderScale();
+
             _rebind = false;
         }
 
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 32a1e4bd85..acd656210d 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -40,7 +40,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 = 2885;
+        private const ulong ShaderCodeGenVersion = 2764;
 
         // Progress reporting helpers
         private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index aafc4db80d..6d6e07457b 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -43,16 +43,9 @@ namespace Ryujinx.Graphics.OpenGL
 
         private CounterQueueEvent _activeConditionalRender;
 
-        private struct Vector4<T>
-        {
-            public T X;
-            public T Y;
-            public T Z;
-            public T W;
-        }
-
         private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
         private Vector4<float>[] _renderScale = new Vector4<float>[65];
+        private int _fragmentScaleCount;
 
         private TextureBase _unit0Texture;
         private Sampler _unit0Sampler;
@@ -68,7 +61,7 @@ namespace Ryujinx.Graphics.OpenGL
         private bool _tfEnabled;
         private TransformFeedbackPrimitiveType _tfTopology;
 
-        private BufferHandle _supportBuffer;
+        private SupportBufferUpdater _supportBuffer;
         private readonly BufferHandle[] _tfbs;
         private readonly BufferRange[] _tfbTargets;
 
@@ -95,13 +88,13 @@ namespace Ryujinx.Graphics.OpenGL
             _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
         }
 
-        public void Initialize()
+        public void Initialize(Renderer renderer)
         {
-            _supportBuffer = Buffer.Create(SupportBuffer.RequiredSize);
-            GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer));
+            _supportBuffer = new SupportBufferUpdater(renderer);
+            GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer.Handle));
 
-            SetSupportBufferData<Vector4<int>>(SupportBuffer.FragmentIsBgraOffset, _fpIsBgra, SupportBuffer.FragmentIsBgraCount);
-            SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, SupportBuffer.RenderScaleMaxCount);
+            _supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount);
+            _supportBuffer.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount);
         }
 
         public void Barrier()
@@ -558,6 +551,8 @@ namespace Ryujinx.Graphics.OpenGL
         {
             if (texture is TextureView view && sampler is Sampler samp)
             {
+                _supportBuffer.Commit();
+
                 if (HwCapabilities.SupportsDrawTexture)
                 {
                     GL.NV.DrawTexture(
@@ -1038,7 +1033,7 @@ namespace Ryujinx.Graphics.OpenGL
         public void SetRenderTargetScale(float scale)
         {
             _renderScale[0].X = scale;
-            SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1); // Just the first element.
+            _supportBuffer.UpdateRenderScale(_renderScale, 0, 1); // Just the first element.
         }
 
         public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
@@ -1076,7 +1071,7 @@ namespace Ryujinx.Graphics.OpenGL
 
             if (isBgraChanged)
             {
-                SetSupportBufferData<Vector4<int>>(SupportBuffer.FragmentIsBgraOffset, _fpIsBgra, SupportBuffer.FragmentIsBgraCount);
+                _supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount);
             }
 
             TextureView depthStencilView = (TextureView)depthStencil;
@@ -1384,16 +1379,11 @@ namespace Ryujinx.Graphics.OpenGL
             return (_boundDrawFramebuffer, _boundReadFramebuffer);
         }
 
-        public void UpdateRenderScale(ShaderStage stage, ReadOnlySpan<float> scales, int textureCount, int imageCount)
+        public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
         {
-            if (stage != ShaderStage.Compute && stage != ShaderStage.Fragment)
-            {
-                return;
-            }
-
             bool changed = false;
 
-            for (int index = 0; index < textureCount + imageCount; index++)
+            for (int index = 0; index < totalCount; index++)
             {
                 if (_renderScale[1 + index].X != scales[index])
                 {
@@ -1402,20 +1392,23 @@ namespace Ryujinx.Graphics.OpenGL
                 }
             }
 
+            // Only update fragment count if there are scales after it for the vertex stage.
+            if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount)
+            {
+                _fragmentScaleCount = fragmentCount;
+                _supportBuffer.UpdateFragmentRenderScaleCount(_fragmentScaleCount);
+            }
+
             if (changed)
             {
-                SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1 + textureCount + imageCount);
+                _supportBuffer.UpdateRenderScale(_renderScale, 0, 1 + totalCount);
             }
         }
 
-        private void SetSupportBufferData<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
-        {
-            Buffer.SetData(_supportBuffer, offset, MemoryMarshal.Cast<T, byte>(data.Slice(0, count)));
-        }
-
         private void PrepareForDispatch()
         {
             _unit0Texture?.Bind(0);
+            _supportBuffer.Commit();
         }
 
         private void PreDraw()
@@ -1424,6 +1417,7 @@ namespace Ryujinx.Graphics.OpenGL
 
             _vertexArray.Validate();
             _unit0Texture?.Bind(0);
+            _supportBuffer.Commit();
         }
 
         private void PostDraw()
@@ -1521,11 +1515,7 @@ namespace Ryujinx.Graphics.OpenGL
 
         public void Dispose()
         {
-            if (_supportBuffer != BufferHandle.Null)
-            {
-                Buffer.Delete(_supportBuffer);
-                _supportBuffer = BufferHandle.Null;
-            }
+            _supportBuffer?.Dispose();
 
             for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
             {
diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs
index 0c16ec5a1a..7806157dc1 100644
--- a/Ryujinx.Graphics.OpenGL/Renderer.cs
+++ b/Ryujinx.Graphics.OpenGL/Renderer.cs
@@ -151,7 +151,7 @@ namespace Ryujinx.Graphics.OpenGL
                 GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8));
             }
 
-            _pipeline.Initialize();
+            _pipeline.Initialize(this);
             _counters.Initialize();
         }
 
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 7dcd1671ea..d895656724 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -208,7 +208,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
             bool isFragment = context.Config.Stage == ShaderStage.Fragment;
 
-            if (isFragment || context.Config.Stage == ShaderStage.Compute)
+            if (isFragment || context.Config.Stage == ShaderStage.Compute || context.Config.Stage == ShaderStage.Vertex)
             {
                 if (isFragment && context.Config.GpuAccessor.QueryEarlyZForce())
                 {
@@ -227,7 +227,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                         scaleElements++; // Also includes render target scale, for gl_FragCoord.
                     }
 
-                    DeclareSupportUniformBlock(context, isFragment, scaleElements);
+                    DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements);
 
                     if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling))
                     {
@@ -237,7 +237,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
                 }
                 else if (isFragment)
                 {
-                    DeclareSupportUniformBlock(context, true, 0);
+                    DeclareSupportUniformBlock(context, context.Config.Stage, 0);
                 }
             }
 
@@ -591,8 +591,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             context.AppendLine($"patch out vec4 {name};");
         }
 
-        private static void DeclareSupportUniformBlock(CodeGenContext context, bool isFragment, int scaleElements)
+        private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements)
         {
+            bool isFragment = stage == ShaderStage.Fragment;
             if (!isFragment && scaleElements == 0)
             {
                 return;
@@ -601,20 +602,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             context.AppendLine($"layout (binding = 0, std140) uniform {DefaultNames.SupportBlockName}");
             context.EnterScope();
 
-            if (isFragment)
+            switch (stage)
             {
-                context.AppendLine($"uint {DefaultNames.SupportBlockAlphaTestName};");
-                context.AppendLine($"bool {DefaultNames.SupportBlockIsBgraName}[{SupportBuffer.FragmentIsBgraCount}];");
-            }
-            else
-            {
-                context.AppendLine($"uint s_reserved[{SupportBuffer.ComputeRenderScaleOffset / SupportBuffer.FieldSize}];");
+                case ShaderStage.Fragment:
+                case ShaderStage.Vertex:
+                    context.AppendLine($"uint {DefaultNames.SupportBlockAlphaTestName};");
+                    context.AppendLine($"bool {DefaultNames.SupportBlockIsBgraName}[{SupportBuffer.FragmentIsBgraCount}];");
+                    context.AppendLine($"int {DefaultNames.SupportBlockFragmentScaleCount};");
+                    break;
+                case ShaderStage.Compute:
+                    context.AppendLine($"uint s_reserved[{SupportBuffer.ComputeRenderScaleOffset / SupportBuffer.FieldSize}];");
+                    break;
             }
 
-            if (scaleElements != 0)
-            {
-                context.AppendLine($"float {DefaultNames.SupportBlockRenderScaleName}[{scaleElements}];");
-            }
+            context.AppendLine($"float {DefaultNames.SupportBlockRenderScaleName}[{SupportBuffer.RenderScaleMaxCount}];");
 
             context.LeaveScope(";");
             context.AppendLine();
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
index 4735040809..76203522e9 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
@@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
         public const string SupportBlockName = "support_block";
         public const string SupportBlockAlphaTestName = "s_alpha_test";
         public const string SupportBlockIsBgraName = "s_is_bgra";
+        public const string SupportBlockFragmentScaleCount = "s_frag_scale_count";
         public const string SupportBlockRenderScaleName = "s_render_scale";
 
         public const string BlockSuffix = "block";
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
index 5def1390c5..6c670f91b8 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
@@ -7,7 +7,7 @@
     }
     if (scale < 0.0) // If less than 0, try interpolate between texels by using the screen position.
     {
-        return ivec2(vec2(inputVec) * (-scale) + mod(gl_FragCoord.xy, -scale));
+        return ivec2(vec2(inputVec) * (-scale) + mod(gl_FragCoord.xy, 0.0 - scale));
     }
     else
     {
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl
new file mode 100644
index 0000000000..19eb119db7
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl
@@ -0,0 +1,20 @@
+ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
+{
+    float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]);
+    if (scale == 1.0)
+    {
+        return inputVec;
+    }
+
+    return ivec2(vec2(inputVec) * scale);
+}
+
+int Helper_TextureSizeUnscale(int size, int samplerIndex)
+{
+    float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]);
+    if (scale == 1.0)
+    {
+        return size;
+    }
+    return int(float(size) / scale);
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index abca03aa56..164de7bbfd 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
 
             string ApplyScaling(string vector)
             {
-                if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
+                if ((context.Config.Stage.SupportsRenderScale()) &&
                     texOp.Inst == Instruction.ImageLoad &&
                     !isBindless &&
                     !isIndexed)
@@ -621,7 +621,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
             {
                 if (intCoords)
                 {
-                    if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
+                    if ((context.Config.Stage.SupportsRenderScale()) &&
                         !isBindless &&
                         !isIndexed)
                     {
@@ -770,7 +770,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
             {
                 string texCall = $"textureSize({samplerName}, {lodExpr}){GetMask(texOp.Index)}";
 
-                if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
+                if (context.Config.Stage.SupportsRenderScale() &&
                     !isBindless &&
                     !isIndexed)
                 {
diff --git a/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj b/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj
index c604902f3e..81cc0caf3d 100644
--- a/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj
+++ b/Ryujinx.Graphics.Shader/Ryujinx.Graphics.Shader.csproj
@@ -4,6 +4,10 @@
     <TargetFramework>net6.0</TargetFramework>
   </PropertyGroup>
 
+  <ItemGroup>
+    <None Remove="CodeGen\Glsl\HelperFunctions\TexelFetchScale_vp.glsl" />
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
   </ItemGroup>
@@ -20,6 +24,7 @@
     <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\StoreSharedSmallInt.glsl" />
     <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\StoreStorageSmallInt.glsl" />
     <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\SwizzleAdd.glsl" />
+    <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\TexelFetchScale_vp.glsl" />
     <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\TexelFetchScale_fp.glsl" />
     <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\TexelFetchScale_cp.glsl" />
   </ItemGroup>
diff --git a/Ryujinx.Graphics.Shader/ShaderStage.cs b/Ryujinx.Graphics.Shader/ShaderStage.cs
index 63e3b0684d..f16fe3281d 100644
--- a/Ryujinx.Graphics.Shader/ShaderStage.cs
+++ b/Ryujinx.Graphics.Shader/ShaderStage.cs
@@ -11,4 +11,17 @@ namespace Ryujinx.Graphics.Shader
 
         Count
     }
+
+    public static class ShaderStageExtensions
+    {
+        /// <summary>
+        /// Checks if the shader stage supports render scale.
+        /// </summary>
+        /// <param name="stage">Shader stage</param>
+        /// <returns>True if the shader stage supports render scale, false otherwise</returns>
+        public static bool SupportsRenderScale(this ShaderStage stage)
+        {
+            return stage == ShaderStage.Vertex || stage == ShaderStage.Fragment || stage == ShaderStage.Compute;
+        }
+    }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/SupportBuffer.cs b/Ryujinx.Graphics.Shader/SupportBuffer.cs
index f76d2c922a..47a47ea638 100644
--- a/Ryujinx.Graphics.Shader/SupportBuffer.cs
+++ b/Ryujinx.Graphics.Shader/SupportBuffer.cs
@@ -1,18 +1,55 @@
+using Ryujinx.Common.Memory;
+using System.Runtime.CompilerServices;
+
 namespace Ryujinx.Graphics.Shader
 {
-    public static class SupportBuffer
+    public struct Vector4<T>
     {
-        public const int FieldSize = 16; // Each field takes 16 bytes on default layout, even bool.
+        public T X;
+        public T Y;
+        public T Z;
+        public T W;
+    }
+
+    public struct SupportBuffer
+    {
+        public static int FieldSize;
+        public static int RequiredSize;
+
+        public static int FragmentAlphaTestOffset;
+        public static int FragmentIsBgraOffset;
+        public static int FragmentRenderScaleCountOffset;
+        public static int GraphicsRenderScaleOffset;
+        public static int ComputeRenderScaleOffset;
 
-        public const int FragmentAlphaTestOffset = 0;
-        public const int FragmentIsBgraOffset = FieldSize;
         public const int FragmentIsBgraCount = 8;
-        public const int FragmentRenderScaleOffset = FragmentIsBgraOffset + FragmentIsBgraCount * FieldSize;
-        public const int ComputeRenderScaleOffset = FragmentRenderScaleOffset + FieldSize; // Skip first scale that is used for the render target
-
         // One for the render target, 32 for the textures, and 8 for the images.
         public const int RenderScaleMaxCount = 1 + 32 + 8;
 
-        public const int RequiredSize = FragmentRenderScaleOffset + RenderScaleMaxCount * FieldSize;
+        private static int OffsetOf<T>(ref SupportBuffer storage, ref T target)
+        {
+            return (int)Unsafe.ByteOffset(ref Unsafe.As<SupportBuffer, T>(ref storage), ref target);
+        }
+
+        static SupportBuffer()
+        {
+            FieldSize = Unsafe.SizeOf<Vector4<float>>();
+            RequiredSize = Unsafe.SizeOf<SupportBuffer>();
+
+            SupportBuffer instance = new SupportBuffer();
+
+            FragmentAlphaTestOffset = OffsetOf(ref instance, ref instance.FragmentAlphaTest);
+            FragmentIsBgraOffset = OffsetOf(ref instance, ref instance.FragmentIsBgra);
+            FragmentRenderScaleCountOffset = OffsetOf(ref instance, ref instance.FragmentRenderScaleCount);
+            GraphicsRenderScaleOffset = OffsetOf(ref instance, ref instance.RenderScale);
+            ComputeRenderScaleOffset = GraphicsRenderScaleOffset + FieldSize;
+        }
+
+        public Vector4<int> FragmentAlphaTest;
+        public Array8<Vector4<int>> FragmentIsBgra;
+        public Vector4<int> FragmentRenderScaleCount;
+
+        // Render scale max count: 1 + 32 + 8. First scale is fragment output scale, others are textures/image inputs.
+        public Array41<Vector4<float>> RenderScale;
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index df14a5edca..9d5a40706f 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -413,7 +413,7 @@ namespace Ryujinx.Graphics.Shader.Translation
             {
                 usageFlags |= TextureUsageFlags.NeedsScaleValue;
 
-                var canScale = (Stage == ShaderStage.Fragment || Stage == ShaderStage.Compute) && !isIndexed && !write && dimensions == 2;
+                var canScale = Stage.SupportsRenderScale() && !isIndexed && !write && dimensions == 2;
 
                 if (!canScale)
                 {