pan/mdg: Analyze helper invocation termination
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 12 May 2020 00:22:16 +0000 (20:22 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 12 May 2020 22:30:41 +0000 (22:30 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5014>

src/panfrost/Makefile.sources
src/panfrost/midgard/compiler.h
src/panfrost/midgard/meson.build
src/panfrost/midgard/midgard_helper_invocations.c
src/panfrost/midgard/midgard_print.c

index 2e9a026f27dc6cd36cf0a009d4bef067768811ee..06062b16749c6f4049080b4786025e57a7a58cc0 100644 (file)
@@ -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 \
index 5158ea6a85cf3dfcd9019a7a1fc37aa93f59e4ff..6db0cfea466bee67315fc4d8d8284ccbe22d2d81 100644 (file)
@@ -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(
index fc0cd85f4df968e67949d0d3010b20de72c3c90a..b719af8bda99cfd9aef48a3212fa5a677ac9c025 100644 (file)
@@ -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',
index 32bcbd4d8238c17b959f2eca8a443bd93eb0c1ad..9f8c68a81252c3da4ecfb90f658d149e9320a973 100644 (file)
  * 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;
+                }
+        }
+}
index 89b853ce3cb51da343f9dcb96182fc11955383f8..002026a16b59622bff9d5250342d72a5d886fa97 100644 (file)
@@ -328,6 +328,10 @@ mir_print_instruction(midgard_instruction *ins)
 
         case TAG_TEXTURE_4: {
                 printf("texture");
+
+                if (ins->helper_terminate)
+                        printf(".terminate");
+
                 break;
         }