From 5d2e297556bdde79c28a2bad66b2134253369ee6 Mon Sep 17 00:00:00 2001 From: Christoph Pillmayer Date: Fri, 5 Dec 2025 09:28:58 +0000 Subject: [PATCH] panvk: Setup attachments for ms to ss rendering Reviewed-by: Lars-Ivar Hesselberg Simonsen Part-of: --- src/panfrost/vulkan/panvk_vX_cmd_draw.c | 123 +++++++++++++++++++++++- 1 file changed, 119 insertions(+), 4 deletions(-) diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index ab6bbe55d8a..edca26ee5c6 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -48,6 +48,42 @@ att_set_clear_preload(const VkRenderingAttachmentInfo *att, bool *clear, bool *p } } +static struct panvk_image_view * +get_ms2ss_image_view(struct panvk_image_view *iview, uint32_t nr_samples) +{ + assert(nr_samples >= 2 && nr_samples <= 16); + assert(iview->pview.nr_samples == 1); + assert(iview->vk.image->create_flags & + VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT); + + /* sample count 2 is at index 0, 4 at 1, .. */ + uint32_t vidx = 0; + switch (nr_samples) { + case VK_SAMPLE_COUNT_2_BIT: + vidx = 0; + break; + case VK_SAMPLE_COUNT_4_BIT: + vidx = 1; + break; + case VK_SAMPLE_COUNT_8_BIT: + vidx = 2; + break; + case VK_SAMPLE_COUNT_16_BIT: + vidx = 3; + break; + default: + UNREACHABLE("unhandled sample count"); + } + assert(iview->ms_views[vidx] != VK_NULL_HANDLE); + + struct panvk_image_view *res = + panvk_image_view_from_handle(iview->ms_views[vidx]); + + assert(res->pview.nr_samples == nr_samples); + + return res; +} + static void render_state_set_color_attachment(struct panvk_cmd_buffer *cmdbuf, const VkRenderingAttachmentInfo *att, @@ -58,11 +94,24 @@ render_state_set_color_attachment(struct panvk_cmd_buffer *cmdbuf, struct panvk_cmd_graphics_state *state = &cmdbuf->state.gfx; struct pan_fb_info *fbinfo = &state->render.fb.info; VK_FROM_HANDLE(panvk_image_view, iview, att->imageView); + + struct panvk_image_view *iview_ss = NULL; + const bool ms2ss = cmdbuf->state.gfx.render.fb.nr_samples > 1 && + iview->pview.nr_samples == 1; + + if (ms2ss) { + iview_ss = iview; + iview = + get_ms2ss_image_view(iview, cmdbuf->state.gfx.render.fb.nr_samples); + } + struct panvk_image *img = container_of(iview->vk.image, struct panvk_image, vk); state->render.bound_attachments |= MESA_VK_RP_ATTACHMENT_COLOR_BIT(index); state->render.color_attachments.iviews[index] = iview; + state->render.color_attachments.preload_iviews[index] = + ms2ss ? iview_ss : NULL; state->render.color_attachments.fmts[index] = iview->vk.format; state->render.color_attachments.samples[index] = img->vk.samples; @@ -103,8 +152,20 @@ render_state_set_color_attachment(struct panvk_cmd_buffer *cmdbuf, &state->render.color_attachments.resolve[index]; VK_FROM_HANDLE(panvk_image_view, resolve_iview, att->resolveImageView); + /* VUID-VkRenderingAttachmentInfo-imageView-06862 and + * VUID-VkRenderingAttachmentInfo-imageView-06863: + * If resolveMode != NONE, then + * resolveView == NULL iff. multisampledRenderToSingleSampledEnable */ + assert(ms2ss == (resolve_iview == NULL)); + resolve_info->mode = att->resolveMode; - resolve_info->dst_iview = resolve_iview; + if (!ms2ss) { + resolve_info->dst_iview = resolve_iview; + } else { + assert(iview_ss); + resolve_info->dst_iview = iview_ss; + assert(resolve_info->dst_iview->pview.nr_samples == 1); + } } } @@ -115,6 +176,17 @@ render_state_set_z_attachment(struct panvk_cmd_buffer *cmdbuf, struct panvk_cmd_graphics_state *state = &cmdbuf->state.gfx; struct pan_fb_info *fbinfo = &state->render.fb.info; VK_FROM_HANDLE(panvk_image_view, iview, att->imageView); + + struct panvk_image_view *iview_ss = NULL; + const bool ms2ss = cmdbuf->state.gfx.render.fb.nr_samples > 1 && + iview->pview.nr_samples == 1; + + if (ms2ss) { + iview_ss = iview; + iview = + get_ms2ss_image_view(iview, cmdbuf->state.gfx.render.fb.nr_samples); + } + struct panvk_image *img = container_of(iview->vk.image, struct panvk_image, vk); @@ -142,6 +214,7 @@ render_state_set_z_attachment(struct panvk_cmd_buffer *cmdbuf, MAX2(state->render.fb.nr_samples, pan_image_view_get_nr_samples(&iview->pview)); state->render.z_attachment.iview = iview; + state->render.z_attachment.preload_iview = ms2ss ? iview_ss : NULL; /* D24S8 is a single plane format where the depth/stencil are interleaved. * If we touch the depth component, we need to make sure the stencil @@ -166,7 +239,13 @@ render_state_set_z_attachment(struct panvk_cmd_buffer *cmdbuf, VK_FROM_HANDLE(panvk_image_view, resolve_iview, att->resolveImageView); resolve_info->mode = att->resolveMode; - resolve_info->dst_iview = resolve_iview; + if (!ms2ss) { + resolve_info->dst_iview = resolve_iview; + } else { + assert(iview_ss); + resolve_info->dst_iview = iview_ss; + assert(resolve_info->dst_iview->pview.nr_samples == 1); + } } } @@ -177,6 +256,17 @@ render_state_set_s_attachment(struct panvk_cmd_buffer *cmdbuf, struct panvk_cmd_graphics_state *state = &cmdbuf->state.gfx; struct pan_fb_info *fbinfo = &state->render.fb.info; VK_FROM_HANDLE(panvk_image_view, iview, att->imageView); + + struct panvk_image_view *iview_ss = NULL; + const bool ms2ss = cmdbuf->state.gfx.render.fb.nr_samples > 1 && + iview->pview.nr_samples == 1; + + if (ms2ss) { + iview_ss = iview; + iview = + get_ms2ss_image_view(iview, cmdbuf->state.gfx.render.fb.nr_samples); + } + struct panvk_image *img = container_of(iview->vk.image, struct panvk_image, vk); @@ -212,6 +302,7 @@ render_state_set_s_attachment(struct panvk_cmd_buffer *cmdbuf, MAX2(state->render.fb.nr_samples, pan_image_view_get_nr_samples(&iview->pview)); state->render.s_attachment.iview = iview; + state->render.s_attachment.preload_iview = ms2ss ? iview_ss : NULL; /* If the depth and stencil attachments point to the same image, * and the format is D24S8, we can combine them in a single view @@ -248,7 +339,13 @@ render_state_set_s_attachment(struct panvk_cmd_buffer *cmdbuf, VK_FROM_HANDLE(panvk_image_view, resolve_iview, att->resolveImageView); resolve_info->mode = att->resolveMode; - resolve_info->dst_iview = resolve_iview; + if (!ms2ss) { + resolve_info->dst_iview = resolve_iview; + } else { + assert(iview_ss); + resolve_info->dst_iview = iview_ss; + assert(resolve_info->dst_iview->pview.nr_samples == 1); + } } } @@ -283,6 +380,13 @@ panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf, memset(&state->render.s_attachment, 0, sizeof(state->render.s_attachment)); state->render.bound_attachments = 0; + const VkMultisampledRenderToSingleSampledInfoEXT *ms2ss_info = + vk_find_struct_const(pRenderingInfo, + MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT); + const bool ms2ss = ms2ss_info + ? ms2ss_info->multisampledRenderToSingleSampledEnable + : VK_FALSE; + cmdbuf->state.gfx.render.layer_count = pRenderingInfo->viewMask ? util_last_bit(pRenderingInfo->viewMask) : pRenderingInfo->layerCount; @@ -293,7 +397,12 @@ panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf, .nr_samples = 0, .rt_count = pRenderingInfo->colorAttachmentCount, }; - cmdbuf->state.gfx.render.fb.nr_samples = 1; + /* In case ms2ss is enabled, use the provided sample count. + * All attachments need to have sample count == 1 or the provided value. + * But, if all attachments have 1, we would end up choosing the wrong value + * if we don't set it here already. */ + cmdbuf->state.gfx.render.fb.nr_samples = + ms2ss ? ms2ss_info->rasterizationSamples : 1; assert(pRenderingInfo->colorAttachmentCount <= ARRAY_SIZE(fbinfo->rts)); @@ -391,6 +500,7 @@ panvk_per_arch(cmd_resolve_attachments)(struct panvk_cmd_buffer *cmdbuf) util_last_bit(bound_atts & MESA_VK_RP_ATTACHMENT_ANY_COLOR_BITS); VkRenderingAttachmentInfo color_atts[MAX_RTS]; for (uint32_t i = 0; i < color_att_count; i++) { + const struct panvk_resolve_attachment *resolve_info = &cmdbuf->state.gfx.render.color_attachments.resolve[i]; struct panvk_image_view *src_iview = @@ -408,6 +518,11 @@ panvk_per_arch(cmd_resolve_attachments)(struct panvk_cmd_buffer *cmdbuf) if (resolve_info->mode != VK_RESOLVE_MODE_NONE) needs_resolve = true; + + if (resolve_info->mode != VK_RESOLVE_MODE_NONE) { + assert(src_iview->pview.nr_samples > 1); + assert(resolve_info->dst_iview->pview.nr_samples == 1); + } } const struct panvk_resolve_attachment *resolve_info =