summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Krol <[email protected]>2009-03-12 11:54:11 +0100
committerMichal Krol <[email protected]>2009-03-12 18:32:36 +0100
commit321634d80b48e33b4e9572d99e82c45c65701dd1 (patch)
treeae95e74c86fa4a762df0f242183cbec3160cb544
parentd4ea9a26524c2d0abe4cc6452dcb5c18afb6835d (diff)
tgsi: Rewrite NRM opcode, store 1.0 in W component.
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 25c3ee2b77e..9492a3c2432 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -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;