From ca3d54560bd3f9ea5b0df5fc0946b8f7bb0d5b47 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Fri, 7 Nov 2025 12:29:52 -0500 Subject: [PATCH] panvk/csf: Break VS descriptor setup into a new helper This and the previous commit are the beginning of an overall restructure of the state flushing flow. The idea is that the very first thing flushed are descriptors, including vertex and fragment attributes. Importantly, flushing descriptors does not depend on which vertex shader variant we end up picking in the end. Both the HW and SW VS will use the same descriptors. Signed-off-by: Olivia Lee Reviewed-by: Eric R. Smith Reviewed-by: Christian Gmeiner Part-of: --- src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c | 120 ++++++++++---------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index 0785101bd91..2e6c7943fad 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -286,35 +286,9 @@ emit_vs_attrib(struct panvk_cmd_buffer *cmdbuf, } } -/* Only valid to call after prepare_vi() */ -static bool -vs_driver_set_is_dirty(struct panvk_cmd_buffer *cmdbuf) -{ - /* If any of the attributes change on base instance and the base instance - * has changed, we need to re-emit regardless of what API state is dirty. - * prepare_draw() ensures that BASE_INSTANCE is always dirty for indirect - * draws. - */ - if (cmdbuf->state.gfx.vi.attribs_changing_on_base_instance && - gfx_state_dirty(cmdbuf, BASE_INSTANCE)) - return true; - - return dyn_gfx_state_dirty(cmdbuf, VI) || - dyn_gfx_state_dirty(cmdbuf, VI_BINDINGS_VALID) || - dyn_gfx_state_dirty(cmdbuf, VI_BINDING_STRIDES) || - gfx_state_dirty(cmdbuf, VB) || gfx_state_dirty(cmdbuf, VS) || - gfx_state_dirty(cmdbuf, DESC_STATE); -} - static VkResult -prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, - const struct panvk_draw_info *draw) +prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, uint32_t repeat_count) { - prepare_vi(cmdbuf); - - if (!vs_driver_set_is_dirty(cmdbuf)) - return VK_SUCCESS; - const struct panvk_shader_desc_info *vs_desc_info = &cmdbuf->state.gfx.vs.shader->desc_info; struct panvk_shader_desc_state *vs_desc_state = &cmdbuf->state.gfx.vs.desc; @@ -329,18 +303,6 @@ prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, uint32_t vb_offset = vs_desc_info->dyn_bufs.count + MAX_VS_ATTRIBS + 1; uint32_t desc_count = vb_offset + vb_count; - cmdbuf->state.gfx.vs.desc_repeat_count = 0; - if (draw->indirect.buffer_dev_addr) { - /* BASE_INSTANCE is always dirty for indirect draws so it's safe to look - * at the draw info here. - */ - assert(gfx_state_dirty(cmdbuf, BASE_INSTANCE)); - if (cmdbuf->state.gfx.vi.attribs_changing_on_base_instance) - cmdbuf->state.gfx.vs.desc_repeat_count = draw->indirect.draw_count; - } - - uint32_t repeat_count = MAX2(cmdbuf->state.gfx.vs.desc_repeat_count, 1); - const struct panvk_descriptor_state *desc_state = &cmdbuf->state.gfx.desc_state; struct pan_ptr driver_set = panvk_cmd_alloc_dev_mem( @@ -397,6 +359,66 @@ prepare_vs_driver_set(struct panvk_cmd_buffer *cmdbuf, return VK_SUCCESS; } +/* Only valid to call after prepare_vi() */ +static bool +vs_desc_dirty(struct panvk_cmd_buffer *cmdbuf) +{ + /* If any of the attributes change on base instance and the base instance + * has changed, we need to re-emit regardless of what API state is dirty. + * prepare_draw() ensures that BASE_INSTANCE is always dirty for indirect + * draws. + */ + if (cmdbuf->state.gfx.vi.attribs_changing_on_base_instance && + gfx_state_dirty(cmdbuf, BASE_INSTANCE)) + return true; + + return dyn_gfx_state_dirty(cmdbuf, VI) || + dyn_gfx_state_dirty(cmdbuf, VI_BINDINGS_VALID) || + dyn_gfx_state_dirty(cmdbuf, VI_BINDING_STRIDES) || + gfx_state_dirty(cmdbuf, VB) || gfx_state_dirty(cmdbuf, VS) || + gfx_state_dirty(cmdbuf, DESC_STATE); +} + +static VkResult +prepare_vs_desc(struct panvk_cmd_buffer *cmdbuf, + const struct panvk_draw_info *draw) +{ + prepare_vi(cmdbuf); + + if (!vs_desc_dirty(cmdbuf)) + return VK_SUCCESS; + + cmdbuf->state.gfx.vs.desc_repeat_count = 0; + if (draw->indirect.buffer_dev_addr) { + /* BASE_INSTANCE is always dirty for indirect draws so it's safe to look + * at the draw info here. + */ + assert(gfx_state_dirty(cmdbuf, BASE_INSTANCE)); + if (cmdbuf->state.gfx.vi.attribs_changing_on_base_instance) + cmdbuf->state.gfx.vs.desc_repeat_count = draw->indirect.draw_count; + } + + const uint32_t repeat_count = + MAX2(cmdbuf->state.gfx.vs.desc_repeat_count, 1); + + VkResult result = prepare_vs_driver_set(cmdbuf, repeat_count); + if (result != VK_SUCCESS) + return result; + + const struct panvk_shader_desc_info *vs_desc_info = + &cmdbuf->state.gfx.vs.shader->desc_info; + const struct panvk_descriptor_state *desc_state = + &cmdbuf->state.gfx.desc_state; + struct panvk_shader_desc_state *vs_desc_state = &cmdbuf->state.gfx.vs.desc; + + result = panvk_per_arch(cmd_prepare_shader_res_table)( + cmdbuf, desc_state, vs_desc_info, vs_desc_state, repeat_count); + if (result != VK_SUCCESS) + return result; + + return VK_SUCCESS; +} + static void emit_varying_descs(const struct panvk_cmd_buffer *cmdbuf, struct mali_attribute_packed *descs) @@ -1768,32 +1790,16 @@ static VkResult prepare_vs(struct panvk_cmd_buffer *cmdbuf, const struct panvk_draw_info *draw, const struct panvk_shader_variant *vs) { - struct panvk_descriptor_state *desc_state = &cmdbuf->state.gfx.desc_state; struct panvk_shader_desc_state *vs_desc_state = &cmdbuf->state.gfx.vs.desc; struct cs_builder *b = panvk_get_cs_builder(cmdbuf, PANVK_SUBQUEUE_VERTEX_TILER); - bool upd_res_table = false; - VkResult result = prepare_vs_driver_set(cmdbuf, draw); + VkResult result = prepare_vs_desc(cmdbuf, draw); if (result != VK_SUCCESS) return result; - if (gfx_state_dirty(cmdbuf, VS) || gfx_state_dirty(cmdbuf, DESC_STATE) || - vs_driver_set_is_dirty(cmdbuf)) { - const struct panvk_shader_desc_info *vs_desc_info = - &cmdbuf->state.gfx.vs.shader->desc_info; - - uint32_t repeat_count = MAX2(cmdbuf->state.gfx.vs.desc_repeat_count, 1); - result = panvk_per_arch(cmd_prepare_shader_res_table)( - cmdbuf, desc_state, vs_desc_info, vs_desc_state, repeat_count); - if (result != VK_SUCCESS) - return result; - - upd_res_table = true; - } - cs_update_vt_ctx(b) { - if (upd_res_table) + if (vs_desc_dirty(cmdbuf)) cs_move64_to(b, cs_sr_reg64(b, IDVS, VERTEX_SRT), vs_desc_state->res_table);