From 79df320463afed192a70a8572b8db13a5e8ad4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timur=20Krist=C3=B3f?= Date: Wed, 15 May 2024 03:31:32 +0200 Subject: [PATCH] ac/nir: Move varying cost functions from radeonsi to common code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code will be shared between RADV and RadeonSI. Signed-off-by: Timur Kristóf Reviewed-by: Georg Lehmann Reviewed-by: Samuel Pitoiset Part-of: --- src/amd/common/ac_nir.c | 126 ++++++++++++++++++++++++++ src/amd/common/ac_nir.h | 6 ++ src/gallium/drivers/radeonsi/si_get.c | 121 +------------------------ 3 files changed, 135 insertions(+), 118 deletions(-) diff --git a/src/amd/common/ac_nir.c b/src/amd/common/ac_nir.c index 7a28128c0a4..0afe9d43b80 100644 --- a/src/amd/common/ac_nir.c +++ b/src/amd/common/ac_nir.c @@ -1580,3 +1580,129 @@ ac_get_global_ids(nir_builder *b, unsigned num_components, unsigned bit_size) return nir_iadd(b, nir_imul(b, block_ids, block_size), local_ids); } + +unsigned +ac_nir_varying_expression_max_cost(nir_shader *producer, nir_shader *consumer) +{ + switch (consumer->info.stage) { + case MESA_SHADER_TESS_CTRL: + /* VS->TCS + * Non-amplifying shaders can always have their varying expressions + * moved into later shaders. + */ + return UINT_MAX; + + case MESA_SHADER_GEOMETRY: + /* VS->GS, TES->GS */ + return consumer->info.gs.vertices_in == 1 ? UINT_MAX : + consumer->info.gs.vertices_in == 2 ? 20 : 14; + + case MESA_SHADER_TESS_EVAL: + /* TCS->TES and VS->TES (OpenGL only) */ + case MESA_SHADER_FRAGMENT: + /* Up to 3 uniforms and 5 ALUs. */ + return 14; + + default: + unreachable("unexpected shader stage"); + } +} + +unsigned +ac_nir_varying_estimate_instr_cost(nir_instr *instr) +{ + unsigned dst_bit_size, src_bit_size, num_dst_dwords; + nir_op alu_op; + + /* This is a very loose approximation based on gfx10. */ + switch (instr->type) { + case nir_instr_type_alu: + dst_bit_size = nir_instr_as_alu(instr)->def.bit_size; + src_bit_size = nir_instr_as_alu(instr)->src[0].src.ssa->bit_size; + alu_op = nir_instr_as_alu(instr)->op; + num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32); + + switch (alu_op) { + case nir_op_mov: + case nir_op_vec2: + case nir_op_vec3: + case nir_op_vec4: + case nir_op_vec5: + case nir_op_vec8: + case nir_op_vec16: + case nir_op_fabs: + case nir_op_fneg: + case nir_op_fsat: + return 0; + + case nir_op_imul: + case nir_op_umul_low: + return dst_bit_size <= 16 ? 1 : 4 * num_dst_dwords; + + case nir_op_imul_high: + case nir_op_umul_high: + case nir_op_imul_2x32_64: + case nir_op_umul_2x32_64: + return 4; + + case nir_op_fexp2: + case nir_op_flog2: + case nir_op_frcp: + case nir_op_frsq: + case nir_op_fsqrt: + case nir_op_fsin: + case nir_op_fcos: + case nir_op_fsin_amd: + case nir_op_fcos_amd: + return 4; /* FP16 & FP32. */ + + case nir_op_fpow: + return 4 + 1 + 4; /* log2 + mul + exp2 */ + + case nir_op_fsign: + return dst_bit_size == 64 ? 4 : 3; /* See ac_build_fsign. */ + + case nir_op_idiv: + case nir_op_udiv: + case nir_op_imod: + case nir_op_umod: + case nir_op_irem: + return dst_bit_size == 64 ? 80 : 40; + + case nir_op_fdiv: + return dst_bit_size == 64 ? 80 : 5; /* FP16 & FP32: rcp + mul */ + + case nir_op_fmod: + case nir_op_frem: + return dst_bit_size == 64 ? 80 : 8; + + default: + /* Double opcodes. Comparisons have always full performance. */ + if ((dst_bit_size == 64 && + nir_op_infos[alu_op].output_type & nir_type_float) || + (dst_bit_size >= 8 && src_bit_size == 64 && + nir_op_infos[alu_op].input_types[0] & nir_type_float)) + return 16; + + return DIV_ROUND_UP(MAX2(dst_bit_size, src_bit_size), 32); + } + + case nir_instr_type_intrinsic: + dst_bit_size = nir_instr_as_intrinsic(instr)->def.bit_size; + num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32); + + switch (nir_instr_as_intrinsic(instr)->intrinsic) { + case nir_intrinsic_load_deref: + /* Uniform or UBO load. + * Set a low cost to balance the number of scalar loads and ALUs. + */ + return 3 * num_dst_dwords; + + default: + unreachable("unexpected intrinsic"); + } + + default: + unreachable("unexpected instr type"); + } +} diff --git a/src/amd/common/ac_nir.h b/src/amd/common/ac_nir.h index fee0b71de35..ab6ff6d6c5f 100644 --- a/src/amd/common/ac_nir.h +++ b/src/amd/common/ac_nir.h @@ -314,6 +314,12 @@ ac_nir_store_debug_log_amd(nir_builder *b, nir_def *uvec4); bool ac_nir_opt_pack_half(nir_shader *shader, enum amd_gfx_level gfx_level); +unsigned +ac_nir_varying_expression_max_cost(nir_shader *producer, nir_shader *consumer); + +unsigned +ac_nir_varying_estimate_instr_cost(nir_instr *instr); + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index be34a7d8f15..cb5c9b61367 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -5,6 +5,7 @@ */ #include "compiler/nir/nir.h" +#include "ac_nir.h" #include "ac_shader_util.h" #include "radeon_uvd_enc.h" #include "radeon_vce.h" @@ -1460,123 +1461,7 @@ static unsigned si_varying_expression_max_cost(nir_shader *producer, nir_shader } } - switch (consumer->info.stage) { - case MESA_SHADER_TESS_CTRL: /* VS->TCS */ - /* Non-amplifying shaders can always have their variyng expressions - * moved into later shaders. - */ - return UINT_MAX; - - case MESA_SHADER_GEOMETRY: /* VS->GS, TES->GS */ - return consumer->info.gs.vertices_in == 1 ? UINT_MAX : - consumer->info.gs.vertices_in == 2 ? 20 : 14; - - case MESA_SHADER_TESS_EVAL: /* VS->TES, TCS->TES */ - case MESA_SHADER_FRAGMENT: - /* Up to 3 uniforms and 5 ALUs. */ - return 14; - - default: - unreachable("unexpected shader stage"); - } -} - -static unsigned si_varying_estimate_instr_cost(nir_instr *instr) -{ - unsigned dst_bit_size, src_bit_size, num_dst_dwords; - nir_op alu_op; - - /* This is a very loose approximation based on gfx10. */ - switch (instr->type) { - case nir_instr_type_alu: - dst_bit_size = nir_instr_as_alu(instr)->def.bit_size; - src_bit_size = nir_instr_as_alu(instr)->src[0].src.ssa->bit_size; - alu_op = nir_instr_as_alu(instr)->op; - num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32); - - switch (alu_op) { - case nir_op_mov: - case nir_op_vec2: - case nir_op_vec3: - case nir_op_vec4: - case nir_op_vec5: - case nir_op_vec8: - case nir_op_vec16: - case nir_op_fabs: - case nir_op_fneg: - case nir_op_fsat: - return 0; - - case nir_op_imul: - case nir_op_umul_low: - return dst_bit_size <= 16 ? 1 : 4 * num_dst_dwords; - - case nir_op_imul_high: - case nir_op_umul_high: - case nir_op_imul_2x32_64: - case nir_op_umul_2x32_64: - return 4; - - case nir_op_fexp2: - case nir_op_flog2: - case nir_op_frcp: - case nir_op_frsq: - case nir_op_fsqrt: - case nir_op_fsin: - case nir_op_fcos: - case nir_op_fsin_amd: - case nir_op_fcos_amd: - return 4; /* FP16 & FP32. */ - - case nir_op_fpow: - return 4 + 1 + 4; /* log2 + mul + exp2 */ - - case nir_op_fsign: - return dst_bit_size == 64 ? 4 : 3; /* See ac_build_fsign. */ - - case nir_op_idiv: - case nir_op_udiv: - case nir_op_imod: - case nir_op_umod: - case nir_op_irem: - return dst_bit_size == 64 ? 80 : 40; - - case nir_op_fdiv: - return dst_bit_size == 64 ? 80 : 5; /* FP16 & FP32: rcp + mul */ - - case nir_op_fmod: - case nir_op_frem: - return dst_bit_size == 64 ? 80 : 8; - - default: - /* Double opcodes. Comparisons have always full performance. */ - if ((dst_bit_size == 64 && - nir_op_infos[alu_op].output_type & nir_type_float) || - (dst_bit_size >= 8 && src_bit_size == 64 && - nir_op_infos[alu_op].input_types[0] & nir_type_float)) - return 16; - - return DIV_ROUND_UP(MAX2(dst_bit_size, src_bit_size), 32); - } - - case nir_instr_type_intrinsic: - dst_bit_size = nir_instr_as_intrinsic(instr)->def.bit_size; - num_dst_dwords = DIV_ROUND_UP(dst_bit_size, 32); - - switch (nir_instr_as_intrinsic(instr)->intrinsic) { - case nir_intrinsic_load_deref: - /* Uniform or UBO load. - * Set a low cost to balance the number of scalar loads and ALUs. - */ - return 3 * num_dst_dwords; - - default: - unreachable("unexpected intrinsic"); - } - - default: - unreachable("unexpected instr type"); - } + return ac_nir_varying_expression_max_cost(producer, consumer); } @@ -1696,5 +1581,5 @@ void si_init_screen_get_functions(struct si_screen *sscreen) BITFIELD_BIT(MESA_SHADER_TESS_EVAL); options->support_indirect_outputs = BITFIELD_BIT(MESA_SHADER_TESS_CTRL); options->varying_expression_max_cost = si_varying_expression_max_cost; - options->varying_estimate_instr_cost = si_varying_estimate_instr_cost; + options->varying_estimate_instr_cost = ac_nir_varying_estimate_instr_cost; }