diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 9b209a49ebc28cfa0501d7ba18d7ad072bf7eaed..3bca16364e6a18e1d9e09e5448111ae9de74f243 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -126,6 +126,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
         DrawArrays();
         break;
     }
+    case MAXWELL3D_REG_INDEX(clear_buffers): {
+        ProcessClearBuffers();
+        break;
+    }
     case MAXWELL3D_REG_INDEX(query.query_get): {
         ProcessQueryGet();
         break;
@@ -415,5 +419,13 @@ bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const {
     UNREACHABLE();
 }
 
+void Maxwell3D::ProcessClearBuffers() {
+    ASSERT(regs.clear_buffers.R == regs.clear_buffers.G &&
+           regs.clear_buffers.R == regs.clear_buffers.B &&
+           regs.clear_buffers.R == regs.clear_buffers.A);
+
+    VideoCore::g_renderer->Rasterizer()->Clear();
+}
+
 } // namespace Engines
 } // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 12aec354948c244c8251b84409db323edaa67093..988a6433e0d3389876d2d4f770288364555e4eb4 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -436,7 +436,12 @@ public:
                     u32 count;
                 } vertex_buffer;
 
-                INSERT_PADDING_WORDS(0x99);
+                INSERT_PADDING_WORDS(1);
+
+                float clear_color[4];
+                float clear_depth;
+
+                INSERT_PADDING_WORDS(0x93);
 
                 struct {
                     u32 address_high;
@@ -584,7 +589,21 @@ public:
 
                 Cull cull;
 
-                INSERT_PADDING_WORDS(0x77);
+                INSERT_PADDING_WORDS(0x2B);
+
+                union {
+                    u32 raw;
+                    BitField<0, 1, u32> Z;
+                    BitField<1, 1, u32> S;
+                    BitField<2, 1, u32> R;
+                    BitField<3, 1, u32> G;
+                    BitField<4, 1, u32> B;
+                    BitField<5, 1, u32> A;
+                    BitField<6, 4, u32> RT;
+                    BitField<10, 11, u32> layer;
+                } clear_buffers;
+
+                INSERT_PADDING_WORDS(0x4B);
 
                 struct {
                     u32 query_address_high;
@@ -766,6 +785,9 @@ private:
     /// Handles writes to the macro uploading registers.
     void ProcessMacroUpload(u32 data);
 
+    /// Handles a write to the CLEAR_BUFFERS register.
+    void ProcessClearBuffers();
+
     /// Handles a write to the QUERY_GET register.
     void ProcessQueryGet();
 
@@ -788,6 +810,8 @@ ASSERT_REG_POSITION(rt, 0x200);
 ASSERT_REG_POSITION(viewport_transform[0], 0x280);
 ASSERT_REG_POSITION(viewport, 0x300);
 ASSERT_REG_POSITION(vertex_buffer, 0x35D);
+ASSERT_REG_POSITION(clear_color[0], 0x360);
+ASSERT_REG_POSITION(clear_depth, 0x364);
 ASSERT_REG_POSITION(zeta, 0x3F8);
 ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
 ASSERT_REG_POSITION(rt_control, 0x487);
@@ -803,6 +827,7 @@ ASSERT_REG_POSITION(code_address, 0x582);
 ASSERT_REG_POSITION(draw, 0x585);
 ASSERT_REG_POSITION(index_array, 0x5F2);
 ASSERT_REG_POSITION(cull, 0x646);
+ASSERT_REG_POSITION(clear_buffers, 0x674);
 ASSERT_REG_POSITION(query, 0x6C0);
 ASSERT_REG_POSITION(vertex_array[0], 0x700);
 ASSERT_REG_POSITION(independent_blend, 0x780);
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 145e583344039ac4068256a80176dc5e73cb542a..499e84b8926d0331e7e289acb5b364e7751540c9 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -19,6 +19,9 @@ public:
     /// Draw the current batch of vertex arrays
     virtual void DrawArrays() = 0;
 
+    /// Clear the current framebuffer
+    virtual void Clear() = 0;
+
     /// Notify rasterizer that the specified Maxwell register has been changed
     virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
 
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c7b7a5817200b86c8550e41d3e713d7474c5d795..43dbf4da925e2ae9b6ebd4f982b3ef3e683c62a8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -297,11 +297,7 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
     return true;
 }
 
-void RasterizerOpenGL::DrawArrays() {
-    if (accelerate_draw == AccelDraw::Disabled)
-        return;
-
-    MICROPROFILE_SCOPE(OpenGL_Drawing);
+std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
     const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
 
     // Sync the depth test state before configuring the framebuffer surfaces.
@@ -344,11 +340,6 @@ void RasterizerOpenGL::DrawArrays() {
     BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
 
     SyncViewport(surfaces_rect);
-    SyncBlendState();
-    SyncCullMode();
-
-    // TODO(bunnei): Sync framebuffer_scale uniform here
-    // TODO(bunnei): Sync scissorbox uniform(s) here
 
     // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
     // scissor test to prevent drawing outside of the framebuffer region
@@ -359,6 +350,58 @@ void RasterizerOpenGL::DrawArrays() {
     state.scissor.height = draw_rect.GetHeight();
     state.Apply();
 
+    // Only return the surface to be marked as dirty if writing to it is enabled.
+    return std::make_pair(write_color_fb ? color_surface : nullptr,
+                          write_depth_fb ? depth_surface : nullptr);
+}
+
+void RasterizerOpenGL::Clear() {
+    const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
+
+    GLbitfield clear_mask = 0;
+    if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B &&
+        regs.clear_buffers.A) {
+        clear_mask |= GL_COLOR_BUFFER_BIT;
+    }
+    if (regs.clear_buffers.Z)
+        clear_mask |= GL_DEPTH_BUFFER_BIT;
+
+    if (clear_mask == 0)
+        return;
+
+    auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
+
+    // TODO(Subv): Support clearing only partial colors.
+    glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
+                 regs.clear_color[3]);
+    glClearDepth(regs.clear_depth);
+
+    glClear(clear_mask);
+
+    // Mark framebuffer surfaces as dirty
+    if (dirty_color_surface != nullptr) {
+        res_cache.MarkSurfaceAsDirty(dirty_color_surface);
+    }
+    if (dirty_depth_surface != nullptr) {
+        res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
+    }
+}
+
+void RasterizerOpenGL::DrawArrays() {
+    if (accelerate_draw == AccelDraw::Disabled)
+        return;
+
+    MICROPROFILE_SCOPE(OpenGL_Drawing);
+    const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
+
+    auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
+
+    SyncBlendState();
+    SyncCullMode();
+
+    // TODO(bunnei): Sync framebuffer_scale uniform here
+    // TODO(bunnei): Sync scissorbox uniform(s) here
+
     // Draw the vertex batch
     const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
     const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
@@ -439,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() {
     state.Apply();
 
     // Mark framebuffer surfaces as dirty
-    if (color_surface != nullptr && write_color_fb) {
-        res_cache.MarkSurfaceAsDirty(color_surface);
+    if (dirty_color_surface != nullptr) {
+        res_cache.MarkSurfaceAsDirty(dirty_color_surface);
     }
-    if (depth_surface != nullptr && write_depth_fb) {
-        res_cache.MarkSurfaceAsDirty(depth_surface);
+    if (dirty_depth_surface != nullptr) {
+        res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
     }
 }
 
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 493aa39e5a9b4bb0d2e7834d2c198848d2740d41..7738f40b18211fd343fbec3a5b66e526212f0478 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -7,6 +7,7 @@
 #include <array>
 #include <cstddef>
 #include <memory>
+#include <utility>
 #include <vector>
 #include <glad/glad.h>
 #include "common/common_types.h"
@@ -28,6 +29,7 @@ public:
     ~RasterizerOpenGL() override;
 
     void DrawArrays() override;
+    void Clear() override;
     void NotifyMaxwellRegisterChanged(u32 method) override;
     void FlushAll() override;
     void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
@@ -81,6 +83,10 @@ private:
         u32 border_color_a;
     };
 
+    /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
+    /// surfaces if writing was enabled.
+    std::pair<Surface, Surface> ConfigureFramebuffers();
+
     /// Binds the framebuffer color and depth surface
     void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
                                  bool has_stencil);