From 923f59c97164ce24c3016cae24d479d4b6b9e3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 25 Dec 2024 12:44:59 -0500 Subject: [PATCH] amd: lower load_barycentric_at_offset in NIR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Timur Kristóf Part-of: --- src/amd/common/ac_nir.c | 19 +++++++ .../compiler/aco_instruction_selection.cpp | 57 ------------------- .../aco_instruction_selection_setup.cpp | 1 - src/amd/llvm/ac_llvm_build.c | 18 ------ src/amd/llvm/ac_llvm_build.h | 2 - src/amd/llvm/ac_nir_to_llvm.c | 46 --------------- 6 files changed, 19 insertions(+), 124 deletions(-) diff --git a/src/amd/common/ac_nir.c b/src/amd/common/ac_nir.c index dc486c040c4..b5daf6dac95 100644 --- a/src/amd/common/ac_nir.c +++ b/src/amd/common/ac_nir.c @@ -305,6 +305,25 @@ lower_intrinsic_to_arg(nir_builder *b, nir_instr *instr, void *state) case nir_intrinsic_load_barycentric_model: replacement = ac_nir_load_arg(b, s->args, s->args->pull_model); break; + case nir_intrinsic_load_barycentric_at_offset: { + nir_def *baryc = nir_intrinsic_interp_mode(intrin) == INTERP_MODE_NOPERSPECTIVE ? + ac_nir_load_arg(b, s->args, s->args->linear_center) : + ac_nir_load_arg(b, s->args, s->args->persp_center); + nir_def *i = nir_channel(b, baryc, 0); + nir_def *j = nir_channel(b, baryc, 1); + nir_def *offset_x = nir_channel(b, intrin->src[0].ssa, 0); + nir_def *offset_y = nir_channel(b, intrin->src[0].ssa, 1); + nir_def *ddx_i = nir_ddx(b, i); + nir_def *ddx_j = nir_ddx(b, j); + nir_def *ddy_i = nir_ddy(b, i); + nir_def *ddy_j = nir_ddy(b, j); + + /* Interpolate standard barycentrics by offset. */ + nir_def *offset_i = nir_ffma(b, ddy_i, offset_y, nir_ffma(b, ddx_i, offset_x, i)); + nir_def *offset_j = nir_ffma(b, ddy_j, offset_y, nir_ffma(b, ddx_j, offset_x, j)); + replacement = nir_vec2(b, offset_i, offset_j); + break; + } default: return false; } diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 099dca6a5bc..44740b4d617 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -7895,52 +7895,6 @@ emit_rotate_by_constant(isel_context* ctx, Temp& dst, Temp src, unsigned cluster return dst.id() != 0; } -void -emit_interp_center(isel_context* ctx, Temp dst, Temp bary, Temp pos1, Temp pos2) -{ - Builder bld(ctx->program, ctx->block); - Temp p1 = emit_extract_vector(ctx, bary, 0, v1); - Temp p2 = emit_extract_vector(ctx, bary, 1, v1); - - Temp ddx_1, ddx_2, ddy_1, ddy_2; - uint32_t dpp_ctrl0 = dpp_quad_perm(0, 0, 0, 0); - uint32_t dpp_ctrl1 = dpp_quad_perm(1, 1, 1, 1); - uint32_t dpp_ctrl2 = dpp_quad_perm(2, 2, 2, 2); - - /* Build DD X/Y */ - if (ctx->program->gfx_level >= GFX8) { - Temp tl_1 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1), p1, dpp_ctrl0); - ddx_1 = bld.vop2_dpp(aco_opcode::v_sub_f32, bld.def(v1), p1, tl_1, dpp_ctrl1); - ddy_1 = bld.vop2_dpp(aco_opcode::v_sub_f32, bld.def(v1), p1, tl_1, dpp_ctrl2); - Temp tl_2 = bld.vop1_dpp(aco_opcode::v_mov_b32, bld.def(v1), p2, dpp_ctrl0); - ddx_2 = bld.vop2_dpp(aco_opcode::v_sub_f32, bld.def(v1), p2, tl_2, dpp_ctrl1); - ddy_2 = bld.vop2_dpp(aco_opcode::v_sub_f32, bld.def(v1), p2, tl_2, dpp_ctrl2); - } else { - Temp tl_1 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p1, (1 << 15) | dpp_ctrl0); - ddx_1 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p1, (1 << 15) | dpp_ctrl1); - ddx_1 = bld.vop2(aco_opcode::v_sub_f32, bld.def(v1), ddx_1, tl_1); - ddy_1 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p1, (1 << 15) | dpp_ctrl2); - ddy_1 = bld.vop2(aco_opcode::v_sub_f32, bld.def(v1), ddy_1, tl_1); - - Temp tl_2 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p2, (1 << 15) | dpp_ctrl0); - ddx_2 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p2, (1 << 15) | dpp_ctrl1); - ddx_2 = bld.vop2(aco_opcode::v_sub_f32, bld.def(v1), ddx_2, tl_2); - ddy_2 = bld.ds(aco_opcode::ds_swizzle_b32, bld.def(v1), p2, (1 << 15) | dpp_ctrl2); - ddy_2 = bld.vop2(aco_opcode::v_sub_f32, bld.def(v1), ddy_2, tl_2); - } - - /* res_k = p_k + ddx_k * pos1 + ddy_k * pos2 */ - aco_opcode mad = - ctx->program->gfx_level >= GFX10_3 ? aco_opcode::v_fma_f32 : aco_opcode::v_mad_f32; - Temp tmp1 = bld.vop3(mad, bld.def(v1), ddx_1, pos1, p1); - Temp tmp2 = bld.vop3(mad, bld.def(v1), ddx_2, pos1, p2); - tmp1 = bld.vop3(mad, bld.def(v1), ddy_1, pos2, tmp1); - tmp2 = bld.vop3(mad, bld.def(v1), ddy_2, pos2, tmp2); - bld.pseudo(aco_opcode::p_create_vector, Definition(dst), tmp1, tmp2); - set_wqm(ctx, true); - return; -} - Temp merged_wave_info_to_mask(isel_context* ctx, unsigned i); Temp lanecount_to_mask(isel_context* ctx, Temp count, unsigned bit_offset); void pops_await_overlapped_waves(isel_context* ctx); @@ -8042,17 +7996,6 @@ visit_intrinsic(isel_context* ctx, nir_intrinsic_instr* instr) { Builder bld(ctx->program, ctx->block); switch (instr->intrinsic) { - case nir_intrinsic_load_barycentric_at_offset: { - Temp offset = get_ssa_temp(ctx, instr->src[0].ssa); - RegClass rc = RegClass(offset.type(), 1); - Temp pos1 = bld.tmp(rc), pos2 = bld.tmp(rc); - bld.pseudo(aco_opcode::p_split_vector, Definition(pos1), Definition(pos2), offset); - Temp bary = get_arg(ctx, nir_intrinsic_interp_mode(instr) == INTERP_MODE_NOPERSPECTIVE - ? ctx->args->linear_center - : ctx->args->persp_center); - emit_interp_center(ctx, get_ssa_temp(ctx, &instr->def), bary, pos1, pos2); - break; - } case nir_intrinsic_load_tess_coord: visit_load_tess_coord(ctx, instr); break; case nir_intrinsic_load_interpolated_input: visit_load_interpolated_input(ctx, instr); break; case nir_intrinsic_store_output: visit_store_output(ctx, instr); break; diff --git a/src/amd/compiler/aco_instruction_selection_setup.cpp b/src/amd/compiler/aco_instruction_selection_setup.cpp index acecb7eb266..e7d7928cdca 100644 --- a/src/amd/compiler/aco_instruction_selection_setup.cpp +++ b/src/amd/compiler/aco_instruction_selection_setup.cpp @@ -550,7 +550,6 @@ init_context(isel_context* ctx, nir_shader* shader) 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_barycentric_at_offset: case nir_intrinsic_load_interpolated_input: case nir_intrinsic_load_local_invocation_index: case nir_intrinsic_load_subgroup_invocation: diff --git a/src/amd/llvm/ac_llvm_build.c b/src/amd/llvm/ac_llvm_build.c index 0763cb3f4d8..1011d6b9923 100644 --- a/src/amd/llvm/ac_llvm_build.c +++ b/src/amd/llvm/ac_llvm_build.c @@ -3483,24 +3483,6 @@ LLVMValueRef ac_build_canonicalize(struct ac_llvm_context *ctx, LLVMValueRef src return ac_build_intrinsic(ctx, intr, type, params, 1, 0); } -/* - * this takes an I,J coordinate pair, - * and works out the X and Y derivatives. - * it returns DDX(I), DDX(J), DDY(I), DDY(J). - */ -LLVMValueRef ac_build_ddxy_interp(struct ac_llvm_context *ctx, LLVMValueRef interp_ij) -{ - LLVMValueRef result[4], a; - unsigned i; - - for (i = 0; i < 2; i++) { - a = LLVMBuildExtractElement(ctx->builder, interp_ij, LLVMConstInt(ctx->i32, i, false), ""); - result[i] = ac_build_ddxy(ctx, AC_TID_MASK_TOP_LEFT, 1, a); - result[2 + i] = ac_build_ddxy(ctx, AC_TID_MASK_TOP_LEFT, 2, a); - } - return ac_build_gather_values(ctx, result, 4); -} - LLVMValueRef ac_build_load_helper_invocation(struct ac_llvm_context *ctx) { LLVMValueRef result = ac_build_intrinsic(ctx, "llvm.amdgcn.live.mask", ctx->i1, NULL, 0, 0); diff --git a/src/amd/llvm/ac_llvm_build.h b/src/amd/llvm/ac_llvm_build.h index e62540a131b..818b749bfd9 100644 --- a/src/amd/llvm/ac_llvm_build.h +++ b/src/amd/llvm/ac_llvm_build.h @@ -459,8 +459,6 @@ LLVMValueRef ac_build_frexp_mant(struct ac_llvm_context *ctx, LLVMValueRef src0, LLVMValueRef ac_build_canonicalize(struct ac_llvm_context *ctx, LLVMValueRef src0, unsigned bitsize); -LLVMValueRef ac_build_ddxy_interp(struct ac_llvm_context *ctx, LLVMValueRef interp_ij); - LLVMValueRef ac_build_load_helper_invocation(struct ac_llvm_context *ctx); LLVMValueRef ac_build_call(struct ac_llvm_context *ctx, LLVMTypeRef fn_type, LLVMValueRef func, diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index ff734b712f0..b4ff9afcd65 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -2657,47 +2657,6 @@ static LLVMValueRef visit_var_atomic(struct ac_nir_context *ctx, const nir_intri return result; } -static LLVMValueRef barycentric_offset(struct ac_nir_context *ctx, unsigned mode, - LLVMValueRef offset) -{ - LLVMValueRef interp_param = mode == INTERP_MODE_NOPERSPECTIVE ? - ac_get_arg(&ctx->ac, ctx->args->linear_center) : - ac_get_arg(&ctx->ac, ctx->args->persp_center); - LLVMValueRef src_c0 = - ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder, offset, ctx->ac.i32_0, "")); - LLVMValueRef src_c1 = - ac_to_float(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder, offset, ctx->ac.i32_1, "")); - - LLVMValueRef ij_out[2]; - LLVMValueRef ddxy_out = ac_build_ddxy_interp(&ctx->ac, interp_param); - - /* - * take the I then J parameters, and the DDX/Y for it, and - * calculate the IJ inputs for the interpolator. - * temp1 = ddx * offset/sample.x + I; - * interp_param.I = ddy * offset/sample.y + temp1; - * temp1 = ddx * offset/sample.x + J; - * interp_param.J = ddy * offset/sample.y + temp1; - */ - for (unsigned i = 0; i < 2; i++) { - LLVMValueRef ix_ll = LLVMConstInt(ctx->ac.i32, i, false); - LLVMValueRef iy_ll = LLVMConstInt(ctx->ac.i32, i + 2, false); - LLVMValueRef ddx_el = LLVMBuildExtractElement(ctx->ac.builder, ddxy_out, ix_ll, ""); - LLVMValueRef ddy_el = LLVMBuildExtractElement(ctx->ac.builder, ddxy_out, iy_ll, ""); - LLVMValueRef interp_el = LLVMBuildExtractElement(ctx->ac.builder, interp_param, ix_ll, ""); - LLVMValueRef temp1, temp2; - - interp_el = LLVMBuildBitCast(ctx->ac.builder, interp_el, ctx->ac.f32, ""); - - temp1 = ac_build_fmad(&ctx->ac, ddx_el, src_c0, interp_el); - temp2 = ac_build_fmad(&ctx->ac, ddy_el, src_c1, temp1); - - ij_out[i] = LLVMBuildBitCast(ctx->ac.builder, temp2, ctx->ac.i32, ""); - } - interp_param = ac_build_gather_values(&ctx->ac, ij_out, 2); - return LLVMBuildBitCast(ctx->ac.builder, interp_param, ctx->ac.v2i32, ""); -} - static LLVMValueRef load_interpolated_input(struct ac_nir_context *ctx, LLVMValueRef interp_param, unsigned index, unsigned comp_start, unsigned num_components, unsigned bitsize, @@ -3010,11 +2969,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins result = visit_var_atomic(ctx, instr, ptr, 1); break; } - case nir_intrinsic_load_barycentric_at_offset: { - LLVMValueRef offset = ac_to_float(&ctx->ac, get_src(ctx, instr->src[0])); - result = barycentric_offset(ctx, nir_intrinsic_interp_mode(instr), offset); - break; - } case nir_intrinsic_load_interpolated_input: { /* We assume any indirect loads have been lowered away */ ASSERTED nir_const_value *offset = nir_src_as_const_value(instr->src[1]);