From 581a7d785bb4936c92d320f17d3d824e244eee5a Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Wed, 7 Dec 2022 00:28:35 +0100
Subject: [PATCH] Rasterizer: Setup skeleton for Host Conditional rendering

---
 src/video_core/engines/maxwell_3d.cpp         | 14 +++++++---
 src/video_core/rasterizer_interface.h         |  4 +++
 .../renderer_opengl/gl_rasterizer.cpp         | 15 ++++++++++
 .../renderer_opengl/gl_rasterizer.h           |  1 +
 .../renderer_vulkan/vk_rasterizer.cpp         | 28 +++++++++++++++----
 .../renderer_vulkan/vk_rasterizer.h           |  1 +
 6 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d44a5cabfc..943a69935d 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -16,7 +16,6 @@
 #include "video_core/rasterizer_interface.h"
 #include "video_core/textures/texture.h"
 
-
 namespace Tegra::Engines {
 
 using VideoCore::QueryType;
@@ -538,13 +537,17 @@ void Maxwell3D::ProcessQueryGet() {
 void Maxwell3D::ProcessQueryCondition() {
     const GPUVAddr condition_address{regs.render_enable.Address()};
     switch (regs.render_enable_override) {
-    case Regs::RenderEnable::Override::AlwaysRender:
+    case Regs::RenderEnable::Override::AlwaysRender: {
         execute_on = true;
         break;
     case Regs::RenderEnable::Override::NeverRender:
         execute_on = false;
         break;
-    case Regs::RenderEnable::Override::UseRenderEnable:
+    case Regs::RenderEnable::Override::UseRenderEnable: {
+        if (rasterizer->AccelerateConditionalRendering()) {
+            execute_on = true;
+            return;
+        }
         switch (regs.render_enable.mode) {
         case Regs::RenderEnable::Mode::True: {
             execute_on = true;
@@ -582,6 +585,8 @@ void Maxwell3D::ProcessQueryCondition() {
         }
         break;
     }
+    }
+    }
 }
 
 void Maxwell3D::ProcessCounterReset() {
@@ -618,7 +623,8 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
 }
 
 void Maxwell3D::ProcessCBBind(size_t stage_index) {
-    // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
+    // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader
+    // stage.
     const auto& bind_data = regs.bind_groups[stage_index];
     auto& buffer = state.shader_stages[stage_index].const_buffers[bind_data.shader_slot];
     buffer.enabled = bind_data.valid.Value() != 0;
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 6d8d2b6665..f44c7df506 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -127,6 +127,10 @@ public:
     /// Notify rasterizer that a frame is about to finish
     virtual void TickFrame() = 0;
 
+    virtual bool AccelerateConditionalRendering() {
+        return false;
+    }
+
     /// Attempt to use a faster method to perform a surface copy
     [[nodiscard]] virtual bool AccelerateSurfaceCopy(
         const Tegra::Engines::Fermi2D::Surface& src, const Tegra::Engines::Fermi2D::Surface& dst,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index d58dcedeac..ed7558073f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -525,6 +525,21 @@ void RasterizerOpenGL::TickFrame() {
     }
 }
 
+bool RasterizerOpenGL::AccelerateConditionalRendering() {
+    if (Settings::IsGPULevelHigh()) {
+        // Reimplement Host conditional rendering.
+        return false;
+    }
+    // Medium / Low Hack: stub any checks on queries writen into the buffer cache.
+    const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()};
+    Maxwell::ReportSemaphore::Compare cmp;
+    if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp),
+                                  VideoCommon::CacheType::BufferCache)) {
+        return true;
+    }
+    return false;
+}
+
 bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
                                              const Tegra::Engines::Fermi2D::Surface& dst,
                                              const Tegra::Engines::Fermi2D::Config& copy_config) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 94e65d64bf..d119c2b667 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -100,6 +100,7 @@ public:
     void TiledCacheBarrier() override;
     void FlushCommands() override;
     void TickFrame() override;
+    bool AccelerateConditionalRendering() override;
     bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
                                const Tegra::Engines::Fermi2D::Surface& dst,
                                const Tegra::Engines::Fermi2D::Config& copy_config) override;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 463c49f9c9..3ab2defa22 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -600,6 +600,21 @@ void RasterizerVulkan::TickFrame() {
     }
 }
 
+bool RasterizerVulkan::AccelerateConditionalRendering() {
+    if (Settings::IsGPULevelHigh()) {
+        // TODO(Blinkhawk): Reimplement Host conditional rendering.
+        return false;
+    }
+    // Medium / Low Hack: stub any checks on queries writen into the buffer cache.
+    const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()};
+    Maxwell::ReportSemaphore::Compare cmp;
+    if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp),
+                                  VideoCommon::CacheType::BufferCache)) {
+        return true;
+    }
+    return false;
+}
+
 bool RasterizerVulkan::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
                                              const Tegra::Engines::Fermi2D::Surface& dst,
                                              const Tegra::Engines::Fermi2D::Config& copy_config) {
@@ -995,7 +1010,8 @@ void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& re
     };
     const u32 topology_index = static_cast<u32>(maxwell3d->draw_manager->GetDrawState().topology);
     const u32 enable = enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]];
-    scheduler.Record([enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable != 0); });
+    scheduler.Record(
+        [enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable != 0); });
 }
 
 void RasterizerVulkan::UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
@@ -1012,11 +1028,11 @@ void RasterizerVulkan::UpdateDepthClampEnable(Tegra::Engines::Maxwell3D::Regs& r
         return;
     }
     bool is_enabled = !(regs.viewport_clip_control.geometry_clip ==
-                                 Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
-                             regs.viewport_clip_control.geometry_clip ==
-                                 Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
-                             regs.viewport_clip_control.geometry_clip ==
-                                 Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
+                            Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
+                        regs.viewport_clip_control.geometry_clip ==
+                            Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
+                        regs.viewport_clip_control.geometry_clip ==
+                            Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
     scheduler.Record(
         [is_enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthClampEnableEXT(is_enabled); });
 }
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 82b28a54a4..c06182807f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -96,6 +96,7 @@ public:
     void TiledCacheBarrier() override;
     void FlushCommands() override;
     void TickFrame() override;
+    bool AccelerateConditionalRendering() override;
     bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
                                const Tegra::Engines::Fermi2D::Surface& dst,
                                const Tegra::Engines::Fermi2D::Config& copy_config) override;