diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 319c77df4c..966a22e382 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -81,6 +81,7 @@ namespace vk //Other texture management helpers void copy_image_to_buffer(VkCommandBuffer cmd, const vk::image* src, const vk::buffer* dst, const VkBufferImageCopy& region, bool swap_bytes = false); void copy_buffer_to_image(VkCommandBuffer cmd, const vk::buffer* src, const vk::image* dst, const VkBufferImageCopy& region); + u64 calculate_working_buffer_size(u64 base_size, VkImageAspectFlags aspect); void copy_image_typeless(const command_buffer &cmd, image *src, image *dst, const areai& src_rect, const areai& dst_rect, u32 mipmaps, VkImageAspectFlags src_transfer_mask = 0xFF, VkImageAspectFlags dst_transfer_mask = 0xFF); diff --git a/rpcs3/Emu/RSX/VK/VKTexture.cpp b/rpcs3/Emu/RSX/VK/VKTexture.cpp index 40609007af..d8eddfd9a1 100644 --- a/rpcs3/Emu/RSX/VK/VKTexture.cpp +++ b/rpcs3/Emu/RSX/VK/VKTexture.cpp @@ -33,6 +33,22 @@ namespace vk } } + u64 calculate_working_buffer_size(u64 base_size, VkImageAspectFlags aspect) + { + if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) + { + return (base_size * 9) / 4; + } + else if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + { + return base_size * 2; + } + else + { + return base_size; + } + } + void copy_image_to_buffer(VkCommandBuffer cmd, const vk::image* src, const vk::buffer* dst, const VkBufferImageCopy& region, bool swap_bytes) { // Always validate @@ -328,15 +344,7 @@ namespace vk const auto src_texel_size = vk::get_format_texel_width(src->info.format); const auto src_length = src_texel_size * src_copy.imageExtent.width * src_copy.imageExtent.height; - u32 min_scratch_size = src_length; - - // Check for DS manipulation which will affect scratch memory requirements - if (const VkFlags combined_aspect = src->aspect() | dst->aspect(); - (combined_aspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0) - { - // At least one depth-stencil merge/extract required; requirements change to 2(w*h*bpp) + (w*h) - min_scratch_size = (src_length * 2) + (src_length / src_texel_size); - } + const auto min_scratch_size = calculate_working_buffer_size(src_length, src->aspect() | dst->aspect()); // Initialize scratch memory auto scratch_buf = vk::get_scratch_buffer(min_scratch_size); @@ -977,6 +985,12 @@ namespace vk scratch_buf_size += scratch_buf_size; } + if (requires_depth_processing) + { + // D-S aspect requires a load section that can fit a separated block => D(4) + S(1) + scratch_buf_size += dst_image->width() * dst_image->height() * 5; + } + scratch_buf = vk::get_scratch_buffer(scratch_buf_size); buffer_copies.reserve(subresource_layout.size()); } diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp index eb3d187696..ac3a13ce5f 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp @@ -43,8 +43,9 @@ namespace vk const auto section_length = valid_range.length(); const auto transfer_pitch = real_pitch; const auto task_length = transfer_pitch * src_area.height(); + const auto working_buffer_length = calculate_working_buffer_size(task_length, src->aspect()); - auto working_buffer = vk::get_scratch_buffer(task_length); + auto working_buffer = vk::get_scratch_buffer(working_buffer_length); auto final_mapping = vk::map_dma(valid_range.start, section_length); VkBufferImageCopy region = {}; diff --git a/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp b/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp index 67ee2c748f..1401aa2d66 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp @@ -151,7 +151,7 @@ namespace vk return ptr.get(); } - vk::buffer* get_scratch_buffer(u32 min_required_size) + vk::buffer* get_scratch_buffer(u64 min_required_size) { auto& scratch_buffer = g_scratch_buffers_pool[0 /*TODO: Replace with Queue Family ID*/].get_buf(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/scratch.h b/rpcs3/Emu/RSX/VK/vkutils/scratch.h index 50053b9cff..39a00604b4 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/scratch.h +++ b/rpcs3/Emu/RSX/VK/vkutils/scratch.h @@ -6,7 +6,7 @@ namespace vk VkSampler null_sampler(); image_view* null_image_view(command_buffer&, VkImageViewType type); image* get_typeless_helper(VkFormat format, rsx::format_class format_class, u32 requested_width, u32 requested_height); - buffer* get_scratch_buffer(u32 min_required_size); + buffer* get_scratch_buffer(u64 min_required_size); void clear_scratch_resources(); }