diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs
index 96ccfb2859..bb3a8dcac9 100644
--- a/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -68,8 +68,7 @@ namespace Ryujinx.Graphics.GAL
 
         void SetSampler(int binding, ISampler sampler);
 
-        void SetScissorEnable(int index, bool enable);
-        void SetScissor(int index, int x, int y, int width, int height);
+        void SetScissor(int index, bool enable, int x, int y, int width, int height);
 
         void SetStencilTest(StencilTestDescriptor stencilTest);
 
diff --git a/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs b/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs
index 1547658e47..b3248b621f 100644
--- a/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs
+++ b/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs
@@ -1,6 +1,8 @@
+using System;
+
 namespace Ryujinx.Graphics.GAL
 {
-    public struct VertexAttribDescriptor
+    public struct VertexAttribDescriptor : IEquatable<VertexAttribDescriptor>
     {
         public int BufferIndex { get; }
         public int Offset      { get; }
@@ -16,5 +18,23 @@ namespace Ryujinx.Graphics.GAL
             IsZero      = isZero;
             Format      = format;
         }
+
+        public override bool Equals(object obj)
+        {
+            return obj is VertexAttribDescriptor other && Equals(other);
+        }
+
+        public bool Equals(VertexAttribDescriptor other)
+        {
+            return BufferIndex == other.BufferIndex &&
+                   Offset      == other.Offset &&
+                   IsZero      == other.IsZero &&
+                   Format      == other.Format;
+        }
+
+        public override int GetHashCode()
+        {
+            return HashCode.Combine(BufferIndex, Offset, IsZero, Format);
+        }
     }
 }
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index d6bd51106c..a41fd5414d 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -436,8 +436,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
                 bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff);
 
-                _context.Renderer.Pipeline.SetScissorEnable(index, enable);
-
                 if (enable)
                 {
                     int x = scissor.X1;
@@ -454,7 +452,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
                         height = (int)Math.Ceiling(height * scale);
                     }
 
-                    _context.Renderer.Pipeline.SetScissor(index, x, y, width, height);
+                    _context.Renderer.Pipeline.SetScissor(index, true, x, y, width, height);
+                }
+                else
+                {
+                    _context.Renderer.Pipeline.SetScissor(index, false, 0, 0, 0, 0);
                 }
             }
         }
diff --git a/Ryujinx.Graphics.OpenGL/Framebuffer.cs b/Ryujinx.Graphics.OpenGL/Framebuffer.cs
index 015b0ec0ae..66bf892b31 100644
--- a/Ryujinx.Graphics.OpenGL/Framebuffer.cs
+++ b/Ryujinx.Graphics.OpenGL/Framebuffer.cs
@@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL;
 using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.OpenGL.Image;
 using System;
+using System.Runtime.CompilerServices;
 
 namespace Ryujinx.Graphics.OpenGL
 {
@@ -29,21 +30,27 @@ namespace Ryujinx.Graphics.OpenGL
             return Handle;
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void AttachColor(int index, TextureView color)
         {
+            if (_colors[index] == color)
+            {
+                return;
+            }
+
             FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
 
             if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
                 HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
             {
                 GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0);
-
-                _colors[index] = color;
             }
             else
             {
                 GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
             }
+
+            _colors[index] = color;
         }
 
         public void AttachDepthStencil(TextureView depthStencil)
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index b6a34e9cb8..f42187bdf7 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL
 
         private readonly uint[] _componentMasks;
 
-        private bool _scissor0Enable = false;
+        private uint _scissorEnables;
 
         private bool _tfEnabled;
         private TransformFeedbackPrimitiveType _tfTopology;
@@ -883,25 +883,27 @@ namespace Ryujinx.Graphics.OpenGL
             ((Sampler)sampler).Bind(binding);
         }
 
-        public void SetScissorEnable(int index, bool enable)
+        public void SetScissor(int index, bool enable, int x, int y, int width, int height)
         {
-            if (enable)
+            uint mask = 1u << index;
+
+            if (!enable)
             {
+                if ((_scissorEnables & mask) != 0)
+                {
+                    _scissorEnables &= ~mask;
+                    GL.Disable(IndexedEnableCap.ScissorTest, index);
+                }
+
+                return;
+            }
+
+            if ((_scissorEnables & mask) == 0)
+            {
+                _scissorEnables |= mask;
                 GL.Enable(IndexedEnableCap.ScissorTest, index);
             }
-            else
-            {
-                GL.Disable(IndexedEnableCap.ScissorTest, index);
-            }
 
-            if (index == 0)
-            {
-                _scissor0Enable = enable;
-            }
-        }
-
-        public void SetScissor(int index, int x, int y, int width, int height)
-        {
             GL.ScissorIndexed(index, x, y, width, height);
         }
 
@@ -1241,7 +1243,7 @@ namespace Ryujinx.Graphics.OpenGL
 
         public void RestoreScissor0Enable()
         {
-            if (_scissor0Enable)
+            if ((_scissorEnables & 1u) != 0)
             {
                 GL.Enable(IndexedEnableCap.ScissorTest, 0);
             }
diff --git a/Ryujinx.Graphics.OpenGL/VertexArray.cs b/Ryujinx.Graphics.OpenGL/VertexArray.cs
index 64c6a82198..17703cd129 100644
--- a/Ryujinx.Graphics.OpenGL/VertexArray.cs
+++ b/Ryujinx.Graphics.OpenGL/VertexArray.cs
@@ -1,6 +1,7 @@
 using OpenTK.Graphics.OpenGL;
 using Ryujinx.Graphics.GAL;
 using System;
+using System.Runtime.CompilerServices;
 
 namespace Ryujinx.Graphics.OpenGL
 {
@@ -16,6 +17,9 @@ namespace Ryujinx.Graphics.OpenGL
         private int _vertexAttribsCount;
         private int _vertexBuffersCount;
 
+        private uint _vertexAttribsInUse;
+        private uint _vertexBuffersInUse;
+
         public VertexArray()
         {
             Handle = GL.GenVertexArray();
@@ -31,30 +35,30 @@ namespace Ryujinx.Graphics.OpenGL
 
         public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
         {
-            int bindingIndex = 0;
-
-            for (int index = 0; index < vertexBuffers.Length; index++)
+            int bindingIndex;
+            for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
             {
-                VertexBufferDescriptor vb = vertexBuffers[index];
+                VertexBufferDescriptor vb = vertexBuffers[bindingIndex];
 
                 if (vb.Buffer.Handle != BufferHandle.Null)
                 {
                     GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
-
                     GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
+                    _vertexBuffersInUse |= 1u << bindingIndex;
                 }
                 else
                 {
-                    GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
+                    if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0)
+                    {
+                        GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
+                        _vertexBuffersInUse &= ~(1u << bindingIndex);
+                    }
                 }
 
-                _vertexBuffers[index] = vb;
-
-                bindingIndex++;
+                _vertexBuffers[bindingIndex] = vb;
             }
 
             _vertexBuffersCount = bindingIndex;
-
             _needsAttribsUpdate = true;
         }
 
@@ -66,17 +70,22 @@ namespace Ryujinx.Graphics.OpenGL
             {
                 VertexAttribDescriptor attrib = vertexAttribs[index];
 
+                if (attrib.Equals(_vertexAttribs[index]))
+                {
+                    continue;
+                }
+
                 FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
 
                 if (attrib.IsZero)
                 {
                     // Disabling the attribute causes the shader to read a constant value.
                     // The value is configurable, but by default is a vector of (0, 0, 0, 1).
-                    GL.DisableVertexAttribArray(index);
+                    DisableVertexAttrib(index);
                 }
                 else
                 {
-                    GL.EnableVertexAttribArray(index);
+                    EnableVertexAttrib(index);
                 }
 
                 int offset = attrib.Offset;
@@ -107,7 +116,7 @@ namespace Ryujinx.Graphics.OpenGL
 
             for (; index < Constants.MaxVertexAttribs; index++)
             {
-                GL.DisableVertexAttribArray(index);
+                DisableVertexAttrib(index);
             }
         }
 
@@ -122,29 +131,54 @@ namespace Ryujinx.Graphics.OpenGL
             {
                 VertexAttribDescriptor attrib = _vertexAttribs[attribIndex];
 
-                if ((uint)attrib.BufferIndex >= _vertexBuffersCount)
+                if (!attrib.IsZero)
                 {
-                    GL.DisableVertexAttribArray(attribIndex);
+                    if ((uint)attrib.BufferIndex >= _vertexBuffersCount)
+                    {
+                        DisableVertexAttrib(attribIndex);
+                        continue;
+                    }
 
-                    continue;
-                }
+                    if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null)
+                    {
+                        DisableVertexAttrib(attribIndex);
+                        continue;
+                    }
 
-                if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null)
-                {
-                    GL.DisableVertexAttribArray(attribIndex);
-
-                    continue;
-                }
-
-                if (_needsAttribsUpdate && !attrib.IsZero)
-                {
-                    GL.EnableVertexAttribArray(attribIndex);
+                    if (_needsAttribsUpdate)
+                    {
+                        EnableVertexAttrib(attribIndex);
+                    }
                 }
             }
 
             _needsAttribsUpdate = false;
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void EnableVertexAttrib(int index)
+        {
+            uint mask = 1u << index;
+
+            if ((_vertexAttribsInUse & mask) == 0)
+            {
+                _vertexAttribsInUse |= mask;
+                GL.EnableVertexAttribArray(index);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void DisableVertexAttrib(int index)
+        {
+            uint mask = 1u << index;
+
+            if ((_vertexAttribsInUse & mask) != 0)
+            {
+                _vertexAttribsInUse &= ~mask;
+                GL.DisableVertexAttribArray(index);
+            }
+        }
+
         public void Dispose()
         {
             if (Handle != 0)