mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 04:48:08 +02:00
ir3: Fix infinite loop in scheduler when splitting
When we go to split e.g. a p0.x producer, the only other instructions ready to schedule are often only p0.x producers. It could happen that they all have a lower priority than the split instruction. Then we would immediately schedule the split instruction again, then again try to schedule one of the other producers, be blocked, and split it, around and around again, leading to an infinite loop. The following commit triggered this with dEQP-GLES3.functional.shaders.discard.dynamic_loop_always on a3xx. Fixes:d2f4d33("freedreno/ir3: new pre-RA scheduler") Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6752> (cherry picked from commitbb3212dd4d)
This commit is contained in:
parent
442df9d8f4
commit
43ade99dcc
2 changed files with 20 additions and 1 deletions
|
|
@ -1534,7 +1534,7 @@
|
|||
"description": "ir3: Fix infinite loop in scheduler when splitting",
|
||||
"nominated": true,
|
||||
"nomination_type": 1,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": "d2f4d332dbb552af62fe5caabe67664d98f32229"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ struct ir3_sched_ctx {
|
|||
struct ir3_instruction *addr1; /* current a1.x user, if any */
|
||||
struct ir3_instruction *pred; /* current p0.x user, if any */
|
||||
|
||||
struct ir3_instruction *split; /* most-recently-split a0/a1/p0 producer */
|
||||
|
||||
int remaining_kills;
|
||||
int remaining_tex;
|
||||
|
||||
|
|
@ -336,6 +338,13 @@ check_instr(struct ir3_sched_ctx *ctx, struct ir3_sched_notes *notes,
|
|||
{
|
||||
debug_assert(!is_scheduled(instr));
|
||||
|
||||
if (instr == ctx->split) {
|
||||
/* Don't schedule instructions created by splitting a a0.x/a1.x/p0.x
|
||||
* write until another "normal" instruction has been scheduled.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->remaining_kills && (is_tex(instr) || is_mem(instr))) {
|
||||
/* avoid texture/memory access if we have unscheduled kills
|
||||
* that could make the expensive operation unnecessary. By
|
||||
|
|
@ -1127,6 +1136,11 @@ sched_block(struct ir3_sched_ctx *ctx, struct ir3_block *block)
|
|||
}
|
||||
|
||||
schedule(ctx, instr);
|
||||
|
||||
/* Since we've scheduled a "real" instruction, we can now
|
||||
* schedule any split instruction created by the scheduler again.
|
||||
*/
|
||||
ctx->split = NULL;
|
||||
} else {
|
||||
struct ir3_instruction *new_instr = NULL;
|
||||
struct ir3 *ir = block->shader;
|
||||
|
|
@ -1157,6 +1171,11 @@ sched_block(struct ir3_sched_ctx *ctx, struct ir3_block *block)
|
|||
list_delinit(&new_instr->node);
|
||||
list_addtail(&new_instr->node, &ctx->unscheduled_list);
|
||||
}
|
||||
|
||||
/* If we produced a new instruction, do not schedule it next to
|
||||
* guarantee progress.
|
||||
*/
|
||||
ctx->split = new_instr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue