From 9b34f00241eceabfba5494ddb99ef7c275ffff63 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 16 Jan 2020 17:48:55 +0300 Subject: [PATCH] vk: Optimize image transfers - Adds the same optimization/simplification steps to complex image transfer routines. Whenever possible, multi-step transfers are collapsed into a single operation. --- rpcs3/Emu/RSX/VK/VKTexture.cpp | 28 ++++++++++++++++++++++++++++ rpcs3/Emu/RSX/VK/VKTextureCache.h | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 588b2e014d..779704cb36 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -876,6 +876,34 @@ namespace vk vk::image* real_src = src; vk::image* real_dst = dst; + // Optimization pass; check for pass-through data transfer + if (!xfer_info.flip_horizontal && !xfer_info.flip_vertical && src_area.height() == dst_area.height()) + { + auto src_w = src_area.width(); + auto dst_w = dst_area.width(); + + if (xfer_info.src_is_typeless) src_w *= xfer_info.src_scaling_hint; + if (xfer_info.dst_is_typeless) dst_w *= xfer_info.dst_scaling_hint; + + if (src_w == dst_w) + { + // Final dimensions are a match + if (xfer_info.src_is_typeless || xfer_info.dst_is_typeless) + { + const areai src_rect = src_area * size2f{ xfer_info.src_scaling_hint, 1.f }; + const areai dst_rect = dst_area * size2f{ xfer_info.dst_scaling_hint, 1.f }; + vk::copy_image_typeless(cmd, src, dst, src_rect, dst_rect, 1, src->aspect(), dst->aspect()); + } + else + { + copy_image(cmd, src->value, dst->value, src->current_layout, dst->current_layout, + src_area, dst_area, 1, src->aspect(), dst->aspect()); + } + + return; + } + } + if (xfer_info.src_is_typeless) { const auto format = xfer_info.src_native_format_override ? diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 67e67d2ecb..9922e3c333 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -607,6 +607,20 @@ namespace vk const u16 convert_w = u16(src_w * src_bpp) / dst_bpp; const u16 convert_x = u16(src_x * src_bpp) / dst_bpp; + if (convert_w == section.dst_w && src_h == section.dst_h && + transform == rsx::surface_transform::identity && + section.level == 0 && section.dst_z == 0) + { + // Optimization to avoid double transfer + // TODO: Handle level and layer offsets + const areai src_rect = coordi{{ src_x, src_y }, { src_w, src_h }}; + const areai dst_rect = coordi{{ section.dst_x, section.dst_y }, { section.dst_w, section.dst_h }}; + vk::copy_image_typeless(cmd, section.src, dst, src_rect, dst_rect, 1, section.src->aspect(), dst_aspect); + + section.src->pop_layout(cmd); + continue; + } + src_image = vk::get_typeless_helper(dst->info.format, convert_x + convert_w, src_y + src_h); src_image->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);