radeonsi: account for outputs_written when updating spi_shader_col_format

Variants can modify which outputs get written so we must update
these fields otherwise spi_shader_col_format will be incorrect.

This can happen for instance with uniforms inlining:

   uniform bool depth_only;
   void main() {
      if (depth_only) return;
      ...
   }

When depth_only is true, this shader becomes empty after uniforms
inlining but spi_shader_col_format wasn't updated properly,
causing a hang.

Cc: mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/14737
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40372>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2026-03-11 16:10:34 +01:00 committed by Marge Bot
parent da7c515783
commit 88986dcc9c
3 changed files with 18 additions and 5 deletions

View file

@ -2020,7 +2020,7 @@ bool si_create_shader_variant(struct si_screen *sscreen, struct ac_llvm_compiler
shader->info.writes_sample_mask &= !shader->key.ps.part.epilog.kill_samplemask;
shader->info.uses_discard |= shader->key.ps.part.prolog.poly_stipple ||
shader->key.ps.part.epilog.alpha_func != PIPE_FUNC_ALWAYS;
si_shader_update_spi_shader_formats(shader);
si_shader_update_spi_shader_formats(shader, NULL);
break;
default:;
}

View file

@ -159,6 +159,6 @@ void si_get_late_shader_variant_info(struct si_shader *shader, struct si_shader_
nir_shader *nir);
void si_set_spi_ps_input_config_for_separate_prolog(struct si_shader *shader);
void si_fixup_spi_ps_input_config(struct si_shader *shader);
void si_shader_update_spi_shader_formats(struct si_shader *shader);
void si_shader_update_spi_shader_formats(struct si_shader *shader, nir_shader *nir);
#endif

View file

@ -11,21 +11,34 @@
/* The spi_shader_*_format fields depend on the framebuffer state and the
* NIR shader (monolithic or main part).
*/
void si_shader_update_spi_shader_formats(struct si_shader *shader)
void si_shader_update_spi_shader_formats(struct si_shader *shader, nir_shader *nir)
{
unsigned spi_shader_col_format = shader->key.ps.part.epilog.spi_shader_col_format;
unsigned value = 0, num_mrts = 0;
unsigned i, num_targets = (util_last_bit(spi_shader_col_format) + 3) / 4;
uint64_t colors_written = UINT64_MAX;
shader->info.spi_shader_z_format = ac_get_spi_shader_z_format(shader->info.writes_z, shader->info.writes_stencil,
shader->info.writes_sample_mask,
shader->key.ps.part.epilog.alpha_to_coverage_via_mrtz);
if (nir) {
colors_written = (nir->info.outputs_written >> FRAG_RESULT_DATA0) & BITFIELD_MASK(8);
if (nir->info.outputs_written & BITFIELD_BIT(FRAG_RESULT_DUAL_SRC_BLEND))
colors_written |= 0x2;
if (nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
if (colors_written == 0)
colors_written = UINT64_MAX; /* color0_writes_all_cbufs */
else
colors_written |= 0x1;
}
}
/* Remove holes in spi_shader_col_format. */
for (i = 0; i < num_targets; i++) {
unsigned spi_format = (spi_shader_col_format >> (i * 4)) & 0xf;
if (spi_format) {
if (spi_format && (colors_written & 1u << num_mrts)) {
value |= spi_format << (num_mrts * 4);
num_mrts++;
}
@ -346,7 +359,7 @@ void si_get_shader_variant_info(struct si_shader *shader,
}
}
si_shader_update_spi_shader_formats(shader);
si_shader_update_spi_shader_formats(shader, nir);
/* ACO needs spi_ps_input_ena before si_init_shader_args. */
shader->config.spi_ps_input_ena =