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>
(cherry picked from commit 8891c2aeba)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33113>
This commit is contained in:
Boris Brezillon
2025-01-14 12:37:19 +01:00
committed by Dylan Baker
parent 7166b5adc9
commit 75a0bde863
3 changed files with 16 additions and 2 deletions

View File

@@ -854,7 +854,7 @@
"description": "panfrost: Fix instanced draws when attributes have a non-zero divisor",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "3db963a13592c5b215bb776e0365d4c0d70d5286",
"notes": null

View File

@@ -2810,12 +2810,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]);
}
@@ -3440,6 +3446,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) {

View File

@@ -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
};