summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/freedreno/ir3/ir3_sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3_sched.c')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_sched.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
index 24d7c6397c1..b2ef8111f56 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
@@ -242,6 +242,32 @@ static int trysched(struct ir3_sched_ctx *ctx,
if (delay)
return delay;
+ /* if the instruction is a kill, we need to ensure *every*
+ * bary.f is scheduled. The hw seems unhappy if the thread
+ * gets killed before the end-input (ei) flag is hit.
+ *
+ * We could do this by adding each bary.f instruction as
+ * virtual ssa src for the kill instruction. But we have
+ * fixed length instr->regs[].
+ *
+ * TODO this wouldn't be quite right if we had multiple
+ * basic blocks, if any block was conditional. We'd need
+ * to schedule the bary.f's outside of any block which
+ * was conditional that contained a kill.. I think..
+ */
+ if (is_kill(instr)) {
+ struct ir3 *ir = instr->block->shader;
+ unsigned i;
+
+ for (i = 0; i < ir->baryfs_count; i++) {
+ if (ir->baryfs[i]->depth == DEPTH_UNUSED)
+ continue;
+ delay = trysched(ctx, ir->baryfs[i]);
+ if (delay)
+ return delay;
+ }
+ }
+
/* if this is a write to address/predicate register, and that
* register is currently in use, we need to defer until it is
* free: