diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index cf84e03c85..41c2a50a42 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -455,6 +455,15 @@ TransformBufferCopies(std::span copies, size_t bu }; } +[[nodiscard]] VkImageSubresourceRange Expand3DSubresourceRange(VkImageSubresourceRange range, + bool is_3d_image) { + if (is_3d_image) { + range.baseArrayLayer = 0; + range.layerCount = VK_REMAINING_ARRAY_LAYERS; + } + return range; +} + [[nodiscard]] VkImageSubresourceRange MakeSubresourceRange(const ImageView* image_view) { SubresourceRange range = image_view->range; if (True(image_view->flags & VideoCommon::ImageViewFlagBits::Slice)) { @@ -463,7 +472,8 @@ TransformBufferCopies(std::span copies, size_t bu range.base.layer = 0; range.extent.layers = 1; } - return MakeSubresourceRange(ImageAspectMask(image_view->format), range); + return Expand3DSubresourceRange(MakeSubresourceRange(ImageAspectMask(image_view->format), range), + image_view->Is3DImage()); } [[nodiscard]] VkImageSubresourceLayers MakeSubresourceLayers(const ImageView* image_view) { @@ -544,7 +554,7 @@ struct RangedBarrierRange { } }; void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image, - VkImageAspectFlags aspect_mask, bool is_initialized, + VkImageAspectFlags aspect_mask, bool is_initialized, bool is_3d_image, std::span copies) { static constexpr VkAccessFlags WRITE_ACCESS_FLAGS = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | @@ -558,7 +568,8 @@ 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); + VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask); + subresource_range = Expand3DSubresourceRange(subresource_range, is_3d_image); const VkImageMemoryBarrier read_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1481,14 +1492,21 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, }); 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, aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { + scheduler.Record([dst_image, src_image, aspect_mask, vk_copies, dst_is_3d, + src_is_3d](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; for (const VkImageCopy& copy : vk_copies) { dst_range.AddLayers(copy.dstSubresource); src_range.AddLayers(copy.srcSubresource); } + const VkImageSubresourceRange dst_subresource = + Expand3DSubresourceRange(dst_range.SubresourceRange(aspect_mask), dst_is_3d); + const VkImageSubresourceRange src_subresource = + Expand3DSubresourceRange(src_range.SubresourceRange(aspect_mask), src_is_3d); const std::array pre_barriers{ VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1502,7 +1520,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_subresource, }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1516,7 +1534,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_subresource, }, }; const std::array post_barriers{ @@ -1530,7 +1548,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_subresource, }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1547,7 +1565,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_subresource, }, }; cmdbuf.PipelineBarrier( @@ -1577,14 +1595,21 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, }); 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, aspect_mask, vk_resolves](vk::CommandBuffer cmdbuf) { + scheduler.Record([dst_image, src_image, aspect_mask, vk_resolves, dst_is_3d, + src_is_3d](vk::CommandBuffer cmdbuf) { RangedBarrierRange dst_range; RangedBarrierRange src_range; for (const VkImageResolve& region : vk_resolves) { dst_range.AddLayers(region.dstSubresource); src_range.AddLayers(region.srcSubresource); } + const VkImageSubresourceRange dst_subresource = + Expand3DSubresourceRange(dst_range.SubresourceRange(aspect_mask), dst_is_3d); + const VkImageSubresourceRange src_subresource = + Expand3DSubresourceRange(src_range.SubresourceRange(aspect_mask), src_is_3d); const std::array pre_barriers{ VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1599,7 +1624,7 @@ void TextureCacheRuntime::CopyImageMSAA(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_subresource, }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1614,7 +1639,7 @@ void TextureCacheRuntime::CopyImageMSAA(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_subresource, }, }; const std::array post_barriers{ @@ -1628,7 +1653,7 @@ void TextureCacheRuntime::CopyImageMSAA(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_subresource, }, VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1646,7 +1671,7 @@ void TextureCacheRuntime::CopyImageMSAA(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_subresource, }, }; cmdbuf.PipelineBarrier( @@ -1791,9 +1816,10 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, const VkImage temp_vk_image = *temp_wrapper->original_image; const VkImageAspectFlags vk_aspect_mask = temp_wrapper->aspect_mask; - scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask, vk_copies, + const bool temp_is_3d = temp_info.type == ImageType::e3D; + scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask, vk_copies, temp_is_3d, 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, temp_is_3d, VideoCommon::FixSmallVectorADL(vk_copies)); }); // Use MSAACopyPass to convert from non-MSAA to MSAA @@ -1830,9 +1856,10 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, const VkImageAspectFlags vk_aspect_mask = aspect_mask; const bool was_initialized = std::exchange(initialized, true); - scheduler->Record([src_buffer, vk_image, vk_aspect_mask, was_initialized, + const bool is_3d_image = info.type == ImageType::e3D; + scheduler->Record([src_buffer, vk_image, vk_aspect_mask, was_initialized, is_3d_image, vk_copies](vk::CommandBuffer cmdbuf) { - CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized, VideoCommon::FixSmallVectorADL(vk_copies)); + CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized, is_3d_image, VideoCommon::FixSmallVectorADL(vk_copies)); }); if (is_rescaled) { @@ -2216,7 +2243,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI ImageId image_id_, Image& image) : VideoCommon::ImageViewBase{info, image.info, image_id_, image.gpu_addr}, device{&runtime.device}, image_handle{image.Handle()}, - samples(ConvertSampleCount(image.info.num_samples)) { + samples(ConvertSampleCount(image.info.num_samples)), + is_3d_image(image.info.type == ImageType::e3D) { using Shader::TextureType; const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); @@ -2314,7 +2342,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info, const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) : VideoCommon::ImageViewBase{info, view_info, gpu_addr_}, - buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} + buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)}, + is_3d_image(info.type == ImageType::e3D) {} ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params) : VideoCommon::ImageViewBase{params}, device{&runtime.device} { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 12e0802912..b5aa271bda 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -281,6 +281,10 @@ public: [[nodiscard]] bool SupportsDepthCompareSampling() const noexcept; + [[nodiscard]] bool Is3DImage() const noexcept { + return is_3d_image; + } + [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { return *image_views[static_cast(texture_type)]; } @@ -337,6 +341,7 @@ private: VkImageView render_target = VK_NULL_HANDLE; VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; u32 buffer_size = 0; + bool is_3d_image = false; }; class ImageAlloc : public VideoCommon::ImageAllocBase {};