amd: lower load_vertex_id/instance_id and overwrite_vs_arguments in NIR

2 things complicate this:
- overwrite_vs_arguments_amd
- the LS VGPR bug workaround

Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32782>
This commit is contained in:
Marek Olšák
2024-12-25 12:44:59 -05:00
committed by Marge Bot
parent 66dd70adc5
commit 342dcbdc8b
11 changed files with 48 additions and 61 deletions
+39 -1
View File
@@ -98,9 +98,31 @@ ac_nir_lower_sin_cos(nir_shader *shader)
typedef struct {
const struct ac_shader_args *const args;
const enum amd_gfx_level gfx_level;
bool has_ls_vgpr_init_bug;
const enum ac_hw_stage hw_stage;
nir_def *vertex_id;
nir_def *instance_id;
} lower_intrinsics_to_args_state;
static nir_def *
preload_arg(lower_intrinsics_to_args_state *s, nir_function_impl *impl, struct ac_arg arg,
struct ac_arg ls_buggy_arg)
{
nir_builder start_b = nir_builder_at(nir_before_impl(impl));
nir_def *value = ac_nir_load_arg(&start_b, s->args, arg);
/* If there are no HS threads, SPI mistakenly loads the LS VGPRs starting at VGPR 0. */
if ((s->hw_stage == AC_HW_LOCAL_SHADER || s->hw_stage == AC_HW_HULL_SHADER) &&
s->has_ls_vgpr_init_bug) {
nir_def *count = ac_nir_unpack_arg(&start_b, s->args, s->args->merged_wave_info, 8, 8);
nir_def *hs_empty = nir_ieq_imm(&start_b, count, 0);
value = nir_bcsel(&start_b, hs_empty, ac_nir_load_arg(&start_b, s->args, ls_buggy_arg),
value);
}
return value;
}
static bool
lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state)
{
@@ -332,6 +354,21 @@ lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state)
else
unreachable("Shader doesn't have GS wave ID.");
break;
case nir_intrinsic_overwrite_vs_arguments_amd:
s->vertex_id = intrin->src[0].ssa;
s->instance_id = intrin->src[1].ssa;
nir_instr_remove(instr);
return true;
case nir_intrinsic_load_vertex_id_zero_base:
if (!s->vertex_id)
s->vertex_id = preload_arg(s, b->impl, s->args->vertex_id, s->args->tcs_patch_id);
replacement = s->vertex_id;
break;
case nir_intrinsic_load_instance_id:
if (!s->instance_id)
s->instance_id = preload_arg(s, b->impl, s->args->instance_id, s->args->vertex_id);
replacement = s->instance_id;
break;
default:
return false;
}
@@ -343,12 +380,13 @@ lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state)
bool
ac_nir_lower_intrinsics_to_args(nir_shader *shader, const enum amd_gfx_level gfx_level,
const enum ac_hw_stage hw_stage,
bool has_ls_vgpr_init_bug, const enum ac_hw_stage hw_stage,
const struct ac_shader_args *ac_args)
{
lower_intrinsics_to_args_state state = {
.gfx_level = gfx_level,
.hw_stage = hw_stage,
.has_ls_vgpr_init_bug = has_ls_vgpr_init_bug,
.args = ac_args,
};
+1 -1
View File
@@ -77,7 +77,7 @@ ac_nir_unpack_arg(nir_builder *b, const struct ac_shader_args *ac_args, struct a
bool ac_nir_lower_sin_cos(nir_shader *shader);
bool ac_nir_lower_intrinsics_to_args(nir_shader *shader, const enum amd_gfx_level gfx_level,
const enum ac_hw_stage hw_stage,
bool has_ls_vgpr_init_bug, const enum ac_hw_stage hw_stage,
const struct ac_shader_args *ac_args);
bool ac_nir_optimize_outputs(nir_shader *nir, bool sprite_tex_disallowed,
@@ -8852,16 +8852,6 @@ visit_intrinsic(isel_context* ctx, nir_intrinsic_instr* instr)
emit_split_vector(ctx, dst, 2);
break;
}
case nir_intrinsic_load_vertex_id_zero_base: {
Temp dst = get_ssa_temp(ctx, &instr->def);
bld.copy(Definition(dst), get_arg(ctx, ctx->args->vertex_id));
break;
}
case nir_intrinsic_load_instance_id: {
Temp dst = get_ssa_temp(ctx, &instr->def);
bld.copy(Definition(dst), get_arg(ctx, ctx->args->instance_id));
break;
}
case nir_intrinsic_load_primitive_id: {
Temp dst = get_ssa_temp(ctx, &instr->def);
@@ -8924,11 +8914,6 @@ visit_intrinsic(isel_context* ctx, nir_intrinsic_instr* instr)
bld.def(s1, scc), Operand::c32(nir_intrinsic_call_idx(instr)));
break;
}
case nir_intrinsic_overwrite_vs_arguments_amd: {
ctx->arg_temps[ctx->args->vertex_id.arg_index] = get_ssa_temp(ctx, instr->src[0].ssa);
ctx->arg_temps[ctx->args->instance_id.arg_index] = get_ssa_temp(ctx, instr->src[1].ssa);
break;
}
case nir_intrinsic_overwrite_tes_arguments_amd: {
ctx->arg_temps[ctx->args->tes_u.arg_index] = get_ssa_temp(ctx, instr->src[0].ssa);
ctx->arg_temps[ctx->args->tes_v.arg_index] = get_ssa_temp(ctx, instr->src[1].ssa);
@@ -11118,20 +11103,11 @@ fix_ls_vgpr_init_bug(isel_context* ctx)
Temp ls_has_nonzero_hs_threads = bool_to_vector_condition(ctx, hs_thread_count.def(1).getTemp());
/* If there are no HS threads, SPI mistakenly loads the LS VGPRs starting at VGPR 0. */
Temp instance_id =
bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), get_arg(ctx, ctx->args->vertex_id),
get_arg(ctx, ctx->args->instance_id), ls_has_nonzero_hs_threads);
Temp vs_rel_patch_id =
bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), get_arg(ctx, ctx->args->tcs_rel_ids),
get_arg(ctx, ctx->args->vs_rel_patch_id), ls_has_nonzero_hs_threads);
Temp vertex_id =
bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), get_arg(ctx, ctx->args->tcs_patch_id),
get_arg(ctx, ctx->args->vertex_id), ls_has_nonzero_hs_threads);
ctx->arg_temps[ctx->args->instance_id.arg_index] = instance_id;
ctx->arg_temps[ctx->args->vs_rel_patch_id.arg_index] = vs_rel_patch_id;
ctx->arg_temps[ctx->args->vertex_id.arg_index] = vertex_id;
}
void
@@ -549,7 +549,6 @@ init_context(isel_context* ctx, nir_shader* shader)
case nir_intrinsic_load_input_vertex:
case nir_intrinsic_load_per_vertex_input:
case nir_intrinsic_load_per_vertex_output:
case nir_intrinsic_load_vertex_id_zero_base:
case nir_intrinsic_load_interpolated_input:
case nir_intrinsic_load_local_invocation_index:
case nir_intrinsic_load_subgroup_invocation:
@@ -558,7 +557,6 @@ init_context(isel_context* ctx, nir_shader* shader)
case nir_intrinsic_mbcnt_amd:
case nir_intrinsic_lane_permute_16_amd:
case nir_intrinsic_dpp16_shift_amd:
case nir_intrinsic_load_instance_id:
case nir_intrinsic_ssbo_atomic:
case nir_intrinsic_ssbo_atomic_swap:
case nir_intrinsic_global_atomic_amd:
-19
View File
@@ -2822,9 +2822,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
case nir_intrinsic_load_lds_ngg_gs_out_vertex_base_amd:
result = ctx->abi->intrinsic_load(ctx->abi, instr);
break;
case nir_intrinsic_load_vertex_id_zero_base:
result = ctx->abi->vertex_id_replaced ? ctx->abi->vertex_id_replaced : ctx->abi->vertex_id;
break;
case nir_intrinsic_load_primitive_id:
if (ctx->stage == MESA_SHADER_GEOMETRY) {
result = ac_get_arg(&ctx->ac, ctx->args->gs_prim_id);
@@ -2845,10 +2842,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
case nir_intrinsic_is_helper_invocation:
result = ac_build_load_helper_invocation(&ctx->ac);
break;
case nir_intrinsic_load_instance_id:
result = ctx->abi->instance_id_replaced ?
ctx->abi->instance_id_replaced : ctx->abi->instance_id;
break;
case nir_intrinsic_load_num_workgroups:
if (ctx->abi->load_grid_size_from_user_sgpr) {
result = ac_get_arg(&ctx->ac, ctx->args->num_work_groups);
@@ -3262,10 +3255,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
result = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT, ac_get_thread_id(&ctx->ac), count, "");
break;
}
case nir_intrinsic_overwrite_vs_arguments_amd:
ctx->abi->vertex_id_replaced = get_src(ctx, instr->src[0]);
ctx->abi->instance_id_replaced = get_src(ctx, instr->src[1]);
break;
case nir_intrinsic_overwrite_tes_arguments_amd:
ctx->abi->tes_u_replaced = ac_to_float(&ctx->ac, get_src(ctx, instr->src[0]));
ctx->abi->tes_v_replaced = ac_to_float(&ctx->ac, get_src(ctx, instr->src[1]));
@@ -4207,15 +4196,7 @@ void ac_fixup_ls_hs_input_vgprs(struct ac_llvm_context *ac, struct ac_shader_abi
LLVMValueRef count = ac_unpack_param(ac, ac_get_arg(ac, args->merged_wave_info), 8, 8);
LLVMValueRef hs_empty = LLVMBuildICmp(ac->builder, LLVMIntEQ, count, ac->i32_0, "");
abi->instance_id =
LLVMBuildSelect(ac->builder, hs_empty, ac_get_arg(ac, args->vertex_id),
abi->instance_id, "");
abi->vs_rel_patch_id =
LLVMBuildSelect(ac->builder, hs_empty, ac_get_arg(ac, args->tcs_rel_ids),
abi->vs_rel_patch_id, "");
abi->vertex_id =
LLVMBuildSelect(ac->builder, hs_empty, ac_get_arg(ac, args->tcs_patch_id),
abi->vertex_id, "");
}
-4
View File
@@ -26,13 +26,9 @@ struct ac_shader_abi {
bool is_16bit[AC_LLVM_MAX_OUTPUTS * 4];
/* These input registers sometimes need to be fixed up. */
LLVMValueRef vertex_id;
LLVMValueRef vs_rel_patch_id;
LLVMValueRef instance_id;
/* replaced registers when culling enabled */
LLVMValueRef vertex_id_replaced;
LLVMValueRef instance_id_replaced;
LLVMValueRef tes_u_replaced;
LLVMValueRef tes_v_replaced;
LLVMValueRef tes_rel_patch_id_replaced;
-4
View File
@@ -279,12 +279,8 @@ ac_translate_nir_to_llvm(struct ac_llvm_compiler *ac_llvm, const struct radv_nir
if (shader_count >= 2 || is_ngg)
ac_init_exec_full_mask(&ctx.ac);
if (args->ac.vertex_id.used)
ctx.abi.vertex_id = ac_get_arg(&ctx.ac, args->ac.vertex_id);
if (args->ac.vs_rel_patch_id.used)
ctx.abi.vs_rel_patch_id = ac_get_arg(&ctx.ac, args->ac.vs_rel_patch_id);
if (args->ac.instance_id.used)
ctx.abi.instance_id = ac_get_arg(&ctx.ac, args->ac.instance_id);
if (options->info->has_ls_vgpr_init_bug && shaders[shader_count - 1]->info.stage == MESA_SHADER_TESS_CTRL)
ac_fixup_ls_hs_input_vgprs(&ctx.ac, &ctx.abi, &args->ac);
+3 -2
View File
@@ -515,8 +515,9 @@ radv_postprocess_nir(struct radv_device *device, const struct radv_graphics_stat
});
NIR_PASS(_, stage->nir, ac_nir_lower_global_access);
NIR_PASS_V(stage->nir, ac_nir_lower_intrinsics_to_args, gfx_level, radv_select_hw_stage(&stage->info, gfx_level),
&stage->args.ac);
NIR_PASS_V(stage->nir, ac_nir_lower_intrinsics_to_args, gfx_level,
pdev->info.has_ls_vgpr_init_bug && gfx_state && !gfx_state->vs.has_prolog,
radv_select_hw_stage(&stage->info, gfx_level), &stage->args.ac);
NIR_PASS_V(stage->nir, radv_nir_lower_abi, gfx_level, stage, gfx_state, pdev->info.address32_hi);
radv_optimize_nir_algebraic(
stage->nir, io_to_mem || lowered_ngg || stage->stage == MESA_SHADER_COMPUTE || stage->stage == MESA_SHADER_TASK,
+2 -1
View File
@@ -2277,7 +2277,8 @@ radv_create_gs_copy_shader(struct radv_device *device, struct vk_pipeline_cache
gs_copy_stage.info.user_sgprs_locs = gs_copy_stage.args.user_sgprs_locs;
gs_copy_stage.info.inline_push_constant_mask = gs_copy_stage.args.ac.inline_push_const_mask;
NIR_PASS_V(nir, ac_nir_lower_intrinsics_to_args, pdev->info.gfx_level, AC_HW_VERTEX_SHADER, &gs_copy_stage.args.ac);
NIR_PASS_V(nir, ac_nir_lower_intrinsics_to_args, pdev->info.gfx_level, pdev->info.has_ls_vgpr_init_bug,
AC_HW_VERTEX_SHADER, &gs_copy_stage.args.ac);
NIR_PASS_V(nir, radv_nir_lower_abi, pdev->info.gfx_level, &gs_copy_stage, gfx_state, pdev->info.address32_hi);
struct radv_graphics_pipeline_key key = {0};
+3 -1
View File
@@ -2592,6 +2592,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
NIR_PASS(progress, nir, si_nir_lower_abi, shader, args);
NIR_PASS(progress, nir, ac_nir_lower_intrinsics_to_args, sel->screen->info.gfx_level,
sel->screen->info.has_ls_vgpr_init_bug,
si_select_hw_stage(nir->info.stage, key, sel->screen->info.gfx_level),
&args->ac);
@@ -2762,7 +2763,8 @@ si_nir_generate_gs_copy_shader(struct si_screen *sscreen,
si_init_shader_args(shader, &args, &gs_nir->info);
NIR_PASS_V(nir, si_nir_lower_abi, shader, &args);
NIR_PASS_V(nir, ac_nir_lower_intrinsics_to_args, sscreen->info.gfx_level, AC_HW_VERTEX_SHADER, &args.ac);
NIR_PASS_V(nir, ac_nir_lower_intrinsics_to_args, sscreen->info.gfx_level,
sscreen->info.has_ls_vgpr_init_bug, AC_HW_VERTEX_SHADER, &args.ac);
si_nir_opts(gs_selector->screen, nir, false);
@@ -219,8 +219,6 @@ void si_llvm_create_main_func(struct si_shader_context *ctx)
}
if (ctx->stage == MESA_SHADER_VERTEX) {
ctx->abi.vertex_id = ac_get_arg(&ctx->ac, ctx->args->ac.vertex_id);
ctx->abi.instance_id = ac_get_arg(&ctx->ac, ctx->args->ac.instance_id);
if (ctx->args->ac.vs_rel_patch_id.used)
ctx->abi.vs_rel_patch_id = ac_get_arg(&ctx->ac, ctx->args->ac.vs_rel_patch_id);