panfrost: Add optional opaque packs to GenXML
[mesa.git] / src / panfrost / midgard / midgard_helper_invocations.c
index 9f8c68a81252c3da4ecfb90f658d149e9320a973..407de6676b90c127d20c8ddfd9a87db2cd9831a2 100644 (file)
@@ -68,7 +68,7 @@ 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))
+                if (mir_op_computes_derivatives(stage, ins->op))
                         return true;
         }
 
@@ -151,10 +151,97 @@ mir_analyze_helper_terminate(compiler_context *ctx)
 
                 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;
+                        if (!mir_op_computes_derivatives(ctx->stage, ins->op)) continue;
 
                         ins->helper_terminate = true;
                         break;
                 }
         }
 }
+
+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->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);
+}