panfrost/midgard: Broadcast swizzle

Submitted by Alyssa Rosenzweig on June 20, 2019, 2:17 p.m.

Details

Message ID 20190620141710.6379-1-alyssa.rosenzweig@collabora.com
State New
Headers show
Series "panfrost/midgard: Broadcast swizzle" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Alyssa Rosenzweig June 20, 2019, 2:17 p.m.
Fixes regression in shaders using ball/etc.

v2: Don't also regress every other swizzle in Equestria.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
---
 .../panfrost/midgard/midgard_compile.c        | 55 +++++++++++++------
 1 file changed, 39 insertions(+), 16 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/drivers/panfrost/midgard/midgard_compile.c b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
index 1cc551b603c..b6c86ac6c35 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_compile.c
+++ b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
@@ -139,10 +139,25 @@  mask_of(unsigned nr_comp)
  * the corresponding Midgard source */
 
 static midgard_vector_alu_src
-vector_alu_modifiers(nir_alu_src *src, bool is_int)
+vector_alu_modifiers(nir_alu_src *src, bool is_int, bool broadcast_swizzle)
 {
         if (!src) return blank_alu_src;
 
+        /* Figure out how many components there are
+         * so we can adjust the swizzle.
+         * Specifically we want to broadcast the
+         * last channel so things like ball2/3 work
+         */
+
+        unsigned count = nir_src_num_components(src->src);
+        uint8_t last_component = src->swizzle[count - 1];
+
+        if (broadcast_swizzle) {
+                for (unsigned c = count; c < NIR_MAX_VEC_COMPONENTS; ++c) {
+                        src->swizzle[c] = last_component;
+                }
+        }
+
         midgard_vector_alu_src alu_src = {
                 .rep_low = 0,
                 .rep_high = 0,
@@ -698,6 +713,12 @@  emit_indirect_offset(compiler_context *ctx, nir_src *src)
 	case nir_op_##nir: \
 		op = midgard_alu_op_##_op; \
 		break;
+
+#define ALU_CASE_BCAST(nir, _op) \
+        case nir_op_##nir: \
+                op = midgard_alu_op_##_op; \
+                broadcast_swizzle = true; \
+                break;
 static bool
 nir_is_fzero_constant(nir_src src)
 {
@@ -730,6 +751,8 @@  emit_alu(compiler_context *ctx, nir_alu_instr *instr)
 
         unsigned op;
 
+        bool broadcast_swizzle = false;
+
         switch (instr->op) {
                 ALU_CASE(fadd, fadd);
                 ALU_CASE(fmul, fmul);
@@ -805,21 +828,21 @@  emit_alu(compiler_context *ctx, nir_alu_instr *instr)
                 ALU_CASE(ishr, iasr);
                 ALU_CASE(ushr, ilsr);
 
-                ALU_CASE(b32all_fequal2, fball_eq);
-                ALU_CASE(b32all_fequal3, fball_eq);
-                ALU_CASE(b32all_fequal4, fball_eq);
+                ALU_CASE_BCAST(b32all_fequal2, fball_eq);
+                ALU_CASE_BCAST(b32all_fequal3, fball_eq);
+                ALU_CASE_BCAST(b32all_fequal4, fball_eq);
 
-                ALU_CASE(b32any_fnequal2, fbany_neq);
-                ALU_CASE(b32any_fnequal3, fbany_neq);
-                ALU_CASE(b32any_fnequal4, fbany_neq);
+                ALU_CASE_BCAST(b32any_fnequal2, fbany_neq);
+                ALU_CASE_BCAST(b32any_fnequal3, fbany_neq);
+                ALU_CASE_BCAST(b32any_fnequal4, fbany_neq);
 
-                ALU_CASE(b32all_iequal2, iball_eq);
-                ALU_CASE(b32all_iequal3, iball_eq);
-                ALU_CASE(b32all_iequal4, iball_eq);
+                ALU_CASE_BCAST(b32all_iequal2, iball_eq);
+                ALU_CASE_BCAST(b32all_iequal3, iball_eq);
+                ALU_CASE_BCAST(b32all_iequal4, iball_eq);
 
-                ALU_CASE(b32any_inequal2, ibany_neq);
-                ALU_CASE(b32any_inequal3, ibany_neq);
-                ALU_CASE(b32any_inequal4, ibany_neq);
+                ALU_CASE_BCAST(b32any_inequal2, ibany_neq);
+                ALU_CASE_BCAST(b32any_inequal3, ibany_neq);
+                ALU_CASE_BCAST(b32any_inequal4, ibany_neq);
 
                 /* Source mods will be shoved in later */
                 ALU_CASE(fabs, fmov);
@@ -967,8 +990,8 @@  emit_alu(compiler_context *ctx, nir_alu_instr *instr)
                 /* Writemask only valid for non-SSA NIR */
                 .mask = expand_writemask(mask_of(nr_components)),
 
-                .src1 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[0], is_int)),
-                .src2 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[1], is_int)),
+                .src1 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[0], is_int, broadcast_swizzle)),
+                .src2 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[1], is_int, broadcast_swizzle)),
         };
 
         /* Apply writemask if non-SSA, keeping in mind that we can't write to components that don't exist */
@@ -1033,7 +1056,7 @@  emit_alu(compiler_context *ctx, nir_alu_instr *instr)
                         for (int j = 0; j < 4; ++j)
                                 nirmods[0]->swizzle[j] = original_swizzle[i]; /* Pull from the correct component */
 
-                        ins.alu.src1 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[0], is_int));
+                        ins.alu.src1 = vector_alu_srco_unsigned(vector_alu_modifiers(nirmods[0], is_int, broadcast_swizzle));
                         emit_mir_instruction(ctx, ins);
                 }
         } else {