tu: Use safe-const binning VS when safe-const full VS is used
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Otherwise we can have a case where binning VS uses more consts than
full VS (when safe variant is used for full VS), that will result in
a rendering issue because SP_VS_CONST_CONFIG.CONSTLEN is shared between
full and binning VS in PROGRAM_CONFIG state and gets the value from the
full VS.

There are two alternative solutions that can allow binning VS to always
use maximum constlen:
- Move constlen emission to per-XS config. This interferes
  PROGRAM_CONFIG state which uploads consts and does SP_UPDATE_CNTL.
  Consts would need to be uploaded after constlen is defined, while
  SP_UPDATE_CNTL must be done before per-XS state is emitted.
  Also having SP_UPDATE_CNTL in a draw state that is always DIRTY
  isn't great.
  Something didn't work out on A6XX, so this idea was dropped.
- Emit constlen again in VS_BINNING draw state. This seem to work
  but also likely an undefined behaviour since constlen is changed
  after some consts are uploaded.

Cc: mesa-stable

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36203>
This commit is contained in:
Danylo Piliaiev 2025-07-17 19:29:10 +02:00 committed by Marge Bot
parent a0a9c12124
commit 6003a89b89
2 changed files with 25 additions and 12 deletions

View file

@ -2302,7 +2302,9 @@ tu_emit_program_state(struct tu_cs *sub_cs,
prog->vs_binning_state = prog->vs_state;
} else {
prog->vs_binning_state =
shaders[MESA_SHADER_VERTEX]->binning_state;
(safe_variants & (1u << MESA_SHADER_VERTEX))
? shaders[MESA_SHADER_VERTEX]->safe_const_binning_state
: shaders[MESA_SHADER_VERTEX]->binning_state;
}
prog->hs_state = draw_states[MESA_SHADER_TESS_CTRL];

View file

@ -2343,9 +2343,13 @@ tu_upload_shader(struct tu_device *dev,
const struct ir3_shader_variant *v = shader->variant;
const struct ir3_shader_variant *binning = v ? v->binning : NULL;
const struct ir3_shader_variant *safe_const = shader->safe_const_variant;
const struct ir3_shader_variant *safe_const_binning =
safe_const && v->type == MESA_SHADER_VERTEX ? safe_const->binning : NULL;
if (v->type == MESA_SHADER_VERTEX && v->stream_output.num_outputs != 0)
if (v->type == MESA_SHADER_VERTEX && v->stream_output.num_outputs != 0) {
binning = v;
safe_const_binning = safe_const;
}
uint32_t size = 0;
if (v->type == MESA_SHADER_VERTEX)
@ -2354,16 +2358,11 @@ tu_upload_shader(struct tu_device *dev,
const unsigned xs_size = 128;
const unsigned vpc_size = 32 + (v->stream_output.num_outputs != 0 ? 256 : 0);
size += xs_size + tu_xs_get_additional_cs_size_dwords(v);
size += v->info.size / 4;
if (binning) {
size += xs_size + tu_xs_get_additional_cs_size_dwords(binning);
size += binning->info.size / 4;
}
if (safe_const) {
size += xs_size + tu_xs_get_additional_cs_size_dwords(safe_const);
size += safe_const->info.size / 4;
for (auto& variant : {v, binning, safe_const, safe_const_binning}) {
if (variant) {
size += xs_size + tu_xs_get_additional_cs_size_dwords(variant);
size += variant->info.size / 4;
}
}
/* We emit an empty VPC including streamout state in the binning draw state */
@ -2416,6 +2415,7 @@ tu_upload_shader(struct tu_device *dev,
uint64_t iova = tu_upload_variant(&shader->cs, v);
uint64_t binning_iova = tu_upload_variant(&shader->cs, binning);
uint64_t safe_const_iova = tu_upload_variant(&shader->cs, safe_const);
uint64_t safe_const_binning_iova = tu_upload_variant(&shader->cs, safe_const_binning);
struct tu_cs sub_cs;
tu_cs_begin_sub_stream(&shader->cs, xs_size +
@ -2445,6 +2445,17 @@ tu_upload_shader(struct tu_device *dev,
shader->binning_state = tu_cs_end_draw_state(&shader->cs, &sub_cs);
}
if (safe_const_binning) {
tu_cs_begin_sub_stream(&shader->cs, xs_size + vpc_size +
tu_xs_get_additional_cs_size_dwords(safe_const_binning), &sub_cs);
TU_CALLX(dev, tu6_emit_variant)(
&sub_cs, v->type, safe_const_binning, &pvtmem_config, shader->view_mask,
safe_const_binning_iova);
/* emit an empty VPC */
TU_CALLX(dev, tu6_emit_vpc)(&sub_cs, safe_const_binning, NULL, NULL, NULL, NULL);
shader->safe_const_binning_state = tu_cs_end_draw_state(&shader->cs, &sub_cs);
}
/* We don't support binning variants for GS, so the same draw state is used
* when binning and when drawing, but the VPC draw state is not executed
* when binning so we still need to generate an appropriate VPC config for