From e529745be3af9c792fba8e6e8a3075c8d78851af Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 1 Sep 2022 10:16:11 +0200 Subject: [PATCH] radv: do not link shaders when the next stage is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With GPL, it's possible to build the pre-rasterization stages separately from the fragment stage. Implicit IO (like gl_PrimitiveID) between the last pre-rast stage and the FS will be addressed later. Signed-off-by: Samuel Pitoiset Reviewed-by: Timur Kristóf Part-of: --- src/amd/vulkan/radv_pipeline.c | 66 ++++++++++++++++++------------- src/amd/vulkan/radv_shader_info.c | 17 ++++---- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index d3836d4cbc4..e7b3fd5fc2b 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -2437,27 +2437,30 @@ radv_pipeline_link_vs(const struct radv_device *device, struct radv_pipeline_sta const struct radv_pipeline_key *pipeline_key) { assert(vs_stage->nir->info.stage == MESA_SHADER_VERTEX); - assert(next_stage->nir->info.stage == MESA_SHADER_TESS_CTRL || - next_stage->nir->info.stage == MESA_SHADER_GEOMETRY || - next_stage->nir->info.stage == MESA_SHADER_FRAGMENT); - if (radv_should_export_implicit_primitive_id(vs_stage, next_stage)) { - NIR_PASS(_, vs_stage->nir, radv_export_implicit_primitive_id); + if (next_stage) { + assert(next_stage->nir->info.stage == MESA_SHADER_TESS_CTRL || + next_stage->nir->info.stage == MESA_SHADER_GEOMETRY || + next_stage->nir->info.stage == MESA_SHADER_FRAGMENT); + + if (radv_should_export_implicit_primitive_id(vs_stage, next_stage)) { + NIR_PASS(_, vs_stage->nir, radv_export_implicit_primitive_id); + } + + radv_pipeline_link_shaders(device, vs_stage->nir, next_stage->nir, pipeline_key); } - radv_pipeline_link_shaders(device, vs_stage->nir, next_stage->nir, pipeline_key); - nir_foreach_shader_in_variable(var, vs_stage->nir) { var->data.driver_location = var->data.location; } - if (next_stage->nir->info.stage == MESA_SHADER_TESS_CTRL) { + if (next_stage && next_stage->nir->info.stage == MESA_SHADER_TESS_CTRL) { nir_linked_io_var_info vs2tcs = nir_assign_linked_io_var_locations(vs_stage->nir, next_stage->nir); vs_stage->info.vs.num_linked_outputs = vs2tcs.num_linked_io_vars; next_stage->info.tcs.num_linked_inputs = vs2tcs.num_linked_io_vars; - } else if (next_stage->nir->info.stage == MESA_SHADER_GEOMETRY) { + } else if (next_stage && next_stage->nir->info.stage == MESA_SHADER_GEOMETRY) { nir_linked_io_var_info vs2gs = nir_assign_linked_io_var_locations(vs_stage->nir, next_stage->nir); @@ -2500,16 +2503,19 @@ radv_pipeline_link_tes(const struct radv_device *device, struct radv_pipeline_st const struct radv_pipeline_key *pipeline_key) { assert(tes_stage->nir->info.stage == MESA_SHADER_TESS_EVAL); - assert(next_stage->nir->info.stage == MESA_SHADER_GEOMETRY || - next_stage->nir->info.stage == MESA_SHADER_FRAGMENT); - if (radv_should_export_implicit_primitive_id(tes_stage, next_stage)) { - NIR_PASS(_, tes_stage->nir, radv_export_implicit_primitive_id); + if (next_stage) { + assert(next_stage->nir->info.stage == MESA_SHADER_GEOMETRY || + next_stage->nir->info.stage == MESA_SHADER_FRAGMENT); + + if (radv_should_export_implicit_primitive_id(tes_stage, next_stage)) { + NIR_PASS(_, tes_stage->nir, radv_export_implicit_primitive_id); + } + + radv_pipeline_link_shaders(device, tes_stage->nir, next_stage->nir, pipeline_key); } - radv_pipeline_link_shaders(device, tes_stage->nir, next_stage->nir, pipeline_key); - - if (next_stage->nir->info.stage == MESA_SHADER_GEOMETRY) { + if (next_stage && next_stage->nir->info.stage == MESA_SHADER_GEOMETRY) { nir_linked_io_var_info tes2gs = nir_assign_linked_io_var_locations(tes_stage->nir, next_stage->nir); @@ -2528,9 +2534,12 @@ radv_pipeline_link_gs(const struct radv_device *device, struct radv_pipeline_sta const struct radv_pipeline_key *pipeline_key) { assert(gs_stage->nir->info.stage == MESA_SHADER_GEOMETRY); - assert(fs_stage->nir->info.stage == MESA_SHADER_FRAGMENT); - radv_pipeline_link_shaders(device, gs_stage->nir, fs_stage->nir, pipeline_key); + if (fs_stage) { + assert(fs_stage->nir->info.stage == MESA_SHADER_FRAGMENT); + + radv_pipeline_link_shaders(device, gs_stage->nir, fs_stage->nir, pipeline_key); + } nir_foreach_shader_out_variable(var, gs_stage->nir) { var->data.driver_location = var->data.location; @@ -2555,18 +2564,21 @@ radv_pipeline_link_mesh(const struct radv_device *device, struct radv_pipeline_s const struct radv_pipeline_key *pipeline_key) { assert(mesh_stage->nir->info.stage == MESA_SHADER_MESH); - assert(fs_stage->nir->info.stage == MESA_SHADER_FRAGMENT); - nir_foreach_shader_in_variable(var, fs_stage->nir) { - /* These variables are per-primitive when used with a mesh shader. */ - if (var->data.location == VARYING_SLOT_PRIMITIVE_ID || - var->data.location == VARYING_SLOT_VIEWPORT || - var->data.location == VARYING_SLOT_LAYER) { - var->data.per_primitive = true; + if (fs_stage) { + assert(fs_stage->nir->info.stage == MESA_SHADER_FRAGMENT); + + nir_foreach_shader_in_variable(var, fs_stage->nir) { + /* These variables are per-primitive when used with a mesh shader. */ + if (var->data.location == VARYING_SLOT_PRIMITIVE_ID || + var->data.location == VARYING_SLOT_VIEWPORT || + var->data.location == VARYING_SLOT_LAYER) { + var->data.per_primitive = true; + } } - } - radv_pipeline_link_shaders(device, mesh_stage->nir, fs_stage->nir, pipeline_key); + radv_pipeline_link_shaders(device, mesh_stage->nir, fs_stage->nir, pipeline_key); + } /* ac_nir_lower_ngg ignores driver locations for mesh shaders, but set them to all zero just to * be on the safe side. diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c index 7844ed2b8ee..8d31675b309 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -1251,7 +1251,7 @@ radv_link_shaders_info(struct radv_device *device, const struct radv_pipeline_key *pipeline_key) { /* Export primitive ID or clip/cull distances if necessary. */ - if (consumer->stage == MESA_SHADER_FRAGMENT) { + if (consumer && consumer->stage == MESA_SHADER_FRAGMENT) { struct radv_vs_output_info *outinfo = &producer->info.outinfo; const bool ps_prim_id_in = consumer->info.ps.prim_id_input; const bool ps_clip_dists_in = !!consumer->info.ps.num_input_clips_culls; @@ -1276,7 +1276,7 @@ radv_link_shaders_info(struct radv_device *device, } if (producer->stage == MESA_SHADER_VERTEX || producer->stage == MESA_SHADER_TESS_EVAL) { - if (consumer->stage == MESA_SHADER_GEOMETRY) { + if (consumer && consumer->stage == MESA_SHADER_GEOMETRY) { uint32_t num_outputs_written; if (producer->stage == MESA_SHADER_TESS_EVAL) { @@ -1294,20 +1294,21 @@ radv_link_shaders_info(struct radv_device *device, /* Compute NGG info (GFX10+) or GS info. */ if (producer->info.is_ngg) { struct radv_pipeline_stage *gs_stage = - consumer->stage == MESA_SHADER_GEOMETRY ? consumer : NULL; + consumer && consumer->stage == MESA_SHADER_GEOMETRY ? consumer : NULL; gfx10_get_ngg_info(device, producer, gs_stage); /* Determine other NGG settings like culling for VS or TES without GS. */ - if (!gs_stage) { + if (!gs_stage && consumer) { radv_determine_ngg_settings(device, producer, consumer, pipeline_key); } - } else if (consumer->stage == MESA_SHADER_GEOMETRY) { + } else if (consumer && consumer->stage == MESA_SHADER_GEOMETRY) { gfx9_get_gs_info(device, producer, consumer); } } - if (producer->stage == MESA_SHADER_VERTEX && consumer->stage == MESA_SHADER_TESS_CTRL) { + if (producer->stage == MESA_SHADER_VERTEX && + consumer && consumer->stage == MESA_SHADER_TESS_CTRL) { struct radv_pipeline_stage *vs_stage = producer; struct radv_pipeline_stage *tcs_stage = consumer; @@ -1426,7 +1427,9 @@ radv_nir_shader_info_link(struct radv_device *device, const struct radv_pipeline struct radv_pipeline_stage *stages) { /* Walk backwards to link */ - struct radv_pipeline_stage *next_stage = &stages[MESA_SHADER_FRAGMENT]; + struct radv_pipeline_stage *next_stage = + stages[MESA_SHADER_FRAGMENT].nir ? &stages[MESA_SHADER_FRAGMENT] : NULL; + for (int i = ARRAY_SIZE(graphics_shader_order) - 1; i >= 0; i--) { gl_shader_stage s = graphics_shader_order[i]; if (!stages[s].nir)