From 4de9d81b506a5a59447dbc22bbf94a8287932862 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Mon, 20 Nov 2023 12:28:51 -0800 Subject: [PATCH] vk_texture_runtime: Resolve MSAA source image before blit Resolves the MSAA image to the upscale-image before blitting to ensure it is getting the freshest MSAA resolve. Todo: use a dirty flag. --- .../renderer_vulkan/vk_texture_runtime.cpp | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 95041c60e..f07dba5a0 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -576,6 +576,87 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest, .dst_image = dest.Image(1), }; + // Must resolve source-image first + if ((source.sample_count > dest.sample_count) && (dest.sample_count == 1)) { + + scheduler.Record([&source](vk::CommandBuffer cmdbuf) { + const vk::ImageResolve resolve_area = { + .srcSubresource{ + .aspectMask = source.Aspect(), + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .srcOffset = {}, + .dstSubresource{ + .aspectMask = source.Aspect(), + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .dstOffset = {}, + .extent{source.GetScaledWidth(), source.GetScaledHeight(), 0}, + }; + + const std::array read_barriers = { + vk::ImageMemoryBarrier{ + .srcAccessMask = source.AccessFlags(), + .dstAccessMask = vk::AccessFlagBits::eTransferRead, + .oldLayout = vk::ImageLayout::eGeneral, + .newLayout = vk::ImageLayout::eTransferSrcOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = source.Image(3), + .subresourceRange = MakeSubresourceRange(source.Aspect(), 0), + }, + vk::ImageMemoryBarrier{ + .srcAccessMask = source.AccessFlags(), + .dstAccessMask = vk::AccessFlagBits::eTransferWrite, + .oldLayout = vk::ImageLayout::eGeneral, + .newLayout = vk::ImageLayout::eTransferDstOptimal, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = source.Image(1), + .subresourceRange = MakeSubresourceRange(source.Aspect(), 0), + }, + }; + const std::array write_barriers = { + vk::ImageMemoryBarrier{ + .srcAccessMask = vk::AccessFlagBits::eTransferRead, + .dstAccessMask = source.AccessFlags(), + .oldLayout = vk::ImageLayout::eTransferSrcOptimal, + .newLayout = vk::ImageLayout::eGeneral, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = source.Image(3), + .subresourceRange = MakeSubresourceRange(source.Aspect(), 0), + }, + vk::ImageMemoryBarrier{ + .srcAccessMask = vk::AccessFlagBits::eTransferWrite, + .dstAccessMask = source.AccessFlags(), + .oldLayout = vk::ImageLayout::eTransferDstOptimal, + .newLayout = vk::ImageLayout::eGeneral, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = source.Image(1), + .subresourceRange = MakeSubresourceRange(source.Aspect(), 0), + }, + }; + + cmdbuf.pipelineBarrier(source.PipelineStageFlags(), + vk::PipelineStageFlagBits::eTransfer, + vk::DependencyFlagBits::eByRegion, {}, {}, read_barriers); + + cmdbuf.resolveImage(source.Image(3), vk::ImageLayout::eTransferSrcOptimal, + source.Image(1), vk::ImageLayout::eTransferDstOptimal, + resolve_area); + + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, + source.PipelineStageFlags(), vk::DependencyFlagBits::eByRegion, + {}, {}, write_barriers); + }); + } + scheduler.Record([params, blit](vk::CommandBuffer cmdbuf) { const std::array source_offsets = { vk::Offset3D{static_cast(blit.src_rect.left),