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 3db963a135 ("panfrost: Emit attribs in
panfrost_update_state_3d() on bifrost/midgard") and fixes the regression
introduced by this commit.

Fixes: 3db963a135 ("panfrost: Emit attribs in panfrost_update_state_3d() on bifrost/midgard")
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Tested-By: Chris Healy <healych@amazon.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33010>
This commit is contained in:
Boris Brezillon
2025-01-14 12:37:19 +01:00
committed by Marge Bot
parent 1c59793d2d
commit 8891c2aeba
2 changed files with 15 additions and 1 deletions

View File

@@ -2886,12 +2886,18 @@ panfrost_update_state_3d(struct panfrost_batch *batch)
} }
#else #else
unsigned vt_shader_dirty = ctx->dirty_shader[PIPE_SHADER_VERTEX]; 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 /* 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 * an impact on the attributes array, we need to re-emit anytime one of these
* parameters changes. */ * parameters changes. */
if ((dirty & PAN_DIRTY_VERTEX) || 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->attribs[PIPE_SHADER_VERTEX] = panfrost_emit_vertex_data(
batch, &batch->attrib_bufs[PIPE_SHADER_VERTEX]); 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->element_buffer[i] = pan_assign_vertex_buffer(
so->buffers, &so->nr_bufs, elements[i].vertex_buffer_index, so->buffers, &so->nr_bufs, elements[i].vertex_buffer_index,
elements[i].instance_divisor); 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) { for (int i = 0; i < num_elements; ++i) {

View File

@@ -93,6 +93,12 @@ struct panfrost_vertex_state {
unsigned element_buffer[PIPE_MAX_ATTRIBS]; unsigned element_buffer[PIPE_MAX_ATTRIBS];
unsigned nr_bufs; 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]; unsigned formats[PIPE_MAX_ATTRIBS];
#endif #endif
}; };