pan/mdg: Dual source blend input/writeout support
authorIcecream95 <ixn@keemail.me>
Thu, 25 Jun 2020 10:21:50 +0000 (22:21 +1200)
committerMarge Bot <eric+marge@anholt.net>
Wed, 15 Jul 2020 01:30:00 +0000 (01:30 +0000)
We write to r2, which is preseved through to the blend shader, from
where it is read. We won't worry about MRT to keep things simple.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5620>

src/panfrost/midgard/compiler.h
src/panfrost/midgard/midgard_compile.c
src/panfrost/midgard/midgard_opt_copy_prop.c
src/panfrost/midgard/midgard_opt_dce.c
src/panfrost/midgard/midgard_ra.c
src/panfrost/midgard/midgard_ra_pipeline.c
src/panfrost/midgard/mir.c
src/panfrost/midgard/mir_promote_uniforms.c
src/panfrost/midgard/mir_squeeze.c

index 09b18c898956c4196e8e66332b5c90caa97b0a0a..101eb32af655f1f6eba32071f140eefc5802dacb 100644 (file)
@@ -246,6 +246,9 @@ typedef struct compiler_context {
         /* Index to precolour to r0 for an input blend colour */
         unsigned blend_input;
 
+        /* Index to precolour to r2 for a dual-source blend colour */
+        unsigned blend_src1;
+
         /* Tracking for blend constant patching */
         int blend_constant_offset;
 
index 2ae7950bd2968bbfc571d54907a39506e1428b54..c62e9a2ad5799fb0e01b94bf6d3e767d17483ed2 100644 (file)
@@ -1767,13 +1767,15 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
                 } else if (ctx->stage == MESA_SHADER_FRAGMENT && !ctx->is_blend) {
                         emit_varying_read(ctx, reg, offset, nr_comp, component, indirect_offset, t | nir_dest_bit_size(instr->dest), is_flat);
                 } else if (ctx->is_blend) {
-                        /* ctx->blend_input will be precoloured to r0, where
+                        /* ctx->blend_input will be precoloured to r0/r2, where
                          * the input is preloaded */
 
-                        if (ctx->blend_input == ~0)
-                                ctx->blend_input = reg;
+                        unsigned *input = offset ? &ctx->blend_src1 : &ctx->blend_input;
+
+                        if (*input == ~0)
+                                *input = reg;
                         else
-                                emit_mir_instruction(ctx, v_mov(ctx->blend_input, reg));
+                                emit_mir_instruction(ctx, v_mov(*input, reg));
                 } else if (ctx->stage == MESA_SHADER_VERTEX) {
                         emit_attr_read(ctx, reg, offset, nr_comp, t);
                 } else {
@@ -1867,11 +1869,30 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
                                 nir_intrinsic_store_combined_output_pan;
 
                         const nir_variable *var;
-                        enum midgard_rt_id rt;
-
                         var = search_var(&ctx->nir->outputs,
                                          nir_intrinsic_base(instr));
                         assert(var);
+
+                        /* Dual-source blend writeout is done by leaving the
+                         * value in r2 for the blend shader to use. */
+                        if (var->data.index) {
+                                if (instr->src[0].is_ssa) {
+                                        emit_explicit_constant(ctx, reg, reg);
+
+                                        unsigned out = make_compiler_temp(ctx);
+
+                                        midgard_instruction ins = v_mov(reg, out);
+                                        emit_mir_instruction(ctx, ins);
+
+                                        ctx->blend_src1 = out;
+                                } else {
+                                        ctx->blend_src1 = reg;
+                                }
+
+                                break;
+                        }
+
+                        enum midgard_rt_id rt;
                         if (var->data.location == FRAG_RESULT_COLOR)
                                 rt = MIDGARD_COLOR_RT0;
                         else if (var->data.location >= FRAG_RESULT_DATA0)
@@ -2818,6 +2839,7 @@ midgard_compile_shader_nir(nir_shader *nir, panfrost_program *program, bool is_b
         ctx->alpha_ref = program->alpha_ref;
         ctx->blend_rt = MIDGARD_COLOR_RT0 + blend_rt;
         ctx->blend_input = ~0;
+        ctx->blend_src1 = ~0;
         ctx->quirks = midgard_get_quirks(gpu_id);
 
         /* Start off with a safe cutoff, allowing usage of all 16 work
index c27536f989ef3db261daa96dd869cb4ad314679e..fc72da8c2a29504880cd3dc461dd3b7dcb7f9b13 100644 (file)
@@ -120,6 +120,9 @@ midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block)
                 if (skip)
                         continue;
 
+                if (ctx->blend_src1 == to)
+                        ctx->blend_src1 = from;
+
                 /* We're clear -- rewrite, composing the swizzle */
                 mir_rewrite_index_src_swizzle(ctx, to, from, ins->swizzle[1]);
                 mir_remove_instruction(ins);
index 93d3d45b2412423794af2a5e6beb4aa5d2bed1a5..86812b5b0fe5d628403494c4ec253d42b5f88d12 100644 (file)
@@ -36,6 +36,9 @@ can_cull_mask(compiler_context *ctx, midgard_instruction *ins)
         if (ins->dest >= ctx->temp_count)
                 return false;
 
+        if (ins->dest == ctx->blend_src1)
+                return false;
+
         if (ins->type == TAG_LOAD_STORE_4)
                 if (load_store_opcode_props[ins->load_store.op].props & LDST_SPECIAL_MASK)
                         return false;
index 84f83aa443c5a51e4ebf86c7576d1eeee89ffbc8..4ec60ab0a167e108bce386856d385eae6ec80d5d 100644 (file)
@@ -630,6 +630,15 @@ allocate_registers(compiler_context *ctx, bool *spilled)
                 l->solutions[ctx->blend_input] = 0;
         }
 
+        /* Same for the dual-source blend input/output, except here we use r2,
+         * which is also set in the fragment shader. */
+
+        if (ctx->blend_src1 != ~0) {
+                assert(ctx->blend_src1 < ctx->temp_count);
+                l->solutions[ctx->blend_src1] = (16 * 2);
+                ctx->work_registers = MAX2(ctx->work_registers, 2);
+        }
+
         mir_compute_interference(ctx, l);
 
         *spilled = !lcra_solve(l);
index 1037d0645d95eaf18fa0407b26468ca56bc709ac..6f21ee1a699e7a4e929f2ac3dbae6508cc4c9d74 100644 (file)
@@ -67,6 +67,9 @@ mir_pipeline_ins(
         if (node >= SSA_FIXED_MINIMUM)
                 return false;
 
+        if (node == ctx->blend_src1)
+                return false;
+
         /* Analyze the bundle for a per-byte read mask */
 
         for (unsigned j = 0; j < bundle->instruction_count; ++j) {
index 343c4bdb1d76a191fe7865603b6c8cf5e40e2fb0..be5d195062b666ae9803df77005d1d975423909f 100644 (file)
@@ -75,6 +75,9 @@ mir_rewrite_index_dst(compiler_context *ctx, unsigned old, unsigned new)
         /* Implicitly written before the shader */
         if (ctx->blend_input == old)
                 ctx->blend_input = new;
+
+        if (ctx->blend_src1 == old)
+                ctx->blend_src1 = new;
 }
 
 void
index a7f2d9e03a0b1db59daf79e2d38c05e9501eb930..4f86c4aaae062e33f98ba2873823f23b747a6996 100644 (file)
@@ -186,7 +186,7 @@ midgard_promote_uniforms(compiler_context *ctx)
                 /* We do need the move for safety for a non-SSA dest, or if
                  * we're being fed into a special class */
 
-                bool needs_move = ins->dest & PAN_IS_REG;
+                bool needs_move = ins->dest & PAN_IS_REG || ins->dest == ctx->blend_src1;
 
                 if (ins->dest < ctx->temp_count)
                         needs_move |= BITSET_TEST(special, ins->dest);
index 24475c22bdabafb00a4f15854f98fc7e3b71427b..07ba6b309c2059677dc36d7b41d7134659630708 100644 (file)
@@ -80,4 +80,5 @@ mir_squeeze_index(compiler_context *ctx)
         }
 
         ctx->blend_input = find_or_allocate_temp(ctx, ctx->blend_input);
+        ctx->blend_src1 = find_or_allocate_temp(ctx, ctx->blend_src1);
 }