diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index c978906c38..f5dc4acdba 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -916,7 +916,7 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = {aspect, 0, 1, 0, 1}, + .subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}, }; // Single barrier handles both buffer and image @@ -950,7 +950,7 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = {aspect, 0, 1, 0, 1}, + .subresourceRange{aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}, }; cmdbuf.PipelineBarrier( diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 85b9bcd6b9..966aed5408 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -591,19 +591,24 @@ struct RangedBarrierRange { max_layer = (std::max)(max_layer, layers.baseArrayLayer + layers.layerCount); } - VkImageSubresourceRange SubresourceRange(VkImageAspectFlags aspect_mask) const noexcept { + VkImageSubresourceRange SubresourceRange(VkImageAspectFlags aspect_mask, bool is_3d = false) const noexcept { + u32 layer_count = max_layer - min_layer; + // For 3D images with 2D_ARRAY compatibility, use VK_REMAINING_ARRAY_LAYERS for single layer + if (is_3d && layer_count == 1) { + layer_count = VK_REMAINING_ARRAY_LAYERS; + } return VkImageSubresourceRange{ .aspectMask = aspect_mask, .baseMipLevel = min_mip, .levelCount = max_mip - min_mip, .baseArrayLayer = min_layer, - .layerCount = max_layer - min_layer, + .layerCount = layer_count, }; } }; void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image, VkImageAspectFlags aspect_mask, bool is_initialized, - std::span copies) { + std::span copies, bool is_3d_image = false) { static constexpr VkAccessFlags WRITE_ACCESS_FLAGS = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; @@ -616,7 +621,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im for (const auto& region : copies) { range.AddLayers(region.imageSubresource); } - const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask); + const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask, is_3d_image); const VkImageMemoryBarrier read_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1096,9 +1101,11 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, const VkBuffer copy_buffer = GetTemporaryBuffer(total_size); const VkImage dst_image = dst.Handle(); const VkImage src_image = src.Handle(); + const bool dst_is_3d = dst.info.type == ImageType::e3D; + const bool src_is_3d = src.info.type == ImageType::e3D; scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask, - vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) { + vk_in_copies, vk_out_copies, dst_is_3d, src_is_3d](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; for (const VkBufferImageCopy& copy : vk_in_copies) { @@ -1133,7 +1140,7 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = src_image, - .subresourceRange = src_range.SubresourceRange(src_aspect_mask), + .subresourceRange = src_range.SubresourceRange(src_aspect_mask, src_is_3d), }, }; const std::array middle_in_barrier{ @@ -1147,7 +1154,7 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = src_image, - .subresourceRange = src_range.SubresourceRange(src_aspect_mask), + .subresourceRange = src_range.SubresourceRange(src_aspect_mask, src_is_3d), }, }; const std::array middle_out_barrier{ @@ -1163,7 +1170,7 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), + .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask, dst_is_3d), }, }; const std::array post_barriers{ @@ -1182,18 +1189,11 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), + .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask, dst_is_3d), }, }; - const VkPipelineStageFlags src_stages_transfer = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT; - cmdbuf.PipelineBarrier(src_stages_transfer, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, {}, {}, pre_barriers); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + 0, {}, {}, post_barriers); cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer, vk_in_copies); @@ -1570,8 +1570,10 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, }); const VkImage dst_image = dst.Handle(); const VkImage src_image = src.Handle(); + const bool src_is_3d = src.info.type == ImageType::e3D; + const bool dst_is_3d = dst.info.type == ImageType::e3D; scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([dst_image, src_image, aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { + scheduler.Record([dst_image, src_image, aspect_mask, vk_copies, src_is_3d, dst_is_3d](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; for (const VkImageCopy& copy : vk_copies) { @@ -1591,7 +1593,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = src_image, - .subresourceRange = src_range.SubresourceRange(aspect_mask), + .subresourceRange = src_range.SubresourceRange(aspect_mask, src_is_3d), }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1605,7 +1607,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = dst_range.SubresourceRange(aspect_mask), + .subresourceRange = dst_range.SubresourceRange(aspect_mask, dst_is_3d), }, }; const std::array post_barriers{ @@ -1619,7 +1621,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = src_image, - .subresourceRange = src_range.SubresourceRange(aspect_mask), + .subresourceRange = src_range.SubresourceRange(aspect_mask, src_is_3d), }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1636,7 +1638,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = dst_image, - .subresourceRange = dst_range.SubresourceRange(aspect_mask), + .subresourceRange = dst_range.SubresourceRange(aspect_mask, dst_is_3d), }, }; cmdbuf.PipelineBarrier( @@ -1819,7 +1821,7 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask, vk_copies, keep = temp_wrapper](vk::CommandBuffer cmdbuf) { - CopyBufferToImage(cmdbuf, src_buffer, temp_vk_image, vk_aspect_mask, false, VideoCommon::FixSmallVectorADL(vk_copies)); + CopyBufferToImage(cmdbuf, src_buffer, temp_vk_image, vk_aspect_mask, false, VideoCommon::FixSmallVectorADL(vk_copies), false); }); // Use MSAACopyPass to convert from non-MSAA to MSAA @@ -1855,10 +1857,11 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, const VkImage vk_image = *original_image; const VkImageAspectFlags vk_aspect_mask = aspect_mask; const bool was_initialized = std::exchange(initialized, true); + const bool is_3d = info.type == ImageType::e3D; scheduler->Record([src_buffer, vk_image, vk_aspect_mask, was_initialized, - vk_copies](vk::CommandBuffer cmdbuf) { - CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized, VideoCommon::FixSmallVectorADL(vk_copies)); + vk_copies, is_3d](vk::CommandBuffer cmdbuf) { + CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized, VideoCommon::FixSmallVectorADL(vk_copies), is_3d); }); if (is_rescaled) {