From 60a39805615fb0480eb57416f5e9ec17e7c91ce4 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Thu, 23 Sep 2021 03:14:10 +0200
Subject: [PATCH 1/2] Vulkan Rasterizer: Correct DepthBias/PolygonOffset on
 Vulkan.

---
 src/video_core/dirty_flags.h                      |  3 +++
 src/video_core/renderer_vulkan/vk_rasterizer.cpp  | 14 ++++++++++++--
 src/video_core/renderer_vulkan/vk_state_tracker.h |  3 ++-
 src/video_core/texture_cache/texture_cache.h      |  3 +++
 src/video_core/vulkan_common/vulkan_device.cpp    |  4 ++++
 src/video_core/vulkan_common/vulkan_device.h      |  5 +++++
 6 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/video_core/dirty_flags.h b/src/video_core/dirty_flags.h
index 504465d3fb..f0d545f905 100644
--- a/src/video_core/dirty_flags.h
+++ b/src/video_core/dirty_flags.h
@@ -38,6 +38,9 @@ enum : u8 {
 
     Shaders,
 
+    // Special entries
+    DepthBiasGlobal,
+
     LastCommonEntry,
 };
 
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 3bcd6d6cc6..04ecc034dc 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -627,9 +627,19 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
     if (!state_tracker.TouchDepthBias()) {
         return;
     }
-    scheduler.Record([constant = regs.polygon_offset_units, clamp = regs.polygon_offset_clamp,
+    float units = regs.polygon_offset_units / 2.0f;
+    const bool is_d24 = regs.zeta.format == Tegra::DepthFormat::S8_UINT_Z24_UNORM ||
+                        regs.zeta.format == Tegra::DepthFormat::D24X8_UNORM ||
+                        regs.zeta.format == Tegra::DepthFormat::D24S8_UNORM ||
+                        regs.zeta.format == Tegra::DepthFormat::D24C8_UNORM;
+    if (is_d24 && !device.SupportsD24DepthBuffer()) {
+        const double f = static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
+        units = static_cast<float>(static_cast<double>(units) * f);
+    }
+
+    scheduler.Record([constant = units, clamp = regs.polygon_offset_clamp,
                       factor = regs.polygon_offset_factor](vk::CommandBuffer cmdbuf) {
-        cmdbuf.SetDepthBias(constant, clamp, factor / 2.0f);
+        cmdbuf.SetDepthBias(constant, clamp, factor);
     });
 }
 
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h
index d90935f528..2f2d6b31f0 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.h
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.h
@@ -79,7 +79,8 @@ public:
     }
 
     bool TouchDepthBias() {
-        return Exchange(Dirty::DepthBias, false);
+        return Exchange(Dirty::DepthBias, false) ||
+               Exchange(VideoCommon::Dirty::DepthBiasGlobal, false);
     }
 
     bool TouchBlendConstants() {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 24b8092429..c6e50bb5f0 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -216,6 +216,7 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
         BindRenderTarget(&render_targets.depth_buffer_id, FindDepthBuffer(is_clear));
     }
     const ImageViewId depth_buffer_id = render_targets.depth_buffer_id;
+
     PrepareImageView(depth_buffer_id, true, is_clear && IsFullClear(depth_buffer_id));
 
     for (size_t index = 0; index < NUM_RT; ++index) {
@@ -225,6 +226,8 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
         maxwell3d.regs.render_area.width,
         maxwell3d.regs.render_area.height,
     };
+
+    flags[Dirty::DepthBiasGlobal] = true;
 }
 
 template <class P>
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index c2ec9f76ab..3a048900b0 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -618,6 +618,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
         is_float16_supported = false;
     }
 
+    supports_d24_depth =
+        IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT,
+                          VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, FormatType::Optimal);
+
     graphics_queue = logical.GetQueue(graphics_family);
     present_queue = logical.GetQueue(present_family);
 }
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index bc180a32a1..f14e4001ec 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -327,6 +327,10 @@ public:
         return sets_per_pool;
     }
 
+    bool SupportsD24DepthBuffer() const {
+        return supports_d24_depth;
+    }
+
 private:
     /// Checks if the physical device is suitable.
     void CheckSuitability(bool requires_swapchain) const;
@@ -419,6 +423,7 @@ private:
     bool nv_device_diagnostics_config{};    ///< Support for VK_NV_device_diagnostics_config.
     bool has_renderdoc{};                   ///< Has RenderDoc attached
     bool has_nsight_graphics{};             ///< Has Nsight Graphics attached
+    bool supports_d24_depth{};              ///< Supports D24 depth buffers.
 
     // Telemetry parameters
     std::string vendor_name;                       ///< Device's driver name.

From ad8afaf1ef0c2f6c9ecb4e3670d4a3e4192ab0a9 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Sun, 17 Oct 2021 03:49:18 +0200
Subject: [PATCH 2/2] Vulran Rasterizer: address feedback.

---
 src/video_core/renderer_vulkan/vk_rasterizer.cpp | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 04ecc034dc..30b47a7a0f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -633,10 +633,12 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
                         regs.zeta.format == Tegra::DepthFormat::D24S8_UNORM ||
                         regs.zeta.format == Tegra::DepthFormat::D24C8_UNORM;
     if (is_d24 && !device.SupportsD24DepthBuffer()) {
-        const double f = static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
-        units = static_cast<float>(static_cast<double>(units) * f);
+        // the base formulas can be obtained from here:
+        //   https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
+        const double rescale_factor =
+            static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
+        units = static_cast<float>(static_cast<double>(units) * rescale_factor);
     }
-
     scheduler.Record([constant = units, clamp = regs.polygon_offset_clamp,
                       factor = regs.polygon_offset_factor](vk::CommandBuffer cmdbuf) {
         cmdbuf.SetDepthBias(constant, clamp, factor);