From 8b4852be16602dd5efc70f38fc2b195a2fcbdaf0 Mon Sep 17 00:00:00 2001
From: Philip Rebohle <philip.rebohle@tu-dortmund.de>
Date: Wed, 6 Jun 2018 12:45:45 +0200
Subject: [PATCH] [dxvk] Make depth bias a dynamic state

Works around an issue with some games not setting the D3D11 depth
bias state correctly, which can result in an excessive number of
pipelines being compiled.
---
 src/dxvk/dxvk_cmdlist.h       | 11 +++++++++++
 src/dxvk/dxvk_context.cpp     | 26 +++++++++++++++++++-------
 src/dxvk/dxvk_context_state.h |  9 +++++++++
 src/dxvk/dxvk_graphics.cpp    |  9 +++++----
 src/dxvk/dxvk_graphics.h      |  3 ---
 5 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h
index 756aa330..f91d211e 100644
--- a/src/dxvk/dxvk_cmdlist.h
+++ b/src/dxvk/dxvk_cmdlist.h
@@ -516,6 +516,17 @@ namespace dxvk {
       m_vkd->vkCmdSetBlendConstants(m_execBuffer, blendConstants);
     }
     
+
+    void cmdSetDepthBias(
+            float                   depthBiasConstantFactor,
+            float                   depthBiasClamp,
+            float                   depthBiasSlopeFactor) {
+      m_vkd->vkCmdSetDepthBias(m_execBuffer,
+        depthBiasConstantFactor,
+        depthBiasClamp,
+        depthBiasSlopeFactor);
+    }
+
     
     void cmdSetScissor(
             uint32_t                firstScissor,
diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp
index 927fafa8..8816e206 100644
--- a/src/dxvk/dxvk_context.cpp
+++ b/src/dxvk/dxvk_context.cpp
@@ -1450,11 +1450,14 @@ namespace dxvk {
     m_state.gp.state.rsCullMode          = rs.cullMode;
     m_state.gp.state.rsFrontFace         = rs.frontFace;
     m_state.gp.state.rsDepthBiasEnable   = rs.depthBiasEnable;
-    m_state.gp.state.rsDepthBiasConstant = rs.depthBiasConstant;
-    m_state.gp.state.rsDepthBiasClamp    = rs.depthBiasClamp;
-    m_state.gp.state.rsDepthBiasSlope    = rs.depthBiasSlope;
-    
-    m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
+
+    m_state.ds.depthBiasConstant = rs.depthBiasConstant;
+    m_state.ds.depthBiasClamp    = rs.depthBiasClamp;
+    m_state.ds.depthBiasSlope    = rs.depthBiasSlope;
+
+    m_flags.set(
+      DxvkContextFlag::GpDirtyPipelineState,
+      DxvkContextFlag::GpDirtyDepthBias);
   }
   
   
@@ -1718,7 +1721,8 @@ namespace dxvk {
       m_flags.set(
         DxvkContextFlag::GpDirtyBlendConstants,
         DxvkContextFlag::GpDirtyStencilRef,
-        DxvkContextFlag::GpDirtyViewport);
+        DxvkContextFlag::GpDirtyViewport,
+        DxvkContextFlag::GpDirtyDepthBias);
     }
   }
   
@@ -2001,10 +2005,18 @@ namespace dxvk {
     if (m_flags.test(DxvkContextFlag::GpDirtyStencilRef))
       m_cmd->cmdSetStencilReference(VK_STENCIL_FRONT_AND_BACK, m_state.om.stencilReference);
     
+    if (m_flags.test(DxvkContextFlag::GpDirtyDepthBias)) {
+      m_cmd->cmdSetDepthBias(
+        m_state.ds.depthBiasConstant,
+        m_state.ds.depthBiasClamp,
+        m_state.ds.depthBiasSlope);
+    }
+    
     m_flags.clr(
       DxvkContextFlag::GpDirtyBlendConstants,
       DxvkContextFlag::GpDirtyStencilRef,
-      DxvkContextFlag::GpDirtyViewport);
+      DxvkContextFlag::GpDirtyViewport,
+      DxvkContextFlag::GpDirtyDepthBias);
   }
   
   
diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h
index 03cf9937..6e189da4 100644
--- a/src/dxvk/dxvk_context_state.h
+++ b/src/dxvk/dxvk_context_state.h
@@ -32,6 +32,7 @@ namespace dxvk {
     GpDirtyBlendConstants,      ///< Blend constants have changed
     GpDirtyStencilRef,          ///< Stencil reference has changed
     GpDirtyViewport,            ///< Viewport state has changed
+    GpDirtyDepthBias,           ///< Depth bias has changed
     
     CpDirtyPipeline,            ///< Compute pipeline binding are out of date
     CpDirtyPipelineState,       ///< Compute pipeline needs to be recompiled
@@ -55,6 +56,13 @@ namespace dxvk {
     std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports    = { };
     std::array<VkRect2D,   DxvkLimits::MaxNumViewports> scissorRects = { };
   };
+
+
+  struct DxvkDynamicDepthState {
+    float depthBiasConstant = 0.0f;
+    float depthBiasClamp    = 0.0f;
+    float depthBiasSlope    = 0.0f;
+  };
   
   
   struct DxvkOutputMergerState {
@@ -103,6 +111,7 @@ namespace dxvk {
   struct DxvkContextState {
     DxvkVertexInputState      vi;
     DxvkViewportState         vp;
+    DxvkDynamicDepthState     ds;
     DxvkOutputMergerState     om;
     
     DxvkGraphicsPipelineState gp;
diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp
index 844f676d..36357e0c 100644
--- a/src/dxvk/dxvk_graphics.cpp
+++ b/src/dxvk/dxvk_graphics.cpp
@@ -197,9 +197,10 @@ namespace dxvk {
       this->logPipelineState(LogLevel::Debug, state);
     }
     
-    std::array<VkDynamicState, 4> dynamicStates = {
+    std::array<VkDynamicState, 5> dynamicStates = {
       VK_DYNAMIC_STATE_VIEWPORT,
       VK_DYNAMIC_STATE_SCISSOR,
+      VK_DYNAMIC_STATE_DEPTH_BIAS,
       VK_DYNAMIC_STATE_BLEND_CONSTANTS,
       VK_DYNAMIC_STATE_STENCIL_REFERENCE,
     };
@@ -290,9 +291,9 @@ namespace dxvk {
     rsInfo.cullMode               = state.rsCullMode;
     rsInfo.frontFace              = state.rsFrontFace;
     rsInfo.depthBiasEnable        = state.rsDepthBiasEnable;
-    rsInfo.depthBiasConstantFactor= state.rsDepthBiasConstant;
-    rsInfo.depthBiasClamp         = state.rsDepthBiasClamp;
-    rsInfo.depthBiasSlopeFactor   = state.rsDepthBiasSlope;
+    rsInfo.depthBiasConstantFactor= 0.0f;
+    rsInfo.depthBiasClamp         = 0.0f;
+    rsInfo.depthBiasSlopeFactor   = 0.0f;
     rsInfo.lineWidth              = 1.0f;
     
     VkPipelineMultisampleStateCreateInfo msInfo;
diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h
index ad1de14b..9c9347d2 100644
--- a/src/dxvk/dxvk_graphics.h
+++ b/src/dxvk/dxvk_graphics.h
@@ -53,9 +53,6 @@ namespace dxvk {
     VkCullModeFlags                     rsCullMode;
     VkFrontFace                         rsFrontFace;
     VkBool32                            rsDepthBiasEnable;
-    float                               rsDepthBiasConstant;
-    float                               rsDepthBiasClamp;
-    float                               rsDepthBiasSlope;
     uint32_t                            rsViewportCount;
     
     VkSampleCountFlagBits               msSampleCount;