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: 806dcf9db7 ("r300: only output wpos in vertex shaders when needed")
(cherry picked from commit cc7be8433a)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41269>
This commit is contained in:
Pavel Ondračka 2026-04-25 20:22:48 +02:00 committed by Eric Engestrom
parent 4083a34188
commit b07b674765
4 changed files with 30 additions and 18 deletions

View file

@ -1184,7 +1184,7 @@
"description": "r300: dirty VS state when switching variants",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "806dcf9db7c03996794b52e833be86c77ce3d36f",
"notes": null

View file

@ -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 *

View file

@ -2169,6 +2169,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);
@ -2187,21 +2208,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);

View file

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