nir_variable_mode indirect_mask;
+ bool force_unroll_sampler_indirect;
} loop_info_state;
static nir_loop_variable *
*array_index_out = array_index;
nir_deref_instr *parent = nir_deref_instr_parent(d);
+
if (glsl_type_is_array_or_matrix(parent->type)) {
return glsl_get_length(parent->type);
} else {
}
static bool
-force_unroll_array_access(loop_info_state *state, nir_deref_instr *deref)
+force_unroll_array_access(loop_info_state *state, nir_deref_instr *deref,
+ bool contains_sampler)
{
unsigned array_size = find_array_access_via_induction(state, deref, NULL);
if (array_size) {
if (nir_deref_mode_must_be(deref, state->indirect_mask))
return true;
+
+ if (contains_sampler && state->force_unroll_sampler_indirect)
+ return true;
}
return false;
force_unroll_heuristics(loop_info_state *state, nir_block *block)
{
nir_foreach_instr(instr, block) {
+ if (instr->type == nir_instr_type_tex) {
+ nir_tex_instr *tex_instr = nir_instr_as_tex(instr);
+ int sampler_idx =
+ nir_tex_instr_src_index(tex_instr,
+ nir_tex_src_sampler_deref);
+
+
+ if (sampler_idx >= 0) {
+ nir_deref_instr *deref =
+ nir_instr_as_deref(tex_instr->src[sampler_idx].src.ssa->parent_instr);
+ if (force_unroll_array_access(state, deref, true))
+ return true;
+ }
+ }
+
+
if (instr->type != nir_instr_type_intrinsic)
continue;
intrin->intrinsic == nir_intrinsic_store_deref ||
intrin->intrinsic == nir_intrinsic_copy_deref) {
if (force_unroll_array_access(state,
- nir_src_as_deref(intrin->src[0])))
+ nir_src_as_deref(intrin->src[0]),
+ false))
return true;
if (intrin->intrinsic == nir_intrinsic_copy_deref &&
force_unroll_array_access(state,
- nir_src_as_deref(intrin->src[1])))
+ nir_src_as_deref(intrin->src[1]),
+ false))
return true;
}
}
}
static void
-process_loops(nir_cf_node *cf_node, nir_variable_mode indirect_mask)
+process_loops(nir_cf_node *cf_node, nir_variable_mode indirect_mask,
+ bool force_unroll_sampler_indirect)
{
switch (cf_node->type) {
case nir_cf_node_block:
case nir_cf_node_if: {
nir_if *if_stmt = nir_cf_node_as_if(cf_node);
foreach_list_typed(nir_cf_node, nested_node, node, &if_stmt->then_list)
- process_loops(nested_node, indirect_mask);
+ process_loops(nested_node, indirect_mask, force_unroll_sampler_indirect);
foreach_list_typed(nir_cf_node, nested_node, node, &if_stmt->else_list)
- process_loops(nested_node, indirect_mask);
+ process_loops(nested_node, indirect_mask, force_unroll_sampler_indirect);
return;
}
case nir_cf_node_loop: {
nir_loop *loop = nir_cf_node_as_loop(cf_node);
foreach_list_typed(nir_cf_node, nested_node, node, &loop->body)
- process_loops(nested_node, indirect_mask);
+ process_loops(nested_node, indirect_mask, force_unroll_sampler_indirect);
break;
}
default:
loop_info_state *state = initialize_loop_info_state(loop, mem_ctx, impl);
state->indirect_mask = indirect_mask;
+ state->force_unroll_sampler_indirect = force_unroll_sampler_indirect;
get_loop_info(state, impl);
void
nir_loop_analyze_impl(nir_function_impl *impl,
- nir_variable_mode indirect_mask)
+ nir_variable_mode indirect_mask,
+ bool force_unroll_sampler_indirect)
{
nir_index_ssa_defs(impl);
foreach_list_typed(nir_cf_node, node, node, &impl->body)
- process_loops(node, indirect_mask);
+ process_loops(node, indirect_mask, force_unroll_sampler_indirect);
}
static bool
nir_opt_loop_unroll_impl(nir_function_impl *impl,
- nir_variable_mode indirect_mask)
+ nir_variable_mode indirect_mask,
+ bool force_unroll_sampler_indirect)
{
bool progress = false;
- nir_metadata_require(impl, nir_metadata_loop_analysis, indirect_mask);
+ nir_metadata_require(impl, nir_metadata_loop_analysis, indirect_mask,
+ (int) force_unroll_sampler_indirect);
nir_metadata_require(impl, nir_metadata_block_index);
bool has_nested_loop = false;
{
bool progress = false;
+ bool force_unroll_sampler_indirect = shader->options->force_indirect_unrolling_sampler;
nir_variable_mode indirect_mask = shader->options->force_indirect_unrolling;
nir_foreach_function(function, shader) {
if (function->impl) {
- progress |= nir_opt_loop_unroll_impl(function->impl, indirect_mask);
+ progress |= nir_opt_loop_unroll_impl(function->impl, indirect_mask,
+ force_unroll_sampler_indirect);
}
}
return progress;