From e058a15074c8c1881c9b624b750a6bd0d002de27 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 16 Jul 2026 20:29:18 -0400 Subject: [PATCH] [TEST] Wire MSAA resolve to dynamic rendering native resolve --- .../renderer_vulkan/vk_scheduler.cpp | 25 ++++++-- src/video_core/renderer_vulkan/vk_scheduler.h | 3 + .../renderer_vulkan/vk_texture_cache.cpp | 64 +++++++++++++++++-- .../renderer_vulkan/vk_texture_cache.h | 11 ++++ 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 5dba1ebdd9..cbb3010b5f 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -104,6 +104,9 @@ void Scheduler::BeginDynamicRendering(const Framebuffer* framebuffer, const Defe state.renderpass = VkRenderPass{}; state.framebuffer = VkFramebuffer{}; state.attachment_views = attachment_views; + state.color_resolve_views = framebuffer->ColorResolveAttachments(); + state.color_resolve_modes = framebuffer->ColorResolveModes(); + state.discards_msaa_color = framebuffer->DiscardsMsaaColor(); state.render_area = render_area; state.num_color = framebuffer->NumColorAttachments(); state.has_depth = framebuffer->HasAspectDepthBit(); @@ -432,31 +435,41 @@ void Scheduler::InvalidateState() { void Scheduler::RecordDynamicBegin(const DeferredClear* clear) { const std::array views = state.attachment_views; + const std::array resolve_views = state.color_resolve_views; + const std::array resolve_modes = state.color_resolve_modes; const u32 num_color = state.num_color; const bool has_depth = state.has_depth; const bool has_stencil = state.has_stencil; const u32 layers = state.layer_count; const VkExtent2D render_area = state.render_area; const u32 color_clear_mask = clear ? clear->color_clear_mask : 0u; + const u32 color_discard_mask = + clear != nullptr && state.discards_msaa_color ? clear->color_clear_mask : 0u; const std::array color_clear_values = clear ? clear->color_values : std::array{}; const bool ds_clear = clear != nullptr && clear->depth_stencil; const VkClearValue ds_clear_value = clear ? clear->depth_stencil_value : VkClearValue{}; - Record([views, num_color, has_depth, has_stencil, layers, render_area, color_clear_mask, - color_clear_values, ds_clear, ds_clear_value](vk::CommandBuffer cmdbuf) { + Record([views, resolve_views, resolve_modes, num_color, has_depth, has_stencil, layers, + render_area, color_clear_mask, color_discard_mask, color_clear_values, ds_clear, + ds_clear_value](vk::CommandBuffer cmdbuf) { std::array color_infos{}; for (u32 index = 0; index < num_color; ++index) { const bool clear_slot = ((color_clear_mask >> index) & 1u) != 0; + const VkImageView resolve_view = resolve_views[index]; + const bool has_resolve = resolve_view != VK_NULL_HANDLE; + const bool discard_slot = has_resolve && ((color_discard_mask >> index) & 1u) != 0; color_infos[index] = VkRenderingAttachmentInfo{ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .pNext = nullptr, .imageView = views[index], .imageLayout = VK_IMAGE_LAYOUT_GENERAL, - .resolveMode = VK_RESOLVE_MODE_NONE, - .resolveImageView = VK_NULL_HANDLE, - .resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .resolveMode = has_resolve ? resolve_modes[index] : VK_RESOLVE_MODE_NONE, + .resolveImageView = resolve_view, + .resolveImageLayout = + has_resolve ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, .loadOp = clear_slot ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .storeOp = discard_slot ? VK_ATTACHMENT_STORE_OP_DONT_CARE + : VK_ATTACHMENT_STORE_OP_STORE, .clearValue = clear_slot ? color_clear_values[index] : VkClearValue{}, }; } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 1ebd80db2b..4af0054ea2 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -251,9 +251,12 @@ private: VkRenderPass renderpass{}; VkFramebuffer framebuffer{}; std::array attachment_views{}; + std::array color_resolve_views{}; + std::array color_resolve_modes{}; VkExtent2D render_area = {0, 0}; GraphicsPipeline* graphics_pipeline = nullptr; bool rendering = false; + bool discards_msaa_color = false; u32 num_color = 0; bool has_depth = false; bool has_stencil = false; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 6e7507ad3e..8aeafde03b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1041,6 +1041,31 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk shadow.extent = extent; shadow.layers = layers; shadow.up_to_date = true; + if (device.IsKhrDynamicRenderingSupported()) { + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([image = *shadow.image, layers](vk::CommandBuffer cmdbuf) { + const VkImageMemoryBarrier barrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = layers, + }, + }; + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, barrier); + }); + } return *shadow.view; } @@ -2760,8 +2785,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, } renderpass_key.samples = samples; const bool do_resolve_color = - samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0 && runtime.device.IsTiler() && - !runtime.device.IsKhrDynamicRenderingSupported(); + samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0 && runtime.device.IsTiler(); renderpass_key.resolve_color = do_resolve_color; discard_msaa_color = @@ -2781,10 +2805,15 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, } const VkFormat vk_format = MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, format).format; + color_resolve_modes[index] = VideoCore::Surface::IsPixelFormatInteger(format) + ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT + : VK_RESOLVE_MODE_AVERAGE_BIT; if (ENABLE_MSAA_RESOLVE_CONSUME) { const VkImage msaa_image = images[rt_map[index]]; - attachments.push_back(runtime.GetOrCreateResolveShadow(msaa_image, vk_format, - render_area, layers)); + const VkImageView shadow_view = runtime.GetOrCreateResolveShadow( + msaa_image, vk_format, render_area, layers); + color_resolve_attachments[index] = shadow_view; + attachments.push_back(shadow_view); continue; } VkImageCreateInfo resolve_ci{ @@ -2823,6 +2852,33 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, .layerCount = layers, }, }); + if (runtime.device.IsKhrDynamicRenderingSupported()) { + runtime.scheduler.RequestOutsideRenderPassOperationContext(); + runtime.scheduler.Record([image = *resolve_image, layers](vk::CommandBuffer cmdbuf) { + const VkImageMemoryBarrier barrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = layers, + }, + }; + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, + barrier); + }); + } + color_resolve_attachments[index] = *resolve_view; attachments.push_back(*resolve_view); resolve_images.push_back(std::move(resolve_image)); resolve_image_views.push_back(std::move(resolve_view)); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 003d7995cc..d3cd36b049 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -207,6 +207,15 @@ public: return color_attachment_formats; } + [[nodiscard]] const std::array& ColorResolveAttachments() const noexcept { + return color_resolve_attachments; + } + + [[nodiscard]] const std::array& ColorResolveModes() + const noexcept { + return color_resolve_modes; + } + [[nodiscard]] VkImageView DepthAttachment() const noexcept { return depth_attachment; } @@ -283,6 +292,8 @@ private: std::array rt_map{}; std::array color_attachments{}; std::array color_attachment_formats{}; + std::array color_resolve_attachments{}; + std::array color_resolve_modes{}; VkImageView depth_attachment{}; VkFormat depth_attachment_format = VK_FORMAT_UNDEFINED; u32 num_color_attachments = 0;