Browse Source

Merge pull request #7399 from ameerj/art-refactor

video_core: Refactoring post A.R.T. merge
Fernando S 4 năm trước cách đây
mục cha
commit
04b4f3b051

+ 1 - 1
src/video_core/renderer_opengl/gl_texture_cache.h

@@ -92,7 +92,7 @@ public:
 
     void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
 
-    void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) {
+    void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
         UNIMPLEMENTED();
     }
 

+ 20 - 30
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -437,39 +437,29 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 
         glBindTextureUnit(0, fxaa_texture.handle);
     }
-
-    // Set projection matrix
     const std::array ortho_matrix =
         MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
 
-    GLuint fragment_handle;
-    const auto filter = Settings::values.scaling_filter.GetValue();
-    switch (filter) {
-    case Settings::ScalingFilter::NearestNeighbor:
-        fragment_handle = present_bilinear_fragment.handle;
-        break;
-    case Settings::ScalingFilter::Bilinear:
-        fragment_handle = present_bilinear_fragment.handle;
-        break;
-    case Settings::ScalingFilter::Bicubic:
-        fragment_handle = present_bicubic_fragment.handle;
-        break;
-    case Settings::ScalingFilter::Gaussian:
-        fragment_handle = present_gaussian_fragment.handle;
-        break;
-    case Settings::ScalingFilter::ScaleForce:
-        fragment_handle = present_scaleforce_fragment.handle;
-        break;
-    case Settings::ScalingFilter::Fsr:
-        LOG_WARNING(
-            Render_OpenGL,
-            "FidelityFX FSR Super Sampling is not supported in OpenGL, changing to ScaleForce");
-        fragment_handle = present_scaleforce_fragment.handle;
-        break;
-    default:
-        fragment_handle = present_bilinear_fragment.handle;
-        break;
-    }
+    const auto fragment_handle = [this]() {
+        switch (Settings::values.scaling_filter.GetValue()) {
+        case Settings::ScalingFilter::NearestNeighbor:
+        case Settings::ScalingFilter::Bilinear:
+            return present_bilinear_fragment.handle;
+        case Settings::ScalingFilter::Bicubic:
+            return present_bicubic_fragment.handle;
+        case Settings::ScalingFilter::Gaussian:
+            return present_gaussian_fragment.handle;
+        case Settings::ScalingFilter::ScaleForce:
+            return present_scaleforce_fragment.handle;
+        case Settings::ScalingFilter::Fsr:
+            LOG_WARNING(
+                Render_OpenGL,
+                "FidelityFX Super Resolution is not supported in OpenGL, changing to ScaleForce");
+            return present_scaleforce_fragment.handle;
+        default:
+            return present_bilinear_fragment.handle;
+        }
+    }();
     program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
     glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
                                 ortho_matrix.data());

+ 54 - 69
src/video_core/renderer_vulkan/blit_image.cpp

@@ -4,6 +4,7 @@
 
 #include <algorithm>
 
+#include "common/settings.h"
 #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
 #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
 #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
@@ -335,6 +336,17 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
     cmdbuf.SetScissor(0, scissor);
     cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
 }
+
+VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
+    const auto& resolution = Settings::values.resolution_info;
+    const bool is_rescaled = src_image_view.IsRescaled();
+    u32 width = src_image_view.size.width;
+    u32 height = src_image_view.size.height;
+    return VkExtent2D{
+        .width = is_rescaled ? resolution.ScaleUp(width) : width,
+        .height = is_rescaled ? resolution.ScaleUp(height) : height,
+    };
+}
 } // Anonymous namespace
 
 BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
@@ -425,61 +437,52 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
 }
 
 void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
-                                      const ImageView& src_image_view, u32 up_scale,
-                                      u32 down_shift) {
+                                      const ImageView& src_image_view) {
     ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass());
-    Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
+    Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer,
-                                      const ImageView& src_image_view, u32 up_scale,
-                                      u32 down_shift) {
+                                      const ImageView& src_image_view) {
     ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass());
-    Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
+    Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer,
-                                      const ImageView& src_image_view, u32 up_scale,
-                                      u32 down_shift) {
+                                      const ImageView& src_image_view) {
     ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass());
-    Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
+    Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
-                                      const ImageView& src_image_view, u32 up_scale,
-                                      u32 down_shift) {
+                                      const ImageView& src_image_view) {
     ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass());
-    Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
+    Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
-                                          ImageView& src_image_view, u32 up_scale, u32 down_shift) {
+                                          const ImageView& src_image_view) {
     ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
-                                 convert_abgr8_to_d24s8_frag, true);
-    ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
-                 down_shift);
+                                 convert_abgr8_to_d24s8_frag);
+    Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
-                                          ImageView& src_image_view, u32 up_scale, u32 down_shift) {
+                                          ImageView& src_image_view) {
     ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
-                                 convert_d24s8_to_abgr8_frag, false);
-    ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale,
-                        down_shift);
+                                 convert_d24s8_to_abgr8_frag);
+    ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
 }
 
 void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
-                              const ImageView& src_image_view, u32 up_scale, u32 down_shift) {
+                              const ImageView& src_image_view) {
     const VkPipelineLayout layout = *one_texture_pipeline_layout;
     const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
     const VkSampler sampler = *nearest_sampler;
-    const VkExtent2D extent{
-        .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
-        .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
-    };
+    const VkExtent2D extent = GetConversionExtent(src_image_view);
+
     scheduler.RequestRenderpass(dst_framebuffer);
-    scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift,
-                      this](vk::CommandBuffer cmdbuf) {
+    scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) {
         const VkOffset2D offset{
             .x = 0,
             .y = 0,
@@ -563,18 +566,16 @@ void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_f
 }
 
 void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
-                                          ImageView& src_image_view, u32 up_scale, u32 down_shift) {
+                                          ImageView& src_image_view) {
     const VkPipelineLayout layout = *two_textures_pipeline_layout;
     const VkImageView src_depth_view = src_image_view.DepthView();
     const VkImageView src_stencil_view = src_image_view.StencilView();
     const VkSampler sampler = *nearest_sampler;
-    const VkExtent2D extent{
-        .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
-        .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
-    };
+    const VkExtent2D extent = GetConversionExtent(src_image_view);
+
     scheduler.RequestRenderpass(dst_framebuffer);
-    scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale,
-                      down_shift, this](vk::CommandBuffer cmdbuf) {
+    scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent,
+                      this](vk::CommandBuffer cmdbuf) {
         const VkOffset2D offset{
             .x = 0,
             .y = 0,
@@ -695,11 +696,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
     return *blit_depth_stencil_pipelines.back();
 }
 
-void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
+void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass,
+                                      bool is_target_depth) {
     if (pipeline) {
         return;
     }
-    const std::array stages = MakeStages(*full_screen_vert, *convert_depth_to_float_frag);
+    VkShaderModule frag_shader =
+        is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
+    const std::array stages = MakeStages(*full_screen_vert, frag_shader);
     pipeline = device.GetLogical().CreateGraphicsPipeline({
         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
         .pNext = nullptr,
@@ -712,8 +716,9 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
         .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
         .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
         .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-        .pDepthStencilState = nullptr,
-        .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
+        .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
+        .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO
+                                            : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
         .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
         .layout = *one_texture_pipeline_layout,
         .renderPass = renderpass,
@@ -723,37 +728,17 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
     });
 }
 
+void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
+    ConvertPipeline(pipeline, renderpass, false);
+}
+
 void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
-    if (pipeline) {
-        return;
-    }
-    const std::array stages = MakeStages(*full_screen_vert, *convert_float_to_depth_frag);
-    pipeline = device.GetLogical().CreateGraphicsPipeline({
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = nullptr,
-        .flags = 0,
-        .stageCount = static_cast<u32>(stages.size()),
-        .pStages = stages.data(),
-        .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
-        .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
-        .pTessellationState = nullptr,
-        .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
-        .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
-        .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
-        .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
-        .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
-        .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
-        .layout = *one_texture_pipeline_layout,
-        .renderPass = renderpass,
-        .subpass = 0,
-        .basePipelineHandle = VK_NULL_HANDLE,
-        .basePipelineIndex = 0,
-    });
+    ConvertPipeline(pipeline, renderpass, true);
 }
 
 void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                                        vk::ShaderModule& module, bool is_target_depth,
-                                        bool single_texture) {
+                                        vk::ShaderModule& module, bool single_texture,
+                                        bool is_target_depth) {
     if (pipeline) {
         return;
     }
@@ -782,13 +767,13 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
 }
 
 void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                                                   vk::ShaderModule& module, bool single_texture) {
-    ConvertPipelineEx(pipeline, renderpass, module, false, single_texture);
+                                                   vk::ShaderModule& module) {
+    ConvertPipelineEx(pipeline, renderpass, module, false, false);
 }
 
 void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                                                   vk::ShaderModule& module, bool single_texture) {
-    ConvertPipelineEx(pipeline, renderpass, module, true, single_texture);
+                                                   vk::ShaderModule& module) {
+    ConvertPipelineEx(pipeline, renderpass, module, true, true);
 }
 
 } // namespace Vulkan

+ 13 - 17
src/video_core/renderer_vulkan/blit_image.h

@@ -44,50 +44,46 @@ public:
                           const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter,
                           Tegra::Engines::Fermi2D::Operation operation);
 
-    void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
-                         u32 up_scale, u32 down_shift);
+    void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
 
-    void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
-                         u32 up_scale, u32 down_shift);
+    void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
 
-    void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
-                         u32 up_scale, u32 down_shift);
+    void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
 
-    void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
-                         u32 up_scale, u32 down_shift);
+    void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
 
-    void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
-                             u32 up_scale, u32 down_shift);
+    void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
 
-    void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
-                             u32 up_scale, u32 down_shift);
+    void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
 
 private:
     void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
-                 const ImageView& src_image_view, u32 up_scale, u32 down_shift);
+                 const ImageView& src_image_view);
 
     void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
                       ImageView& src_image_view, u32 up_scale, u32 down_shift);
 
     void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
-                             ImageView& src_image_view, u32 up_scale, u32 down_shift);
+                             ImageView& src_image_view);
 
     [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
 
     [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
 
+    void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth);
+
     void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
 
     void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
 
     void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                           vk::ShaderModule& module, bool is_target_depth, bool single_texture);
+                           vk::ShaderModule& module, bool single_texture, bool is_target_depth);
 
     void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                                      vk::ShaderModule& module, bool single_texture);
+                                      vk::ShaderModule& module);
 
     void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
-                                      vk::ShaderModule& module, bool single_texture);
+                                      vk::ShaderModule& module);
 
     const Device& device;
     VKScheduler& scheduler;

+ 16 - 21
src/video_core/renderer_vulkan/vk_blit_screen.cpp

@@ -391,28 +391,23 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
                 .offset = {0, 0},
                 .extent = size,
             };
-            const auto filter = Settings::values.scaling_filter.GetValue();
             cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
-            switch (filter) {
-            case Settings::ScalingFilter::NearestNeighbor:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
-                break;
-            case Settings::ScalingFilter::Bilinear:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
-                break;
-            case Settings::ScalingFilter::Bicubic:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline);
-                break;
-            case Settings::ScalingFilter::Gaussian:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline);
-                break;
-            case Settings::ScalingFilter::ScaleForce:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline);
-                break;
-            default:
-                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
-                break;
-            }
+            auto graphics_pipeline = [this]() {
+                switch (Settings::values.scaling_filter.GetValue()) {
+                case Settings::ScalingFilter::NearestNeighbor:
+                case Settings::ScalingFilter::Bilinear:
+                    return *bilinear_pipeline;
+                case Settings::ScalingFilter::Bicubic:
+                    return *bicubic_pipeline;
+                case Settings::ScalingFilter::Gaussian:
+                    return *gaussian_pipeline;
+                case Settings::ScalingFilter::ScaleForce:
+                    return *scaleforce_pipeline;
+                default:
+                    return *bilinear_pipeline;
+                }
+            }();
+            cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline);
             cmdbuf.SetViewport(0, viewport);
             cmdbuf.SetScissor(0, scissor);
 

+ 23 - 11
src/video_core/renderer_vulkan/vk_texture_cache.cpp

@@ -1057,37 +1057,37 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
     });
 }
 
-void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view,
-                                       bool rescaled) {
-    const u32 up_scale = rescaled ? resolution.up_scale : 1;
-    const u32 down_shift = rescaled ? resolution.down_shift : 0;
+void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
     switch (dst_view.format) {
     case PixelFormat::R16_UNORM:
         if (src_view.format == PixelFormat::D16_UNORM) {
-            return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift);
+            return blit_image_helper.ConvertD16ToR16(dst, src_view);
         }
         break;
     case PixelFormat::A8B8G8R8_UNORM:
         if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
-            return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift);
+            return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view);
         }
         break;
     case PixelFormat::R32_FLOAT:
         if (src_view.format == PixelFormat::D32_FLOAT) {
-            return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift);
+            return blit_image_helper.ConvertD32ToR32(dst, src_view);
         }
         break;
     case PixelFormat::D16_UNORM:
         if (src_view.format == PixelFormat::R16_UNORM) {
-            return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift);
+            return blit_image_helper.ConvertR16ToD16(dst, src_view);
         }
         break;
     case PixelFormat::S8_UINT_D24_UNORM:
-        return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift);
+        if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||
+            src_view.format == PixelFormat::B8G8R8A8_UNORM) {
+            return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view);
+        }
         break;
     case PixelFormat::D32_FLOAT:
         if (src_view.format == PixelFormat::R32_FLOAT) {
-            return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift);
+            return blit_image_helper.ConvertR32ToD32(dst, src_view);
         }
         break;
     default:
@@ -1329,6 +1329,10 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm
     }
 }
 
+bool Image::IsRescaled() const noexcept {
+    return True(flags & ImageFlagBits::Rescaled);
+}
+
 bool Image::ScaleUp(bool ignore) {
     if (True(flags & ImageFlagBits::Rescaled)) {
         return false;
@@ -1469,7 +1473,8 @@ bool Image::BlitScaleHelper(bool scale_up) {
 ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
                      ImageId image_id_, Image& image)
     : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
-      image_handle{image.Handle()}, samples{ConvertSampleCount(image.info.num_samples)} {
+      src_image{&image}, image_handle{image.Handle()},
+      samples(ConvertSampleCount(image.info.num_samples)) {
     using Shader::TextureType;
 
     const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1607,6 +1612,13 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
     return *view;
 }
 
+bool ImageView::IsRescaled() const noexcept {
+    if (!src_image) {
+        return false;
+    }
+    return src_image->IsRescaled();
+}
+
 vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {
     return device->GetLogical().CreateImageView({
         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,

+ 7 - 1
src/video_core/renderer_vulkan/vk_texture_cache.h

@@ -65,7 +65,7 @@ public:
 
     void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
 
-    void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled);
+    void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
 
     bool CanAccelerateImageUpload(Image&) const noexcept {
         return false;
@@ -139,6 +139,8 @@ public:
         return std::exchange(initialized, true);
     }
 
+    bool IsRescaled() const noexcept;
+
     bool ScaleUp(bool ignore = false);
 
     bool ScaleDown(bool ignore = false);
@@ -189,6 +191,8 @@ public:
     [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
                                           Shader::ImageFormat image_format);
 
+    [[nodiscard]] bool IsRescaled() const noexcept;
+
     [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept {
         return *image_views[static_cast<size_t>(texture_type)];
     }
@@ -222,6 +226,8 @@ private:
     [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
 
     const Device* device = nullptr;
+    const Image* src_image{};
+
     std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
     std::unique_ptr<StorageViews> storage_views;
     vk::ImageView depth_view;

+ 13 - 2
src/video_core/texture_cache/texture_cache.h

@@ -1855,9 +1855,20 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
             .height = std::min(dst_view.size.height, src_view.size.height),
             .depth = std::min(dst_view.size.depth, src_view.size.depth),
         };
-        UNIMPLEMENTED_IF(copy.extent != expected_size);
+        const Extent3D scaled_extent = [is_rescaled, expected_size]() {
+            if (!is_rescaled) {
+                return expected_size;
+            }
+            const auto& resolution = Settings::values.resolution_info;
+            return Extent3D{
+                .width = resolution.ScaleUp(expected_size.width),
+                .height = resolution.ScaleUp(expected_size.height),
+                .depth = expected_size.depth,
+            };
+        }();
+        UNIMPLEMENTED_IF(copy.extent != scaled_extent);
 
-        runtime.ConvertImage(dst_framebuffer, dst_view, src_view, is_rescaled);
+        runtime.ConvertImage(dst_framebuffer, dst_view, src_view);
     }
 }