From 8891c2aeba96bdf2f926e3a3ccd41ec78a894872 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 14 Jan 2025 12:37:19 +0100 Subject: [PATCH] panfrost: Fix instanced draws when attributes have a non-zero divisor On Bifrost/Midgard, when an attribute has a non-zero divisors, the attribute offset is tweaked to take the base_instance into account, which implies we have to re-emit the attributes if the base instance value changed. Let's not bother tracking the last base instance and re-emit unconditionally in that case, which is still better than what we had before 3db963a13592 ("panfrost: Emit attribs in panfrost_update_state_3d() on bifrost/midgard") and fixes the regression introduced by this commit. Fixes: 3db963a13592 ("panfrost: Emit attribs in panfrost_update_state_3d() on bifrost/midgard") Signed-off-by: Boris Brezillon Reviewed-by: Erik Faye-Lund Tested-By: Chris Healy Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 10 +++++++++- src/gallium/drivers/panfrost/pan_cmdstream.h | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 43d713b9c1f..cdd78e29778 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -2886,12 +2886,18 @@ panfrost_update_state_3d(struct panfrost_batch *batch) } #else unsigned vt_shader_dirty = ctx->dirty_shader[PIPE_SHADER_VERTEX]; + struct panfrost_compiled_shader *vs = ctx->prog[PIPE_SHADER_VERTEX]; + struct panfrost_vertex_state *vstate = ctx->vertex; + bool attr_offsetted_by_instance_base = + vstate->attr_depends_on_base_instance_mask & + BITFIELD_MASK(vs->info.attributes_read_count); /* Vertex data, vertex shader and images accessed by the vertex shader have * an impact on the attributes array, we need to re-emit anytime one of these * parameters changes. */ if ((dirty & PAN_DIRTY_VERTEX) || - (vt_shader_dirty & (PAN_DIRTY_STAGE_IMAGE | PAN_DIRTY_STAGE_SHADER))) { + (vt_shader_dirty & (PAN_DIRTY_STAGE_IMAGE | PAN_DIRTY_STAGE_SHADER)) || + attr_offsetted_by_instance_base) { batch->attribs[PIPE_SHADER_VERTEX] = panfrost_emit_vertex_data( batch, &batch->attrib_bufs[PIPE_SHADER_VERTEX]); } @@ -3533,6 +3539,8 @@ panfrost_create_vertex_elements_state(struct pipe_context *pctx, so->element_buffer[i] = pan_assign_vertex_buffer( so->buffers, &so->nr_bufs, elements[i].vertex_buffer_index, elements[i].instance_divisor); + if (elements[i].instance_divisor) + so->attr_depends_on_base_instance_mask |= BITFIELD_BIT(i); } for (int i = 0; i < num_elements; ++i) { diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.h b/src/gallium/drivers/panfrost/pan_cmdstream.h index cd8f674db94..9ff07981fa9 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.h +++ b/src/gallium/drivers/panfrost/pan_cmdstream.h @@ -93,6 +93,12 @@ struct panfrost_vertex_state { unsigned element_buffer[PIPE_MAX_ATTRIBS]; unsigned nr_bufs; + /* Bitmask flagging attributes with a non-zero instance divisor which + * require an attribute offset adjustment when base_instance != 0. + * This is used to force attributes re-emission even if the vertex state + * isn't dirty to take the new base instance into account. */ + uint32_t attr_depends_on_base_instance_mask; + unsigned formats[PIPE_MAX_ATTRIBS]; #endif };