nir: Fix per-component negation in prog_to_nir's SWZ handling.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 17 Apr 2015 21:08:14 +0000 (14:08 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 21 Apr 2015 19:01:36 +0000 (12:01 -0700)
I missed the fact that the ARB_fragment_program SWZ instruction allows
per-component negation.  To fix this, move Abs/Negate handling into both
the simple case and the SWZ case's per-component loop.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90000
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/program/prog_to_nir.c

index c738f5073b84f5fe1b4a0d05b8fd7bddfbd43694..ff3d9f3beed2637acf885ff3004a81fd4556642a 100644 (file)
@@ -222,12 +222,23 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
    }
 
    nir_ssa_def *def;
-   if (!HAS_EXTENDED_SWIZZLE(prog_src->Swizzle)) {
+   if (!HAS_EXTENDED_SWIZZLE(prog_src->Swizzle) &&
+       (prog_src->Negate == NEGATE_NONE || prog_src->Negate == NEGATE_XYZW)) {
+      /* The simple non-SWZ case. */
       for (int i = 0; i < 4; i++)
          src.swizzle[i] = GET_SWZ(prog_src->Swizzle, i);
 
       def = nir_fmov_alu(b, src, 4);
+
+      if (prog_src->Abs)
+         def = nir_fabs(b, def);
+
+      if (prog_src->Negate)
+         def = nir_fneg(b, def);
    } else {
+      /* The SWZ instruction allows per-component zero/one swizzles, and also
+       * per-component negation.
+       */
       nir_ssa_def *chans[4];
       for (int i = 0; i < 4; i++) {
          int swizzle = GET_SWZ(prog_src->Swizzle, i);
@@ -246,16 +257,16 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
 
             chans[i] = &mov->dest.dest.ssa;
          }
+
+         if (prog_src->Abs)
+            chans[i] = nir_fabs(b, chans[i]);
+
+         if (prog_src->Negate & (1 << i))
+            chans[i] = nir_fneg(b, chans[i]);
       }
       def = nir_vec4(b, chans[0], chans[1], chans[2], chans[3]);
    }
 
-   if (prog_src->Abs)
-      def = nir_fabs(b, def);
-
-   if (prog_src->Negate)
-      def = nir_fneg(b, def);
-
    return def;
 }