From 5134a4b3c53e8effd672feea0562c77feb0c67b5 Mon Sep 17 00:00:00 2001
From: Philip Rebohle <philip.rebohle@tu-dortmund.de>
Date: Mon, 13 Jan 2025 11:22:25 +0100
Subject: [PATCH] [dxvk] Move HUD update and rendering into swapchain blitter

---
 src/d3d11/d3d11_swapchain.cpp       | 22 ++++-----------
 src/d3d11/d3d11_swapchain.h         |  4 ---
 src/d3d9/d3d9_swapchain.cpp         | 44 +++++++++--------------------
 src/d3d9/d3d9_swapchain.h           |  8 ++----
 src/dxvk/dxvk_swapchain_blitter.cpp | 24 ++++++++--------
 src/dxvk/dxvk_swapchain_blitter.h   | 20 +++++--------
 6 files changed, 40 insertions(+), 82 deletions(-)

diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp
index d86471874..ba8550f78 100644
--- a/src/d3d11/d3d11_swapchain.cpp
+++ b/src/d3d11/d3d11_swapchain.cpp
@@ -68,7 +68,6 @@ namespace dxvk {
     CreatePresenter();
     CreateBackBuffers();
     CreateBlitter();
-    CreateHud();
   }
 
 
@@ -416,7 +415,6 @@ namespace dxvk {
       cBackBuffer     = backBuffer->createView(viewInfo),
       cSwapImage      = GetBackBufferView(),
       cSync           = sync,
-      cHud            = m_hud,
       cPresenter      = m_presenter,
       cColorSpace     = m_colorSpace,
       cFrameId        = m_frameId
@@ -433,17 +431,10 @@ namespace dxvk {
       // swap chain and render the HUD if we have one.
       auto contextObjects = ctx->beginExternalRendering();
 
-      cBlitter->beginPresent(contextObjects,
+      cBlitter->present(contextObjects,
         cBackBuffer, VkRect2D(),
         cSwapImage, VkRect2D());
 
-      if (cHud != nullptr) {
-        cHud->update();
-        cHud->render(contextObjects, cBackBuffer);
-      }
-
-      cBlitter->endPresent(contextObjects, cBackBuffer);
-
       // Submit current command list and present
       ctx->synchronizeWsi(cSync);
       ctx->flushCommandList(nullptr);
@@ -582,15 +573,12 @@ namespace dxvk {
 
 
   void D3D11SwapChain::CreateBlitter() {
-    m_blitter = new DxvkSwapchainBlitter(m_device);    
-  }
+    Rc<hud::Hud> hud = hud::Hud::createHud(m_device);
 
+    if (hud)
+      hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
 
-  void D3D11SwapChain::CreateHud() {
-    m_hud = hud::Hud::createHud(m_device);
-
-    if (m_hud != nullptr)
-      m_hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
+    m_blitter = new DxvkSwapchainBlitter(m_device, std::move(hud));
   }
 
 
diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h
index 74149f9bf..ccd84a382 100644
--- a/src/d3d11/d3d11_swapchain.h
+++ b/src/d3d11/d3d11_swapchain.h
@@ -108,8 +108,6 @@ namespace dxvk {
 
     Rc<DxvkSwapchainBlitter>  m_blitter;
 
-    Rc<hud::Hud>              m_hud;
-
     small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers;
     DxvkSubmitStatus          m_presentStatus;
 
@@ -142,8 +140,6 @@ namespace dxvk {
 
     void CreateBlitter();
 
-    void CreateHud();
-
     void DestroyFrameLatencyEvent();
 
     void SyncFrameLatency();
diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp
index a662a7681..4bad06506 100644
--- a/src/d3d9/d3d9_swapchain.cpp
+++ b/src/d3d9/d3d9_swapchain.cpp
@@ -43,7 +43,6 @@ namespace dxvk {
       throw DxvkError("D3D9: Failed to create swapchain backbuffers");
 
     CreateBlitter();
-    CreateHud();
 
     InitRamp();
 
@@ -863,7 +862,6 @@ namespace dxvk {
         cDstRect        = dstRect,
         cRepeat         = i,
         cSync           = sync,
-        cHud            = m_hud,
         cFrameId        = m_wctx->frameId
       ] (DxvkContext* ctx) {
         // Update back buffer color space as necessary
@@ -877,18 +875,9 @@ namespace dxvk {
         // Blit back buffer onto Vulkan swap chain
         auto contextObjects = ctx->beginExternalRendering();
 
-        cBlitter->beginPresent(contextObjects,
+        cBlitter->present(contextObjects,
           cDstView, cDstRect, cSrcView, cSrcRect);
 
-        if (cHud) {
-          if (!cRepeat)
-            cHud->update();
-
-          cHud->render(contextObjects, cDstView);
-        }
-
-        cBlitter->endPresent(contextObjects, cDstView);
-
         // Submit command list and present
         ctx->synchronizeWsi(cSync);
         ctx->flushCommandList(nullptr);
@@ -1047,23 +1036,20 @@ namespace dxvk {
 
 
   void D3D9SwapChainEx::CreateBlitter() {
-    m_blitter = new DxvkSwapchainBlitter(m_device);
-  }
+    Rc<hud::Hud> hud = hud::Hud::createHud(m_device);
 
-
-  void D3D9SwapChainEx::CreateHud() {
-    m_hud = hud::Hud::createHud(m_device);
-
-    if (m_hud != nullptr) {
-      m_hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
-      m_hud->addItem<hud::HudSamplerCount>("samplers", -1, m_parent);
-      m_hud->addItem<hud::HudFixedFunctionShaders>("ffshaders", -1, m_parent);
-      m_hud->addItem<hud::HudSWVPState>("swvp", -1, m_parent);
+    if (hud) {
+      m_apiHud = hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
+      hud->addItem<hud::HudSamplerCount>("samplers", -1, m_parent);
+      hud->addItem<hud::HudFixedFunctionShaders>("ffshaders", -1, m_parent);
+      hud->addItem<hud::HudSWVPState>("swvp", -1, m_parent);
 
 #ifdef D3D9_ALLOW_UNMAPPING
-      m_hud->addItem<hud::HudTextureMemory>("memory", -1, m_parent);
+      hud->addItem<hud::HudTextureMemory>("memory", -1, m_parent);
 #endif
     }
+
+    m_blitter = new DxvkSwapchainBlitter(m_device, std::move(hud));
   }
 
 
@@ -1095,8 +1081,8 @@ namespace dxvk {
   }
 
   void D3D9SwapChainEx::SetApiName(const char* name) {
-    m_apiName = name;
-    CreateHud();
+    if (m_apiHud && name)
+      m_apiHud->setApiName(name);
   }
 
   uint32_t D3D9SwapChainEx::GetActualFrameLatency() {
@@ -1306,11 +1292,7 @@ namespace dxvk {
 
 
   std::string D3D9SwapChainEx::GetApiName() {
-    if (m_apiName == nullptr) {
-      return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9";
-    } else {
-      return m_apiName;
-    }
+    return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9";
   }
 
   D3D9VkExtSwapchain::D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain)
diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h
index c413a73c0..2e6c8c50f 100644
--- a/src/d3d9/d3d9_swapchain.h
+++ b/src/d3d9/d3d9_swapchain.h
@@ -156,8 +156,6 @@ namespace dxvk {
 
     D3D9WindowContext*        m_wctx = nullptr;
 
-    Rc<hud::Hud>              m_hud;
-
     std::vector<Com<D3D9Surface, false>> m_backBuffers;
     
     RECT                      m_srcRect;
@@ -176,12 +174,12 @@ namespace dxvk {
 
     double                    m_displayRefreshRate = 0.0;
 
-    const char*               m_apiName  = nullptr;
-
     bool                      m_warnedAboutGDIFallback = false;
 
     VkColorSpaceKHR           m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
 
+    Rc<hud::HudClientApiItem> m_apiHud;
+
     std::optional<VkHdrMetadataEXT> m_hdrMetadata;
     bool m_unlockAdditionalFormats = false;
 
@@ -201,8 +199,6 @@ namespace dxvk {
 
     void CreateBlitter();
 
-    void CreateHud();
-
     void InitRamp();
 
     void UpdateTargetFrameRate(uint32_t SyncInterval);
diff --git a/src/dxvk/dxvk_swapchain_blitter.cpp b/src/dxvk/dxvk_swapchain_blitter.cpp
index 40ae2e527..18d856554 100644
--- a/src/dxvk/dxvk_swapchain_blitter.cpp
+++ b/src/dxvk/dxvk_swapchain_blitter.cpp
@@ -9,8 +9,10 @@
 
 namespace dxvk {
   
-  DxvkSwapchainBlitter::DxvkSwapchainBlitter(const Rc<DxvkDevice>& device)
-  : m_device(device),
+  DxvkSwapchainBlitter::DxvkSwapchainBlitter(
+    const Rc<DxvkDevice>& device,
+    const Rc<hud::Hud>&   hud)
+  : m_device(device), m_hud(hud),
     m_setLayout(createSetLayout()),
     m_pipelineLayout(createPipelineLayout()) {
     this->createSampler();
@@ -35,7 +37,7 @@ namespace dxvk {
   }
 
 
-  void DxvkSwapchainBlitter::beginPresent(
+  void DxvkSwapchainBlitter::present(
     const DxvkContextObjects& ctx,
     const Rc<DxvkImageView>&  dstView,
           VkRect2D            dstRect,
@@ -43,6 +45,10 @@ namespace dxvk {
           VkRect2D            srcRect) {
     std::unique_lock lock(m_mutex);
 
+    // Update HUD, if we have one
+    if (m_hud)
+      m_hud->update();
+
     // Fix up default present areas if necessary
     if (!dstRect.extent.width || !dstRect.extent.height) {
       dstRect.offset = { 0, 0 };
@@ -102,13 +108,9 @@ namespace dxvk {
 
     performDraw(ctx, dstView, dstRect,
       srcView, srcRect, VK_FALSE);
-  }
 
-
-  void DxvkSwapchainBlitter::endPresent(
-    const DxvkContextObjects& ctx,
-    const Rc<DxvkImageView>&  dstView) {
-    std::unique_lock lock(m_mutex);
+    if (m_hud)
+      m_hud->render(ctx, dstView);
 
     if (m_cursorView) {
       VkRect2D cursorArea = { };
@@ -121,7 +123,7 @@ namespace dxvk {
 
     ctx.cmd->cmdEndRendering();
 
-    VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
+    barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
     barrier.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
     barrier.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
     barrier.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT;
@@ -133,7 +135,7 @@ namespace dxvk {
     barrier.image = dstView->image()->handle();
     barrier.subresourceRange = dstView->imageSubresources();
 
-    VkDependencyInfo depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
+    depInfo = { VK_STRUCTURE_TYPE_DEPENDENCY_INFO };
     depInfo.imageMemoryBarrierCount = 1;
     depInfo.pImageMemoryBarriers = &barrier;
 
diff --git a/src/dxvk/dxvk_swapchain_blitter.h b/src/dxvk/dxvk_swapchain_blitter.h
index 5f38a7ee0..210d4f989 100644
--- a/src/dxvk/dxvk_swapchain_blitter.h
+++ b/src/dxvk/dxvk_swapchain_blitter.h
@@ -4,6 +4,8 @@
 #include <thread>
 #include <unordered_map>
 
+#include "./hud/dxvk_hud.h"
+
 #include "../util/thread.h"
 
 #include "../dxvk/dxvk_device.h"
@@ -82,7 +84,9 @@ namespace dxvk {
     
   public:
 
-    DxvkSwapchainBlitter(const Rc<DxvkDevice>& device);
+    DxvkSwapchainBlitter(
+      const Rc<DxvkDevice>& device,
+      const Rc<hud::Hud>&   hud);
     ~DxvkSwapchainBlitter();
 
     /**
@@ -98,24 +102,13 @@ namespace dxvk {
      * \param [in] srcColorSpace Image color space
      * \param [in] srcRect Source rectangle to present
      */
-    void beginPresent(
+    void present(
       const DxvkContextObjects& ctx,
       const Rc<DxvkImageView>&  dstView,
             VkRect2D            dstRect,
       const Rc<DxvkImageView>&  srcView,
             VkRect2D            srcRect);
 
-    /**
-     * \brief Finalizes presentation commands
-     *
-     * Finishes rendering and prepares the image for presentation.
-     * \param [in] ctx Context objects
-     * \param [in] dstView Swap chain image view
-     */
-    void endPresent(
-      const DxvkContextObjects& ctx,
-      const Rc<DxvkImageView>&  dstView);
-
     /**
      * \brief Sets gamma ramp
      *
@@ -176,6 +169,7 @@ namespace dxvk {
     };
 
     Rc<DxvkDevice>      m_device;
+    Rc<hud::Hud>        m_hud;
 
     ShaderModule        m_shaderVsBlit;
     ShaderModule        m_shaderFsCopy;