From 85954ecfefd7e8366b27ec07dcc79e52b03d6abd Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 25 Jun 2020 22:21:50 +1200 Subject: [PATCH] pan/mdg: Dual source blend input/writeout support 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 Part-of: --- src/panfrost/midgard/compiler.h | 3 ++ src/panfrost/midgard/midgard_compile.c | 34 ++++++++++++++++---- src/panfrost/midgard/midgard_opt_copy_prop.c | 3 ++ src/panfrost/midgard/midgard_opt_dce.c | 3 ++ src/panfrost/midgard/midgard_ra.c | 9 ++++++ src/panfrost/midgard/midgard_ra_pipeline.c | 3 ++ src/panfrost/midgard/mir.c | 3 ++ src/panfrost/midgard/mir_promote_uniforms.c | 2 +- src/panfrost/midgard/mir_squeeze.c | 1 + 9 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h index 09b18c89895..101eb32af65 100644 --- a/src/panfrost/midgard/compiler.h +++ b/src/panfrost/midgard/compiler.h @@ -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; diff --git a/src/panfrost/midgard/midgard_compile.c b/src/panfrost/midgard/midgard_compile.c index 2ae7950bd29..c62e9a2ad57 100644 --- a/src/panfrost/midgard/midgard_compile.c +++ b/src/panfrost/midgard/midgard_compile.c @@ -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 diff --git a/src/panfrost/midgard/midgard_opt_copy_prop.c b/src/panfrost/midgard/midgard_opt_copy_prop.c index c27536f989e..fc72da8c2a2 100644 --- a/src/panfrost/midgard/midgard_opt_copy_prop.c +++ b/src/panfrost/midgard/midgard_opt_copy_prop.c @@ -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); diff --git a/src/panfrost/midgard/midgard_opt_dce.c b/src/panfrost/midgard/midgard_opt_dce.c index 93d3d45b241..86812b5b0fe 100644 --- a/src/panfrost/midgard/midgard_opt_dce.c +++ b/src/panfrost/midgard/midgard_opt_dce.c @@ -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; diff --git a/src/panfrost/midgard/midgard_ra.c b/src/panfrost/midgard/midgard_ra.c index 84f83aa443c..4ec60ab0a16 100644 --- a/src/panfrost/midgard/midgard_ra.c +++ b/src/panfrost/midgard/midgard_ra.c @@ -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); diff --git a/src/panfrost/midgard/midgard_ra_pipeline.c b/src/panfrost/midgard/midgard_ra_pipeline.c index 1037d0645d9..6f21ee1a699 100644 --- a/src/panfrost/midgard/midgard_ra_pipeline.c +++ b/src/panfrost/midgard/midgard_ra_pipeline.c @@ -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) { diff --git a/src/panfrost/midgard/mir.c b/src/panfrost/midgard/mir.c index 343c4bdb1d7..be5d195062b 100644 --- a/src/panfrost/midgard/mir.c +++ b/src/panfrost/midgard/mir.c @@ -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 diff --git a/src/panfrost/midgard/mir_promote_uniforms.c b/src/panfrost/midgard/mir_promote_uniforms.c index a7f2d9e03a0..4f86c4aaae0 100644 --- a/src/panfrost/midgard/mir_promote_uniforms.c +++ b/src/panfrost/midgard/mir_promote_uniforms.c @@ -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); diff --git a/src/panfrost/midgard/mir_squeeze.c b/src/panfrost/midgard/mir_squeeze.c index 24475c22bda..07ba6b309c2 100644 --- a/src/panfrost/midgard/mir_squeeze.c +++ b/src/panfrost/midgard/mir_squeeze.c @@ -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); } -- 2.30.2