tgsi: Rewrite NRM opcode, store 1.0 in W component.
authorMichal Krol <michal@vmware.com>
Thu, 12 Mar 2009 10:54:11 +0000 (11:54 +0100)
committerMichal Krol <michal@vmware.com>
Thu, 12 Mar 2009 17:32:36 +0000 (18:32 +0100)
src/gallium/auxiliary/tgsi/tgsi_exec.c

index 25c3ee2b77e90f7166ecdcb465c39aa3cdc33ace..9492a3c2432708c87aed51fb76e25ba8c2fe7a19 100644 (file)
@@ -2688,31 +2688,35 @@ exec_instruction(
 
    case TGSI_OPCODE_NRM:
       /* 3-component vector normalize */
-      {
-         union tgsi_exec_channel tmp, dot;
-
-         /* tmp = dp3(src0, src0): */
-         FETCH( &r[0], 0, CHAN_X );
-         micro_mul( &tmp, &r[0], &r[0] );
-
-         FETCH( &r[1], 0, CHAN_Y );
-         micro_mul( &dot, &r[1], &r[1] );
-         micro_add( &tmp, &tmp, &dot );
-
-         FETCH( &r[2], 0, CHAN_Z );
-         micro_mul( &dot, &r[2], &r[2] );
-         micro_add( &tmp, &tmp, &dot );
-
-         /* tmp = 1 / sqrt(tmp) */
-         micro_sqrt( &tmp, &tmp );
-         micro_div( &tmp, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &tmp );
+      if(IS_CHANNEL_ENABLED(*inst, CHAN_X) ||
+         IS_CHANNEL_ENABLED(*inst, CHAN_Y) ||
+         IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+         /* r3 = sqrt(dp3(src0, src0)) */
+         FETCH(&r[0], 0, CHAN_X);
+         micro_mul(&r[3], &r[0], &r[0]);
+         FETCH(&r[1], 0, CHAN_Y);
+         micro_mul(&r[4], &r[1], &r[1]);
+         micro_add(&r[3], &r[3], &r[4]);
+         FETCH(&r[2], 0, CHAN_Z);
+         micro_mul(&r[4], &r[2], &r[2]);
+         micro_add(&r[3], &r[3], &r[4]);
+         micro_sqrt(&r[3], &r[3]);
 
-         /* note: w channel is undefined */
-         FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
-            /* chan = chan * tmp */
-            micro_mul( &r[chan_index], &tmp, &r[chan_index] );
-            STORE( &r[chan_index], 0, chan_index );
+         if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) {
+            micro_div(&r[0], &r[0], &r[3]);
+            STORE(&r[0], 0, CHAN_X);
          }
+         if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) {
+            micro_div(&r[1], &r[1], &r[3]);
+            STORE(&r[1], 0, CHAN_Y);
+         }
+         if (IS_CHANNEL_ENABLED(*inst, CHAN_Z)) {
+            micro_div(&r[2], &r[2], &r[3]);
+            STORE(&r[2], 0, CHAN_Z);
+         }
+      }
+      if (IS_CHANNEL_ENABLED(*inst, CHAN_W)) {
+         STORE(&mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W);
       }
       break;