From 6b366afb05ca48e2ba6dca2d517d56e05d9092e6 Mon Sep 17 00:00:00 2001
From: Stenzek <stenzek@gmail.com>
Date: Mon, 1 May 2023 15:12:30 +1000
Subject: [PATCH] HostDisplay: Treat internal res screenshots as a screenshot

---
 src/core/host_display.cpp                   | 88 ++++++++++++++++-----
 src/core/host_display.h                     |  6 +-
 src/core/system.cpp                         | 11 ++-
 src/frontend-common/d3d11_host_display.cpp  | 20 +++--
 src/frontend-common/d3d11_host_display.h    |  4 +-
 src/frontend-common/d3d12_host_display.cpp  | 19 +++--
 src/frontend-common/d3d12_host_display.h    |  4 +-
 src/frontend-common/opengl_host_display.cpp | 22 +++---
 src/frontend-common/opengl_host_display.h   |  4 +-
 src/frontend-common/vulkan_host_display.cpp | 19 +++--
 src/frontend-common/vulkan_host_display.h   |  4 +-
 11 files changed, 124 insertions(+), 77 deletions(-)

diff --git a/src/core/host_display.cpp b/src/core/host_display.cpp
index bb6f189b0..5da2f140d 100644
--- a/src/core/host_display.cpp
+++ b/src/core/host_display.cpp
@@ -232,18 +232,20 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, float*
     apply_aspect_ratio ?
       (display_aspect_ratio / (static_cast<float>(m_display_width) / static_cast<float>(m_display_height))) :
       1.0f;
-  const float display_width = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_width) : static_cast<float>(m_display_width) * x_scale;
-  const float display_height = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_height) / x_scale : static_cast<float>(m_display_height);
-  const float active_left = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_active_left) : static_cast<float>(m_display_active_left) * x_scale;
-  const float active_top = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_active_top) / x_scale : static_cast<float>(m_display_active_top);
+  const float display_width = g_settings.display_stretch_vertically ? static_cast<float>(m_display_width) :
+                                                                      static_cast<float>(m_display_width) * x_scale;
+  const float display_height = g_settings.display_stretch_vertically ? static_cast<float>(m_display_height) / x_scale :
+                                                                       static_cast<float>(m_display_height);
+  const float active_left = g_settings.display_stretch_vertically ? static_cast<float>(m_display_active_left) :
+                                                                    static_cast<float>(m_display_active_left) * x_scale;
+  const float active_top = g_settings.display_stretch_vertically ? static_cast<float>(m_display_active_top) / x_scale :
+                                                                   static_cast<float>(m_display_active_top);
   const float active_width = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_active_width) : static_cast<float>(m_display_active_width) * x_scale;
+                               static_cast<float>(m_display_active_width) :
+                               static_cast<float>(m_display_active_width) * x_scale;
   const float active_height = g_settings.display_stretch_vertically ?
-    static_cast<float>(m_display_active_height) / x_scale : static_cast<float>(m_display_active_height);
+                                static_cast<float>(m_display_active_height) / x_scale :
+                                static_cast<float>(m_display_active_height);
   if (out_x_scale)
     *out_x_scale = x_scale;
 
@@ -500,11 +502,13 @@ bool HostDisplay::WriteDisplayTextureToFile(std::string filename, bool full_reso
     const float ss_height_scale = static_cast<float>(m_display_active_height) / static_cast<float>(m_display_height);
     const float ss_aspect_ratio = m_display_aspect_ratio * ss_width_scale / ss_height_scale;
     resize_width = g_settings.display_stretch_vertically ?
-      m_display_texture_view_width : static_cast<s32>(static_cast<float>(resize_height) * ss_aspect_ratio);
+                     m_display_texture_view_width :
+                     static_cast<s32>(static_cast<float>(resize_height) * ss_aspect_ratio);
     resize_height = g_settings.display_stretch_vertically ?
-      static_cast<s32>(static_cast<float>(resize_height) /
-      (m_display_aspect_ratio / (static_cast<float>(m_display_width) / static_cast<float>(m_display_height)))) :
-      resize_height;
+                      static_cast<s32>(static_cast<float>(resize_height) /
+                                       (m_display_aspect_ratio /
+                                        (static_cast<float>(m_display_width) / static_cast<float>(m_display_height)))) :
+                      resize_height;
   }
   else
   {
@@ -614,17 +618,65 @@ bool HostDisplay::WriteDisplayTextureToBuffer(std::vector<u32>* buffer, u32 resi
   return true;
 }
 
-bool HostDisplay::WriteScreenshotToFile(std::string filename, bool compress_on_thread /*= false*/)
+bool HostDisplay::WriteScreenshotToFile(std::string filename, bool internal_resolution /* = false */,
+                                        bool compress_on_thread /* = false */)
 {
-  const u32 width = m_window_info.surface_width;
-  const u32 height = m_window_info.surface_height;
+  u32 width = m_window_info.surface_width;
+  u32 height = m_window_info.surface_height;
+  auto [draw_left, draw_top, draw_width, draw_height] = CalculateDrawRect(width, height);
+
+  if (internal_resolution && m_display_texture_view_width != 0 && m_display_texture_view_height != 0)
+  {
+    // If internal res, scale the computed draw rectangle to the internal res.
+    // We re-use the draw rect because it's already been AR corrected.
+    const float sar =
+      static_cast<float>(m_display_texture_view_width) / static_cast<float>(m_display_texture_view_height);
+    const float dar = static_cast<float>(draw_width) / static_cast<float>(draw_height);
+    if (sar >= dar)
+    {
+      // stretch height, preserve width
+      const float scale = static_cast<float>(m_display_texture_view_width) / static_cast<float>(draw_width);
+      width = m_display_texture_view_width;
+      height = static_cast<u32>(std::round(static_cast<float>(draw_height) * scale));
+    }
+    else
+    {
+      // stretch width, preserve height
+      const float scale = static_cast<float>(m_display_texture_view_height) / static_cast<float>(draw_height);
+      width = static_cast<u32>(std::round(static_cast<float>(draw_width) * scale));
+      height = m_display_texture_view_height;
+    }
+
+    // DX11 won't go past 16K texture size.
+    constexpr u32 MAX_TEXTURE_SIZE = 16384;
+    if (width > MAX_TEXTURE_SIZE)
+    {
+      height = static_cast<u32>(static_cast<float>(height) /
+                                (static_cast<float>(width) / static_cast<float>(MAX_TEXTURE_SIZE)));
+      width = MAX_TEXTURE_SIZE;
+    }
+    if (height > MAX_TEXTURE_SIZE)
+    {
+      height = MAX_TEXTURE_SIZE;
+      width = static_cast<u32>(static_cast<float>(width) /
+                               (static_cast<float>(height) / static_cast<float>(MAX_TEXTURE_SIZE)));
+    }
+
+    // Remove padding, it's not part of the framebuffer.
+    draw_left = 0;
+    draw_top = 0;
+    draw_width = static_cast<s32>(width);
+    draw_height = static_cast<s32>(height);
+  }
   if (width == 0 || height == 0)
     return false;
 
   std::vector<u32> pixels;
   u32 pixels_stride;
   GPUTexture::Format pixels_format;
-  if (!RenderScreenshot(width, height, &pixels, &pixels_stride, &pixels_format))
+  if (!RenderScreenshot(width, height,
+                        Common::Rectangle<s32>::FromExtents(draw_top, draw_left, draw_width, draw_height), &pixels,
+                        &pixels_stride, &pixels_format))
   {
     Log_ErrorPrintf("Failed to render %ux%u screenshot", width, height);
     return false;
diff --git a/src/core/host_display.h b/src/core/host_display.h
index f406ef4de..6332624b3 100644
--- a/src/core/host_display.h
+++ b/src/core/host_display.h
@@ -104,8 +104,8 @@ public:
   virtual bool Render(bool skip_present) = 0;
 
   /// Renders the display with postprocessing to the specified image.
-  virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                                GPUTexture::Format* out_format) = 0;
+  virtual bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect,
+                                std::vector<u32>* out_pixels, u32* out_stride, GPUTexture::Format* out_format) = 0;
 
   ALWAYS_INLINE bool IsVsyncEnabled() const { return m_vsync_enabled; }
   virtual void SetVSync(bool enabled) = 0;
@@ -206,7 +206,7 @@ public:
                                    bool clear_alpha = true);
 
   /// Helper function to save screenshot to PNG.
-  bool WriteScreenshotToFile(std::string filename, bool compress_on_thread = false);
+  bool WriteScreenshotToFile(std::string filename, bool internal_resolution = false, bool compress_on_thread = false);
 
 protected:
   ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
diff --git a/src/core/system.cpp b/src/core/system.cpp
index e2a7141d2..59b2b8d7a 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -2069,8 +2069,9 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
     std::vector<u32> screenshot_buffer;
     u32 screenshot_stride;
     GPUTexture::Format screenshot_format;
-    if (g_host_display->RenderScreenshot(screenshot_width, screenshot_height, &screenshot_buffer, &screenshot_stride,
-                                         &screenshot_format) &&
+    if (g_host_display->RenderScreenshot(screenshot_width, screenshot_height,
+                                         Common::Rectangle<s32>::FromExtents(0, 0, screenshot_width, screenshot_height),
+                                         &screenshot_buffer, &screenshot_stride, &screenshot_format) &&
         GPUTexture::ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride,
                                               screenshot_format))
     {
@@ -3911,10 +3912,8 @@ bool System::SaveScreenshot(const char* filename /* = nullptr */, bool full_reso
     return false;
   }
 
-  const bool screenshot_saved =
-    g_settings.display_internal_resolution_screenshots ?
-      g_host_display->WriteDisplayTextureToFile(filename, full_resolution, apply_aspect_ratio, compress_on_thread) :
-      g_host_display->WriteScreenshotToFile(filename, compress_on_thread);
+  const bool screenshot_saved = g_host_display->WriteScreenshotToFile(
+    filename, g_settings.display_internal_resolution_screenshots, compress_on_thread);
 
   if (!screenshot_saved)
   {
diff --git a/src/frontend-common/d3d11_host_display.cpp b/src/frontend-common/d3d11_host_display.cpp
index 8d40248b5..e28e17212 100644
--- a/src/frontend-common/d3d11_host_display.cpp
+++ b/src/frontend-common/d3d11_host_display.cpp
@@ -705,8 +705,8 @@ bool D3D11HostDisplay::Render(bool skip_present)
   return true;
 }
 
-bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                                        GPUTexture::Format* out_format)
+bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect,
+                                        std::vector<u32>* out_pixels, u32* out_stride, GPUTexture::Format* out_format)
 {
   static constexpr GPUTexture::Format hdformat = GPUTexture::Format::RGBA8;
 
@@ -720,20 +720,18 @@ bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>*
 
   if (HasDisplayTexture())
   {
-    const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height);
-
     if (!m_post_processing_chain.IsEmpty())
     {
-      ApplyPostProcessingChain(render_texture.GetD3DRTV(), left, top, draw_width, draw_height,
-                               static_cast<D3D11::Texture*>(m_display_texture), m_display_texture_view_x,
-                               m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
-                               width, height);
+      ApplyPostProcessingChain(render_texture.GetD3DRTV(), draw_rect.left, draw_rect.top, draw_rect.GetWidth(),
+                               draw_rect.GetHeight(), static_cast<D3D11::Texture*>(m_display_texture),
+                               m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
+                               m_display_texture_view_height, width, height);
     }
     else
     {
-      RenderDisplay(left, top, draw_width, draw_height, static_cast<D3D11::Texture*>(m_display_texture),
-                    m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
-                    m_display_texture_view_height, IsUsingLinearFiltering());
+      RenderDisplay(draw_rect.left, draw_rect.top, draw_rect.GetWidth(), draw_rect.GetHeight(),
+                    static_cast<D3D11::Texture*>(m_display_texture), m_display_texture_view_x, m_display_texture_view_y,
+                    m_display_texture_view_width, m_display_texture_view_height, IsUsingLinearFiltering());
     }
   }
 
diff --git a/src/frontend-common/d3d11_host_display.h b/src/frontend-common/d3d11_host_display.h
index 32154e4ee..f6c4f725c 100644
--- a/src/frontend-common/d3d11_host_display.h
+++ b/src/frontend-common/d3d11_host_display.h
@@ -67,8 +67,8 @@ public:
   void SetVSync(bool enabled) override;
 
   bool Render(bool skip_present) override;
-  bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                        GPUTexture::Format* out_format) override;
+  bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect, std::vector<u32>* out_pixels,
+                        u32* out_stride, GPUTexture::Format* out_format) override;
 
   static AdapterAndModeList StaticGetAdapterAndModeList();
 
diff --git a/src/frontend-common/d3d12_host_display.cpp b/src/frontend-common/d3d12_host_display.cpp
index faafe2641..1e3df79ea 100644
--- a/src/frontend-common/d3d12_host_display.cpp
+++ b/src/frontend-common/d3d12_host_display.cpp
@@ -615,8 +615,8 @@ bool D3D12HostDisplay::Render(bool skip_present)
   return true;
 }
 
-bool D3D12HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                                        GPUTexture::Format* out_format)
+bool D3D12HostDisplay::RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect,
+                                        std::vector<u32>* out_pixels, u32* out_stride, GPUTexture::Format* out_format)
 {
   static constexpr DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
   static constexpr GPUTexture::Format hdformat = GPUTexture::Format::RGBA8;
@@ -630,14 +630,13 @@ bool D3D12HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>*
   }
 
   ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
-  const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height);
 
   if (HasDisplayTexture() && !m_post_processing_chain.IsEmpty())
   {
-    ApplyPostProcessingChain(cmdlist, &render_texture, left, top, width, height,
-                             static_cast<D3D12::Texture*>(m_display_texture), m_display_texture_view_x,
-                             m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
-                             width, height);
+    ApplyPostProcessingChain(cmdlist, &render_texture, draw_rect.left, draw_rect.top, draw_rect.GetWidth(),
+                             draw_rect.GetHeight(), static_cast<D3D12::Texture*>(m_display_texture),
+                             m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
+                             m_display_texture_view_height, width, height);
   }
   else
   {
@@ -647,9 +646,9 @@ bool D3D12HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>*
 
     if (HasDisplayTexture())
     {
-      RenderDisplay(cmdlist, left, top, draw_width, draw_height, static_cast<D3D12::Texture*>(m_display_texture),
-                    m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
-                    m_display_texture_view_height, IsUsingLinearFiltering());
+      RenderDisplay(cmdlist, draw_rect.left, draw_rect.top, draw_rect.GetWidth(), draw_rect.GetHeight(),
+                    static_cast<D3D12::Texture*>(m_display_texture), m_display_texture_view_x, m_display_texture_view_y,
+                    m_display_texture_view_width, m_display_texture_view_height, IsUsingLinearFiltering());
     }
   }
 
diff --git a/src/frontend-common/d3d12_host_display.h b/src/frontend-common/d3d12_host_display.h
index 0aeb2f2c8..dfd49848d 100644
--- a/src/frontend-common/d3d12_host_display.h
+++ b/src/frontend-common/d3d12_host_display.h
@@ -66,8 +66,8 @@ public:
   void SetVSync(bool enabled) override;
 
   bool Render(bool skip_present) override;
-  bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                        GPUTexture::Format* out_format) override;
+  bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect, std::vector<u32>* out_pixels,
+                        u32* out_stride, GPUTexture::Format* out_format) override;
 
   bool SetGPUTimingEnabled(bool enabled) override;
   float GetAndResetAccumulatedGPUTime() override;
diff --git a/src/frontend-common/opengl_host_display.cpp b/src/frontend-common/opengl_host_display.cpp
index d9e120fe4..c058b56de 100644
--- a/src/frontend-common/opengl_host_display.cpp
+++ b/src/frontend-common/opengl_host_display.cpp
@@ -680,8 +680,8 @@ bool OpenGLHostDisplay::Render(bool skip_present)
   return true;
 }
 
-bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                                         GPUTexture::Format* out_format)
+bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect,
+                                         std::vector<u32>* out_pixels, u32* out_stride, GPUTexture::Format* out_format)
 {
   GL::Texture texture;
   if (!texture.Create(width, height, 1, 1, 1, GPUTexture::Format::RGBA8, nullptr, 0) || !texture.CreateFramebuffer())
@@ -692,14 +692,13 @@ bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
   glDisable(GL_SCISSOR_TEST);
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
-  const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height);
-
   if (HasDisplayTexture() && !m_post_processing_chain.IsEmpty())
   {
-    ApplyPostProcessingChain(texture.GetGLFramebufferID(), left, height - top - draw_height, draw_width, draw_height,
-                             static_cast<GL::Texture*>(m_display_texture), m_display_texture_view_x,
-                             m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
-                             width, height);
+    ApplyPostProcessingChain(texture.GetGLFramebufferID(), draw_rect.left,
+                             height - draw_rect.top - draw_rect.GetHeight(), draw_rect.GetWidth(),
+                             draw_rect.GetHeight(), static_cast<GL::Texture*>(m_display_texture),
+                             m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
+                             m_display_texture_view_height, width, height);
   }
   else
   {
@@ -708,9 +707,10 @@ bool OpenGLHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
 
     if (HasDisplayTexture())
     {
-      RenderDisplay(left, height - top - draw_height, draw_width, draw_height,
-                    static_cast<GL::Texture*>(m_display_texture), m_display_texture_view_x, m_display_texture_view_y,
-                    m_display_texture_view_width, m_display_texture_view_height, IsUsingLinearFiltering());
+      RenderDisplay(draw_rect.left, height - draw_rect.top - draw_rect.GetHeight(), draw_rect.GetWidth(),
+                    draw_rect.GetHeight(), static_cast<GL::Texture*>(m_display_texture), m_display_texture_view_x,
+                    m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
+                    IsUsingLinearFiltering());
     }
   }
 
diff --git a/src/frontend-common/opengl_host_display.h b/src/frontend-common/opengl_host_display.h
index 3ae85976e..2cc21c120 100644
--- a/src/frontend-common/opengl_host_display.h
+++ b/src/frontend-common/opengl_host_display.h
@@ -55,8 +55,8 @@ public:
   void SetVSync(bool enabled) override;
 
   bool Render(bool skip_present) override;
-  bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                        GPUTexture::Format* out_format) override;
+  bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect, std::vector<u32>* out_pixels,
+                        u32* out_stride, GPUTexture::Format* out_format) override;
 
   bool SetGPUTimingEnabled(bool enabled) override;
   float GetAndResetAccumulatedGPUTime() override;
diff --git a/src/frontend-common/vulkan_host_display.cpp b/src/frontend-common/vulkan_host_display.cpp
index 990f8704d..aa0eade9f 100644
--- a/src/frontend-common/vulkan_host_display.cpp
+++ b/src/frontend-common/vulkan_host_display.cpp
@@ -677,8 +677,8 @@ bool VulkanHostDisplay::Render(bool skip_present)
   return true;
 }
 
-bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                                         GPUTexture::Format* out_format)
+bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect,
+                                         std::vector<u32>* out_pixels, u32* out_stride, GPUTexture::Format* out_format)
 {
   // in theory we could do this without a swap chain, but postprocessing assumes it for now...
   if (!m_swap_chain)
@@ -746,20 +746,19 @@ bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
                                             "VulkanHostDisplay::RenderScreenshot: %ux%u", width, height);
   tex.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
-  const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height);
-
   if (!m_post_processing_chain.IsEmpty())
   {
-    ApplyPostProcessingChain(fb, left, top, draw_width, draw_height, static_cast<Vulkan::Texture*>(m_display_texture),
-                             m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
-                             m_display_texture_view_height, width, height);
+    ApplyPostProcessingChain(fb, draw_rect.left, draw_rect.top, draw_rect.GetWidth(), draw_rect.GetHeight(),
+                             static_cast<Vulkan::Texture*>(m_display_texture), m_display_texture_view_x,
+                             m_display_texture_view_y, m_display_texture_view_width, m_display_texture_view_height,
+                             width, height);
   }
   else
   {
     BeginSwapChainRenderPass(fb, width, height);
-    RenderDisplay(left, top, draw_width, draw_height, static_cast<Vulkan::Texture*>(m_display_texture),
-                  m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width,
-                  m_display_texture_view_height, IsUsingLinearFiltering());
+    RenderDisplay(draw_rect.left, draw_rect.top, draw_rect.GetWidth(), draw_rect.GetHeight(),
+                  static_cast<Vulkan::Texture*>(m_display_texture), m_display_texture_view_x, m_display_texture_view_y,
+                  m_display_texture_view_width, m_display_texture_view_height, IsUsingLinearFiltering());
   }
 
   vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
diff --git a/src/frontend-common/vulkan_host_display.h b/src/frontend-common/vulkan_host_display.h
index 7106aa88c..1da6c500a 100644
--- a/src/frontend-common/vulkan_host_display.h
+++ b/src/frontend-common/vulkan_host_display.h
@@ -59,8 +59,8 @@ public:
   void SetVSync(bool enabled) override;
 
   bool Render(bool skip_present) override;
-  bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
-                        GPUTexture::Format* out_format) override;
+  bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle<s32>& draw_rect, std::vector<u32>* out_pixels,
+                        u32* out_stride, GPUTexture::Format* out_format) override;
 
   bool SetGPUTimingEnabled(bool enabled) override;
   float GetAndResetAccumulatedGPUTime() override;