aboutsummaryrefslogtreecommitdiffstats
path: root/src/panfrost
diff options
context:
space:
mode:
Diffstat (limited to 'src/panfrost')
-rw-r--r--src/panfrost/midgard/compiler.h2
-rw-r--r--src/panfrost/midgard/midgard_helper_invocations.c87
-rw-r--r--src/panfrost/midgard/midgard_print.c3
-rw-r--r--src/panfrost/util/pan_ir.h7
-rw-r--r--src/panfrost/util/pan_liveness.c8
5 files changed, 99 insertions, 8 deletions
diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h
index 6db0cfea466..bf125369fde 100644
--- a/src/panfrost/midgard/compiler.h
+++ b/src/panfrost/midgard/compiler.h
@@ -107,6 +107,7 @@ typedef struct midgard_instruction {
/* For textures: should helpers execute this instruction (instead of
* just helping with derivatives)? Should helpers terminate after? */
bool helper_terminate;
+ bool helper_execute;
/* I.e. (1 << alu_bit) */
int unit;
@@ -634,6 +635,7 @@ midgard_lower_derivatives(compiler_context *ctx, midgard_block *block);
bool mir_op_computes_derivatives(gl_shader_stage stage, unsigned op);
void mir_analyze_helper_terminate(compiler_context *ctx);
+void mir_analyze_helper_requirements(compiler_context *ctx);
/* Final emission */
diff --git a/src/panfrost/midgard/midgard_helper_invocations.c b/src/panfrost/midgard/midgard_helper_invocations.c
index 9f8c68a8125..6dfb9c09973 100644
--- a/src/panfrost/midgard/midgard_helper_invocations.c
+++ b/src/panfrost/midgard/midgard_helper_invocations.c
@@ -158,3 +158,90 @@ mir_analyze_helper_terminate(compiler_context *ctx)
}
}
}
+
+static bool
+mir_helper_block_update(BITSET_WORD *deps, pan_block *_block, unsigned temp_count)
+{
+ bool progress = false;
+ midgard_block *block = (midgard_block *) _block;
+
+ mir_foreach_instr_in_block_rev(block, ins) {
+ /* Ensure we write to a helper dependency */
+ if (ins->dest >= temp_count || !BITSET_TEST(deps, ins->dest))
+ continue;
+
+ /* Then add all of our dependencies */
+ mir_foreach_src(ins, s) {
+ if (ins->src[s] >= temp_count)
+ continue;
+
+ /* Progress if the dependency set changes */
+ progress |= !BITSET_TEST(deps, ins->src[s]);
+ BITSET_SET(deps, ins->src[s]);
+ }
+ }
+
+ return progress;
+}
+
+void
+mir_analyze_helper_requirements(compiler_context *ctx)
+{
+ mir_compute_temp_count(ctx);
+ unsigned temp_count = ctx->temp_count;
+ BITSET_WORD *deps = calloc(sizeof(BITSET_WORD), BITSET_WORDS(temp_count));
+
+ /* Initialize with the sources of instructions consuming
+ * derivatives */
+
+ mir_foreach_instr_global(ctx, ins) {
+ if (ins->type != TAG_TEXTURE_4) continue;
+ if (ins->dest >= ctx->temp_count) continue;
+ if (!mir_op_computes_derivatives(ctx->stage, ins->texture.op)) continue;
+
+ mir_foreach_src(ins, s) {
+ if (ins->src[s] < temp_count)
+ BITSET_SET(deps, ins->src[s]);
+ }
+ }
+
+ /* Propagate that up */
+
+ struct set *work_list = _mesa_set_create(NULL,
+ _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+
+ struct set *visited = _mesa_set_create(NULL,
+ _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+
+ struct set_entry *cur = _mesa_set_add(work_list, pan_exit_block(&ctx->blocks));
+
+ do {
+ pan_block *blk = (struct pan_block *) cur->key;
+ _mesa_set_remove(work_list, cur);
+
+ bool progress = mir_helper_block_update(deps, blk, temp_count);
+
+ if (progress || !_mesa_set_search(visited, blk)) {
+ pan_foreach_predecessor(blk, pred)
+ _mesa_set_add(work_list, pred);
+ }
+
+ _mesa_set_add(visited, blk);
+ } while((cur = _mesa_set_next_entry(work_list, NULL)) != NULL);
+
+ _mesa_set_destroy(visited, NULL);
+ _mesa_set_destroy(work_list, NULL);
+
+ /* Set the execute bits */
+
+ mir_foreach_instr_global(ctx, ins) {
+ if (ins->type != TAG_TEXTURE_4) continue;
+ if (ins->dest >= ctx->temp_count) continue;
+
+ ins->helper_execute = BITSET_TEST(deps, ins->dest);
+ }
+
+ free(deps);
+}
diff --git a/src/panfrost/midgard/midgard_print.c b/src/panfrost/midgard/midgard_print.c
index 002026a16b5..1b1ff6a145f 100644
--- a/src/panfrost/midgard/midgard_print.c
+++ b/src/panfrost/midgard/midgard_print.c
@@ -332,6 +332,9 @@ mir_print_instruction(midgard_instruction *ins)
if (ins->helper_terminate)
printf(".terminate");
+ if (ins->helper_execute)
+ printf(".execute");
+
break;
}
diff --git a/src/panfrost/util/pan_ir.h b/src/panfrost/util/pan_ir.h
index c57a8e01c34..a45478ae6ec 100644
--- a/src/panfrost/util/pan_ir.h
+++ b/src/panfrost/util/pan_ir.h
@@ -160,6 +160,13 @@ struct pan_instruction {
_entry_##v = _mesa_set_next_entry(blk->predecessors, _entry_##v), \
v = (struct pan_block *) (_entry_##v ? _entry_##v->key : NULL))
+static inline pan_block *
+pan_exit_block(struct list_head *blocks)
+{
+ pan_block *last = list_last_entry(blocks, pan_block, link);
+ assert(!last->successors[0] && !last->successors[1]);
+ return last;
+}
typedef void (*pan_liveness_update)(uint16_t *, void *, unsigned max);
diff --git a/src/panfrost/util/pan_liveness.c b/src/panfrost/util/pan_liveness.c
index a46a11d9d3c..9772feb1a9c 100644
--- a/src/panfrost/util/pan_liveness.c
+++ b/src/panfrost/util/pan_liveness.c
@@ -104,14 +104,6 @@ liveness_block_update(
* adding the predecessors of the block to the work list if we made progress.
*/
-static inline pan_block *
-pan_exit_block(struct list_head *blocks)
-{
- pan_block *last = list_last_entry(blocks, pan_block, link);
- assert(!last->successors[0] && !last->successors[1]);
- return last;
-}
-
void
pan_compute_liveness(
struct list_head *blocks,