From 0395fb9955964846ab2ef140c6e0277a2628a5e4 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 27 Feb 2019 21:28:49 +0300 Subject: [PATCH] rsx/tecture_cache: Addendum - fix data cast with scaling conversion (AA emulation) - Blit operations do format conversion automatically which is NOT what we want! - Scale onto temp buffer with similar format before performing data cast. --- rpcs3/Emu/RSX/GL/GLTextureCache.h | 23 ++++++++++++--- rpcs3/Emu/RSX/VK/VKTexture.cpp | 2 +- rpcs3/Emu/RSX/VK/VKTextureCache.h | 49 ++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 4ff29aa932..eaf18225ba 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -426,7 +426,7 @@ namespace gl if (require_manual_shuffle) { //byte swapping does not work on byte types, use uint_8_8_8_8 for rgba8 instead to avoid penalty - rsx::shuffle_texel_data_wzyx(dst, rsx_pitch, width, valid_length / rsx_pitch); + rsx::shuffle_texel_data_wzyx(dst, rsx_pitch, width, align(valid_length, rsx_pitch) / rsx_pitch); } else if (pack_unpack_swap_bytes && ::gl::get_driver_caps().vendor_AMD) { @@ -750,12 +750,28 @@ namespace gl { verify(HERE), dst_image->get_target() == gl::texture::target::texture2D; + std::unique_ptr tmp; + auto _dst = dst_image; + auto _blitter = gl::g_hw_blitter; const areai src_rect = { slice.src_x, slice.src_y, slice.src_x + slice.src_w, slice.src_y + slice.src_h }; const areai dst_rect = { slice.dst_x, slice.dst_y, slice.dst_x + slice.dst_w, slice.dst_y + slice.dst_h }; - _blitter->scale_image(cmd, slice.src, dst_image, + if (UNLIKELY(slice.src->get_internal_format() != dst_image->get_internal_format())) + { + tmp = std::make_unique(GL_TEXTURE_2D, dst_rect.x2, dst_rect.y2, 1, 1, (GLenum)slice.src->get_internal_format()); + _dst = tmp.get(); + } + + _blitter->scale_image(cmd, slice.src, _dst, src_rect, dst_rect, false, false, {}); + + if (tmp) + { + // Data cast comes after scaling + glCopyImageSubData(tmp->id(), GL_TEXTURE_2D, 0, slice.dst_x, slice.dst_y, 0, + dst_image->id(), (GLenum)dst_image->get_target(), 0, slice.dst_x, slice.dst_y, slice.dst_z, slice.dst_w, slice.dst_h, 1); + } } } } @@ -860,8 +876,7 @@ namespace gl const texture_channel_remap_t& remap_vector) override { auto _template = get_template_from_collection_impl(sections_to_copy); - const GLenum ifmt = _template ? (GLenum)_template->get_internal_format() : GL_NONE; - auto result = create_temporary_subresource_impl(_template, ifmt, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false); + auto result = create_temporary_subresource_impl(_template, GL_NONE, GL_TEXTURE_2D, gcm_format, 0, 0, width, height, remap_vector, false); copy_transfer_regions_impl(cmd, result->image(), sections_to_copy); return result; diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 76bb3e530f..94c198285b 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -236,7 +236,7 @@ namespace vk for (u32 mip_level = 0; mip_level < mipmaps; ++mip_level) { - vkCmdCopyImage(cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &rgn); + vkCmdCopyImage(cmd, src, preferred_src_format, dst, preferred_dst_format, 1, &rgn); rgn.srcSubresource.mipLevel++; rgn.dstSubresource.mipLevel++; diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 7de207cf77..f8bcfea621 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -535,13 +535,27 @@ namespace vk else { verify(HERE), section.dst_z == 0; + + u32 dst_x = section.dst_x, dst_y = section.dst_y; + vk::image* _dst; + + if (LIKELY(section.src->info.format == dst->info.format)) + { + _dst = dst; + } + else + { + _dst = vk::get_typeless_helper(section.src->info.format, dst->width(), dst->height() * 2); + vk::change_image_layout(cmd, _dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, src_range); + } + if (section.xform == surface_transform::identity) { - vk::copy_scaled_image(cmd, section.src->value, dst->value, section.src->current_layout, dst->current_layout, + vk::copy_scaled_image(cmd, section.src->value, _dst->value, section.src->current_layout, _dst->current_layout, section.src_x, section.src_y, section.src_w, section.src_h, section.dst_x, section.dst_y, section.dst_w, section.dst_h, - 1, src_aspect, section.src->info.format == dst->info.format, - VK_FILTER_NEAREST); + 1, src_aspect, section.src->info.format == _dst->info.format, + VK_FILTER_NEAREST, section.src->info.format, _dst->info.format); } else if (section.xform == surface_transform::argb_to_bgra) { @@ -572,11 +586,17 @@ namespace vk vkCmdCopyBufferToImage(cmd, scratch_buf->value, tmp->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); - vk::copy_scaled_image(cmd, tmp->value, dst->value, tmp->current_layout, dst->current_layout, + if (UNLIKELY(tmp == _dst)) + { + dst_x = 0; + dst_y = section.src_h; + } + + vk::copy_scaled_image(cmd, tmp->value, _dst->value, tmp->current_layout, _dst->current_layout, 0, 0, section.src_w, section.src_h, - section.dst_x, section.dst_y, section.dst_w, section.dst_h, - 1, src_aspect, section.src->info.format == dst->info.format, - VK_FILTER_NEAREST); + dst_x, dst_y, section.dst_w, section.dst_h, + 1, src_aspect, section.src->info.format == _dst->info.format, + VK_FILTER_NEAREST, tmp->info.format, _dst->info.format); vk::change_image_layout(cmd, section.src, old_src_layout, src_range); } @@ -584,6 +604,21 @@ namespace vk { fmt::throw_exception("Unreachable" HERE); } + + if (UNLIKELY(_dst != dst)) + { + // Casting comes after the scaling! + + VkImageCopy copy_rgn; + copy_rgn.srcOffset = { s32(dst_x), s32(dst_y), 0 }; + copy_rgn.dstOffset = { section.dst_x, section.dst_y, 0 }; + copy_rgn.dstSubresource = { dst_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 0, 1 }; + copy_rgn.srcSubresource = { src_aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 0, 1 }; + copy_rgn.extent = { section.dst_w, section.dst_h, 1 }; + + vk::change_image_layout(cmd, _dst, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_range); + vkCmdCopyImage(cmd, _dst->value, _dst->current_layout, dst->value, dst->current_layout, 1, ©_rgn); + } } } }