+ /* Default to a tag 1 which will break from the shader, in case we jump
+ * to the exit block (i.e. `return` in a compute shader) */
+
+ return 1;
+}
+
+static unsigned
+pan_format_from_nir_base(nir_alu_type base)
+{
+ switch (base) {
+ case nir_type_int:
+ return MALI_FORMAT_SINT;
+ case nir_type_uint:
+ case nir_type_bool:
+ return MALI_FORMAT_UINT;
+ case nir_type_float:
+ return MALI_CHANNEL_FLOAT;
+ default:
+ unreachable("Invalid base");
+ }
+}
+
+static unsigned
+pan_format_from_nir_size(nir_alu_type base, unsigned size)
+{
+ if (base == nir_type_float) {
+ switch (size) {
+ case 16: return MALI_FORMAT_SINT;
+ case 32: return MALI_FORMAT_UNORM;
+ default:
+ unreachable("Invalid float size for format");
+ }
+ } else {
+ switch (size) {
+ case 1:
+ case 8: return MALI_CHANNEL_8;
+ case 16: return MALI_CHANNEL_16;
+ case 32: return MALI_CHANNEL_32;
+ default:
+ unreachable("Invalid int size for format");
+ }
+ }
+}
+
+static enum mali_format
+pan_format_from_glsl(const struct glsl_type *type)
+{
+ enum glsl_base_type glsl_base = glsl_get_base_type(glsl_without_array(type));
+ nir_alu_type t = nir_get_nir_type_for_glsl_base_type(glsl_base);
+
+ unsigned base = nir_alu_type_get_base_type(t);
+ unsigned size = nir_alu_type_get_type_size(t);
+
+ return pan_format_from_nir_base(base) |
+ pan_format_from_nir_size(base, size) |
+ MALI_NR_CHANNELS(4);
+}
+
+/* For each fragment writeout instruction, generate a writeout loop to
+ * associate with it */
+
+static void
+mir_add_writeout_loops(compiler_context *ctx)
+{
+ for (unsigned rt = 0; rt < ARRAY_SIZE(ctx->writeout_branch); ++rt) {
+ midgard_instruction *br = ctx->writeout_branch[rt];
+ if (!br) continue;
+
+ unsigned popped = br->branch.target_block;
+ pan_block_add_successor(&(mir_get_block(ctx, popped - 1)->base), &ctx->current_block->base);
+ br->branch.target_block = emit_fragment_epilogue(ctx, rt);
+
+ /* If we have more RTs, we'll need to restore back after our
+ * loop terminates */
+
+ if ((rt + 1) < ARRAY_SIZE(ctx->writeout_branch) && ctx->writeout_branch[rt + 1]) {
+ midgard_instruction uncond = v_branch(false, false);
+ uncond.branch.target_block = popped;
+ emit_mir_instruction(ctx, uncond);
+ pan_block_add_successor(&ctx->current_block->base, &(mir_get_block(ctx, popped)->base));
+ schedule_barrier(ctx);
+ } else {
+ /* We're last, so we can terminate here */
+ br->last_writeout = true;
+ }
+ }