From 1e4cfd9dfafafd0e0f43d36f6833852e7a414893 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 13 Mar 2025 19:27:44 +0100 Subject: [PATCH] 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 Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 70 ++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 00c2599b05b..e3e8dab4137 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -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); }