From b8de34da2ba30f05207d86f926ab97fe7309354b Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Thu, 12 Feb 2026 17:18:20 -0500 Subject: [PATCH] panvk: Use resolve shaders for color resolves This massively improves the performance of the Sascha Willems multisampling example: - With 2x MSAA: 590 -> 2605 (4.4x speedup) - With 4x MSAA: 347 -> 2570 (7.4x speedup) - With 8x MSAA: 188 FPS -> 2494 FPS (13.2x speedup) - With 16x MSAA: 96.7 FPS -> 2483 FPS (25.7x speedup) Reviewed-by: Lars-Ivar Hesselberg Simonsen Acked-by: Boris Brezillon Acked-by: Eric R. Smith Part-of: --- src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c | 7 ++-- src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c | 3 +- src/panfrost/vulkan/panvk_cmd_draw.h | 1 + src/panfrost/vulkan/panvk_vX_cmd_draw.c | 34 ++++++++++++++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index a44a497180c..174386de116 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -1308,7 +1308,8 @@ get_fb_descs(struct panvk_cmd_buffer *cmdbuf) }; VkResult result = panvk_per_arch(cmd_get_frame_shaders)( - cmdbuf, fbd_info.fb, fbd_info.load, NULL, &fbd_info.frame_shaders); + cmdbuf, fbd_info.fb, fbd_info.load, &render->fb.resolve, + &fbd_info.frame_shaders); if (result != VK_SUCCESS) return result; @@ -1348,7 +1349,9 @@ get_fb_descs(struct panvk_cmd_buffer *cmdbuf) &render->fb.store : &render->fb.spill.store; VkResult result = panvk_per_arch(cmd_get_frame_shaders)( - cmdbuf, fbd_info.fb, fbd_info.load, NULL, &fbd_info.frame_shaders); + cmdbuf, fbd_info.fb, fbd_info.load, + ir_pass == PANVK_IR_LAST_PASS ? &render->fb.resolve : NULL, + &fbd_info.frame_shaders); if (result != VK_SUCCESS) return result; diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c index 9ec36c5e15b..a7e0ba0c641 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c @@ -155,7 +155,8 @@ panvk_per_arch(cmd_close_batch)(struct panvk_cmd_buffer *cmdbuf) struct pan_fb_frame_shaders fs; VkResult result = panvk_per_arch(cmd_get_frame_shaders)( - cmdbuf, &render->fb.layout, fbd_info.load, NULL, &fs); + cmdbuf, &render->fb.layout, fbd_info.load, + render->fb.needs_store ? &render->fb.resolve : NULL, &fs); if (result != VK_SUCCESS) return; diff --git a/src/panfrost/vulkan/panvk_cmd_draw.h b/src/panfrost/vulkan/panvk_cmd_draw.h index 93a1e56394b..a0ac3af6d79 100644 --- a/src/panfrost/vulkan/panvk_cmd_draw.h +++ b/src/panfrost/vulkan/panvk_cmd_draw.h @@ -72,6 +72,7 @@ struct panvk_rendering_state { struct { struct pan_fb_layout layout; struct pan_fb_load load; + struct pan_fb_resolve resolve; struct pan_fb_store store; struct { struct pan_fb_load load; diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index 5fb2e18ece1..9750d3f9f70 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -45,6 +45,18 @@ get_att_fb_load_op(const VkRenderingAttachmentInfo *att) } } +static enum pan_fb_msaa_copy_op +vk_to_pan_fb_resolve_mode(VkResolveModeFlagBits resolveMode) +{ + switch (resolveMode) { + case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT: return PAN_FB_MSAA_COPY_SAMPLE_0; + case VK_RESOLVE_MODE_AVERAGE_BIT: return PAN_FB_MSAA_COPY_AVERAGE; + case VK_RESOLVE_MODE_MIN_BIT: return PAN_FB_MSAA_COPY_MIN; + case VK_RESOLVE_MODE_MAX_BIT: return PAN_FB_MSAA_COPY_MAX; + default: UNREACHABLE("Unsupported resolveMode"); + } +} + static struct panvk_image_view * get_ms2ss_image_view(struct panvk_image_view *iview, uint32_t nr_samples) { @@ -163,9 +175,25 @@ render_state_set_color_attachment(struct panvk_cmd_buffer *cmdbuf, assert(resolve.dst_iview != NULL); assert(resolve.dst_iview->pview.nr_samples == 1); - /* We need to store so we can do the MSAA resolve later */ - render->fb.store.rts[index] = pan_fb_store_iview(&iview->pview); - render->color_attachments.resolve[index] = resolve; + if (ms2ss || att->storeOp != VK_ATTACHMENT_STORE_OP_STORE) { + render->fb.resolve.rts[index] = (struct pan_fb_resolve_target) { + .in_bounds = { + .resolve = PAN_FB_RESOLVE_RT(index), + .msaa = vk_to_pan_fb_resolve_mode(att->resolveMode), + }, + .border = { + .resolve = PAN_FB_RESOLVE_IMAGE, + .msaa = PAN_FB_MSAA_COPY_SINGLE, + }, + .iview = &resolve.dst_iview->pview, + }; + render->fb.store.rts[index] = + pan_fb_always_store_iview_s0(&resolve.dst_iview->pview); + } else { + /* We need to store so we can do the MSAA resolve later */ + render->fb.store.rts[index] = pan_fb_store_iview(&iview->pview); + render->color_attachments.resolve[index] = resolve; + } } }