diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 65c0533e..d68eaa74 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -203,21 +203,9 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) { Frame* frame = GetRenderFrame(); // Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image. - const std::array pre_barriers{ - vk::ImageMemoryBarrier{.srcAccessMask = vk::AccessFlagBits::eTransferWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead, - .oldLayout = vk::ImageLayout::eUndefined, - .newLayout = vk::ImageLayout::eTransferSrcOptimal, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image.image, - .subresourceRange{ - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }}, + image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead); + + const std::array pre_barrier{ vk::ImageMemoryBarrier{ .srcAccessMask = vk::AccessFlagBits::eTransferRead, .dstAccessMask = vk::AccessFlagBits::eTransferWrite, @@ -235,6 +223,17 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) { }, }, }; + + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, + vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, + {}, {}, pre_barrier); + + cmdbuf.blitImage( + image.image, image.layout, frame->image, vk::ImageLayout::eTransferDstOptimal, + MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height), + vk::Filter::eLinear); + const vk::ImageMemoryBarrier post_barrier{ .srcAccessMask = vk::AccessFlagBits::eTransferWrite, .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, @@ -252,16 +251,6 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) { }, }; - const auto cmdbuf = scheduler.CommandBuffer(); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, - vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, - {}, {}, pre_barriers); - cmdbuf.blitImage( - image.image, vk::ImageLayout::eTransferSrcOptimal, frame->image, - vk::ImageLayout::eTransferDstOptimal, - MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height), - vk::Filter::eLinear); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, vk::DependencyFlagBits::eByRegion, {}, {}, post_barrier); diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 83efe17c..ea0336cc 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -124,27 +124,41 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, image.Create(image_ci); - const vk::ImageMemoryBarrier init_barrier = { - .srcAccessMask = vk::AccessFlagBits::eNone, - .dstAccessMask = vk::AccessFlagBits::eNone, - .oldLayout = vk::ImageLayout::eUndefined, - .newLayout = vk::ImageLayout::eGeneral, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; + Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone); +} +void Image::Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask) { + if (dst_layout == layout && dst_mask == access_mask) { + return; + } + + const vk::ImageMemoryBarrier barrier = {.srcAccessMask = access_mask, + .dstAccessMask = dst_mask, + .oldLayout = layout, + .newLayout = dst_layout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }}; + + // Adjust pipieline stage + vk::PipelineStageFlagBits dst_pl_stage = (dst_mask == vk::AccessFlagBits::eTransferRead || + dst_mask == vk::AccessFlagBits::eTransferWrite) + ? vk::PipelineStageFlagBits::eTransfer + : vk::PipelineStageFlagBits::eAllGraphics; const auto cmdbuf = scheduler->CommandBuffer(); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, - vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlagBits::eByRegion, - {}, {}, init_barrier); + cmdbuf.pipelineBarrier(pl_stage, dst_pl_stage, vk::DependencyFlagBits::eByRegion, {}, {}, + barrier); + + layout = dst_layout; + access_mask = dst_mask; + pl_stage = dst_pl_stage; } Image::~Image() = default; diff --git a/src/video_core/texture_cache/image.h b/src/video_core/texture_cache/image.h index 3048229d..32c9df6e 100644 --- a/src/video_core/texture_cache/image.h +++ b/src/video_core/texture_cache/image.h @@ -100,14 +100,21 @@ struct Image { return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end; } + void Transit(vk::ImageLayout dst_layout, vk::Flags dst_mask); + const Vulkan::Instance* instance; Vulkan::Scheduler* scheduler; ImageInfo info; UniqueImage image; - vk::ImageAspectFlags aspect_mask; + vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor; ImageFlagBits flags = ImageFlagBits::CpuModified; VAddr cpu_addr = 0; VAddr cpu_addr_end = 0; + + // Resource state tracking + vk::Flags pl_stage = vk::PipelineStageFlagBits::eAllCommands; + vk::Flags access_mask = vk::AccessFlagBits::eNone; + vk::ImageLayout layout = vk::ImageLayout::eUndefined; }; } // namespace VideoCore diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 7242ebe0..71abd9c2 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -166,35 +166,14 @@ void TextureCache::RefreshImage(Image& image) { .baseArrayLayer = 0, .layerCount = VK_REMAINING_ARRAY_LAYERS, }; - const vk::ImageMemoryBarrier read_barrier = { - .srcAccessMask = vk::AccessFlagBits::eShaderRead, - .dstAccessMask = vk::AccessFlagBits::eTransferWrite, - .oldLayout = vk::ImageLayout::eGeneral, - .newLayout = vk::ImageLayout::eTransferDstOptimal, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image.image, - .subresourceRange = range, - }; - const vk::ImageMemoryBarrier write_barrier = { - .srcAccessMask = vk::AccessFlagBits::eTransferWrite, - .dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead, - .oldLayout = vk::ImageLayout::eTransferDstOptimal, - .newLayout = vk::ImageLayout::eGeneral, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image.image, - .subresourceRange = range, - }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, - vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, - {}, {}, read_barrier); + image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits::eTransferWrite); + cmdbuf.copyBufferToImage(staging.Handle(), image.image, vk::ImageLayout::eTransferDstOptimal, image_copy); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, - vk::PipelineStageFlagBits::eAllGraphics, - vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier); + + image.Transit(vk::ImageLayout::eGeneral, + vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead); } void TextureCache::RegisterImage(ImageId image_id) {