panvk: Also use resolve shaders for Z/S

As a side-effect, we're now also respecting storeOp for separate Z/S.
For interleaved, we still always store because interleaved is annoyingly
complicated.

Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com>
Acked-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39759>
This commit is contained in:
Faith Ekstrand 2026-02-13 23:27:10 -05:00 committed by Marge Bot
parent b8de34da2b
commit 46f611c932
2 changed files with 82 additions and 29 deletions

View file

@ -66,7 +66,7 @@ struct panvk_rendering_state {
/* Used for separate Z/S images */ /* Used for separate Z/S images */
struct { struct {
struct pan_image_view load, spill, store; struct pan_image_view load, spill, store, resolve;
} z_pview, s_pview; } z_pview, s_pview;
struct { struct {

View file

@ -412,49 +412,102 @@ render_state_set_zs_attachments(struct panvk_cmd_buffer *cmdbuf,
* multisample resolves. * multisample resolves.
*/ */
struct panvk_resolve_attachment z_resolve = { };
if (z_att && z_att->resolveMode != VK_RESOLVE_MODE_NONE) {
VK_FROM_HANDLE(panvk_image_view, resolve_iview, z_att->resolveImageView);
assert(z_ms2ss == (resolve_iview == NULL));
z_resolve = (struct panvk_resolve_attachment) {
.dst_iview = z_ms2ss ? z_iview_ss : resolve_iview,
.mode = z_att->resolveMode,
};
assert(z_resolve.dst_iview != NULL);
assert(z_resolve.dst_iview->pview.nr_samples == 1);
}
struct panvk_resolve_attachment s_resolve = { };
if (s_att && s_att->resolveMode != VK_RESOLVE_MODE_NONE) {
VK_FROM_HANDLE(panvk_image_view, resolve_iview, s_att->resolveImageView);
assert(s_ms2ss == (resolve_iview == NULL));
s_resolve = (struct panvk_resolve_attachment) {
.dst_iview = s_ms2ss ? s_iview_ss : resolve_iview,
.mode = s_att->resolveMode,
};
assert(s_resolve.dst_iview != NULL);
assert(s_resolve.dst_iview->pview.nr_samples == 1);
}
if (interleaved_zs) { if (interleaved_zs) {
/* Store both Z and S together */ /* Store both Z and S together */
struct panvk_image_view *iview = z_iview ? z_iview : s_iview; struct panvk_image_view *iview = z_iview ? z_iview : s_iview;
render->z_pview.store = get_zs_pan_image_view(iview); render->z_pview.store = get_zs_pan_image_view(iview);
render->fb.store.zs = pan_fb_store_iview(&render->z_pview.store); render->fb.store.zs = pan_fb_store_iview(&render->z_pview.store);
/* It's probably possible to make resolve shaders work with interleaved
* Z/S but it's tricky at best. For now, skip this optimization in the
* interleaved case.
*/
render->z_attachment.resolve = z_resolve;
render->s_attachment.resolve = s_resolve;
} else { } else {
if (z_iview) { if (z_iview) {
render->z_pview.store = get_z_pan_image_view(z_iview); render->z_pview.store = get_z_pan_image_view(z_iview);
render->fb.store.zs = pan_fb_store_iview(&render->z_pview.store); if (z_att->storeOp == VK_ATTACHMENT_STORE_OP_STORE && !z_ms2ss)
render->fb.store.zs = pan_fb_store_iview(&render->z_pview.store);
} }
if (s_iview) { if (s_iview) {
render->s_pview.store = get_s_pan_image_view(s_iview); render->s_pview.store = get_s_pan_image_view(s_iview);
render->fb.store.s = pan_fb_store_iview(&render->s_pview.store); if (s_att->storeOp == VK_ATTACHMENT_STORE_OP_STORE && !s_ms2ss)
render->fb.store.s = pan_fb_store_iview(&render->s_pview.store);
} }
}
if (z_att && z_att->resolveMode != VK_RESOLVE_MODE_NONE) { if (z_resolve.mode != VK_RESOLVE_MODE_NONE) {
VK_FROM_HANDLE(panvk_image_view, resolve_iview, z_att->resolveImageView); if (z_ms2ss || z_att->storeOp != VK_ATTACHMENT_STORE_OP_STORE) {
assert(z_ms2ss == (resolve_iview == NULL)); render->z_pview.resolve = get_z_pan_image_view(z_resolve.dst_iview);
render->fb.resolve.z = (struct pan_fb_resolve_target) {
.in_bounds = {
.resolve = PAN_FB_RESOLVE_Z,
.msaa = vk_to_pan_fb_resolve_mode(z_att->resolveMode),
},
.border = {
.resolve = PAN_FB_RESOLVE_IMAGE,
.msaa = PAN_FB_MSAA_COPY_SINGLE,
},
.iview = &render->z_pview.resolve,
};
render->fb.store.zs =
pan_fb_always_store_iview_s0(&render->z_pview.resolve);
} else {
/* We need to store so we can do the MSAA resolve later */
render->fb.store.zs = pan_fb_store_iview(&render->z_pview.store);
render->z_attachment.resolve = z_resolve;
}
}
const struct panvk_resolve_attachment resolve = { if (s_resolve.mode != VK_RESOLVE_MODE_NONE) {
.dst_iview = z_ms2ss ? z_iview_ss : resolve_iview, if (s_ms2ss || s_att->storeOp != VK_ATTACHMENT_STORE_OP_STORE) {
.mode = z_att->resolveMode, render->s_pview.resolve = get_s_pan_image_view(s_resolve.dst_iview);
}; render->fb.resolve.s = (struct pan_fb_resolve_target) {
assert(resolve.dst_iview != NULL); .in_bounds = {
assert(resolve.dst_iview->pview.nr_samples == 1); .resolve = PAN_FB_RESOLVE_S,
.msaa = vk_to_pan_fb_resolve_mode(s_att->resolveMode),
render->z_attachment.resolve = resolve; },
} .border = {
.resolve = PAN_FB_RESOLVE_IMAGE,
if (s_att && s_att->resolveMode != VK_RESOLVE_MODE_NONE) { .msaa = PAN_FB_MSAA_COPY_SINGLE,
VK_FROM_HANDLE(panvk_image_view, resolve_iview, s_att->resolveImageView); },
assert(s_ms2ss == (resolve_iview == NULL)); .iview = &render->s_pview.resolve,
};
const struct panvk_resolve_attachment resolve = { render->fb.store.s =
.dst_iview = s_ms2ss ? s_iview_ss : resolve_iview, pan_fb_always_store_iview_s0(&render->s_pview.resolve);
.mode = s_att->resolveMode, } else {
}; /* We need to store so we can do the MSAA resolve later */
assert(resolve.dst_iview != NULL); render->fb.store.s = pan_fb_store_iview(&render->s_pview.store);
assert(resolve.dst_iview->pview.nr_samples == 1); render->s_attachment.resolve = s_resolve;
}
render->s_attachment.resolve = resolve; }
} }
} }