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.writes_sample_mask &= !shader->key.ps.part.epilog.kill_samplemask;
shader->info.uses_discard |= shader->key.ps.part.prolog.poly_stipple || shader->info.uses_discard |= shader->key.ps.part.prolog.poly_stipple ||
shader->key.ps.part.epilog.alpha_func != PIPE_FUNC_ALWAYS; 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; break;
default:; default:;
} }

View file

@ -159,6 +159,6 @@ void si_get_late_shader_variant_info(struct si_shader *shader, struct si_shader_
nir_shader *nir); nir_shader *nir);
void si_set_spi_ps_input_config_for_separate_prolog(struct si_shader *shader); 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_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 #endif

View file

@ -11,21 +11,34 @@
/* The spi_shader_*_format fields depend on the framebuffer state and the /* The spi_shader_*_format fields depend on the framebuffer state and the
* NIR shader (monolithic or main part). * 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 spi_shader_col_format = shader->key.ps.part.epilog.spi_shader_col_format;
unsigned value = 0, num_mrts = 0; unsigned value = 0, num_mrts = 0;
unsigned i, num_targets = (util_last_bit(spi_shader_col_format) + 3) / 4; 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.spi_shader_z_format = ac_get_spi_shader_z_format(shader->info.writes_z, shader->info.writes_stencil,
shader->info.writes_sample_mask, shader->info.writes_sample_mask,
shader->key.ps.part.epilog.alpha_to_coverage_via_mrtz); 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. */ /* Remove holes in spi_shader_col_format. */
for (i = 0; i < num_targets; i++) { for (i = 0; i < num_targets; i++) {
unsigned spi_format = (spi_shader_col_format >> (i * 4)) & 0xf; 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); value |= spi_format << (num_mrts * 4);
num_mrts++; 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. */ /* ACO needs spi_ps_input_ena before si_init_shader_args. */
shader->config.spi_ps_input_ena = shader->config.spi_ps_input_ena =