vc4: Add support for the lit opcode.
authorEric Anholt <eric@anholt.net>
Wed, 16 Jul 2014 16:08:48 +0000 (09:08 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 9 Aug 2014 01:59:47 +0000 (18:59 -0700)
v2: Fix how it was using the X channel for the real work of the opcode,
    instead of Y.  Fixes glean's LIT test.
v3: Rebase on the helpers.

src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_qir.h

index 005b986829afb1434d0dc6276ffb21b3134ea208..1cf518dceb26d7e9f882ef8ca9061946b4cff80e 100644 (file)
@@ -224,6 +224,42 @@ tgsi_to_qir_mad(struct tgsi_to_qir *trans,
                         src[2 * 4 + i]);
 }
 
+static struct qreg
+tgsi_to_qir_lit(struct tgsi_to_qir *trans,
+                 struct tgsi_full_instruction *tgsi_inst,
+                 enum qop op, struct qreg *src, int i)
+{
+        struct qcompile *c = trans->c;
+        struct qreg x = src[0 * 4 + 0];
+        struct qreg y = src[0 * 4 + 1];
+        struct qreg w = src[0 * 4 + 3];
+
+        switch (i) {
+        case 0:
+        case 3:
+                return qir_uniform_f(trans, 1.0);
+        case 1:
+                return qir_FMAX(c, src[0 * 4 + 0], qir_uniform_f(trans, 0.0));
+        case 2: {
+                struct qreg zero = qir_uniform_f(trans, 0.0);
+
+                /* XXX: Clamp w to -128..128 */
+                return qir_CMP(c,
+                               x,
+                               zero,
+                               qir_EXP2(c, qir_FMUL(c,
+                                                    w,
+                                                    qir_LOG2(c,
+                                                             qir_FMAX(c,
+                                                                      y,
+                                                                      zero)))));
+        }
+        default:
+                assert(!"not reached");
+                return c->undef;
+        }
+}
+
 static struct qreg
 tgsi_to_qir_lrp(struct tgsi_to_qir *trans,
                  struct tgsi_full_instruction *tgsi_inst,
@@ -372,7 +408,7 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
                 [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_alu },
                 [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_alu },
                 [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_alu },
-                [TGSI_OPCODE_LIT] = { QOP_MOV, tgsi_to_qir_alu }, /* XXX */
+                [TGSI_OPCODE_LIT] = { 0, tgsi_to_qir_lit },
                 [TGSI_OPCODE_LRP] = { 0, tgsi_to_qir_lrp },
                 [TGSI_OPCODE_POW] = { 0, tgsi_to_qir_pow },
         };
index 5332478039aa8f760be863a428f86eb0362b125b..ff222e4aeff5aa0d53d9ad7b8556c2e3ae08a17f 100644 (file)
@@ -198,4 +198,12 @@ qir_VPM_WRITE(struct qcompile *c, struct qreg a)
         qir_emit(c, qir_inst(QOP_VPM_WRITE, c->undef, a, c->undef));
 }
 
+static inline struct qreg
+qir_CMP(struct qcompile *c, struct qreg cmp, struct qreg a, struct qreg b)
+{
+        struct qreg t = qir_get_temp(c);
+        qir_emit(c, qir_inst4(QOP_CMP, t, cmp, a, b, c->undef));
+        return t;
+}
+
 #endif /* VC4_QIR_H */