diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 90bb0a37a25..cc30bfbdcc6 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -10476,13 +10476,6 @@ create_vs_exports(isel_context* ctx) get_arg(ctx, ctx->args->ac.vs_prim_id); } - if (ctx->options->key.has_multiview_view_index && - !outinfo->writes_layer_per_primitive) { - ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1; - ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = - as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index)); - } - /* Hardware requires position data to always be exported, even if the * application did not write gl_Position. */ @@ -10531,13 +10524,6 @@ create_primitive_exports(isel_context *ctx, Temp prim_ch1) Builder bld(ctx->program, ctx->block); - if (ctx->options->key.has_multiview_view_index && - outinfo->writes_layer_per_primitive) { - ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1; - ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = - as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index)); - } - /* Use zeroes if the shader doesn't write these but they are needed by eg. PS. */ if (outinfo->writes_layer_per_primitive && !ctx->outputs.mask[VARYING_SLOT_LAYER]) ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = bld.copy(bld.def(v1), Operand::c32(0)); diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c index 8d242b8fd66..408ccc31970 100644 --- a/src/amd/vulkan/radv_nir_to_llvm.c +++ b/src/amd/vulkan/radv_nir_to_llvm.c @@ -1070,19 +1070,6 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, bool export_prim_id, boo struct radv_shader_output_values *outputs; unsigned noutput = 0; - if (ctx->options->key.has_multiview_view_index) { - LLVMValueRef *tmp_out = &ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)]; - if (!*tmp_out) { - for (unsigned i = 0; i < 4; ++i) - ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, i)] = - ac_build_alloca_undef(&ctx->ac, ctx->ac.f32, ""); - } - - LLVMValueRef view_index = ac_get_arg(&ctx->ac, ctx->args->ac.view_index); - LLVMBuildStore(ctx->ac.builder, ac_to_float(&ctx->ac, view_index), *tmp_out); - ctx->output_mask |= 1ull << VARYING_SLOT_LAYER; - } - if (ctx->shader_info->so.num_outputs && !ctx->args->is_gs_copy_shader) { /* The GS copy shader emission already emits streamout. */ radv_emit_streamout(ctx, 0); @@ -1177,9 +1164,6 @@ ngg_gs_get_vertex_storage(struct radv_shader_context *ctx) { unsigned num_outputs = util_bitcount64(ctx->output_mask); - if (ctx->options->key.has_multiview_view_index) - num_outputs++; - LLVMTypeRef elements[2] = { LLVMArrayType(ctx->ac.i32, 4 * num_outputs), LLVMArrayType(ctx->ac.i8, 4), @@ -1650,12 +1634,11 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context *ctx) ac_build_ifcc(&ctx->ac, tmp, 5145); { const struct radv_vs_output_info *outinfo = &ctx->shader_info->vs.outinfo; - bool export_view_index = ctx->options->key.has_multiview_view_index; struct radv_shader_output_values *outputs; unsigned noutput = 0; /* Allocate a temporary array for the output values. */ - unsigned num_outputs = util_bitcount64(ctx->output_mask) + export_view_index; + unsigned num_outputs = util_bitcount64(ctx->output_mask); outputs = calloc(num_outputs, sizeof(outputs[0])); tmp = ngg_gs_vertex_ptr(ctx, tid); @@ -1697,18 +1680,6 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context *ctx) noutput++; } - /* Export ViewIndex. */ - if (export_view_index) { - outputs[noutput].slot_name = VARYING_SLOT_LAYER; - outputs[noutput].slot_index = 0; - outputs[noutput].usage_mask = 0x1; - outputs[noutput].values[0] = - ac_to_float(&ctx->ac, ac_get_arg(&ctx->ac, ctx->args->ac.view_index)); - for (unsigned j = 1; j < 4; j++) - outputs[noutput].values[j] = ctx->ac.f32_0; - noutput++; - } - radv_llvm_export_vs(ctx, outputs, noutput, outinfo, outinfo->export_clip_dists); FREE(outputs); } diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 83985f7bd5c..55fac2e375d 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -2511,6 +2511,77 @@ radv_lower_viewport_to_zero(nir_shader *nir) return false; } +static nir_variable * +find_layer_out_var(nir_shader *nir) +{ + nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_out, VARYING_SLOT_LAYER); + if (var != NULL) + return var; + + var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "layer id"); + var->data.per_primitive = nir->info.stage == MESA_SHADER_MESH; + var->data.location = VARYING_SLOT_LAYER; + var->data.interpolation = INTERP_MODE_NONE; + + return var; +} + +static bool +radv_lower_multiview(nir_shader *nir) +{ + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + bool progress = false; + + nir_builder b; + nir_builder_init(&b, impl); + + /* 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; + + 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; + + 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_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 |= BITFIELD64_BIT(VARYING_SLOT_LAYER); + if (nir->info.stage == MESA_SHADER_MESH) + nir->info.per_primitive_outputs |= BITFIELD64_BIT(VARYING_SLOT_LAYER); + + progress = true; + if (nir->info.stage == MESA_SHADER_VERTEX) + return progress; + } + } + + return progress; +} + static void radv_link_shaders(struct radv_pipeline *pipeline, const struct radv_pipeline_key *pipeline_key, @@ -2688,6 +2759,14 @@ radv_link_shaders(struct radv_pipeline *pipeline, radv_lower_viewport_to_zero(shaders[MESA_SHADER_FRAGMENT]); } + /* Export the layer in the last VGT stage if multiview is used. */ + if (pipeline_key->has_multiview_view_index && pipeline->graphics.last_vgt_api_stage != -1 && + !(shaders[pipeline->graphics.last_vgt_api_stage]->info.outputs_written & + VARYING_BIT_LAYER)) { + nir_shader *last_vgt_shader = shaders[pipeline->graphics.last_vgt_api_stage]; + radv_lower_multiview(last_vgt_shader); + } + for (int i = 1; !optimize_conservatively && (i < shader_count); ++i) { if (nir_link_opt_varyings(ordered_shaders[i], ordered_shaders[i - 1])) { nir_opt_constant_folding(ordered_shaders[i - 1]); @@ -4377,8 +4456,7 @@ radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout pipeline->gs_copy_shader = radv_create_gs_copy_shader( device, nir[MESA_SHADER_GEOMETRY], &info, &gs_copy_args, &gs_copy_binary, - keep_executable_info, keep_statistic_info, pipeline_key->has_multiview_view_index, - pipeline_key->optimisations_disabled); + keep_executable_info, keep_statistic_info, pipeline_key->optimisations_disabled); } if (nir[MESA_SHADER_FRAGMENT]) { diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 8a7f9695e9a..5361a0349d3 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -2051,12 +2051,11 @@ struct radv_shader * radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *shader, struct radv_shader_info *info, const struct radv_shader_args *args, struct radv_shader_binary **binary_out, bool keep_shader_info, - bool keep_statistic_info, bool multiview, bool disable_optimizations) + bool keep_statistic_info, bool disable_optimizations) { struct radv_nir_compiler_options options = {0}; gl_shader_stage stage = MESA_SHADER_VERTEX; - options.key.has_multiview_view_index = multiview; options.key.optimisations_disabled = disable_optimizations; return shader_compile(device, NULL, &shader, 1, stage, info, args, &options, true, false, diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 88cb617a148..212bc0eb2c9 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -553,7 +553,7 @@ void radv_free_shader_memory(struct radv_device *device, union radv_shader_arena struct radv_shader * radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *nir, struct radv_shader_info *info, const struct radv_shader_args *args, - struct radv_shader_binary **binary_out, bool multiview, + struct radv_shader_binary **binary_out, bool keep_shader_info, bool keep_statistic_info, bool disable_optimizations); diff --git a/src/amd/vulkan/radv_shader_args.c b/src/amd/vulkan/radv_shader_args.c index bd40dfe8d3a..13397790dc8 100644 --- a/src/amd/vulkan/radv_shader_args.c +++ b/src/amd/vulkan/radv_shader_args.c @@ -74,38 +74,6 @@ struct user_sgpr_info { bool inlined_all_push_consts; }; -static bool -needs_view_index_sgpr(const struct radv_pipeline_key *key, const struct radv_shader_info *info, - gl_shader_stage stage) -{ - switch (stage) { - case MESA_SHADER_VERTEX: - if (info->uses_view_index || - (!info->vs.as_es && !info->vs.as_ls && key->has_multiview_view_index)) - return true; - break; - case MESA_SHADER_TESS_EVAL: - if (info->uses_view_index || (!info->tes.as_es && key->has_multiview_view_index)) - return true; - break; - case MESA_SHADER_TESS_CTRL: - if (info->uses_view_index) - return true; - break; - case MESA_SHADER_GEOMETRY: - if (info->uses_view_index || (info->is_ngg && key->has_multiview_view_index)) - return true; - break; - case MESA_SHADER_MESH: - if (info->uses_view_index || key->has_multiview_view_index) - return true; - break; - default: - break; - } - return false; -} - static uint8_t count_vs_user_sgprs(const struct radv_shader_info *info) { @@ -554,7 +522,7 @@ radv_declare_shader_args(enum chip_class chip_class, const struct radv_pipeline_ struct radv_shader_args *args) { struct user_sgpr_info user_sgpr_info; - bool needs_view_index = needs_view_index_sgpr(key, info, stage); + bool needs_view_index = info->uses_view_index; bool has_api_gs = stage == MESA_SHADER_GEOMETRY; if (chip_class >= GFX10 && info->is_ngg && stage != MESA_SHADER_GEOMETRY) { diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c index 4ff27c814c8..4196d97fa37 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -673,14 +673,6 @@ radv_nir_shader_info_pass(struct radv_device *device, const struct nir_shader *n struct radv_vs_output_info *outinfo = get_vs_output_info(nir, info); if (outinfo) { - /* Make sure to export the LayerID if the subpass has multiviews. */ - if (pipeline_key->has_multiview_view_index) { - if (nir->info.stage == MESA_SHADER_MESH) - outinfo->writes_layer_per_primitive = true; - else - outinfo->writes_layer = true; - } - int pos_written = 0x1; if (outinfo->writes_pointsize || outinfo->writes_viewport_index || outinfo->writes_layer ||