From aacbfc9da2b518b94a67fb4e258a525459c119d6 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 9 Feb 2026 14:57:08 -0500 Subject: [PATCH] panvk: Always set pan_fb_layout.rt_count to at least 1 Instead of having the pan_fb code have to `max(rt_count, 1)` add then constantly be doing the same in the driver, just make the condition an assert and do the `max(colorAttachmentCount, 1)` up-front. This way we're not constantly worried if everyone has the same count or not. The pan_fb code will handle having an empty render target just fine. Reviewed-by: Lars-Ivar Hesselberg Simonsen Acked-by: Boris Brezillon Acked-by: Eric R. Smith Part-of: --- src/panfrost/lib/pan_fb.c | 9 ++++----- src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c | 17 +++++++---------- src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c | 2 +- src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c | 2 +- src/panfrost/vulkan/panvk_vX_blend.c | 5 ++--- src/panfrost/vulkan/panvk_vX_cmd_draw.c | 6 +++++- src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c | 6 ++---- 7 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/panfrost/lib/pan_fb.c b/src/panfrost/lib/pan_fb.c index 91316b56731..f457f0d284c 100644 --- a/src/panfrost/lib/pan_fb.c +++ b/src/panfrost/lib/pan_fb.c @@ -429,8 +429,6 @@ GENX(pan_emit_fb_desc)(const struct pan_fb_desc_info *info, void *out) const struct pan_fb_store *store = info->store; const bool has_zs_crc_ext = pan_fb_has_zs(fb); - assert(fb->rt_count > 0 || fb->rt_formats[0] == PIPE_FORMAT_NONE); - const unsigned rt_count = MAX2(fb->rt_count, 1); struct mali_framebuffer_packed fbd = {}; @@ -502,7 +500,8 @@ GENX(pan_emit_fb_desc)(const struct pan_fb_desc_info *info, void *out) cfg.first_provoking_vertex = info->provoking_vertex_first; #endif - cfg.render_target_count = rt_count; + assert(fb->rt_count > 0); + cfg.render_target_count = fb->rt_count; cfg.color_buffer_allocation = fb->tile_rt_alloc_B; if (fb->s_format != PIPE_FORMAT_NONE) { @@ -553,7 +552,7 @@ GENX(pan_emit_fb_desc)(const struct pan_fb_desc_info *info, void *out) } uint32_t tile_rt_offset_B = 0; - for (unsigned rt = 0; rt < rt_count; rt++) { + for (unsigned rt = 0; rt < fb->rt_count; rt++) { struct mali_rgb_render_target_packed rgb_rt; emit_rgb_rt_desc(info, rt, tile_rt_offset_B, &rgb_rt); memcpy(out, &rgb_rt, sizeof(rgb_rt)); @@ -569,7 +568,7 @@ GENX(pan_emit_fb_desc)(const struct pan_fb_desc_info *info, void *out) struct mali_framebuffer_pointer_packed tag; pan_pack(&tag, FRAMEBUFFER_POINTER, cfg) { cfg.zs_crc_extension_present = has_zs_crc_ext; - cfg.render_target_count = rt_count; + cfg.render_target_count = fb->rt_count; } return tag.opaque[0]; } diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index 160bd1ffb52..13e480c3ca2 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -133,9 +133,8 @@ calc_fn_set_fbds_provoking_vertex_idx(struct panvk_cmd_buffer *cmdbuf) { const struct pan_fb_layout *fb = &cmdbuf->state.gfx.render.fb.layout; const bool has_zs_ext = pan_fb_has_zs(fb); - uint32_t rt_count = MAX2(fb->rt_count, 1); - return get_fn_set_fbds_provoking_vertex_idx(has_zs_ext, rt_count); + return get_fn_set_fbds_provoking_vertex_idx(has_zs_ext, fb->rt_count); } VkResult @@ -663,7 +662,7 @@ prepare_blend(struct panvk_cmd_buffer *cmdbuf) const struct panvk_shader_variant *fs = panvk_shader_only_variant(get_fs(cmdbuf)); - uint32_t bd_count = MAX2(cmdbuf->state.gfx.render.fb.layout.rt_count, 1); + uint32_t bd_count = cmdbuf->state.gfx.render.fb.layout.rt_count; struct cs_builder *b = panvk_get_cs_builder(cmdbuf, PANVK_SUBQUEUE_VERTEX_TILER); struct pan_ptr ptr = panvk_cmd_alloc_desc_array(cmdbuf, bd_count, BLEND); @@ -927,9 +926,8 @@ calc_fbd_size(struct panvk_cmd_buffer *cmdbuf) { const struct pan_fb_layout *fb = &cmdbuf->state.gfx.render.fb.layout; const bool has_zs_ext = pan_fb_has_zs(fb); - uint32_t rt_count = MAX2(fb->rt_count, 1); - return get_fbd_size(has_zs_ext, rt_count); + return get_fbd_size(has_zs_ext, fb->rt_count); } static uint32_t @@ -1329,7 +1327,7 @@ get_fb_descs(struct panvk_cmd_buffer *cmdbuf) } const bool has_zs_ext = pan_fb_has_zs(&render->fb.layout); - const uint32_t rt_count = MAX2(render->fb.layout.rt_count, 1); + const uint32_t rt_count = render->fb.layout.rt_count; struct cs_builder *b = panvk_get_cs_builder(cmdbuf, PANVK_SUBQUEUE_FRAGMENT); for (uint32_t ir_pass = 0; ir_pass < PANVK_IR_PASS_COUNT; ir_pass++) { @@ -2990,7 +2988,7 @@ panvk_per_arch(cmd_inherit_render_state)( render->fb.layout.sample_count == sample_count); render->fb.layout = (struct pan_fb_layout) { .sample_count = sample_count, - .rt_count = inheritance_info->colorAttachmentCount, + .rt_count = MAX2(inheritance_info->colorAttachmentCount, 1), .tile_size_px = render->fb.layout.tile_size_px, .tile_rt_alloc_B = render->fb.layout.tile_rt_alloc_B, @@ -3324,9 +3322,8 @@ calc_tiler_oom_handler_idx(struct panvk_cmd_buffer *cmdbuf) { const struct pan_fb_layout *fb = &cmdbuf->state.gfx.render.fb.layout; const bool has_zs_ext = pan_fb_has_zs(fb); - uint32_t rt_count = MAX2(fb->rt_count, 1); - return get_tiler_oom_handler_idx(has_zs_ext, rt_count); + return get_tiler_oom_handler_idx(has_zs_ext, fb->rt_count); } static void @@ -3475,7 +3472,7 @@ issue_fragment_jobs(struct panvk_cmd_buffer *cmdbuf) } const bool has_zs_ext = pan_fb_has_zs(fb); - const uint32_t rt_count = MAX2(fb->rt_count, 1); + const uint32_t rt_count = fb->rt_count; /* IR was hit: set up IR FBD */ cs_if(b, MALI_CS_CONDITION_GREATER, counter) { diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c index 2d4d900ba0a..8459c25be54 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c @@ -214,7 +214,7 @@ panvk_per_arch(cmd_alloc_fb_desc)(struct panvk_cmd_buffer *cmdbuf) pan_size(ZS_CRC_EXTENSION); fbd_size = ALIGN_POT(fbd_size, pan_alignment(RENDER_TARGET)) + - (MAX2(fb->rt_count, 1) * pan_size(RENDER_TARGET)); + (fb->rt_count * pan_size(RENDER_TARGET)); batch->fb.bo_count = cmdbuf->state.gfx.render.fb.bo_count; memcpy(batch->fb.bos, cmdbuf->state.gfx.render.fb.bos, diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c index 3c813ca5cdc..0155095be41 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c @@ -241,7 +241,7 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, const struct panvk_shader_variant *fs = panvk_shader_only_variant(get_fs(cmdbuf)); const struct pan_shader_info *fs_info = fs ? &fs->info : NULL; - uint32_t bd_count = MAX2(cmdbuf->state.gfx.render.fb.layout.rt_count, 1); + uint32_t bd_count = cmdbuf->state.gfx.render.fb.layout.rt_count; bool test_s = has_stencil_att(cmdbuf) && ds->stencil.test_enable; bool test_z = has_depth_att(cmdbuf) && ds->depth.test_enable; bool writes_z = writes_depth(cmdbuf); diff --git a/src/panfrost/vulkan/panvk_vX_blend.c b/src/panfrost/vulkan/panvk_vX_blend.c index 8c9f083ff92..abfc5ee2d1e 100644 --- a/src/panfrost/vulkan/panvk_vX_blend.c +++ b/src/panfrost/vulkan/panvk_vX_blend.c @@ -296,7 +296,6 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf, uint64_t blend_shaders[8] = {}; /* All bits set to one encodes unused fixed-function blend constant. */ unsigned ff_blend_constant = ~0; - uint32_t blend_count = MAX2(cmdbuf->state.gfx.render.fb.layout.rt_count, 1); uint8_t loc_rt[MAX_RTS], rt_loc[MAX_RTS]; memset(loc_rt, MESA_VK_ATTACHMENT_UNUSED, sizeof(loc_rt)); @@ -380,13 +379,13 @@ panvk_per_arch(blend_emit_descs)(struct panvk_cmd_buffer *cmdbuf, ff_blend_constant = 0; struct mali_blend_packed packed[MAX_RTS]; - for (uint8_t rt = 0; rt < blend_count; rt++) { + for (uint8_t rt = 0; rt < bs.rt_count; rt++) { emit_blend_desc(&bs, rt, fs_info, rt_loc[rt], fs_code, blend_shaders[rt], ff_blend_constant, &packed[rt]); } /* Copy into the GPU descriptor array */ - typed_memcpy(bds, packed, blend_count); + typed_memcpy(bds, packed, bs.rt_count); /* Re-order blend descriptors for the shader * diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index f2c793d3d89..a37da9f31c4 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -471,7 +471,11 @@ panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf, * value if we don't set it here already. */ .sample_count = 0, - .rt_count = pRenderingInfo->colorAttachmentCount, + + /* The hardware requires us to have at least one color target, even if + * it's a dummy. + */ + .rt_count = MAX2(pRenderingInfo->colorAttachmentCount, 1), .tile_rt_budget_B = pan_query_optimal_tib_size(PAN_ARCH, phys_dev->model), diff --git a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c index eb2e72cf2c8..b2a11a86adc 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c @@ -349,9 +349,7 @@ fill_bds(const struct pan_fb_layout *fb, const struct panvk_fb_preload_shader_key *key, struct mali_blend_packed *bds) { - uint32_t bd_count = MAX2(fb->rt_count, 1); - - for (unsigned i = 0; i < bd_count; i++) { + for (unsigned i = 0; i < fb->rt_count; i++) { pan_pack(&bds[i], BLEND, cfg) { if (!pan_fb_shader_key_target_written(&key->key.rts[i]) || fb->rt_formats[i] == PIPE_FORMAT_NONE) { @@ -421,7 +419,7 @@ cmd_emit_dcd(struct panvk_cmd_buffer *cmdbuf, assert(preload_color != (preload_z || preload_s)); uint32_t tex_count = util_bitcount(locations_written); - uint32_t bd_count = MAX2(fb->rt_count, 1); + uint32_t bd_count = fb->rt_count; struct pan_ptr rsd = panvk_cmd_alloc_desc_aggregate( cmdbuf, PAN_DESC(RENDERER_STATE),