From adb17a8609b5397aeb304a4309d7c541fda6e481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 25 Jun 2025 18:49:03 -0400 Subject: [PATCH] nir: move nir_recompute_io_bases into its own file Acked-by: Alyssa Rosenzweig Part-of: --- src/compiler/nir/meson.build | 1 + src/compiler/nir/nir.h | 2 + src/compiler/nir/nir_lower_mediump.c | 134 +----------------- src/compiler/nir/nir_recompute_io_bases.c | 157 ++++++++++++++++++++++ 4 files changed, 161 insertions(+), 133 deletions(-) create mode 100644 src/compiler/nir/nir_recompute_io_bases.c diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index 76defa573f3..d6a9e89ac70 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -306,6 +306,7 @@ else 'nir_propagate_invariant.c', 'nir_range_analysis.c', 'nir_range_analysis.h', + 'nir_recompute_io_bases.c', 'nir_remove_dead_variables.c', 'nir_remove_tex_shadow.c', 'nir_repair_ssa.c', diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 248246c3138..d953e35e9c9 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5886,6 +5886,8 @@ bool nir_lower_doubles(nir_shader *shader, const nir_shader *softfp64, nir_lower_doubles_options options); bool nir_lower_pack(nir_shader *shader); +nir_intrinsic_instr *nir_get_io_intrinsic(nir_instr *instr, nir_variable_mode modes, + nir_variable_mode *out_mode); bool nir_recompute_io_bases(nir_shader *nir, nir_variable_mode modes); bool nir_lower_mediump_vars(nir_shader *nir, nir_variable_mode modes); bool nir_lower_mediump_io(nir_shader *nir, nir_variable_mode modes, diff --git a/src/compiler/nir/nir_lower_mediump.c b/src/compiler/nir/nir_lower_mediump.c index 546194a6ae9..043388b185e 100644 --- a/src/compiler/nir/nir_lower_mediump.c +++ b/src/compiler/nir/nir_lower_mediump.c @@ -25,138 +25,6 @@ #include "nir.h" #include "nir_builder.h" -/** - * Return the intrinsic if it matches the mask in "modes", else return NULL. - */ -static nir_intrinsic_instr * -get_io_intrinsic(nir_instr *instr, nir_variable_mode modes, - nir_variable_mode *out_mode) -{ - if (instr->type != nir_instr_type_intrinsic) - return NULL; - - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - - switch (intr->intrinsic) { - case nir_intrinsic_load_input: - case nir_intrinsic_load_per_primitive_input: - case nir_intrinsic_load_input_vertex: - case nir_intrinsic_load_interpolated_input: - case nir_intrinsic_load_per_vertex_input: - *out_mode = nir_var_shader_in; - return modes & nir_var_shader_in ? intr : NULL; - case nir_intrinsic_load_output: - case nir_intrinsic_load_per_vertex_output: - case nir_intrinsic_load_per_view_output: - case nir_intrinsic_store_output: - case nir_intrinsic_store_per_vertex_output: - case nir_intrinsic_store_per_view_output: - *out_mode = nir_var_shader_out; - return modes & nir_var_shader_out ? intr : NULL; - default: - return NULL; - } -} - -/** - * Recompute the IO "base" indices from scratch to remove holes or to fix - * incorrect base values due to changes in IO locations by using IO locations - * to assign new bases. The mapping from locations to bases becomes - * monotonically increasing. - */ -bool -nir_recompute_io_bases(nir_shader *nir, nir_variable_mode modes) -{ - nir_function_impl *impl = nir_shader_get_entrypoint(nir); - - BITSET_DECLARE(inputs, NUM_TOTAL_VARYING_SLOTS); - BITSET_DECLARE(per_prim_inputs, NUM_TOTAL_VARYING_SLOTS); /* FS only */ - BITSET_DECLARE(dual_slot_inputs, NUM_TOTAL_VARYING_SLOTS); /* VS only */ - BITSET_DECLARE(outputs, NUM_TOTAL_VARYING_SLOTS); - BITSET_ZERO(inputs); - BITSET_ZERO(per_prim_inputs); - BITSET_ZERO(dual_slot_inputs); - BITSET_ZERO(outputs); - - /* Gather the bitmasks of used locations. */ - nir_foreach_block_safe(block, impl) { - nir_foreach_instr_safe(instr, block) { - nir_variable_mode mode; - nir_intrinsic_instr *intr = get_io_intrinsic(instr, modes, &mode); - if (!intr) - continue; - - nir_io_semantics sem = nir_intrinsic_io_semantics(intr); - unsigned num_slots = sem.num_slots; - if (sem.medium_precision) - num_slots = (num_slots + sem.high_16bits + 1) / 2; - - if (mode == nir_var_shader_in) { - for (unsigned i = 0; i < num_slots; i++) { - if (intr->intrinsic == nir_intrinsic_load_per_primitive_input) - BITSET_SET(per_prim_inputs, sem.location + i); - else - BITSET_SET(inputs, sem.location + i); - - if (sem.high_dvec2) - BITSET_SET(dual_slot_inputs, sem.location + i); - } - } else if (!sem.dual_source_blend_index) { - for (unsigned i = 0; i < num_slots; i++) - BITSET_SET(outputs, sem.location + i); - } - } - } - - const unsigned num_normal_inputs = BITSET_COUNT(inputs) + BITSET_COUNT(dual_slot_inputs); - - /* Renumber bases. */ - bool changed = false; - - nir_foreach_block_safe(block, impl) { - nir_foreach_instr_safe(instr, block) { - nir_variable_mode mode; - nir_intrinsic_instr *intr = get_io_intrinsic(instr, modes, &mode); - if (!intr) - continue; - - nir_io_semantics sem = nir_intrinsic_io_semantics(intr); - unsigned num_slots = sem.num_slots; - if (sem.medium_precision) - num_slots = (num_slots + sem.high_16bits + 1) / 2; - - if (mode == nir_var_shader_in) { - if (intr->intrinsic == nir_intrinsic_load_per_primitive_input) { - nir_intrinsic_set_base(intr, - num_normal_inputs + - BITSET_PREFIX_SUM(per_prim_inputs, sem.location)); - } else { - nir_intrinsic_set_base(intr, - BITSET_PREFIX_SUM(inputs, sem.location) + - BITSET_PREFIX_SUM(dual_slot_inputs, sem.location) + - (sem.high_dvec2 ? 1 : 0)); - } - } else if (sem.dual_source_blend_index) { - nir_intrinsic_set_base(intr, - BITSET_PREFIX_SUM(outputs, NUM_TOTAL_VARYING_SLOTS)); - } else { - nir_intrinsic_set_base(intr, - BITSET_PREFIX_SUM(outputs, sem.location)); - } - changed = true; - } - } - - nir_progress(changed, impl, nir_metadata_control_flow); - - if (modes & nir_var_shader_in) - nir->num_inputs = BITSET_COUNT(inputs); - if (modes & nir_var_shader_out) - nir->num_outputs = BITSET_COUNT(outputs); - - return changed; -} - /** * Lower mediump inputs and/or outputs to 16 bits. * @@ -178,7 +46,7 @@ nir_lower_mediump_io(nir_shader *nir, nir_variable_mode modes, nir_foreach_block_safe(block, impl) { nir_foreach_instr_safe(instr, block) { nir_variable_mode mode; - nir_intrinsic_instr *intr = get_io_intrinsic(instr, modes, &mode); + nir_intrinsic_instr *intr = nir_get_io_intrinsic(instr, modes, &mode); if (!intr) continue; diff --git a/src/compiler/nir/nir_recompute_io_bases.c b/src/compiler/nir/nir_recompute_io_bases.c new file mode 100644 index 00000000000..1b6f81f7647 --- /dev/null +++ b/src/compiler/nir/nir_recompute_io_bases.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2020 Google, Inc. + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "nir.h" + +/** + * Return the intrinsic if it matches the mask in "modes", else return NULL. + */ +nir_intrinsic_instr * +nir_get_io_intrinsic(nir_instr *instr, nir_variable_mode modes, + nir_variable_mode *out_mode) +{ + if (instr->type != nir_instr_type_intrinsic) + return NULL; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + switch (intr->intrinsic) { + case nir_intrinsic_load_input: + case nir_intrinsic_load_per_primitive_input: + case nir_intrinsic_load_input_vertex: + case nir_intrinsic_load_interpolated_input: + case nir_intrinsic_load_per_vertex_input: + *out_mode = nir_var_shader_in; + return modes & nir_var_shader_in ? intr : NULL; + case nir_intrinsic_load_output: + case nir_intrinsic_load_per_vertex_output: + case nir_intrinsic_load_per_view_output: + case nir_intrinsic_store_output: + case nir_intrinsic_store_per_vertex_output: + case nir_intrinsic_store_per_view_output: + *out_mode = nir_var_shader_out; + return modes & nir_var_shader_out ? intr : NULL; + default: + return NULL; + } +} + +/** + * Recompute the IO "base" indices from scratch to remove holes or to fix + * incorrect base values due to changes in IO locations by using IO locations + * to assign new bases. The mapping from locations to bases becomes + * monotonically increasing. + */ +bool +nir_recompute_io_bases(nir_shader *nir, nir_variable_mode modes) +{ + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + + BITSET_DECLARE(inputs, NUM_TOTAL_VARYING_SLOTS); + BITSET_DECLARE(per_prim_inputs, NUM_TOTAL_VARYING_SLOTS); /* FS only */ + BITSET_DECLARE(dual_slot_inputs, NUM_TOTAL_VARYING_SLOTS); /* VS only */ + BITSET_DECLARE(outputs, NUM_TOTAL_VARYING_SLOTS); + BITSET_ZERO(inputs); + BITSET_ZERO(per_prim_inputs); + BITSET_ZERO(dual_slot_inputs); + BITSET_ZERO(outputs); + + /* Gather the bitmasks of used locations. */ + nir_foreach_block_safe(block, impl) { + nir_foreach_instr_safe(instr, block) { + nir_variable_mode mode; + nir_intrinsic_instr *intr = nir_get_io_intrinsic(instr, modes, &mode); + if (!intr) + continue; + + nir_io_semantics sem = nir_intrinsic_io_semantics(intr); + unsigned num_slots = sem.num_slots; + if (sem.medium_precision) + num_slots = (num_slots + sem.high_16bits + 1) / 2; + + if (mode == nir_var_shader_in) { + for (unsigned i = 0; i < num_slots; i++) { + if (intr->intrinsic == nir_intrinsic_load_per_primitive_input) + BITSET_SET(per_prim_inputs, sem.location + i); + else + BITSET_SET(inputs, sem.location + i); + + if (sem.high_dvec2) + BITSET_SET(dual_slot_inputs, sem.location + i); + } + } else if (!sem.dual_source_blend_index) { + for (unsigned i = 0; i < num_slots; i++) + BITSET_SET(outputs, sem.location + i); + } + } + } + + const unsigned num_normal_inputs = BITSET_COUNT(inputs) + BITSET_COUNT(dual_slot_inputs); + + /* Renumber bases. */ + bool changed = false; + + nir_foreach_block_safe(block, impl) { + nir_foreach_instr_safe(instr, block) { + nir_variable_mode mode; + nir_intrinsic_instr *intr = nir_get_io_intrinsic(instr, modes, &mode); + if (!intr) + continue; + + nir_io_semantics sem = nir_intrinsic_io_semantics(intr); + unsigned num_slots = sem.num_slots; + if (sem.medium_precision) + num_slots = (num_slots + sem.high_16bits + 1) / 2; + + if (mode == nir_var_shader_in) { + if (intr->intrinsic == nir_intrinsic_load_per_primitive_input) { + nir_intrinsic_set_base(intr, + num_normal_inputs + + BITSET_PREFIX_SUM(per_prim_inputs, sem.location)); + } else { + nir_intrinsic_set_base(intr, + BITSET_PREFIX_SUM(inputs, sem.location) + + BITSET_PREFIX_SUM(dual_slot_inputs, sem.location) + + (sem.high_dvec2 ? 1 : 0)); + } + } else if (sem.dual_source_blend_index) { + nir_intrinsic_set_base(intr, + BITSET_PREFIX_SUM(outputs, NUM_TOTAL_VARYING_SLOTS)); + } else { + nir_intrinsic_set_base(intr, + BITSET_PREFIX_SUM(outputs, sem.location)); + } + changed = true; + } + } + + nir_progress(changed, impl, nir_metadata_control_flow); + + if (modes & nir_var_shader_in) + nir->num_inputs = BITSET_COUNT(inputs); + if (modes & nir_var_shader_out) + nir->num_outputs = BITSET_COUNT(outputs); + + return changed; +}