pan/bi: Collect return addresses of blend calls

We will need that for blend shaders so they can be passed a return
address and jump back to the fragment shader when they're done.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7151>
diff --git a/src/panfrost/bifrost/bi_pack.c b/src/panfrost/bifrost/bi_pack.c
index 86b7efc..0c9dd39 100644
--- a/src/panfrost/bifrost/bi_pack.c
+++ b/src/panfrost/bifrost/bi_pack.c
@@ -1078,6 +1078,34 @@
                 return false;
 }
 
+static void
+bi_collect_blend_ret_addr(bi_context *ctx, struct util_dynarray *emission,
+                          const bi_clause *clause)
+{
+        /* No need to collect return addresses when we're in a blend shader. */
+        if (ctx->is_blend)
+                return;
+
+        const bi_bundle *bundle = &clause->bundles[clause->bundle_count - 1];
+        const bi_instruction *ins = bundle->add;
+
+        if (!ins || ins->type != BI_BLEND)
+                return;
+
+        /* We don't support non-terminal blend instructions yet.
+         * That would requires fixing blend shaders to restore the registers
+         * they use before jumping back to the fragment shader, which is
+         * currently not supported.
+         */
+        assert(0);
+
+        assert(ins->blend_location < ARRAY_SIZE(ctx->blend_ret_offsets));
+        assert(!ctx->blend_ret_offsets[ins->blend_location]);
+        ctx->blend_ret_offsets[ins->blend_location] =
+                util_dynarray_num_elements(emission, uint8_t);
+        assert(!(ctx->blend_ret_offsets[ins->blend_location] & 0x7));
+}
+
 void
 bi_pack(bi_context *ctx, struct util_dynarray *emission)
 {
@@ -1101,6 +1129,9 @@
                         bi_clause *next_2 = is_last ? succ_clause : NULL;
 
                         bi_pack_clause(ctx, clause, next, next_2, emission, ctx->stage, tdd);
+
+                        if (!is_last)
+                                bi_collect_blend_ret_addr(ctx, emission, clause);
                 }
         }
 }
diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c
index b8191d9..1dbfa43 100644
--- a/src/panfrost/bifrost/bifrost_compile.c
+++ b/src/panfrost/bifrost/bifrost_compile.c
@@ -1806,6 +1806,8 @@
                 bi_print_shader(ctx, stdout);
         bi_pack(ctx, &program->compiled);
 
+        memcpy(program->blend_ret_offsets, ctx->blend_ret_offsets, sizeof(program->blend_ret_offsets));
+
         if (bifrost_debug & BIFROST_DBG_SHADERS)
                 disassemble_bifrost(stdout, program->compiled.data, program->compiled.size, true);
 
diff --git a/src/panfrost/bifrost/compiler.h b/src/panfrost/bifrost/compiler.h
index 7a2a1fd..1debc43 100644
--- a/src/panfrost/bifrost/compiler.h
+++ b/src/panfrost/bifrost/compiler.h
@@ -453,6 +453,9 @@
        /* Blend constants */
        float blend_constants[4];
 
+       /* Blend return offsets */
+       uint32_t blend_ret_offsets[8];
+
        /* Blend tile buffer conversion desc */
        uint64_t blend_desc;
 
diff --git a/src/panfrost/util/pan_ir.h b/src/panfrost/util/pan_ir.h
index 7a04f25..ccb087f 100644
--- a/src/panfrost/util/pan_ir.h
+++ b/src/panfrost/util/pan_ir.h
@@ -88,6 +88,9 @@
         /* For Bifrost - output type for each RT */
         nir_alu_type blend_types[8];
 
+        /* For Bifrost - return address for blend instructions */
+        uint32_t blend_ret_offsets[8];
+
         /* Prepended before uniforms, mapping to SYSVAL_ names for the
          * sysval */