radv: emit a dummy PS state for noop FS on GFX12

It seems the hardware requires a dummy PS state with a noop FS,
otherwise it might just hang. This used to work just fine on older
gens.

Note that RadeonSI refuses to draw if VS or PS is missing and AMDVLK
seems to also always emit this state. So, this might be a bug that AMD
didn't encounter at all.

This fixes a GPU hang during loading with Ghostwire: Tokyo.

Backport-to: 25.0
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34070>
This commit is contained in:
Samuel Pitoiset
2025-03-13 19:27:44 +01:00
committed by Marge Bot
parent 4608eef0a0
commit 1e4cfd9dfa
+45 -25
View File
@@ -2593,11 +2593,45 @@ radv_emit_ps_inputs(struct radv_cmd_buffer *cmd_buffer)
}
}
static void
radv_emit_fragment_shader_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *ps)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
const struct radv_physical_device *pdev = radv_device_physical(device);
const uint32_t spi_ps_input_ena = ps ? ps->config.spi_ps_input_ena : 0;
const uint32_t spi_ps_input_addr = ps ? ps->config.spi_ps_input_addr : 0;
const uint32_t spi_ps_in_control = ps ? ps->info.regs.ps.spi_ps_in_control : 0;
if (pdev->info.gfx_level >= GFX12) {
const uint32_t pa_sc_hisz_control = ps ? ps->info.regs.ps.pa_sc_hisz_control : 0;
radeon_opt_set_context_reg2(cmd_buffer, R_02865C_SPI_PS_INPUT_ENA, RADV_TRACKED_SPI_PS_INPUT_ENA,
spi_ps_input_ena, spi_ps_input_addr);
radeon_opt_set_context_reg(cmd_buffer, R_028640_SPI_PS_IN_CONTROL, RADV_TRACKED_SPI_PS_IN_CONTROL,
spi_ps_in_control);
radeon_set_context_reg(cmd_buffer->cs, R_028BBC_PA_SC_HISZ_CONTROL, pa_sc_hisz_control);
} else {
const uint32_t pa_sc_shader_control = ps ? ps->info.regs.ps.pa_sc_shader_control : 0;
radeon_opt_set_context_reg2(cmd_buffer, R_0286CC_SPI_PS_INPUT_ENA, RADV_TRACKED_SPI_PS_INPUT_ENA,
spi_ps_input_ena, spi_ps_input_addr);
if (pdev->info.gfx_level != GFX10_3) {
radeon_opt_set_context_reg(cmd_buffer, R_0286D8_SPI_PS_IN_CONTROL, RADV_TRACKED_SPI_PS_IN_CONTROL,
spi_ps_in_control);
}
if (pdev->info.gfx_level >= GFX9 && pdev->info.gfx_level < GFX11)
radeon_opt_set_context_reg(cmd_buffer, R_028C40_PA_SC_SHADER_CONTROL, RADV_TRACKED_PA_SC_SHADER_CONTROL,
pa_sc_shader_control);
}
}
static void
radv_emit_fragment_shader(struct radv_cmd_buffer *cmd_buffer)
{
const struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
const struct radv_physical_device *pdev = radv_device_physical(device);
const struct radv_shader *ps = cmd_buffer->state.shaders[MESA_SHADER_FRAGMENT];
const uint64_t va = radv_shader_get_va(ps);
@@ -2607,27 +2641,7 @@ radv_emit_fragment_shader(struct radv_cmd_buffer *cmd_buffer)
radeon_emit(cmd_buffer->cs, ps->config.rsrc1);
radeon_emit(cmd_buffer->cs, ps->config.rsrc2);
if (pdev->info.gfx_level >= GFX12) {
radeon_opt_set_context_reg2(cmd_buffer, R_02865C_SPI_PS_INPUT_ENA, RADV_TRACKED_SPI_PS_INPUT_ENA,
ps->config.spi_ps_input_ena, ps->config.spi_ps_input_addr);
radeon_opt_set_context_reg(cmd_buffer, R_028640_SPI_PS_IN_CONTROL, RADV_TRACKED_SPI_PS_IN_CONTROL,
ps->info.regs.ps.spi_ps_in_control);
radeon_set_context_reg(cmd_buffer->cs, R_028BBC_PA_SC_HISZ_CONTROL, ps->info.regs.ps.pa_sc_hisz_control);
} else {
radeon_opt_set_context_reg2(cmd_buffer, R_0286CC_SPI_PS_INPUT_ENA, RADV_TRACKED_SPI_PS_INPUT_ENA,
ps->config.spi_ps_input_ena, ps->config.spi_ps_input_addr);
if (pdev->info.gfx_level != GFX10_3) {
radeon_opt_set_context_reg(cmd_buffer, R_0286D8_SPI_PS_IN_CONTROL, RADV_TRACKED_SPI_PS_IN_CONTROL,
ps->info.regs.ps.spi_ps_in_control);
}
if (pdev->info.gfx_level >= GFX9 && pdev->info.gfx_level < GFX11)
radeon_opt_set_context_reg(cmd_buffer, R_028C40_PA_SC_SHADER_CONTROL, RADV_TRACKED_PA_SC_SHADER_CONTROL,
ps->info.regs.ps.pa_sc_shader_control);
}
radv_emit_fragment_shader_state(cmd_buffer, ps);
}
static void
@@ -2841,8 +2855,14 @@ radv_emit_graphics_shaders(struct radv_cmd_buffer *cmd_buffer)
if (pdev->info.gfx_level >= GFX12) {
const struct radv_shader *ps = cmd_buffer->state.shaders[MESA_SHADER_FRAGMENT];
const struct radv_shader *last_vgt_shader = cmd_buffer->state.last_vgt_shader;
const uint32_t gs_out_config_ps =
last_vgt_shader->info.regs.spi_vs_out_config | (ps ? ps->info.regs.ps.spi_gs_out_config_ps : 0);
uint32_t gs_out_config_ps = last_vgt_shader->info.regs.spi_vs_out_config;
if (ps) {
gs_out_config_ps |= ps->info.regs.ps.spi_gs_out_config_ps;
} else {
/* GFX12 seems to require a dummy FS state otherwise it might just hang. */
radv_emit_fragment_shader_state(cmd_buffer, NULL);
}
radeon_set_sh_reg(cmd_buffer->cs, R_00B0C4_SPI_SHADER_GS_OUT_CONFIG_PS, gs_out_config_ps);
}