diff --git a/src/amd/vulkan/nir/radv_nir_export_multiview.c b/src/amd/vulkan/nir/radv_nir_export_multiview.c index 97f59dfb37c..4b05ff53904 100644 --- a/src/amd/vulkan/nir/radv_nir_export_multiview.c +++ b/src/amd/vulkan/nir/radv_nir_export_multiview.c @@ -10,77 +10,53 @@ #include "nir_builder.h" #include "radv_nir.h" -static nir_variable * -find_layer_out_var(nir_shader *nir) +static void +export_multiview(nir_builder *b) { - nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_out, VARYING_SLOT_LAYER); - if (var != NULL) - return var; + nir_io_semantics io_sem = { + .location = VARYING_SLOT_LAYER, + .num_slots = 1, + .no_varying = true, + }; - var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "layer id"); - var->data.location = VARYING_SLOT_LAYER; - var->data.interpolation = INTERP_MODE_NONE; + nir_store_output(b, nir_load_view_index(b), nir_imm_int(b, 0), .component = 0, .src_type = nir_type_int32, + .io_semantics = io_sem); - return var; + b->shader->info.outputs_written |= VARYING_BIT_LAYER; +} + +static bool +export_multiview_per_emit(nir_builder *b, nir_intrinsic_instr *intr, void *unused) +{ + if (intr->intrinsic != nir_intrinsic_emit_vertex_with_counter) + return false; + + b->cursor = nir_before_instr(&intr->instr); + export_multiview(b); + return true; } bool radv_nir_export_multiview(nir_shader *nir) { - nir_function_impl *impl = nir_shader_get_entrypoint(nir); - bool progress = false; - - nir_builder b = nir_builder_create(impl); - /* This pass is not suitable for mesh shaders, because it can't know the mapping between API mesh * shader invocations and output primitives. Needs to be handled in ac_nir_lower_ngg. */ assert(nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_TESS_EVAL || nir->info.stage == MESA_SHADER_GEOMETRY); - /* Iterate in reverse order since there should be only one deref store to POS after - * lower_io_to_temporaries for vertex shaders and inject the layer there. For geometry shaders, - * the layer is injected right before every emit_vertex_with_counter. - */ - nir_variable *layer = NULL; - nir_foreach_block_reverse (block, impl) { - nir_foreach_instr_reverse (instr, block) { - if (instr->type != nir_instr_type_intrinsic) - continue; + /* The shader shouldn't write gl_Layer itself. */ + assert(!(nir->info.outputs_written & VARYING_BIT_LAYER)); - if (nir->info.stage == MESA_SHADER_GEOMETRY) { - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - if (intr->intrinsic != nir_intrinsic_emit_vertex_with_counter) - continue; + if (nir->info.stage == MESA_SHADER_GEOMETRY) { + /* For geometry shaders, the layer is injected right before every emit_vertex_with_counter. */ + return nir_shader_intrinsics_pass(nir, export_multiview_per_emit, nir_metadata_control_flow, NULL); + } else { + nir_function_impl *impl = nir_shader_get_entrypoint(nir); - b.cursor = nir_before_instr(instr); - } else { - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - if (intr->intrinsic != nir_intrinsic_store_deref) - continue; + nir_builder b = nir_builder_at(nir_after_impl(impl)); + export_multiview(&b); - nir_variable *var = nir_intrinsic_get_var(intr, 0); - if (var->data.mode != nir_var_shader_out || var->data.location != VARYING_SLOT_POS) - continue; - - b.cursor = nir_after_instr(instr); - } - - if (!layer) - layer = find_layer_out_var(nir); - - nir_store_var(&b, layer, nir_load_view_index(&b), 1); - - /* Update outputs_written to reflect that the pass added a new output. */ - nir->info.outputs_written |= VARYING_BIT_LAYER; - - progress = true; - if (nir->info.stage == MESA_SHADER_VERTEX) - break; - } - if (nir->info.stage == MESA_SHADER_VERTEX && progress) - break; + return nir_progress(true, impl, nir_metadata_control_flow); } - - return nir_progress(progress, impl, nir_metadata_control_flow); } diff --git a/src/amd/vulkan/radv_pipeline_graphics.c b/src/amd/vulkan/radv_pipeline_graphics.c index 2192a080a95..9cfb3b107cb 100644 --- a/src/amd/vulkan/radv_pipeline_graphics.c +++ b/src/amd/vulkan/radv_pipeline_graphics.c @@ -1211,17 +1211,6 @@ static const mesa_shader_stage graphics_shader_order[] = { MESA_SHADER_FRAGMENT, }; -static void -radv_link_vs(struct radv_shader_stage *vs_stage, struct radv_shader_stage *next_stage, - const struct radv_graphics_state_key *gfx_state) -{ - assert(vs_stage->nir->info.stage == MESA_SHADER_VERTEX); - - if (radv_should_export_multiview(vs_stage, gfx_state)) { - NIR_PASS(_, vs_stage->nir, radv_nir_export_multiview); - } -} - static void radv_link_tcs(struct radv_shader_stage *tcs_stage, struct radv_shader_stage *tes_stage, const struct radv_graphics_state_key *gfx_state) @@ -1236,28 +1225,6 @@ radv_link_tcs(struct radv_shader_stage *tcs_stage, struct radv_shader_stage *tes merge_tess_info(&tes_stage->nir->info, &tcs_stage->nir->info); } -static void -radv_link_tes(struct radv_shader_stage *tes_stage, struct radv_shader_stage *next_stage, - const struct radv_graphics_state_key *gfx_state) -{ - assert(tes_stage->nir->info.stage == MESA_SHADER_TESS_EVAL); - - if (radv_should_export_multiview(tes_stage, gfx_state)) { - NIR_PASS(_, tes_stage->nir, radv_nir_export_multiview); - } -} - -static void -radv_link_gs(struct radv_shader_stage *gs_stage, struct radv_shader_stage *fs_stage, - const struct radv_graphics_state_key *gfx_state) -{ - assert(gs_stage->nir->info.stage == MESA_SHADER_GEOMETRY); - - if (radv_should_export_multiview(gs_stage, gfx_state)) { - NIR_PASS(_, gs_stage->nir, radv_nir_export_multiview); - } -} - static bool radv_pipeline_needs_noop_fs(struct radv_graphics_pipeline *pipeline, const struct radv_graphics_state_key *gfx_state) { @@ -1286,16 +1253,13 @@ radv_graphics_shaders_link(const struct radv_device *device, const struct radv_g switch (s) { case MESA_SHADER_VERTEX: - radv_link_vs(&stages[s], next_stage, gfx_state); break; case MESA_SHADER_TESS_CTRL: radv_link_tcs(&stages[s], next_stage, gfx_state); break; case MESA_SHADER_TESS_EVAL: - radv_link_tes(&stages[s], next_stage, gfx_state); break; case MESA_SHADER_GEOMETRY: - radv_link_gs(&stages[s], next_stage, gfx_state); break; case MESA_SHADER_TASK: break; @@ -2671,6 +2635,9 @@ radv_graphics_shaders_compile(struct radv_device *device, struct vk_pipeline_cac BITSET_TEST(stages[i].nir->info.system_values_read, SYSTEM_VALUE_DRAW_ID)) radv_nir_lower_draw_id_to_zero(stages[i].nir); + if (i != MESA_SHADER_MESH && radv_should_export_multiview(&stages[i], gfx_state)) + NIR_PASS(_, stages[i].nir, radv_nir_export_multiview); + uint64_t remove_as_varying = 0; uint64_t remove_as_sysval = 0;