diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_exec.c | 50 |
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 25c3ee2b77..9492a3c243 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; |