diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 092da9fdc2..d80e168662 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -593,7 +593,7 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, bool force_init auto src_texture = static_cast(old_contents); if (src_texture->get_rsx_pitch() != get_rsx_pitch()) { - LOG_TODO(RSX, "Pitch mismatch, could not transfer inherited memory"); + LOG_TRACE(RSX, "Pitch mismatch, could not transfer inherited memory"); return; } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 599b527d32..26b131d575 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -449,6 +449,9 @@ namespace vk barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; + case VK_IMAGE_LAYOUT_UNDEFINED: + case VK_IMAGE_LAYOUT_PREINITIALIZED: + fmt::throw_exception("Attempted to transition to an invalid layout"); } switch (current_layout) diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 9d6d81d35b..d1b8f167cb 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -59,12 +59,14 @@ namespace vk void memory_barrier(vk::command_buffer& cmd, bool force_init = false) { - if (!old_contents) + // Helper to optionally clear/initialize memory contents depending on barrier type + auto null_transfer_impl = [&]() { if (dirty && force_init) { // Initialize memory contents if we did not find anything usable // TODO: Properly sync with Cell + VkImageSubresourceRange range{ attachment_aspect_flag, 0, 1, 0, 1 }; const auto old_layout = current_layout; @@ -84,14 +86,18 @@ namespace vk change_image_layout(cmd, this, old_layout, range); on_write(); } + }; + if (!old_contents) + { + null_transfer_impl(); return; } auto src_texture = static_cast(old_contents); if (src_texture->get_rsx_pitch() != get_rsx_pitch()) { - LOG_TODO(RSX, "Pitch mismatch, could not transfer inherited memory"); + LOG_TRACE(RSX, "Pitch mismatch, could not transfer inherited memory"); return; } @@ -107,8 +113,15 @@ namespace vk } else { - const bool src_is_depth = !!(vk::get_aspect_flags(src_texture->info.format) & VK_IMAGE_ASPECT_DEPTH_BIT); - const bool dst_is_depth = !!(vk::get_aspect_flags(info.format) & VK_IMAGE_ASPECT_DEPTH_BIT); + const bool src_is_depth = !!(src_texture->attachment_aspect_flag & VK_IMAGE_ASPECT_DEPTH_BIT); + const bool dst_is_depth = !!(attachment_aspect_flag & VK_IMAGE_ASPECT_DEPTH_BIT); + + if (src_is_depth != dst_is_depth) + { + // TODO: Implement proper copy_typeless for vulkan that crosses the depth<->color aspect barrier + null_transfer_impl(); + return; + } if (src_bpp != dst_bpp || src_is_depth || dst_is_depth) { diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 22fdb51a24..b346898c6e 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -542,34 +542,40 @@ namespace vk if (xfer_info.src_is_typeless) { - auto internal_width = src->width() * xfer_info.src_scaling_hint; - auto format = xfer_info.src_native_format_override ? + const auto internal_width = src->width() * xfer_info.src_scaling_hint; + const auto format = xfer_info.src_native_format_override ? VkFormat(xfer_info.src_native_format_override) : vk::get_compatible_sampler_format(vk::get_current_renderer()->get_formats_support(), xfer_info.src_gcm_format); + const auto aspect = vk::get_aspect_flags(format); // Transfer bits from src to typeless src real_src = vk::get_typeless_helper(format, (u32)internal_width, src->height()); - src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint); - src_area.x2 = (u16)(src_area.x2 * xfer_info.src_scaling_hint); + vk::change_image_layout(cmd, real_src, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); vk::copy_image_typeless(cmd, src, real_src, { 0, 0, (s32)src->width(), (s32)src->height() }, { 0, 0, (s32)internal_width, (s32)src->height() }, 1, - vk::get_aspect_flags(src->info.format), vk::get_aspect_flags(format)); + vk::get_aspect_flags(src->info.format), aspect); + + src_area.x1 = (u16)(src_area.x1 * xfer_info.src_scaling_hint); + src_area.x2 = (u16)(src_area.x2 * xfer_info.src_scaling_hint); } if (xfer_info.dst_is_typeless) { - auto internal_width = dst->width() * xfer_info.dst_scaling_hint; - auto format = xfer_info.dst_native_format_override ? + const auto internal_width = dst->width() * xfer_info.dst_scaling_hint; + const auto format = xfer_info.dst_native_format_override ? VkFormat(xfer_info.dst_native_format_override) : vk::get_compatible_sampler_format(vk::get_current_renderer()->get_formats_support(), xfer_info.dst_gcm_format); + const auto aspect = vk::get_aspect_flags(format); // Transfer bits from dst to typeless dst real_dst = vk::get_typeless_helper(format, (u32)internal_width, dst->height()); - dst_area.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint); - dst_area.x2 = (u16)(dst_area.x2 * xfer_info.dst_scaling_hint); + vk::change_image_layout(cmd, real_dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, { aspect, 0, 1, 0, 1 }); vk::copy_image_typeless(cmd, dst, real_dst, { 0, 0, (s32)dst->width(), (s32)dst->height() }, { 0, 0, (s32)internal_width, (s32)dst->height() }, 1, - vk::get_aspect_flags(dst->info.format), vk::get_aspect_flags(format)); + vk::get_aspect_flags(dst->info.format), aspect); + + dst_area.x1 = (u16)(dst_area.x1 * xfer_info.dst_scaling_hint); + dst_area.x2 = (u16)(dst_area.x2 * xfer_info.dst_scaling_hint); } else if (xfer_info.dst_context == rsx::texture_upload_context::framebuffer_storage) { @@ -647,7 +653,5 @@ namespace vk vk::copy_image_typeless(cmd, real_dst, dst, { 0, 0, (s32)internal_width, (s32)dst->height() }, { 0, 0, (s32)dst->width(), (s32)dst->height() }, 1, vk::get_aspect_flags(real_dst->info.format), vk::get_aspect_flags(dst->info.format)); } - - change_image_layout(cmd, dst, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, { (VkImageAspectFlags)dst_aspect, 0, dst->info.mipLevels, 0, dst->info.arrayLayers }); } }