From cc7be8433a84557740cbc8e095a93afef860a0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Sat, 25 Apr 2026 20:22:48 +0200 Subject: [PATCH] r300: dirty VS state when switching variants When r300_pick_vertex_shader switches to a WPOS variant, it only dirtied rs_block_state, leaving vs_state with a stale code size. This caused cs_count warnings (offset of -4 for one extra VS instruction) but was mostly harmless since the emitted packet stream still used the current shader. Factor the VS code dirtying out of r300_bind_vs_state into a helper and call it when selecting a new variant too. Fixes: 806dcf9db7c ("r300: only output wpos in vertex shaders when needed") Part-of: --- src/gallium/drivers/r300/r300_context.h | 1 + src/gallium/drivers/r300/r300_state.c | 37 +++++++++++-------- src/gallium/drivers/r300/r300_state_derived.c | 8 +++- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 472ed59871f..f684500d33c 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -804,6 +804,7 @@ enum r300_fb_state_change { void r300_mark_fb_state_dirty(struct r300_context *r300, enum r300_fb_state_change change); +void r300_mark_vs_code_dirty(struct r300_context *r300); void r300_mark_fs_code_dirty(struct r300_context *r300); struct pipe_sampler_view * diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 769ca0365bf..5c82443ca68 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -2212,6 +2212,27 @@ static void* r300_create_vs_state(struct pipe_context* pipe, return vs; } +void r300_mark_vs_code_dirty(struct r300_context *r300) +{ + struct r300_vertex_shader *vs = r300_vs(r300); + unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2; + + r300_mark_atom_dirty(r300, &r300->vs_state); + r300->vs_state.size = vs->shader->code.length + 9 + + (R300_VS_MAX_FC_OPS * fc_op_dwords + 4); + + r300_mark_atom_dirty(r300, &r300->vs_constants); + r300->vs_constants.size = + 2 + + (vs->shader->externals_count ? vs->shader->externals_count * 4 + 3 : 0) + + (vs->shader->immediates_count ? vs->shader->immediates_count * 4 + 3 : 0); + + ((struct r300_constant_buffer*)r300->vs_constants.state)->remap_table = + vs->shader->code.constants_remap_table; + + r300_mark_atom_dirty(r300, &r300->pvs_flush); +} + static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); @@ -2230,21 +2251,7 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */ if (r300->screen->caps.has_tcl) { - unsigned fc_op_dwords = r300->screen->caps.is_r500 ? 3 : 2; - r300_mark_atom_dirty(r300, &r300->vs_state); - r300->vs_state.size = vs->shader->code.length + 9 + - (R300_VS_MAX_FC_OPS * fc_op_dwords + 4); - - r300_mark_atom_dirty(r300, &r300->vs_constants); - r300->vs_constants.size = - 2 + - (vs->shader->externals_count ? vs->shader->externals_count * 4 + 3 : 0) + - (vs->shader->immediates_count ? vs->shader->immediates_count * 4 + 3 : 0); - - ((struct r300_constant_buffer*)r300->vs_constants.state)->remap_table = - vs->shader->code.constants_remap_table; - - r300_mark_atom_dirty(r300, &r300->pvs_flush); + r300_mark_vs_code_dirty(r300); } else { draw_bind_vertex_shader(r300->draw, (struct draw_vertex_shader*)vs->draw_vs); diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 9df4f7e53e3..ba89b8ddc25 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -1056,8 +1056,10 @@ static void r300_pick_vertex_shader(struct r300_context *r300) vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code); vs->first->wpos = wpos; r300_translate_vertex_shader(r300, vs); - if (!vs->first->dummy) + if (!vs->first->dummy) { + r300_mark_vs_code_dirty(r300); r300_mark_atom_dirty(r300, &r300->rs_block_state); + } return; } /* Pick the vertex shader based on whether we need wpos */ @@ -1074,8 +1076,10 @@ static void r300_pick_vertex_shader(struct r300_context *r300) vs->shader->wpos = wpos; r300_translate_vertex_shader(r300, vs); } - if (!vs->first->dummy) + if (!vs->first->dummy) { + r300_mark_vs_code_dirty(r300); r300_mark_atom_dirty(r300, &r300->rs_block_state); + } } } }