vc4: Add support for the SIN instruction.
authorEric Anholt <eric@anholt.net>
Wed, 6 Aug 2014 23:41:12 +0000 (16:41 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 9 Aug 2014 01:59:47 +0000 (18:59 -0700)
v2: Rebase on helpers.

src/gallium/drivers/vc4/vc4_program.c

index 4e991148c407d88481effe7300f0d9dfbdc097bd..1d048206f8fde324867b7e33199f574a95189f8e 100644 (file)
@@ -369,6 +369,40 @@ tgsi_to_qir_abs(struct tgsi_to_qir *trans,
         return qir_FMAXABS(c, arg, arg);
 }
 
+/* Note that this instruction replicates its result from the x channel */
+static struct qreg
+tgsi_to_qir_sin(struct tgsi_to_qir *trans,
+                struct tgsi_full_instruction *tgsi_inst,
+                enum qop op, struct qreg *src, int i)
+{
+        struct qcompile *c = trans->c;
+        float coeff[] = {
+                2.0 * M_PI,
+                -pow(2.0 * M_PI, 3) / (3 * 2 * 1),
+                pow(2.0 * M_PI, 5) / (5 * 4 * 3 * 2 * 1),
+                -pow(2.0 * M_PI, 7) / (7 * 6 * 5 * 4 * 3 * 2 * 1),
+        };
+
+        struct qreg scaled_x =
+                qir_FMUL(c,
+                         src[0 * 4 + 0],
+                         qir_uniform_f(trans, 1.0f / (M_PI * 2.0f)));
+
+
+        struct qreg x = tgsi_to_qir_frc(trans, NULL, 0, &scaled_x, 0);
+        struct qreg x2 = qir_FMUL(c, x, x);
+        struct qreg sum = qir_FMUL(c, x, qir_uniform_f(trans, coeff[0]));
+        for (int i = 1; i < ARRAY_SIZE(coeff); i++) {
+                x = qir_FMUL(c, x, x2);
+                sum = qir_FADD(c,
+                               sum,
+                               qir_FMUL(c,
+                                        x,
+                                        qir_uniform_f(trans, coeff[i])));
+        }
+        return sum;
+}
+
 static void
 emit_vertex_input(struct tgsi_to_qir *trans, int attr)
 {
@@ -497,6 +531,7 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
                 [TGSI_OPCODE_POW] = { 0, tgsi_to_qir_pow },
                 [TGSI_OPCODE_TRUNC] = { 0, tgsi_to_qir_trunc },
                 [TGSI_OPCODE_FRC] = { 0, tgsi_to_qir_frc },
+                [TGSI_OPCODE_SIN] = { 0, tgsi_to_qir_sin },
         };
         static int asdf = 0;
         uint32_t tgsi_op = tgsi_inst->Instruction.Opcode;