Mesa (master): pan/mdg: Analyze helper invocation termination

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue May 12 22:54:14 UTC 2020


Module: Mesa
Branch: master
Commit: 3228b3106a672e79093f2186f3e040a7579cd7b4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3228b3106a672e79093f2186f3e040a7579cd7b4

Author: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
Date:   Mon May 11 20:22:16 2020 -0400

pan/mdg: Analyze helper invocation termination

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5014>

---

 src/panfrost/Makefile.sources                     |  1 +
 src/panfrost/midgard/compiler.h                   |  9 +++
 src/panfrost/midgard/meson.build                  |  1 +
 src/panfrost/midgard/midgard_helper_invocations.c | 97 +++++++++++++++++++++++
 src/panfrost/midgard/midgard_print.c              |  4 +
 5 files changed, 112 insertions(+)

diff --git a/src/panfrost/Makefile.sources b/src/panfrost/Makefile.sources
index 2e9a026f27d..06062b16749 100644
--- a/src/panfrost/Makefile.sources
+++ b/src/panfrost/Makefile.sources
@@ -47,6 +47,7 @@ midgard_FILES := \
         midgard/midgard_emit.c \
         midgard/midgard.h \
         midgard/midgard_liveness.c \
+        midgard/midgard_helper_invocations.c \
         midgard/midgard_nir.h \
         midgard/midgard_ops.c \
         midgard/midgard_ops.h \
diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h
index 5158ea6a85c..6db0cfea466 100644
--- a/src/panfrost/midgard/compiler.h
+++ b/src/panfrost/midgard/compiler.h
@@ -104,6 +104,10 @@ typedef struct midgard_instruction {
         /* Special fields for an ALU instruction */
         midgard_reg_info registers;
 
+        /* For textures: should helpers execute this instruction (instead of
+         * just helping with derivatives)? Should helpers terminate after? */
+        bool helper_terminate;
+
         /* I.e. (1 << alu_bit) */
         int unit;
 
@@ -179,6 +183,9 @@ typedef struct midgard_block {
 
         /* Indicates this is a fixed-function fragment epilogue block */
         bool epilogue;
+
+        /* Are helper invocations required by this block? */
+        bool helpers_in;
 } midgard_block;
 
 typedef struct midgard_bundle {
@@ -626,6 +633,8 @@ 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);
+
 /* Final emission */
 
 void emit_binary_bundle(
diff --git a/src/panfrost/midgard/meson.build b/src/panfrost/midgard/meson.build
index fc0cd85f4df..b719af8bda9 100644
--- a/src/panfrost/midgard/meson.build
+++ b/src/panfrost/midgard/meson.build
@@ -27,6 +27,7 @@ libpanfrost_midgard_files = files(
   'midgard_schedule.c',
   'midgard_derivatives.c',
   'midgard_emit.c',
+  'midgard_helper_invocations.c',
   'midgard_ra.c',
   'midgard_ra_pipeline.c',
   'midgard_liveness.c',
diff --git a/src/panfrost/midgard/midgard_helper_invocations.c b/src/panfrost/midgard/midgard_helper_invocations.c
index 32bcbd4d823..9f8c68a8125 100644
--- a/src/panfrost/midgard/midgard_helper_invocations.c
+++ b/src/panfrost/midgard/midgard_helper_invocations.c
@@ -61,3 +61,100 @@
  * with union as the join operation and the generating set being the union of
  * sources of instructions writing executed values.
  */
+
+/* Does a block use helpers directly */
+static bool
+mir_block_uses_helpers(gl_shader_stage stage, midgard_block *block)
+{
+        mir_foreach_instr_in_block(block, ins) {
+                if (ins->type != TAG_TEXTURE_4) continue;
+                if (mir_op_computes_derivatives(stage, ins->texture.op))
+                        return true;
+        }
+
+        return false;
+}
+
+static bool
+mir_block_terminates_helpers(midgard_block *block)
+{
+        /* Can't terminate if there are no helpers */
+        if (!block->helpers_in)
+                return false;
+
+        /* Can't terminate if a successor needs helpers */
+        pan_foreach_successor((&block->base), succ) {
+                if (((midgard_block *) succ)->helpers_in)
+                        return false;
+        }
+
+        /* Otherwise we terminate */
+        return true;
+}
+
+void
+mir_analyze_helper_terminate(compiler_context *ctx)
+{
+        /* Set blocks as directly requiring helpers, and if they do add them to
+         * the worklist to propagate to their predecessors */
+
+        struct set *worklist = _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);
+
+        mir_foreach_block(ctx, _block) {
+                midgard_block *block = (midgard_block *) _block;
+                block->helpers_in |= mir_block_uses_helpers(ctx->stage, block);
+
+                if (block->helpers_in)
+                        _mesa_set_add(worklist, _block);
+        }
+
+        /* Next, propagate back. Since there are a finite number of blocks, the
+         * worklist (a subset of all the blocks) is finite. Since a block can
+         * only be added to the worklist if it is not on the visited list and
+         * the visited list - also a subset of the blocks - grows every
+         * iteration, the algorithm must terminate. */
+
+        struct set_entry *cur;
+
+        while((cur = _mesa_set_next_entry(worklist, NULL)) != NULL) {
+                /* Pop off a block requiring helpers */
+                pan_block *blk = (struct pan_block *) cur->key;
+                _mesa_set_remove(worklist, cur);
+
+                /* Its predecessors also require helpers */
+                pan_foreach_predecessor(blk, pred) {
+                        if (!_mesa_set_search(visited, pred)) {
+                                ((midgard_block *) pred)->helpers_in = true;
+                                _mesa_set_add(worklist, pred);
+                        }
+                }
+ 
+                _mesa_set_add(visited, blk);
+        }
+
+        _mesa_set_destroy(visited, NULL);
+        _mesa_set_destroy(worklist, NULL);
+
+        /* Finally, set helper_terminate on the last derivative-calculating
+         * instruction in a block that terminates helpers */
+        mir_foreach_block(ctx, _block) {
+                midgard_block *block = (midgard_block *) _block;
+
+                if (!mir_block_terminates_helpers(block))
+                        continue;
+
+                mir_foreach_instr_in_block_rev(block, ins) {
+                        if (ins->type != TAG_TEXTURE_4) continue;
+                        if (!mir_op_computes_derivatives(ctx->stage, ins->texture.op)) continue;
+
+                        ins->helper_terminate = true;
+                        break;
+                }
+        }
+}
diff --git a/src/panfrost/midgard/midgard_print.c b/src/panfrost/midgard/midgard_print.c
index 89b853ce3cb..002026a16b5 100644
--- a/src/panfrost/midgard/midgard_print.c
+++ b/src/panfrost/midgard/midgard_print.c
@@ -328,6 +328,10 @@ mir_print_instruction(midgard_instruction *ins)
 
         case TAG_TEXTURE_4: {
                 printf("texture");
+
+                if (ins->helper_terminate)
+                        printf(".terminate");
+
                 break;
         }
 



More information about the mesa-commit mailing list