From 211e0823ecc1662cab69b66af5267ae919652cf7 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 29 Aug 2025 16:37:00 +0200 Subject: [PATCH] radv: add a new dirty bit for compiling/binding a PS epilog Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 50 ++++++++++++++++++-------------- src/amd/vulkan/radv_cmd_buffer.h | 3 +- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 2832ded50a8..20f6dceb06c 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -8317,6 +8317,9 @@ radv_bind_fragment_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_ cmd_buffer->sample_positions_needed = true; } + if (ps->info.ps.has_epilog) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_PS_EPILOG_SHADER; + if (radv_get_user_sgpr_info(ps, AC_UD_PS_STATE)->sgpr_idx != -1) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_FS_STATE; @@ -8378,12 +8381,22 @@ radv_bind_rt_prolog(struct radv_cmd_buffer *cmd_buffer, struct radv_shader *rt_p radv_cs_add_buffer(device->ws, cs->b, rt_prolog->bo); } -static void -radv_bind_ps_epilog(struct radv_cmd_buffer *cmd_buffer, struct radv_shader_part *ps_epilog) +static struct radv_shader_part * +radv_bind_ps_epilog(struct radv_cmd_buffer *cmd_buffer) { const struct radv_device *device = radv_cmd_buffer_device(cmd_buffer); const struct radv_shader *ps = cmd_buffer->state.shaders[MESA_SHADER_FRAGMENT]; struct radv_cmd_stream *cs = cmd_buffer->cs; + struct radv_shader_part *ps_epilog; + + if (!ps || !ps->info.ps.has_epilog) + return NULL; + + ps_epilog = lookup_ps_epilog(cmd_buffer); + if (!ps_epilog) { + vk_command_buffer_set_error(&cmd_buffer->vk, VK_ERROR_OUT_OF_HOST_MEMORY); + return NULL; + } assert(cmd_buffer->state.custom_blend_mode == 0); radv_bind_fragment_output_state(cmd_buffer, ps, ps_epilog, 0); @@ -8393,6 +8406,8 @@ radv_bind_ps_epilog(struct radv_cmd_buffer *cmd_buffer, struct radv_shader_part cmd_buffer->shader_upload_seq = MAX2(cmd_buffer->shader_upload_seq, ps_epilog->upload_seq); radv_cs_add_buffer(device->ws, cs->b, ps_epilog->bo); + + return ps_epilog; } /* This function binds/unbinds a shader to the cmdbuffer state. */ @@ -9835,7 +9850,8 @@ radv_CmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo *pRe cmd_buffer->state.dirty |= RADV_CMD_DIRTY_FRAMEBUFFER | RADV_CMD_DIRTY_BINNING_STATE | RADV_CMD_DIRTY_FBFETCH_OUTPUT | RADV_CMD_DIRTY_DEPTH_BIAS_STATE | RADV_CMD_DIRTY_DEPTH_STENCIL_STATE | RADV_CMD_DIRTY_CB_RENDER_STATE | - RADV_CMD_DIRTY_MSAA_STATE | RADV_CMD_DIRTY_RAST_SAMPLES_STATE | RADV_CMD_DIRTY_FS_STATE; + RADV_CMD_DIRTY_MSAA_STATE | RADV_CMD_DIRTY_RAST_SAMPLES_STATE | RADV_CMD_DIRTY_FS_STATE | + RADV_CMD_DIRTY_PS_EPILOG_SHADER; if (pdev->info.rbplus_allowed) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_RBPLUS; @@ -12009,6 +12025,11 @@ radv_validate_dynamic_states(struct radv_cmd_buffer *cmd_buffer, uint64_t dynami if ((dynamic_states & RADV_DYNAMIC_PRIMITIVE_TOPOLOGY) || (pdev->info.gfx_level >= GFX12 && dynamic_states & RADV_DYNAMIC_PATCH_CONTROL_POINTS)) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_VGT_PRIM_STATE; + + if (dynamic_states & + (RADV_DYNAMIC_COLOR_WRITE_MASK | RADV_DYNAMIC_COLOR_BLEND_ENABLE | RADV_DYNAMIC_ALPHA_TO_COVERAGE_ENABLE | + RADV_DYNAMIC_COLOR_BLEND_EQUATION | RADV_DYNAMIC_ALPHA_TO_ONE_ENABLE | RADV_DYNAMIC_COLOR_ATTACHMENT_MAP)) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_PS_EPILOG_SHADER; } static void @@ -12018,24 +12039,6 @@ radv_emit_all_graphics_states(struct radv_cmd_buffer *cmd_buffer, const struct r const struct radv_physical_device *pdev = radv_device_physical(device); struct radv_shader_part *ps_epilog = NULL; - if (cmd_buffer->state.shaders[MESA_SHADER_FRAGMENT] && - cmd_buffer->state.shaders[MESA_SHADER_FRAGMENT]->info.ps.has_epilog) { - if ((cmd_buffer->state.emitted_graphics_pipeline != cmd_buffer->state.graphics_pipeline || - ((cmd_buffer->state.dirty & (RADV_CMD_DIRTY_GRAPHICS_SHADERS | RADV_CMD_DIRTY_FRAMEBUFFER)) || - (cmd_buffer->state.dirty_dynamic & - (RADV_DYNAMIC_COLOR_WRITE_MASK | RADV_DYNAMIC_COLOR_BLEND_ENABLE | RADV_DYNAMIC_ALPHA_TO_COVERAGE_ENABLE | - RADV_DYNAMIC_COLOR_BLEND_EQUATION | RADV_DYNAMIC_ALPHA_TO_ONE_ENABLE | - RADV_DYNAMIC_COLOR_ATTACHMENT_MAP))))) { - ps_epilog = lookup_ps_epilog(cmd_buffer); - if (!ps_epilog) { - vk_command_buffer_set_error(&cmd_buffer->vk, VK_ERROR_OUT_OF_HOST_MEMORY); - return; - } - - radv_bind_ps_epilog(cmd_buffer, ps_epilog); - } - } - const uint64_t dynamic_states = cmd_buffer->state.dirty_dynamic & radv_get_needed_dynamic_states(cmd_buffer); if (((cmd_buffer->state.dirty & (RADV_CMD_DIRTY_PIPELINE | RADV_CMD_DIRTY_GRAPHICS_SHADERS)) || (dynamic_states & RADV_DYNAMIC_PATCH_CONTROL_POINTS))) { @@ -12065,6 +12068,11 @@ radv_emit_all_graphics_states(struct radv_cmd_buffer *cmd_buffer, const struct r if (dynamic_states) radv_validate_dynamic_states(cmd_buffer, dynamic_states); + if (cmd_buffer->state.dirty & RADV_CMD_DIRTY_PS_EPILOG_SHADER) { + ps_epilog = radv_bind_ps_epilog(cmd_buffer); + cmd_buffer->state.dirty &= ~RADV_CMD_DIRTY_PS_EPILOG_SHADER; + } + /* Determine whether GFX9 late scissor workaround should be applied based on: * 1. radv_need_late_scissor_emission * 2. any dirty dynamic flags that may cause context rolls diff --git a/src/amd/vulkan/radv_cmd_buffer.h b/src/amd/vulkan/radv_cmd_buffer.h index 46c4ca02c2d..1e247e37f99 100644 --- a/src/amd/vulkan/radv_cmd_buffer.h +++ b/src/amd/vulkan/radv_cmd_buffer.h @@ -120,7 +120,8 @@ enum radv_cmd_dirty_bits { RADV_CMD_DIRTY_FORCE_VRS_STATE = 1ull << 34, RADV_CMD_DIRTY_NGGC_VIEWPORT = 1ull << 35, RADV_CMD_DIRTY_NGGC_SETTINGS = 1ull << 36, - RADV_CMD_DIRTY_ALL = (1ull << 37) - 1, + RADV_CMD_DIRTY_PS_EPILOG_SHADER = 1ull << 37, + RADV_CMD_DIRTY_ALL = (1ull << 38) - 1, RADV_CMD_DIRTY_SHADER_QUERY = RADV_CMD_DIRTY_NGG_STATE | RADV_CMD_DIRTY_TASK_STATE, };