panfrost/midgard: Allow fp16 in scalar ALU
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 2 Jul 2019 01:35:28 +0000 (18:35 -0700)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 10 Jul 2019 13:12:04 +0000 (06:12 -0700)
The packing is a little different, so implement that.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/midgard/midgard_emit.c
src/gallium/drivers/panfrost/midgard/midgard_schedule.c

index 3c331551dd8db981baa0afc73d30a0d9ee40c19d..701ef1074ffec542d14a25b4d7f6887281ab5b30 100644 (file)
  * this, we just demote vector ALU payloads to scalar. */
 
 static int
-component_from_mask(unsigned mask)
+component_from_mask(unsigned mask, bool full)
 {
-        for (int c = 0; c < 4; ++c) {
-                if (mask & (3 << (2 * c)))
+        for (int c = 0; c < 8; ++c) {
+                if (mask & (1 << c))
                         return c;
+
+                /* Full uses every other bit */
+                if (full)
+                        c++;
         }
 
         assert(0);
@@ -41,17 +45,35 @@ component_from_mask(unsigned mask)
 }
 
 static unsigned
-vector_to_scalar_source(unsigned u, bool is_int)
+vector_to_scalar_source(unsigned u, bool is_int, bool is_full)
 {
         midgard_vector_alu_src v;
         memcpy(&v, &u, sizeof(v));
 
         /* TODO: Integers */
 
-        midgard_scalar_alu_src s = {
-                .full = !v.half,
-                .component = (v.swizzle & 3) << 1
-        };
+        unsigned component = v.swizzle & 3;
+        bool upper = false; /* TODO */
+
+        midgard_scalar_alu_src s = { 0 };
+
+        if (is_full) {
+                /* For a 32-bit op, just check the source half flag */
+                s.full = !v.half;
+        } else if (!v.half) {
+                /* For a 16-bit op that's not subdivided, never full */
+                s.full = false;
+        } else {
+                /* We can't do 8-bit scalar, abort! */
+                assert(0);
+        }
+
+        /* Component indexing takes size into account */
+
+        if (s.full)
+                s.component = component << 1;
+        else
+                s.component = component + (upper << 2);
 
         if (is_int) {
                 /* TODO */
@@ -70,16 +92,17 @@ static midgard_scalar_alu
 vector_to_scalar_alu(midgard_vector_alu v, midgard_instruction *ins)
 {
         bool is_int = midgard_is_integer_op(v.op);
+        bool is_full = v.reg_mode == midgard_reg_mode_32;
 
         /* The output component is from the mask */
         midgard_scalar_alu s = {
                 .op = v.op,
-                .src1 = vector_to_scalar_source(v.src1, is_int),
-                .src2 = vector_to_scalar_source(v.src2, is_int),
+                .src1 = vector_to_scalar_source(v.src1, is_int, is_full),
+                .src2 = vector_to_scalar_source(v.src2, is_int, is_full),
                 .unknown = 0,
                 .outmod = v.outmod,
-                .output_full = 1, /* TODO: Half */
-                .output_component = component_from_mask(v.mask) << 1,
+                .output_full = is_full,
+                .output_component = component_from_mask(v.mask, is_full),
         };
 
         /* Inline constant is passed along rather than trying to extract it
index c0dd5764595c78bb754b989ddd790e68532e89f2..77738731b8a88ffab653365424185d5cf5acf94e 100644 (file)
@@ -44,14 +44,19 @@ swizzle_to_access_mask(unsigned swizzle)
 /* Does the mask cover more than a scalar? */
 
 static bool
-is_single_component_mask(unsigned mask)
+is_single_component_mask(unsigned mask, bool full)
 {
         int components = 0;
 
-        for (int c = 0; c < 4; ++c)
-                if (mask & (3 << (2 * c)))
+        for (int c = 0; c < 8; ++c) {
+                if (mask & (1 << c))
                         components++;
 
+                /* Full uses 2-bit components */
+                if (full)
+                        c++;
+        }
+
         return components == 1;
 }
 
@@ -193,9 +198,17 @@ schedule_bundle(compiler_context *ctx, midgard_block *block, midgard_instruction
 
                                 bool vectorable = units & UNITS_ANY_VECTOR;
                                 bool scalarable = units & UNITS_SCALAR;
-                                bool could_scalar = is_single_component_mask(ains->alu.mask);
+                                bool full = ains->alu.reg_mode == midgard_reg_mode_32;
+                                bool could_scalar = is_single_component_mask(ains->alu.mask, full);
                                 bool vector = vectorable && !(could_scalar && scalarable);
 
+                                /* Only 16/32-bit can run on a scalar unit */
+                                could_scalar &= ains->alu.reg_mode != midgard_reg_mode_8;
+                                could_scalar &= ains->alu.reg_mode != midgard_reg_mode_64;
+
+                                /* TODO: Check ahead-of-time for other scalar
+                                 * hazards that otherwise get aborted out */
+
                                 if (!vector)
                                         assert(units & UNITS_SCALAR);