From 5a9df3c6753e66519acaa13685abb89231e45ade Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Tue, 3 Jul 2018 22:32:59 -0500
Subject: [PATCH] GPU: Only configure the used framebuffers during clear.

Don't try to configure the color buffer if it is not being cleared, it may not be completely valid at this point.
---
 .../renderer_opengl/gl_rasterizer.cpp         | 20 +++++++----
 .../renderer_opengl/gl_rasterizer.h           |  2 +-
 .../renderer_opengl/gl_rasterizer_cache.cpp   | 34 +++++++++++++++----
 .../renderer_opengl/gl_rasterizer_cache.h     |  9 +++--
 4 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 43dbf4da92..e516eb1adf 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -297,7 +297,8 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
     return true;
 }
 
-std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
+std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb,
+                                                                    bool using_depth_fb) {
     const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
 
     // Sync the depth test state before configuring the framebuffer surfaces.
@@ -306,9 +307,6 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
     // TODO(bunnei): Implement this
     const bool has_stencil = false;
 
-    const bool using_color_fb = true;
-    const bool using_depth_fb = regs.zeta.Address() != 0;
-
     const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
 
     const bool write_color_fb =
@@ -358,18 +356,25 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
 void RasterizerOpenGL::Clear() {
     const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
 
+    bool use_color_fb = false;
+    bool use_depth_fb = false;
+
     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;
+        use_color_fb = true;
     }
-    if (regs.clear_buffers.Z)
+    if (regs.clear_buffers.Z) {
         clear_mask |= GL_DEPTH_BUFFER_BIT;
+        use_depth_fb = true;
+    }
 
     if (clear_mask == 0)
         return;
 
-    auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
+    auto [dirty_color_surface, dirty_depth_surface] =
+        ConfigureFramebuffers(use_color_fb, use_depth_fb);
 
     // TODO(Subv): Support clearing only partial colors.
     glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
@@ -394,7 +399,8 @@ void RasterizerOpenGL::DrawArrays() {
     MICROPROFILE_SCOPE(OpenGL_Drawing);
     const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
 
-    auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
+    auto [dirty_color_surface, dirty_depth_surface] =
+        ConfigureFramebuffers(true, regs.zeta.Address() != 0);
 
     SyncBlendState();
     SyncCullMode();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 7738f40b18..c406142e49 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -85,7 +85,7 @@ private:
 
     /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
     /// surfaces if writing was enabled.
-    std::pair<Surface, Surface> ConfigureFramebuffers();
+    std::pair<Surface, Surface> ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb);
 
     /// Binds the framebuffer color and depth surface
     void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 3a00d93831..50469c05cc 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -65,6 +65,25 @@ struct FormatTuple {
     return params;
 }
 
+/*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer(
+    const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, Tegra::GPUVAddr zeta_address,
+    Tegra::DepthFormat format) {
+
+    SurfaceParams params{};
+    params.addr = zeta_address;
+    params.is_tiled = true;
+    params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
+    params.pixel_format = PixelFormatFromDepthFormat(format);
+    params.component_type = ComponentTypeFromDepthFormat(format);
+    params.type = GetFormatType(params.pixel_format);
+    params.size_in_bytes = params.SizeInBytes();
+    params.width = config.width;
+    params.height = config.height;
+    params.unaligned_height = config.height;
+    params.size_in_bytes = params.SizeInBytes();
+    return params;
+}
+
 static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
     {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8
     {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false},    // B5G6R5
@@ -461,15 +480,16 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
     LOG_WARNING(Render_OpenGL, "hard-coded for render target 0!");
 
     // get color and depth surfaces
-    const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])};
-    SurfaceParams depth_params{color_params};
+    SurfaceParams color_params{};
+    SurfaceParams depth_params{};
+
+    if (using_color_fb) {
+        color_params = SurfaceParams::CreateForFramebuffer(regs.rt[0]);
+    }
 
     if (using_depth_fb) {
-        depth_params.addr = regs.zeta.Address();
-        depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(regs.zeta.format);
-        depth_params.component_type = SurfaceParams::ComponentTypeFromDepthFormat(regs.zeta.format);
-        depth_params.type = SurfaceParams::GetFormatType(depth_params.pixel_format);
-        depth_params.size_in_bytes = depth_params.SizeInBytes();
+        depth_params =
+            SurfaceParams::CreateForDepthBuffer(regs.rt[0], regs.zeta.Address(), regs.zeta.format);
     }
 
     MathUtil::Rectangle<u32> color_rect{};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 7aaf371bda..8005a81b83 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -326,13 +326,18 @@ struct SurfaceParams {
         return addr <= (region_addr + region_size) && region_addr <= (addr + size_in_bytes);
     }
 
-    /// Creates SurfaceParams from a texture configation
+    /// Creates SurfaceParams from a texture configuration
     static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
 
-    /// Creates SurfaceParams from a framebuffer configation
+    /// Creates SurfaceParams from a framebuffer configuration
     static SurfaceParams CreateForFramebuffer(
         const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
 
+    /// Creates SurfaceParams for a depth buffer configuration
+    static SurfaceParams CreateForDepthBuffer(
+        const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config,
+        Tegra::GPUVAddr zeta_address, Tegra::DepthFormat format);
+
     Tegra::GPUVAddr addr;
     bool is_tiled;
     u32 block_height;