*/
indirect_mask |= nir_var_function_temp;
- progress |= nir_lower_indirect_derefs(nir, indirect_mask);
+ progress |= nir_lower_indirect_derefs(nir, indirect_mask, UINT32_MAX);
return progress;
}
bool nir_lower_array_deref_of_vec(nir_shader *shader, nir_variable_mode modes,
nir_lower_array_deref_of_vec_options options);
-bool nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes);
+bool nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes,
+ uint32_t max_lower_array_len);
bool nir_lower_locals_to_regs(nir_shader *shader);
static bool
lower_indirect_derefs_block(nir_block *block, nir_builder *b,
- nir_variable_mode modes)
+ nir_variable_mode modes,
+ uint32_t max_lower_array_len)
{
bool progress = false;
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
/* Walk the deref chain back to the base and look for indirects */
+ uint32_t indirect_array_len = 1;
bool has_indirect = false;
nir_deref_instr *base = deref;
while (base && base->deref_type != nir_deref_type_var) {
+ nir_deref_instr *parent = nir_deref_instr_parent(base);
if (base->deref_type == nir_deref_type_array &&
- !nir_src_is_const(base->arr.index))
+ !nir_src_is_const(base->arr.index)) {
+ indirect_array_len *= glsl_get_length(parent->type);
has_indirect = true;
+ }
- base = nir_deref_instr_parent(base);
+ base = parent;
}
- if (!has_indirect || !base)
+ if (!has_indirect || !base || indirect_array_len > max_lower_array_len)
continue;
/* Only lower variables whose mode is in the mask, or compact
}
static bool
-lower_indirects_impl(nir_function_impl *impl, nir_variable_mode modes)
+lower_indirects_impl(nir_function_impl *impl, nir_variable_mode modes,
+ uint32_t max_lower_array_len)
{
nir_builder builder;
nir_builder_init(&builder, impl);
bool progress = false;
nir_foreach_block_safe(block, impl) {
- progress |= lower_indirect_derefs_block(block, &builder, modes);
+ progress |= lower_indirect_derefs_block(block, &builder, modes,
+ max_lower_array_len);
}
if (progress)
* that does a binary search on the array index.
*/
bool
-nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes)
+nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes,
+ uint32_t max_lower_array_len)
{
bool progress = false;
nir_foreach_function(function, shader) {
- if (function->impl)
- progress = lower_indirects_impl(function->impl, modes) || progress;
+ if (function->impl) {
+ progress = lower_indirects_impl(function->impl, modes,
+ max_lower_array_len) || progress;
+ }
}
return progress;
* a global BO, they can be directly accessed via stg and ldg.
* nir_lower_indirect_derefs will instead generate a big if-ladder which
* isn't *incorrect* but is much less efficient. */
- NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out);
+ NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out, UINT32_MAX);
NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);
NIR_PASS_V(s, nir_lower_regs_to_ssa);
NIR_PASS_V(s, nir_lower_vars_to_ssa);
- NIR_PASS_V(s, nir_lower_indirect_derefs, nir_var_all);
+ NIR_PASS_V(s, nir_lower_indirect_derefs, nir_var_all, UINT32_MAX);
NIR_PASS_V(s, nir_lower_tex, &(struct nir_lower_tex_options) { .lower_txp = ~0u });
NIR_PASS_V(s, nir_lower_alu_to_scalar, etna_alu_to_scalar_filter_cb, specs);
OPT_V(s, nir_lower_regs_to_ssa);
OPT_V(s, nir_lower_vars_to_ssa);
- OPT_V(s, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out);
+ OPT_V(s, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out, UINT32_MAX);
if (lower) {
OPT_V(s, ir3_nir_apply_trig_workarounds);
nir_variable_mode indirect_mask =
brw_nir_no_indirect_mask(compiler, nir->info.stage);
- OPT(nir_lower_indirect_derefs, indirect_mask);
+ OPT(nir_lower_indirect_derefs, indirect_mask, UINT32_MAX);
/* Lower array derefs of vectors for SSBO and UBO loads. For both UBOs and
* SSBOs, our back-end is capable of loading an entire vec4 at a time and
* varyings we have demoted here.
*/
NIR_PASS_V(producer, nir_lower_indirect_derefs,
- brw_nir_no_indirect_mask(compiler, producer->info.stage));
+ brw_nir_no_indirect_mask(compiler, producer->info.stage),
+ UINT32_MAX);
NIR_PASS_V(consumer, nir_lower_indirect_derefs,
- brw_nir_no_indirect_mask(compiler, consumer->info.stage));
+ brw_nir_no_indirect_mask(compiler, consumer->info.stage),
+ UINT32_MAX);
brw_nir_optimize(producer, compiler, p_is_scalar, false);
brw_nir_optimize(consumer, compiler, c_is_scalar, false);