diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 2427b8c073..2ec4c9f551 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1102,12 +1102,28 @@ void RasterizerOpenGL::SyncLogicOpState() {
 }
 
 void RasterizerOpenGL::SyncScissorTest() {
-    const auto& regs = system.GPU().Maxwell3D().regs;
+    auto& gpu = system.GPU().Maxwell3D();
+    auto& flags = gpu.dirty.flags;
+    if (!flags[Dirty::Scissors]) {
+        return;
+    }
+    flags[Dirty::Scissors] = false;
+
+    const auto& regs = gpu.regs;
     for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
+        if (!flags[Dirty::Scissor0 + index]) {
+            continue;
+        }
+        flags[Dirty::Scissor0 + index] = false;
+
         const auto& src = regs.scissor_test[index];
-        oglEnablei(GL_SCISSOR_TEST, src.enable, static_cast<GLuint>(index));
-        glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y, src.max_x - src.min_x,
-                         src.max_y - src.min_y);
+        if (src.enable) {
+            glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
+            glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y,
+                             src.max_x - src.min_x, src.max_y - src.min_y);
+        } else {
+            glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
+        }
     }
 }
 
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index 6293f61021..9e1db59ae2 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -77,6 +77,14 @@ void SetupDirtyViewports(Tables& tables) {
     tables[1][OFF(viewport_transform_enabled)] = Viewports;
 }
 
+void SetupDirtyScissors(Tables& tables) {
+    for (std::size_t i = 0; i < Regs::NumViewports; ++i) {
+        const std::size_t offset = OFF(scissor_test) + i * NUM(scissor_test[0]);
+        FillBlock(tables[0], offset, NUM(scissor_test[0]), Scissor0 + i);
+    }
+    FillBlock(tables[1], OFF(scissor_test), NUM(scissor_test), Scissors);
+}
+
 } // Anonymous namespace
 
 StateTracker::StateTracker(Core::System& system) : system{system} {}
@@ -97,6 +105,7 @@ void StateTracker::Initialize() {
     auto& tables = dirty.tables;
     SetupDirtyRenderTargets(tables);
     SetupDirtyViewports(tables);
+    SetupDirtyScissors(tables);
 }
 
 } // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h
index 93c64a44a9..5153dc5d14 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.h
+++ b/src/video_core/renderer_opengl/gl_state_tracker.h
@@ -15,15 +15,30 @@ class System;
 namespace OpenGL {
 
 namespace Dirty {
+
 enum : u8 {
     First = VideoCommon::Dirty::LastCommonEntry,
 
     VertexFormats,
+
     VertexBuffers,
+    VertexBuffer0,
+    VertexBuffer31 = VertexBuffer0 + 31,
+
     VertexInstances,
-    Shaders,
-    Viewports,
+    VertexInstance0,
+    VertexInstance31 = VertexInstance0 + 31,
+
     ViewportTransform,
+    Viewports,
+    Viewport0,
+    Viewport15 = Viewport0 + 15,
+
+    Scissors,
+    Scissor0,
+    Scissor15 = Scissor0 + 15,
+
+    Shaders,
     CullTestEnable,
     FrontFace,
     CullFace,
@@ -34,11 +49,11 @@ enum : u8 {
     BlendState,
     PolygonOffset,
 
-    Viewport0,
-    VertexBuffer0 = Viewport0 + 16,
-    VertexInstance0 = VertexBuffer0 + 32,
+    Last
 };
-}
+static_assert(Last <= 0xff);
+
+} // namespace Dirty
 
 class StateTracker {
 public:
@@ -52,6 +67,12 @@ public:
         flags[OpenGL::Dirty::Viewport0] = true;
     }
 
+    void NotifyScissor0() {
+        auto& flags = system.GPU().Maxwell3D().dirty.flags;
+        flags[OpenGL::Dirty::Scissors] = true;
+        flags[OpenGL::Dirty::Scissor0] = true;
+    }
+
     void NotifyFramebuffer() {
         auto& flags = system.GPU().Maxwell3D().dirty.flags;
         flags[VideoCommon::Dirty::RenderTargets] = true;
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 1cadcf2871..a02326b9f4 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -519,6 +519,7 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view,
     UNIMPLEMENTED_IF(dst_params.target == SurfaceTarget::Texture3D);
 
     // TODO: Signal state tracker about these changes
+    state_tracker.NotifyScissor0();
     state_tracker.NotifyFramebuffer();
 
     if (dst_params.srgb_conversion) {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 73d2d90273..f2b07ac81c 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -577,6 +577,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 
     // TODO: Signal state tracker about these changes
     state_tracker.NotifyViewport0();
+    state_tracker.NotifyScissor0();
     state_tracker.NotifyFramebuffer();
 
     program_manager.UseVertexShader(vertex_program.handle);