panvk: Fix ls_tracker usage in cs_maybe

Currently a cs_maybe block affects the ls_tracker of a command stream
even if the cs_maybe block is later replaced by NOP instructions. This
can lead to missing WAIT instructions in the command stream.

* Add a WAIT at the end of the cs_maybe block if the block has changed
 the ls_tracker state
* At the end of a cs_maybe block, restore the ls_tracker state to what
 it was before the block

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13259
Fixes: 885805560f ("panvk/csf: fix case where vk_meta is used before PROVOKING_VERTEX_MODE_LAST")
Tested-By: Alexandre ARNOUD <aarnoud@me.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Olivia Lee <olivia.lee@collabora.com>
Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35460>
This commit is contained in:
Ludvig Lindau 2025-06-11 08:44:17 +00:00 committed by Marge Bot
parent 8dd496955d
commit 3778b22268

View file

@ -1356,6 +1356,8 @@ cs_while_end(struct cs_builder *b, struct cs_loop *loop)
struct cs_maybe_state {
struct cs_block block;
uint32_t patch_pos;
struct cs_load_store_tracker ls_state;
struct cs_load_store_tracker *orig_ls_state;
};
static inline struct cs_maybe_state *
@ -1363,6 +1365,13 @@ cs_maybe_start(struct cs_builder *b, struct cs_maybe_state *state)
{
cs_block_start(b, &state->block);
state->patch_pos = cs_block_next_pos(b);
/* store the original ls_tracker state so that we can revert to it after
* the maybe-block */
state->orig_ls_state = b->cur_ls_tracker;
state->ls_state = *b->cur_ls_tracker;
b->cur_ls_tracker = &state->ls_state;
return state;
}
@ -1372,6 +1381,18 @@ cs_maybe_end(struct cs_builder *b, struct cs_maybe_state *state,
{
assert(cs_cur_block(b) == &state->block);
/* Flush any new loads and stores */
BITSET_DECLARE(new_loads, 256);
BITSET_ANDNOT(new_loads, b->cur_ls_tracker->pending_loads,
state->orig_ls_state->pending_loads);
bool new_stores =
b->cur_ls_tracker->pending_stores && !state->orig_ls_state->pending_stores;
if (!BITSET_IS_EMPTY(new_loads) || new_stores)
cs_wait_slots(b, BITFIELD_BIT(b->conf.ls_sb_slot));
/* Restore the original ls tracker state */
b->cur_ls_tracker = state->orig_ls_state;
uint32_t num_instrs = cs_block_next_pos(b) - state->patch_pos;
size_t size = num_instrs * sizeof(uint64_t);
uint64_t *instrs = (uint64_t *) b->blocks.instrs.data + state->patch_pos;