From 879ddf97202fb4721be28f0efffeb064ea61c57b Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 24 Mar 2023 09:36:01 +0100 Subject: [PATCH] radv: rework binding shaders to cmdbuf by introducing new helpers For future work. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 182 +++++++++++++++++++++++++++------------ src/amd/vulkan/radv_pipeline.c | 7 -- src/amd/vulkan/radv_private.h | 6 -- 3 files changed, 129 insertions(+), 66 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 9706dc3..df2c0b0 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -6247,6 +6247,107 @@ radv_bind_vs_input_state(struct radv_cmd_buffer *cmd_buffer, cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT; } +static void +radv_bind_pre_rast_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *shader) +{ + if (radv_get_user_sgpr(shader, AC_UD_NGG_PROVOKING_VTX)->sgpr_idx != -1) { + /* Re-emit the provoking vertex mode state because the SGPR idx can be different. */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PROVOKING_VERTEX_MODE; + } + + if (radv_get_user_sgpr(shader, AC_UD_STREAMOUT_BUFFERS)->sgpr_idx != -1) { + /* Re-emit the streamout buffers because the SGPR idx can be different and with NGG streamout + * they always need to be emitted because a buffer size of 0 is used to disable streamout. + */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_STREAMOUT_BUFFER; + + if (cmd_buffer->device->physical_device->use_ngg_streamout) { + cmd_buffer->gds_needed = true; + cmd_buffer->gds_oa_needed = true; + } + } + + if (radv_get_user_sgpr(shader, AC_UD_NUM_VERTS_PER_PRIM)->sgpr_idx != -1) { + /* Re-emit the primitive topology because the SGPR idx can be different. */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; + } + + if (radv_get_user_sgpr(shader, AC_UD_NGG_QUERY_STATE)->sgpr_idx != -1) { + /* Re-emit NGG query state when SGPR exists but location potentially changed. */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_NGG_QUERY; + } +} + +static void +radv_bind_vertex_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *vs) +{ + radv_bind_pre_rast_shader(cmd_buffer, vs); +} + +static void +radv_bind_tess_ctrl_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *tcs) +{ + cmd_buffer->tess_rings_needed = true; + + /* Always re-emit patch control points when a new pipeline with tessellation is bound because a + * bunch of parameters (user SGPRs, TCS vertices out, ccw, etc) can be different. + */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PATCH_CONTROL_POINTS; +} + +static void +radv_bind_tess_eval_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *tes) +{ + radv_bind_pre_rast_shader(cmd_buffer, tes); + + cmd_buffer->tess_rings_needed = true; + + /* Always re-emit patch control points/domain origin when a new pipeline with tessellation is + * bound because a bunch of parameters (user SGPRs, TCS vertices out, ccw, etc) can be different. + */ + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PATCH_CONTROL_POINTS | + RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN; +} + +static void +radv_bind_geometry_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *gs) +{ + radv_bind_pre_rast_shader(cmd_buffer, gs); +} + +static void +radv_bind_mesh_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *ms) +{ + radv_bind_pre_rast_shader(cmd_buffer, ms); + + cmd_buffer->mesh_scratch_ring_needed |= ms->info.ms.needs_ms_scratch_ring; +} + +static void +radv_bind_fragment_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *ps) +{ + if (ps->info.ps.needs_sample_positions) { + cmd_buffer->sample_positions_needed = true; + } + + /* Re-emit the rasterization samples state because the SGPR idx can be different. */ + if (radv_get_user_sgpr(ps, AC_UD_PS_NUM_SAMPLES)->sgpr_idx != -1) { + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_RASTERIZATION_SAMPLES; + } +} + +static void +radv_bind_task_shader(struct radv_cmd_buffer *cmd_buffer, const struct radv_shader *ts) +{ + if (!cmd_buffer->ace_internal.cs) { + cmd_buffer->ace_internal.cs = radv_ace_internal_create(cmd_buffer); + if (!cmd_buffer->ace_internal.cs) + return; + } + + cmd_buffer->task_rings_needed = true; +} + VKAPI_ATTR void VKAPI_CALL radv_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline _pipeline) @@ -6334,13 +6435,6 @@ radv_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipeline cmd_buffer->state.tess_num_patches = tcs->info.num_tess_patches; cmd_buffer->state.tess_lds_size = tcs->info.tcs.num_lds_blocks; } - - /* Always re-emit patch control points/domain origin when a new pipeline with tessellation - * is bound because a bunch of parameters (user SGPRs, TCS vertices out, ccw, etc) can be - * different. - */ - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PATCH_CONTROL_POINTS | - RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN; } /* Re-emit the vertex buffer descriptors because they are really tied to the pipeline. */ @@ -6348,11 +6442,6 @@ radv_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipeline cmd_buffer->state.dirty |= RADV_CMD_DIRTY_VERTEX_BUFFER; } - /* Re-emit the provoking vertex mode state because the SGPR idx can be different. */ - if (graphics_pipeline->has_pv_sgpr) { - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PROVOKING_VERTEX_MODE; - } - if (cmd_buffer->device->physical_device->rad_info.rbplus_allowed && (!cmd_buffer->state.emitted_graphics_pipeline || cmd_buffer->state.col_format_non_compacted != graphics_pipeline->col_format_non_compacted)) { @@ -6360,39 +6449,10 @@ radv_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipeline cmd_buffer->state.dirty |= RADV_CMD_DIRTY_RBPLUS; } - /* Re-emit the streamout buffers because the SGPR idx can be different and with NGG streamout - * they always need to be emitted because a buffer size of 0 is used to disable streamout. - */ - if (graphics_pipeline->has_streamout) { - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_STREAMOUT_BUFFER; - - if (cmd_buffer->device->physical_device->use_ngg_streamout) { - cmd_buffer->gds_needed = true; - cmd_buffer->gds_oa_needed = true; - } - } - - /* Re-emit NGG query state when SGPR exists but location potentially changed. */ - if (graphics_pipeline->last_vgt_api_stage_locs[AC_UD_NGG_QUERY_STATE].sgpr_idx != -1) - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_NGG_QUERY; - - /* Re-emit the rasterization samples state because the SGPR idx can be different. */ - if (graphics_pipeline->has_dynamic_samples) { - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_RASTERIZATION_SAMPLES; - } - - /* Re-emit the primitive topology because the SGPR idx can be different. */ - if (graphics_pipeline->has_num_verts_per_prim) { - cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; - } - radv_bind_dynamic_state(cmd_buffer, &graphics_pipeline->dynamic_state); radv_bind_vs_input_state(cmd_buffer, graphics_pipeline); - if (graphics_pipeline->has_sample_positions) - cmd_buffer->sample_positions_needed = true; - if (graphics_pipeline->esgs_ring_size > cmd_buffer->esgs_ring_size_needed) cmd_buffer->esgs_ring_size_needed = graphics_pipeline->esgs_ring_size; if (graphics_pipeline->gsvs_ring_size > cmd_buffer->gsvs_ring_size_needed) @@ -6402,21 +6462,37 @@ radv_CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipeline MAX2(cmd_buffer->scratch_size_per_wave_needed, pipeline->scratch_bytes_per_wave); cmd_buffer->scratch_waves_wanted = MAX2(cmd_buffer->scratch_waves_wanted, pipeline->max_waves); - if (graphics_pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) - cmd_buffer->tess_rings_needed = true; - if (mesh_shading) - cmd_buffer->mesh_scratch_ring_needed |= - pipeline->shaders[MESA_SHADER_MESH]->info.ms.needs_ms_scratch_ring; + for (uint32_t s = 0; s < MESA_SHADER_COMPUTE; s++) { + const struct radv_shader *shader = graphics_pipeline->base.shaders[s]; - if (graphics_pipeline->active_stages & VK_SHADER_STAGE_TASK_BIT_EXT) { - if (!cmd_buffer->ace_internal.cs) { - cmd_buffer->ace_internal.cs = radv_ace_internal_create(cmd_buffer); - if (!cmd_buffer->ace_internal.cs) - return; - } + if (!shader) + continue; - cmd_buffer->task_rings_needed = true; + switch (s) { + case MESA_SHADER_VERTEX: + radv_bind_vertex_shader(cmd_buffer, shader); + break; + case MESA_SHADER_TESS_CTRL: + radv_bind_tess_ctrl_shader(cmd_buffer, shader); + break; + case MESA_SHADER_TESS_EVAL: + radv_bind_tess_eval_shader(cmd_buffer, shader); + break; + case MESA_SHADER_GEOMETRY: + radv_bind_geometry_shader(cmd_buffer, shader); + break; + case MESA_SHADER_FRAGMENT: + radv_bind_fragment_shader(cmd_buffer, shader); + break; + default: + unreachable("invalid graphics shader stage"); + } } + + if (graphics_pipeline->base.shaders[MESA_SHADER_MESH]) + radv_bind_mesh_shader(cmd_buffer, graphics_pipeline->base.shaders[MESA_SHADER_MESH]); + if (graphics_pipeline->base.shaders[MESA_SHADER_TASK]) + radv_bind_task_shader(cmd_buffer, graphics_pipeline->base.shaders[MESA_SHADER_TASK]); break; } default: diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 4489ff2..cafb21d 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -4989,13 +4989,6 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv pipeline->rast_prim = vgt_gs_out_prim_type; pipeline->last_vgt_api_stage_locs = pipeline->base.shaders[pipeline->last_vgt_api_stage]->info.user_sgprs_locs.shader_data; - pipeline->has_pv_sgpr = pipeline->last_vgt_api_stage_locs[AC_UD_NGG_PROVOKING_VTX].sgpr_idx != -1; - pipeline->has_streamout = pipeline->last_vgt_api_stage_locs[AC_UD_STREAMOUT_BUFFERS].sgpr_idx != -1; - pipeline->has_dynamic_samples = ps->info.user_sgprs_locs.shader_data[AC_UD_PS_NUM_SAMPLES].sgpr_idx != -1; - pipeline->has_sample_positions = ps->info.ps.needs_sample_positions; - pipeline->has_num_verts_per_prim = - pipeline->last_vgt_api_stage_locs[AC_UD_NUM_VERTS_PER_PRIM].sgpr_idx != -1; - pipeline->base.push_constant_size = pipeline_layout.push_constant_size; pipeline->base.dynamic_offset_count = pipeline_layout.dynamic_offset_count; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 3bf84bb..3b7e5b8 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -2205,12 +2205,6 @@ struct radv_graphics_pipeline { /* Whether the pipeline uses NGG (GFX10+). */ bool is_ngg; bool has_ngg_culling; - /* shortcuts for pipeline bind */ - bool has_pv_sgpr; - bool has_streamout; - bool has_dynamic_samples; - bool has_sample_positions; - bool has_num_verts_per_prim; uint8_t vtx_emit_num; -- 2.7.4