nir/schedule: Add an option for a fallback scheduling algorithm
The current scheduling algorithm favors parallelism a bit too aggressively and sometimes generates shaders that fail register allocation. This happens even if the threshold is set to zero to force it to always use the CSR instruction choosing algorithm. This patch adds an option to use an even more aggressive fallback that just always picks the instruction with the shortest maximum delay in the hope that that will generate the least register pressure. The intention is to use this as a last resort after register allocation fails in order to at least have a working shader. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Acked-by: Iago Toral Quiroga <itoral@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5953>
This commit is contained in:
@@ -583,6 +583,50 @@ nir_schedule_regs_freed(nir_schedule_scoreboard *scoreboard, nir_schedule_node *
|
||||
return state.regs_freed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses an instruction that will minimise the register pressure as much as
|
||||
* possible. This should only be used as a fallback when the regular scheduling
|
||||
* generates a shader whose register allocation fails.
|
||||
*/
|
||||
static nir_schedule_node *
|
||||
nir_schedule_choose_instruction_fallback(nir_schedule_scoreboard *scoreboard)
|
||||
{
|
||||
nir_schedule_node *chosen = NULL;
|
||||
|
||||
/* Find the leader in the ready (shouldn't-stall) set with the mininum
|
||||
* cost.
|
||||
*/
|
||||
list_for_each_entry(nir_schedule_node, n, &scoreboard->dag->heads, dag.link) {
|
||||
if (scoreboard->time < n->ready_time)
|
||||
continue;
|
||||
|
||||
if (!chosen || chosen->max_delay > n->max_delay)
|
||||
chosen = n;
|
||||
}
|
||||
if (chosen) {
|
||||
if (debug) {
|
||||
fprintf(stderr, "chose (ready fallback): ");
|
||||
nir_print_instr(chosen->instr, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/* Otherwise, choose the leader with the minimum cost. */
|
||||
list_for_each_entry(nir_schedule_node, n, &scoreboard->dag->heads, dag.link) {
|
||||
if (!chosen || chosen->max_delay > n->max_delay)
|
||||
chosen = n;
|
||||
}
|
||||
if (debug) {
|
||||
fprintf(stderr, "chose (leader fallback): ");
|
||||
nir_print_instr(chosen->instr, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses an instruction to schedule using the Goodman/Hsu (1988) CSP (Code
|
||||
* Scheduling for Parallelism) heuristic.
|
||||
@@ -913,7 +957,9 @@ nir_schedule_instructions(nir_schedule_scoreboard *scoreboard, nir_block *block)
|
||||
}
|
||||
|
||||
nir_schedule_node *chosen;
|
||||
if (scoreboard->pressure < scoreboard->options->threshold)
|
||||
if (scoreboard->options->fallback)
|
||||
chosen = nir_schedule_choose_instruction_fallback(scoreboard);
|
||||
else if (scoreboard->pressure < scoreboard->options->threshold)
|
||||
chosen = nir_schedule_choose_instruction_csp(scoreboard);
|
||||
else
|
||||
chosen = nir_schedule_choose_instruction_csr(scoreboard);
|
||||
|
||||
Reference in New Issue
Block a user