mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-12-11 13:30:59 +00:00
18097 lines
463 KiB
C++
18097 lines
463 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 GPL Source Code
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
|
|
|
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "sys/platform.h"
|
|
#include "idlib/geometry/DrawVert.h"
|
|
|
|
#include "idlib/math/Simd_SSE.h"
|
|
|
|
//===============================================================
|
|
// M
|
|
// SSE implementation of idSIMDProcessor MrE
|
|
// E
|
|
//===============================================================
|
|
|
|
#define DRAWVERT_SIZE 60
|
|
#define DRAWVERT_XYZ_OFFSET (0*4)
|
|
#define DRAWVERT_ST_OFFSET (3*4)
|
|
#define DRAWVERT_NORMAL_OFFSET (5*4)
|
|
#define DRAWVERT_TANGENT0_OFFSET (8*4)
|
|
#define DRAWVERT_TANGENT1_OFFSET (11*4)
|
|
#define DRAWVERT_COLOR_OFFSET (14*4)
|
|
|
|
#if defined(__GNUC__) && defined(__SSE__)
|
|
|
|
#include <xmmintrin.h>
|
|
|
|
#define SHUFFLEPS( x, y, z, w ) (( (x) & 3 ) << 6 | ( (y) & 3 ) << 4 | ( (z) & 3 ) << 2 | ( (w) & 3 ))
|
|
#define R_SHUFFLEPS( x, y, z, w ) (( (w) & 3 ) << 6 | ( (z) & 3 ) << 4 | ( (y) & 3 ) << 2 | ( (x) & 3 ))
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::GetName
|
|
============
|
|
*/
|
|
const char * idSIMD_SSE::GetName( void ) const {
|
|
return "MMX & SSE";
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant.Normal() * src[i].xyz + constant[3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idPlane &constant, const idDrawVert *src, const int count ) {
|
|
// 0, 1, 2
|
|
// 3, 4, 5
|
|
// 6, 7, 8
|
|
// 9, 10, 11
|
|
|
|
/*
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
*/
|
|
__m128 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; // Declare 8 xmm registers.
|
|
int count_l4 = count; // count_l4 = eax
|
|
int count_l1 = count; // count_l1 = edx
|
|
char *constant_p = (char *)&constant; // constant_p = edi
|
|
char *src_p = (char *) src; // src_p = esi
|
|
char *dst_p = (char *) dst; // dst_p = ecx
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( ptrdiff_t(&src->xyz) - ptrdiff_t(src) == DRAWVERT_XYZ_OFFSET );
|
|
|
|
/*
|
|
and eax, ~3
|
|
movss xmm4, [edi+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [edi+4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [edi+12]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
*/
|
|
count_l4 = count_l4 & ~3;
|
|
xmm4 = _mm_load_ss((float *) (constant_p));
|
|
xmm4 = _mm_shuffle_ps(xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm5 = _mm_load_ss((float *) (constant_p + 4));
|
|
xmm5 = _mm_shuffle_ps(xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm6 = _mm_load_ss((float *) (constant_p + 8));
|
|
xmm6 = _mm_shuffle_ps(xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm7 = _mm_load_ss((float *) (constant_p + 12));
|
|
xmm7 = _mm_shuffle_ps(xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
|
|
/*
|
|
jz startVert1
|
|
*/
|
|
if(count_l4 != 0) {
|
|
/*
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
*/
|
|
count_l4 = count_l4 * DRAWVERT_SIZE;
|
|
src_p = src_p + count_l4;
|
|
count_l4 = -count_l4;
|
|
/*
|
|
loopVert4:
|
|
*/
|
|
do {
|
|
/*
|
|
movss xmm0, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, X, X
|
|
movss xmm2, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 2, X, X, X
|
|
movhps xmm0, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, 0, 1
|
|
movaps xmm1, xmm0 // 3, X, 0, 1
|
|
*/
|
|
xmm0 = _mm_load_ss((float *) (src_p+count_l4+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0)); // 3, X, X, X
|
|
xmm2 = _mm_load_ss((float *) (src_p+count_l4+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8)); // 2, X, X, X
|
|
xmm0 = _mm_loadh_pi(xmm0, (__m64 *) (src_p+count_l4+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0)); // 3, X, 0, 1
|
|
xmm1 = xmm0; // 3, X, 0, 1
|
|
|
|
/*
|
|
movlps xmm1, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 4, 5, 0, 1
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) // 2, X, 4, 5
|
|
*/
|
|
xmm1 = _mm_loadl_pi(xmm1, (__m64 *) (src_p+count_l4+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4)); // 4, 5, 0, 1
|
|
xmm2 = _mm_shuffle_ps(xmm2, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 )); // 2, X, 4, 5
|
|
|
|
/*
|
|
movss xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, X, X
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, 6, 7
|
|
shufps xmm0, xmm3, R_SHUFFLEPS( 2, 0, 2, 0 ) // 0, 3, 6, 9
|
|
*/
|
|
xmm3 = _mm_load_ss((float *) (src_p+count_l4+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0)); // 9, X, X, X
|
|
xmm3 = _mm_loadh_pi(xmm3, (__m64 *) (src_p+count_l4+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0)); // 9, X, 6, 7
|
|
xmm0 = _mm_shuffle_ps(xmm0, xmm3, R_SHUFFLEPS( 2, 0, 2, 0 )); // 0, 3, 6, 9
|
|
/*
|
|
movlps xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 10, 11, 6, 7
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 1, 4, 7, 10
|
|
*/
|
|
xmm3 = _mm_loadl_pi(xmm3, (__m64 *)(src_p+count_l4+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4)); // 10, 11, 6, 7
|
|
xmm1 = _mm_shuffle_ps(xmm1, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 )); // 1, 4, 7, 10
|
|
/*
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 10, 11, 8, X
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 3, 2, 1 ) // 2, 5, 8, 11
|
|
*/
|
|
xmm3 = _mm_loadh_pi(xmm3, (__m64 *)(src_p+count_l4+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8)); // 10, 11, 8, X
|
|
xmm2 = _mm_shuffle_ps(xmm2, xmm3, R_SHUFFLEPS( 0, 3, 2, 1 )); // 2, 5, 8, 11
|
|
|
|
/*
|
|
add ecx, 16
|
|
add eax, 4*DRAWVERT_SIZE
|
|
*/
|
|
dst_p = dst_p + 16;
|
|
count_l4 = count_l4 + 4*DRAWVERT_SIZE;
|
|
|
|
/*
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
*/
|
|
xmm0 = _mm_mul_ps(xmm0, xmm4);
|
|
xmm1 = _mm_mul_ps(xmm1, xmm5);
|
|
xmm2 = _mm_mul_ps(xmm2, xmm6);
|
|
xmm0 = _mm_add_ps(xmm0, xmm7);
|
|
xmm0 = _mm_add_ps(xmm0, xmm1);
|
|
xmm0 = _mm_add_ps(xmm0, xmm2);
|
|
|
|
/*
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loopVert4
|
|
*/
|
|
_mm_storel_pi((__m64 *) (dst_p-16+0), xmm0);
|
|
_mm_storeh_pi((__m64 *) (dst_p-16+8), xmm0);
|
|
} while(count_l4 < 0);
|
|
}
|
|
|
|
/*
|
|
startVert1:
|
|
and edx, 3
|
|
jz done
|
|
*/
|
|
count_l1 = count_l1 & 3;
|
|
if(count_l1 != 0) {
|
|
/*
|
|
loopVert1:
|
|
movss xmm0, [esi+eax+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_XYZ_OFFSET+8]
|
|
mulss xmm0, xmm4
|
|
mulss xmm1, xmm5
|
|
mulss xmm2, xmm6
|
|
addss xmm0, xmm7
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, DRAWVERT_SIZE
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loopVert1
|
|
*/
|
|
do {
|
|
xmm0 = _mm_load_ss((float *) (src_p+count_l4+DRAWVERT_XYZ_OFFSET+0));
|
|
xmm1 = _mm_load_ss((float *) (src_p+count_l4+DRAWVERT_XYZ_OFFSET+4));
|
|
xmm2 = _mm_load_ss((float *) (src_p+count_l4+DRAWVERT_XYZ_OFFSET+8));
|
|
xmm0 = _mm_mul_ss(xmm0, xmm4);
|
|
xmm1 = _mm_mul_ss(xmm1, xmm5);
|
|
xmm2 = _mm_mul_ss(xmm2, xmm6);
|
|
xmm0 = _mm_add_ss(xmm0, xmm7);
|
|
dst_p = dst_p + 4;
|
|
xmm0 = _mm_add_ss(xmm0, xmm1);
|
|
count_l4 = count_l4 + DRAWVERT_SIZE;
|
|
xmm0 = _mm_add_ss(xmm0, xmm2);
|
|
count_l1 = count_l1 - 1;
|
|
_mm_store_ss((float *) (dst_p-4), xmm0);
|
|
} while( count_l1 != 0);
|
|
}
|
|
/*
|
|
done:
|
|
*/
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( idVec3 &min, idVec3 &max, const idDrawVert *src, const int *indexes, const int count ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( ptrdiff_t(&src->xyz) - ptrdiff_t(src) == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__m128 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
|
|
char *indexes_p;
|
|
char *src_p;
|
|
int count_l;
|
|
int edx;
|
|
char *min_p;
|
|
char *max_p;
|
|
|
|
/*
|
|
movss xmm0, idMath::INFINITY
|
|
xorps xmm1, xmm1
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
subps xmm1, xmm0
|
|
movaps xmm2, xmm0
|
|
movaps xmm3, xmm1
|
|
*/
|
|
xmm0 = _mm_load_ss(&idMath::INFINITY);
|
|
// To satisfy the compiler use xmm0 instead.
|
|
xmm1 = _mm_xor_ps(xmm0, xmm0);
|
|
xmm0 = _mm_shuffle_ps(xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm1 = _mm_sub_ps(xmm1, xmm0);
|
|
xmm2 = xmm0;
|
|
xmm3 = xmm1;
|
|
|
|
/*
|
|
mov edi, indexes
|
|
mov esi, src
|
|
mov eax, count
|
|
and eax, ~3
|
|
jz done4
|
|
*/
|
|
indexes_p = (char *) indexes;
|
|
src_p = (char *) src;
|
|
count_l = count;
|
|
count_l = count_l & ~3;
|
|
if(count_l != 0) {
|
|
/*
|
|
shl eax, 2
|
|
add edi, eax
|
|
neg eax
|
|
*/
|
|
count_l = count_l << 2;
|
|
indexes_p = indexes_p + count_l;
|
|
count_l = -count_l;
|
|
/*
|
|
loop4:
|
|
// prefetchnta [edi+128]
|
|
// prefetchnta [esi+4*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET]
|
|
*/
|
|
do {
|
|
/*
|
|
mov edx, [edi+eax+0]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
*/
|
|
edx = *((int*)(indexes_p+count_l+0));
|
|
edx = edx * DRAWVERT_SIZE;
|
|
xmm4 = _mm_load_ss((float *) (src_p+edx+DRAWVERT_XYZ_OFFSET+8));
|
|
xmm4 = _mm_loadh_pi(xmm4, (__m64 *) (src_p+edx+DRAWVERT_XYZ_OFFSET+0) );
|
|
xmm0 = _mm_min_ps(xmm0, xmm4);
|
|
xmm1 = _mm_max_ps(xmm1, xmm4);
|
|
|
|
/*
|
|
mov edx, [edi+eax+4]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm5, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm5, [esi+edx+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm5
|
|
maxps xmm3, xmm5
|
|
*/
|
|
edx = *((int*)(indexes_p+count_l+4));
|
|
edx = edx * DRAWVERT_SIZE;
|
|
xmm5 = _mm_load_ss((float *) (src_p+edx+DRAWVERT_XYZ_OFFSET+0));
|
|
xmm5 = _mm_loadh_pi(xmm5, (__m64 *) (src_p+edx+DRAWVERT_XYZ_OFFSET+4) );
|
|
xmm2 = _mm_min_ps(xmm2, xmm5);
|
|
xmm3 = _mm_max_ps(xmm3, xmm5);
|
|
|
|
/*
|
|
mov edx, [edi+eax+8]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm6, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm6, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm6
|
|
maxps xmm1, xmm6
|
|
*/
|
|
edx = *((int*)(indexes_p+count_l+8));
|
|
edx = edx * DRAWVERT_SIZE;
|
|
xmm6 = _mm_load_ss((float *) (src_p+edx+DRAWVERT_XYZ_OFFSET+8));
|
|
xmm6 = _mm_loadh_pi(xmm6, (__m64 *) (src_p+edx+DRAWVERT_XYZ_OFFSET+0) );
|
|
xmm0 = _mm_min_ps(xmm0, xmm6);
|
|
xmm1 = _mm_max_ps(xmm1, xmm6);
|
|
|
|
/*
|
|
mov edx, [edi+eax+12]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm7, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm7, [esi+edx+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm7
|
|
maxps xmm3, xmm7
|
|
*/
|
|
edx = *((int*)(indexes_p+count_l+12));
|
|
edx = edx * DRAWVERT_SIZE;
|
|
xmm7 = _mm_load_ss((float *) (src_p+edx+DRAWVERT_XYZ_OFFSET+0));
|
|
xmm7 = _mm_loadh_pi(xmm7, (__m64 *) (src_p+edx+DRAWVERT_XYZ_OFFSET+4) );
|
|
xmm2 = _mm_min_ps(xmm2, xmm7);
|
|
xmm3 = _mm_max_ps(xmm3, xmm7);
|
|
|
|
/*
|
|
add eax, 4*4
|
|
jl loop4
|
|
*/
|
|
count_l = count_l + 4*4;
|
|
} while (count_l < 0);
|
|
}
|
|
/*
|
|
done4:
|
|
mov eax, count
|
|
and eax, 3
|
|
jz done1
|
|
*/
|
|
count_l = count;
|
|
count_l = count_l & 3;
|
|
if(count_l != 0) {
|
|
/*
|
|
shl eax, 2
|
|
add edi, eax
|
|
neg eax
|
|
*/
|
|
count_l = count_l << 2;
|
|
indexes_p = indexes_p + count_l;
|
|
count_l = -count_l;
|
|
/*
|
|
loop1:
|
|
*/
|
|
do{
|
|
/*
|
|
mov edx, [edi+eax+0]
|
|
imul edx, DRAWVERT_SIZE;
|
|
movss xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
*/
|
|
edx = *((int*)(indexes_p+count_l+0));
|
|
edx = edx * DRAWVERT_SIZE;
|
|
xmm4 = _mm_load_ss((float *) (src_p+edx+DRAWVERT_XYZ_OFFSET+8));
|
|
xmm4 = _mm_loadh_pi(xmm4, (__m64 *) (src_p+edx+DRAWVERT_XYZ_OFFSET+0) );
|
|
xmm0 = _mm_min_ps(xmm0, xmm4);
|
|
xmm1 = _mm_max_ps(xmm1, xmm4);
|
|
|
|
/*
|
|
add eax, 4
|
|
jl loop1
|
|
*/
|
|
count_l = count_l + 4;
|
|
} while (count_l < 0);
|
|
|
|
}
|
|
|
|
/*
|
|
done1:
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm3
|
|
mov esi, min
|
|
movhps [esi], xmm0
|
|
movss [esi+8], xmm0
|
|
mov edi, max
|
|
movhps [edi], xmm1
|
|
movss [edi+8], xmm1
|
|
*/
|
|
xmm2 = _mm_shuffle_ps(xmm2, xmm2, R_SHUFFLEPS( 3, 1, 0, 2 ));
|
|
xmm3 = _mm_shuffle_ps(xmm3, xmm3, R_SHUFFLEPS( 3, 1, 0, 2 ));
|
|
xmm0 = _mm_min_ps(xmm0, xmm2);
|
|
xmm1 = _mm_max_ps(xmm1, xmm3);
|
|
min_p = (char *) &min;
|
|
_mm_storeh_pi((__m64 *)(min_p), xmm0);
|
|
_mm_store_ss((float *)(min_p+8), xmm0);
|
|
max_p = (char *) &max;
|
|
_mm_storeh_pi((__m64 *)(max_p), xmm1);
|
|
_mm_store_ss((float *)(max_p+8), xmm1);
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant * src[i].Normal() + src[i][3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idVec3 &constant, const idPlane *src, const int count ) {
|
|
int count_l4;
|
|
int count_l1;
|
|
char *constant_p;
|
|
char *src_p;
|
|
char *dst_p;
|
|
__m128 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
|
|
|
|
// DG: GCC and clang warn about xmm1-4 maybe being used uninitialized below.
|
|
// according to https://stackoverflow.com/a/18749079 the initialization
|
|
// code is generated anyway, so make it explicit to shut up the warning
|
|
xmm1 = _mm_setzero_ps();
|
|
xmm2 = _mm_setzero_ps();
|
|
xmm3 = _mm_setzero_ps();
|
|
xmm4 = _mm_setzero_ps();
|
|
|
|
/*
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
*/
|
|
count_l4 = count;
|
|
constant_p = (char *) &constant;
|
|
count_l1 = count_l4;
|
|
src_p = (char *) src;
|
|
dst_p = (char *) dst;
|
|
count_l4 = count_l4 & ~3;
|
|
|
|
/*
|
|
movss xmm5, [edi+0]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [edi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
*/
|
|
xmm5 = _mm_load_ss((float *) (constant_p+0));
|
|
xmm5 = _mm_shuffle_ps(xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm6 = _mm_load_ss((float *) (constant_p+4));
|
|
xmm6 = _mm_shuffle_ps(xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
xmm7 = _mm_load_ss((float *) (constant_p+8));
|
|
xmm7 = _mm_shuffle_ps(xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ));
|
|
|
|
/*
|
|
jz startVert1
|
|
*/
|
|
if (count_l4 != 0) {
|
|
/*
|
|
imul eax, 16
|
|
add esi, eax
|
|
neg eax
|
|
*/
|
|
count_l4 = count_l4 * 16;
|
|
src_p = src_p + count_l4;
|
|
count_l4 = -count_l4;
|
|
/*
|
|
loopVert4:
|
|
*/
|
|
do {
|
|
/*
|
|
movlps xmm1, [esi+eax+ 0]
|
|
movlps xmm3, [esi+eax+ 8]
|
|
movhps xmm1, [esi+eax+16]
|
|
movhps xmm3, [esi+eax+24]
|
|
movlps xmm2, [esi+eax+32]
|
|
movlps xmm4, [esi+eax+40]
|
|
movhps xmm2, [esi+eax+48]
|
|
movhps xmm4, [esi+eax+56]
|
|
movaps xmm0, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
movaps xmm2, xmm3
|
|
shufps xmm2, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm3, xmm4, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
*/
|
|
xmm1 = _mm_loadl_pi(xmm1, (__m64 *)(src_p+count_l4+ 0));
|
|
xmm3 = _mm_loadl_pi(xmm3, (__m64 *)(src_p+count_l4+ 8));
|
|
xmm1 = _mm_loadh_pi(xmm1, (__m64 *)(src_p+count_l4+16));
|
|
xmm3 = _mm_loadh_pi(xmm3, (__m64 *)(src_p+count_l4+24));
|
|
xmm2 = _mm_loadl_pi(xmm2, (__m64 *)(src_p+count_l4+32));
|
|
xmm4 = _mm_loadl_pi(xmm4, (__m64 *)(src_p+count_l4+40));
|
|
xmm2 = _mm_loadh_pi(xmm2, (__m64 *)(src_p+count_l4+48));
|
|
xmm4 = _mm_loadh_pi(xmm4, (__m64 *)(src_p+count_l4+56));
|
|
|
|
xmm0 = xmm1;
|
|
xmm0 = _mm_shuffle_ps(xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 ));
|
|
xmm1 = _mm_shuffle_ps(xmm1, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 ));
|
|
xmm2 = xmm3;
|
|
xmm2 = _mm_shuffle_ps(xmm2, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ));
|
|
xmm3 = _mm_shuffle_ps(xmm3, xmm4, R_SHUFFLEPS( 1, 3, 1, 3 ));
|
|
|
|
/*
|
|
add ecx, 16
|
|
add eax, 4*16
|
|
*/
|
|
dst_p = dst_p + 16;
|
|
count_l4 = count_l4 + 4*16;
|
|
|
|
/*
|
|
mulps xmm0, xmm5
|
|
mulps xmm1, xmm6
|
|
mulps xmm2, xmm7
|
|
addps xmm0, xmm3
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
*/
|
|
xmm0 = _mm_mul_ps(xmm0, xmm5);
|
|
xmm1 = _mm_mul_ps(xmm1, xmm6);
|
|
xmm2 = _mm_mul_ps(xmm2, xmm7);
|
|
xmm0 = _mm_add_ps(xmm0, xmm3);
|
|
xmm0 = _mm_add_ps(xmm0, xmm1);
|
|
xmm0 = _mm_add_ps(xmm0, xmm2);
|
|
|
|
/*
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loopVert4
|
|
*/
|
|
_mm_storel_pi((__m64 *) (dst_p-16+0), xmm0);
|
|
_mm_storeh_pi((__m64 *) (dst_p-16+8), xmm0);
|
|
} while (count_l4 < 0);
|
|
}
|
|
|
|
/*
|
|
startVert1:
|
|
and edx, 3
|
|
jz done
|
|
*/
|
|
count_l1 = count_l1 & 3;
|
|
|
|
if(count_l1 != 0) {
|
|
/*
|
|
loopVert1:
|
|
*/
|
|
do {
|
|
/*
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
movss xmm2, [esi+eax+8]
|
|
mulss xmm0, xmm5
|
|
mulss xmm1, xmm6
|
|
mulss xmm2, xmm7
|
|
addss xmm0, [esi+eax+12]
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, 16
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loopVert1
|
|
*/
|
|
xmm0 = _mm_load_ss((float *) (src_p+count_l4+ 0));
|
|
xmm1 = _mm_load_ss((float *) (src_p+count_l4+ 4));
|
|
xmm2 = _mm_load_ss((float *) (src_p+count_l4+ 8));
|
|
xmm3 = _mm_load_ss((float *) (src_p+count_l4+12));
|
|
|
|
xmm0 = _mm_mul_ss(xmm0, xmm5);
|
|
xmm1 = _mm_mul_ss(xmm1, xmm6);
|
|
xmm2 = _mm_mul_ss(xmm2, xmm7);
|
|
|
|
xmm0 = _mm_add_ss(xmm0, xmm3);
|
|
dst_p = dst_p + 4;
|
|
xmm0 = _mm_add_ss(xmm0, xmm1);
|
|
count_l4 = count_l4 + 16;
|
|
xmm0 = _mm_add_ss(xmm0, xmm2);
|
|
count_l1 = count_l1 - 1;
|
|
_mm_store_ss((float *) (dst_p-4), xmm0);
|
|
} while (count_l1 != 0);
|
|
}
|
|
/*
|
|
done:
|
|
*/
|
|
}
|
|
|
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
|
|
|
#include <xmmintrin.h>
|
|
|
|
#include "idlib/geometry/JointTransform.h"
|
|
#include "idlib/math/Vector.h"
|
|
#include "idlib/math/Matrix.h"
|
|
#include "idlib/math/Quat.h"
|
|
#include "idlib/math/Plane.h"
|
|
#include "renderer/Model.h"
|
|
|
|
#define SHUFFLEPS( x, y, z, w ) (( (x) & 3 ) << 6 | ( (y) & 3 ) << 4 | ( (z) & 3 ) << 2 | ( (w) & 3 ))
|
|
#define R_SHUFFLEPS( x, y, z, w ) (( (w) & 3 ) << 6 | ( (z) & 3 ) << 4 | ( (y) & 3 ) << 2 | ( (x) & 3 ))
|
|
|
|
// transpose a 4x4 matrix loaded into 4 xmm registers (reg4 is temporary)
|
|
#define TRANSPOSE_4x4( reg0, reg1, reg2, reg3, reg4 ) \
|
|
__asm movaps reg4, reg2 /* reg4 = 8, 9, 10, 11 */ \
|
|
__asm unpcklps reg2, reg3 /* reg2 = 8, 12, 9, 13 */ \
|
|
__asm unpckhps reg4, reg3 /* reg4 = 10, 14, 11, 15 */ \
|
|
__asm movaps reg3, reg0 /* reg3 = 0, 1, 2, 3 */ \
|
|
__asm unpcklps reg0, reg1 /* reg0 = 0, 4, 1, 5 */ \
|
|
__asm unpckhps reg3, reg1 /* reg3 = 2, 6, 3, 7 */ \
|
|
__asm movaps reg1, reg0 /* reg1 = 0, 4, 1, 5 */ \
|
|
__asm shufps reg0, reg2, R_SHUFFLEPS( 0, 1, 0, 1 ) /* reg0 = 0, 4, 8, 12 */ \
|
|
__asm shufps reg1, reg2, R_SHUFFLEPS( 2, 3, 2, 3 ) /* reg1 = 1, 5, 9, 13 */ \
|
|
__asm movaps reg2, reg3 /* reg2 = 2, 6, 3, 7 */ \
|
|
__asm shufps reg2, reg4, R_SHUFFLEPS( 0, 1, 0, 1 ) /* reg2 = 2, 6, 10, 14 */ \
|
|
__asm shufps reg3, reg4, R_SHUFFLEPS( 2, 3, 2, 3 ) /* reg3 = 3, 7, 11, 15 */
|
|
|
|
// transpose a 4x4 matrix from memory into 4 xmm registers (reg4 is temporary)
|
|
#define TRANPOSE_4x4_FROM_MEMORY( address, reg0, reg1, reg2, reg3, reg4 ) \
|
|
__asm movlps reg1, [address+ 0] /* reg1 = 0, 1, X, X */ \
|
|
__asm movlps reg3, [address+ 8] /* reg3 = 2, 3, X, X */ \
|
|
__asm movhps reg1, [address+16] /* reg1 = 0, 1, 4, 5 */ \
|
|
__asm movhps reg3, [address+24] /* reg3 = 2, 3, 6, 7 */ \
|
|
__asm movlps reg2, [address+32] /* reg2 = 8, 9, X, X */ \
|
|
__asm movlps reg4, [address+40] /* reg4 = 10, 11, X, X */ \
|
|
__asm movhps reg2, [address+48] /* reg2 = 8, 9, 12, 13 */ \
|
|
__asm movhps reg4, [address+56] /* reg4 = 10, 11, 14, 15 */ \
|
|
__asm movaps reg0, reg1 /* reg0 = 0, 1, 4, 5 */ \
|
|
__asm shufps reg0, reg2, R_SHUFFLEPS( 0, 2, 0, 2 ) /* reg0 = 0, 4, 8, 12 */ \
|
|
__asm shufps reg1, reg2, R_SHUFFLEPS( 1, 3, 1, 3 ) /* reg1 = 1, 5, 9, 13 */ \
|
|
__asm movaps reg2, reg3 /* reg2 = 2, 3, 6, 7 */ \
|
|
__asm shufps reg2, reg4, R_SHUFFLEPS( 0, 2, 0, 2 ) /* reg2 = 2, 6, 10, 14 */ \
|
|
__asm shufps reg3, reg4, R_SHUFFLEPS( 1, 3, 1, 3 ) /* reg3 = 3, 7, 11, 15 */
|
|
|
|
// transpose a 4x4 matrix to memory from 4 xmm registers (reg4 is temporary)
|
|
#define TRANPOSE_4x4_TO_MEMORY( address, reg0, reg1, reg2, reg3, reg4 ) \
|
|
__asm movaps reg4, reg0 /* reg4 = 0, 4, 8, 12 */ \
|
|
__asm unpcklps reg0, reg1 /* reg0 = 0, 1, 4, 5 */ \
|
|
__asm unpckhps reg4, reg1 /* reg4 = 8, 9, 12, 13 */ \
|
|
__asm movaps reg1, reg2 /* reg1 = 2, 6, 10, 14 */ \
|
|
__asm unpcklps reg2, reg3 /* reg2 = 2, 3, 6, 7 */ \
|
|
__asm unpckhps reg1, reg3 /* reg1 = 10, 11, 14, 15 */ \
|
|
__asm movlps [address+ 0], reg0 /* mem0 = 0, 1, X, X */ \
|
|
__asm movlps [address+ 8], reg2 /* mem0 = 0, 1, 2, 3 */ \
|
|
__asm movhps [address+16], reg0 /* mem1 = 4, 5, X, X */ \
|
|
__asm movhps [address+24], reg2 /* mem1 = 4, 5, 6, 7 */ \
|
|
__asm movlps [address+32], reg4 /* mem2 = 8, 9, X, X */ \
|
|
__asm movlps [address+40], reg1 /* mem2 = 8, 9, 10, 11 */ \
|
|
__asm movhps [address+48], reg4 /* mem3 = 12, 13, X, X */ \
|
|
__asm movhps [address+56], reg1 /* mem3 = 12, 13, 14, 15 */
|
|
|
|
// transpose a 4x3 matrix loaded into 3 xmm registers (reg3 is temporary)
|
|
#define TRANSPOSE_4x3( reg0, reg1, reg2, reg3 ) \
|
|
__asm movaps reg3, reg2 /* reg3 = 8, 9, 10, 11 */ \
|
|
__asm shufps reg3, reg1, R_SHUFFLEPS( 2, 3, 0, 1 ) /* reg3 = 10, 11, 4, 5 */ \
|
|
__asm shufps reg2, reg0, R_SHUFFLEPS( 0, 1, 2, 3 ) /* reg2 = 8, 9, 2, 3 */ \
|
|
__asm shufps reg1, reg0, R_SHUFFLEPS( 2, 3, 0, 1 ) /* reg1 = 6, 7, 0, 1 */ \
|
|
__asm movaps reg0, reg1 /* reg0 = 6, 7, 0, 1 */ \
|
|
__asm shufps reg0, reg2, R_SHUFFLEPS( 2, 0, 3, 1 ) /* reg0 = 0, 6, 3, 9 */ \
|
|
__asm shufps reg1, reg3, R_SHUFFLEPS( 3, 1, 2, 0 ) /* reg1 = 1, 7, 4, 10 */ \
|
|
__asm shufps reg2, reg3, R_SHUFFLEPS( 2, 0, 3, 1 ) /* reg2 = 2, 8, 5, 11 */
|
|
|
|
// transpose a 4x3 matrix from memory into 3 xmm registers (reg3 is temporary)
|
|
#define TRANSPOSE_4x3_FROM_MEMORY( address, reg0, reg1, reg2, reg3 ) \
|
|
__asm movlps reg1, [address+ 0] /* reg1 = 0, 1, X, X */ \
|
|
__asm movlps reg2, [address+ 8] /* reg2 = 2, 3, X, X */ \
|
|
__asm movlps reg3, [address+16] /* reg3 = 4, 5, X, X */ \
|
|
__asm movhps reg1, [address+24] /* reg1 = 0, 1, 6, 7 */ \
|
|
__asm movhps reg2, [address+32] /* reg2 = 2, 3, 8, 9 */ \
|
|
__asm movhps reg3, [address+40] /* reg3 = 4, 5, 10, 11 */ \
|
|
__asm movaps reg0, reg1 /* reg0 = 0, 1, 6, 7 */ \
|
|
__asm shufps reg0, reg2, R_SHUFFLEPS( 0, 2, 1, 3 ) /* reg0 = 0, 6, 3, 9 */ \
|
|
__asm shufps reg1, reg3, R_SHUFFLEPS( 1, 3, 0, 2 ) /* reg1 = 1, 7, 4, 10 */ \
|
|
__asm shufps reg2, reg3, R_SHUFFLEPS( 0, 2, 1, 3 ) /* reg2 = 2, 8, 5, 11 */
|
|
|
|
// transpose a 4x3 matrix to memory from 3 xmm registers (reg3 is temporary)
|
|
#define TRANSPOSE_4x3_TO_MEMORY( address, reg0, reg1, reg2, reg3 ) \
|
|
__asm movhlps reg3, reg0 /* reg3 = 3, 9, X, X */ \
|
|
__asm unpcklps reg0, reg1 /* reg0 = 0, 1, 6, 7 */ \
|
|
__asm unpckhps reg1, reg2 /* reg1 = 4, 5, 10, 11 */ \
|
|
__asm unpcklps reg2, reg3 /* reg2 = 2, 3, 8, 9 */ \
|
|
__asm movlps [address+ 0], reg0 /* mem0 = 0, 1, X, X */ \
|
|
__asm movlps [address+ 8], reg2 /* mem0 = 0, 1, 2, 3 */ \
|
|
__asm movlps [address+16], reg1 /* mem1 = 4, 5, X, X */ \
|
|
__asm movhps [address+24], reg0 /* mem1 = 4, 5, 6, 7 */ \
|
|
__asm movhps [address+32], reg2 /* mem2 = 8, 9, X, X */ \
|
|
__asm movhps [address+40], reg1 /* mem2 = 8, 9, 10, 11 */
|
|
|
|
|
|
// with alignment
|
|
#define KFLOATINITS( SRC0, COUNT, PRE, POST ) KFLOATINITDSS( SRC0,SRC0,SRC0,COUNT,PRE,POST )
|
|
#define KFLOATINITD( DST, COUNT, PRE, POST ) KFLOATINITDSS( DST,DST,DST,COUNT,PRE,POST )
|
|
#define KFLOATINITDS( DST, SRC0, COUNT, PRE, POST ) KFLOATINITDSS( DST,SRC0,SRC0,COUNT,PRE,POST )
|
|
|
|
#define KFLOATINITDSS( DST, SRC0, SRC1, COUNT, PRE, POST )\
|
|
__asm mov ecx,DST \
|
|
__asm shr ecx,2 \
|
|
__asm mov ebx,COUNT \
|
|
__asm neg ecx \
|
|
__asm mov edx,SRC0 \
|
|
__asm and ecx,3 \
|
|
__asm mov esi,SRC1 \
|
|
__asm sub ebx,ecx \
|
|
__asm jge noUnderFlow \
|
|
__asm xor ebx,ebx \
|
|
__asm mov ecx,COUNT \
|
|
__asm noUnderFlow: \
|
|
__asm mov PRE,ecx \
|
|
__asm mov eax,ebx \
|
|
__asm mov edi,DST \
|
|
__asm and eax,8-1 \
|
|
__asm mov POST,eax \
|
|
__asm and ebx,0xfffffff8 \
|
|
__asm jle done \
|
|
__asm shl ebx,2 \
|
|
__asm lea ecx,[ecx*4+ebx] \
|
|
__asm neg ebx \
|
|
__asm add edx,ecx \
|
|
__asm add esi,ecx \
|
|
__asm add edi,ecx \
|
|
__asm mov eax,edx \
|
|
__asm or eax,esi
|
|
|
|
// without alignment (pre==0)
|
|
#define KFLOATINITS_NA( SRC0, COUNT, PRE, POST ) KFLOATINITDSS_NA( SRC0,SRC0,SRC0,COUNT,PRE,POST )
|
|
#define KFLOATINITD_NA( DST, COUNT, PRE, POST ) KFLOATINITDSS_NA( DST,DST,DST,COUNT,PRE,POST )
|
|
#define KFLOATINITDS_NA( DST, SRC0, COUNT, PRE, POST ) KFLOATINITDSS_NA( DST,SRC0,SRC0,COUNT,PRE,POST )
|
|
#define KFLOATINITDSS_NA( DST, SRC0, SRC1, COUNT, PRE, POST )\
|
|
__asm mov eax,COUNT \
|
|
__asm mov PRE,0 \
|
|
__asm and eax,8-1 \
|
|
__asm mov ebx,COUNT \
|
|
__asm mov POST,eax \
|
|
__asm and ebx,0xfffffff8 \
|
|
__asm je done \
|
|
__asm shl ebx,2 \
|
|
__asm mov edx,SRC0 \
|
|
__asm mov esi,SRC1 \
|
|
__asm mov edi,DST \
|
|
__asm add edx,ebx \
|
|
__asm add esi,ebx \
|
|
__asm add edi,ebx \
|
|
__asm mov eax,edx \
|
|
__asm or eax,esi \
|
|
__asm or eax,edi \
|
|
__asm neg ebx \
|
|
|
|
/*
|
|
when OPER is called:
|
|
edx = s0
|
|
esi = s1
|
|
edi = d
|
|
ebx = index*4
|
|
|
|
xmm0 & xmm1 must not be trashed
|
|
*/
|
|
#define KMOVDS1( DST, SRC0 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm movss DST,xmm2
|
|
#define KMOVDS4( DST, SRC0 ) \
|
|
__asm movups xmm2,SRC0 \
|
|
__asm movups DST,xmm2
|
|
#define KMINDS1( DST, SRC0 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm minss DST,xmm2
|
|
#define KMAXDS1( DST, SRC0 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm maxss DST,xmm2
|
|
|
|
// general ALU operation
|
|
#define KALUDSS1( OP, DST, SRC0, SRC1 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm OP##ss xmm2,SRC1 \
|
|
__asm movss DST,xmm2
|
|
#define KALUDSS4( OP, DST, SRC0, SRC1 ) \
|
|
__asm movups xmm2,SRC0 \
|
|
__asm movups xmm3,SRC1 \
|
|
__asm OP##ps xmm2,xmm3 \
|
|
__asm movups DST,xmm2
|
|
|
|
#define KADDDSS1( DST, SRC0, SRC1 ) KALUDSS1( add, DST,SRC0,SRC1 )
|
|
#define KADDDSS4( DST, SRC0, SRC1 ) KALUDSS4( add, DST,SRC0,SRC1 )
|
|
#define KSUBDSS1( DST, SRC0, SRC1 ) KALUDSS1( sub, DST,SRC0,SRC1 )
|
|
#define KSUBDSS4( DST, SRC0, SRC1 ) KALUDSS4( sub, DST,SRC0,SRC1 )
|
|
#define KMULDSS1( DST, SRC0, SRC1 ) KALUDSS1( mul, DST,SRC0,SRC1 )
|
|
#define KMULDSS4( DST, SRC0, SRC1 ) KALUDSS4( mul, DST,SRC0,SRC1 )
|
|
|
|
#define KDIVDSS1( DST, SRC0, SRC1 ) \
|
|
__asm movss xmm2,SRC1 \
|
|
__asm rcpss xmm3,xmm2 \
|
|
__asm mulss xmm2,xmm3 \
|
|
__asm mulss xmm2,xmm3 \
|
|
__asm addss xmm3,xmm3 \
|
|
__asm subss xmm3,xmm2 \
|
|
__asm mulss xmm3,SRC0 \
|
|
__asm movss DST,xmm3
|
|
#define KDIVDSS4( DST, SRC0, SRC1 ) \
|
|
__asm movups xmm2,SRC1 \
|
|
__asm rcpps xmm3,xmm2 \
|
|
__asm mulps xmm2,xmm3 \
|
|
__asm mulps xmm2,xmm3 \
|
|
__asm addps xmm3,xmm3 \
|
|
__asm subps xmm3,xmm2 \
|
|
__asm movups xmm2,SRC0 \
|
|
__asm mulps xmm3,xmm2 \
|
|
__asm movups DST,xmm3
|
|
#define KF2IDS1( SRC0 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm cvttps2pi mm2,xmm2 \
|
|
__asm movd [edi+ebx],mm2
|
|
#define KF2IDS4( SRC0 ) \
|
|
__asm movups xmm2,SRC0 \
|
|
__asm cvttps2pi mm2,xmm2 \
|
|
__asm movq [edi+ebx+0],mm2 \
|
|
__asm shufps xmm2,xmm2,SHUFFLEPS(1,0,3,2) \
|
|
__asm cvttps2pi mm2,xmm2 \
|
|
__asm movq [edi+ebx+8],mm2
|
|
#define KISQRTDS1( DST,SRC0 ) \
|
|
__asm movss xmm2,SRC0 \
|
|
__asm rsqrtss xmm3,xmm2 \
|
|
__asm mulss xmm2,xmm3 \
|
|
__asm mulss xmm2,xmm3 \
|
|
__asm subss xmm2,xmm1 \
|
|
__asm mulss xmm3,xmm0 \
|
|
__asm mulss xmm3,xmm2 \
|
|
__asm movss DST,xmm3
|
|
#define KISQRTDS4( DST,SRC0 ) \
|
|
__asm movups xmm2,SRC0 \
|
|
__asm rsqrtps xmm3,xmm2 \
|
|
__asm mulps xmm2,xmm3 \
|
|
__asm mulps xmm2,xmm3 \
|
|
__asm subps xmm2,xmm1 \
|
|
__asm mulps xmm3,xmm0 \
|
|
__asm mulps xmm3,xmm2 \
|
|
__asm movups DST,xmm3
|
|
|
|
// this is used in vector4 implementation to shift constant V4
|
|
#define KANDREGDSV( DST, SRC0, VALUE ) \
|
|
__asm mov DST,SRC0 \
|
|
__asm and DST,VALUE
|
|
|
|
// this is used in vector4 code to operate with float arrays as sources
|
|
#define KEXPANDFLOAT( DST, SRC ) \
|
|
__asm movss DST,SRC \
|
|
__asm shufps DST,DST,0
|
|
|
|
#define KADDDS1( DST,SRC ) KADDDSS1( DST,DST,SRC )
|
|
#define KADDDS4( DST,SRC ) KADDDSS4( DST,DST,SRC )
|
|
#define KSUBDS1( DST,SRC ) KSUBDSS1( DST,DST,SRC )
|
|
#define KSUBDS4( DST,SRC ) KSUBDSS4( DST,DST,SRC )
|
|
#define KMULDS1( DST,SRC ) KMULDSS1( DST,DST,SRC )
|
|
#define KMULDS4( DST,SRC ) KMULDSS4( DST,DST,SRC )
|
|
#define KDIVDS1( DST,SRC ) KDIVDSS1( DST,DST,SRC )
|
|
#define KDIVDS4( DST,SRC ) KDIVDSS4( DST,DST,SRC )
|
|
|
|
// handles pre & post leftovers
|
|
#define KFLOATOPER( OPER, OPER4, COUNT ) \
|
|
__asm mov ecx,pre \
|
|
__asm mov ebx,COUNT \
|
|
__asm cmp ebx,ecx \
|
|
__asm cmovl ecx,COUNT \
|
|
__asm test ecx,ecx \
|
|
__asm je preDone \
|
|
__asm xor ebx,ebx \
|
|
__asm lpPre: \
|
|
OPER \
|
|
__asm add ebx,4 \
|
|
__asm dec ecx \
|
|
__asm jg lpPre \
|
|
__asm preDone: \
|
|
__asm mov ecx,post \
|
|
__asm mov ebx,COUNT \
|
|
__asm sub ebx,ecx \
|
|
__asm shl ebx,2 \
|
|
__asm cmp ecx,4 \
|
|
__asm jl post4Done \
|
|
OPER4 \
|
|
__asm sub ecx,4 \
|
|
__asm add ebx,4*4 \
|
|
__asm post4Done: \
|
|
__asm test ecx,ecx \
|
|
__asm je postDone \
|
|
__asm lpPost: \
|
|
OPER \
|
|
__asm add ebx,4 \
|
|
__asm dec ecx \
|
|
__asm jg lpPost \
|
|
__asm postDone:
|
|
|
|
// operate on a constant and a float array
|
|
#define KFLOAT_CA( ALUOP, DST, SRC, CONSTANT, COUNT ) \
|
|
int pre,post; \
|
|
__asm movss xmm0,CONSTANT \
|
|
__asm shufps xmm0,xmm0,0 \
|
|
KFLOATINITDS( DST, SRC, COUNT, pre, post ) \
|
|
__asm and eax,15 \
|
|
__asm jne lpNA \
|
|
__asm jmp lpA \
|
|
__asm align 16 \
|
|
__asm lpA: \
|
|
__asm prefetchnta [edx+ebx+64] \
|
|
__asm movaps xmm1,xmm0 \
|
|
__asm movaps xmm2,xmm0 \
|
|
__asm ALUOP##ps xmm1,[edx+ebx] \
|
|
__asm ALUOP##ps xmm2,[edx+ebx+16] \
|
|
__asm movaps [edi+ebx],xmm1 \
|
|
__asm movaps [edi+ebx+16],xmm2 \
|
|
__asm add ebx,16*2 \
|
|
__asm jl lpA \
|
|
__asm jmp done \
|
|
__asm align 16 \
|
|
__asm lpNA: \
|
|
__asm prefetchnta [edx+ebx+64] \
|
|
__asm movaps xmm1,xmm0 \
|
|
__asm movaps xmm2,xmm0 \
|
|
__asm movups xmm3,[edx+ebx] \
|
|
__asm movups xmm4,[edx+ebx+16] \
|
|
__asm ALUOP##ps xmm1,xmm3 \
|
|
__asm ALUOP##ps xmm2,xmm4 \
|
|
__asm movaps [edi+ebx],xmm1 \
|
|
__asm movaps [edi+ebx+16],xmm2 \
|
|
__asm add ebx,16*2 \
|
|
__asm jl lpNA \
|
|
__asm done: \
|
|
__asm mov edx,SRC \
|
|
__asm mov edi,DST \
|
|
__asm KFLOATOPER( KALUDSS1( ALUOP, [edi+ebx],xmm0,[edx+ebx] ), \
|
|
__asm KALUDSS4( ALUOP, [edi+ebx],xmm0,[edx+ebx] ), COUNT )
|
|
|
|
// operate on two float arrays
|
|
#define KFLOAT_AA( ALUOP, DST, SRC0, SRC1, COUNT ) \
|
|
int pre,post; \
|
|
KFLOATINITDSS( DST, SRC0, SRC1, COUNT, pre, post ) \
|
|
__asm and eax,15 \
|
|
__asm jne lpNA \
|
|
__asm jmp lpA \
|
|
__asm align 16 \
|
|
__asm lpA: \
|
|
__asm movaps xmm1,[edx+ebx] \
|
|
__asm movaps xmm2,[edx+ebx+16] \
|
|
__asm ALUOP##ps xmm1,[esi+ebx] \
|
|
__asm ALUOP##ps xmm2,[esi+ebx+16] \
|
|
__asm prefetchnta [edx+ebx+64] \
|
|
__asm prefetchnta [esi+ebx+64] \
|
|
__asm movaps [edi+ebx],xmm1 \
|
|
__asm movaps [edi+ebx+16],xmm2 \
|
|
__asm add ebx,16*2 \
|
|
__asm jl lpA \
|
|
__asm jmp done \
|
|
__asm align 16 \
|
|
__asm lpNA: \
|
|
__asm movups xmm1,[edx+ebx] \
|
|
__asm movups xmm2,[edx+ebx+16] \
|
|
__asm movups xmm3,[esi+ebx] \
|
|
__asm movups xmm4,[esi+ebx+16] \
|
|
__asm prefetchnta [edx+ebx+64] \
|
|
__asm prefetchnta [esi+ebx+64] \
|
|
__asm ALUOP##ps xmm1,xmm3 \
|
|
__asm ALUOP##ps xmm2,xmm4 \
|
|
__asm movaps [edi+ebx],xmm1 \
|
|
__asm movaps [edi+ebx+16],xmm2 \
|
|
__asm add ebx,16*2 \
|
|
__asm jl lpNA \
|
|
__asm done: \
|
|
__asm mov edx,SRC0 \
|
|
__asm mov esi,SRC1 \
|
|
__asm mov edi,DST \
|
|
KFLOATOPER( KALUDSS1( ALUOP, [edi+ebx],[edx+ebx],[esi+ebx] ), \
|
|
KALUDSS4( ALUOP, [edi+ebx],[edx+ebx],[esi+ebx] ), COUNT )
|
|
|
|
|
|
#define DRAWVERT_SIZE 60
|
|
|
|
#define JOINTQUAT_SIZE (7*4)
|
|
#define JOINTMAT_SIZE (4*3*4)
|
|
#define JOINTWEIGHT_SIZE (4*4)
|
|
|
|
|
|
#define ALIGN4_INIT1( X, INIT ) ALIGN16( static X[4] ) = { INIT, INIT, INIT, INIT }
|
|
#define ALIGN4_INIT4( X, I0, I1, I2, I3 ) ALIGN16( static X[4] ) = { I0, I1, I2, I3 }
|
|
#define ALIGN8_INIT1( X, INIT ) ALIGN16( static X[8] ) = { INIT, INIT, INIT, INIT, INIT, INIT, INIT, INIT }
|
|
|
|
ALIGN8_INIT1( unsigned short SIMD_W_zero, 0 );
|
|
ALIGN8_INIT1( unsigned short SIMD_W_maxShort, 1<<15 );
|
|
|
|
ALIGN4_INIT1( unsigned int SIMD_DW_mat2quatShuffle0, (3<<0)|(2<<8)|(1<<16)|(0<<24) );
|
|
ALIGN4_INIT1( unsigned int SIMD_DW_mat2quatShuffle1, (0<<0)|(1<<8)|(2<<16)|(3<<24) );
|
|
ALIGN4_INIT1( unsigned int SIMD_DW_mat2quatShuffle2, (1<<0)|(0<<8)|(3<<16)|(2<<24) );
|
|
ALIGN4_INIT1( unsigned int SIMD_DW_mat2quatShuffle3, (2<<0)|(3<<8)|(0<<16)|(1<<24) );
|
|
|
|
ALIGN4_INIT4( unsigned int SIMD_SP_singleSignBitMask, (unsigned int) ( 1 << 31 ), 0, 0, 0 );
|
|
ALIGN4_INIT1( unsigned int SIMD_SP_signBitMask, (unsigned int) ( 1 << 31 ) );
|
|
ALIGN4_INIT1( unsigned int SIMD_SP_absMask, (unsigned int) ~( 1 << 31 ) );
|
|
ALIGN4_INIT1( unsigned int SIMD_SP_infinityMask, (unsigned int) ~( 1 << 23 ) );
|
|
ALIGN4_INIT1( unsigned int SIMD_SP_not, 0xFFFFFFFF );
|
|
|
|
ALIGN4_INIT1( float SIMD_SP_zero, 0.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_half, 0.5f );
|
|
ALIGN4_INIT1( float SIMD_SP_one, 1.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_two, 2.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_three, 3.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_four, 4.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_maxShort, (1<<15) );
|
|
ALIGN4_INIT1( float SIMD_SP_tiny, 1e-10f );
|
|
ALIGN4_INIT1( float SIMD_SP_PI, idMath::PI );
|
|
ALIGN4_INIT1( float SIMD_SP_halfPI, idMath::HALF_PI );
|
|
ALIGN4_INIT1( float SIMD_SP_twoPI, idMath::TWO_PI );
|
|
ALIGN4_INIT1( float SIMD_SP_oneOverTwoPI, 1.0f / idMath::TWO_PI );
|
|
ALIGN4_INIT1( float SIMD_SP_infinity, idMath::INFINITY );
|
|
ALIGN4_INIT4( float SIMD_SP_lastOne, 0.0f, 0.0f, 0.0f, 1.0f );
|
|
|
|
ALIGN4_INIT1( float SIMD_SP_rsqrt_c0, 3.0f );
|
|
ALIGN4_INIT1( float SIMD_SP_rsqrt_c1, -0.5f );
|
|
ALIGN4_INIT1( float SIMD_SP_mat2quat_rsqrt_c1, -0.5f*0.5f );
|
|
|
|
ALIGN4_INIT1( float SIMD_SP_sin_c0, -2.39e-08f );
|
|
ALIGN4_INIT1( float SIMD_SP_sin_c1, 2.7526e-06f );
|
|
ALIGN4_INIT1( float SIMD_SP_sin_c2, -1.98409e-04f );
|
|
ALIGN4_INIT1( float SIMD_SP_sin_c3, 8.3333315e-03f );
|
|
ALIGN4_INIT1( float SIMD_SP_sin_c4, -1.666666664e-01f );
|
|
|
|
ALIGN4_INIT1( float SIMD_SP_cos_c0, -2.605e-07f );
|
|
ALIGN4_INIT1( float SIMD_SP_cos_c1, 2.47609e-05f );
|
|
ALIGN4_INIT1( float SIMD_SP_cos_c2, -1.3888397e-03f );
|
|
ALIGN4_INIT1( float SIMD_SP_cos_c3, 4.16666418e-02f );
|
|
ALIGN4_INIT1( float SIMD_SP_cos_c4, -4.999999963e-01f );
|
|
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c0, 0.0028662257f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c1, -0.0161657367f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c2, 0.0429096138f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c3, -0.0752896400f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c4, 0.1065626393f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c5, -0.1420889944f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c6, 0.1999355085f );
|
|
ALIGN4_INIT1( float SIMD_SP_atan_c7, -0.3333314528f );
|
|
|
|
/*
|
|
============
|
|
SSE_InvSqrt
|
|
============
|
|
*/
|
|
float SSE_InvSqrt( float x ) {
|
|
float y;
|
|
|
|
__asm {
|
|
movss xmm0, x
|
|
rsqrtss xmm1, xmm0
|
|
mulss xmm0, xmm1
|
|
mulss xmm0, xmm1
|
|
subss xmm0, SIMD_SP_rsqrt_c0
|
|
mulss xmm1, SIMD_SP_rsqrt_c1
|
|
mulss xmm0, xmm1
|
|
movss y, xmm0
|
|
}
|
|
return y;
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_InvSqrt4
|
|
============
|
|
*/
|
|
void SSE_InvSqrt4( float x[4] ) {
|
|
__asm {
|
|
mov edi, x
|
|
movaps xmm0, [edi]
|
|
rsqrtps xmm1, xmm0
|
|
mulps xmm0, xmm1
|
|
mulps xmm0, xmm1
|
|
subps xmm0, SIMD_SP_rsqrt_c0
|
|
mulps xmm1, SIMD_SP_rsqrt_c1
|
|
mulps xmm0, xmm1
|
|
movaps [edi], xmm0
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_SinZeroHalfPI
|
|
|
|
The angle must be between zero and half PI.
|
|
============
|
|
*/
|
|
float SSE_SinZeroHalfPI( float a ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
assert( a >= 0.0f && a <= idMath::HALF_PI );
|
|
|
|
__asm {
|
|
movss xmm0, a
|
|
movss xmm1, xmm0
|
|
mulss xmm1, xmm1
|
|
movss xmm2, SIMD_SP_sin_c0
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c1
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c2
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c3
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c4
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_one
|
|
mulss xmm2, xmm0
|
|
movss t, xmm2
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float s, t;
|
|
|
|
assert( a >= 0.0f && a <= idMath::HALF_PI );
|
|
|
|
s = a * a;
|
|
t = -2.39e-08f;
|
|
t *= s;
|
|
t += 2.7526e-06f;
|
|
t *= s;
|
|
t += -1.98409e-04f;
|
|
t *= s;
|
|
t += 8.3333315e-03f;
|
|
t *= s;
|
|
t += -1.666666664e-01f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
t *= a;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Sin4ZeroHalfPI
|
|
|
|
The angle must be between zero and half PI.
|
|
============
|
|
*/
|
|
void SSE_Sin4ZeroHalfPI( float a[4], float s[4] ) {
|
|
__asm {
|
|
mov edi, a
|
|
mov esi, s
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, xmm0
|
|
mulps xmm1, xmm1
|
|
movaps xmm2, SIMD_SP_sin_c0
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c1
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c2
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c3
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c4
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_one
|
|
mulps xmm2, xmm0
|
|
movaps [esi], xmm2
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Sin
|
|
============
|
|
*/
|
|
float SSE_Sin( float a ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
__asm {
|
|
movss xmm1, a
|
|
movss xmm2, xmm1
|
|
movss xmm3, xmm1
|
|
mulss xmm2, SIMD_SP_oneOverTwoPI
|
|
cvttss2si ecx, xmm2
|
|
cmpltss xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
cvtsi2ss xmm2, ecx
|
|
subss xmm2, xmm3
|
|
mulss xmm2, SIMD_SP_twoPI
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subss xmm0, xmm1 // xmm0 = PI - a
|
|
movss xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movss xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltss xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movss xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
movss xmm1, xmm0
|
|
mulss xmm1, xmm1
|
|
movss xmm2, SIMD_SP_sin_c0
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c1
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c2
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c3
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_sin_c4
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_one
|
|
mulss xmm2, xmm0
|
|
movss t, xmm2
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float s, t;
|
|
|
|
if ( ( a < 0.0f ) || ( a >= idMath::TWO_PI ) ) {
|
|
a -= floorf( a / idMath::TWO_PI ) * idMath::TWO_PI;
|
|
}
|
|
|
|
a = idMath::PI - a;
|
|
if ( fabs( a ) >= idMath::HALF_PI ) {
|
|
a = ( ( a < 0.0f ) ? -idMath::PI : idMath::PI ) - a;
|
|
}
|
|
|
|
s = a * a;
|
|
t = -2.39e-08f;
|
|
t *= s;
|
|
t += 2.7526e-06f;
|
|
t *= s;
|
|
t += -1.98409e-04f;
|
|
t *= s;
|
|
t += 8.3333315e-03f;
|
|
t *= s;
|
|
t += -1.666666664e-01f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
t *= a;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Sin4
|
|
============
|
|
*/
|
|
void SSE_Sin4( float a[4], float s[4] ) {
|
|
__asm {
|
|
mov edi, a
|
|
mov esi, s
|
|
movaps xmm1, [edi]
|
|
movaps xmm2, xmm1
|
|
mulps xmm2, SIMD_SP_oneOverTwoPI
|
|
movhlps xmm3, xmm2
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 0, 1, 0 )
|
|
movaps xmm3, xmm1
|
|
cmpltps xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
subps xmm2, xmm3
|
|
mulps xmm2, SIMD_SP_twoPI
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subps xmm0, xmm1 // xmm0 = PI - a
|
|
movaps xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movaps xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltps xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movaps xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
movaps xmm1, xmm0
|
|
mulps xmm1, xmm1
|
|
movaps xmm2, SIMD_SP_sin_c0
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c1
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c2
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c3
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_sin_c4
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_one
|
|
mulps xmm2, xmm0
|
|
movaps [esi], xmm2
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_CosZeroHalfPI
|
|
|
|
The angle must be between zero and half PI.
|
|
============
|
|
*/
|
|
float SSE_CosZeroHalfPI( float a ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
assert( a >= 0.0f && a <= idMath::HALF_PI );
|
|
|
|
__asm {
|
|
movss xmm0, a
|
|
mulss xmm0, xmm0
|
|
movss xmm1, SIMD_SP_cos_c0
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c1
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c2
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c3
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c4
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_one
|
|
movss t, xmm1
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float s, t;
|
|
|
|
assert( a >= 0.0f && a <= idMath::HALF_PI );
|
|
|
|
s = a * a;
|
|
t = -2.605e-07f;
|
|
t *= s;
|
|
t += 2.47609e-05f;
|
|
t *= s;
|
|
t += -1.3888397e-03f;
|
|
t *= s;
|
|
t += 4.16666418e-02f;
|
|
t *= s;
|
|
t += -4.999999963e-01f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Cos4ZeroHalfPI
|
|
|
|
The angle must be between zero and half PI.
|
|
============
|
|
*/
|
|
void SSE_Cos4ZeroHalfPI( float a[4], float c[4] ) {
|
|
__asm {
|
|
mov edi, a
|
|
mov esi, c
|
|
movaps xmm0, [edi]
|
|
mulps xmm0, xmm0
|
|
movaps xmm1, SIMD_SP_cos_c0
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c1
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c2
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c3
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c4
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_one
|
|
movaps [esi], xmm2
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Cos
|
|
============
|
|
*/
|
|
float SSE_Cos( float a ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
__asm {
|
|
movss xmm1, a
|
|
movss xmm2, xmm1
|
|
movss xmm3, xmm1
|
|
mulss xmm2, SIMD_SP_oneOverTwoPI
|
|
cvttss2si ecx, xmm2
|
|
cmpltss xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
cvtsi2ss xmm2, ecx
|
|
subss xmm2, xmm3
|
|
mulss xmm2, SIMD_SP_twoPI
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subss xmm0, xmm1 // xmm0 = PI - a
|
|
movss xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movss xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltss xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movss xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
mulss xmm0, xmm0
|
|
movss xmm1, SIMD_SP_cos_c0
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c1
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c2
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c3
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_cos_c4
|
|
mulss xmm1, xmm0
|
|
addss xmm1, SIMD_SP_one
|
|
xorps xmm2, SIMD_SP_signBitMask
|
|
xorps xmm1, xmm2
|
|
movss t, xmm1
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float s, t;
|
|
|
|
if ( ( a < 0.0f ) || ( a >= idMath::TWO_PI ) ) {
|
|
a -= floorf( a / idMath::TWO_PI ) * idMath::TWO_PI;
|
|
}
|
|
|
|
a = idMath::PI - a;
|
|
if ( fabs( a ) >= idMath::HALF_PI ) {
|
|
a = ( ( a < 0.0f ) ? -idMath::PI : idMath::PI ) - a;
|
|
d = 1.0f;
|
|
} else {
|
|
d = -1.0f;
|
|
}
|
|
|
|
s = a * a;
|
|
t = -2.605e-07f;
|
|
t *= s;
|
|
t += 2.47609e-05f;
|
|
t *= s;
|
|
t += -1.3888397e-03f;
|
|
t *= s;
|
|
t += 4.16666418e-02f;
|
|
t *= s;
|
|
t += -4.999999963e-01f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
t *= d;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_Cos4
|
|
============
|
|
*/
|
|
void SSE_Cos4( float a[4], float c[4] ) {
|
|
__asm {
|
|
mov edi, a
|
|
mov esi, c
|
|
movaps xmm1, [edi]
|
|
movaps xmm2, xmm1
|
|
mulps xmm2, SIMD_SP_oneOverTwoPI
|
|
movhlps xmm3, xmm2
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 0, 1, 0 )
|
|
movaps xmm3, xmm1
|
|
cmpltps xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
subps xmm2, xmm3
|
|
mulps xmm2, SIMD_SP_twoPI
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subps xmm0, xmm1 // xmm0 = PI - a
|
|
movaps xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movaps xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltps xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movaps xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
mulps xmm0, xmm0
|
|
movaps xmm1, SIMD_SP_cos_c0
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c1
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c2
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c3
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_cos_c4
|
|
mulps xmm1, xmm0
|
|
addps xmm1, SIMD_SP_one
|
|
xorps xmm2, SIMD_SP_signBitMask
|
|
xorps xmm1, xmm2
|
|
movaps [esi], xmm1
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_SinCos
|
|
============
|
|
*/
|
|
void SSE_SinCos( float a, float &s, float &c ) {
|
|
__asm {
|
|
mov edi, s
|
|
mov esi, c
|
|
movss xmm1, a
|
|
movss xmm2, xmm1
|
|
movss xmm3, xmm1
|
|
mulss xmm2, SIMD_SP_oneOverTwoPI
|
|
cvttss2si ecx, xmm2
|
|
cmpltss xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
cvtsi2ss xmm2, ecx
|
|
subss xmm2, xmm3
|
|
mulss xmm2, SIMD_SP_twoPI
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subss xmm0, xmm1 // xmm0 = PI - a
|
|
movss xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movss xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltss xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movss xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
movss xmm1, xmm0
|
|
mulss xmm1, xmm1
|
|
movss xmm3, SIMD_SP_sin_c0
|
|
movss xmm4, SIMD_SP_cos_c0
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm1
|
|
addss xmm3, SIMD_SP_sin_c1
|
|
addss xmm4, SIMD_SP_cos_c1
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm1
|
|
addss xmm3, SIMD_SP_sin_c2
|
|
addss xmm4, SIMD_SP_cos_c2
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm1
|
|
addss xmm3, SIMD_SP_sin_c3
|
|
addss xmm4, SIMD_SP_cos_c3
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm1
|
|
addss xmm3, SIMD_SP_sin_c4
|
|
addss xmm4, SIMD_SP_cos_c4
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm1
|
|
addss xmm3, SIMD_SP_one
|
|
addss xmm4, SIMD_SP_one
|
|
mulss xmm3, xmm0
|
|
xorps xmm2, SIMD_SP_signBitMask
|
|
xorps xmm4, xmm2
|
|
movss [edi], xmm2
|
|
movss [esi], xmm3
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_SinCos4
|
|
============
|
|
*/
|
|
void SSE_SinCos4( float a[4], float s[4], float c[4] ) {
|
|
__asm {
|
|
mov eax, a
|
|
mov edi, s
|
|
mov esi, c
|
|
movaps xmm1, [eax]
|
|
movaps xmm2, xmm1
|
|
mulps xmm2, SIMD_SP_oneOverTwoPI
|
|
movhlps xmm3, xmm2
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
cvttss2si ecx, xmm2
|
|
cvtsi2ss xmm2, ecx
|
|
cvttss2si edx, xmm3
|
|
cvtsi2ss xmm3, edx
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 0, 1, 0 )
|
|
movaps xmm3, xmm1
|
|
cmpltps xmm3, SIMD_SP_zero
|
|
andps xmm3, SIMD_SP_one
|
|
subps xmm2, xmm3
|
|
mulps xmm2, SIMD_SP_twoPI
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm0, SIMD_SP_PI // xmm0 = PI
|
|
subps xmm0, xmm1 // xmm0 = PI - a
|
|
movaps xmm1, xmm0 // xmm1 = PI - a
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signbit( PI - a )
|
|
movaps xmm2, xmm0 // xmm2 = PI - a
|
|
xorps xmm2, xmm1 // xmm2 = fabs( PI - a )
|
|
cmpnltps xmm2, SIMD_SP_halfPI // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? 0xFFFFFFFF : 0x00000000
|
|
movaps xmm3, SIMD_SP_PI // xmm3 = PI
|
|
xorps xmm3, xmm1 // xmm3 = PI ^ signbit( PI - a )
|
|
andps xmm3, xmm2 // xmm3 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? ( PI ^ signbit( PI - a ) ) : 0.0f
|
|
andps xmm2, SIMD_SP_signBitMask // xmm2 = ( fabs( PI - a ) >= idMath::HALF_PI ) ? SIMD_SP_signBitMask : 0.0f
|
|
xorps xmm0, xmm2
|
|
addps xmm0, xmm3
|
|
|
|
movaps xmm0, [eax]
|
|
movaps xmm1, xmm0
|
|
mulps xmm1, xmm1
|
|
movaps xmm3, SIMD_SP_sin_c0
|
|
movaps xmm4, SIMD_SP_cos_c0
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, SIMD_SP_sin_c1
|
|
addps xmm4, SIMD_SP_cos_c1
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, SIMD_SP_sin_c2
|
|
addps xmm4, SIMD_SP_cos_c2
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, SIMD_SP_sin_c3
|
|
addps xmm4, SIMD_SP_cos_c3
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, SIMD_SP_sin_c4
|
|
addps xmm4, SIMD_SP_cos_c4
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, SIMD_SP_one
|
|
addps xmm4, SIMD_SP_one
|
|
mulps xmm3, xmm0
|
|
xorps xmm2, SIMD_SP_signBitMask
|
|
xorps xmm4, xmm2
|
|
movaps [edi], xmm3
|
|
movaps [esi], xmm4
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_ATanPositive
|
|
|
|
Both 'x' and 'y' must be positive.
|
|
============
|
|
*/
|
|
float SSE_ATanPositive( float y, float x ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
assert( y >= 0.0f && x >= 0.0f );
|
|
|
|
__asm {
|
|
movss xmm0, x
|
|
movss xmm3, xmm0
|
|
movss xmm1, y
|
|
minss xmm0, xmm1
|
|
maxss xmm1, xmm3
|
|
cmpeqss xmm3, xmm0
|
|
rcpss xmm2, xmm1
|
|
mulss xmm1, xmm2
|
|
mulss xmm1, xmm2
|
|
addss xmm2, xmm2
|
|
subss xmm2, xmm1 // xmm2 = 1 / y or 1 / x
|
|
mulss xmm0, xmm2 // xmm0 = x / y or y / x
|
|
movss xmm1, xmm3
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
xorps xmm0, xmm1 // xmm0 = -x / y or y / x
|
|
andps xmm3, SIMD_SP_halfPI // xmm3 = HALF_PI or 0.0f
|
|
movss xmm1, xmm0
|
|
mulss xmm1, xmm1 // xmm1 = s
|
|
movss xmm2, SIMD_SP_atan_c0
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c1
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c2
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c3
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c4
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c5
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c6
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c7
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_one
|
|
mulss xmm2, xmm0
|
|
addss xmm2, xmm3
|
|
movss t, xmm2
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float a, d, s, t;
|
|
|
|
assert( y >= 0.0f && x >= 0.0f );
|
|
|
|
if ( y > x ) {
|
|
a = -x / y;
|
|
d = idMath::HALF_PI;
|
|
} else {
|
|
a = y / x;
|
|
d = 0.0f;
|
|
}
|
|
s = a * a;
|
|
t = 0.0028662257f;
|
|
t *= s;
|
|
t += -0.0161657367f;
|
|
t *= s;
|
|
t += 0.0429096138f;
|
|
t *= s;
|
|
t += -0.0752896400f;
|
|
t *= s;
|
|
t += 0.1065626393f;
|
|
t *= s;
|
|
t += -0.1420889944f;
|
|
t *= s;
|
|
t += 0.1999355085f;
|
|
t *= s;
|
|
t += -0.3333314528f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
t *= a;
|
|
t += d;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_ATan4Positive
|
|
|
|
Both 'x' and 'y' must be positive.
|
|
============
|
|
*/
|
|
void SSE_ATan4Positive( float y[4], float x[4], float at[4] ) {
|
|
__asm {
|
|
mov esi, x
|
|
mov edi, y
|
|
mov edx, at
|
|
movaps xmm0, [esi]
|
|
movaps xmm3, xmm0
|
|
movaps xmm1, [edi]
|
|
minps xmm0, xmm1
|
|
maxps xmm1, xmm3
|
|
cmpeqps xmm3, xmm0
|
|
rcpps xmm2, xmm1
|
|
mulps xmm1, xmm2
|
|
mulps xmm1, xmm2
|
|
addps xmm2, xmm2
|
|
subps xmm2, xmm1 // xmm2 = 1 / y or 1 / x
|
|
mulps xmm0, xmm2 // xmm0 = x / y or y / x
|
|
movaps xmm1, xmm3
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
xorps xmm0, xmm1 // xmm0 = -x / y or y / x
|
|
andps xmm3, SIMD_SP_halfPI // xmm3 = HALF_PI or 0.0f
|
|
movaps xmm1, xmm0
|
|
mulps xmm1, xmm1 // xmm1 = s
|
|
movaps xmm2, SIMD_SP_atan_c0
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c1
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c2
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c3
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c4
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c5
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c6
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c7
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_one
|
|
mulps xmm2, xmm0
|
|
addps xmm2, xmm3
|
|
movaps [edx], xmm2
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_ATan
|
|
============
|
|
*/
|
|
float SSE_ATan( float y, float x ) {
|
|
#if 1
|
|
|
|
float t;
|
|
|
|
__asm {
|
|
movss xmm0, x
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm0
|
|
andps xmm0, SIMD_SP_absMask
|
|
movss xmm1, y
|
|
xorps xmm4, xmm1
|
|
andps xmm1, SIMD_SP_absMask
|
|
andps xmm4, SIMD_SP_signBitMask
|
|
minss xmm0, xmm1
|
|
maxss xmm1, xmm3
|
|
cmpeqss xmm3, xmm0
|
|
rcpss xmm2, xmm1
|
|
mulss xmm1, xmm2
|
|
mulss xmm1, xmm2
|
|
addss xmm2, xmm2
|
|
subss xmm2, xmm1 // xmm2 = 1 / y or 1 / x
|
|
mulss xmm0, xmm2 // xmm0 = x / y or y / x
|
|
xorps xmm0, xmm4
|
|
movss xmm1, xmm3
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
xorps xmm0, xmm1 // xmm0 = -x / y or y / x
|
|
orps xmm4, SIMD_SP_halfPI // xmm4 = +/- HALF_PI
|
|
andps xmm3, xmm4 // xmm3 = +/- HALF_PI or 0.0f
|
|
movss xmm1, xmm0
|
|
mulss xmm1, xmm1 // xmm1 = s
|
|
movss xmm2, SIMD_SP_atan_c0
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c1
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c2
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c3
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c4
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c5
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c6
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_atan_c7
|
|
mulss xmm2, xmm1
|
|
addss xmm2, SIMD_SP_one
|
|
mulss xmm2, xmm0
|
|
addss xmm2, xmm3
|
|
movss t, xmm2
|
|
}
|
|
|
|
return t;
|
|
|
|
#else
|
|
|
|
float a, d, s, t;
|
|
|
|
if ( fabs( y ) > fabs( x ) ) {
|
|
a = -x / y;
|
|
d = idMath::HALF_PI;
|
|
*((unsigned int *)&d) ^= ( *((unsigned int *)&x) ^ *((unsigned int *)&y) ) & (1<<31);
|
|
} else {
|
|
a = y / x;
|
|
d = 0.0f;
|
|
}
|
|
|
|
s = a * a;
|
|
t = 0.0028662257f;
|
|
t *= s;
|
|
t += -0.0161657367f;
|
|
t *= s;
|
|
t += 0.0429096138f;
|
|
t *= s;
|
|
t += -0.0752896400f;
|
|
t *= s;
|
|
t += 0.1065626393f;
|
|
t *= s;
|
|
t += -0.1420889944f;
|
|
t *= s;
|
|
t += 0.1999355085f;
|
|
t *= s;
|
|
t += -0.3333314528f;
|
|
t *= s;
|
|
t += 1.0f;
|
|
t *= a;
|
|
t += d;
|
|
|
|
return t;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_ATan4
|
|
============
|
|
*/
|
|
void SSE_ATan4( float y[4], float x[4], float at[4] ) {
|
|
__asm {
|
|
mov esi, x
|
|
mov edi, y
|
|
mov edx, at
|
|
movaps xmm0, [esi]
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm0
|
|
andps xmm0, SIMD_SP_absMask
|
|
movaps xmm1, [edi]
|
|
xorps xmm4, xmm1
|
|
andps xmm1, SIMD_SP_absMask
|
|
andps xmm4, SIMD_SP_signBitMask
|
|
minps xmm0, xmm1
|
|
maxps xmm1, xmm3
|
|
cmpeqps xmm3, xmm0
|
|
rcpps xmm2, xmm1
|
|
mulps xmm1, xmm2
|
|
mulps xmm1, xmm2
|
|
addps xmm2, xmm2
|
|
subps xmm2, xmm1 // xmm2 = 1 / y or 1 / x
|
|
mulps xmm0, xmm2 // xmm0 = x / y or y / x
|
|
xorps xmm0, xmm4
|
|
movaps xmm1, xmm3
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
xorps xmm0, xmm1 // xmm0 = -x / y or y / x
|
|
orps xmm4, SIMD_SP_halfPI // xmm4 = +/- HALF_PI
|
|
andps xmm3, xmm4 // xmm3 = +/- HALF_PI or 0.0f
|
|
movaps xmm1, xmm0
|
|
mulps xmm1, xmm1 // xmm1 = s
|
|
movaps xmm2, SIMD_SP_atan_c0
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c1
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c2
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c3
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c4
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c5
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c6
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_atan_c7
|
|
mulps xmm2, xmm1
|
|
addps xmm2, SIMD_SP_one
|
|
mulps xmm2, xmm0
|
|
addps xmm2, xmm3
|
|
movaps [edx], xmm2
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_TestTrigonometry
|
|
============
|
|
*/
|
|
void SSE_TestTrigonometry( void ) {
|
|
int i;
|
|
float a, s1, s2, c1, c2;
|
|
|
|
for ( i = 0; i < 100; i++ ) {
|
|
a = i * idMath::HALF_PI / 100.0f;
|
|
|
|
s1 = sin( a );
|
|
s2 = SSE_SinZeroHalfPI( a );
|
|
|
|
if ( fabs( s1 - s2 ) > 1e-7f ) {
|
|
assert( 0 );
|
|
}
|
|
|
|
c1 = cos( a );
|
|
c2 = SSE_CosZeroHalfPI( a );
|
|
|
|
if ( fabs( c1 - c2 ) > 1e-7f ) {
|
|
assert( 0 );
|
|
}
|
|
}
|
|
|
|
for ( i = -200; i < 200; i++ ) {
|
|
a = i * idMath::TWO_PI / 100.0f;
|
|
|
|
s1 = sin( a );
|
|
s2 = SSE_Sin( a );
|
|
|
|
if ( fabs( s1 - s2 ) > 1e-6f ) {
|
|
assert( 0 );
|
|
}
|
|
|
|
c1 = cos( a );
|
|
c2 = SSE_Cos( a );
|
|
|
|
if ( fabs( c1 - c2 ) > 1e-6f ) {
|
|
assert( 0 );
|
|
}
|
|
|
|
SSE_SinCos( a, s2, c2 );
|
|
if ( fabs( s1 - s2 ) > 1e-6f || fabs( c1 - c2 ) > 1e-6f ) {
|
|
assert( 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::GetName
|
|
============
|
|
*/
|
|
const char * idSIMD_SSE::GetName( void ) const {
|
|
return "MMX & SSE";
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Add
|
|
|
|
dst[i] = constant + src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Add( float *dst, const float constant, const float *src, const int count ) {
|
|
KFLOAT_CA( add, dst, src, constant, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Add
|
|
|
|
dst[i] = src0[i] + src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Add( float *dst, const float *src0, const float *src1, const int count ) {
|
|
KFLOAT_AA( add, dst, src0, src1, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Sub
|
|
|
|
dst[i] = constant - src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Sub( float *dst, const float constant, const float *src, const int count ) {
|
|
KFLOAT_CA( sub, dst, src, constant, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Sub
|
|
|
|
dst[i] = src0[i] - src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Sub( float *dst, const float *src0, const float *src1, const int count ) {
|
|
KFLOAT_AA( sub, dst, src0, src1, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Mul
|
|
|
|
dst[i] = constant * src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Mul( float *dst, const float constant, const float *src, const int count ) {
|
|
KFLOAT_CA( mul, dst, src, constant, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Mul
|
|
|
|
dst[i] = src0[i] * src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Mul( float *dst, const float *src0, const float *src1, const int count ) {
|
|
KFLOAT_AA( mul, dst, src0, src1, count )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Div
|
|
|
|
dst[i] = constant / src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Div( float *dst, const float constant, const float *src, const int count ) {
|
|
int pre, post;
|
|
|
|
// 1 / x = 2 * rcpps(x) - (x * rcpps(x) * rcpps(x));
|
|
__asm
|
|
{
|
|
movss xmm1,constant
|
|
shufps xmm1,xmm1,0
|
|
|
|
KFLOATINITDS( dst, src, count, pre, post )
|
|
and eax,15
|
|
jne lpNA
|
|
jmp lpA
|
|
align 16
|
|
lpA:
|
|
movaps xmm2,[edx+ebx]
|
|
movaps xmm3,[edx+ebx+16]
|
|
rcpps xmm4,xmm2
|
|
rcpps xmm5,xmm3
|
|
prefetchnta [edx+ebx+64]
|
|
mulps xmm2,xmm4
|
|
mulps xmm2,xmm4
|
|
mulps xmm3,xmm5
|
|
mulps xmm3,xmm5
|
|
addps xmm4,xmm4
|
|
addps xmm5,xmm5
|
|
subps xmm4,xmm2
|
|
subps xmm5,xmm3
|
|
mulps xmm4,xmm1
|
|
mulps xmm5,xmm1
|
|
movaps [edi+ebx],xmm4
|
|
movaps [edi+ebx+16],xmm5
|
|
add ebx,16*2
|
|
jl lpA
|
|
jmp done
|
|
align 16
|
|
lpNA:
|
|
movups xmm2,[edx+ebx]
|
|
movups xmm3,[edx+ebx+16]
|
|
rcpps xmm4,xmm2
|
|
rcpps xmm5,xmm3
|
|
prefetchnta [edx+ebx+64]
|
|
mulps xmm2,xmm4
|
|
mulps xmm2,xmm4
|
|
mulps xmm3,xmm5
|
|
mulps xmm3,xmm5
|
|
addps xmm4,xmm4
|
|
addps xmm5,xmm5
|
|
subps xmm4,xmm2
|
|
subps xmm5,xmm3
|
|
mulps xmm4,xmm1
|
|
mulps xmm5,xmm1
|
|
movaps [edi+ebx],xmm4
|
|
movaps [edi+ebx+16],xmm5
|
|
add ebx,16*2
|
|
jl lpNA
|
|
done:
|
|
mov edx,src
|
|
mov edi,dst
|
|
KFLOATOPER( KDIVDSS1( [edi+ebx],xmm1,[edx+ebx] ),
|
|
KDIVDSS4( [edi+ebx],xmm1,[edx+ebx] ), count )
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Div
|
|
|
|
dst[i] = src0[i] / src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Div( float *dst, const float *src0, const float *src1, const int count ) {
|
|
int pre,post;
|
|
|
|
// 1 / x = 2 * rcpps(x) - (x * rcpps(x) * rcpps(x));
|
|
__asm
|
|
{
|
|
KFLOATINITDSS( dst, src0, src1, count, pre, post )
|
|
and eax,15
|
|
jne lpNA
|
|
jmp lpA
|
|
align 16
|
|
lpA:
|
|
movaps xmm2,[esi+ebx]
|
|
movaps xmm3,[esi+ebx+16]
|
|
rcpps xmm4,xmm2
|
|
rcpps xmm5,xmm3
|
|
prefetchnta [esi+ebx+64]
|
|
mulps xmm2,xmm4
|
|
mulps xmm2,xmm4
|
|
mulps xmm3,xmm5
|
|
mulps xmm3,xmm5
|
|
addps xmm4,xmm4
|
|
addps xmm5,xmm5
|
|
subps xmm4,xmm2
|
|
subps xmm5,xmm3
|
|
mulps xmm4,[edx+ebx]
|
|
mulps xmm5,[edx+ebx+16]
|
|
movaps [edi+ebx],xmm4
|
|
movaps [edi+ebx+16],xmm5
|
|
add ebx,16*2
|
|
jl lpA
|
|
jmp done
|
|
align 16
|
|
lpNA:
|
|
movups xmm2,[esi+ebx]
|
|
movups xmm3,[esi+ebx+16]
|
|
rcpps xmm4,xmm2
|
|
rcpps xmm5,xmm3
|
|
prefetchnta [esi+ebx+64]
|
|
mulps xmm2,xmm4
|
|
mulps xmm2,xmm4
|
|
mulps xmm3,xmm5
|
|
mulps xmm3,xmm5
|
|
addps xmm4,xmm4
|
|
addps xmm5,xmm5
|
|
subps xmm4,xmm2
|
|
subps xmm5,xmm3
|
|
movups xmm2,[edx+ebx]
|
|
movups xmm3,[edx+ebx+16]
|
|
mulps xmm4,xmm2
|
|
mulps xmm5,xmm3
|
|
movaps [edi+ebx],xmm4
|
|
movaps [edi+ebx+16],xmm5
|
|
add ebx,16*2
|
|
jl lpNA
|
|
done:
|
|
mov edx,src0
|
|
mov esi,src1
|
|
mov edi,dst
|
|
KFLOATOPER( KDIVDSS1( [edi+ebx],[edx+ebx],[esi+ebx] ),
|
|
KDIVDSS4( [edi+ebx],[edx+ebx],[esi+ebx] ), count )
|
|
}
|
|
}
|
|
/*
|
|
============
|
|
Simd_MulAdd
|
|
|
|
assumes count >= 7
|
|
============
|
|
*/
|
|
static void Simd_MulAdd( float *dst, const float constant, const float *src, const int count ) {
|
|
__asm mov esi, dst
|
|
__asm mov edi, src
|
|
__asm mov eax, count
|
|
__asm shl eax, 2
|
|
__asm mov ecx, esi
|
|
__asm mov edx, eax
|
|
__asm or ecx, edi
|
|
__asm fld constant
|
|
__asm and ecx, 15
|
|
__asm jz SimdMulAdd16
|
|
__asm and ecx, 3
|
|
__asm jnz SimdMulAdd8
|
|
__asm mov ecx, esi
|
|
__asm xor ecx, edi
|
|
__asm and ecx, 15
|
|
__asm jnz MulAdd8
|
|
__asm mov ecx, esi
|
|
__asm and ecx, 15
|
|
__asm neg ecx
|
|
__asm add ecx, 16
|
|
__asm sub eax, ecx
|
|
__asm add edi, ecx
|
|
__asm add esi, ecx
|
|
__asm neg ecx
|
|
__asm mov edx, eax
|
|
__asm loopPreMulAdd16:
|
|
__asm fld st
|
|
__asm fmul dword ptr [edi+ecx]
|
|
__asm fadd dword ptr [esi+ecx]
|
|
__asm fstp dword ptr [esi+ecx]
|
|
__asm add ecx, 4
|
|
__asm jl loopPreMulAdd16
|
|
__asm SimdMulAdd16:
|
|
__asm and eax, ~15
|
|
__asm movss xmm1, constant
|
|
__asm shufps xmm1, xmm1, 0x00
|
|
__asm add esi, eax
|
|
__asm add edi, eax
|
|
__asm neg eax
|
|
__asm align 16
|
|
__asm loopMulAdd16:
|
|
__asm movaps xmm0, [edi+eax]
|
|
__asm mulps xmm0, xmm1
|
|
__asm addps xmm0, [esi+eax]
|
|
__asm movaps [esi+eax], xmm0
|
|
__asm add eax, 16
|
|
__asm jl loopMulAdd16
|
|
__asm jmp postMulAdd
|
|
__asm MulAdd8:
|
|
__asm mov ecx, esi
|
|
__asm and ecx, 7
|
|
__asm jz SimdMulAdd8
|
|
__asm sub eax, ecx
|
|
__asm add esi, ecx
|
|
__asm add edi, ecx
|
|
__asm neg ecx
|
|
__asm mov edx, eax
|
|
__asm loopPreMulAdd8:
|
|
__asm fld st
|
|
__asm fmul dword ptr [edi+ecx]
|
|
__asm fadd dword ptr [esi+ecx]
|
|
__asm fstp dword ptr [esi+ecx]
|
|
__asm add ecx, 4
|
|
__asm jl loopPreMulAdd8
|
|
__asm SimdMulAdd8:
|
|
__asm and eax, ~15
|
|
__asm movss xmm1, constant
|
|
__asm shufps xmm1, xmm1, 0x00
|
|
__asm add esi, eax
|
|
__asm add edi, eax
|
|
__asm neg eax
|
|
__asm align 16
|
|
__asm loopMulAdd8:
|
|
__asm movlps xmm0, [edi+eax]
|
|
__asm movhps xmm0, [edi+eax+8]
|
|
__asm mulps xmm0, xmm1
|
|
__asm movlps xmm2, [esi+eax]
|
|
__asm movhps xmm2, [esi+eax+8]
|
|
__asm addps xmm0, xmm2
|
|
__asm movlps [esi+eax], xmm0
|
|
__asm movhps [esi+eax+8], xmm0
|
|
__asm add eax, 16
|
|
__asm jl loopMulAdd8
|
|
__asm jmp postMulAdd
|
|
__asm postMulAdd:
|
|
__asm and edx, 15
|
|
__asm jz MulAddDone
|
|
__asm add esi, edx
|
|
__asm add edi, edx
|
|
__asm neg edx
|
|
__asm loopPostMulAdd:
|
|
__asm fld st
|
|
__asm fmul dword ptr [edi+edx]
|
|
__asm fadd dword ptr [esi+edx]
|
|
__asm fstp dword ptr [esi+edx]
|
|
__asm add edx, 4
|
|
__asm jl loopPostMulAdd
|
|
__asm MulAddDone:
|
|
__asm fstp st
|
|
}
|
|
|
|
#define MULADD_FEW( OPER ) \
|
|
switch( count ) { \
|
|
case 0: \
|
|
return; \
|
|
case 1: \
|
|
dst[0] OPER c * src[0]; \
|
|
return; \
|
|
case 2: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; \
|
|
return; \
|
|
case 3: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; \
|
|
return; \
|
|
case 4: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
return; \
|
|
case 5: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; \
|
|
return; \
|
|
case 6: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; \
|
|
return; \
|
|
case 7: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; dst[6] OPER c * src[6]; \
|
|
return; \
|
|
case 8: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; dst[6] OPER c * src[6]; dst[7] OPER c * src[7]; \
|
|
return; \
|
|
case 9: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; dst[6] OPER c * src[6]; dst[7] OPER c * src[7]; \
|
|
dst[8] OPER c * src[8]; \
|
|
return; \
|
|
case 10: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; dst[6] OPER c * src[6]; dst[7] OPER c * src[7]; \
|
|
dst[8] OPER c * src[8]; dst[9] OPER c * src[9]; \
|
|
return; \
|
|
case 11: \
|
|
dst[0] OPER c * src[0]; dst[1] OPER c * src[1]; dst[2] OPER c * src[2]; dst[3] OPER c * src[3]; \
|
|
dst[4] OPER c * src[4]; dst[5] OPER c * src[5]; dst[6] OPER c * src[6]; dst[7] OPER c * src[7]; \
|
|
dst[8] OPER c * src[8]; dst[9] OPER c * src[9]; dst[10] OPER c * src[10]; \
|
|
return; \
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MulAdd
|
|
|
|
dst[i] += constant * src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MulAdd( float *dst, const float constant, const float *src, const int count ) {
|
|
float c = constant;
|
|
MULADD_FEW( += )
|
|
Simd_MulAdd( dst, constant, src, count );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MulAdd
|
|
|
|
dst[i] += src0[i] * src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MulAdd( float *dst, const float *src0, const float *src1, const int count ) {
|
|
for ( int i = 0; i < count; i++ ) {
|
|
dst[i] += src0[i] + src1[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MulSub
|
|
|
|
dst[i] -= constant * src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MulSub( float *dst, const float constant, const float *src, const int count ) {
|
|
float c = constant;
|
|
MULADD_FEW( -= )
|
|
Simd_MulAdd( dst, -constant, src, count );
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MulSub
|
|
|
|
dst[i] -= src0[i] * src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MulSub( float *dst, const float *src0, const float *src1, const int count ) {
|
|
for ( int i = 0; i < count; i++ ) {
|
|
dst[i] -= src0[i] + src1[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant * src[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idVec3 &constant, const idVec3 *src, const int count ) {
|
|
__asm
|
|
{
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
movss xmm4, [edi+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [edi+4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
jz done4
|
|
imul eax, 12
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
movlps xmm1, [esi+eax+ 0]
|
|
movlps xmm2, [esi+eax+ 8]
|
|
movlps xmm3, [esi+eax+16]
|
|
movhps xmm1, [esi+eax+24]
|
|
movhps xmm2, [esi+eax+32]
|
|
movhps xmm3, [esi+eax+40]
|
|
movaps xmm0, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 1, 3, 0, 2 )
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
add ecx, 16
|
|
add eax, 4*12
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loop4
|
|
|
|
done4:
|
|
and edx, 3
|
|
jz done1
|
|
|
|
loop1:
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
movss xmm2, [esi+eax+8]
|
|
mulss xmm0, xmm4
|
|
mulss xmm1, xmm5
|
|
mulss xmm2, xmm6
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, 12
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loop1
|
|
|
|
done1:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant * src[i].Normal() + src[i][3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idVec3 &constant, const idPlane *src, const int count ) {
|
|
__asm {
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
movss xmm5, [edi+0]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [edi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
jz startVert1
|
|
imul eax, 16
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopVert4:
|
|
|
|
movlps xmm1, [esi+eax+ 0]
|
|
movlps xmm3, [esi+eax+ 8]
|
|
movhps xmm1, [esi+eax+16]
|
|
movhps xmm3, [esi+eax+24]
|
|
movlps xmm2, [esi+eax+32]
|
|
movlps xmm4, [esi+eax+40]
|
|
movhps xmm2, [esi+eax+48]
|
|
movhps xmm4, [esi+eax+56]
|
|
movaps xmm0, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
movaps xmm2, xmm3
|
|
shufps xmm2, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm3, xmm4, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
|
|
add ecx, 16
|
|
add eax, 4*16
|
|
|
|
mulps xmm0, xmm5
|
|
mulps xmm1, xmm6
|
|
mulps xmm2, xmm7
|
|
addps xmm0, xmm3
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loopVert4
|
|
|
|
startVert1:
|
|
and edx, 3
|
|
jz done
|
|
|
|
loopVert1:
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
movss xmm2, [esi+eax+8]
|
|
mulss xmm0, xmm5
|
|
mulss xmm1, xmm6
|
|
mulss xmm2, xmm7
|
|
addss xmm0, [esi+eax+12]
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, 16
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loopVert1
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant * src[i].xyz;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idVec3 &constant, const idDrawVert *src, const int count ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
// 0, 1, 2
|
|
// 3, 4, 5
|
|
// 6, 7, 8
|
|
// 9, 10, 11
|
|
|
|
__asm {
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
movss xmm4, [edi+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [edi+4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
jz startVert1
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopVert4:
|
|
movss xmm0, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, X, X
|
|
movss xmm2, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 2, X, X, X
|
|
movhps xmm0, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, 0, 1
|
|
movaps xmm1, xmm0 // 3, X, 0, 1
|
|
|
|
movlps xmm1, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 4, 5, 0, 1
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) // 2, X, 4, 5
|
|
|
|
movss xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, X, X
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, 6, 7
|
|
shufps xmm0, xmm3, R_SHUFFLEPS( 2, 0, 2, 0 ) // 0, 3, 6, 9
|
|
|
|
movlps xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 10, 11, 6, 7
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 1, 4, 7, 10
|
|
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 10, 11, 8, X
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 3, 2, 1 ) // 2, 5, 8, 11
|
|
|
|
add ecx, 16
|
|
add eax, 4*DRAWVERT_SIZE
|
|
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loopVert4
|
|
|
|
startVert1:
|
|
and edx, 3
|
|
jz done
|
|
|
|
loopVert1:
|
|
movss xmm0, [esi+eax+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_XYZ_OFFSET+8]
|
|
mulss xmm0, xmm4
|
|
mulss xmm1, xmm5
|
|
mulss xmm2, xmm6
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, DRAWVERT_SIZE
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loopVert1
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant.Normal() * src[i] + constant[3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idPlane &constant, const idVec3 *src, const int count ) {
|
|
__asm
|
|
{
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
movss xmm4, [edi+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [edi+4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [edi+12]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
jz done4
|
|
imul eax, 12
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
movlps xmm1, [esi+eax+ 0]
|
|
movlps xmm2, [esi+eax+ 8]
|
|
movlps xmm3, [esi+eax+16]
|
|
movhps xmm1, [esi+eax+24]
|
|
movhps xmm2, [esi+eax+32]
|
|
movhps xmm3, [esi+eax+40]
|
|
movaps xmm0, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 1, 3, 0, 2 )
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
|
|
add ecx, 16
|
|
add eax, 4*12
|
|
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loop4
|
|
|
|
done4:
|
|
and edx, 3
|
|
jz done1
|
|
|
|
loop1:
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
movss xmm2, [esi+eax+8]
|
|
mulss xmm0, xmm4
|
|
mulss xmm1, xmm5
|
|
mulss xmm2, xmm6
|
|
addss xmm0, xmm7
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, 12
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loop1
|
|
|
|
done1:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant.Normal() * src[i].Normal() + constant[3] * src[i][3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idPlane &constant, const idPlane *src, const int count ) {
|
|
|
|
#define SINGLE_OP(SRC, DEST) \
|
|
__asm movlps xmm0,[SRC] \
|
|
__asm movlps xmm1,[SRC+8] \
|
|
__asm mulps xmm0,xmm4 \
|
|
__asm mulps xmm1,xmm5 \
|
|
__asm addps xmm0,xmm1 \
|
|
__asm movaps xmm1,xmm0 \
|
|
__asm shufps xmm1,xmm1,SHUFFLEPS(1,1,1,1) \
|
|
__asm addss xmm0,xmm1 \
|
|
__asm movss [DEST],xmm0 \
|
|
__asm add SRC,16 \
|
|
__asm add DEST,4
|
|
|
|
#define DUAL_OP(SRC, DEST) \
|
|
__asm movlps xmm0,[SRC] \
|
|
__asm movlps xmm1,[SRC+8] \
|
|
__asm movhps xmm0,[SRC+16] \
|
|
__asm movhps xmm1,[SRC+24] \
|
|
__asm mulps xmm0,xmm4 \
|
|
__asm mulps xmm1,xmm5 \
|
|
__asm addps xmm0,xmm1 \
|
|
__asm shufps xmm1,xmm0,SHUFFLEPS(2,0,1,0) \
|
|
__asm shufps xmm0,xmm0,SHUFFLEPS(3,1,2,0) \
|
|
__asm addps xmm0,xmm1 \
|
|
__asm movhps [DEST],xmm0 \
|
|
__asm add SRC,32 \
|
|
__asm add DEST,8
|
|
|
|
__asm {
|
|
mov edx, dst
|
|
mov eax, src
|
|
mov ebx, constant
|
|
mov ecx, count
|
|
|
|
movlps xmm4, [ebx]
|
|
shufps xmm4, xmm4, SHUFFLEPS(1,0,1,0)
|
|
movlps xmm5, [ebx+8]
|
|
shufps xmm5, xmm5, SHUFFLEPS(1,0,1,0)
|
|
|
|
xorps xmm0, xmm0
|
|
xorps xmm1, xmm1
|
|
|
|
_lpAlignDest:
|
|
test edx, 0x0f
|
|
jz _destAligned
|
|
SINGLE_OP(eax,edx)
|
|
dec ecx
|
|
jnz _lpAlignDest
|
|
jmp _vpExit
|
|
|
|
_destAligned:
|
|
push ecx
|
|
|
|
cmp ecx, 4
|
|
jl _post
|
|
|
|
and ecx, ~3
|
|
shl ecx, 2
|
|
lea eax, [eax+ecx*4]
|
|
add edx, ecx
|
|
neg ecx
|
|
|
|
movlps xmm0, [eax+ecx*4]
|
|
movhps xmm0, [eax+ecx*4+16]
|
|
movlps xmm2, [eax+ecx*4+32]
|
|
movhps xmm2, [eax+ecx*4+48]
|
|
jmp _lpStart
|
|
|
|
align 16
|
|
_lp:
|
|
prefetchnta [eax+ecx*4+128]
|
|
addps xmm1, xmm0
|
|
movlps xmm0, [eax+ecx*4]
|
|
movhps xmm0, [eax+ecx*4+16]
|
|
movlps xmm2, [eax+ecx*4+32]
|
|
movhps xmm2, [eax+ecx*4+48]
|
|
movaps [edx+ecx-16],xmm1
|
|
_lpStart:
|
|
movlps xmm1, [eax+ecx*4+8]
|
|
movhps xmm1, [eax+ecx*4+24]
|
|
movlps xmm3, [eax+ecx*4+40]
|
|
movhps xmm3, [eax+ecx*4+56]
|
|
add ecx, 16
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm4
|
|
mulps xmm3, xmm5
|
|
addps xmm2, xmm3 // y3+w3 x3+z3 y2+w2 x2+z2
|
|
mulps xmm0, xmm4
|
|
addps xmm0, xmm1 // y1+w1 x1+z1 y0+w0 x0+z0
|
|
movaps xmm1, xmm0
|
|
shufps xmm0, xmm2, SHUFFLEPS(2,0,2,0) // x3+z3 x2+z2 x1+z1 x0+z0
|
|
shufps xmm1, xmm2, SHUFFLEPS(3,1,3,1) // y3+w3 y2+w2 y1+w1 y0+w0
|
|
js _lp
|
|
addps xmm1, xmm0
|
|
movaps [edx+ecx-16], xmm1
|
|
_post:
|
|
pop ecx
|
|
and ecx, 0x3
|
|
cmp ecx, 2
|
|
jl _post1
|
|
DUAL_OP(eax,edx)
|
|
sub ecx, 2
|
|
_post1:
|
|
cmp ecx, 1
|
|
jne _vpExit
|
|
SINGLE_OP(eax,edx)
|
|
_vpExit:
|
|
}
|
|
|
|
#undef DUAL_OP
|
|
#undef SINGLE_OP
|
|
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = constant.Normal() * src[i].xyz + constant[3];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idPlane &constant, const idDrawVert *src, const int count ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
// 0, 1, 2
|
|
// 3, 4, 5
|
|
// 6, 7, 8
|
|
// 9, 10, 11
|
|
|
|
__asm {
|
|
mov eax, count
|
|
mov edi, constant
|
|
mov edx, eax
|
|
mov esi, src
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
movss xmm4, [edi+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [edi+4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [edi+8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [edi+12]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
jz startVert1
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopVert4:
|
|
movss xmm0, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, X, X
|
|
movss xmm2, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 2, X, X, X
|
|
movhps xmm0, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 3, X, 0, 1
|
|
movaps xmm1, xmm0 // 3, X, 0, 1
|
|
|
|
movlps xmm1, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 4, 5, 0, 1
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) // 2, X, 4, 5
|
|
|
|
movss xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, X, X
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0] // 9, X, 6, 7
|
|
shufps xmm0, xmm3, R_SHUFFLEPS( 2, 0, 2, 0 ) // 0, 3, 6, 9
|
|
|
|
movlps xmm3, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4] // 10, 11, 6, 7
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 1, 4, 7, 10
|
|
|
|
movhps xmm3, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8] // 10, 11, 8, X
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 3, 2, 1 ) // 2, 5, 8, 11
|
|
|
|
add ecx, 16
|
|
add eax, 4*DRAWVERT_SIZE
|
|
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
|
|
movlps [ecx-16+0], xmm0
|
|
movhps [ecx-16+8], xmm0
|
|
jl loopVert4
|
|
|
|
startVert1:
|
|
and edx, 3
|
|
jz done
|
|
|
|
loopVert1:
|
|
movss xmm0, [esi+eax+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_XYZ_OFFSET+8]
|
|
mulss xmm0, xmm4
|
|
mulss xmm1, xmm5
|
|
mulss xmm2, xmm6
|
|
addss xmm0, xmm7
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, DRAWVERT_SIZE
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loopVert1
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dst[i] = src0[i] * src1[i];
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float *dst, const idVec3 *src0, const idVec3 *src1, const int count ) {
|
|
__asm
|
|
{
|
|
mov eax, count
|
|
mov edi, src0
|
|
mov edx, eax
|
|
mov esi, src1
|
|
mov ecx, dst
|
|
and eax, ~3
|
|
|
|
jz done4
|
|
imul eax, 12
|
|
add edi, eax
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
movlps xmm0, [esi+eax] // 0, 1, X, X
|
|
movlps xmm3, [edi+eax] // 0, 1, X, X
|
|
movlps xmm1, [esi+eax+8] // 2, 3, X, X
|
|
movlps xmm4, [edi+eax+8] // 2, 3, X, X
|
|
movhps xmm0, [esi+eax+24] // 0, 1, 6, 7
|
|
movhps xmm3, [edi+eax+24] // 0, 1, 6, 7
|
|
movhps xmm1, [esi+eax+32] // 2, 3, 8, 9
|
|
movhps xmm4, [edi+eax+32] // 2, 3, 8, 9
|
|
movlps xmm2, [esi+eax+16] // 4, 5, X, X
|
|
movlps xmm5, [edi+eax+16] // 4, 5, X, X
|
|
movhps xmm2, [esi+eax+40] // 4, 5, 10, 11
|
|
movhps xmm5, [edi+eax+40] // 4, 5, 10, 11
|
|
|
|
add ecx, 16
|
|
add eax, 48
|
|
|
|
mulps xmm0, xmm3
|
|
mulps xmm1, xmm4
|
|
mulps xmm2, xmm5
|
|
movaps xmm7, xmm0
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 ) // 0, 6, 3, 9
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 1, 3, 0, 2 ) // 1, 7, 4, 10
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 2, 1, 3 ) // 2, 8, 5, 11
|
|
addps xmm7, xmm0
|
|
addps xmm7, xmm1
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
|
|
movlps [ecx-16+0], xmm7
|
|
movhps [ecx-16+8], xmm7
|
|
jl loop4
|
|
|
|
done4:
|
|
and edx, 3
|
|
jz done1
|
|
|
|
loop1:
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm3, [edi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
movss xmm4, [edi+eax+4]
|
|
movss xmm2, [esi+eax+8]
|
|
movss xmm5, [edi+eax+8]
|
|
mulss xmm0, xmm3
|
|
mulss xmm1, xmm4
|
|
mulss xmm2, xmm5
|
|
add ecx, 4
|
|
addss xmm0, xmm1
|
|
add eax, 12
|
|
addss xmm0, xmm2
|
|
dec edx
|
|
movss [ecx-4], xmm0
|
|
jnz loop1
|
|
|
|
done1:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Dot
|
|
|
|
dot = src1[0] * src2[0] + src1[1] * src2[1] + src1[2] * src2[2] + ...
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Dot( float &dot, const float *src1, const float *src2, const int count ) {
|
|
switch( count ) {
|
|
case 0:
|
|
dot = 0.0f;
|
|
return;
|
|
case 1:
|
|
dot = src1[0] * src2[0];
|
|
return;
|
|
case 2:
|
|
dot = src1[0] * src2[0] + src1[1] * src2[1];
|
|
return;
|
|
case 3:
|
|
dot = src1[0] * src2[0] + src1[1] * src2[1] + src1[2] * src2[2];
|
|
return;
|
|
default:
|
|
__asm {
|
|
mov ecx, src1
|
|
mov edx, src2
|
|
mov eax, ecx
|
|
or eax, edx
|
|
and eax, 15
|
|
jz alignedDot
|
|
// unaligned
|
|
mov eax, count
|
|
shr eax, 2
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
movups xmm0, [ecx+eax]
|
|
movups xmm1, [edx+eax]
|
|
mulps xmm0, xmm1
|
|
add eax, 16
|
|
jz doneDot
|
|
loopUnalignedDot:
|
|
movups xmm1, [ecx+eax]
|
|
movups xmm2, [edx+eax]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
add eax, 16
|
|
jl loopUnalignedDot
|
|
jmp doneDot
|
|
// aligned
|
|
alignedDot:
|
|
mov eax, count
|
|
shr eax, 2
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
movaps xmm0, [ecx+eax]
|
|
movaps xmm1, [edx+eax]
|
|
mulps xmm0, xmm1
|
|
add eax, 16
|
|
jz doneDot
|
|
loopAlignedDot:
|
|
movaps xmm1, [ecx+eax]
|
|
movaps xmm2, [edx+eax]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
add eax, 16
|
|
jl loopAlignedDot
|
|
doneDot:
|
|
}
|
|
switch( count & 3 ) {
|
|
case 1:
|
|
__asm {
|
|
movss xmm1, [ecx]
|
|
movss xmm2, [edx]
|
|
mulss xmm1, xmm2
|
|
addss xmm0, xmm1
|
|
}
|
|
break;
|
|
case 2:
|
|
__asm {
|
|
xorps xmm2, xmm2
|
|
movlps xmm1, [ecx]
|
|
movlps xmm2, [edx]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
}
|
|
break;
|
|
case 3:
|
|
__asm {
|
|
movss xmm1, [ecx]
|
|
movhps xmm1, [ecx+4]
|
|
movss xmm2, [edx]
|
|
movhps xmm2, [edx+4]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
}
|
|
break;
|
|
}
|
|
__asm {
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
mov eax, dot
|
|
movss [eax], xmm0
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// cmpeqps == Equal
|
|
// cmpneqps != Not Equal
|
|
// cmpltps < Less Than
|
|
// cmpnltps >= Not Less Than
|
|
// cmpnleps > Not Less Or Equal
|
|
//
|
|
#define FLIP not al
|
|
#define NOFLIP
|
|
|
|
#define COMPARECONSTANT( DST, SRC0, CONSTANT, COUNT, CMP, CMPSIMD, DOFLIP ) \
|
|
int i, cnt, pre, post; \
|
|
float *aligned; \
|
|
\
|
|
/* if the float array is not aligned on a 4 byte boundary */ \
|
|
if ( ((int) SRC0) & 3 ) { \
|
|
/* unaligned memory access */ \
|
|
pre = 0; \
|
|
cnt = COUNT >> 2; \
|
|
post = COUNT - (cnt<<2); \
|
|
__asm mov edx, cnt \
|
|
__asm test edx, edx \
|
|
__asm je doneCmp \
|
|
__asm push ebx \
|
|
__asm neg edx \
|
|
__asm mov esi, SRC0 \
|
|
__asm prefetchnta [esi+64] \
|
|
__asm movss xmm1, CONSTANT \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mov edi, DST \
|
|
__asm mov ecx, 0x01010101 \
|
|
__asm loopNA: \
|
|
__asm movups xmm0, [esi] \
|
|
__asm prefetchnta [esi+128] \
|
|
__asm CMPSIMD xmm0, xmm1 \
|
|
__asm movmskps eax, xmm0 \
|
|
__asm DOFLIP \
|
|
__asm mov ah, al \
|
|
__asm shr ah, 1 \
|
|
__asm mov bx, ax \
|
|
__asm shl ebx, 14 \
|
|
__asm mov bx, ax \
|
|
__asm and ebx, ecx \
|
|
__asm mov dword ptr [edi], ebx \
|
|
__asm add esi, 16 \
|
|
__asm add edi, 4 \
|
|
__asm inc edx \
|
|
__asm jl loopNA \
|
|
__asm pop ebx \
|
|
} \
|
|
else { \
|
|
/* aligned memory access */ \
|
|
aligned = (float *) ((((int) SRC0) + 15) & ~15); \
|
|
if ( (int)aligned > ((int)src0) + COUNT ) { \
|
|
pre = COUNT; \
|
|
post = 0; \
|
|
} \
|
|
else { \
|
|
pre = aligned - SRC0; \
|
|
cnt = (COUNT - pre) >> 2; \
|
|
post = COUNT - pre - (cnt<<2); \
|
|
__asm mov edx, cnt \
|
|
__asm test edx, edx \
|
|
__asm je doneCmp \
|
|
__asm push ebx \
|
|
__asm neg edx \
|
|
__asm mov esi, aligned \
|
|
__asm prefetchnta [esi+64] \
|
|
__asm movss xmm1, CONSTANT \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mov edi, DST \
|
|
__asm add edi, pre \
|
|
__asm mov ecx, 0x01010101 \
|
|
__asm loopA: \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm prefetchnta [esi+128] \
|
|
__asm CMPSIMD xmm0, xmm1 \
|
|
__asm movmskps eax, xmm0 \
|
|
__asm DOFLIP \
|
|
__asm mov ah, al \
|
|
__asm shr ah, 1 \
|
|
__asm mov bx, ax \
|
|
__asm shl ebx, 14 \
|
|
__asm mov bx, ax \
|
|
__asm and ebx, ecx \
|
|
__asm mov dword ptr [edi], ebx \
|
|
__asm add esi, 16 \
|
|
__asm add edi, 4 \
|
|
__asm inc edx \
|
|
__asm jl loopA \
|
|
__asm pop ebx \
|
|
} \
|
|
} \
|
|
doneCmp: \
|
|
double c = constant; \
|
|
for ( i = 0; i < pre; i++ ) { \
|
|
dst[i] = src0[i] CMP c; \
|
|
} \
|
|
for ( i = count - post; i < count; i++ ) { \
|
|
dst[i] = src0[i] CMP c; \
|
|
}
|
|
|
|
#define COMPAREBITCONSTANT( DST, BITNUM, SRC0, CONSTANT, COUNT, CMP, CMPSIMD, DOFLIP ) \
|
|
int i, cnt, pre, post; \
|
|
float *aligned; \
|
|
\
|
|
/* if the float array is not aligned on a 4 byte boundary */ \
|
|
if ( ((int) SRC0) & 3 ) { \
|
|
/* unaligned memory access */ \
|
|
pre = 0; \
|
|
cnt = COUNT >> 2; \
|
|
post = COUNT - (cnt<<2); \
|
|
__asm mov edx, cnt \
|
|
__asm test edx, edx \
|
|
__asm je doneCmp \
|
|
__asm push ebx \
|
|
__asm neg edx \
|
|
__asm mov esi, SRC0 \
|
|
__asm prefetchnta [esi+64] \
|
|
__asm movss xmm1, CONSTANT \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mov edi, DST \
|
|
__asm mov cl, bitNum \
|
|
__asm loopNA: \
|
|
__asm movups xmm0, [esi] \
|
|
__asm prefetchnta [esi+128] \
|
|
__asm CMPSIMD xmm0, xmm1 \
|
|
__asm movmskps eax, xmm0 \
|
|
__asm DOFLIP \
|
|
__asm mov ah, al \
|
|
__asm shr ah, 1 \
|
|
__asm mov bx, ax \
|
|
__asm shl ebx, 14 \
|
|
__asm mov bx, ax \
|
|
__asm and ebx, 0x01010101 \
|
|
__asm shl ebx, cl \
|
|
__asm or ebx, dword ptr [edi] \
|
|
__asm mov dword ptr [edi], ebx \
|
|
__asm add esi, 16 \
|
|
__asm add edi, 4 \
|
|
__asm inc edx \
|
|
__asm jl loopNA \
|
|
__asm pop ebx \
|
|
} \
|
|
else { \
|
|
/* aligned memory access */ \
|
|
aligned = (float *) ((((int) SRC0) + 15) & ~15); \
|
|
if ( (int)aligned > ((int)src0) + COUNT ) { \
|
|
pre = COUNT; \
|
|
post = 0; \
|
|
} \
|
|
else { \
|
|
pre = aligned - SRC0; \
|
|
cnt = (COUNT - pre) >> 2; \
|
|
post = COUNT - pre - (cnt<<2); \
|
|
__asm mov edx, cnt \
|
|
__asm test edx, edx \
|
|
__asm je doneCmp \
|
|
__asm push ebx \
|
|
__asm neg edx \
|
|
__asm mov esi, aligned \
|
|
__asm prefetchnta [esi+64] \
|
|
__asm movss xmm1, CONSTANT \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mov edi, DST \
|
|
__asm add edi, pre \
|
|
__asm mov cl, bitNum \
|
|
__asm loopA: \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm prefetchnta [esi+128] \
|
|
__asm CMPSIMD xmm0, xmm1 \
|
|
__asm movmskps eax, xmm0 \
|
|
__asm DOFLIP \
|
|
__asm mov ah, al \
|
|
__asm shr ah, 1 \
|
|
__asm mov bx, ax \
|
|
__asm shl ebx, 14 \
|
|
__asm mov bx, ax \
|
|
__asm and ebx, 0x01010101 \
|
|
__asm shl ebx, cl \
|
|
__asm or ebx, dword ptr [edi] \
|
|
__asm mov dword ptr [edi], ebx \
|
|
__asm add esi, 16 \
|
|
__asm add edi, 4 \
|
|
__asm inc edx \
|
|
__asm jl loopA \
|
|
__asm pop ebx \
|
|
} \
|
|
} \
|
|
doneCmp: \
|
|
float c = constant; \
|
|
for ( i = 0; i < pre; i++ ) { \
|
|
dst[i] |= ( src0[i] CMP c ) << BITNUM; \
|
|
} \
|
|
for ( i = count - post; i < count; i++ ) { \
|
|
dst[i] |= ( src0[i] CMP c ) << BITNUM; \
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpGT
|
|
|
|
dst[i] = src0[i] > constant;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpGT( byte *dst, const float *src0, const float constant, const int count ) {
|
|
COMPARECONSTANT( dst, src0, constant, count, >, cmpnleps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpGT
|
|
|
|
dst[i] |= ( src0[i] > constant ) << bitNum;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpGT( byte *dst, const byte bitNum, const float *src0, const float constant, const int count ) {
|
|
COMPAREBITCONSTANT( dst, bitNum, src0, constant, count, >, cmpnleps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpGE
|
|
|
|
dst[i] = src0[i] >= constant;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpGE( byte *dst, const float *src0, const float constant, const int count ) {
|
|
COMPARECONSTANT( dst, src0, constant, count, >=, cmpnltps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpGE
|
|
|
|
dst[i] |= ( src0[i] >= constant ) << bitNum;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpGE( byte *dst, const byte bitNum, const float *src0, const float constant, const int count ) {
|
|
COMPAREBITCONSTANT( dst, bitNum, src0, constant, count, >=, cmpnltps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpLT
|
|
|
|
dst[i] = src0[i] < constant;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpLT( byte *dst, const float *src0, const float constant, const int count ) {
|
|
COMPARECONSTANT( dst, src0, constant, count, <, cmpltps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpLT
|
|
|
|
dst[i] |= ( src0[i] < constant ) << bitNum;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpLT( byte *dst, const byte bitNum, const float *src0, const float constant, const int count ) {
|
|
COMPAREBITCONSTANT( dst, bitNum, src0, constant, count, <, cmpltps, NOFLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpLE
|
|
|
|
dst[i] = src0[i] <= constant;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpLE( byte *dst, const float *src0, const float constant, const int count ) {
|
|
COMPARECONSTANT( dst, src0, constant, count, <=, cmpnleps, FLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CmpLE
|
|
|
|
dst[i] |= ( src0[i] <= constant ) << bitNum;
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CmpLE( byte *dst, const byte bitNum, const float *src0, const float constant, const int count ) {
|
|
COMPAREBITCONSTANT( dst, bitNum, src0, constant, count, <=, cmpnleps, FLIP )
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( float &min, float &max, const float *src, const int count ) {
|
|
int i, pre, post;
|
|
|
|
min = idMath::INFINITY; max = -idMath::INFINITY;
|
|
|
|
__asm
|
|
{
|
|
push ebx
|
|
mov eax, min
|
|
mov ebx, max
|
|
movss xmm0, [eax]
|
|
movss xmm1, [ebx]
|
|
shufps xmm0, xmm0, 0
|
|
shufps xmm1, xmm1, 0
|
|
|
|
KFLOATINITS( src, count, pre, post )
|
|
and eax, 15
|
|
jz lpA
|
|
jmp lpNA
|
|
align 16
|
|
lpNA:
|
|
movups xmm2, [edx+ebx]
|
|
movups xmm3, [edx+ebx+16]
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm2
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm0, xmm3
|
|
maxps xmm1, xmm3
|
|
add ebx, 16*2
|
|
jl lpNA
|
|
jmp done2
|
|
lpA:
|
|
movaps xmm2, [edx+ebx]
|
|
movaps xmm3, [edx+ebx+16]
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm2
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm0, xmm3
|
|
maxps xmm1, xmm3
|
|
add ebx, 16*2
|
|
jl lpA
|
|
jmp done2
|
|
align 16
|
|
done2:
|
|
movaps xmm2, xmm0
|
|
movaps xmm3, xmm1
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
minss xmm0, xmm2
|
|
maxss xmm1, xmm3
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
minss xmm0, xmm2
|
|
maxss xmm1, xmm3
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
minss xmm0, xmm2
|
|
maxss xmm1, xmm3
|
|
mov eax, min
|
|
mov ebx, max
|
|
movss [eax], xmm0
|
|
movss [ebx], xmm1
|
|
done:
|
|
pop ebx
|
|
}
|
|
|
|
for ( i = 0; i < pre; i++ ) {
|
|
float tmp = src[i];
|
|
if ( tmp > max ) {
|
|
max = tmp;
|
|
}
|
|
if ( tmp < min ) {
|
|
min = tmp;
|
|
}
|
|
}
|
|
for ( i = count - post; i < count; i++ ) {
|
|
float tmp = src[i];
|
|
if ( tmp > max ) {
|
|
max = tmp;
|
|
}
|
|
if ( tmp < min ) {
|
|
min = tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( idVec2 &min, idVec2 &max, const idVec2 *src, const int count ) {
|
|
__asm {
|
|
mov eax, count
|
|
test eax, eax
|
|
movss xmm0, idMath::INFINITY
|
|
xorps xmm1, xmm1
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
subps xmm1, xmm0
|
|
jz done
|
|
mov ecx, eax
|
|
and ecx, 1
|
|
mov esi, src
|
|
jz startLoop
|
|
movlps xmm2, [esi]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
dec eax
|
|
add esi, 2*4
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm2
|
|
startLoop:
|
|
imul eax, 2*4
|
|
add esi, eax
|
|
neg eax
|
|
loopVert:
|
|
movlps xmm2, [esi+eax]
|
|
movhps xmm2, [esi+eax+8]
|
|
add eax, 4*4
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm2
|
|
jl loopVert
|
|
done:
|
|
movaps xmm2, xmm0
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
minps xmm0, xmm2
|
|
mov esi, min
|
|
movlps [esi], xmm0
|
|
movaps xmm3, xmm1
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
maxps xmm1, xmm3
|
|
mov edi, max
|
|
movlps [edi], xmm1
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( idVec3 &min, idVec3 &max, const idVec3 *src, const int count ) {
|
|
__asm {
|
|
|
|
movss xmm0, idMath::INFINITY
|
|
xorps xmm1, xmm1
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
subps xmm1, xmm0
|
|
movaps xmm2, xmm0
|
|
movaps xmm3, xmm1
|
|
|
|
mov esi, src
|
|
mov eax, count
|
|
and eax, ~3
|
|
jz done4
|
|
imul eax, 12
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
// prefetchnta [esi+4*12]
|
|
|
|
movss xmm4, [esi+eax+0*12+8]
|
|
movhps xmm4, [esi+eax+0*12+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
movss xmm5, [esi+eax+1*12+0]
|
|
movhps xmm5, [esi+eax+1*12+4]
|
|
minps xmm2, xmm5
|
|
maxps xmm3, xmm5
|
|
|
|
movss xmm6, [esi+eax+2*12+8]
|
|
movhps xmm6, [esi+eax+2*12+0]
|
|
minps xmm0, xmm6
|
|
maxps xmm1, xmm6
|
|
|
|
movss xmm7, [esi+eax+3*12+0]
|
|
movhps xmm7, [esi+eax+3*12+4]
|
|
minps xmm2, xmm7
|
|
maxps xmm3, xmm7
|
|
|
|
add eax, 4*12
|
|
jl loop4
|
|
|
|
done4:
|
|
mov eax, count
|
|
and eax, 3
|
|
jz done1
|
|
imul eax, 12
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop1:
|
|
movss xmm4, [esi+eax+0*12+8]
|
|
movhps xmm4, [esi+eax+0*12+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
add eax, 12
|
|
jl loop1
|
|
|
|
done1:
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm3
|
|
mov esi, min
|
|
movhps [esi], xmm0
|
|
movss [esi+8], xmm0
|
|
mov edi, max
|
|
movhps [edi], xmm1
|
|
movss [edi+8], xmm1
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( idVec3 &min, idVec3 &max, const idDrawVert *src, const int count ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
|
|
movss xmm0, idMath::INFINITY
|
|
xorps xmm1, xmm1
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
subps xmm1, xmm0
|
|
movaps xmm2, xmm0
|
|
movaps xmm3, xmm1
|
|
|
|
mov esi, src
|
|
mov eax, count
|
|
and eax, ~3
|
|
jz done4
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
// prefetchnta [esi+4*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET]
|
|
|
|
movss xmm4, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
movss xmm5, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm5, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm5
|
|
maxps xmm3, xmm5
|
|
|
|
movss xmm6, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm6, [esi+eax+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm6
|
|
maxps xmm1, xmm6
|
|
|
|
movss xmm7, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm7, [esi+eax+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm7
|
|
maxps xmm3, xmm7
|
|
|
|
add eax, 4*DRAWVERT_SIZE
|
|
jl loop4
|
|
|
|
done4:
|
|
mov eax, count
|
|
and eax, 3
|
|
jz done1
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loop1:
|
|
movss xmm4, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
add eax, DRAWVERT_SIZE
|
|
jl loop1
|
|
|
|
done1:
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm3
|
|
mov esi, min
|
|
movhps [esi], xmm0
|
|
movss [esi+8], xmm0
|
|
mov edi, max
|
|
movhps [edi], xmm1
|
|
movss [edi+8], xmm1
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MinMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MinMax( idVec3 &min, idVec3 &max, const idDrawVert *src, const int *indexes, const int count ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
|
|
movss xmm0, idMath::INFINITY
|
|
xorps xmm1, xmm1
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
subps xmm1, xmm0
|
|
movaps xmm2, xmm0
|
|
movaps xmm3, xmm1
|
|
|
|
mov edi, indexes
|
|
mov esi, src
|
|
mov eax, count
|
|
and eax, ~3
|
|
jz done4
|
|
shl eax, 2
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
// prefetchnta [edi+128]
|
|
// prefetchnta [esi+4*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET]
|
|
|
|
mov edx, [edi+eax+0]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
mov edx, [edi+eax+4]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm5, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm5, [esi+edx+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm5
|
|
maxps xmm3, xmm5
|
|
|
|
mov edx, [edi+eax+8]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm6, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm6, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm6
|
|
maxps xmm1, xmm6
|
|
|
|
mov edx, [edi+eax+12]
|
|
imul edx, DRAWVERT_SIZE
|
|
movss xmm7, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm7, [esi+edx+DRAWVERT_XYZ_OFFSET+4]
|
|
minps xmm2, xmm7
|
|
maxps xmm3, xmm7
|
|
|
|
add eax, 4*4
|
|
jl loop4
|
|
|
|
done4:
|
|
mov eax, count
|
|
and eax, 3
|
|
jz done1
|
|
shl eax, 2
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loop1:
|
|
mov edx, [edi+eax+0]
|
|
imul edx, DRAWVERT_SIZE;
|
|
movss xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm4, [esi+edx+DRAWVERT_XYZ_OFFSET+0]
|
|
minps xmm0, xmm4
|
|
maxps xmm1, xmm4
|
|
|
|
add eax, 4
|
|
jl loop1
|
|
|
|
done1:
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 1, 0, 2 )
|
|
minps xmm0, xmm2
|
|
maxps xmm1, xmm3
|
|
mov esi, min
|
|
movhps [esi], xmm0
|
|
movss [esi+8], xmm0
|
|
mov edi, max
|
|
movhps [edi], xmm1
|
|
movss [edi+8], xmm1
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Clamp
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Clamp( float *dst, const float *src, const float min, const float max, const int count ) {
|
|
int i, pre, post;
|
|
|
|
__asm
|
|
{
|
|
movss xmm0,min
|
|
movss xmm1,max
|
|
shufps xmm0,xmm0,0
|
|
shufps xmm1,xmm1,0
|
|
|
|
KFLOATINITDS( dst, src, count, pre, post )
|
|
and eax,15
|
|
jne lpNA
|
|
jmp lpA
|
|
align 16
|
|
lpA:
|
|
movaps xmm2,[edx+ebx]
|
|
movaps xmm3,[edx+ebx+16]
|
|
maxps xmm2,xmm0
|
|
maxps xmm3,xmm0
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm2,xmm1
|
|
minps xmm3,xmm1
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpA
|
|
jmp done
|
|
|
|
align 16
|
|
lpNA:
|
|
movups xmm2,[edx+ebx]
|
|
movups xmm3,[edx+ebx+16]
|
|
maxps xmm2,xmm0
|
|
maxps xmm3,xmm0
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm2,xmm1
|
|
minps xmm3,xmm1
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpNA
|
|
done:
|
|
}
|
|
|
|
for ( i = 0; i < pre; i++ ) {
|
|
if ( src[i] < min )
|
|
dst[i] = min;
|
|
else if ( src[i] > max )
|
|
dst[i] = max;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
|
|
for( i = count - post; i < count; i++ ) {
|
|
if ( src[i] < min )
|
|
dst[i] = min;
|
|
else if ( src[i] > max )
|
|
dst[i] = max;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::ClampMin
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::ClampMin( float *dst, const float *src, const float min, const int count ) {
|
|
int i, pre, post;
|
|
|
|
__asm
|
|
{
|
|
movss xmm0,min
|
|
shufps xmm0,xmm0,0
|
|
|
|
KFLOATINITDS( dst, src, count, pre, post )
|
|
and eax,15
|
|
jne lpNA
|
|
jmp lpA
|
|
align 16
|
|
lpA:
|
|
movaps xmm2,[edx+ebx]
|
|
movaps xmm3,[edx+ebx+16]
|
|
maxps xmm2,xmm0
|
|
prefetchnta [edx+ebx+64]
|
|
maxps xmm3,xmm0
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpA
|
|
jmp done
|
|
|
|
align 16
|
|
lpNA:
|
|
movups xmm2,[edx+ebx]
|
|
movups xmm3,[edx+ebx+16]
|
|
maxps xmm2,xmm0
|
|
prefetchnta [edx+ebx+64]
|
|
maxps xmm3,xmm0
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpNA
|
|
done:
|
|
}
|
|
|
|
for( i = 0; i < pre; i++ ) {
|
|
if ( src[i] < min )
|
|
dst[i] = min;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
for( i = count - post; i < count; i++ ) {
|
|
if ( src[i] < min )
|
|
dst[i] = min;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::ClampMax
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::ClampMax( float *dst, const float *src, const float max, const int count ) {
|
|
int i, pre, post;
|
|
|
|
__asm
|
|
{
|
|
movss xmm1,max
|
|
shufps xmm1,xmm1,0
|
|
|
|
KFLOATINITDS( dst, src, count, pre, post )
|
|
and eax,15
|
|
jne lpNA
|
|
jmp lpA
|
|
align 16
|
|
lpA:
|
|
movaps xmm2,[edx+ebx]
|
|
movaps xmm3,[edx+ebx+16]
|
|
minps xmm2,xmm1
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm3,xmm1
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpA
|
|
jmp done
|
|
|
|
align 16
|
|
lpNA:
|
|
movups xmm2,[edx+ebx]
|
|
movups xmm3,[edx+ebx+16]
|
|
minps xmm2,xmm1
|
|
prefetchnta [edx+ebx+64]
|
|
minps xmm3,xmm1
|
|
movaps [edi+ebx],xmm2
|
|
movaps [edi+ebx+16],xmm3
|
|
add ebx,16*2
|
|
jl lpNA
|
|
done:
|
|
}
|
|
|
|
for( i = 0; i < pre; i++ ) {
|
|
if ( src[i] > max )
|
|
dst[i] = max;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
|
|
for( i = count - post; i < count; i++ ) {
|
|
if ( src[i] > max )
|
|
dst[i] = max;
|
|
else
|
|
dst[i] = src[i];
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Zero16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Zero16( float *dst, const int count ) {
|
|
__asm {
|
|
mov edx, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneZero16
|
|
shl eax, 4
|
|
add edx, eax
|
|
neg eax
|
|
xorps xmm0, xmm0
|
|
loopZero16:
|
|
movaps [edx+eax], xmm0
|
|
add eax, 16
|
|
jl loopZero16
|
|
doneZero16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Negate16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Negate16( float *dst, const int count ) {
|
|
__asm {
|
|
mov edx, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneNegate16
|
|
shl eax, 4
|
|
add edx, eax
|
|
neg eax
|
|
movss xmm0, SIMD_SP_signBitMask
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
loopNegate16:
|
|
movaps xmm1, [edx+eax]
|
|
xorps xmm1, xmm0
|
|
movaps [edx+eax], xmm1
|
|
add eax, 16
|
|
jl loopNegate16
|
|
doneNegate16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Copy16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Copy16( float *dst, const float *src, const int count ) {
|
|
__asm {
|
|
mov ecx, src
|
|
mov edx, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneCopy16
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
loopCopy16:
|
|
movaps xmm0, [ecx+eax]
|
|
movaps [edx+eax], xmm0
|
|
add eax, 16
|
|
jl loopCopy16
|
|
doneCopy16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Add16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Add16( float *dst, const float *src1, const float *src2, const int count ) {
|
|
__asm {
|
|
mov ecx, src1
|
|
mov edx, src2
|
|
mov esi, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneAdd16
|
|
shl eax, 4
|
|
add esi, eax
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
loopAdd16:
|
|
movaps xmm0, [ecx+eax]
|
|
addps xmm0, [edx+eax]
|
|
movaps [esi+eax], xmm0
|
|
add eax, 16
|
|
jl loopAdd16
|
|
doneAdd16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Sub16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Sub16( float *dst, const float *src1, const float *src2, const int count ) {
|
|
__asm {
|
|
mov ecx, src1
|
|
mov edx, src2
|
|
mov esi, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneSub16
|
|
shl eax, 4
|
|
add esi, eax
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
loopSub16:
|
|
movaps xmm0, [ecx+eax]
|
|
subps xmm0, [edx+eax]
|
|
movaps [esi+eax], xmm0
|
|
add eax, 16
|
|
jl loopSub16
|
|
doneSub16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::Mul16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::Mul16( float *dst, const float *src1, const float constant, const int count ) {
|
|
__asm {
|
|
mov ecx, dst
|
|
mov edx, src1
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneMulScalar16
|
|
movss xmm1, constant
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
shufps xmm1, xmm1, 0x00
|
|
loopMulScalar16:
|
|
movaps xmm0, [edx+eax]
|
|
mulps xmm0, xmm1
|
|
movaps [ecx+eax], xmm0
|
|
add eax, 16
|
|
jl loopMulScalar16
|
|
doneMulScalar16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::AddAssign16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::AddAssign16( float *dst, const float *src, const int count ) {
|
|
__asm {
|
|
mov ecx, dst
|
|
mov edx, src
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneAddAssign16
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
loopAddAssign16:
|
|
movaps xmm0, [ecx+eax]
|
|
addps xmm0, [edx+eax]
|
|
movaps [ecx+eax], xmm0
|
|
add eax, 16
|
|
jl loopAddAssign16
|
|
doneAddAssign16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::SubAssign16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::SubAssign16( float *dst, const float *src, const int count ) {
|
|
__asm {
|
|
mov ecx, dst
|
|
mov edx, src
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneSubAssign16
|
|
shl eax, 4
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
loopSubAssign16:
|
|
movaps xmm0, [ecx+eax]
|
|
subps xmm0, [edx+eax]
|
|
movaps [ecx+eax], xmm0
|
|
add eax, 16
|
|
jl loopSubAssign16
|
|
doneSubAssign16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MulAssign16
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MulAssign16( float *dst, const float constant, const int count ) {
|
|
__asm {
|
|
mov ecx, dst
|
|
mov eax, count
|
|
add eax, 3
|
|
shr eax, 2
|
|
jz doneMulAssign16
|
|
movss xmm1, constant
|
|
shl eax, 4
|
|
add ecx, eax
|
|
neg eax
|
|
shufps xmm1, xmm1, 0x00
|
|
loopMulAssign16:
|
|
movaps xmm0, [ecx+eax]
|
|
mulps xmm0, xmm1
|
|
movaps [ecx+eax], xmm0
|
|
add eax, 16
|
|
jl loopMulAssign16
|
|
doneMulAssign16:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_MultiplyVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
NxN * Nx1
|
|
Nx6 * 6x1
|
|
6xN * Nx1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_MultiplyVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss [eax+offset], reg1
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps [eax+offset], reg1
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps [eax+offset], reg1
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps [eax+offset], reg1 \
|
|
__asm movhps [eax+offset+8], reg1
|
|
#define STOREC =
|
|
|
|
int numRows;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumColumns() );
|
|
assert( dst.GetSize() >= mat.GetNumRows() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numRows = mat.GetNumRows();
|
|
switch( mat.GetNumColumns() ) {
|
|
case 1: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
STORE1( 0, xmm0, xmm1 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
switch( numRows ) {
|
|
case 2: { // 2x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm1, [esi+4]
|
|
movss xmm2, [edi]
|
|
mulss xmm2, xmm0
|
|
movss xmm3, [edi+4]
|
|
mulss xmm3, xmm1
|
|
addss xmm2, xmm3
|
|
STORE1( 0, xmm2, xmm4 )
|
|
mulss xmm0, [edi+8]
|
|
mulss xmm1, [edi+8+4]
|
|
addss xmm0, xmm1
|
|
STORE1( 4, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, [esi]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movaps xmm0, [edi]
|
|
mulps xmm0, xmm7
|
|
movaps xmm1, [edi+16]
|
|
mulps xmm1, xmm7
|
|
movaps xmm2, xmm0
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
movaps xmm3, [edi+32]
|
|
addps xmm0, xmm2
|
|
mulps xmm3, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm1, xmm3
|
|
addps xmm3, xmm1
|
|
STORE2LO( 16, xmm3, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1];
|
|
mPtr += 2;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
switch( numRows ) {
|
|
case 3: { // 3x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm4, [edi]
|
|
mulss xmm4, xmm0
|
|
movss xmm1, [esi+4]
|
|
movss xmm5, [edi+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm4, xmm5
|
|
movss xmm2, [esi+8]
|
|
movss xmm6, [edi+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm4, xmm6
|
|
movss xmm3, [edi+12]
|
|
mulss xmm3, xmm0
|
|
STORE1( 0, xmm4, xmm7 );
|
|
movss xmm5, [edi+12+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm3, xmm5
|
|
movss xmm6, [edi+12+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm3, xmm6
|
|
mulss xmm0, [edi+24]
|
|
mulss xmm1, [edi+24+4]
|
|
STORE1( 4, xmm3, xmm7 );
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+24+8]
|
|
addss xmm0, xmm2
|
|
STORE1( 8, xmm0, xmm7 );
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm5, [esi]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [esi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm0, [edi] // xmm0 = 0, 1, 2, 3
|
|
movlps xmm1, [edi+4*4]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm1 = 4, 5, 1, 2
|
|
movlps xmm2, [edi+6*4]
|
|
movhps xmm2, [edi+8*4] // xmm2 = 6, 7, 8, 9
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 3, 0, 3 ) // xmm0 = 0, 3, 6, 9
|
|
mulps xmm0, xmm5
|
|
movlps xmm3, [edi+10*4]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 2, 0, 1 ) // xmm2 = 7, 8, 10, 11
|
|
movaps xmm3, xmm1
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 2, 0, 0, 2 ) // xmm1 = 1, 4, 7, 10
|
|
mulps xmm1, xmm6
|
|
shufps xmm3, xmm2, R_SHUFFLEPS( 3, 1, 1, 3 ) // xmm3 = 2, 5, 8, 11
|
|
mulps xmm3, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm3
|
|
STORE4( 0, xmm0, xmm4 )
|
|
movss xmm1, [edi+12*4]
|
|
mulss xmm1, xmm5
|
|
movss xmm2, [edi+13*4]
|
|
mulss xmm2, xmm6
|
|
movss xmm3, [edi+14*4]
|
|
mulss xmm3, xmm7
|
|
addss xmm1, xmm2
|
|
addss xmm1, xmm3
|
|
STORE1( 16, xmm1, xmm4 )
|
|
mulss xmm5, [edi+15*4]
|
|
mulss xmm6, [edi+16*4]
|
|
mulss xmm7, [edi+17*4]
|
|
addss xmm5, xmm6
|
|
addss xmm5, xmm7
|
|
STORE1( 20, xmm5, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2];
|
|
mPtr += 3;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
switch( numRows ) {
|
|
case 4: { // 4x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi ]
|
|
movlps xmm0, qword ptr [edi ]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
STORE4( 0, xmm0, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi+ 0]
|
|
movlps xmm0, qword ptr [edi+ 0]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
movlps xmm1, qword ptr [edi+64]
|
|
movhps xmm1, qword ptr [edi+80]
|
|
STORE4( 0, xmm0, xmm4 )
|
|
mulps xmm1, xmm6
|
|
movlps xmm2, qword ptr [edi+72]
|
|
movhps xmm2, qword ptr [edi+88]
|
|
mulps xmm2, xmm7
|
|
addps xmm1, xmm2
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm3, xmm1
|
|
addps xmm1, xmm3
|
|
STORE2LO( 16, xmm1, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3];
|
|
mPtr += 4;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
switch( numRows ) {
|
|
case 5: { // 5x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+5*4] // xmm0 = 5, X, X, X
|
|
movhps xmm0, [edi+0*4] // xmm0 = 5, X, 0, 1
|
|
movss xmm5, [edi+15*4] // xmm4 = 15, X, X, X
|
|
movhps xmm5, [edi+10*4] // xmm5 = 15, X, 10, 11
|
|
movaps xmm1, xmm0 // xmm1 = 5, X, 0, 1
|
|
shufps xmm0, xmm5, R_SHUFFLEPS( 2, 0, 2, 0 ) // xmm0 = 0, 5, 10, 15
|
|
movlps xmm1, [edi+6*4] // xmm1 = 6, 7, 0, 1
|
|
movlps xmm5, [edi+16*4] // xmm5 = 16, 17, 10, 11
|
|
movaps xmm2, xmm1 // xmm2 = 6, 7, 0, 1
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm1 = 1, 6, 11, 16
|
|
movhps xmm2, [edi+2*4] // xmm2 = 6, 7, 2, 3
|
|
movhps xmm5, [edi+12*4] // xmm5 = 16, 17, 12, 13
|
|
movaps xmm3, xmm2 // xmm3 = 6, 7, 2, 3
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 2, 1, 2, 1 ) // xmm2 = 2, 7, 12, 17
|
|
movlps xmm3, [edi+8*4] // xmm3 = 8, 9, 2, 3
|
|
movlps xmm5, [edi+18*4] // xmm5 = 18, 19, 12, 13
|
|
movss xmm4, [edi+4*4] // xmm4 = 4, X, X, X
|
|
movlhps xmm4, xmm3 // xmm4 = 4, X, 8, 9
|
|
shufps xmm3, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm3 = 3, 8, 13, 18
|
|
movhps xmm5, [edi+14*4] // xmm6 = 18, 19, 14, 15
|
|
shufps xmm4, xmm5, R_SHUFFLEPS( 0, 3, 2, 1 ) // xmm4 = 4, 9, 14, 19
|
|
movss xmm7, [esi+0*4]
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm0, xmm7
|
|
movss xmm5, [esi+1*4]
|
|
shufps xmm5, xmm5, 0
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, 0
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm2
|
|
movss xmm1, [esi+3*4]
|
|
shufps xmm1, xmm1, 0
|
|
mulps xmm3, xmm1
|
|
addps xmm0, xmm3
|
|
movss xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm4, xmm2
|
|
addps xmm0, xmm4
|
|
mulss xmm7, [edi+20*4]
|
|
mulss xmm5, [edi+21*4]
|
|
addps xmm7, xmm5
|
|
mulss xmm6, [edi+22*4]
|
|
addps xmm7, xmm6
|
|
mulss xmm1, [edi+23*4]
|
|
addps xmm7, xmm1
|
|
mulss xmm2, [edi+24*4]
|
|
addps xmm7, xmm2
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE1( 16, xmm7, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [esi]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm0, [edi]
|
|
movhps xmm3, [edi+8]
|
|
movaps xmm1, [edi+16]
|
|
movlps xmm2, [edi+32]
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm0 = 0, 1, 5, 6
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 4, 7, 8, 9
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 2, 3, 7, 8
|
|
mulps xmm0, xmm6
|
|
mulps xmm3, xmm7
|
|
movlps xmm2, [edi+40]
|
|
addps xmm0, xmm3 // xmm0 + xmm1
|
|
movhps xmm5, [edi+40+8]
|
|
movlps xmm3, [edi+40+16]
|
|
movhps xmm3, [edi+40+24]
|
|
movlps xmm4, [edi+40+32]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm2 = 10, 11, 15, 16
|
|
shufps xmm3, xmm4, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm3 = 14, 17, 18, 19
|
|
shufps xmm5, xmm3, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm5 = 12, 13, 17, 18
|
|
mulps xmm2, xmm6
|
|
mulps xmm5, xmm7
|
|
addps xmm2, xmm5 // xmm2 + xmm3
|
|
movss xmm5, [esi+16]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm0
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm4, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 0, 3, 0, 3 )
|
|
addps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
STORE4( 0, xmm0, xmm2 )
|
|
movlps xmm4, [edi+80]
|
|
movhps xmm3, [edi+80+8]
|
|
movaps xmm1, [edi+80+16]
|
|
movlps xmm2, [edi+80+32]
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm4 = 20, 21, 25, 26
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 24, 27, 28, 29
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 22, 23, 27, 28
|
|
mulps xmm4, xmm6
|
|
mulps xmm3, xmm7
|
|
mulps xmm1, xmm5
|
|
addps xmm4, xmm3 // xmm4 + xmm1
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 0, 3, 0, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 1, 3, 0, 0 )
|
|
addps xmm4, xmm1
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
addps xmm4, xmm1
|
|
STORE2LO( 16, xmm4, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4];
|
|
mPtr += 5;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 6: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
movss xmm1, [esi+4]
|
|
mulss xmm1, [edi+4]
|
|
movss xmm2, [esi+8]
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+8]
|
|
movss xmm3, [esi+12]
|
|
addss xmm0, xmm2
|
|
mulss xmm3, [edi+12]
|
|
movss xmm4, [esi+16]
|
|
addss xmm0, xmm3
|
|
mulss xmm4, [edi+16]
|
|
movss xmm5, [esi+20]
|
|
addss xmm0, xmm4
|
|
mulss xmm5, [edi+20]
|
|
movss xmm6, [esi+24]
|
|
addss xmm0, xmm5
|
|
mulss xmm6, [edi+24]
|
|
addss xmm0, xmm6
|
|
STORE1( 0, xmm0, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 2x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 3x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
// row 2
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
STORE1( 8, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 4x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 5x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
// row 5
|
|
movaps xmm0, [edi+96]
|
|
movaps xmm1, [edi+96+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 0x01
|
|
addss xmm0, xmm1
|
|
STORE1( 16, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, qword ptr [esi]
|
|
movlps xmm6, qword ptr [esi+8]
|
|
shufps xmm7, xmm7, 0x44
|
|
shufps xmm6, xmm6, 0x44
|
|
movlps xmm0, qword ptr [edi ]
|
|
movhps xmm0, qword ptr [edi+ 24]
|
|
mulps xmm0, xmm7
|
|
movlps xmm3, qword ptr [edi+ 8]
|
|
movhps xmm3, qword ptr [edi+ 32]
|
|
mulps xmm3, xmm6
|
|
movlps xmm1, qword ptr [edi+ 48]
|
|
movhps xmm1, qword ptr [edi+ 72]
|
|
mulps xmm1, xmm7
|
|
movlps xmm2, qword ptr [edi+ 96]
|
|
movhps xmm2, qword ptr [edi+120]
|
|
mulps xmm2, xmm7
|
|
movlps xmm4, qword ptr [edi+ 56]
|
|
movhps xmm4, qword ptr [edi+ 80]
|
|
movlps xmm5, qword ptr [edi+104]
|
|
movhps xmm5, qword ptr [edi+128]
|
|
mulps xmm4, xmm6
|
|
movlps xmm7, qword ptr [esi+16]
|
|
addps xmm0, xmm3
|
|
shufps xmm7, xmm7, 0x44
|
|
mulps xmm5, xmm6
|
|
addps xmm1, xmm4
|
|
movlps xmm3, qword ptr [edi+ 16]
|
|
movhps xmm3, qword ptr [edi+ 40]
|
|
addps xmm2, xmm5
|
|
movlps xmm4, qword ptr [edi+ 64]
|
|
movhps xmm4, qword ptr [edi+ 88]
|
|
mulps xmm3, xmm7
|
|
movlps xmm5, qword ptr [edi+112]
|
|
movhps xmm5, qword ptr [edi+136]
|
|
addps xmm0, xmm3
|
|
mulps xmm4, xmm7
|
|
mulps xmm5, xmm7
|
|
addps xmm1, xmm4
|
|
addps xmm2, xmm5
|
|
movaps xmm6, xmm0
|
|
shufps xmm0, xmm1, 0x88
|
|
shufps xmm6, xmm1, 0xDD
|
|
movaps xmm7, xmm2
|
|
shufps xmm7, xmm2, 0x88
|
|
shufps xmm2, xmm2, 0xDD
|
|
addps xmm0, xmm6
|
|
addps xmm2, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE2LO( 16, xmm2, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] +
|
|
mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4] + mPtr[5] * vPtr[5];
|
|
mPtr += 6;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
int numColumns = mat.GetNumColumns();
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numColumns; j++ ) {
|
|
sum += mPtr[j] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
mPtr += numColumns;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_MultiplyAddVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
NxN * Nx1
|
|
Nx6 * 6x1
|
|
6xN * Nx1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_MultiplyAddVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss reg2, [eax+offset] \
|
|
__asm addss reg2, reg1 \
|
|
__asm movss [eax+offset], reg2
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps reg2, [eax+offset] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movhps [eax+offset], reg2
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm movhps reg2, [eax+offset+8] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2 \
|
|
__asm movhps [eax+offset+8], reg2
|
|
#define STOREC +=
|
|
|
|
int numRows;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumColumns() );
|
|
assert( dst.GetSize() >= mat.GetNumRows() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numRows = mat.GetNumRows();
|
|
switch( mat.GetNumColumns() ) {
|
|
case 1: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
STORE1( 0, xmm0, xmm1 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
switch( numRows ) {
|
|
case 2: { // 2x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm1, [esi+4]
|
|
movss xmm2, [edi]
|
|
mulss xmm2, xmm0
|
|
movss xmm3, [edi+4]
|
|
mulss xmm3, xmm1
|
|
addss xmm2, xmm3
|
|
STORE1( 0, xmm2, xmm4 )
|
|
mulss xmm0, [edi+8]
|
|
mulss xmm1, [edi+8+4]
|
|
addss xmm0, xmm1
|
|
STORE1( 4, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, [esi]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movaps xmm0, [edi]
|
|
mulps xmm0, xmm7
|
|
movaps xmm1, [edi+16]
|
|
mulps xmm1, xmm7
|
|
movaps xmm2, xmm0
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
movaps xmm3, [edi+32]
|
|
addps xmm0, xmm2
|
|
mulps xmm3, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm1, xmm3
|
|
addps xmm3, xmm1
|
|
STORE2LO( 16, xmm3, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1];
|
|
mPtr += 2;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
switch( numRows ) {
|
|
case 3: { // 3x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm4, [edi]
|
|
mulss xmm4, xmm0
|
|
movss xmm1, [esi+4]
|
|
movss xmm5, [edi+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm4, xmm5
|
|
movss xmm2, [esi+8]
|
|
movss xmm6, [edi+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm4, xmm6
|
|
movss xmm3, [edi+12]
|
|
mulss xmm3, xmm0
|
|
STORE1( 0, xmm4, xmm7 );
|
|
movss xmm5, [edi+12+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm3, xmm5
|
|
movss xmm6, [edi+12+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm3, xmm6
|
|
mulss xmm0, [edi+24]
|
|
mulss xmm1, [edi+24+4]
|
|
STORE1( 4, xmm3, xmm7 );
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+24+8]
|
|
addss xmm0, xmm2
|
|
STORE1( 8, xmm0, xmm7 );
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm5, [esi]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [esi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm0, [edi] // xmm0 = 0, 1, 2, 3
|
|
movlps xmm1, [edi+4*4]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm1 = 4, 5, 1, 2
|
|
movlps xmm2, [edi+6*4]
|
|
movhps xmm2, [edi+8*4] // xmm2 = 6, 7, 8, 9
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 3, 0, 3 ) // xmm0 = 0, 3, 6, 9
|
|
mulps xmm0, xmm5
|
|
movlps xmm3, [edi+10*4]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 2, 0, 1 ) // xmm2 = 7, 8, 10, 11
|
|
movaps xmm3, xmm1
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 2, 0, 0, 2 ) // xmm1 = 1, 4, 7, 10
|
|
mulps xmm1, xmm6
|
|
shufps xmm3, xmm2, R_SHUFFLEPS( 3, 1, 1, 3 ) // xmm3 = 2, 5, 8, 11
|
|
mulps xmm3, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm3
|
|
STORE4( 0, xmm0, xmm4 )
|
|
movss xmm1, [edi+12*4]
|
|
mulss xmm1, xmm5
|
|
movss xmm2, [edi+13*4]
|
|
mulss xmm2, xmm6
|
|
movss xmm3, [edi+14*4]
|
|
mulss xmm3, xmm7
|
|
addss xmm1, xmm2
|
|
addss xmm1, xmm3
|
|
STORE1( 16, xmm1, xmm4 )
|
|
mulss xmm5, [edi+15*4]
|
|
mulss xmm6, [edi+16*4]
|
|
mulss xmm7, [edi+17*4]
|
|
addss xmm5, xmm6
|
|
addss xmm5, xmm7
|
|
STORE1( 20, xmm5, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2];
|
|
mPtr += 3;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
switch( numRows ) {
|
|
case 4: { // 4x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi ]
|
|
movlps xmm0, qword ptr [edi ]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
STORE4( 0, xmm0, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi+ 0]
|
|
movlps xmm0, qword ptr [edi+ 0]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
movlps xmm1, qword ptr [edi+64]
|
|
movhps xmm1, qword ptr [edi+80]
|
|
STORE4( 0, xmm0, xmm4 )
|
|
mulps xmm1, xmm6
|
|
movlps xmm2, qword ptr [edi+72]
|
|
movhps xmm2, qword ptr [edi+88]
|
|
mulps xmm2, xmm7
|
|
addps xmm1, xmm2
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm3, xmm1
|
|
addps xmm1, xmm3
|
|
STORE2LO( 16, xmm1, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3];
|
|
mPtr += 4;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
switch( numRows ) {
|
|
case 5: { // 5x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+5*4] // xmm0 = 5, X, X, X
|
|
movhps xmm0, [edi+0*4] // xmm0 = 5, X, 0, 1
|
|
movss xmm5, [edi+15*4] // xmm4 = 15, X, X, X
|
|
movhps xmm5, [edi+10*4] // xmm5 = 15, X, 10, 11
|
|
movaps xmm1, xmm0 // xmm1 = 5, X, 0, 1
|
|
shufps xmm0, xmm5, R_SHUFFLEPS( 2, 0, 2, 0 ) // xmm0 = 0, 5, 10, 15
|
|
movlps xmm1, [edi+6*4] // xmm1 = 6, 7, 0, 1
|
|
movlps xmm5, [edi+16*4] // xmm5 = 16, 17, 10, 11
|
|
movaps xmm2, xmm1 // xmm2 = 6, 7, 0, 1
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm1 = 1, 6, 11, 16
|
|
movhps xmm2, [edi+2*4] // xmm2 = 6, 7, 2, 3
|
|
movhps xmm5, [edi+12*4] // xmm5 = 16, 17, 12, 13
|
|
movaps xmm3, xmm2 // xmm3 = 6, 7, 2, 3
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 2, 1, 2, 1 ) // xmm2 = 2, 7, 12, 17
|
|
movlps xmm3, [edi+8*4] // xmm3 = 8, 9, 2, 3
|
|
movlps xmm5, [edi+18*4] // xmm5 = 18, 19, 12, 13
|
|
movss xmm4, [edi+4*4] // xmm4 = 4, X, X, X
|
|
movlhps xmm4, xmm3 // xmm4 = 4, X, 8, 9
|
|
shufps xmm3, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm3 = 3, 8, 13, 18
|
|
movhps xmm5, [edi+14*4] // xmm6 = 18, 19, 14, 15
|
|
shufps xmm4, xmm5, R_SHUFFLEPS( 0, 3, 2, 1 ) // xmm4 = 4, 9, 14, 19
|
|
movss xmm7, [esi+0*4]
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm0, xmm7
|
|
movss xmm5, [esi+1*4]
|
|
shufps xmm5, xmm5, 0
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, 0
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm2
|
|
movss xmm1, [esi+3*4]
|
|
shufps xmm1, xmm1, 0
|
|
mulps xmm3, xmm1
|
|
addps xmm0, xmm3
|
|
movss xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm4, xmm2
|
|
addps xmm0, xmm4
|
|
mulss xmm7, [edi+20*4]
|
|
mulss xmm5, [edi+21*4]
|
|
addps xmm7, xmm5
|
|
mulss xmm6, [edi+22*4]
|
|
addps xmm7, xmm6
|
|
mulss xmm1, [edi+23*4]
|
|
addps xmm7, xmm1
|
|
mulss xmm2, [edi+24*4]
|
|
addps xmm7, xmm2
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE1( 16, xmm7, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [esi]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm0, [edi]
|
|
movhps xmm3, [edi+8]
|
|
movaps xmm1, [edi+16]
|
|
movlps xmm2, [edi+32]
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm0 = 0, 1, 5, 6
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 4, 7, 8, 9
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 2, 3, 7, 8
|
|
mulps xmm0, xmm6
|
|
mulps xmm3, xmm7
|
|
movlps xmm2, [edi+40]
|
|
addps xmm0, xmm3 // xmm0 + xmm1
|
|
movhps xmm5, [edi+40+8]
|
|
movlps xmm3, [edi+40+16]
|
|
movhps xmm3, [edi+40+24]
|
|
movlps xmm4, [edi+40+32]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm2 = 10, 11, 15, 16
|
|
shufps xmm3, xmm4, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm3 = 14, 17, 18, 19
|
|
shufps xmm5, xmm3, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm5 = 12, 13, 17, 18
|
|
mulps xmm2, xmm6
|
|
mulps xmm5, xmm7
|
|
addps xmm2, xmm5 // xmm2 + xmm3
|
|
movss xmm5, [esi+16]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm0
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm4, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 0, 3, 0, 3 )
|
|
addps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
STORE4( 0, xmm0, xmm2 )
|
|
movlps xmm4, [edi+80]
|
|
movhps xmm3, [edi+80+8]
|
|
movaps xmm1, [edi+80+16]
|
|
movlps xmm2, [edi+80+32]
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm4 = 20, 21, 25, 26
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 24, 27, 28, 29
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 22, 23, 27, 28
|
|
mulps xmm4, xmm6
|
|
mulps xmm3, xmm7
|
|
mulps xmm1, xmm5
|
|
addps xmm4, xmm3 // xmm4 + xmm1
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 0, 3, 0, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 1, 3, 0, 0 )
|
|
addps xmm4, xmm1
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
addps xmm4, xmm1
|
|
STORE2LO( 16, xmm4, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4];
|
|
mPtr += 5;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 6: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
movss xmm1, [esi+4]
|
|
mulss xmm1, [edi+4]
|
|
movss xmm2, [esi+8]
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+8]
|
|
movss xmm3, [esi+12]
|
|
addss xmm0, xmm2
|
|
mulss xmm3, [edi+12]
|
|
movss xmm4, [esi+16]
|
|
addss xmm0, xmm3
|
|
mulss xmm4, [edi+16]
|
|
movss xmm5, [esi+20]
|
|
addss xmm0, xmm4
|
|
mulss xmm5, [edi+20]
|
|
movss xmm6, [esi+24]
|
|
addss xmm0, xmm5
|
|
mulss xmm6, [edi+24]
|
|
addss xmm0, xmm6
|
|
STORE1( 0, xmm0, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 2x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 3x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
// row 2
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
STORE1( 8, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 4x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 5x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
// row 5
|
|
movaps xmm0, [edi+96]
|
|
movaps xmm1, [edi+96+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 0x01
|
|
addss xmm0, xmm1
|
|
STORE1( 16, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, qword ptr [esi]
|
|
movlps xmm6, qword ptr [esi+8]
|
|
shufps xmm7, xmm7, 0x44
|
|
shufps xmm6, xmm6, 0x44
|
|
movlps xmm0, qword ptr [edi ]
|
|
movhps xmm0, qword ptr [edi+ 24]
|
|
mulps xmm0, xmm7
|
|
movlps xmm3, qword ptr [edi+ 8]
|
|
movhps xmm3, qword ptr [edi+ 32]
|
|
mulps xmm3, xmm6
|
|
movlps xmm1, qword ptr [edi+ 48]
|
|
movhps xmm1, qword ptr [edi+ 72]
|
|
mulps xmm1, xmm7
|
|
movlps xmm2, qword ptr [edi+ 96]
|
|
movhps xmm2, qword ptr [edi+120]
|
|
mulps xmm2, xmm7
|
|
movlps xmm4, qword ptr [edi+ 56]
|
|
movhps xmm4, qword ptr [edi+ 80]
|
|
movlps xmm5, qword ptr [edi+104]
|
|
movhps xmm5, qword ptr [edi+128]
|
|
mulps xmm4, xmm6
|
|
movlps xmm7, qword ptr [esi+16]
|
|
addps xmm0, xmm3
|
|
shufps xmm7, xmm7, 0x44
|
|
mulps xmm5, xmm6
|
|
addps xmm1, xmm4
|
|
movlps xmm3, qword ptr [edi+ 16]
|
|
movhps xmm3, qword ptr [edi+ 40]
|
|
addps xmm2, xmm5
|
|
movlps xmm4, qword ptr [edi+ 64]
|
|
movhps xmm4, qword ptr [edi+ 88]
|
|
mulps xmm3, xmm7
|
|
movlps xmm5, qword ptr [edi+112]
|
|
movhps xmm5, qword ptr [edi+136]
|
|
addps xmm0, xmm3
|
|
mulps xmm4, xmm7
|
|
mulps xmm5, xmm7
|
|
addps xmm1, xmm4
|
|
addps xmm2, xmm5
|
|
movaps xmm6, xmm0
|
|
shufps xmm0, xmm1, 0x88
|
|
shufps xmm6, xmm1, 0xDD
|
|
movaps xmm7, xmm2
|
|
shufps xmm7, xmm2, 0x88
|
|
shufps xmm2, xmm2, 0xDD
|
|
addps xmm0, xmm6
|
|
addps xmm2, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE2LO( 16, xmm2, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] +
|
|
mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4] + mPtr[5] * vPtr[5];
|
|
mPtr += 6;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
int numColumns = mat.GetNumColumns();
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numColumns; j++ ) {
|
|
sum += mPtr[j] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
mPtr += numColumns;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_MultiplySubVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
NxN * Nx1
|
|
Nx6 * 6x1
|
|
6xN * Nx1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_MultiplySubVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss reg2, [eax+offset] \
|
|
__asm subss reg2, reg1 \
|
|
__asm movss [eax+offset], reg2
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps reg2, [eax+offset] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movhps [eax+offset], reg2
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm movhps reg2, [eax+offset+8] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2 \
|
|
__asm movhps [eax+offset+8], reg2
|
|
#define STOREC -=
|
|
|
|
int numRows;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumColumns() );
|
|
assert( dst.GetSize() >= mat.GetNumRows() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numRows = mat.GetNumRows();
|
|
switch( mat.GetNumColumns() ) {
|
|
case 1: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
STORE1( 0, xmm0, xmm1 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x1 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
switch( numRows ) {
|
|
case 2: { // 2x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm1, [esi+4]
|
|
movss xmm2, [edi]
|
|
mulss xmm2, xmm0
|
|
movss xmm3, [edi+4]
|
|
mulss xmm3, xmm1
|
|
addss xmm2, xmm3
|
|
STORE1( 0, xmm2, xmm4 )
|
|
mulss xmm0, [edi+8]
|
|
mulss xmm1, [edi+8+4]
|
|
addss xmm0, xmm1
|
|
STORE1( 4, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x2 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, [esi]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movaps xmm0, [edi]
|
|
mulps xmm0, xmm7
|
|
movaps xmm1, [edi+16]
|
|
mulps xmm1, xmm7
|
|
movaps xmm2, xmm0
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm2, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
movaps xmm3, [edi+32]
|
|
addps xmm0, xmm2
|
|
mulps xmm3, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm1, xmm3
|
|
addps xmm3, xmm1
|
|
STORE2LO( 16, xmm3, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1];
|
|
mPtr += 2;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
switch( numRows ) {
|
|
case 3: { // 3x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
movss xmm4, [edi]
|
|
mulss xmm4, xmm0
|
|
movss xmm1, [esi+4]
|
|
movss xmm5, [edi+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm4, xmm5
|
|
movss xmm2, [esi+8]
|
|
movss xmm6, [edi+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm4, xmm6
|
|
movss xmm3, [edi+12]
|
|
mulss xmm3, xmm0
|
|
STORE1( 0, xmm4, xmm7 );
|
|
movss xmm5, [edi+12+4]
|
|
mulss xmm5, xmm1
|
|
addss xmm3, xmm5
|
|
movss xmm6, [edi+12+8]
|
|
mulss xmm6, xmm2
|
|
addss xmm3, xmm6
|
|
mulss xmm0, [edi+24]
|
|
mulss xmm1, [edi+24+4]
|
|
STORE1( 4, xmm3, xmm7 );
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+24+8]
|
|
addss xmm0, xmm2
|
|
STORE1( 8, xmm0, xmm7 );
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x3 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm5, [esi]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [esi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm0, [edi] // xmm0 = 0, 1, 2, 3
|
|
movlps xmm1, [edi+4*4]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm1 = 4, 5, 1, 2
|
|
movlps xmm2, [edi+6*4]
|
|
movhps xmm2, [edi+8*4] // xmm2 = 6, 7, 8, 9
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 3, 0, 3 ) // xmm0 = 0, 3, 6, 9
|
|
mulps xmm0, xmm5
|
|
movlps xmm3, [edi+10*4]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 1, 2, 0, 1 ) // xmm2 = 7, 8, 10, 11
|
|
movaps xmm3, xmm1
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 2, 0, 0, 2 ) // xmm1 = 1, 4, 7, 10
|
|
mulps xmm1, xmm6
|
|
shufps xmm3, xmm2, R_SHUFFLEPS( 3, 1, 1, 3 ) // xmm3 = 2, 5, 8, 11
|
|
mulps xmm3, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm3
|
|
STORE4( 0, xmm0, xmm4 )
|
|
movss xmm1, [edi+12*4]
|
|
mulss xmm1, xmm5
|
|
movss xmm2, [edi+13*4]
|
|
mulss xmm2, xmm6
|
|
movss xmm3, [edi+14*4]
|
|
mulss xmm3, xmm7
|
|
addss xmm1, xmm2
|
|
addss xmm1, xmm3
|
|
STORE1( 16, xmm1, xmm4 )
|
|
mulss xmm5, [edi+15*4]
|
|
mulss xmm6, [edi+16*4]
|
|
mulss xmm7, [edi+17*4]
|
|
addss xmm5, xmm6
|
|
addss xmm5, xmm7
|
|
STORE1( 20, xmm5, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2];
|
|
mPtr += 3;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
switch( numRows ) {
|
|
case 4: { // 4x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi ]
|
|
movlps xmm0, qword ptr [edi ]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
STORE4( 0, xmm0, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x4 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, qword ptr [esi+ 0]
|
|
movlps xmm0, qword ptr [edi+ 0]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm0, qword ptr [edi+16]
|
|
mulps xmm0, xmm6
|
|
movlps xmm7, qword ptr [esi+ 8]
|
|
movlps xmm2, qword ptr [edi+ 8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movhps xmm2, qword ptr [edi+24]
|
|
mulps xmm2, xmm7
|
|
movlps xmm1, qword ptr [edi+32]
|
|
movhps xmm1, qword ptr [edi+48]
|
|
mulps xmm1, xmm6
|
|
movlps xmm3, qword ptr [edi+40]
|
|
addps xmm0, xmm2
|
|
movhps xmm3, qword ptr [edi+56]
|
|
mulps xmm3, xmm7
|
|
movaps xmm4, xmm0
|
|
addps xmm1, xmm3
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm4
|
|
movlps xmm1, qword ptr [edi+64]
|
|
movhps xmm1, qword ptr [edi+80]
|
|
STORE4( 0, xmm0, xmm4 )
|
|
mulps xmm1, xmm6
|
|
movlps xmm2, qword ptr [edi+72]
|
|
movhps xmm2, qword ptr [edi+88]
|
|
mulps xmm2, xmm7
|
|
addps xmm1, xmm2
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm3, xmm1
|
|
addps xmm1, xmm3
|
|
STORE2LO( 16, xmm1, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3];
|
|
mPtr += 4;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
switch( numRows ) {
|
|
case 5: { // 5x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+5*4] // xmm0 = 5, X, X, X
|
|
movhps xmm0, [edi+0*4] // xmm0 = 5, X, 0, 1
|
|
movss xmm5, [edi+15*4] // xmm4 = 15, X, X, X
|
|
movhps xmm5, [edi+10*4] // xmm5 = 15, X, 10, 11
|
|
movaps xmm1, xmm0 // xmm1 = 5, X, 0, 1
|
|
shufps xmm0, xmm5, R_SHUFFLEPS( 2, 0, 2, 0 ) // xmm0 = 0, 5, 10, 15
|
|
movlps xmm1, [edi+6*4] // xmm1 = 6, 7, 0, 1
|
|
movlps xmm5, [edi+16*4] // xmm5 = 16, 17, 10, 11
|
|
movaps xmm2, xmm1 // xmm2 = 6, 7, 0, 1
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm1 = 1, 6, 11, 16
|
|
movhps xmm2, [edi+2*4] // xmm2 = 6, 7, 2, 3
|
|
movhps xmm5, [edi+12*4] // xmm5 = 16, 17, 12, 13
|
|
movaps xmm3, xmm2 // xmm3 = 6, 7, 2, 3
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 2, 1, 2, 1 ) // xmm2 = 2, 7, 12, 17
|
|
movlps xmm3, [edi+8*4] // xmm3 = 8, 9, 2, 3
|
|
movlps xmm5, [edi+18*4] // xmm5 = 18, 19, 12, 13
|
|
movss xmm4, [edi+4*4] // xmm4 = 4, X, X, X
|
|
movlhps xmm4, xmm3 // xmm4 = 4, X, 8, 9
|
|
shufps xmm3, xmm5, R_SHUFFLEPS( 3, 0, 3, 0 ) // xmm3 = 3, 8, 13, 18
|
|
movhps xmm5, [edi+14*4] // xmm6 = 18, 19, 14, 15
|
|
shufps xmm4, xmm5, R_SHUFFLEPS( 0, 3, 2, 1 ) // xmm4 = 4, 9, 14, 19
|
|
movss xmm7, [esi+0*4]
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm0, xmm7
|
|
movss xmm5, [esi+1*4]
|
|
shufps xmm5, xmm5, 0
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, 0
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm2
|
|
movss xmm1, [esi+3*4]
|
|
shufps xmm1, xmm1, 0
|
|
mulps xmm3, xmm1
|
|
addps xmm0, xmm3
|
|
movss xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm4, xmm2
|
|
addps xmm0, xmm4
|
|
mulss xmm7, [edi+20*4]
|
|
mulss xmm5, [edi+21*4]
|
|
addps xmm7, xmm5
|
|
mulss xmm6, [edi+22*4]
|
|
addps xmm7, xmm6
|
|
mulss xmm1, [edi+23*4]
|
|
addps xmm7, xmm1
|
|
mulss xmm2, [edi+24*4]
|
|
addps xmm7, xmm2
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE1( 16, xmm7, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x5 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [esi]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm7, [esi+8]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movlps xmm0, [edi]
|
|
movhps xmm3, [edi+8]
|
|
movaps xmm1, [edi+16]
|
|
movlps xmm2, [edi+32]
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm0 = 0, 1, 5, 6
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 4, 7, 8, 9
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 2, 3, 7, 8
|
|
mulps xmm0, xmm6
|
|
mulps xmm3, xmm7
|
|
movlps xmm2, [edi+40]
|
|
addps xmm0, xmm3 // xmm0 + xmm1
|
|
movhps xmm5, [edi+40+8]
|
|
movlps xmm3, [edi+40+16]
|
|
movhps xmm3, [edi+40+24]
|
|
movlps xmm4, [edi+40+32]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm2 = 10, 11, 15, 16
|
|
shufps xmm3, xmm4, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm3 = 14, 17, 18, 19
|
|
shufps xmm5, xmm3, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm5 = 12, 13, 17, 18
|
|
mulps xmm2, xmm6
|
|
mulps xmm5, xmm7
|
|
addps xmm2, xmm5 // xmm2 + xmm3
|
|
movss xmm5, [esi+16]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm0
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm4, xmm2, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
shufps xmm1, xmm3, R_SHUFFLEPS( 0, 3, 0, 3 )
|
|
addps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
STORE4( 0, xmm0, xmm2 )
|
|
movlps xmm4, [edi+80]
|
|
movhps xmm3, [edi+80+8]
|
|
movaps xmm1, [edi+80+16]
|
|
movlps xmm2, [edi+80+32]
|
|
shufps xmm4, xmm1, R_SHUFFLEPS( 0, 1, 1, 2 ) // xmm4 = 20, 21, 25, 26
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 3, 0, 1 ) // xmm1 = 24, 27, 28, 29
|
|
shufps xmm3, xmm1, R_SHUFFLEPS( 2, 3, 1, 2 ) // xmm3 = 22, 23, 27, 28
|
|
mulps xmm4, xmm6
|
|
mulps xmm3, xmm7
|
|
mulps xmm1, xmm5
|
|
addps xmm4, xmm3 // xmm4 + xmm1
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 0, 3, 0, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 1, 3, 0, 0 )
|
|
addps xmm4, xmm1
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
addps xmm4, xmm1
|
|
STORE2LO( 16, xmm4, xmm2 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] + mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4];
|
|
mPtr += 5;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 6: {
|
|
switch( numRows ) {
|
|
case 1: { // 1x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
mulss xmm0, [edi]
|
|
movss xmm1, [esi+4]
|
|
mulss xmm1, [edi+4]
|
|
movss xmm2, [esi+8]
|
|
addss xmm0, xmm1
|
|
mulss xmm2, [edi+8]
|
|
movss xmm3, [esi+12]
|
|
addss xmm0, xmm2
|
|
mulss xmm3, [edi+12]
|
|
movss xmm4, [esi+16]
|
|
addss xmm0, xmm3
|
|
mulss xmm4, [edi+16]
|
|
movss xmm5, [esi+20]
|
|
addss xmm0, xmm4
|
|
mulss xmm5, [edi+20]
|
|
movss xmm6, [esi+24]
|
|
addss xmm0, xmm5
|
|
mulss xmm6, [edi+24]
|
|
addss xmm0, xmm6
|
|
STORE1( 0, xmm0, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 2x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 3x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 1, 3 )
|
|
movhlps xmm0, xmm1
|
|
addps xmm0, xmm1
|
|
STORE2LO( 0, xmm0, xmm3 )
|
|
// row 2
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
STORE1( 8, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 4x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 5x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
// load idVecX
|
|
movlps xmm4, [esi]
|
|
movhps xmm4, [esi+8]
|
|
movlps xmm5, [esi+16]
|
|
movlhps xmm5, xmm4
|
|
movhlps xmm6, xmm4
|
|
movlhps xmm6, xmm5
|
|
// row 0 and 1
|
|
movaps xmm0, [edi]
|
|
movaps xmm1, [edi+16]
|
|
movaps xmm2, [edi+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm7, xmm0
|
|
movlhps xmm7, xmm2
|
|
addps xmm7, xmm1
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm7, xmm0
|
|
// row 2 and 3
|
|
movaps xmm0, [edi+48]
|
|
movaps xmm1, [edi+48+16]
|
|
movaps xmm2, [edi+48+32]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
mulps xmm2, xmm6
|
|
movhlps xmm3, xmm0
|
|
movlhps xmm3, xmm2
|
|
addps xmm1, xmm3
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
addps xmm1, xmm0
|
|
// last 4 additions for the first 4 rows and store result
|
|
movaps xmm0, xmm7
|
|
shufps xmm7, xmm1, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 1, 3, 1, 3 )
|
|
addps xmm0, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
// row 5
|
|
movaps xmm0, [edi+96]
|
|
movaps xmm1, [edi+96+16]
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 0x01
|
|
addss xmm0, xmm1
|
|
STORE1( 16, xmm0, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm7, qword ptr [esi]
|
|
movlps xmm6, qword ptr [esi+8]
|
|
shufps xmm7, xmm7, 0x44
|
|
shufps xmm6, xmm6, 0x44
|
|
movlps xmm0, qword ptr [edi ]
|
|
movhps xmm0, qword ptr [edi+ 24]
|
|
mulps xmm0, xmm7
|
|
movlps xmm3, qword ptr [edi+ 8]
|
|
movhps xmm3, qword ptr [edi+ 32]
|
|
mulps xmm3, xmm6
|
|
movlps xmm1, qword ptr [edi+ 48]
|
|
movhps xmm1, qword ptr [edi+ 72]
|
|
mulps xmm1, xmm7
|
|
movlps xmm2, qword ptr [edi+ 96]
|
|
movhps xmm2, qword ptr [edi+120]
|
|
mulps xmm2, xmm7
|
|
movlps xmm4, qword ptr [edi+ 56]
|
|
movhps xmm4, qword ptr [edi+ 80]
|
|
movlps xmm5, qword ptr [edi+104]
|
|
movhps xmm5, qword ptr [edi+128]
|
|
mulps xmm4, xmm6
|
|
movlps xmm7, qword ptr [esi+16]
|
|
addps xmm0, xmm3
|
|
shufps xmm7, xmm7, 0x44
|
|
mulps xmm5, xmm6
|
|
addps xmm1, xmm4
|
|
movlps xmm3, qword ptr [edi+ 16]
|
|
movhps xmm3, qword ptr [edi+ 40]
|
|
addps xmm2, xmm5
|
|
movlps xmm4, qword ptr [edi+ 64]
|
|
movhps xmm4, qword ptr [edi+ 88]
|
|
mulps xmm3, xmm7
|
|
movlps xmm5, qword ptr [edi+112]
|
|
movhps xmm5, qword ptr [edi+136]
|
|
addps xmm0, xmm3
|
|
mulps xmm4, xmm7
|
|
mulps xmm5, xmm7
|
|
addps xmm1, xmm4
|
|
addps xmm2, xmm5
|
|
movaps xmm6, xmm0
|
|
shufps xmm0, xmm1, 0x88
|
|
shufps xmm6, xmm1, 0xDD
|
|
movaps xmm7, xmm2
|
|
shufps xmm7, xmm2, 0x88
|
|
shufps xmm2, xmm2, 0xDD
|
|
addps xmm0, xmm6
|
|
addps xmm2, xmm7
|
|
STORE4( 0, xmm0, xmm3 )
|
|
STORE2LO( 16, xmm2, xmm4 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
dstPtr[i] STOREC mPtr[0] * vPtr[0] + mPtr[1] * vPtr[1] + mPtr[2] * vPtr[2] +
|
|
mPtr[3] * vPtr[3] + mPtr[4] * vPtr[4] + mPtr[5] * vPtr[5];
|
|
mPtr += 6;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
int numColumns = mat.GetNumColumns();
|
|
for ( int i = 0; i < numRows; i++ ) {
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numColumns; j++ ) {
|
|
sum += mPtr[j] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
mPtr += numColumns;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_TransposeMultiplyVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
Nx6 * Nx1
|
|
6xN * 6x1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_TransposeMultiplyVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss [eax+offset], reg1
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps [eax+offset], reg1
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps [eax+offset], reg1
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps [eax+offset], reg1 \
|
|
__asm movhps [eax+offset+8], reg1
|
|
#define STOREC =
|
|
|
|
int numColumns;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumRows() );
|
|
assert( dst.GetSize() >= mat.GetNumColumns() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numColumns = mat.GetNumColumns();
|
|
switch( mat.GetNumRows() ) {
|
|
case 1:
|
|
switch( numColumns ) {
|
|
case 6: { // 1x6 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
switch( numColumns ) {
|
|
case 6: { // 2x6 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movaps xmm1, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movaps xmm2, [edi]
|
|
mulps xmm2, xmm0
|
|
movlps xmm3, [edi+24]
|
|
movhps xmm3, [edi+32]
|
|
mulps xmm3, xmm1
|
|
addps xmm2, xmm3
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm4, [edi+16]
|
|
movhps xmm4, [edi+40]
|
|
mulps xmm4, xmm0
|
|
movhlps xmm3, xmm4
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm2, xmm5 )
|
|
STORE2LO( 16, xmm3, xmm6 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
switch( numColumns ) {
|
|
case 6: { // 3x6 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movss xmm1, [esi+2*4]
|
|
movlps xmm3, [edi+(0*6+0)*4]
|
|
movhps xmm3, [edi+(0*6+2)*4]
|
|
movaps xmm4, xmm0
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(2*6+4)*4]
|
|
mulps xmm5, xmm1
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
switch( numColumns ) {
|
|
case 6: { // 4x6 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
switch( numColumns ) {
|
|
case 6: { // 5x6 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movss xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm2
|
|
mulps xmm4, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 6:
|
|
switch( numColumns ) {
|
|
case 1: { // 6x1 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movhps xmm0, [esi+8]
|
|
movlps xmm1, [esi+16]
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 3, 2 )
|
|
addps xmm0, xmm1
|
|
movhlps xmm2, xmm0
|
|
addss xmm2, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm2, xmm0
|
|
STORE1( 0, xmm2, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 6x2 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm6, [edi+0*4]
|
|
mulps xmm6, xmm0
|
|
movlps xmm1, [esi+2*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+4*4]
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+8*4]
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movhlps xmm3, xmm6
|
|
addps xmm3, xmm6
|
|
STORE2LO( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 6x3 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+(0*3+2)*4]
|
|
movhps xmm0, [edi+(0*3+0)*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm6, [esi+0*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movss xmm1, [edi+(1*3+0)*4]
|
|
movhps xmm1, [edi+(1*3+1)*4]
|
|
movss xmm7, [esi+1*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movss xmm2, [edi+(2*3+2)*4]
|
|
movhps xmm2, [edi+(2*3+0)*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+2*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movss xmm3, [edi+(3*3+0)*4]
|
|
movhps xmm3, [edi+(3*3+1)*4]
|
|
movss xmm7, [esi+3*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movss xmm4, [edi+(4*3+2)*4]
|
|
movhps xmm4, [edi+(4*3+0)*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+4*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movss xmm5, [edi+(5*3+0)*4]
|
|
movhps xmm5, [edi+(5*3+1)*4]
|
|
movss xmm7, [esi+5*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE1( 0, xmm6, xmm7 )
|
|
STORE2HI( 4, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 6x4 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm3, [edi+(0*4+0)*4]
|
|
movhps xmm3, [edi+(0*4+2)*4]
|
|
movss xmm4, [esi+0*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*4+0)*4]
|
|
movhps xmm5, [edi+(1*4+2)*4]
|
|
movss xmm6, [esi+1*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*4+0)*4]
|
|
movhps xmm4, [edi+(2*4+2)*4]
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*4+0)*4]
|
|
movhps xmm5, [edi+(3*4+2)*4]
|
|
movss xmm6, [esi+3*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(4*4+0)*4]
|
|
movhps xmm4, [edi+(4*4+2)*4]
|
|
movss xmm6, [esi+4*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(5*4+0)*4]
|
|
movhps xmm5, [edi+(5*4+2)*4]
|
|
movss xmm6, [esi+5*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 6x5 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [edi+(0*5+0)*4]
|
|
movhps xmm6, [edi+(0*5+2)*4]
|
|
movss xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movlps xmm7, [edi+(1*5+0)*4]
|
|
movhps xmm7, [edi+(1*5+2)*4]
|
|
movss xmm1, [esi+1*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(2*5+0)*4]
|
|
movhps xmm7, [edi+(2*5+2)*4]
|
|
movss xmm2, [esi+2*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(3*5+0)*4]
|
|
movhps xmm7, [edi+(3*5+2)*4]
|
|
movss xmm3, [esi+3*4]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(4*5+0)*4]
|
|
movhps xmm7, [edi+(4*5+2)*4]
|
|
movss xmm4, [esi+4*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(5*5+0)*4]
|
|
movhps xmm7, [edi+(5*5+2)*4]
|
|
movss xmm5, [esi+5*4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE4( 0, xmm6, xmm7 )
|
|
movss xmm6, [edi+(0*5+4)*4]
|
|
mulss xmm6, xmm0
|
|
movss xmm7, [edi+(1*5+4)*4]
|
|
mulss xmm7, xmm1
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(2*5+4)*4]
|
|
mulss xmm7, xmm2
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(3*5+4)*4]
|
|
mulss xmm7, xmm3
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(4*5+4)*4]
|
|
mulss xmm7, xmm4
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(5*5+4)*4]
|
|
mulss xmm7, xmm5
|
|
addss xmm6, xmm7
|
|
STORE1( 16, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movlps xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(5*6+0)*4]
|
|
movhps xmm5, [edi+(5*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
movhps xmm5, [edi+(5*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4] + *(mPtr+5*numColumns) * vPtr[5];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
int numRows = mat.GetNumRows();
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
mPtr = mat.ToFloatPtr() + i;
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numRows; j++ ) {
|
|
mPtr += numColumns;
|
|
sum += mPtr[0] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_TransposeMultiplyAddVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
Nx6 * Nx1
|
|
6xN * 6x1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_TransposeMultiplyAddVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss reg2, [eax+offset] \
|
|
__asm addss reg2, reg1 \
|
|
__asm movss [eax+offset], reg2
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps reg2, [eax+offset] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movhps [eax+offset], reg2
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm movhps reg2, [eax+offset+8] \
|
|
__asm addps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2 \
|
|
__asm movhps [eax+offset+8], reg2
|
|
#define STOREC +=
|
|
|
|
int numColumns;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumRows() );
|
|
assert( dst.GetSize() >= mat.GetNumColumns() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numColumns = mat.GetNumColumns();
|
|
switch( mat.GetNumRows() ) {
|
|
case 1:
|
|
switch( numColumns ) {
|
|
case 6: { // 1x6 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
switch( numColumns ) {
|
|
case 6: { // 2x6 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movaps xmm1, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movaps xmm2, [edi]
|
|
mulps xmm2, xmm0
|
|
movlps xmm3, [edi+24]
|
|
movhps xmm3, [edi+32]
|
|
mulps xmm3, xmm1
|
|
addps xmm2, xmm3
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm4, [edi+16]
|
|
movhps xmm4, [edi+40]
|
|
mulps xmm4, xmm0
|
|
movhlps xmm3, xmm4
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm2, xmm5 )
|
|
STORE2LO( 16, xmm3, xmm6 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
switch( numColumns ) {
|
|
case 6: { // 3x6 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movss xmm1, [esi+2*4]
|
|
movlps xmm3, [edi+(0*6+0)*4]
|
|
movhps xmm3, [edi+(0*6+2)*4]
|
|
movaps xmm4, xmm0
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(2*6+4)*4]
|
|
mulps xmm5, xmm1
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
switch( numColumns ) {
|
|
case 6: { // 4x6 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
switch( numColumns ) {
|
|
case 6: { // 5x6 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movss xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm2
|
|
mulps xmm4, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 6:
|
|
switch( numColumns ) {
|
|
case 1: { // 6x1 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movhps xmm0, [esi+8]
|
|
movlps xmm1, [esi+16]
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 3, 2 )
|
|
addps xmm0, xmm1
|
|
movhlps xmm2, xmm0
|
|
addss xmm2, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm2, xmm0
|
|
STORE1( 0, xmm2, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 6x2 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm6, [edi+0*4]
|
|
mulps xmm6, xmm0
|
|
movlps xmm1, [esi+2*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+4*4]
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+8*4]
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movhlps xmm3, xmm6
|
|
addps xmm3, xmm6
|
|
STORE2LO( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 6x3 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+(0*3+2)*4]
|
|
movhps xmm0, [edi+(0*3+0)*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm6, [esi+0*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movss xmm1, [edi+(1*3+0)*4]
|
|
movhps xmm1, [edi+(1*3+1)*4]
|
|
movss xmm7, [esi+1*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movss xmm2, [edi+(2*3+2)*4]
|
|
movhps xmm2, [edi+(2*3+0)*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+2*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movss xmm3, [edi+(3*3+0)*4]
|
|
movhps xmm3, [edi+(3*3+1)*4]
|
|
movss xmm7, [esi+3*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movss xmm4, [edi+(4*3+2)*4]
|
|
movhps xmm4, [edi+(4*3+0)*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+4*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movss xmm5, [edi+(5*3+0)*4]
|
|
movhps xmm5, [edi+(5*3+1)*4]
|
|
movss xmm7, [esi+5*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE1( 0, xmm6, xmm7 )
|
|
STORE2HI( 4, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 6x4 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm3, [edi+(0*4+0)*4]
|
|
movhps xmm3, [edi+(0*4+2)*4]
|
|
movss xmm4, [esi+0*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*4+0)*4]
|
|
movhps xmm5, [edi+(1*4+2)*4]
|
|
movss xmm6, [esi+1*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*4+0)*4]
|
|
movhps xmm4, [edi+(2*4+2)*4]
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*4+0)*4]
|
|
movhps xmm5, [edi+(3*4+2)*4]
|
|
movss xmm6, [esi+3*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(4*4+0)*4]
|
|
movhps xmm4, [edi+(4*4+2)*4]
|
|
movss xmm6, [esi+4*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(5*4+0)*4]
|
|
movhps xmm5, [edi+(5*4+2)*4]
|
|
movss xmm6, [esi+5*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 6x5 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [edi+(0*5+0)*4]
|
|
movhps xmm6, [edi+(0*5+2)*4]
|
|
movss xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movlps xmm7, [edi+(1*5+0)*4]
|
|
movhps xmm7, [edi+(1*5+2)*4]
|
|
movss xmm1, [esi+1*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(2*5+0)*4]
|
|
movhps xmm7, [edi+(2*5+2)*4]
|
|
movss xmm2, [esi+2*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(3*5+0)*4]
|
|
movhps xmm7, [edi+(3*5+2)*4]
|
|
movss xmm3, [esi+3*4]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(4*5+0)*4]
|
|
movhps xmm7, [edi+(4*5+2)*4]
|
|
movss xmm4, [esi+4*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(5*5+0)*4]
|
|
movhps xmm7, [edi+(5*5+2)*4]
|
|
movss xmm5, [esi+5*4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE4( 0, xmm6, xmm7 )
|
|
movss xmm6, [edi+(0*5+4)*4]
|
|
mulss xmm6, xmm0
|
|
movss xmm7, [edi+(1*5+4)*4]
|
|
mulss xmm7, xmm1
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(2*5+4)*4]
|
|
mulss xmm7, xmm2
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(3*5+4)*4]
|
|
mulss xmm7, xmm3
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(4*5+4)*4]
|
|
mulss xmm7, xmm4
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(5*5+4)*4]
|
|
mulss xmm7, xmm5
|
|
addss xmm6, xmm7
|
|
STORE1( 16, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movlps xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(5*6+0)*4]
|
|
movhps xmm5, [edi+(5*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
movhps xmm5, [edi+(5*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4] + *(mPtr+5*numColumns) * vPtr[5];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
int numRows = mat.GetNumRows();
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
mPtr = mat.ToFloatPtr() + i;
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numRows; j++ ) {
|
|
mPtr += numColumns;
|
|
sum += mPtr[0] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
void idSIMD_SSE::MatX_TransposeMultiplySubVecX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
Nx6 * Nx1
|
|
6xN * 6x1
|
|
|
|
with N in the range [1-6]
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_TransposeMultiplySubVecX( idVecX &dst, const idMatX &mat, const idVecX &vec ) {
|
|
#define STORE1( offset, reg1, reg2 ) \
|
|
__asm movss reg2, [eax+offset] \
|
|
__asm subss reg2, reg1 \
|
|
__asm movss [eax+offset], reg2
|
|
#define STORE2LO( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2
|
|
#define STORE2HI( offset, reg1, reg2 ) \
|
|
__asm movhps reg2, [eax+offset] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movhps [eax+offset], reg2
|
|
#define STORE4( offset, reg1, reg2 ) \
|
|
__asm movlps reg2, [eax+offset] \
|
|
__asm movhps reg2, [eax+offset+8] \
|
|
__asm subps reg2, reg1 \
|
|
__asm movlps [eax+offset], reg2 \
|
|
__asm movhps [eax+offset+8], reg2
|
|
#define STOREC -=
|
|
|
|
int numColumns;
|
|
const float *mPtr, *vPtr;
|
|
float *dstPtr;
|
|
|
|
assert( vec.GetSize() >= mat.GetNumRows() );
|
|
assert( dst.GetSize() >= mat.GetNumColumns() );
|
|
|
|
mPtr = mat.ToFloatPtr();
|
|
vPtr = vec.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
numColumns = mat.GetNumColumns();
|
|
switch( mat.GetNumRows() ) {
|
|
case 1:
|
|
switch( numColumns ) {
|
|
case 6: { // 1x6 * 1x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
STORE4( 0, xmm0, xmm2 )
|
|
STORE2LO( 16, xmm1, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
switch( numColumns ) {
|
|
case 6: { // 2x6 * 2x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movaps xmm1, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movaps xmm2, [edi]
|
|
mulps xmm2, xmm0
|
|
movlps xmm3, [edi+24]
|
|
movhps xmm3, [edi+32]
|
|
mulps xmm3, xmm1
|
|
addps xmm2, xmm3
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm4, [edi+16]
|
|
movhps xmm4, [edi+40]
|
|
mulps xmm4, xmm0
|
|
movhlps xmm3, xmm4
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm2, xmm5 )
|
|
STORE2LO( 16, xmm3, xmm6 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
switch( numColumns ) {
|
|
case 6: { // 3x6 * 3x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movss xmm1, [esi+2*4]
|
|
movlps xmm3, [edi+(0*6+0)*4]
|
|
movhps xmm3, [edi+(0*6+2)*4]
|
|
movaps xmm4, xmm0
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(2*6+4)*4]
|
|
mulps xmm5, xmm1
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
switch( numColumns ) {
|
|
case 6: { // 4x6 * 4x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*6+0)*4]
|
|
movhps xmm4, [edi+(2*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
switch( numColumns ) {
|
|
case 6: { // 5x6 * 5x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movss xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm4, xmm2
|
|
mulps xmm4, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm4
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 6:
|
|
switch( numColumns ) {
|
|
case 1: { // 6x1 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi]
|
|
movhps xmm0, [esi+8]
|
|
movlps xmm1, [esi+16]
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 3, 2 )
|
|
addps xmm0, xmm1
|
|
movhlps xmm2, xmm0
|
|
addss xmm2, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm2, xmm0
|
|
STORE1( 0, xmm2, xmm3 )
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 6x2 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm6, [edi+0*4]
|
|
mulps xmm6, xmm0
|
|
movlps xmm1, [esi+2*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+4*4]
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm2, [esi+4*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm7, [edi+8*4]
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movhlps xmm3, xmm6
|
|
addps xmm3, xmm6
|
|
STORE2LO( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 3: { // 6x3 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi+(0*3+2)*4]
|
|
movhps xmm0, [edi+(0*3+0)*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm6, [esi+0*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movss xmm1, [edi+(1*3+0)*4]
|
|
movhps xmm1, [edi+(1*3+1)*4]
|
|
movss xmm7, [esi+1*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movss xmm2, [edi+(2*3+2)*4]
|
|
movhps xmm2, [edi+(2*3+0)*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+2*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movss xmm3, [edi+(3*3+0)*4]
|
|
movhps xmm3, [edi+(3*3+1)*4]
|
|
movss xmm7, [esi+3*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movss xmm4, [edi+(4*3+2)*4]
|
|
movhps xmm4, [edi+(4*3+0)*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 2, 1, 3, 0 )
|
|
movss xmm7, [esi+4*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movss xmm5, [edi+(5*3+0)*4]
|
|
movhps xmm5, [edi+(5*3+1)*4]
|
|
movss xmm7, [esi+5*4]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE1( 0, xmm6, xmm7 )
|
|
STORE2HI( 4, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 4: { // 6x4 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm3, [edi+(0*4+0)*4]
|
|
movhps xmm3, [edi+(0*4+2)*4]
|
|
movss xmm4, [esi+0*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm4
|
|
movlps xmm5, [edi+(1*4+0)*4]
|
|
movhps xmm5, [edi+(1*4+2)*4]
|
|
movss xmm6, [esi+1*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(2*4+0)*4]
|
|
movhps xmm4, [edi+(2*4+2)*4]
|
|
movss xmm6, [esi+2*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(3*4+0)*4]
|
|
movhps xmm5, [edi+(3*4+2)*4]
|
|
movss xmm6, [esi+3*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movlps xmm4, [edi+(4*4+0)*4]
|
|
movhps xmm4, [edi+(4*4+2)*4]
|
|
movss xmm6, [esi+4*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(5*4+0)*4]
|
|
movhps xmm5, [edi+(5*4+2)*4]
|
|
movss xmm6, [esi+5*4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 5: { // 6x5 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm6, [edi+(0*5+0)*4]
|
|
movhps xmm6, [edi+(0*5+2)*4]
|
|
movss xmm0, [esi+0*4]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movlps xmm7, [edi+(1*5+0)*4]
|
|
movhps xmm7, [edi+(1*5+2)*4]
|
|
movss xmm1, [esi+1*4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(2*5+0)*4]
|
|
movhps xmm7, [edi+(2*5+2)*4]
|
|
movss xmm2, [esi+2*4]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(3*5+0)*4]
|
|
movhps xmm7, [edi+(3*5+2)*4]
|
|
movss xmm3, [esi+3*4]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(4*5+0)*4]
|
|
movhps xmm7, [edi+(4*5+2)*4]
|
|
movss xmm4, [esi+4*4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movlps xmm7, [edi+(5*5+0)*4]
|
|
movhps xmm7, [edi+(5*5+2)*4]
|
|
movss xmm5, [esi+5*4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
STORE4( 0, xmm6, xmm7 )
|
|
movss xmm6, [edi+(0*5+4)*4]
|
|
mulss xmm6, xmm0
|
|
movss xmm7, [edi+(1*5+4)*4]
|
|
mulss xmm7, xmm1
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(2*5+4)*4]
|
|
mulss xmm7, xmm2
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(3*5+4)*4]
|
|
mulss xmm7, xmm3
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(4*5+4)*4]
|
|
mulss xmm7, xmm4
|
|
addss xmm6, xmm7
|
|
movss xmm7, [edi+(5*5+4)*4]
|
|
mulss xmm7, xmm5
|
|
addss xmm6, xmm7
|
|
STORE1( 16, xmm6, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, vPtr
|
|
mov edi, mPtr
|
|
mov eax, dstPtr
|
|
movlps xmm0, [esi+0*4]
|
|
movlps xmm1, [esi+2*4]
|
|
movlps xmm2, [esi+4*4]
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, [edi+(0*6+0)*4]
|
|
movlps xmm5, [edi+(1*6+0)*4]
|
|
movhps xmm5, [edi+(1*6+2)*4]
|
|
movaps xmm6, xmm0
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(2*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(3*6+0)*4]
|
|
movhps xmm5, [edi+(3*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, [edi+(4*6+0)*4]
|
|
addps xmm3, xmm6
|
|
movaps xmm6, xmm2
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movlps xmm5, [edi+(5*6+0)*4]
|
|
movhps xmm5, [edi+(5*6+2)*4]
|
|
mulps xmm5, xmm6
|
|
addps xmm3, xmm5
|
|
STORE4( 0, xmm3, xmm7 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movlps xmm3, [edi+(0*6+4)*4]
|
|
movhps xmm3, [edi+(1*6+4)*4]
|
|
mulps xmm3, xmm0
|
|
movlps xmm4, [edi+(2*6+4)*4]
|
|
movhps xmm4, [edi+(3*6+4)*4]
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movlps xmm5, [edi+(4*6+4)*4]
|
|
movhps xmm5, [edi+(5*6+4)*4]
|
|
mulps xmm5, xmm2
|
|
addps xmm3, xmm5
|
|
movhlps xmm4, xmm3
|
|
addps xmm3, xmm4
|
|
STORE2LO( 16, xmm3, xmm7 )
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
dstPtr[i] STOREC *(mPtr) * vPtr[0] + *(mPtr+numColumns) * vPtr[1] + *(mPtr+2*numColumns) * vPtr[2] +
|
|
*(mPtr+3*numColumns) * vPtr[3] + *(mPtr+4*numColumns) * vPtr[4] + *(mPtr+5*numColumns) * vPtr[5];
|
|
mPtr++;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
int numRows = mat.GetNumRows();
|
|
for ( int i = 0; i < numColumns; i++ ) {
|
|
mPtr = mat.ToFloatPtr() + i;
|
|
float sum = mPtr[0] * vPtr[0];
|
|
for ( int j = 1; j < numRows; j++ ) {
|
|
mPtr += numColumns;
|
|
sum += mPtr[0] * vPtr[j];
|
|
}
|
|
dstPtr[i] STOREC sum;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#undef STOREC
|
|
#undef STORE4
|
|
#undef STORE2HI
|
|
#undef STORE2LO
|
|
#undef STORE1
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_MultiplyMatX
|
|
|
|
optimizes the following matrix multiplications:
|
|
|
|
NxN * Nx6
|
|
6xN * Nx6
|
|
Nx6 * 6xN
|
|
6x6 * 6xN
|
|
|
|
with N in the range [1-6].
|
|
|
|
The hot cache clock cycle counts are generally better for the SIMD version than the
|
|
FPU version. At times up to 40% less clock cycles on a P3. In practise however,
|
|
the results are poor probably due to memory access.
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_MultiplyMatX( idMatX &dst, const idMatX &m1, const idMatX &m2 ) {
|
|
int i, j, k, l, n;
|
|
float *dstPtr;
|
|
const float *m1Ptr, *m2Ptr;
|
|
double sum;
|
|
|
|
assert( m1.GetNumColumns() == m2.GetNumRows() );
|
|
|
|
dstPtr = dst.ToFloatPtr();
|
|
m1Ptr = m1.ToFloatPtr();
|
|
m2Ptr = m2.ToFloatPtr();
|
|
k = m1.GetNumRows();
|
|
l = m2.GetNumColumns();
|
|
n = m1.GetNumColumns();
|
|
|
|
switch( n ) {
|
|
case 1: {
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 1: { // 1x1 * 1x6, no precision loss compared to FPU version
|
|
__asm {
|
|
mov esi, m2Ptr
|
|
mov edi, m1Ptr
|
|
mov eax, dstPtr
|
|
movss xmm0, [edi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, [esi]
|
|
mulps xmm1, xmm0
|
|
movaps [eax], xmm1
|
|
movlps xmm2, [esi+16]
|
|
mulps xmm2, xmm0
|
|
movlps [eax+16], xmm2
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x1 * 1x6, no precision loss compared to FPU version
|
|
__asm {
|
|
mov esi, m2Ptr
|
|
mov edi, m1Ptr
|
|
mov eax, dstPtr
|
|
xorps xmm1, xmm1
|
|
movaps xmm0, [edi]
|
|
movlps xmm1, [edi+16]
|
|
movlhps xmm1, xmm0
|
|
movhlps xmm2, xmm0
|
|
movlhps xmm2, xmm1
|
|
// row 0 and 1
|
|
movaps xmm3, [esi]
|
|
movaps xmm4, xmm3
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm5, xmm3
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
movaps xmm6, xmm3
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
movaps [eax], xmm4
|
|
movaps [eax+16], xmm5
|
|
movaps [eax+32], xmm6
|
|
// row 2 and 3
|
|
movaps xmm4, xmm3
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 2, 2, 2, 2 )
|
|
movaps xmm5, xmm3
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 2, 2, 3, 3 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 3, 3, 3 )
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm3, xmm2
|
|
movaps [eax+48], xmm4
|
|
movaps [eax+64], xmm5
|
|
movaps [eax+80], xmm3
|
|
// row 4 and 5
|
|
movlps xmm3, [esi+16]
|
|
movaps xmm4, xmm3
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm5, xmm3
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm3, xmm2
|
|
movaps [eax+96], xmm4
|
|
movaps [eax+112], xmm5
|
|
movaps [eax+128], xmm3
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 2: { // 2x2 * 2x6
|
|
|
|
#define MUL_Nx2_2x6_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm movlps xmm1, [esi+16] \
|
|
__asm movhps xmm1, [esi+40] \
|
|
__asm movlps xmm2, [esi+24] \
|
|
__asm movhps xmm2, [esi+32]
|
|
|
|
#define MUL_Nx2_2x6_ROW2( row ) \
|
|
__asm movaps xmm3, [edi+row*16] \
|
|
__asm movaps xmm5, xmm0 \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm movaps xmm6, xmm2 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 1, 1, 1, 1 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm5, xmm6 \
|
|
__asm movaps [eax+row*48], xmm5 \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm movaps xmm7, xmm1 \
|
|
__asm mulps xmm7, xmm4 \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm movaps xmm5, xmm0 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 2, 2, 2, 2 ) \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm movaps xmm6, xmm2 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 3, 3, 3, 3 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm5, xmm6 \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 2, 2, 3, 3 ) \
|
|
__asm movaps xmm6, xmm1 \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm movaps xmm4, xmm7 \
|
|
__asm movlhps xmm7, xmm6 \
|
|
__asm movhlps xmm6, xmm4 \
|
|
__asm addps xmm6, xmm7 \
|
|
__asm movlps [eax+row*48+16], xmm6 \
|
|
__asm movlps [eax+row*48+24], xmm5 \
|
|
__asm movhps [eax+row*48+32], xmm5 \
|
|
__asm movhps [eax+row*48+40], xmm6
|
|
|
|
MUL_Nx2_2x6_INIT
|
|
MUL_Nx2_2x6_ROW2( 0 )
|
|
|
|
return;
|
|
}
|
|
case 6: { // 6x2 * 2x6
|
|
|
|
MUL_Nx2_2x6_INIT
|
|
MUL_Nx2_2x6_ROW2( 0 )
|
|
MUL_Nx2_2x6_ROW2( 1 )
|
|
MUL_Nx2_2x6_ROW2( 2 )
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr += 2;
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 3: { // 3x3 * 3x6
|
|
__asm {
|
|
mov esi, m2Ptr
|
|
mov edi, m1Ptr
|
|
mov eax, dstPtr
|
|
movaps xmm5, xmmword ptr [esi]
|
|
movlps xmm6, qword ptr [esi+24]
|
|
movhps xmm6, qword ptr [esi+32]
|
|
movaps xmm7, xmmword ptr [esi+48]
|
|
movss xmm0, dword ptr [edi]
|
|
shufps xmm0, xmm0, 0
|
|
mulps xmm0, xmm5
|
|
movss xmm1, dword ptr [edi+4]
|
|
shufps xmm1, xmm1, 0
|
|
mulps xmm1, xmm6
|
|
movss xmm2, dword ptr [edi+8]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm2, xmm7
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
movaps xmmword ptr [eax], xmm0
|
|
movss xmm3, dword ptr [edi+12]
|
|
shufps xmm3, xmm3, 0
|
|
mulps xmm3, xmm5
|
|
movss xmm4, dword ptr [edi+16]
|
|
shufps xmm4, xmm4, 0
|
|
mulps xmm4, xmm6
|
|
movss xmm0, dword ptr [edi+20]
|
|
shufps xmm0, xmm0, 0
|
|
mulps xmm0, xmm7
|
|
addps xmm3, xmm4
|
|
addps xmm0, xmm3
|
|
movlps qword ptr [eax+24], xmm0
|
|
movhps qword ptr [eax+32], xmm0
|
|
movss xmm1, dword ptr [edi+24]
|
|
shufps xmm1, xmm1, 0
|
|
mulps xmm1, xmm5
|
|
movss xmm2, dword ptr [edi+28]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm2, xmm6
|
|
movss xmm3, dword ptr [edi+32]
|
|
shufps xmm3, xmm3, 0
|
|
mulps xmm3, xmm7
|
|
addps xmm1, xmm2
|
|
addps xmm1, xmm3
|
|
movaps xmmword ptr [eax+48], xmm1
|
|
movlps xmm5, qword ptr [esi+16]
|
|
movlps xmm6, qword ptr [esi+40]
|
|
movlps xmm7, qword ptr [esi+64]
|
|
shufps xmm5, xmm5, 0x44
|
|
shufps xmm6, xmm6, 0x44
|
|
shufps xmm7, xmm7, 0x44
|
|
movaps xmm3, xmmword ptr [edi]
|
|
movlps xmm4, qword ptr [edi+16]
|
|
movaps xmm0, xmm3
|
|
shufps xmm0, xmm0, 0xF0
|
|
mulps xmm0, xmm5
|
|
movaps xmm1, xmm3
|
|
shufps xmm1, xmm4, 0x05
|
|
mulps xmm1, xmm6
|
|
shufps xmm3, xmm4, 0x5A
|
|
mulps xmm3, xmm7
|
|
addps xmm1, xmm0
|
|
addps xmm1, xmm3
|
|
movlps qword ptr [eax+16], xmm1
|
|
movhps qword ptr [eax+40], xmm1
|
|
movss xmm0, dword ptr [edi+24]
|
|
shufps xmm0, xmm0, 0
|
|
mulps xmm0, xmm5
|
|
movss xmm2, dword ptr [edi+28]
|
|
shufps xmm2, xmm2, 0
|
|
mulps xmm2, xmm6
|
|
movss xmm4, dword ptr [edi+32]
|
|
shufps xmm4, xmm4, 0
|
|
mulps xmm4, xmm7
|
|
addps xmm0, xmm2
|
|
addps xmm0, xmm4
|
|
movlps qword ptr [eax+64], xmm0
|
|
}
|
|
return;
|
|
}
|
|
case 6: { // 6x3 * 3x6
|
|
#define MUL_Nx3_3x6_FIRST4COLUMNS_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 2*4] \
|
|
__asm movlps xmm1, [esi+ 6*4] \
|
|
__asm movhps xmm1, [esi+ 8*4] \
|
|
__asm movlps xmm2, [esi+12*4] \
|
|
__asm movhps xmm2, [esi+14*4]
|
|
|
|
#define MUL_Nx3_3x6_FIRST4COLUMNS_ROW( row ) \
|
|
__asm movss xmm3, [edi+(row*3+0)*4] \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm movss xmm4, [edi+(row*3+1)*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm movss xmm5, [edi+(row*3+2)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movlps [eax+(row*6+0)*4], xmm3 \
|
|
__asm movhps [eax+(row*6+2)*4], xmm3
|
|
|
|
#define MUL_Nx3_3x6_LAST2COLUMNS_ROW6 \
|
|
__asm movlps xmm0, [esi+ 4*4] \
|
|
__asm movlps xmm1, [esi+10*4] \
|
|
__asm movlps xmm2, [esi+16*4] \
|
|
__asm shufps xmm0, xmm0, 0x44 \
|
|
__asm shufps xmm1, xmm1, 0x44 \
|
|
__asm shufps xmm2, xmm2, 0x44 \
|
|
__asm movlps xmm3, [edi+0*4] \
|
|
__asm movhps xmm3, [edi+2*4] \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm movaps xmm5, xmm3 \
|
|
__asm shufps xmm3, xmm3, 0xF0 \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm movlps xmm6, [edi+4*4] \
|
|
__asm movhps xmm6, [edi+6*4] \
|
|
__asm shufps xmm4, xmm6, 0x05 \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm shufps xmm5, xmm6, 0x5A \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movlps [eax+4*4], xmm3 \
|
|
__asm movhps [eax+10*4], xmm3 \
|
|
__asm movaps xmm5, xmm6 \
|
|
__asm movlps xmm3, [edi+8*4] \
|
|
__asm movhps xmm3, [edi+10*4] \
|
|
__asm movaps xmm4, xmm3 \
|
|
__asm shufps xmm5, xmm3, 0x5A \
|
|
__asm mulps xmm5, xmm0 \
|
|
__asm shufps xmm6, xmm3, 0xAF \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm5, xmm6 \
|
|
__asm shufps xmm4, xmm4, 0xF0 \
|
|
__asm mulps xmm4, xmm2 \
|
|
__asm addps xmm4, xmm5 \
|
|
__asm movlps [eax+16*4], xmm4 \
|
|
__asm movhps [eax+22*4], xmm4 \
|
|
__asm movlps xmm6, [edi+12*4] \
|
|
__asm movhps xmm6, [edi+14*4] \
|
|
__asm movaps xmm5, xmm6 \
|
|
__asm movaps xmm4, xmm6 \
|
|
__asm shufps xmm6, xmm6, 0xF0 \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm movlps xmm3, [edi+16*4] \
|
|
__asm shufps xmm5, xmm3, 0x05 \
|
|
__asm mulps xmm5, xmm1 \
|
|
__asm addps xmm5, xmm6 \
|
|
__asm shufps xmm4, xmm3, 0x5A \
|
|
__asm mulps xmm4, xmm2 \
|
|
__asm addps xmm4, xmm5 \
|
|
__asm movlps [eax+28*4], xmm4 \
|
|
__asm movhps [eax+34*4], xmm4
|
|
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_INIT
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 0 )
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 1 )
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 2 )
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 3 )
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 4 )
|
|
MUL_Nx3_3x6_FIRST4COLUMNS_ROW( 5 )
|
|
MUL_Nx3_3x6_LAST2COLUMNS_ROW6
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[l] + m1Ptr[2] * m2Ptr[2*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr += 3;
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 4: { // 4x4 * 4x6
|
|
|
|
#define MUL_Nx4_4x6_FIRST4COLUMNS_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 2*4] \
|
|
__asm movlps xmm1, [esi+ 6*4] \
|
|
__asm movhps xmm1, [esi+ 8*4] \
|
|
__asm movlps xmm2, [esi+12*4] \
|
|
__asm movhps xmm2, [esi+14*4] \
|
|
__asm movlps xmm3, [esi+18*4] \
|
|
__asm movhps xmm3, [esi+20*4]
|
|
|
|
#define MUL_Nx4_4x6_FIRST4COLUMNS_ROW( row ) \
|
|
__asm movss xmm4, [edi+row*16+0*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm4, xmm0 \
|
|
__asm movss xmm5, [edi+row*16+1*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm1 \
|
|
__asm addps xmm4, xmm5 \
|
|
__asm movss xmm6, [edi+row*16+2*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm4, xmm6 \
|
|
__asm movss xmm7, [edi+row*16+3*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm3 \
|
|
__asm addps xmm4, xmm7 \
|
|
__asm movlps [eax+row*24+0], xmm4 \
|
|
__asm movhps [eax+row*24+8], xmm4
|
|
|
|
#define MUL_Nx4_4x6_LAST2COLUMNS_INIT \
|
|
__asm movlps xmm0, [esi+ 4*4] \
|
|
__asm movlps xmm1, [esi+10*4] \
|
|
__asm movlps xmm2, [esi+16*4] \
|
|
__asm movlps xmm3, [esi+22*4] \
|
|
__asm shufps xmm0, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm1, xmm0, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm2, xmm3, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm3, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
|
|
#define MUL_Nx4_4x6_LAST2COLUMNS_ROW2( row ) \
|
|
__asm movlps xmm7, [edi+row*32+ 0*4] \
|
|
__asm movhps xmm7, [edi+row*32+ 4*4] \
|
|
__asm movaps xmm6, xmm7 \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 3, 3 ) \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 1, 1, 2, 2 ) \
|
|
__asm mulps xmm7, xmm1 \
|
|
__asm addps xmm6, xmm7 \
|
|
__asm movlps xmm4, [edi+row*32+ 2*4] \
|
|
__asm movhps xmm4, [edi+row*32+ 6*4] \
|
|
__asm movaps xmm5, xmm4 \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 3, 3 ) \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 1, 1, 2, 2 ) \
|
|
__asm mulps xmm4, xmm3 \
|
|
__asm addps xmm6, xmm4 \
|
|
__asm movlps [eax+row*48+ 4*4], xmm6 \
|
|
__asm movhps [eax+row*48+10*4], xmm6
|
|
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_INIT
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 0 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 1 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 2 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 3 )
|
|
MUL_Nx4_4x6_LAST2COLUMNS_INIT
|
|
MUL_Nx4_4x6_LAST2COLUMNS_ROW2( 0 )
|
|
MUL_Nx4_4x6_LAST2COLUMNS_ROW2( 1 )
|
|
|
|
return;
|
|
}
|
|
case 6: { // 6x4 * 4x6
|
|
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_INIT
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 0 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 1 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 2 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 3 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 4 )
|
|
MUL_Nx4_4x6_FIRST4COLUMNS_ROW( 5 )
|
|
MUL_Nx4_4x6_LAST2COLUMNS_INIT
|
|
MUL_Nx4_4x6_LAST2COLUMNS_ROW2( 0 )
|
|
MUL_Nx4_4x6_LAST2COLUMNS_ROW2( 1 )
|
|
MUL_Nx4_4x6_LAST2COLUMNS_ROW2( 2 )
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[l] + m1Ptr[2] * m2Ptr[2*l] +
|
|
m1Ptr[3] * m2Ptr[3*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr += 4;
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 5: { // 5x5 * 5x6
|
|
|
|
#define MUL_Nx5_5x6_FIRST4COLUMNS_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 2*4] \
|
|
__asm movlps xmm1, [esi+ 6*4] \
|
|
__asm movhps xmm1, [esi+ 8*4] \
|
|
__asm movlps xmm2, [esi+12*4] \
|
|
__asm movhps xmm2, [esi+14*4] \
|
|
__asm movlps xmm3, [esi+18*4] \
|
|
__asm movhps xmm3, [esi+20*4] \
|
|
__asm movlps xmm4, [esi+24*4] \
|
|
__asm movhps xmm4, [esi+26*4]
|
|
|
|
#define MUL_Nx5_5x6_FIRST4COLUMNS_ROW( row ) \
|
|
__asm movss xmm6, [edi+row*20+0*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm movss xmm5, [edi+row*20+1*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm1 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movss xmm5, [edi+row*20+2*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movss xmm5, [edi+row*20+3*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm3 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movss xmm5, [edi+row*20+4*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movlps [eax+row*24+0], xmm6 \
|
|
__asm movhps [eax+row*24+8], xmm6
|
|
|
|
#define MUL_Nx5_5x6_LAST2COLUMNS_INIT \
|
|
__asm movlps xmm0, [esi+ 4*4] \
|
|
__asm movlps xmm1, [esi+10*4] \
|
|
__asm movlps xmm2, [esi+16*4] \
|
|
__asm movlps xmm3, [esi+22*4] \
|
|
__asm movlps xmm4, [esi+28*4] \
|
|
__asm shufps xmm0, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm1, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm2, xmm3, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm3, xmm4, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm4, xmm0, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
|
|
#define MUL_Nx5_5x6_LAST2COLUMNS_ROW2( row ) \
|
|
__asm movlps xmm7, [edi+row*40+ 0*4] \
|
|
__asm movhps xmm7, [edi+row*40+ 6*4] \
|
|
__asm movaps xmm6, xmm7 \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 2, 2 ) \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm movaps xmm5, xmm7 \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 1, 1, 3, 3 ) \
|
|
__asm mulps xmm5, xmm1 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movlps xmm7, [edi+row*40+ 2*4] \
|
|
__asm movhps xmm7, [edi+row*40+ 8*4] \
|
|
__asm movaps xmm5, xmm7 \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 2, 2 ) \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movaps xmm5, xmm7 \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 1, 1, 3, 3 ) \
|
|
__asm mulps xmm5, xmm3 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movlps xmm5, [edi+row*40+ 4*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movlps [eax+row*48+ 4*4], xmm6 \
|
|
__asm movhps [eax+row*48+10*4], xmm6
|
|
|
|
#define MUL_Nx5_5x6_LAST2COLUMNS_ROW( row ) \
|
|
__asm movlps xmm6, [edi+20*4+0*4] \
|
|
__asm unpcklps xmm6, xmm6 \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm movlps xmm5, [edi+20*4+2*4] \
|
|
__asm unpcklps xmm5, xmm5 \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movss xmm5, [edi+20*4+4*4] \
|
|
__asm unpcklps xmm5, xmm5 \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm movhlps xmm7, xmm6 \
|
|
__asm addps xmm6, xmm7 \
|
|
__asm movlps [eax+row*24+4*4], xmm6
|
|
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_INIT
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 0 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 1 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 2 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 3 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 4 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_INIT
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW2( 0 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW2( 1 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW( 4 )
|
|
|
|
return;
|
|
}
|
|
case 6: { // 6x5 * 5x6
|
|
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_INIT
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 0 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 1 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 2 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 3 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 4 )
|
|
MUL_Nx5_5x6_FIRST4COLUMNS_ROW( 5 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_INIT
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW2( 0 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW2( 1 )
|
|
MUL_Nx5_5x6_LAST2COLUMNS_ROW2( 2 )
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[l] + m1Ptr[2] * m2Ptr[2*l] +
|
|
m1Ptr[3] * m2Ptr[3*l] + m1Ptr[4] * m2Ptr[4*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr += 5;
|
|
}
|
|
break;
|
|
}
|
|
case 6: {
|
|
switch( k ) {
|
|
case 1: {
|
|
if ( !(l^1) ) { // 1x6 * 6x1
|
|
dstPtr[0] = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[1] + m1Ptr[2] * m2Ptr[2] +
|
|
m1Ptr[3] * m2Ptr[3] + m1Ptr[4] * m2Ptr[4] + m1Ptr[5] * m2Ptr[5];
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
if ( !(l^2) ) { // 2x6 * 6x2
|
|
|
|
#define MUL_Nx6_6x2_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm movaps xmm1, [esi+16] \
|
|
__asm movaps xmm2, [esi+32]
|
|
|
|
#define MUL_Nx6_6x2_ROW2( row ) \
|
|
__asm movaps xmm7, [edi+row*48+0*4] \
|
|
__asm movaps xmm6, xmm7 \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 2, 2, 3, 3 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movaps xmm6, [edi+row*48+4*4] \
|
|
__asm movaps xmm5, xmm6 \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 2, 2, 3, 3 ) \
|
|
__asm mulps xmm5, xmm0 \
|
|
__asm movaps xmm6, [edi+row*48+24+2*4] \
|
|
__asm movaps xmm4, xmm6 \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm5, xmm6 \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 2, 2, 3, 3 ) \
|
|
__asm mulps xmm4, xmm2 \
|
|
__asm addps xmm5, xmm4 \
|
|
__asm movaps xmm4, xmm5 \
|
|
__asm movhlps xmm5, xmm7 \
|
|
__asm movlhps xmm7, xmm4 \
|
|
__asm addps xmm7, xmm5 \
|
|
__asm movaps [eax+row*16], xmm7
|
|
|
|
MUL_Nx6_6x2_INIT
|
|
MUL_Nx6_6x2_ROW2( 0 )
|
|
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 3: {
|
|
if ( !(l^3) ) { // 3x6 * 6x3
|
|
|
|
#define MUL_Nx6_6x3_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movss xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 1*4] \
|
|
__asm movss xmm1, [esi+ 3*4] \
|
|
__asm movhps xmm1, [esi+ 4*4] \
|
|
__asm movss xmm2, [esi+ 6*4] \
|
|
__asm movhps xmm2, [esi+ 7*4] \
|
|
__asm movss xmm3, [esi+ 9*4] \
|
|
__asm movhps xmm3, [esi+10*4] \
|
|
__asm movss xmm4, [esi+12*4] \
|
|
__asm movhps xmm4, [esi+13*4] \
|
|
__asm movss xmm5, [esi+15*4] \
|
|
__asm movhps xmm5, [esi+16*4]
|
|
|
|
#define MUL_Nx6_6x3_ROW( row ) \
|
|
__asm movss xmm7, [edi+row*24+0] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movss xmm6, [edi+row*24+4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+8] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+12] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+16] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+20] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss [eax+row*12+0], xmm7 \
|
|
__asm movhps [eax+row*12+4], xmm7
|
|
|
|
MUL_Nx6_6x3_INIT
|
|
MUL_Nx6_6x3_ROW( 0 )
|
|
MUL_Nx6_6x3_ROW( 1 )
|
|
MUL_Nx6_6x3_ROW( 2 )
|
|
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
if ( !(l^4) ) { // 4x6 * 6x4
|
|
|
|
#define MUL_Nx6_6x4_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm movaps xmm1, [esi+16] \
|
|
__asm movaps xmm2, [esi+32] \
|
|
__asm movaps xmm3, [esi+48] \
|
|
__asm movaps xmm4, [esi+64] \
|
|
__asm movaps xmm5, [esi+80]
|
|
|
|
#define MUL_Nx6_6x4_ROW( row ) \
|
|
__asm movss xmm7, [edi+row*24+0] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movss xmm6, [edi+row*24+4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+8] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+12] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+16] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+row*24+20] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movaps [eax+row*16], xmm7
|
|
|
|
MUL_Nx6_6x4_INIT
|
|
MUL_Nx6_6x4_ROW( 0 )
|
|
MUL_Nx6_6x4_ROW( 1 )
|
|
MUL_Nx6_6x4_ROW( 2 )
|
|
MUL_Nx6_6x4_ROW( 3 )
|
|
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 5: {
|
|
if ( !(l^5) ) { // 5x6 * 6x5
|
|
|
|
#define MUL_Nx6_6x5_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm movlps xmm1, [esi+20] \
|
|
__asm movhps xmm1, [esi+28] \
|
|
__asm movlps xmm2, [esi+40] \
|
|
__asm movhps xmm2, [esi+48] \
|
|
__asm movlps xmm3, [esi+60] \
|
|
__asm movhps xmm3, [esi+68] \
|
|
__asm movaps xmm4, [esi+80] \
|
|
__asm movlps xmm5, [esi+100] \
|
|
__asm movhps xmm5, [esi+108]
|
|
|
|
#define MUL_Nx6_6x5_ROW( row ) \
|
|
__asm movss xmm7, [edi+row*24+0] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm fld dword ptr [edi+(row*6+0)*4] \
|
|
__asm fmul dword ptr [esi+(4+0*5)*4] \
|
|
__asm movss xmm6, [edi+row*24+4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm fld dword ptr [edi+(row*6+1)*4] \
|
|
__asm fmul dword ptr [esi+(4+1*5)*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm6, [edi+row*24+8] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm fld dword ptr [edi+(row*6+2)*4] \
|
|
__asm fmul dword ptr [esi+(4+2*5)*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm6, [edi+row*24+12] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm fld dword ptr [edi+(row*6+3)*4] \
|
|
__asm fmul dword ptr [esi+(4+3*5)*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm6, [edi+row*24+16] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm fld dword ptr [edi+(row*6+4)*4] \
|
|
__asm fmul dword ptr [esi+(4+4*5)*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm6, [edi+row*24+20] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm fld dword ptr [edi+(row*6+5)*4] \
|
|
__asm fmul dword ptr [esi+(4+5*5)*4] \
|
|
__asm faddp st(1),st \
|
|
__asm fstp dword ptr [eax+(row*5+4)*4] \
|
|
__asm movlps [eax+row*20], xmm7 \
|
|
__asm movhps [eax+row*20+8], xmm7
|
|
|
|
MUL_Nx6_6x5_INIT
|
|
MUL_Nx6_6x5_ROW( 0 )
|
|
MUL_Nx6_6x5_ROW( 1 )
|
|
MUL_Nx6_6x5_ROW( 2 )
|
|
MUL_Nx6_6x5_ROW( 3 )
|
|
MUL_Nx6_6x5_ROW( 4 )
|
|
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 6: {
|
|
switch( l ) {
|
|
case 1: { // 6x6 * 6x1
|
|
__asm {
|
|
mov esi, m2Ptr
|
|
mov edi, m1Ptr
|
|
mov eax, dstPtr
|
|
movlps xmm7, qword ptr [esi]
|
|
movlps xmm6, qword ptr [esi+8]
|
|
shufps xmm7, xmm7, 0x44
|
|
shufps xmm6, xmm6, 0x44
|
|
movlps xmm0, qword ptr [edi ]
|
|
movhps xmm0, qword ptr [edi+ 24]
|
|
mulps xmm0, xmm7
|
|
movlps xmm3, qword ptr [edi+ 8]
|
|
movhps xmm3, qword ptr [edi+ 32]
|
|
mulps xmm3, xmm6
|
|
movlps xmm1, qword ptr [edi+ 48]
|
|
movhps xmm1, qword ptr [edi+ 72]
|
|
mulps xmm1, xmm7
|
|
movlps xmm2, qword ptr [edi+ 96]
|
|
movhps xmm2, qword ptr [edi+120]
|
|
mulps xmm2, xmm7
|
|
movlps xmm4, qword ptr [edi+ 56]
|
|
movhps xmm4, qword ptr [edi+ 80]
|
|
movlps xmm5, qword ptr [edi+104]
|
|
movhps xmm5, qword ptr [edi+128]
|
|
mulps xmm4, xmm6
|
|
movlps xmm7, qword ptr [esi+16]
|
|
addps xmm0, xmm3
|
|
shufps xmm7, xmm7, 0x44
|
|
mulps xmm5, xmm6
|
|
addps xmm1, xmm4
|
|
movlps xmm3, qword ptr [edi+ 16]
|
|
movhps xmm3, qword ptr [edi+ 40]
|
|
addps xmm2, xmm5
|
|
movlps xmm4, qword ptr [edi+ 64]
|
|
movhps xmm4, qword ptr [edi+ 88]
|
|
mulps xmm3, xmm7
|
|
movlps xmm5, qword ptr [edi+112]
|
|
movhps xmm5, qword ptr [edi+136]
|
|
addps xmm0, xmm3
|
|
mulps xmm4, xmm7
|
|
mulps xmm5, xmm7
|
|
addps xmm1, xmm4
|
|
addps xmm2, xmm5
|
|
movaps xmm6, xmm0
|
|
shufps xmm0, xmm1, 0x88
|
|
shufps xmm6, xmm1, 0xDD
|
|
movaps xmm7, xmm2
|
|
shufps xmm7, xmm2, 0x88
|
|
shufps xmm2, xmm2, 0xDD
|
|
addps xmm0, xmm6
|
|
addps xmm2, xmm7
|
|
movlps [eax], xmm0
|
|
movhps [eax+8], xmm0
|
|
movlps [eax+16], xmm2
|
|
}
|
|
return;
|
|
}
|
|
case 2: { // 6x6 * 6x2
|
|
|
|
MUL_Nx6_6x2_INIT
|
|
MUL_Nx6_6x2_ROW2( 0 )
|
|
MUL_Nx6_6x2_ROW2( 1 )
|
|
MUL_Nx6_6x2_ROW2( 2 )
|
|
|
|
return;
|
|
}
|
|
case 3: { // 6x6 * 6x3
|
|
|
|
MUL_Nx6_6x3_INIT
|
|
MUL_Nx6_6x3_ROW( 0 )
|
|
MUL_Nx6_6x3_ROW( 1 )
|
|
MUL_Nx6_6x3_ROW( 2 )
|
|
MUL_Nx6_6x3_ROW( 3 )
|
|
MUL_Nx6_6x3_ROW( 4 )
|
|
MUL_Nx6_6x3_ROW( 5 )
|
|
|
|
return;
|
|
}
|
|
case 4: { // 6x6 * 6x4
|
|
|
|
MUL_Nx6_6x4_INIT
|
|
MUL_Nx6_6x4_ROW( 0 )
|
|
MUL_Nx6_6x4_ROW( 1 )
|
|
MUL_Nx6_6x4_ROW( 2 )
|
|
MUL_Nx6_6x4_ROW( 3 )
|
|
MUL_Nx6_6x4_ROW( 4 )
|
|
MUL_Nx6_6x4_ROW( 5 )
|
|
|
|
return;
|
|
}
|
|
case 5: { // 6x6 * 6x5
|
|
|
|
MUL_Nx6_6x5_INIT
|
|
MUL_Nx6_6x5_ROW( 0 )
|
|
MUL_Nx6_6x5_ROW( 1 )
|
|
MUL_Nx6_6x5_ROW( 2 )
|
|
MUL_Nx6_6x5_ROW( 3 )
|
|
MUL_Nx6_6x5_ROW( 4 )
|
|
MUL_Nx6_6x5_ROW( 5 )
|
|
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x6
|
|
__asm {
|
|
mov ecx, dword ptr m2Ptr
|
|
movlps xmm3, qword ptr [ecx+72]
|
|
mov edx, dword ptr m1Ptr
|
|
// Loading first 4 columns (upper 4 rows) of m2Ptr.
|
|
movaps xmm0, xmmword ptr [ecx]
|
|
movlps xmm1, qword ptr [ecx+24]
|
|
movhps xmm1, qword ptr [ecx+32]
|
|
movaps xmm2, xmmword ptr [ecx+48]
|
|
movhps xmm3, qword ptr [ecx+80]
|
|
// Calculating first 4 elements in the first row of the destination matrix.
|
|
movss xmm4, dword ptr [edx]
|
|
movss xmm5, dword ptr [edx+4]
|
|
mov eax, dword ptr dstPtr
|
|
shufps xmm4, xmm4, 0
|
|
movss xmm6, dword ptr [edx+8]
|
|
shufps xmm5, xmm5, 0
|
|
movss xmm7, dword ptr [edx+12]
|
|
mulps xmm4, xmm0
|
|
shufps xmm6, xmm6, 0
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
addps xmm5, xmm4
|
|
mulps xmm7, xmm3
|
|
addps xmm6, xmm5
|
|
addps xmm7, xmm6
|
|
movaps xmmword ptr [eax], xmm7
|
|
// Calculating first 4 elements in the second row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+24]
|
|
shufps xmm4, xmm4, 0
|
|
mulps xmm4, xmm0
|
|
movss xmm5, dword ptr [edx+28]
|
|
shufps xmm5, xmm5, 0
|
|
mulps xmm5, xmm1
|
|
movss xmm6, dword ptr [edx+32]
|
|
shufps xmm6, xmm6, 0
|
|
movss xmm7, dword ptr [edx+36]
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm6, xmm2
|
|
mulps xmm7, xmm3
|
|
addps xmm7, xmm6
|
|
addps xmm5, xmm4
|
|
addps xmm7, xmm5
|
|
// Calculating first 4 elements in the third row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+48]
|
|
movss xmm5, dword ptr [edx+52]
|
|
movlps qword ptr [eax+24], xmm7 ; save 2nd
|
|
movhps qword ptr [eax+32], xmm7 ; row
|
|
movss xmm6, dword ptr [edx+56]
|
|
movss xmm7, dword ptr [edx+60]
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
shufps xmm6, xmm6, 0
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
mulps xmm7, xmm3
|
|
addps xmm5, xmm4
|
|
addps xmm7, xmm6
|
|
addps xmm7, xmm5
|
|
movaps xmmword ptr [eax+48], xmm7
|
|
// Calculating first 4 elements in the fourth row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+72]
|
|
movss xmm5, dword ptr [edx+76]
|
|
movss xmm6, dword ptr [edx+80]
|
|
movss xmm7, dword ptr [edx+84]
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
shufps xmm6, xmm6, 0
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
mulps xmm7, xmm3
|
|
addps xmm4, xmm5
|
|
addps xmm6, xmm4
|
|
addps xmm7, xmm6
|
|
movlps qword ptr [eax+72], xmm7
|
|
movhps qword ptr [eax+80], xmm7
|
|
// Calculating first 4 elements in the fifth row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+96]
|
|
movss xmm5, dword ptr [edx+100]
|
|
movss xmm6, dword ptr [edx+104]
|
|
movss xmm7, dword ptr [edx+108]
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
shufps xmm6, xmm6, 0
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
mulps xmm7, xmm3
|
|
addps xmm5, xmm4
|
|
addps xmm7, xmm6
|
|
addps xmm7, xmm5
|
|
movaps xmmword ptr [eax+96], xmm7
|
|
// Calculating first 4 elements in the sixth row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+120]
|
|
movss xmm5, dword ptr [edx+124]
|
|
movss xmm6, dword ptr [edx+128]
|
|
movss xmm7, dword ptr [edx+132]
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
shufps xmm6, xmm6, 0
|
|
shufps xmm7, xmm7, 0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm6, xmm2
|
|
mulps xmm7, xmm3
|
|
addps xmm4, xmm5
|
|
addps xmm6, xmm4
|
|
addps xmm7, xmm6
|
|
movhps qword ptr [eax+128], xmm7
|
|
movlps qword ptr [eax+120], xmm7
|
|
// Loading first 4 columns (lower 2 rows) of m2Ptr.
|
|
movlps xmm0, qword ptr [ecx+96]
|
|
movhps xmm0, qword ptr [ecx+104]
|
|
movlps xmm1, qword ptr [ecx+120]
|
|
movhps xmm1, qword ptr [ecx+128]
|
|
// Calculating first 4 elements in the first row of the destination matrix.
|
|
movss xmm2, dword ptr [edx+16]
|
|
shufps xmm2, xmm2, 0
|
|
movss xmm4, dword ptr [edx+40]
|
|
movss xmm3, dword ptr [edx+20]
|
|
movss xmm5, dword ptr [edx+44]
|
|
movaps xmm6, xmmword ptr [eax]
|
|
movlps xmm7, qword ptr [eax+24]
|
|
shufps xmm3, xmm3, 0
|
|
shufps xmm5, xmm5, 0
|
|
movhps xmm7, qword ptr [eax+32]
|
|
shufps xmm4, xmm4, 0
|
|
mulps xmm5, xmm1
|
|
mulps xmm2, xmm0
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm0
|
|
addps xmm6, xmm2
|
|
addps xmm7, xmm4
|
|
addps xmm7, xmm5
|
|
addps xmm6, xmm3
|
|
movlps qword ptr [eax+24], xmm7
|
|
movaps xmmword ptr [eax], xmm6
|
|
movhps qword ptr [eax+32], xmm7
|
|
// Calculating first 4 elements in the third row of the destination matrix.
|
|
movss xmm2, dword ptr [edx+64]
|
|
movss xmm4, dword ptr [edx+88]
|
|
movss xmm5, dword ptr [edx+92]
|
|
movss xmm3, dword ptr [edx+68]
|
|
movaps xmm6, xmmword ptr [eax+48]
|
|
movlps xmm7, qword ptr [eax+72]
|
|
movhps xmm7, qword ptr [eax+80]
|
|
shufps xmm2, xmm2, 0
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
shufps xmm3, xmm3, 0
|
|
mulps xmm2, xmm0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
mulps xmm3, xmm1
|
|
addps xmm6, xmm2
|
|
addps xmm6, xmm3
|
|
addps xmm7, xmm4
|
|
addps xmm7, xmm5
|
|
movlps qword ptr [eax+72], xmm7
|
|
movaps xmmword ptr [eax+48], xmm6
|
|
movhps qword ptr [eax+80], xmm7
|
|
// Calculating first 4 elements in the fifth row of the destination matrix.
|
|
movss xmm2, dword ptr [edx+112]
|
|
movss xmm3, dword ptr [edx+116]
|
|
movaps xmm6, xmmword ptr [eax+96]
|
|
shufps xmm2, xmm2, 0
|
|
shufps xmm3, xmm3, 0
|
|
mulps xmm2, xmm0
|
|
mulps xmm3, xmm1
|
|
addps xmm6, xmm2
|
|
addps xmm6, xmm3
|
|
movaps xmmword ptr [eax+96], xmm6
|
|
// Calculating first 4 elements in the sixth row of the destination matrix.
|
|
movss xmm4, dword ptr [edx+136]
|
|
movss xmm5, dword ptr [edx+140]
|
|
movhps xmm7, qword ptr [eax+128]
|
|
movlps xmm7, qword ptr [eax+120]
|
|
shufps xmm4, xmm4, 0
|
|
shufps xmm5, xmm5, 0
|
|
mulps xmm4, xmm0
|
|
mulps xmm5, xmm1
|
|
addps xmm7, xmm4
|
|
addps xmm7, xmm5
|
|
// Calculating last 2 columns of the destination matrix.
|
|
movlps xmm0, qword ptr [ecx+16]
|
|
movhps xmm0, qword ptr [ecx+40]
|
|
movhps qword ptr [eax+128], xmm7
|
|
movlps qword ptr [eax+120], xmm7
|
|
movlps xmm2, qword ptr [ecx+64]
|
|
movhps xmm2, qword ptr [ecx+88]
|
|
movaps xmm3, xmm2
|
|
shufps xmm3, xmm3, 4Eh
|
|
movlps xmm4, qword ptr [ecx+112]
|
|
movhps xmm4, qword ptr [ecx+136]
|
|
movaps xmm5, xmm4
|
|
shufps xmm5, xmm5, 4Eh
|
|
movlps xmm6, qword ptr [edx]
|
|
movhps xmm6, qword ptr [edx+24]
|
|
movaps xmm7, xmm6
|
|
shufps xmm7, xmm7, 0F0h
|
|
mulps xmm7, xmm0
|
|
shufps xmm6, xmm6, 0A5h
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 4Eh
|
|
mulps xmm1, xmm6
|
|
addps xmm7, xmm1
|
|
movlps xmm6, qword ptr [edx+8]
|
|
movhps xmm6, qword ptr [edx+32]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm2
|
|
mulps xmm6, xmm3
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movhps xmm6, qword ptr [edx+40]
|
|
movlps xmm6, qword ptr [edx+16]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm4
|
|
mulps xmm6, xmm5
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movlps qword ptr [eax+16], xmm7
|
|
movhps qword ptr [eax+40], xmm7
|
|
movlps xmm6, qword ptr [edx+48]
|
|
movhps xmm6, qword ptr [edx+72]
|
|
movaps xmm7, xmm6
|
|
shufps xmm7, xmm7, 0F0h
|
|
mulps xmm7, xmm0
|
|
shufps xmm6, xmm6, 0A5h
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 4Eh
|
|
mulps xmm1, xmm6
|
|
addps xmm7, xmm1
|
|
movhps xmm6, qword ptr [edx+80]
|
|
movlps xmm6, qword ptr [edx+56]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm2
|
|
mulps xmm6, xmm3
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movlps xmm6, qword ptr [edx+64]
|
|
movhps xmm6, qword ptr [edx+88]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm4
|
|
mulps xmm6, xmm5
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movlps qword ptr [eax+64], xmm7
|
|
movhps qword ptr [eax+88], xmm7
|
|
movlps xmm6, qword ptr [edx+96]
|
|
movhps xmm6, qword ptr [edx+120]
|
|
movaps xmm7, xmm6
|
|
shufps xmm7, xmm7, 0F0h
|
|
mulps xmm7, xmm0
|
|
shufps xmm6, xmm6, 0A5h
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, 4Eh
|
|
mulps xmm1, xmm6
|
|
addps xmm7, xmm1
|
|
movlps xmm6, qword ptr [edx+104]
|
|
movhps xmm6, qword ptr [edx+128]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm2
|
|
mulps xmm6, xmm3
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movlps xmm6, qword ptr [edx+112]
|
|
movhps xmm6, qword ptr [edx+136]
|
|
movaps xmm1, xmm6
|
|
shufps xmm1, xmm1, 0F0h
|
|
shufps xmm6, xmm6, 0A5h
|
|
mulps xmm1, xmm4
|
|
mulps xmm6, xmm5
|
|
addps xmm7, xmm1
|
|
addps xmm7, xmm6
|
|
movlps qword ptr [eax+112], xmm7
|
|
movhps qword ptr [eax+136], xmm7
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[1] * m2Ptr[l] + m1Ptr[2] * m2Ptr[2*l] +
|
|
m1Ptr[3] * m2Ptr[3*l] + m1Ptr[4] * m2Ptr[4*l] + m1Ptr[5] * m2Ptr[5*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr += 6;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
for ( i = 0; i < k; i++ ) {
|
|
for ( j = 0; j < l; j++ ) {
|
|
m2Ptr = m2.ToFloatPtr() + j;
|
|
sum = m1Ptr[0] * m2Ptr[0];
|
|
for ( n = 1; n < m1.GetNumColumns(); n++ ) {
|
|
m2Ptr += l;
|
|
sum += m1Ptr[n] * m2Ptr[0];
|
|
}
|
|
*dstPtr++ = sum;
|
|
}
|
|
m1Ptr += m1.GetNumColumns();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_TransposeMultiplyMatX
|
|
|
|
optimizes the following transpose matrix multiplications:
|
|
|
|
Nx6 * NxN
|
|
6xN * 6x6
|
|
|
|
with N in the range [1-6].
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_TransposeMultiplyMatX( idMatX &dst, const idMatX &m1, const idMatX &m2 ) {
|
|
int i, j, k, l, n;
|
|
float *dstPtr;
|
|
const float *m1Ptr, *m2Ptr;
|
|
double sum;
|
|
|
|
assert( m1.GetNumRows() == m2.GetNumRows() );
|
|
|
|
m1Ptr = m1.ToFloatPtr();
|
|
m2Ptr = m2.ToFloatPtr();
|
|
dstPtr = dst.ToFloatPtr();
|
|
k = m1.GetNumColumns();
|
|
l = m2.GetNumColumns();
|
|
|
|
switch( m1.GetNumRows() ) {
|
|
case 1:
|
|
if ( !((k^6)|(l^1)) ) { // 1x6 * 1x1
|
|
__asm {
|
|
mov esi, m2Ptr
|
|
mov edi, m1Ptr
|
|
mov eax, dstPtr
|
|
movss xmm0, [esi]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm1, xmm0
|
|
mulps xmm0, [edi]
|
|
mulps xmm1, [edi+16]
|
|
movaps [eax], xmm0
|
|
movlps [eax+16], xmm1
|
|
}
|
|
return;
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
case 2:
|
|
if ( !((k^6)|(l^2)) ) { // 2x6 * 2x2
|
|
#define MUL_2xN_2x2_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi] \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm movlps xmm1, [esi+8] \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
|
|
#define MUL_2xN_2x2_ROW2( N, row ) \
|
|
__asm movlps xmm6, [edi+(row+0*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm movlps xmm7, [edi+(row+1*N)*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm mulps xmm7, xmm1 \
|
|
__asm addps xmm6, xmm7 \
|
|
__asm movaps [eax+(row*2)*4], xmm6
|
|
|
|
MUL_2xN_2x2_INIT
|
|
MUL_2xN_2x2_ROW2( 6, 0 )
|
|
MUL_2xN_2x2_ROW2( 6, 2 )
|
|
MUL_2xN_2x2_ROW2( 6, 4 )
|
|
|
|
return;
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[k] * m2Ptr[l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
case 3:
|
|
if ( !((k^6)|(l^3)) ) { // 3x6 * 3x3
|
|
|
|
#define MUL_3xN_3x3_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movss xmm0, [esi+(0*3+0)*4] \
|
|
__asm movhps xmm0, [esi+(0*3+1)*4] \
|
|
__asm movss xmm1, [esi+(1*3+0)*4] \
|
|
__asm movhps xmm1, [esi+(1*3+1)*4] \
|
|
__asm movss xmm2, [esi+(2*3+0)*4] \
|
|
__asm movhps xmm2, [esi+(2*3+1)*4]
|
|
|
|
#define MUL_3xN_3x3_INIT_ROW4 \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 0, 2, 3, 0 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 3, 0 ) \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 0, 2, 3, 0 )
|
|
|
|
#define MUL_3xN_3x3_ROW4( N, row ) \
|
|
__asm movlps xmm3, [edi+(row+0*N+0)*4] \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 1 ) \
|
|
__asm movlps xmm4, [edi+(row+1*N+0)*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 1 ) \
|
|
__asm movlps xmm5, [edi+(row+2*N+0)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 1 ) \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movaps [eax+(row*3+0)*4], xmm3 \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm movlps xmm3, [edi+(row+0*N+1)*4] \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm movlps xmm4, [edi+(row+1*N+1)*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm movlps xmm5, [edi+(row+2*N+1)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movaps [eax+(row*3+4)*4], xmm3 \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 1 ) \
|
|
__asm movlps xmm3, [edi+(row+0*N+2)*4] \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 1, 1, 1 ) \
|
|
__asm movlps xmm4, [edi+(row+1*N+2)*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 1, 1, 1 ) \
|
|
__asm movlps xmm5, [edi+(row+2*N+2)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 1, 1, 1 ) \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movaps [eax+(row*3+8)*4], xmm3
|
|
|
|
#define MUL_3xN_3x3_INIT_ROW4_ROW4 \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 ) \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
#define MUL_3xN_3x3_INIT_ROW4_ROW \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 1, 1, 2, 3 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 2, 3 ) \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 1, 1, 2, 3 )
|
|
|
|
#define MUL_3xN_3x3_ROW( N, row ) \
|
|
__asm movss xmm3, [edi+(row+0*N)*4] \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm movss xmm4, [edi+(row+1*N)*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm movss xmm5, [edi+(row+2*N)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm3, xmm0 \
|
|
__asm mulps xmm4, xmm1 \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm3, xmm4 \
|
|
__asm addps xmm3, xmm5 \
|
|
__asm movss [eax+(row*3+0)*4], xmm3 \
|
|
__asm movhps [eax+(row*3+1)*4], xmm3
|
|
|
|
MUL_3xN_3x3_INIT
|
|
MUL_3xN_3x3_INIT_ROW4
|
|
MUL_3xN_3x3_ROW4( 6, 0 )
|
|
MUL_3xN_3x3_INIT_ROW4_ROW
|
|
MUL_3xN_3x3_ROW( 6, 4 )
|
|
MUL_3xN_3x3_ROW( 6, 5 )
|
|
|
|
return;
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[k] * m2Ptr[l] + m1Ptr[2*k] * m2Ptr[2*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
case 4:
|
|
if ( !((k^6)|(l^4)) ) { // 4x6 * 4x4
|
|
|
|
#define MUL_4xN_4x4_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movaps xmm0, [esi] \
|
|
__asm movaps xmm1, [esi+16] \
|
|
__asm movaps xmm2, [esi+32] \
|
|
__asm movaps xmm3, [esi+48]
|
|
|
|
#define MUL_4xN_4x4_ROW( N, row ) \
|
|
__asm movss xmm7, [edi+(row+0*N)*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movss xmm6, [edi+(row+1*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+2*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+3*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movaps [eax+row*16], xmm7
|
|
|
|
MUL_4xN_4x4_INIT
|
|
MUL_4xN_4x4_ROW( 6, 0 )
|
|
MUL_4xN_4x4_ROW( 6, 1 )
|
|
MUL_4xN_4x4_ROW( 6, 2 )
|
|
MUL_4xN_4x4_ROW( 6, 3 )
|
|
MUL_4xN_4x4_ROW( 6, 4 )
|
|
MUL_4xN_4x4_ROW( 6, 5 )
|
|
|
|
return;
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[k] * m2Ptr[l] + m1Ptr[2*k] * m2Ptr[2*l] +
|
|
m1Ptr[3*k] * m2Ptr[3*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
case 5:
|
|
if ( !((k^6)|(l^5)) ) { // 5x6 * 5x5
|
|
|
|
#define MUL_5xN_5x5_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 2*4] \
|
|
__asm movlps xmm1, [esi+ 5*4] \
|
|
__asm movhps xmm1, [esi+ 7*4] \
|
|
__asm movlps xmm2, [esi+10*4] \
|
|
__asm movhps xmm2, [esi+12*4] \
|
|
__asm movlps xmm3, [esi+15*4] \
|
|
__asm movhps xmm3, [esi+17*4] \
|
|
__asm movlps xmm4, [esi+20*4] \
|
|
__asm movhps xmm4, [esi+22*4]
|
|
|
|
#define MUL_5xN_5x5_ROW( N, row ) \
|
|
__asm movss xmm6, [edi+(row+0*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm0 \
|
|
__asm fld dword ptr [edi+(row+0*N)*4] \
|
|
__asm fmul dword ptr [esi+ 4*4] \
|
|
__asm movss xmm5, [edi+(row+1*N)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm1 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm fld dword ptr [edi+(row+1*N)*4] \
|
|
__asm fmul dword ptr [esi+ 9*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm5, [edi+(row+2*N)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm2 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm fld dword ptr [edi+(row+2*N)*4] \
|
|
__asm fmul dword ptr [esi+14*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm5, [edi+(row+3*N)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm3 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm fld dword ptr [edi+(row+3*N)*4] \
|
|
__asm fmul dword ptr [esi+19*4] \
|
|
__asm faddp st(1),st \
|
|
__asm movss xmm5, [edi+(row+4*N)*4] \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm5, xmm4 \
|
|
__asm addps xmm6, xmm5 \
|
|
__asm fld dword ptr [edi+(row+4*N)*4] \
|
|
__asm fmul dword ptr [esi+24*4] \
|
|
__asm faddp st(1),st \
|
|
__asm fstp dword ptr [eax+(row*5+4)*4] \
|
|
__asm movlps [eax+(row*5+0)*4], xmm6 \
|
|
__asm movhps [eax+(row*5+2)*4], xmm6
|
|
|
|
MUL_5xN_5x5_INIT
|
|
MUL_5xN_5x5_ROW( 6, 0 )
|
|
MUL_5xN_5x5_ROW( 6, 1 )
|
|
MUL_5xN_5x5_ROW( 6, 2 )
|
|
MUL_5xN_5x5_ROW( 6, 3 )
|
|
MUL_5xN_5x5_ROW( 6, 4 )
|
|
MUL_5xN_5x5_ROW( 6, 5 )
|
|
|
|
return;
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[k] * m2Ptr[l] + m1Ptr[2*k] * m2Ptr[2*l] +
|
|
m1Ptr[3*k] * m2Ptr[3*l] + m1Ptr[4*k] * m2Ptr[4*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
case 6:
|
|
if ( !(l^6) ) {
|
|
switch( k ) {
|
|
case 1: { // 6x1 * 6x6
|
|
#define MUL_6xN_6x6_FIRST4COLUMNS_INIT \
|
|
__asm mov esi, m2Ptr \
|
|
__asm mov edi, m1Ptr \
|
|
__asm mov eax, dstPtr \
|
|
__asm movlps xmm0, [esi+ 0*4] \
|
|
__asm movhps xmm0, [esi+ 2*4] \
|
|
__asm movlps xmm1, [esi+ 6*4] \
|
|
__asm movhps xmm1, [esi+ 8*4] \
|
|
__asm movlps xmm2, [esi+12*4] \
|
|
__asm movhps xmm2, [esi+14*4] \
|
|
__asm movlps xmm3, [esi+18*4] \
|
|
__asm movhps xmm3, [esi+20*4] \
|
|
__asm movlps xmm4, [esi+24*4] \
|
|
__asm movhps xmm4, [esi+26*4] \
|
|
__asm movlps xmm5, [esi+30*4] \
|
|
__asm movhps xmm5, [esi+32*4]
|
|
|
|
#define MUL_6xN_6x6_FIRST4COLUMNS_ROW( N, row ) \
|
|
__asm movss xmm7, [edi+(row+0*N)*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movss xmm6, [edi+(row+1*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+2*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+3*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+4*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(row+5*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps [eax+(row*6+0)*4], xmm7 \
|
|
__asm movhps [eax+(row*6+2)*4], xmm7
|
|
|
|
#define MUL_6xN_6x6_LAST2COLUMNS_INIT \
|
|
__asm movlps xmm0, [esi+ 4*4] \
|
|
__asm movlps xmm1, [esi+10*4] \
|
|
__asm shufps xmm0, xmm0, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm1, xmm1, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm movlps xmm2, [esi+16*4] \
|
|
__asm movlps xmm3, [esi+22*4] \
|
|
__asm shufps xmm2, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm3, xmm3, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm movlps xmm4, [esi+28*4] \
|
|
__asm movlps xmm5, [esi+34*4] \
|
|
__asm shufps xmm4, xmm4, R_SHUFFLEPS( 0, 1, 0, 1 ) \
|
|
__asm shufps xmm5, xmm5, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
|
|
#define MUL_6xN_6x6_LAST2COLUMNS_ROW2( N, row ) \
|
|
__asm movlps xmm7, [edi+(row*2+0*N)*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movlps xmm6, [edi+(row*2+1*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps xmm6, [edi+(row*2+2*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps xmm6, [edi+(row*2+3*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps xmm6, [edi+(row*2+4*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps xmm6, [edi+(row*2+5*N)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 1, 1 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps [eax+(row*12+ 4)*4], xmm7 \
|
|
__asm movhps [eax+(row*12+10)*4], xmm7
|
|
|
|
#define MUL_6xN_6x6_LAST2COLUMNS_ROW( N, row ) \
|
|
__asm movss xmm7, [edi+(1*N-1)*4] \
|
|
__asm shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm7, xmm0 \
|
|
__asm movss xmm6, [edi+(2*N-1)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm1 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(3*N-1)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm2 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(4*N-1)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm3 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(5*N-1)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm4 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movss xmm6, [edi+(6*N-1)*4] \
|
|
__asm shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 ) \
|
|
__asm mulps xmm6, xmm5 \
|
|
__asm addps xmm7, xmm6 \
|
|
__asm movlps [eax+(row*6+4)*4], xmm7
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 1, 0 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW( 1, 0 )
|
|
|
|
return;
|
|
}
|
|
case 2: { // 6x2 * 6x6
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 2, 0 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 2, 1 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 2, 0 )
|
|
|
|
return;
|
|
}
|
|
case 3: { // 6x3 * 6x6
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 3, 0 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 3, 1 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 3, 2 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 3, 0 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW( 3, 2 )
|
|
|
|
return;
|
|
}
|
|
case 4: { // 6x4 * 6x6
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 4, 0 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 4, 1 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 4, 2 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 4, 3 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 4, 0 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 4, 1 )
|
|
|
|
return;
|
|
}
|
|
case 5: { // 6x5 * 6x6
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 5, 0 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 5, 1 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 5, 2 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 5, 3 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 5, 4 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 5, 0 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 5, 1 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW( 5, 4 )
|
|
|
|
return;
|
|
}
|
|
case 6: { // 6x6 * 6x6
|
|
|
|
MUL_6xN_6x6_FIRST4COLUMNS_INIT
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 0 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 1 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 2 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 3 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 4 )
|
|
MUL_6xN_6x6_FIRST4COLUMNS_ROW( 6, 5 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_INIT
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 6, 0 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 6, 1 )
|
|
MUL_6xN_6x6_LAST2COLUMNS_ROW2( 6, 2 )
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
for ( i = 0; i < k; i++ ) {
|
|
m2Ptr = m2.ToFloatPtr();
|
|
for ( j = 0; j < l; j++ ) {
|
|
*dstPtr++ = m1Ptr[0] * m2Ptr[0] + m1Ptr[k] * m2Ptr[l] + m1Ptr[2*k] * m2Ptr[2*l] +
|
|
m1Ptr[3*k] * m2Ptr[3*l] + m1Ptr[4*k] * m2Ptr[4*l] + m1Ptr[5*k] * m2Ptr[5*l];
|
|
m2Ptr++;
|
|
}
|
|
m1Ptr++;
|
|
}
|
|
break;
|
|
default:
|
|
for ( i = 0; i < k; i++ ) {
|
|
for ( j = 0; j < l; j++ ) {
|
|
m1Ptr = m1.ToFloatPtr() + i;
|
|
m2Ptr = m2.ToFloatPtr() + j;
|
|
sum = m1Ptr[0] * m2Ptr[0];
|
|
for ( n = 1; n < m1.GetNumRows(); n++ ) {
|
|
m1Ptr += k;
|
|
m2Ptr += l;
|
|
sum += m1Ptr[0] * m2Ptr[0];
|
|
}
|
|
*dstPtr++ = sum;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_LowerTriangularSolve
|
|
|
|
solves x in Lx = b for the n * n sub-matrix of L
|
|
if skip > 0 the first skip elements of x are assumed to be valid already
|
|
L has to be a lower triangular matrix with (implicit) ones on the diagonal
|
|
x == b is allowed
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_LowerTriangularSolve( const idMatX &L, float *x, const float *b, const int n, int skip ) {
|
|
int nc;
|
|
const float *lptr;
|
|
|
|
if ( skip >= n ) {
|
|
return;
|
|
}
|
|
|
|
lptr = L.ToFloatPtr();
|
|
nc = L.GetNumColumns();
|
|
|
|
// unrolled cases for n < 8
|
|
if ( n < 8 ) {
|
|
#define NSKIP( n, s ) ((n<<3)|(s&7))
|
|
switch( NSKIP( n, skip ) ) {
|
|
case NSKIP( 1, 0 ): x[0] = b[0];
|
|
return;
|
|
case NSKIP( 2, 0 ): x[0] = b[0];
|
|
case NSKIP( 2, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
return;
|
|
case NSKIP( 3, 0 ): x[0] = b[0];
|
|
case NSKIP( 3, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case NSKIP( 3, 2 ): x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
return;
|
|
case NSKIP( 4, 0 ): x[0] = b[0];
|
|
case NSKIP( 4, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case NSKIP( 4, 2 ): x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
case NSKIP( 4, 3 ): x[3] = b[3] - lptr[3*nc+0] * x[0] - lptr[3*nc+1] * x[1] - lptr[3*nc+2] * x[2];
|
|
return;
|
|
case NSKIP( 5, 0 ): x[0] = b[0];
|
|
case NSKIP( 5, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case NSKIP( 5, 2 ): x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
case NSKIP( 5, 3 ): x[3] = b[3] - lptr[3*nc+0] * x[0] - lptr[3*nc+1] * x[1] - lptr[3*nc+2] * x[2];
|
|
case NSKIP( 5, 4 ): x[4] = b[4] - lptr[4*nc+0] * x[0] - lptr[4*nc+1] * x[1] - lptr[4*nc+2] * x[2] - lptr[4*nc+3] * x[3];
|
|
return;
|
|
case NSKIP( 6, 0 ): x[0] = b[0];
|
|
case NSKIP( 6, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case NSKIP( 6, 2 ): x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
case NSKIP( 6, 3 ): x[3] = b[3] - lptr[3*nc+0] * x[0] - lptr[3*nc+1] * x[1] - lptr[3*nc+2] * x[2];
|
|
case NSKIP( 6, 4 ): x[4] = b[4] - lptr[4*nc+0] * x[0] - lptr[4*nc+1] * x[1] - lptr[4*nc+2] * x[2] - lptr[4*nc+3] * x[3];
|
|
case NSKIP( 6, 5 ): x[5] = b[5] - lptr[5*nc+0] * x[0] - lptr[5*nc+1] * x[1] - lptr[5*nc+2] * x[2] - lptr[5*nc+3] * x[3] - lptr[5*nc+4] * x[4];
|
|
return;
|
|
case NSKIP( 7, 0 ): x[0] = b[0];
|
|
case NSKIP( 7, 1 ): x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case NSKIP( 7, 2 ): x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
case NSKIP( 7, 3 ): x[3] = b[3] - lptr[3*nc+0] * x[0] - lptr[3*nc+1] * x[1] - lptr[3*nc+2] * x[2];
|
|
case NSKIP( 7, 4 ): x[4] = b[4] - lptr[4*nc+0] * x[0] - lptr[4*nc+1] * x[1] - lptr[4*nc+2] * x[2] - lptr[4*nc+3] * x[3];
|
|
case NSKIP( 7, 5 ): x[5] = b[5] - lptr[5*nc+0] * x[0] - lptr[5*nc+1] * x[1] - lptr[5*nc+2] * x[2] - lptr[5*nc+3] * x[3] - lptr[5*nc+4] * x[4];
|
|
case NSKIP( 7, 6 ): x[6] = b[6] - lptr[6*nc+0] * x[0] - lptr[6*nc+1] * x[1] - lptr[6*nc+2] * x[2] - lptr[6*nc+3] * x[3] - lptr[6*nc+4] * x[4] - lptr[6*nc+5] * x[5];
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// process first 4 rows
|
|
switch( skip ) {
|
|
case 0: x[0] = b[0];
|
|
case 1: x[1] = b[1] - lptr[1*nc+0] * x[0];
|
|
case 2: x[2] = b[2] - lptr[2*nc+0] * x[0] - lptr[2*nc+1] * x[1];
|
|
case 3: x[3] = b[3] - lptr[3*nc+0] * x[0] - lptr[3*nc+1] * x[1] - lptr[3*nc+2] * x[2];
|
|
skip = 4;
|
|
}
|
|
|
|
lptr = L[skip];
|
|
|
|
// this code assumes n > 4
|
|
__asm {
|
|
push ebx
|
|
mov eax, skip // eax = i
|
|
shl eax, 2 // eax = i*4
|
|
mov edx, n // edx = n
|
|
shl edx, 2 // edx = n*4
|
|
mov esi, x // esi = x
|
|
mov edi, lptr // edi = lptr
|
|
add esi, eax
|
|
add edi, eax
|
|
mov ebx, b // ebx = b
|
|
|
|
// check for aligned memory
|
|
mov ecx, nc
|
|
shl ecx, 2
|
|
or ecx, esi
|
|
or ecx, edi
|
|
and ecx, 15
|
|
jnz loopurow
|
|
|
|
// aligned
|
|
looprow:
|
|
mov ecx, eax
|
|
neg ecx
|
|
movaps xmm0, [esi+ecx]
|
|
mulps xmm0, [edi+ecx]
|
|
add ecx, 12*4
|
|
jg donedot8
|
|
dot8:
|
|
movaps xmm1, [esi+ecx-(8*4)]
|
|
mulps xmm1, [edi+ecx-(8*4)]
|
|
addps xmm0, xmm1
|
|
movaps xmm3, [esi+ecx-(4*4)]
|
|
mulps xmm3, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm3
|
|
add ecx, 8*4
|
|
jle dot8
|
|
donedot8:
|
|
sub ecx, 4*4
|
|
jg donedot4
|
|
//dot4:
|
|
movaps xmm1, [esi+ecx-(4*4)]
|
|
mulps xmm1, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm1
|
|
add ecx, 4*4
|
|
donedot4:
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
sub ecx, 4*4
|
|
jz dot0
|
|
add ecx, 4
|
|
jz dot1
|
|
add ecx, 4
|
|
jz dot2
|
|
//dot3:
|
|
movss xmm1, [esi-(3*4)]
|
|
mulss xmm1, [edi-(3*4)]
|
|
addss xmm0, xmm1
|
|
dot2:
|
|
movss xmm3, [esi-(2*4)]
|
|
mulss xmm3, [edi-(2*4)]
|
|
addss xmm0, xmm3
|
|
dot1:
|
|
movss xmm5, [esi-(1*4)]
|
|
mulss xmm5, [edi-(1*4)]
|
|
addss xmm0, xmm5
|
|
dot0:
|
|
movss xmm1, [ebx+eax]
|
|
subss xmm1, xmm0
|
|
movss [esi], xmm1
|
|
add eax, 4
|
|
cmp eax, edx
|
|
jge done
|
|
add esi, 4
|
|
mov ecx, nc
|
|
shl ecx, 2
|
|
add edi, ecx
|
|
add edi, 4
|
|
jmp looprow
|
|
|
|
// unaligned
|
|
loopurow:
|
|
mov ecx, eax
|
|
neg ecx
|
|
movups xmm0, [esi+ecx]
|
|
movups xmm1, [edi+ecx]
|
|
mulps xmm0, xmm1
|
|
add ecx, 12*4
|
|
jg doneudot8
|
|
udot8:
|
|
movups xmm1, [esi+ecx-(8*4)]
|
|
movups xmm2, [edi+ecx-(8*4)]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
movups xmm3, [esi+ecx-(4*4)]
|
|
movups xmm4, [edi+ecx-(4*4)]
|
|
mulps xmm3, xmm4
|
|
addps xmm0, xmm3
|
|
add ecx, 8*4
|
|
jle udot8
|
|
doneudot8:
|
|
sub ecx, 4*4
|
|
jg doneudot4
|
|
//udot4:
|
|
movups xmm1, [esi+ecx-(4*4)]
|
|
movups xmm2, [edi+ecx-(4*4)]
|
|
mulps xmm1, xmm2
|
|
addps xmm0, xmm1
|
|
add ecx, 4*4
|
|
doneudot4:
|
|
movhlps xmm1, xmm0
|
|
addps xmm0, xmm1
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm1
|
|
sub ecx, 4*4
|
|
jz udot0
|
|
add ecx, 4
|
|
jz udot1
|
|
add ecx, 4
|
|
jz udot2
|
|
//udot3:
|
|
movss xmm1, [esi-(3*4)]
|
|
movss xmm2, [edi-(3*4)]
|
|
mulss xmm1, xmm2
|
|
addss xmm0, xmm1
|
|
udot2:
|
|
movss xmm3, [esi-(2*4)]
|
|
movss xmm4, [edi-(2*4)]
|
|
mulss xmm3, xmm4
|
|
addss xmm0, xmm3
|
|
udot1:
|
|
movss xmm5, [esi-(1*4)]
|
|
movss xmm6, [edi-(1*4)]
|
|
mulss xmm5, xmm6
|
|
addss xmm0, xmm5
|
|
udot0:
|
|
movss xmm1, [ebx+eax]
|
|
subss xmm1, xmm0
|
|
movss [esi], xmm1
|
|
add eax, 4
|
|
cmp eax, edx
|
|
jge done
|
|
add esi, 4
|
|
mov ecx, nc
|
|
shl ecx, 2
|
|
add edi, ecx
|
|
add edi, 4
|
|
jmp loopurow
|
|
done:
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_LowerTriangularSolveTranspose
|
|
|
|
solves x in L'x = b for the n * n sub-matrix of L
|
|
L has to be a lower triangular matrix with (implicit) ones on the diagonal
|
|
x == b is allowed
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MatX_LowerTriangularSolveTranspose( const idMatX &L, float *x, const float *b, const int n ) {
|
|
int nc;
|
|
const float *lptr;
|
|
|
|
lptr = L.ToFloatPtr();
|
|
nc = L.GetNumColumns();
|
|
|
|
// unrolled cases for n < 8
|
|
if ( n < 8 ) {
|
|
switch( n ) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
x[0] = b[0];
|
|
return;
|
|
case 2:
|
|
x[1] = b[1];
|
|
x[0] = b[0] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
case 3:
|
|
x[2] = b[2];
|
|
x[1] = b[1] - lptr[2*nc+1] * x[2];
|
|
x[0] = b[0] - lptr[2*nc+0] * x[2] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
case 4:
|
|
x[3] = b[3];
|
|
x[2] = b[2] - lptr[3*nc+2] * x[3];
|
|
x[1] = b[1] - lptr[3*nc+1] * x[3] - lptr[2*nc+1] * x[2];
|
|
x[0] = b[0] - lptr[3*nc+0] * x[3] - lptr[2*nc+0] * x[2] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
case 5:
|
|
x[4] = b[4];
|
|
x[3] = b[3] - lptr[4*nc+3] * x[4];
|
|
x[2] = b[2] - lptr[4*nc+2] * x[4] - lptr[3*nc+2] * x[3];
|
|
x[1] = b[1] - lptr[4*nc+1] * x[4] - lptr[3*nc+1] * x[3] - lptr[2*nc+1] * x[2];
|
|
x[0] = b[0] - lptr[4*nc+0] * x[4] - lptr[3*nc+0] * x[3] - lptr[2*nc+0] * x[2] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
case 6:
|
|
x[5] = b[5];
|
|
x[4] = b[4] - lptr[5*nc+4] * x[5];
|
|
x[3] = b[3] - lptr[5*nc+3] * x[5] - lptr[4*nc+3] * x[4];
|
|
x[2] = b[2] - lptr[5*nc+2] * x[5] - lptr[4*nc+2] * x[4] - lptr[3*nc+2] * x[3];
|
|
x[1] = b[1] - lptr[5*nc+1] * x[5] - lptr[4*nc+1] * x[4] - lptr[3*nc+1] * x[3] - lptr[2*nc+1] * x[2];
|
|
x[0] = b[0] - lptr[5*nc+0] * x[5] - lptr[4*nc+0] * x[4] - lptr[3*nc+0] * x[3] - lptr[2*nc+0] * x[2] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
case 7:
|
|
x[6] = b[6];
|
|
x[5] = b[5] - lptr[6*nc+5] * x[6];
|
|
x[4] = b[4] - lptr[6*nc+4] * x[6] - lptr[5*nc+4] * x[5];
|
|
x[3] = b[3] - lptr[6*nc+3] * x[6] - lptr[5*nc+3] * x[5] - lptr[4*nc+3] * x[4];
|
|
x[2] = b[2] - lptr[6*nc+2] * x[6] - lptr[5*nc+2] * x[5] - lptr[4*nc+2] * x[4] - lptr[3*nc+2] * x[3];
|
|
x[1] = b[1] - lptr[6*nc+1] * x[6] - lptr[5*nc+1] * x[5] - lptr[4*nc+1] * x[4] - lptr[3*nc+1] * x[3] - lptr[2*nc+1] * x[2];
|
|
x[0] = b[0] - lptr[6*nc+0] * x[6] - lptr[5*nc+0] * x[5] - lptr[4*nc+0] * x[4] - lptr[3*nc+0] * x[3] - lptr[2*nc+0] * x[2] - lptr[1*nc+0] * x[1];
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
#if 1
|
|
|
|
int i, j, m;
|
|
float *xptr;
|
|
double s0;
|
|
|
|
// if the number of columns is not a multiple of 2 we're screwed for alignment.
|
|
// however, if the number of columns is a multiple of 2 but the number of to be
|
|
// processed rows is not a multiple of 2 we can still run 8 byte aligned
|
|
m = n;
|
|
if ( m & 1 ) {
|
|
|
|
m--;
|
|
x[m] = b[m];
|
|
|
|
lptr = L.ToFloatPtr() + m * nc + m - 4;
|
|
xptr = x + m;
|
|
__asm {
|
|
push ebx
|
|
mov eax, m // eax = i
|
|
mov esi, xptr // esi = xptr
|
|
mov edi, lptr // edi = lptr
|
|
mov ebx, b // ebx = b
|
|
mov edx, nc // edx = nc*sizeof(float)
|
|
shl edx, 2
|
|
process4rows_1:
|
|
movlps xmm0, [ebx+eax*4-16] // load b[i-2], b[i-1]
|
|
movhps xmm0, [ebx+eax*4-8] // load b[i-4], b[i-3]
|
|
xor ecx, ecx
|
|
sub eax, m
|
|
neg eax
|
|
jz done4x4_1
|
|
process4x4_1: // process 4x4 blocks
|
|
movlps xmm2, [edi+0]
|
|
movhps xmm2, [edi+8]
|
|
add edi, edx
|
|
movss xmm1, [esi+4*ecx+0]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm3, [edi+0]
|
|
movhps xmm3, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm2
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm4, [edi+0]
|
|
movhps xmm4, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm3
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+8]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm5, [edi+0]
|
|
movhps xmm5, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm4
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+12]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
add ecx, 4
|
|
cmp ecx, eax
|
|
mulps xmm1, xmm5
|
|
subps xmm0, xmm1
|
|
jl process4x4_1
|
|
done4x4_1: // process left over of the 4 rows
|
|
movlps xmm2, [edi+0]
|
|
movhps xmm2, [edi+8]
|
|
movss xmm1, [esi+4*ecx]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm1, xmm2
|
|
subps xmm0, xmm1
|
|
imul ecx, edx
|
|
sub edi, ecx
|
|
neg eax
|
|
|
|
add eax, m
|
|
sub eax, 4
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movaps xmm2, xmm0
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 2, 2, 2 )
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 3, 3, 3 )
|
|
sub edi, edx
|
|
movss [esi-4], xmm3 // xptr[-1] = s3
|
|
movss xmm4, xmm3
|
|
movss xmm5, xmm3
|
|
mulss xmm3, [edi+8] // lptr[-1*nc+2] * s3
|
|
mulss xmm4, [edi+4] // lptr[-1*nc+1] * s3
|
|
mulss xmm5, [edi+0] // lptr[-1*nc+0] * s3
|
|
subss xmm2, xmm3
|
|
movss [esi-8], xmm2 // xptr[-2] = s2
|
|
movss xmm6, xmm2
|
|
sub edi, edx
|
|
subss xmm0, xmm5
|
|
subss xmm1, xmm4
|
|
mulss xmm2, [edi+4] // lptr[-2*nc+1] * s2
|
|
mulss xmm6, [edi+0] // lptr[-2*nc+0] * s2
|
|
subss xmm1, xmm2
|
|
movss [esi-12], xmm1 // xptr[-3] = s1
|
|
subss xmm0, xmm6
|
|
sub edi, edx
|
|
cmp eax, 4
|
|
mulss xmm1, [edi+0] // lptr[-3*nc+0] * s1
|
|
subss xmm0, xmm1
|
|
movss [esi-16], xmm0 // xptr[-4] = s0
|
|
jl done4rows_1
|
|
sub edi, edx
|
|
sub edi, 16
|
|
sub esi, 16
|
|
jmp process4rows_1
|
|
done4rows_1:
|
|
pop ebx
|
|
}
|
|
|
|
} else {
|
|
|
|
lptr = L.ToFloatPtr() + m * nc + m - 4;
|
|
xptr = x + m;
|
|
__asm {
|
|
push ebx
|
|
mov eax, m // eax = i
|
|
mov esi, xptr // esi = xptr
|
|
mov edi, lptr // edi = lptr
|
|
mov ebx, b // ebx = b
|
|
mov edx, nc // edx = nc*sizeof(float)
|
|
shl edx, 2
|
|
process4rows:
|
|
movlps xmm0, [ebx+eax*4-16] // load b[i-2], b[i-1]
|
|
movhps xmm0, [ebx+eax*4-8] // load b[i-4], b[i-3]
|
|
sub eax, m
|
|
jz done4x4
|
|
neg eax
|
|
xor ecx, ecx
|
|
process4x4: // process 4x4 blocks
|
|
movlps xmm2, [edi+0]
|
|
movhps xmm2, [edi+8]
|
|
add edi, edx
|
|
movss xmm1, [esi+4*ecx+0]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm3, [edi+0]
|
|
movhps xmm3, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm2
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm4, [edi+0]
|
|
movhps xmm4, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm3
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+8]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps xmm5, [edi+0]
|
|
movhps xmm5, [edi+8]
|
|
add edi, edx
|
|
mulps xmm1, xmm4
|
|
subps xmm0, xmm1
|
|
movss xmm1, [esi+4*ecx+12]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
add ecx, 4
|
|
cmp ecx, eax
|
|
mulps xmm1, xmm5
|
|
subps xmm0, xmm1
|
|
jl process4x4
|
|
imul ecx, edx
|
|
sub edi, ecx
|
|
neg eax
|
|
done4x4: // process left over of the 4 rows
|
|
add eax, m
|
|
sub eax, 4
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
movaps xmm2, xmm0
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 2, 2, 2 )
|
|
movaps xmm3, xmm0
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 3, 3, 3 )
|
|
sub edi, edx
|
|
movss [esi-4], xmm3 // xptr[-1] = s3
|
|
movss xmm4, xmm3
|
|
movss xmm5, xmm3
|
|
mulss xmm3, [edi+8] // lptr[-1*nc+2] * s3
|
|
mulss xmm4, [edi+4] // lptr[-1*nc+1] * s3
|
|
mulss xmm5, [edi+0] // lptr[-1*nc+0] * s3
|
|
subss xmm2, xmm3
|
|
movss [esi-8], xmm2 // xptr[-2] = s2
|
|
movss xmm6, xmm2
|
|
sub edi, edx
|
|
subss xmm0, xmm5
|
|
subss xmm1, xmm4
|
|
mulss xmm2, [edi+4] // lptr[-2*nc+1] * s2
|
|
mulss xmm6, [edi+0] // lptr[-2*nc+0] * s2
|
|
subss xmm1, xmm2
|
|
movss [esi-12], xmm1 // xptr[-3] = s1
|
|
subss xmm0, xmm6
|
|
sub edi, edx
|
|
cmp eax, 4
|
|
mulss xmm1, [edi+0] // lptr[-3*nc+0] * s1
|
|
subss xmm0, xmm1
|
|
movss [esi-16], xmm0 // xptr[-4] = s0
|
|
jl done4rows
|
|
sub edi, edx
|
|
sub edi, 16
|
|
sub esi, 16
|
|
jmp process4rows
|
|
done4rows:
|
|
pop ebx
|
|
}
|
|
}
|
|
|
|
// process left over rows
|
|
for ( i = (m&3)-1; i >= 0; i-- ) {
|
|
s0 = b[i];
|
|
lptr = L[0] + i;
|
|
for ( j = i + 1; j < n; j++ ) {
|
|
s0 -= lptr[j*nc] * x[j];
|
|
}
|
|
x[i] = s0;
|
|
}
|
|
|
|
#else
|
|
|
|
int i, j, m;
|
|
double s0, s1, s2, s3, t;
|
|
const float *lptr2;
|
|
float *xptr, *xptr2;
|
|
|
|
m = n;
|
|
if ( m & 1 ) {
|
|
|
|
m--;
|
|
x[m] = b[m];
|
|
|
|
lptr = L.ToFloatPtr() + m * nc + m - 4;
|
|
xptr = x + m;
|
|
// process 4 rows at a time
|
|
for ( i = m; i >= 4; i -= 4 ) {
|
|
s0 = b[i-4];
|
|
s1 = b[i-3];
|
|
s2 = b[i-2];
|
|
s3 = b[i-1];
|
|
// process 4x4 blocks
|
|
xptr2 = xptr; // x + i;
|
|
lptr2 = lptr; // ptr = L[i] + i - 4;
|
|
for ( j = 0; j < m-i; j += 4 ) {
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
}
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
// process left over of the 4 rows
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s3;
|
|
s1 -= lptr[1] * s3;
|
|
s2 -= lptr[2] * s3;
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s2;
|
|
s1 -= lptr[1] * s2;
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s1;
|
|
lptr -= nc;
|
|
// store result
|
|
xptr[-4] = s0;
|
|
xptr[-3] = s1;
|
|
xptr[-2] = s2;
|
|
xptr[-1] = s3;
|
|
// update pointers for next four rows
|
|
lptr -= 4;
|
|
xptr -= 4;
|
|
}
|
|
|
|
} else {
|
|
|
|
lptr = L.ToFloatPtr() + m * nc + m - 4;
|
|
xptr = x + m;
|
|
// process 4 rows at a time
|
|
for ( i = m; i >= 4; i -= 4 ) {
|
|
s0 = b[i-4];
|
|
s1 = b[i-3];
|
|
s2 = b[i-2];
|
|
s3 = b[i-1];
|
|
// process 4x4 blocks
|
|
xptr2 = xptr; // x + i;
|
|
lptr2 = lptr; // ptr = L[i] + i - 4;
|
|
for ( j = 0; j < m-i; j += 4 ) {
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
t = xptr2[0];
|
|
s0 -= lptr2[0] * t;
|
|
s1 -= lptr2[1] * t;
|
|
s2 -= lptr2[2] * t;
|
|
s3 -= lptr2[3] * t;
|
|
lptr2 += nc;
|
|
xptr2++;
|
|
}
|
|
// process left over of the 4 rows
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s3;
|
|
s1 -= lptr[1] * s3;
|
|
s2 -= lptr[2] * s3;
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s2;
|
|
s1 -= lptr[1] * s2;
|
|
lptr -= nc;
|
|
s0 -= lptr[0] * s1;
|
|
lptr -= nc;
|
|
// store result
|
|
xptr[-4] = s0;
|
|
xptr[-3] = s1;
|
|
xptr[-2] = s2;
|
|
xptr[-1] = s3;
|
|
// update pointers for next four rows
|
|
lptr -= 4;
|
|
xptr -= 4;
|
|
}
|
|
}
|
|
// process left over rows
|
|
for ( i--; i >= 0; i-- ) {
|
|
s0 = b[i];
|
|
lptr = L[0] + i;
|
|
for ( j = i + 1; j < m; j++ ) {
|
|
s0 -= lptr[j*nc] * x[j];
|
|
}
|
|
x[i] = s0;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MatX_LDLTFactor
|
|
|
|
in-place factorization LDL' of the n * n sub-matrix of mat
|
|
the reciprocal of the diagonal elements are stored in invDiag
|
|
currently assumes the number of columns of mat is a multiple of 4
|
|
============
|
|
*/
|
|
bool VPCALL idSIMD_SSE::MatX_LDLTFactor( idMatX &mat, idVecX &invDiag, const int n ) {
|
|
#if 1
|
|
|
|
int j, nc;
|
|
float *v, *diag, *invDiagPtr, *mptr;
|
|
double s0, s1, s2, sum, d;
|
|
|
|
v = (float *) _alloca16( n * sizeof( float ) );
|
|
diag = (float *) _alloca16( n * sizeof( float ) );
|
|
invDiagPtr = invDiag.ToFloatPtr();
|
|
|
|
nc = mat.GetNumColumns();
|
|
|
|
assert( ( nc & 3 ) == 0 );
|
|
|
|
if ( n <= 0 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
|
|
sum = mptr[0];
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
diag[0] = sum;
|
|
invDiagPtr[0] = d = 1.0f / sum;
|
|
|
|
if ( n <= 1 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 1; j < n; j++ ) {
|
|
mptr[j*nc+0] = ( mptr[j*nc+0] ) * d;
|
|
}
|
|
|
|
mptr = mat[1];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
sum = mptr[1] - s0;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[1][1] = sum;
|
|
diag[1] = sum;
|
|
invDiagPtr[1] = d = 1.0f / sum;
|
|
|
|
if ( n <= 2 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 2; j < n; j++ ) {
|
|
mptr[j*nc+1] = ( mptr[j*nc+1] - v[0] * mptr[j*nc+0] ) * d;
|
|
}
|
|
|
|
mptr = mat[2];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
v[1] = diag[1] * mptr[1]; s1 = v[1] * mptr[1];
|
|
sum = mptr[2] - s0 - s1;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[2][2] = sum;
|
|
diag[2] = sum;
|
|
invDiagPtr[2] = d = 1.0f / sum;
|
|
|
|
if ( n <= 3 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 3; j < n; j++ ) {
|
|
mptr[j*nc+2] = ( mptr[j*nc+2] - v[0] * mptr[j*nc+0] - v[1] * mptr[j*nc+1] ) * d;
|
|
}
|
|
|
|
mptr = mat[3];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
v[1] = diag[1] * mptr[1]; s1 = v[1] * mptr[1];
|
|
v[2] = diag[2] * mptr[2]; s2 = v[2] * mptr[2];
|
|
sum = mptr[3] - s0 - s1 - s2;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[3][3] = sum;
|
|
diag[3] = sum;
|
|
invDiagPtr[3] = d = 1.0f / sum;
|
|
|
|
if ( n <= 4 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 4; j < n; j++ ) {
|
|
mptr[j*nc+3] = ( mptr[j*nc+3] - v[0] * mptr[j*nc+0] - v[1] * mptr[j*nc+1] - v[2] * mptr[j*nc+2] ) * d;
|
|
}
|
|
|
|
int ncf = nc * sizeof( float );
|
|
mptr = mat[0];
|
|
|
|
__asm {
|
|
xorps xmm2, xmm2
|
|
xorps xmm3, xmm3
|
|
xorps xmm4, xmm4
|
|
|
|
push ebx
|
|
mov ebx, 4
|
|
|
|
loopRow:
|
|
cmp ebx, n
|
|
jge done
|
|
|
|
mov ecx, ebx // esi = i
|
|
shl ecx, 2 // esi = i * 4
|
|
mov edx, diag // edx = diag
|
|
add edx, ecx // edx = &diag[i]
|
|
mov edi, ebx // edi = i
|
|
imul edi, ncf // edi = i * nc * sizeof( float )
|
|
add edi, mptr // edi = mat[i]
|
|
add edi, ecx // edi = &mat[i][i]
|
|
mov esi, v // ecx = v
|
|
add esi, ecx // ecx = &v[i]
|
|
mov eax, invDiagPtr // eax = invDiagPtr
|
|
add eax, ecx // eax = &invDiagPtr[i]
|
|
neg ecx
|
|
|
|
movaps xmm0, [edx+ecx]
|
|
mulps xmm0, [edi+ecx]
|
|
movaps [esi+ecx], xmm0
|
|
mulps xmm0, [edi+ecx]
|
|
add ecx, 12*4
|
|
jg doneDot8
|
|
dot8:
|
|
movaps xmm1, [edx+ecx-(8*4)]
|
|
mulps xmm1, [edi+ecx-(8*4)]
|
|
movaps [esi+ecx-(8*4)], xmm1
|
|
mulps xmm1, [edi+ecx-(8*4)]
|
|
addps xmm0, xmm1
|
|
movaps xmm2, [edx+ecx-(4*4)]
|
|
mulps xmm2, [edi+ecx-(4*4)]
|
|
movaps [esi+ecx-(4*4)], xmm2
|
|
mulps xmm2, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm2
|
|
add ecx, 8*4
|
|
jle dot8
|
|
doneDot8:
|
|
sub ecx, 4*4
|
|
jg doneDot4
|
|
movaps xmm1, [edx+ecx-(4*4)]
|
|
mulps xmm1, [edi+ecx-(4*4)]
|
|
movaps [esi+ecx-(4*4)], xmm1
|
|
mulps xmm1, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm1
|
|
add ecx, 4*4
|
|
doneDot4:
|
|
sub ecx, 2*4
|
|
jg doneDot2
|
|
movlps xmm3, [edx+ecx-(2*4)]
|
|
movlps xmm4, [edi+ecx-(2*4)]
|
|
mulps xmm3, xmm4
|
|
movlps [esi+ecx-(2*4)], xmm3
|
|
mulps xmm3, xmm4
|
|
addps xmm0, xmm3
|
|
add ecx, 2*4
|
|
doneDot2:
|
|
sub ecx, 1*4
|
|
jg doneDot1
|
|
movss xmm3, [edx+ecx-(1*4)]
|
|
movss xmm4, [edi+ecx-(1*4)]
|
|
mulss xmm3, xmm4
|
|
movss [esi+ecx-(1*4)], xmm3
|
|
mulss xmm3, xmm4
|
|
addss xmm0, xmm3
|
|
doneDot1:
|
|
movhlps xmm2, xmm0
|
|
addps xmm0, xmm2
|
|
movaps xmm2, xmm0
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm2
|
|
movss xmm1, [edi]
|
|
subss xmm1, xmm0
|
|
movss [edi], xmm1 // mptr[i] = sum;
|
|
movss [edx], xmm1 // diag[i] = sum;
|
|
|
|
// if ( sum == 0.0f ) return false;
|
|
movaps xmm2, xmm1
|
|
cmpeqss xmm2, SIMD_SP_zero
|
|
andps xmm2, SIMD_SP_tiny
|
|
orps xmm1, xmm2
|
|
|
|
rcpss xmm7, xmm1
|
|
mulss xmm1, xmm7
|
|
mulss xmm1, xmm7
|
|
addss xmm7, xmm7
|
|
subss xmm7, xmm1
|
|
movss [eax], xmm7 // invDiagPtr[i] = 1.0f / sum;
|
|
|
|
mov edx, n // edx = n
|
|
sub edx, ebx // edx = n - i
|
|
dec edx // edx = n - i - 1
|
|
jle doneSubRow // if ( i + 1 >= n ) return true;
|
|
|
|
mov eax, ebx // eax = i
|
|
shl eax, 2 // eax = i * 4
|
|
neg eax
|
|
|
|
loopSubRow:
|
|
add edi, ncf
|
|
mov ecx, eax
|
|
movaps xmm0, [esi+ecx]
|
|
mulps xmm0, [edi+ecx]
|
|
add ecx, 12*4
|
|
jg doneSubDot8
|
|
subDot8:
|
|
movaps xmm1, [esi+ecx-(8*4)]
|
|
mulps xmm1, [edi+ecx-(8*4)]
|
|
addps xmm0, xmm1
|
|
movaps xmm2, [esi+ecx-(4*4)]
|
|
mulps xmm2, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm2
|
|
add ecx, 8*4
|
|
jle subDot8
|
|
doneSubDot8:
|
|
sub ecx, 4*4
|
|
jg doneSubDot4
|
|
movaps xmm1, [esi+ecx-(4*4)]
|
|
mulps xmm1, [edi+ecx-(4*4)]
|
|
addps xmm0, xmm1
|
|
add ecx, 4*4
|
|
doneSubDot4:
|
|
sub ecx, 2*4
|
|
jg doneSubDot2
|
|
movlps xmm3, [esi+ecx-(2*4)]
|
|
movlps xmm4, [edi+ecx-(2*4)]
|
|
mulps xmm3, xmm4
|
|
addps xmm0, xmm3
|
|
add ecx, 2*4
|
|
doneSubDot2:
|
|
sub ecx, 1*4
|
|
jg doneSubDot1
|
|
movss xmm3, [esi+ecx-(1*4)]
|
|
movss xmm4, [edi+ecx-(1*4)]
|
|
mulss xmm3, xmm4
|
|
addss xmm0, xmm3
|
|
doneSubDot1:
|
|
movhlps xmm2, xmm0
|
|
addps xmm0, xmm2
|
|
movaps xmm2, xmm0
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 0, 0, 0 )
|
|
addss xmm0, xmm2
|
|
movss xmm1, [edi]
|
|
subss xmm1, xmm0
|
|
mulss xmm1, xmm7
|
|
movss [edi], xmm1
|
|
dec edx
|
|
jg loopSubRow
|
|
doneSubRow:
|
|
inc ebx
|
|
jmp loopRow
|
|
done:
|
|
pop ebx
|
|
}
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
int i, j, k, nc;
|
|
float *v, *diag, *mptr;
|
|
double s0, s1, s2, s3, sum, d;
|
|
|
|
v = (float *) _alloca16( n * sizeof( float ) );
|
|
diag = (float *) _alloca16( n * sizeof( float ) );
|
|
|
|
nc = mat.GetNumColumns();
|
|
|
|
if ( n <= 0 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
|
|
sum = mptr[0];
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
diag[0] = sum;
|
|
invDiag[0] = d = 1.0f / sum;
|
|
|
|
if ( n <= 1 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 1; j < n; j++ ) {
|
|
mptr[j*nc+0] = ( mptr[j*nc+0] ) * d;
|
|
}
|
|
|
|
mptr = mat[1];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
sum = mptr[1] - s0;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[1][1] = sum;
|
|
diag[1] = sum;
|
|
invDiag[1] = d = 1.0f / sum;
|
|
|
|
if ( n <= 2 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 2; j < n; j++ ) {
|
|
mptr[j*nc+1] = ( mptr[j*nc+1] - v[0] * mptr[j*nc+0] ) * d;
|
|
}
|
|
|
|
mptr = mat[2];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
v[1] = diag[1] * mptr[1]; s1 = v[1] * mptr[1];
|
|
sum = mptr[2] - s0 - s1;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[2][2] = sum;
|
|
diag[2] = sum;
|
|
invDiag[2] = d = 1.0f / sum;
|
|
|
|
if ( n <= 3 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 3; j < n; j++ ) {
|
|
mptr[j*nc+2] = ( mptr[j*nc+2] - v[0] * mptr[j*nc+0] - v[1] * mptr[j*nc+1] ) * d;
|
|
}
|
|
|
|
mptr = mat[3];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
v[1] = diag[1] * mptr[1]; s1 = v[1] * mptr[1];
|
|
v[2] = diag[2] * mptr[2]; s2 = v[2] * mptr[2];
|
|
sum = mptr[3] - s0 - s1 - s2;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[3][3] = sum;
|
|
diag[3] = sum;
|
|
invDiag[3] = d = 1.0f / sum;
|
|
|
|
if ( n <= 4 ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[0];
|
|
for ( j = 4; j < n; j++ ) {
|
|
mptr[j*nc+3] = ( mptr[j*nc+3] - v[0] * mptr[j*nc+0] - v[1] * mptr[j*nc+1] - v[2] * mptr[j*nc+2] ) * d;
|
|
}
|
|
|
|
for ( i = 4; i < n; i++ ) {
|
|
|
|
mptr = mat[i];
|
|
|
|
v[0] = diag[0] * mptr[0]; s0 = v[0] * mptr[0];
|
|
v[1] = diag[1] * mptr[1]; s1 = v[1] * mptr[1];
|
|
v[2] = diag[2] * mptr[2]; s2 = v[2] * mptr[2];
|
|
v[3] = diag[3] * mptr[3]; s3 = v[3] * mptr[3];
|
|
for ( k = 4; k < i-3; k += 4 ) {
|
|
v[k+0] = diag[k+0] * mptr[k+0]; s0 += v[k+0] * mptr[k+0];
|
|
v[k+1] = diag[k+1] * mptr[k+1]; s1 += v[k+1] * mptr[k+1];
|
|
v[k+2] = diag[k+2] * mptr[k+2]; s2 += v[k+2] * mptr[k+2];
|
|
v[k+3] = diag[k+3] * mptr[k+3]; s3 += v[k+3] * mptr[k+3];
|
|
}
|
|
switch( i - k ) {
|
|
case 3: v[k+2] = diag[k+2] * mptr[k+2]; s0 += v[k+2] * mptr[k+2];
|
|
case 2: v[k+1] = diag[k+1] * mptr[k+1]; s1 += v[k+1] * mptr[k+1];
|
|
case 1: v[k+0] = diag[k+0] * mptr[k+0]; s2 += v[k+0] * mptr[k+0];
|
|
}
|
|
sum = s3;
|
|
sum += s2;
|
|
sum += s1;
|
|
sum += s0;
|
|
sum = mptr[i] - sum;
|
|
|
|
if ( sum == 0.0f ) {
|
|
return false;
|
|
}
|
|
|
|
mat[i][i] = sum;
|
|
diag[i] = sum;
|
|
invDiag[i] = d = 1.0f / sum;
|
|
|
|
if ( i + 1 >= n ) {
|
|
return true;
|
|
}
|
|
|
|
mptr = mat[i+1];
|
|
for ( j = i+1; j < n; j++ ) {
|
|
s0 = mptr[0] * v[0];
|
|
s1 = mptr[1] * v[1];
|
|
s2 = mptr[2] * v[2];
|
|
s3 = mptr[3] * v[3];
|
|
for ( k = 4; k < i-7; k += 8 ) {
|
|
s0 += mptr[k+0] * v[k+0];
|
|
s1 += mptr[k+1] * v[k+1];
|
|
s2 += mptr[k+2] * v[k+2];
|
|
s3 += mptr[k+3] * v[k+3];
|
|
s0 += mptr[k+4] * v[k+4];
|
|
s1 += mptr[k+5] * v[k+5];
|
|
s2 += mptr[k+6] * v[k+6];
|
|
s3 += mptr[k+7] * v[k+7];
|
|
}
|
|
switch( i - k ) {
|
|
case 7: s0 += mptr[k+6] * v[k+6];
|
|
case 6: s1 += mptr[k+5] * v[k+5];
|
|
case 5: s2 += mptr[k+4] * v[k+4];
|
|
case 4: s3 += mptr[k+3] * v[k+3];
|
|
case 3: s0 += mptr[k+2] * v[k+2];
|
|
case 2: s1 += mptr[k+1] * v[k+1];
|
|
case 1: s2 += mptr[k+0] * v[k+0];
|
|
}
|
|
sum = s3;
|
|
sum += s2;
|
|
sum += s1;
|
|
sum += s0;
|
|
mptr[i] = ( mptr[i] - sum ) * d;
|
|
mptr += nc;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::BlendJoints
|
|
============
|
|
*/
|
|
#define REFINE_BLENDJOINTS_RECIPROCAL
|
|
|
|
void VPCALL idSIMD_SSE::BlendJoints( idJointQuat *joints, const idJointQuat *blendJoints, const float lerp, const int *index, const int numJoints ) {
|
|
int i;
|
|
|
|
if ( lerp <= 0.0f ) {
|
|
return;
|
|
} else if ( lerp >= 1.0f ) {
|
|
for ( i = 0; i < numJoints; i++ ) {
|
|
int j = index[i];
|
|
joints[j] = blendJoints[j];
|
|
}
|
|
return;
|
|
}
|
|
|
|
for ( i = 0; i <= numJoints - 4; i += 4 ) {
|
|
ALIGN16( float jointVert0[4] );
|
|
ALIGN16( float jointVert1[4] );
|
|
ALIGN16( float jointVert2[4] );
|
|
ALIGN16( float blendVert0[4] );
|
|
ALIGN16( float blendVert1[4] );
|
|
ALIGN16( float blendVert2[4] );
|
|
ALIGN16( float jointQuat0[4] );
|
|
ALIGN16( float jointQuat1[4] );
|
|
ALIGN16( float jointQuat2[4] );
|
|
ALIGN16( float jointQuat3[4] );
|
|
ALIGN16( float blendQuat0[4] );
|
|
ALIGN16( float blendQuat1[4] );
|
|
ALIGN16( float blendQuat2[4] );
|
|
ALIGN16( float blendQuat3[4] );
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
int n = index[i+j];
|
|
|
|
jointVert0[j] = joints[n].t[0];
|
|
jointVert1[j] = joints[n].t[1];
|
|
jointVert2[j] = joints[n].t[2];
|
|
|
|
blendVert0[j] = blendJoints[n].t[0];
|
|
blendVert1[j] = blendJoints[n].t[1];
|
|
blendVert2[j] = blendJoints[n].t[2];
|
|
|
|
jointQuat0[j] = joints[n].q[0];
|
|
jointQuat1[j] = joints[n].q[1];
|
|
jointQuat2[j] = joints[n].q[2];
|
|
jointQuat3[j] = joints[n].q[3];
|
|
|
|
blendQuat0[j] = blendJoints[n].q[0];
|
|
blendQuat1[j] = blendJoints[n].q[1];
|
|
blendQuat2[j] = blendJoints[n].q[2];
|
|
blendQuat3[j] = blendJoints[n].q[3];
|
|
}
|
|
|
|
#if 1
|
|
__asm {
|
|
// lerp translation
|
|
movss xmm7, lerp
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movaps xmm0, blendVert0
|
|
subps xmm0, jointVert0
|
|
mulps xmm0, xmm7
|
|
addps xmm0, jointVert0
|
|
movaps jointVert0, xmm0
|
|
movaps xmm1, blendVert1
|
|
subps xmm1, jointVert1
|
|
mulps xmm1, xmm7
|
|
addps xmm1, jointVert1
|
|
movaps jointVert1, xmm1
|
|
movaps xmm2, blendVert2
|
|
subps xmm2, jointVert2
|
|
mulps xmm2, xmm7
|
|
addps xmm2, jointVert2
|
|
movaps jointVert2, xmm2
|
|
|
|
// lerp quaternions
|
|
movaps xmm0, jointQuat0
|
|
mulps xmm0, blendQuat0
|
|
movaps xmm1, jointQuat1
|
|
mulps xmm1, blendQuat1
|
|
addps xmm0, xmm1
|
|
movaps xmm2, jointQuat2
|
|
mulps xmm2, blendQuat2
|
|
addps xmm0, xmm2
|
|
movaps xmm3, jointQuat3
|
|
mulps xmm3, blendQuat3
|
|
addps xmm0, xmm3 // xmm0 = cosom
|
|
|
|
movaps xmm1, xmm0
|
|
movaps xmm2, xmm0
|
|
andps xmm1, SIMD_SP_signBitMask // xmm1 = signBit
|
|
xorps xmm0, xmm1
|
|
mulps xmm2, xmm2
|
|
|
|
xorps xmm4, xmm4
|
|
movaps xmm3, SIMD_SP_one
|
|
subps xmm3, xmm2 // xmm3 = scale0
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
|
|
#ifdef REFINE_BLENDJOINTS_RECIPROCAL
|
|
movaps xmm2, xmm3
|
|
rsqrtps xmm4, xmm2
|
|
mulps xmm2, xmm4
|
|
mulps xmm2, xmm4
|
|
subps xmm2, SIMD_SP_rsqrt_c0
|
|
mulps xmm4, SIMD_SP_rsqrt_c1
|
|
mulps xmm2, xmm4
|
|
#else
|
|
rsqrtps xmm2, xmm3 // xmm2 = sinom
|
|
#endif
|
|
mulps xmm3, xmm2 // xmm3 = sqrt( scale0 )
|
|
|
|
// omega0 = atan2( xmm3, xmm0 )
|
|
movaps xmm4, xmm0
|
|
minps xmm0, xmm3
|
|
maxps xmm3, xmm4
|
|
cmpeqps xmm4, xmm0
|
|
|
|
#ifdef REFINE_BLENDJOINTS_RECIPROCAL
|
|
rcpps xmm5, xmm3
|
|
mulps xmm3, xmm5
|
|
mulps xmm3, xmm5
|
|
addps xmm5, xmm5
|
|
subps xmm5, xmm3 // xmm5 = 1 / y or 1 / x
|
|
mulps xmm0, xmm5 // xmm0 = x / y or y / x
|
|
#else
|
|
rcpps xmm3, xmm3 // xmm3 = 1 / y or 1 / x
|
|
mulps xmm0, xmm3 // xmm0 = x / y or y / x
|
|
#endif
|
|
movaps xmm3, xmm4
|
|
andps xmm3, SIMD_SP_signBitMask
|
|
xorps xmm0, xmm3 // xmm0 = -x / y or y / x
|
|
andps xmm4, SIMD_SP_halfPI // xmm4 = HALF_PI or 0.0f
|
|
movaps xmm3, xmm0
|
|
mulps xmm3, xmm3 // xmm3 = s
|
|
movaps xmm5, SIMD_SP_atan_c0
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c1
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c2
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c3
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c4
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c5
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c6
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_atan_c7
|
|
mulps xmm5, xmm3
|
|
addps xmm5, SIMD_SP_one
|
|
mulps xmm5, xmm0
|
|
addps xmm5, xmm4 // xmm5 = omega0
|
|
|
|
movaps xmm6, xmm7 // xmm6 = lerp
|
|
mulps xmm6, xmm5 // xmm6 = omega1
|
|
subps xmm5, xmm6 // xmm5 = omega0
|
|
|
|
// scale0 = sin( xmm5 ) * xmm2
|
|
// scale1 = sin( xmm6 ) * xmm2
|
|
movaps xmm3, xmm5
|
|
movaps xmm7, xmm6
|
|
mulps xmm3, xmm3
|
|
mulps xmm7, xmm7
|
|
movaps xmm4, SIMD_SP_sin_c0
|
|
movaps xmm0, SIMD_SP_sin_c0
|
|
mulps xmm4, xmm3
|
|
mulps xmm0, xmm7
|
|
addps xmm4, SIMD_SP_sin_c1
|
|
addps xmm0, SIMD_SP_sin_c1
|
|
mulps xmm4, xmm3
|
|
mulps xmm0, xmm7
|
|
addps xmm4, SIMD_SP_sin_c2
|
|
addps xmm0, SIMD_SP_sin_c2
|
|
mulps xmm4, xmm3
|
|
mulps xmm0, xmm7
|
|
addps xmm4, SIMD_SP_sin_c3
|
|
addps xmm0, SIMD_SP_sin_c3
|
|
mulps xmm4, xmm3
|
|
mulps xmm0, xmm7
|
|
addps xmm4, SIMD_SP_sin_c4
|
|
addps xmm0, SIMD_SP_sin_c4
|
|
mulps xmm4, xmm3
|
|
mulps xmm0, xmm7
|
|
addps xmm4, SIMD_SP_one
|
|
addps xmm0, SIMD_SP_one
|
|
mulps xmm5, xmm4
|
|
mulps xmm6, xmm0
|
|
mulps xmm5, xmm2 // xmm5 = scale0
|
|
mulps xmm6, xmm2 // xmm6 = scale1
|
|
|
|
xorps xmm6, xmm1
|
|
|
|
movaps xmm0, jointQuat0
|
|
mulps xmm0, xmm5
|
|
movaps xmm1, blendQuat0
|
|
mulps xmm1, xmm6
|
|
addps xmm0, xmm1
|
|
movaps jointQuat0, xmm0
|
|
|
|
movaps xmm1, jointQuat1
|
|
mulps xmm1, xmm5
|
|
movaps xmm2, blendQuat1
|
|
mulps xmm2, xmm6
|
|
addps xmm1, xmm2
|
|
movaps jointQuat1, xmm1
|
|
|
|
movaps xmm2, jointQuat2
|
|
mulps xmm2, xmm5
|
|
movaps xmm3, blendQuat2
|
|
mulps xmm3, xmm6
|
|
addps xmm2, xmm3
|
|
movaps jointQuat2, xmm2
|
|
|
|
movaps xmm3, jointQuat3
|
|
mulps xmm3, xmm5
|
|
movaps xmm4, blendQuat3
|
|
mulps xmm4, xmm6
|
|
addps xmm3, xmm4
|
|
movaps jointQuat3, xmm3
|
|
}
|
|
|
|
#else
|
|
|
|
jointVert0[0] += lerp * ( blendVert0[0] - jointVert0[0] );
|
|
jointVert0[1] += lerp * ( blendVert0[1] - jointVert0[1] );
|
|
jointVert0[2] += lerp * ( blendVert0[2] - jointVert0[2] );
|
|
jointVert0[3] += lerp * ( blendVert0[3] - jointVert0[3] );
|
|
|
|
jointVert1[0] += lerp * ( blendVert1[0] - jointVert1[0] );
|
|
jointVert1[1] += lerp * ( blendVert1[1] - jointVert1[1] );
|
|
jointVert1[2] += lerp * ( blendVert1[2] - jointVert1[2] );
|
|
jointVert1[3] += lerp * ( blendVert1[3] - jointVert1[3] );
|
|
|
|
jointVert2[0] += lerp * ( blendVert2[0] - jointVert2[0] );
|
|
jointVert2[1] += lerp * ( blendVert2[1] - jointVert2[1] );
|
|
jointVert2[2] += lerp * ( blendVert2[2] - jointVert2[2] );
|
|
jointVert2[3] += lerp * ( blendVert2[3] - jointVert2[3] );
|
|
|
|
ALIGN16( float cosom[4] );
|
|
ALIGN16( float sinom[4] );
|
|
ALIGN16( float omega0[4] );
|
|
ALIGN16( float omega1[4] );
|
|
ALIGN16( float scale0[4] );
|
|
ALIGN16( float scale1[4] );
|
|
ALIGN16( unsigned int signBit[4] );
|
|
|
|
cosom[0] = jointQuat0[0] * blendQuat0[0];
|
|
cosom[1] = jointQuat0[1] * blendQuat0[1];
|
|
cosom[2] = jointQuat0[2] * blendQuat0[2];
|
|
cosom[3] = jointQuat0[3] * blendQuat0[3];
|
|
|
|
cosom[0] += jointQuat1[0] * blendQuat1[0];
|
|
cosom[1] += jointQuat1[1] * blendQuat1[1];
|
|
cosom[2] += jointQuat1[2] * blendQuat1[2];
|
|
cosom[3] += jointQuat1[3] * blendQuat1[3];
|
|
|
|
cosom[0] += jointQuat2[0] * blendQuat2[0];
|
|
cosom[1] += jointQuat2[1] * blendQuat2[1];
|
|
cosom[2] += jointQuat2[2] * blendQuat2[2];
|
|
cosom[3] += jointQuat2[3] * blendQuat2[3];
|
|
|
|
cosom[0] += jointQuat3[0] * blendQuat3[0];
|
|
cosom[1] += jointQuat3[1] * blendQuat3[1];
|
|
cosom[2] += jointQuat3[2] * blendQuat3[2];
|
|
cosom[3] += jointQuat3[3] * blendQuat3[3];
|
|
|
|
signBit[0] = (*(unsigned int *)&cosom[0]) & ( 1 << 31 );
|
|
signBit[1] = (*(unsigned int *)&cosom[1]) & ( 1 << 31 );
|
|
signBit[2] = (*(unsigned int *)&cosom[2]) & ( 1 << 31 );
|
|
signBit[3] = (*(unsigned int *)&cosom[3]) & ( 1 << 31 );
|
|
|
|
(*(unsigned int *)&cosom[0]) ^= signBit[0];
|
|
(*(unsigned int *)&cosom[1]) ^= signBit[1];
|
|
(*(unsigned int *)&cosom[2]) ^= signBit[2];
|
|
(*(unsigned int *)&cosom[3]) ^= signBit[3];
|
|
|
|
scale0[0] = 1.0f - cosom[0] * cosom[0];
|
|
scale0[1] = 1.0f - cosom[1] * cosom[1];
|
|
scale0[2] = 1.0f - cosom[2] * cosom[2];
|
|
scale0[3] = 1.0f - cosom[3] * cosom[3];
|
|
|
|
scale0[0] = ( scale0[0] <= 0.0f ) ? SIMD_SP_tiny[0] : scale0[0];
|
|
scale0[1] = ( scale0[1] <= 0.0f ) ? SIMD_SP_tiny[1] : scale0[1];
|
|
scale0[2] = ( scale0[2] <= 0.0f ) ? SIMD_SP_tiny[2] : scale0[2];
|
|
scale0[3] = ( scale0[3] <= 0.0f ) ? SIMD_SP_tiny[3] : scale0[3];
|
|
|
|
sinom[0] = idMath::RSqrt( scale0[0] );
|
|
sinom[1] = idMath::RSqrt( scale0[1] );
|
|
sinom[2] = idMath::RSqrt( scale0[2] );
|
|
sinom[3] = idMath::RSqrt( scale0[3] );
|
|
|
|
scale0[0] *= sinom[0];
|
|
scale0[1] *= sinom[1];
|
|
scale0[2] *= sinom[2];
|
|
scale0[3] *= sinom[3];
|
|
|
|
omega0[0] = SSE_ATanPositive( scale0[0], cosom[0] );
|
|
omega0[1] = SSE_ATanPositive( scale0[1], cosom[1] );
|
|
omega0[2] = SSE_ATanPositive( scale0[2], cosom[2] );
|
|
omega0[3] = SSE_ATanPositive( scale0[3], cosom[3] );
|
|
|
|
omega1[0] = lerp * omega0[0];
|
|
omega1[1] = lerp * omega0[1];
|
|
omega1[2] = lerp * omega0[2];
|
|
omega1[3] = lerp * omega0[3];
|
|
|
|
omega0[0] -= omega1[0];
|
|
omega0[1] -= omega1[1];
|
|
omega0[2] -= omega1[2];
|
|
omega0[3] -= omega1[3];
|
|
|
|
scale0[0] = SSE_SinZeroHalfPI( omega0[0] ) * sinom[0];
|
|
scale0[1] = SSE_SinZeroHalfPI( omega0[1] ) * sinom[1];
|
|
scale0[2] = SSE_SinZeroHalfPI( omega0[2] ) * sinom[2];
|
|
scale0[3] = SSE_SinZeroHalfPI( omega0[3] ) * sinom[3];
|
|
|
|
scale1[0] = SSE_SinZeroHalfPI( omega1[0] ) * sinom[0];
|
|
scale1[1] = SSE_SinZeroHalfPI( omega1[1] ) * sinom[1];
|
|
scale1[2] = SSE_SinZeroHalfPI( omega1[2] ) * sinom[2];
|
|
scale1[3] = SSE_SinZeroHalfPI( omega1[3] ) * sinom[3];
|
|
|
|
(*(unsigned int *)&scale1[0]) ^= signBit[0];
|
|
(*(unsigned int *)&scale1[1]) ^= signBit[1];
|
|
(*(unsigned int *)&scale1[2]) ^= signBit[2];
|
|
(*(unsigned int *)&scale1[3]) ^= signBit[3];
|
|
|
|
jointQuat0[0] = scale0[0] * jointQuat0[0] + scale1[0] * blendQuat0[0];
|
|
jointQuat0[1] = scale0[1] * jointQuat0[1] + scale1[1] * blendQuat0[1];
|
|
jointQuat0[2] = scale0[2] * jointQuat0[2] + scale1[2] * blendQuat0[2];
|
|
jointQuat0[3] = scale0[3] * jointQuat0[3] + scale1[3] * blendQuat0[3];
|
|
|
|
jointQuat1[0] = scale0[0] * jointQuat1[0] + scale1[0] * blendQuat1[0];
|
|
jointQuat1[1] = scale0[1] * jointQuat1[1] + scale1[1] * blendQuat1[1];
|
|
jointQuat1[2] = scale0[2] * jointQuat1[2] + scale1[2] * blendQuat1[2];
|
|
jointQuat1[3] = scale0[3] * jointQuat1[3] + scale1[3] * blendQuat1[3];
|
|
|
|
jointQuat2[0] = scale0[0] * jointQuat2[0] + scale1[0] * blendQuat2[0];
|
|
jointQuat2[1] = scale0[1] * jointQuat2[1] + scale1[1] * blendQuat2[1];
|
|
jointQuat2[2] = scale0[2] * jointQuat2[2] + scale1[2] * blendQuat2[2];
|
|
jointQuat2[3] = scale0[3] * jointQuat2[3] + scale1[3] * blendQuat2[3];
|
|
|
|
jointQuat3[0] = scale0[0] * jointQuat3[0] + scale1[0] * blendQuat3[0];
|
|
jointQuat3[1] = scale0[1] * jointQuat3[1] + scale1[1] * blendQuat3[1];
|
|
jointQuat3[2] = scale0[2] * jointQuat3[2] + scale1[2] * blendQuat3[2];
|
|
jointQuat3[3] = scale0[3] * jointQuat3[3] + scale1[3] * blendQuat3[3];
|
|
|
|
#endif
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
int n = index[i+j];
|
|
|
|
joints[n].t[0] = jointVert0[j];
|
|
joints[n].t[1] = jointVert1[j];
|
|
joints[n].t[2] = jointVert2[j];
|
|
|
|
joints[n].q[0] = jointQuat0[j];
|
|
joints[n].q[1] = jointQuat1[j];
|
|
joints[n].q[2] = jointQuat2[j];
|
|
joints[n].q[3] = jointQuat3[j];
|
|
}
|
|
}
|
|
|
|
for ( ; i < numJoints; i++ ) {
|
|
int n = index[i];
|
|
|
|
idVec3 &jointVert = joints[n].t;
|
|
const idVec3 &blendVert = blendJoints[n].t;
|
|
|
|
jointVert[0] += lerp * ( blendVert[0] - jointVert[0] );
|
|
jointVert[1] += lerp * ( blendVert[1] - jointVert[1] );
|
|
jointVert[2] += lerp * ( blendVert[2] - jointVert[2] );
|
|
|
|
idQuat &jointQuat = joints[n].q;
|
|
const idQuat &blendQuat = blendJoints[n].q;
|
|
|
|
float cosom;
|
|
float sinom;
|
|
float omega;
|
|
float scale0;
|
|
float scale1;
|
|
unsigned int signBit;
|
|
|
|
cosom = jointQuat.x * blendQuat.x + jointQuat.y * blendQuat.y + jointQuat.z * blendQuat.z + jointQuat.w * blendQuat.w;
|
|
|
|
signBit = (*(unsigned int *)&cosom) & ( 1 << 31 );
|
|
|
|
(*(unsigned int *)&cosom) ^= signBit;
|
|
|
|
scale0 = 1.0f - cosom * cosom;
|
|
scale0 = ( scale0 <= 0.0f ) ? SIMD_SP_tiny[0] : scale0;
|
|
sinom = idMath::InvSqrt( scale0 );
|
|
omega = idMath::ATan16( scale0 * sinom, cosom );
|
|
scale0 = idMath::Sin16( ( 1.0f - lerp ) * omega ) * sinom;
|
|
scale1 = idMath::Sin16( lerp * omega ) * sinom;
|
|
|
|
(*(unsigned int *)&scale1) ^= signBit;
|
|
|
|
jointQuat.x = scale0 * jointQuat.x + scale1 * blendQuat.x;
|
|
jointQuat.y = scale0 * jointQuat.y + scale1 * blendQuat.y;
|
|
jointQuat.z = scale0 * jointQuat.z + scale1 * blendQuat.z;
|
|
jointQuat.w = scale0 * jointQuat.w + scale1 * blendQuat.w;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::ConvertJointQuatsToJointMats
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::ConvertJointQuatsToJointMats( idJointMat *jointMats, const idJointQuat *jointQuats, const int numJoints ) {
|
|
|
|
assert( sizeof( idJointQuat ) == JOINTQUAT_SIZE );
|
|
assert( sizeof( idJointMat ) == JOINTMAT_SIZE );
|
|
assert( (int)(&((idJointQuat *)0)->t) == (int)(&((idJointQuat *)0)->q) + (int)sizeof( ((idJointQuat *)0)->q ) );
|
|
|
|
for ( int i = 0; i < numJoints; i++ ) {
|
|
|
|
const float *q = jointQuats[i].q.ToFloatPtr();
|
|
float *m = jointMats[i].ToFloatPtr();
|
|
|
|
m[0*4+3] = q[4];
|
|
m[1*4+3] = q[5];
|
|
m[2*4+3] = q[6];
|
|
|
|
float x2 = q[0] + q[0];
|
|
float y2 = q[1] + q[1];
|
|
float z2 = q[2] + q[2];
|
|
|
|
{
|
|
float xx = q[0] * x2;
|
|
float yy = q[1] * y2;
|
|
float zz = q[2] * z2;
|
|
|
|
m[0*4+0] = 1.0f - yy - zz;
|
|
m[1*4+1] = 1.0f - xx - zz;
|
|
m[2*4+2] = 1.0f - xx - yy;
|
|
}
|
|
|
|
{
|
|
float yz = q[1] * z2;
|
|
float wx = q[3] * x2;
|
|
|
|
m[2*4+1] = yz - wx;
|
|
m[1*4+2] = yz + wx;
|
|
}
|
|
|
|
{
|
|
float xy = q[0] * y2;
|
|
float wz = q[3] * z2;
|
|
|
|
m[1*4+0] = xy - wz;
|
|
m[0*4+1] = xy + wz;
|
|
}
|
|
|
|
{
|
|
float xz = q[0] * z2;
|
|
float wy = q[3] * y2;
|
|
|
|
m[0*4+2] = xz - wy;
|
|
m[2*4+0] = xz + wy;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::ConvertJointMatsToJointQuats
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::ConvertJointMatsToJointQuats( idJointQuat *jointQuats, const idJointMat *jointMats, const int numJoints ) {
|
|
|
|
assert( sizeof( idJointQuat ) == JOINTQUAT_SIZE );
|
|
assert( sizeof( idJointMat ) == JOINTMAT_SIZE );
|
|
assert( (int)(&((idJointQuat *)0)->t) == (int)(&((idJointQuat *)0)->q) + (int)sizeof( ((idJointQuat *)0)->q ) );
|
|
|
|
#if 1
|
|
|
|
ALIGN16( byte shuffle[16] );
|
|
|
|
__asm {
|
|
mov eax, numJoints
|
|
mov esi, jointMats
|
|
mov edi, jointQuats
|
|
and eax, ~3
|
|
jz done4
|
|
imul eax, JOINTMAT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopMat4:
|
|
movss xmm5, [esi+eax+3*JOINTMAT_SIZE+0*16+0*4]
|
|
movss xmm6, [esi+eax+3*JOINTMAT_SIZE+1*16+1*4]
|
|
movss xmm7, [esi+eax+3*JOINTMAT_SIZE+2*16+2*4]
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm0, [esi+eax+2*JOINTMAT_SIZE+0*16+0*4]
|
|
movss xmm1, [esi+eax+2*JOINTMAT_SIZE+1*16+1*4]
|
|
movss xmm2, [esi+eax+2*JOINTMAT_SIZE+2*16+2*4]
|
|
|
|
movss xmm5, xmm0
|
|
movss xmm6, xmm1
|
|
movss xmm7, xmm2
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm0, [esi+eax+1*JOINTMAT_SIZE+0*16+0*4]
|
|
movss xmm1, [esi+eax+1*JOINTMAT_SIZE+1*16+1*4]
|
|
movss xmm2, [esi+eax+1*JOINTMAT_SIZE+2*16+2*4]
|
|
|
|
movss xmm5, xmm0
|
|
movss xmm6, xmm1
|
|
movss xmm7, xmm2
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm0, [esi+eax+0*JOINTMAT_SIZE+0*16+0*4]
|
|
movss xmm1, [esi+eax+0*JOINTMAT_SIZE+1*16+1*4]
|
|
movss xmm2, [esi+eax+0*JOINTMAT_SIZE+2*16+2*4]
|
|
|
|
movss xmm5, xmm0
|
|
movss xmm6, xmm1
|
|
movss xmm7, xmm2
|
|
|
|
// -------------------
|
|
|
|
movaps xmm0, xmm5
|
|
addps xmm0, xmm6
|
|
addps xmm0, xmm7
|
|
cmpnltps xmm0, SIMD_SP_zero // xmm0 = m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] > 0.0f
|
|
|
|
movaps xmm1, xmm5
|
|
movaps xmm2, xmm5
|
|
cmpnltps xmm1, xmm6
|
|
cmpnltps xmm2, xmm7
|
|
andps xmm2, xmm1 // xmm2 = m[0 * 4 + 0] > m[1 * 4 + 1] && m[0 * 4 + 0] > m[2 * 4 + 2]
|
|
|
|
movaps xmm4, xmm6
|
|
cmpnltps xmm4, xmm7 // xmm3 = m[1 * 4 + 1] > m[2 * 4 + 2]
|
|
|
|
movaps xmm1, xmm0
|
|
andnps xmm1, xmm2
|
|
orps xmm2, xmm0
|
|
movaps xmm3, xmm2
|
|
andnps xmm2, xmm4
|
|
orps xmm3, xmm2
|
|
xorps xmm3, SIMD_SP_not
|
|
|
|
andps xmm0, SIMD_DW_mat2quatShuffle0
|
|
movaps xmm4, xmm1
|
|
andps xmm4, SIMD_DW_mat2quatShuffle1
|
|
orps xmm0, xmm4
|
|
movaps xmm4, xmm2
|
|
andps xmm4, SIMD_DW_mat2quatShuffle2
|
|
orps xmm0, xmm4
|
|
movaps xmm4, xmm3
|
|
andps xmm4, SIMD_DW_mat2quatShuffle3
|
|
orps xmm4, xmm0
|
|
|
|
movaps shuffle, xmm4
|
|
|
|
movaps xmm0, xmm2
|
|
orps xmm0, xmm3 // xmm0 = xmm2 | xmm3 = s0
|
|
orps xmm2, xmm1 // xmm2 = xmm1 | xmm2 = s2
|
|
orps xmm1, xmm3 // xmm1 = xmm1 | xmm3 = s1
|
|
|
|
andps xmm0, SIMD_SP_signBitMask
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
andps xmm2, SIMD_SP_signBitMask
|
|
|
|
xorps xmm5, xmm0
|
|
xorps xmm6, xmm1
|
|
xorps xmm7, xmm2
|
|
addps xmm5, xmm6
|
|
addps xmm7, SIMD_SP_one
|
|
addps xmm5, xmm7 // xmm5 = t
|
|
|
|
movaps xmm7, xmm5 // xmm7 = t
|
|
rsqrtps xmm6, xmm5
|
|
mulps xmm5, xmm6
|
|
mulps xmm5, xmm6
|
|
subps xmm5, SIMD_SP_rsqrt_c0
|
|
mulps xmm6, SIMD_SP_mat2quat_rsqrt_c1
|
|
mulps xmm6, xmm5 // xmm5 = s
|
|
|
|
mulps xmm7, xmm6 // xmm7 = s * t
|
|
xorps xmm6, SIMD_SP_signBitMask // xmm6 = -s
|
|
|
|
// -------------------
|
|
|
|
add edi, 4*JOINTQUAT_SIZE
|
|
|
|
movzx ecx, byte ptr shuffle[0*4+0] // ecx = k0
|
|
movss [edi+ecx*4-4*JOINTQUAT_SIZE], xmm7 // q[k0] = s * t;
|
|
|
|
movzx edx, byte ptr shuffle[0*4+1] // edx = k1
|
|
movss xmm4, [esi+eax+0*JOINTMAT_SIZE+1*16+0*4]
|
|
xorps xmm4, xmm2
|
|
subss xmm4, [esi+eax+0*JOINTMAT_SIZE+0*16+1*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-4*JOINTQUAT_SIZE], xmm4 // q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
|
|
movzx ecx, byte ptr shuffle[0*4+2] // ecx = k2
|
|
movss xmm3, [esi+eax+0*JOINTMAT_SIZE+0*16+2*4]
|
|
xorps xmm3, xmm1
|
|
subss xmm3, [esi+eax+0*JOINTMAT_SIZE+2*16+0*4]
|
|
mulss xmm3, xmm6
|
|
movss [edi+ecx*4-4*JOINTQUAT_SIZE], xmm3 // q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
|
|
movzx edx, byte ptr shuffle[0*4+3] // edx = k3
|
|
movss xmm4, [esi+eax+0*JOINTMAT_SIZE+2*16+1*4]
|
|
xorps xmm4, xmm0
|
|
subss xmm4, [esi+eax+0*JOINTMAT_SIZE+1*16+2*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-4*JOINTQUAT_SIZE], xmm4 // q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
mov ecx, [esi+eax+0*JOINTMAT_SIZE+0*16+3*4]
|
|
mov [edi-4*JOINTQUAT_SIZE+16], ecx // q[4] = m[0 * 4 + 3];
|
|
mov edx, [esi+eax+0*JOINTMAT_SIZE+1*16+3*4]
|
|
mov [edi-4*JOINTQUAT_SIZE+20], edx // q[5] = m[1 * 4 + 3];
|
|
mov ecx, [esi+eax+0*JOINTMAT_SIZE+2*16+3*4]
|
|
mov [edi-4*JOINTQUAT_SIZE+24], ecx // q[6] = m[2 * 4 + 3];
|
|
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movzx ecx, byte ptr shuffle[1*4+0] // ecx = k0
|
|
movss [edi+ecx*4-3*JOINTQUAT_SIZE], xmm7 // q[k0] = s * t;
|
|
|
|
movzx edx, byte ptr shuffle[1*4+1] // edx = k1
|
|
movss xmm4, [esi+eax+1*JOINTMAT_SIZE+1*16+0*4]
|
|
xorps xmm4, xmm2
|
|
subss xmm4, [esi+eax+1*JOINTMAT_SIZE+0*16+1*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-3*JOINTQUAT_SIZE], xmm4 // q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
|
|
movzx ecx, byte ptr shuffle[1*4+2] // ecx = k2
|
|
movss xmm3, [esi+eax+1*JOINTMAT_SIZE+0*16+2*4]
|
|
xorps xmm3, xmm1
|
|
subss xmm3, [esi+eax+1*JOINTMAT_SIZE+2*16+0*4]
|
|
mulss xmm3, xmm6
|
|
movss [edi+ecx*4-3*JOINTQUAT_SIZE], xmm3 // q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
|
|
movzx edx, byte ptr shuffle[1*4+3] // edx = k3
|
|
movss xmm4, [esi+eax+1*JOINTMAT_SIZE+2*16+1*4]
|
|
xorps xmm4, xmm0
|
|
subss xmm4, [esi+eax+1*JOINTMAT_SIZE+1*16+2*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-3*JOINTQUAT_SIZE], xmm4 // q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
mov ecx, [esi+eax+1*JOINTMAT_SIZE+0*16+3*4]
|
|
mov [edi-3*JOINTQUAT_SIZE+16], ecx // q[4] = m[0 * 4 + 3];
|
|
mov edx, [esi+eax+1*JOINTMAT_SIZE+1*16+3*4]
|
|
mov [edi-3*JOINTQUAT_SIZE+20], edx // q[5] = m[1 * 4 + 3];
|
|
mov ecx, [esi+eax+1*JOINTMAT_SIZE+2*16+3*4]
|
|
mov [edi-3*JOINTQUAT_SIZE+24], ecx // q[6] = m[2 * 4 + 3];
|
|
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movzx ecx, byte ptr shuffle[2*4+0] // ecx = k0
|
|
movss [edi+ecx*4-2*JOINTQUAT_SIZE], xmm7 // q[k0] = s * t;
|
|
|
|
movzx edx, byte ptr shuffle[2*4+1] // edx = k1
|
|
movss xmm4, [esi+eax+2*JOINTMAT_SIZE+1*16+0*4]
|
|
xorps xmm4, xmm2
|
|
subss xmm4, [esi+eax+2*JOINTMAT_SIZE+0*16+1*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-2*JOINTQUAT_SIZE], xmm4 // q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
|
|
movzx ecx, byte ptr shuffle[2*4+2] // ecx = k2
|
|
movss xmm3, [esi+eax+2*JOINTMAT_SIZE+0*16+2*4]
|
|
xorps xmm3, xmm1
|
|
subss xmm3, [esi+eax+2*JOINTMAT_SIZE+2*16+0*4]
|
|
mulss xmm3, xmm6
|
|
movss [edi+ecx*4-2*JOINTQUAT_SIZE], xmm3 // q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
|
|
movzx edx, byte ptr shuffle[2*4+3] // edx = k3
|
|
movss xmm4, [esi+eax+2*JOINTMAT_SIZE+2*16+1*4]
|
|
xorps xmm4, xmm0
|
|
subss xmm4, [esi+eax+2*JOINTMAT_SIZE+1*16+2*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-2*JOINTQUAT_SIZE], xmm4 // q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
mov ecx, [esi+eax+2*JOINTMAT_SIZE+0*16+3*4]
|
|
mov [edi-2*JOINTQUAT_SIZE+16], ecx // q[4] = m[0 * 4 + 3];
|
|
mov edx, [esi+eax+2*JOINTMAT_SIZE+1*16+3*4]
|
|
mov [edi-2*JOINTQUAT_SIZE+20], edx // q[5] = m[1 * 4 + 3];
|
|
mov ecx, [esi+eax+2*JOINTMAT_SIZE+2*16+3*4]
|
|
mov [edi-2*JOINTQUAT_SIZE+24], ecx // q[6] = m[2 * 4 + 3];
|
|
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movzx ecx, byte ptr shuffle[3*4+0] // ecx = k0
|
|
movss [edi+ecx*4-1*JOINTQUAT_SIZE], xmm7 // q[k0] = s * t;
|
|
|
|
movzx edx, byte ptr shuffle[3*4+1] // edx = k1
|
|
movss xmm4, [esi+eax+3*JOINTMAT_SIZE+1*16+0*4]
|
|
xorps xmm4, xmm2
|
|
subss xmm4, [esi+eax+3*JOINTMAT_SIZE+0*16+1*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-1*JOINTQUAT_SIZE], xmm4 // q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
|
|
movzx ecx, byte ptr shuffle[3*4+2] // ecx = k2
|
|
movss xmm3, [esi+eax+3*JOINTMAT_SIZE+0*16+2*4]
|
|
xorps xmm3, xmm1
|
|
subss xmm3, [esi+eax+3*JOINTMAT_SIZE+2*16+0*4]
|
|
mulss xmm3, xmm6
|
|
movss [edi+ecx*4-1*JOINTQUAT_SIZE], xmm3 // q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
|
|
movzx edx, byte ptr shuffle[3*4+3] // edx = k3
|
|
movss xmm4, [esi+eax+3*JOINTMAT_SIZE+2*16+1*4]
|
|
xorps xmm4, xmm0
|
|
subss xmm4, [esi+eax+3*JOINTMAT_SIZE+1*16+2*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-1*JOINTQUAT_SIZE], xmm4 // q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
mov ecx, [esi+eax+3*JOINTMAT_SIZE+0*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+16], ecx // q[4] = m[0 * 4 + 3];
|
|
mov edx, [esi+eax+3*JOINTMAT_SIZE+1*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+20], edx // q[5] = m[1 * 4 + 3];
|
|
mov ecx, [esi+eax+3*JOINTMAT_SIZE+2*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+24], ecx // q[6] = m[2 * 4 + 3];
|
|
|
|
add eax, 4*JOINTMAT_SIZE
|
|
jl loopMat4
|
|
|
|
done4:
|
|
mov eax, numJoints
|
|
and eax, 3
|
|
jz done1
|
|
imul eax, JOINTMAT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopMat1:
|
|
movss xmm5, [esi+eax+0*JOINTMAT_SIZE+0*16+0*4]
|
|
movss xmm6, [esi+eax+0*JOINTMAT_SIZE+1*16+1*4]
|
|
movss xmm7, [esi+eax+0*JOINTMAT_SIZE+2*16+2*4]
|
|
|
|
// -------------------
|
|
|
|
movaps xmm0, xmm5
|
|
addss xmm0, xmm6
|
|
addss xmm0, xmm7
|
|
cmpnltss xmm0, SIMD_SP_zero // xmm0 = m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] > 0.0f
|
|
|
|
movaps xmm1, xmm5
|
|
movaps xmm2, xmm5
|
|
cmpnltss xmm1, xmm6
|
|
cmpnltss xmm2, xmm7
|
|
andps xmm2, xmm1 // xmm2 = m[0 * 4 + 0] > m[1 * 4 + 1] && m[0 * 4 + 0] > m[2 * 4 + 2]
|
|
|
|
movaps xmm4, xmm6
|
|
cmpnltss xmm4, xmm7 // xmm3 = m[1 * 4 + 1] > m[2 * 4 + 2]
|
|
|
|
movaps xmm1, xmm0
|
|
andnps xmm1, xmm2
|
|
orps xmm2, xmm0
|
|
movaps xmm3, xmm2
|
|
andnps xmm2, xmm4
|
|
orps xmm3, xmm2
|
|
xorps xmm3, SIMD_SP_not
|
|
|
|
andps xmm0, SIMD_DW_mat2quatShuffle0
|
|
movaps xmm4, xmm1
|
|
andps xmm4, SIMD_DW_mat2quatShuffle1
|
|
orps xmm0, xmm4
|
|
movaps xmm4, xmm2
|
|
andps xmm4, SIMD_DW_mat2quatShuffle2
|
|
orps xmm0, xmm4
|
|
movaps xmm4, xmm3
|
|
andps xmm4, SIMD_DW_mat2quatShuffle3
|
|
orps xmm4, xmm0
|
|
|
|
movss shuffle, xmm4
|
|
|
|
movaps xmm0, xmm2
|
|
orps xmm0, xmm3 // xmm0 = xmm2 | xmm3 = s0
|
|
orps xmm2, xmm1 // xmm2 = xmm1 | xmm2 = s2
|
|
orps xmm1, xmm3 // xmm1 = xmm1 | xmm3 = s1
|
|
|
|
andps xmm0, SIMD_SP_signBitMask
|
|
andps xmm1, SIMD_SP_signBitMask
|
|
andps xmm2, SIMD_SP_signBitMask
|
|
|
|
xorps xmm5, xmm0
|
|
xorps xmm6, xmm1
|
|
xorps xmm7, xmm2
|
|
addss xmm5, xmm6
|
|
addss xmm7, SIMD_SP_one
|
|
addss xmm5, xmm7 // xmm5 = t
|
|
|
|
movss xmm7, xmm5 // xmm7 = t
|
|
rsqrtss xmm6, xmm5
|
|
mulss xmm5, xmm6
|
|
mulss xmm5, xmm6
|
|
subss xmm5, SIMD_SP_rsqrt_c0
|
|
mulss xmm6, SIMD_SP_mat2quat_rsqrt_c1
|
|
mulss xmm6, xmm5 // xmm5 = s
|
|
|
|
mulss xmm7, xmm6 // xmm7 = s * t
|
|
xorps xmm6, SIMD_SP_signBitMask // xmm6 = -s
|
|
|
|
// -------------------
|
|
|
|
movzx ecx, byte ptr shuffle[0] // ecx = k0
|
|
add edi, JOINTQUAT_SIZE
|
|
movss [edi+ecx*4-1*JOINTQUAT_SIZE], xmm7 // q[k0] = s * t;
|
|
|
|
movzx edx, byte ptr shuffle[1] // edx = k1
|
|
movss xmm4, [esi+eax+0*JOINTMAT_SIZE+1*16+0*4]
|
|
xorps xmm4, xmm2
|
|
subss xmm4, [esi+eax+0*JOINTMAT_SIZE+0*16+1*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-1*JOINTQUAT_SIZE], xmm4 // q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
|
|
movzx ecx, byte ptr shuffle[2] // ecx = k2
|
|
movss xmm3, [esi+eax+0*JOINTMAT_SIZE+0*16+2*4]
|
|
xorps xmm3, xmm1
|
|
subss xmm3, [esi+eax+0*JOINTMAT_SIZE+2*16+0*4]
|
|
mulss xmm3, xmm6
|
|
movss [edi+ecx*4-1*JOINTQUAT_SIZE], xmm3 // q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
|
|
movzx edx, byte ptr shuffle[3] // edx = k3
|
|
movss xmm4, [esi+eax+0*JOINTMAT_SIZE+2*16+1*4]
|
|
xorps xmm4, xmm0
|
|
subss xmm4, [esi+eax+0*JOINTMAT_SIZE+1*16+2*4]
|
|
mulss xmm4, xmm6
|
|
movss [edi+edx*4-1*JOINTQUAT_SIZE], xmm4 // q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
mov ecx, [esi+eax+0*JOINTMAT_SIZE+0*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+16], ecx // q[4] = m[0 * 4 + 3];
|
|
mov edx, [esi+eax+0*JOINTMAT_SIZE+1*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+20], edx // q[5] = m[1 * 4 + 3];
|
|
mov ecx, [esi+eax+0*JOINTMAT_SIZE+2*16+3*4]
|
|
mov [edi-1*JOINTQUAT_SIZE+24], ecx // q[6] = m[2 * 4 + 3];
|
|
|
|
add eax, JOINTMAT_SIZE
|
|
jl loopMat1
|
|
|
|
done1:
|
|
}
|
|
|
|
#elif 0
|
|
|
|
for ( int i = 0; i < numJoints; i++ ) {
|
|
float s0, s1, s2;
|
|
int k0, k1, k2, k3;
|
|
|
|
float *q = jointQuats[i].q.ToFloatPtr();
|
|
const float *m = jointMats[i].ToFloatPtr();
|
|
|
|
if ( m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] > 0.0f ) {
|
|
|
|
k0 = 3;
|
|
k1 = 2;
|
|
k2 = 1;
|
|
k3 = 0;
|
|
s0 = 1.0f;
|
|
s1 = 1.0f;
|
|
s2 = 1.0f;
|
|
|
|
} else if ( m[0 * 4 + 0] > m[1 * 4 + 1] && m[0 * 4 + 0] > m[2 * 4 + 2] ) {
|
|
|
|
k0 = 0;
|
|
k1 = 1;
|
|
k2 = 2;
|
|
k3 = 3;
|
|
s0 = 1.0f;
|
|
s1 = -1.0f;
|
|
s2 = -1.0f;
|
|
|
|
} else if ( m[1 * 4 + 1] > m[2 * 4 + 2] ) {
|
|
|
|
k0 = 1;
|
|
k1 = 0;
|
|
k2 = 3;
|
|
k3 = 2;
|
|
s0 = -1.0f;
|
|
s1 = 1.0f;
|
|
s2 = -1.0f;
|
|
|
|
} else {
|
|
|
|
k0 = 2;
|
|
k1 = 3;
|
|
k2 = 0;
|
|
k3 = 1;
|
|
s0 = -1.0f;
|
|
s1 = -1.0f;
|
|
s2 = 1.0f;
|
|
|
|
}
|
|
|
|
float t = s0 * m[0 * 4 + 0] + s1 * m[1 * 4 + 1] + s2 * m[2 * 4 + 2] + 1.0f;
|
|
float s = idMath::InvSqrt( t ) * 0.5f;
|
|
|
|
q[k0] = s * t;
|
|
q[k1] = ( m[0 * 4 + 1] - s2 * m[1 * 4 + 0] ) * s;
|
|
q[k2] = ( m[2 * 4 + 0] - s1 * m[0 * 4 + 2] ) * s;
|
|
q[k3] = ( m[1 * 4 + 2] - s0 * m[2 * 4 + 1] ) * s;
|
|
|
|
q[4] = m[0 * 4 + 3];
|
|
q[5] = m[1 * 4 + 3];
|
|
q[6] = m[2 * 4 + 3];
|
|
}
|
|
|
|
#elif 1
|
|
|
|
for ( int i = 0; i < numJoints; i++ ) {
|
|
|
|
float *q = jointQuats[i].q.ToFloatPtr();
|
|
const float *m = jointMats[i].ToFloatPtr();
|
|
|
|
if ( m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] > 0.0f ) {
|
|
|
|
float t = + m[0 * 4 + 0] + m[1 * 4 + 1] + m[2 * 4 + 2] + 1.0f;
|
|
float s = idMath::InvSqrt( t ) * 0.5f;
|
|
|
|
q[3] = s * t;
|
|
q[2] = ( m[0 * 4 + 1] - m[1 * 4 + 0] ) * s;
|
|
q[1] = ( m[2 * 4 + 0] - m[0 * 4 + 2] ) * s;
|
|
q[0] = ( m[1 * 4 + 2] - m[2 * 4 + 1] ) * s;
|
|
|
|
} else if ( m[0 * 4 + 0] > m[1 * 4 + 1] && m[0 * 4 + 0] > m[2 * 4 + 2] ) {
|
|
|
|
float t = + m[0 * 4 + 0] - m[1 * 4 + 1] - m[2 * 4 + 2] + 1.0f;
|
|
float s = idMath::InvSqrt( t ) * 0.5f;
|
|
|
|
q[0] = s * t;
|
|
q[1] = ( m[0 * 4 + 1] + m[1 * 4 + 0] ) * s;
|
|
q[2] = ( m[2 * 4 + 0] + m[0 * 4 + 2] ) * s;
|
|
q[3] = ( m[1 * 4 + 2] - m[2 * 4 + 1] ) * s;
|
|
|
|
} else if ( m[1 * 4 + 1] > m[2 * 4 + 2] ) {
|
|
|
|
float t = - m[0 * 4 + 0] + m[1 * 4 + 1] - m[2 * 4 + 2] + 1.0f;
|
|
float s = idMath::InvSqrt( t ) * 0.5f;
|
|
|
|
q[1] = s * t;
|
|
q[0] = ( m[0 * 4 + 1] + m[1 * 4 + 0] ) * s;
|
|
q[3] = ( m[2 * 4 + 0] - m[0 * 4 + 2] ) * s;
|
|
q[2] = ( m[1 * 4 + 2] + m[2 * 4 + 1] ) * s;
|
|
|
|
} else {
|
|
|
|
float t = - m[0 * 4 + 0] - m[1 * 4 + 1] + m[2 * 4 + 2] + 1.0f;
|
|
float s = idMath::InvSqrt( t ) * 0.5f;
|
|
|
|
q[2] = s * t;
|
|
q[3] = ( m[0 * 4 + 1] - m[1 * 4 + 0] ) * s;
|
|
q[0] = ( m[2 * 4 + 0] + m[0 * 4 + 2] ) * s;
|
|
q[1] = ( m[1 * 4 + 2] + m[2 * 4 + 1] ) * s;
|
|
|
|
}
|
|
|
|
q[4] = m[0 * 4 + 3];
|
|
q[5] = m[1 * 4 + 3];
|
|
q[6] = m[2 * 4 + 3];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::TransformJoints
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::TransformJoints( idJointMat *jointMats, const int *parents, const int firstJoint, const int lastJoint ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idJointMat ) == JOINTMAT_SIZE );
|
|
|
|
__asm {
|
|
|
|
mov ecx, firstJoint
|
|
mov eax, lastJoint
|
|
sub eax, ecx
|
|
jl done
|
|
imul ecx, 4
|
|
mov edi, parents
|
|
add edi, ecx
|
|
imul ecx, 12
|
|
mov esi, jointMats
|
|
imul eax, 4
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loopJoint:
|
|
|
|
movaps xmm0, [esi+ecx+ 0] // xmm0 = m0, m1, m2, t0
|
|
mov edx, [edi+eax]
|
|
movaps xmm1, [esi+ecx+16] // xmm1 = m2, m3, m4, t1
|
|
imul edx, JOINTMAT_SIZE
|
|
movaps xmm2, [esi+ecx+32] // xmm2 = m5, m6, m7, t2
|
|
|
|
movss xmm4, [esi+edx+ 0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm0
|
|
|
|
movss xmm5, [esi+edx+ 4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm1
|
|
addps xmm4, xmm5
|
|
movss xmm6, [esi+edx+ 8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm2
|
|
addps xmm4, xmm6
|
|
|
|
movss xmm5, [esi+edx+16]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm0
|
|
|
|
movss xmm7, [esi+edx+12]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
addps xmm4, xmm7
|
|
|
|
movaps [esi+ecx+ 0], xmm4
|
|
|
|
movss xmm6, [esi+edx+20]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm1
|
|
addps xmm5, xmm6
|
|
movss xmm7, [esi+edx+24]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm5, xmm7
|
|
|
|
movss xmm6, [esi+edx+32]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
|
|
movss xmm3, [esi+edx+28]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
addps xmm5, xmm3
|
|
|
|
movaps [esi+ecx+16], xmm5
|
|
|
|
movss xmm7, [esi+edx+36]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movss xmm3, [esi+edx+40]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm2
|
|
addps xmm6, xmm3
|
|
|
|
movss xmm7, [esi+edx+44]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
addps xmm6, xmm7
|
|
|
|
movaps [esi+ecx+32], xmm6
|
|
|
|
add ecx, JOINTMAT_SIZE
|
|
add eax, 4
|
|
jle loopJoint
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
|
|
for( i = firstJoint; i <= lastJoint; i++ ) {
|
|
assert( parents[i] < i );
|
|
jointMats[i] *= jointMats[parents[i]];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::UntransformJoints
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::UntransformJoints( idJointMat *jointMats, const int *parents, const int firstJoint, const int lastJoint ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idJointMat ) == JOINTMAT_SIZE );
|
|
|
|
__asm {
|
|
|
|
mov edx, firstJoint
|
|
mov eax, lastJoint
|
|
mov ecx, eax
|
|
sub eax, edx
|
|
jl done
|
|
mov esi, jointMats
|
|
imul ecx, JOINTMAT_SIZE
|
|
imul edx, 4
|
|
mov edi, parents
|
|
add edi, edx
|
|
imul eax, 4
|
|
|
|
loopJoint:
|
|
|
|
movaps xmm0, [esi+ecx+ 0] // xmm0 = m0, m1, m2, t0
|
|
mov edx, [edi+eax]
|
|
movaps xmm1, [esi+ecx+16] // xmm1 = m2, m3, m4, t1
|
|
imul edx, JOINTMAT_SIZE
|
|
movaps xmm2, [esi+ecx+32] // xmm2 = m5, m6, m7, t2
|
|
|
|
movss xmm6, [esi+edx+12]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
subps xmm0, xmm6
|
|
movss xmm7, [esi+edx+28]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
subps xmm1, xmm7
|
|
movss xmm3, [esi+edx+44]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
subps xmm2, xmm3
|
|
|
|
movss xmm4, [esi+edx+ 0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm4, xmm0
|
|
movss xmm5, [esi+edx+16]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm1
|
|
addps xmm4, xmm5
|
|
movss xmm6, [esi+edx+32]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm2
|
|
addps xmm4, xmm6
|
|
|
|
movaps [esi+ecx+ 0], xmm4
|
|
|
|
movss xmm5, [esi+edx+ 4]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm5, xmm0
|
|
movss xmm6, [esi+edx+20]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm1
|
|
addps xmm5, xmm6
|
|
movss xmm7, [esi+edx+36]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm5, xmm7
|
|
|
|
movaps [esi+ecx+16], xmm5
|
|
|
|
movss xmm6, [esi+edx+ 8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movss xmm7, [esi+edx+24]
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movss xmm3, [esi+edx+40]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm3, xmm2
|
|
addps xmm6, xmm3
|
|
|
|
movaps [esi+ecx+32], xmm6
|
|
|
|
sub ecx, JOINTMAT_SIZE
|
|
sub eax, 4
|
|
jge loopJoint
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
|
|
for( i = lastJoint; i >= firstJoint; i-- ) {
|
|
assert( parents[i] < i );
|
|
jointMats[i] /= jointMats[parents[i]];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::TransformVerts
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::TransformVerts( idDrawVert *verts, const int numVerts, const idJointMat *joints, const idVec4 *weights, const int *index, const int numWeights ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
assert( sizeof( idVec4 ) == JOINTWEIGHT_SIZE );
|
|
assert( sizeof( idJointMat ) == JOINTMAT_SIZE );
|
|
|
|
__asm
|
|
{
|
|
mov eax, numVerts
|
|
test eax, eax
|
|
jz done
|
|
imul eax, DRAWVERT_SIZE
|
|
|
|
mov ecx, verts
|
|
mov edx, index
|
|
mov esi, weights
|
|
mov edi, joints
|
|
|
|
add ecx, eax
|
|
neg eax
|
|
|
|
loopVert:
|
|
mov ebx, [edx]
|
|
movaps xmm2, [esi]
|
|
add edx, 8
|
|
movaps xmm0, xmm2
|
|
add esi, JOINTWEIGHT_SIZE
|
|
movaps xmm1, xmm2
|
|
|
|
mulps xmm0, [edi+ebx+ 0] // xmm0 = m0, m1, m2, t0
|
|
mulps xmm1, [edi+ebx+16] // xmm1 = m3, m4, m5, t1
|
|
mulps xmm2, [edi+ebx+32] // xmm2 = m6, m7, m8, t2
|
|
|
|
cmp dword ptr [edx-4], 0
|
|
|
|
jne doneWeight
|
|
|
|
loopWeight:
|
|
mov ebx, [edx]
|
|
movaps xmm5, [esi]
|
|
add edx, 8
|
|
movaps xmm3, xmm5
|
|
add esi, JOINTWEIGHT_SIZE
|
|
movaps xmm4, xmm5
|
|
|
|
mulps xmm3, [edi+ebx+ 0] // xmm3 = m0, m1, m2, t0
|
|
mulps xmm4, [edi+ebx+16] // xmm4 = m3, m4, m5, t1
|
|
mulps xmm5, [edi+ebx+32] // xmm5 = m6, m7, m8, t2
|
|
|
|
cmp dword ptr [edx-4], 0
|
|
|
|
addps xmm0, xmm3
|
|
addps xmm1, xmm4
|
|
addps xmm2, xmm5
|
|
|
|
je loopWeight
|
|
|
|
doneWeight:
|
|
add eax, DRAWVERT_SIZE
|
|
|
|
movaps xmm6, xmm0 // xmm6 = m0, m1, m2, t0
|
|
unpcklps xmm6, xmm1 // xmm6 = m0, m3, m1, m4
|
|
unpckhps xmm0, xmm1 // xmm1 = m2, m5, t0, t1
|
|
addps xmm6, xmm0 // xmm6 = m0+m2, m3+m5, m1+t0, m4+t1
|
|
|
|
movaps xmm7, xmm2 // xmm7 = m6, m7, m8, t2
|
|
movlhps xmm2, xmm6 // xmm2 = m6, m7, m0+m2, m3+m5
|
|
movhlps xmm6, xmm7 // xmm6 = m8, t2, m1+t0, m4+t1
|
|
addps xmm6, xmm2 // xmm6 = m6+m8, m7+t2, m0+m1+m2+t0, m3+m4+m5+t1
|
|
|
|
movhps [ecx+eax-DRAWVERT_SIZE+0], xmm6
|
|
|
|
movaps xmm5, xmm6 // xmm5 = m6+m8, m7+t2
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 0, 2, 3 ) // xmm5 = m7+t2, m6+m8
|
|
addss xmm5, xmm6 // xmm5 = m6+m8+m7+t2
|
|
|
|
movss [ecx+eax-DRAWVERT_SIZE+8], xmm5
|
|
|
|
jl loopVert
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
int i, j;
|
|
const byte *jointsPtr = (byte *)joints;
|
|
|
|
for( j = i = 0; i < numVerts; i++ ) {
|
|
idVec3 v;
|
|
|
|
v = ( *(idJointMat *) ( jointsPtr + index[j*2+0] ) ) * weights[j];
|
|
while( index[j*2+1] == 0 ) {
|
|
j++;
|
|
v += ( *(idJointMat *) ( jointsPtr + index[j*2+0] ) ) * weights[j];
|
|
}
|
|
j++;
|
|
|
|
verts[i].xyz = v;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::TracePointCull
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::TracePointCull( byte *cullBits, byte &totalOr, const float radius, const idPlane *planes, const idDrawVert *verts, const int numVerts ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
push ebx
|
|
mov eax, numVerts
|
|
test eax, eax
|
|
jz done
|
|
|
|
mov edi, planes
|
|
movlps xmm1, [edi] // xmm1 = 0, 1, X, X
|
|
movhps xmm1, [edi+16] // xmm1 = 0, 1, 4, 5
|
|
movlps xmm3, [edi+8] // xmm3 = 2, 3, X, X
|
|
movhps xmm3, [edi+24] // xmm3 = 2, 3, 6, 7
|
|
movlps xmm4, [edi+32] // xmm4 = 8, 9, X, X
|
|
movhps xmm4, [edi+48] // xmm4 = 8, 9, 12, 13
|
|
movlps xmm5, [edi+40] // xmm5 = 10, 11, X, X
|
|
movhps xmm5, [edi+56] // xmm5 = 10, 11, 14, 15
|
|
movaps xmm0, xmm1 // xmm0 = 0, 1, 4, 5
|
|
shufps xmm0, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm0 = 0, 4, 8, 12
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm1 = 1, 5, 9, 13
|
|
movaps xmm2, xmm3 // xmm2 = 2, 3, 6, 7
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm2 = 2, 6, 10, 14
|
|
shufps xmm3, xmm5, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm3 = 3, 7, 11, 15
|
|
movss xmm7, radius
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
xor edx, edx
|
|
mov esi, verts
|
|
mov edi, cullBits
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopVert:
|
|
movss xmm4, [esi+eax+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm5, [esi+eax+DRAWVERT_XYZ_OFFSET+4]
|
|
mulps xmm4, xmm0
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movss xmm6, [esi+eax+DRAWVERT_XYZ_OFFSET+8]
|
|
mulps xmm5, xmm1
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
addps xmm4, xmm5
|
|
mulps xmm6, xmm2
|
|
addps xmm4, xmm3
|
|
addps xmm4, xmm6
|
|
movaps xmm5, xmm4
|
|
xorps xmm5, SIMD_SP_signBitMask
|
|
cmpltps xmm4, xmm7
|
|
movmskps ecx, xmm4
|
|
cmpltps xmm5, xmm7
|
|
movmskps ebx, xmm5
|
|
shl cx, 4
|
|
or cl, bl
|
|
inc edi
|
|
or dl, cl
|
|
add eax, DRAWVERT_SIZE
|
|
mov byte ptr [edi-1], cl
|
|
jl loopVert
|
|
|
|
done:
|
|
mov esi, totalOr
|
|
mov byte ptr [esi], dl
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
byte tOr;
|
|
|
|
tOr = 0;
|
|
|
|
for ( i = 0; i < numVerts; i++ ) {
|
|
byte bits;
|
|
float d0, d1, d2, d3, t;
|
|
const idVec3 &v = verts[i].xyz;
|
|
|
|
d0 = planes[0][0] * v[0] + planes[0][1] * v[1] + planes[0][2] * v[2] + planes[0][3];
|
|
d1 = planes[1][0] * v[0] + planes[1][1] * v[1] + planes[1][2] * v[2] + planes[1][3];
|
|
d2 = planes[2][0] * v[0] + planes[2][1] * v[1] + planes[2][2] * v[2] + planes[2][3];
|
|
d3 = planes[3][0] * v[0] + planes[3][1] * v[1] + planes[3][2] * v[2] + planes[3][3];
|
|
|
|
t = d0 + radius;
|
|
bits = FLOATSIGNBITSET( t ) << 0;
|
|
t = d1 + radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 1;
|
|
t = d2 + radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 2;
|
|
t = d3 + radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 3;
|
|
|
|
t = d0 - radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 4;
|
|
t = d1 - radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 5;
|
|
t = d2 - radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 6;
|
|
t = d3 - radius;
|
|
bits |= FLOATSIGNBITSET( t ) << 7;
|
|
|
|
bits ^= 0x0F; // flip lower four bits
|
|
|
|
tOr |= bits;
|
|
cullBits[i] = bits;
|
|
}
|
|
|
|
totalOr = tOr;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::DecalPointCull
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::DecalPointCull( byte *cullBits, const idPlane *planes, const idDrawVert *verts, const int numVerts ) {
|
|
#if 1
|
|
|
|
ALIGN16( float p0[4] );
|
|
ALIGN16( float p1[4] );
|
|
ALIGN16( float p2[4] );
|
|
ALIGN16( float p3[4] );
|
|
ALIGN16( float p4[4] );
|
|
ALIGN16( float p5[4] );
|
|
ALIGN16( float p6[4] );
|
|
ALIGN16( float p7[4] );
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
mov ecx, planes
|
|
movlps xmm1, [ecx] // xmm1 = 0, 1, X, X
|
|
movhps xmm1, [ecx+16] // xmm1 = 0, 1, 4, 5
|
|
movlps xmm3, [ecx+8] // xmm3 = 2, 3, X, X
|
|
movhps xmm3, [ecx+24] // xmm3 = 2, 3, 6, 7
|
|
movlps xmm4, [ecx+32] // xmm4 = 8, 9, X, X
|
|
movhps xmm4, [ecx+48] // xmm4 = 8, 9, 12, 13
|
|
movlps xmm5, [ecx+40] // xmm5 = 10, 11, X, X
|
|
movhps xmm5, [ecx+56] // xmm5 = 10, 11, 14, 15
|
|
movaps xmm0, xmm1 // xmm0 = 0, 1, 4, 5
|
|
shufps xmm0, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm0 = 0, 4, 8, 12
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm1 = 1, 5, 9, 13
|
|
movaps xmm2, xmm3 // xmm2 = 2, 3, 6, 7
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm2 = 2, 6, 10, 14
|
|
shufps xmm3, xmm5, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm3 = 3, 7, 11, 15
|
|
|
|
movaps p0, xmm0
|
|
movaps p1, xmm1
|
|
movaps p2, xmm2
|
|
movaps p3, xmm3
|
|
|
|
movlps xmm4, [ecx+64] // xmm4 = p40, p41, X, X
|
|
movhps xmm4, [ecx+80] // xmm4 = p40, p41, p50, p51
|
|
movaps xmm5, xmm4 // xmm5 = p40, p41, p50, p51
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm4 = p40, p50, p40, p50
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm5 = p41, p51, p41, p51
|
|
movlps xmm6, [ecx+72] // xmm6 = p42, p43, X, X
|
|
movhps xmm6, [ecx+88] // xmm6 = p42, p43, p52, p53
|
|
movaps xmm7, xmm6 // xmm7 = p42, p43, p52, p53
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 2, 0, 2 ) // xmm6 = p42, p52, p42, p52
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 1, 3, 1, 3 ) // xmm7 = p43, p53, p43, p53
|
|
|
|
movaps p4, xmm4
|
|
movaps p5, xmm5
|
|
movaps p6, xmm6
|
|
movaps p7, xmm7
|
|
|
|
mov esi, verts
|
|
mov edi, cullBits
|
|
mov eax, numVerts
|
|
and eax, ~1
|
|
jz done2
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
|
|
loopVert2:
|
|
movaps xmm6, p0
|
|
movss xmm0, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movaps xmm7, p1
|
|
movss xmm1, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movaps xmm7, p2
|
|
movss xmm2, [esi+eax+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
addps xmm6, p3
|
|
|
|
cmpnltps xmm6, SIMD_SP_zero
|
|
movmskps ecx, xmm6
|
|
|
|
movaps xmm6, p0
|
|
movss xmm3, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm3
|
|
movaps xmm7, p1
|
|
movss xmm4, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm4
|
|
addps xmm6, xmm7
|
|
movaps xmm7, p2
|
|
movss xmm5, [esi+eax+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm5
|
|
addps xmm6, xmm7
|
|
addps xmm6, p3
|
|
|
|
cmpnltps xmm6, SIMD_SP_zero
|
|
movmskps edx, xmm6
|
|
mov ch, dl
|
|
|
|
shufps xmm0, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm0, p4
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm1, p5
|
|
addps xmm0, xmm1
|
|
shufps xmm2, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm2, p6
|
|
addps xmm0, xmm2
|
|
addps xmm0, p7
|
|
|
|
cmpnltps xmm0, SIMD_SP_zero
|
|
movmskps edx, xmm0
|
|
|
|
add edi, 2
|
|
|
|
mov dh, dl
|
|
shl dl, 4
|
|
shl dh, 2
|
|
and edx, (3<<4)|(3<<12)
|
|
or ecx, edx
|
|
|
|
add eax, 2*DRAWVERT_SIZE
|
|
mov word ptr [edi-2], cx
|
|
jl loopVert2
|
|
|
|
done2:
|
|
|
|
mov eax, numVerts
|
|
and eax, 1
|
|
jz done
|
|
|
|
movaps xmm6, p0
|
|
movss xmm0, [esi+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm6, xmm0
|
|
movaps xmm7, p1
|
|
movss xmm1, [esi+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm1
|
|
addps xmm6, xmm7
|
|
movaps xmm7, p2
|
|
movss xmm2, [esi+DRAWVERT_XYZ_OFFSET+8]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm7, xmm2
|
|
addps xmm6, xmm7
|
|
addps xmm6, p3
|
|
|
|
cmpnltps xmm6, SIMD_SP_zero
|
|
movmskps ecx, xmm6
|
|
|
|
mulps xmm0, p4
|
|
mulps xmm1, p5
|
|
addps xmm0, xmm1
|
|
mulps xmm2, p6
|
|
addps xmm0, xmm2
|
|
addps xmm0, p7
|
|
|
|
cmpnltps xmm0, SIMD_SP_zero
|
|
movmskps edx, xmm0
|
|
|
|
and edx, 3
|
|
shl edx, 4
|
|
or ecx, edx
|
|
|
|
mov byte ptr [edi], cl
|
|
|
|
done:
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
int i;
|
|
|
|
for ( i = 0; i < numVerts; i += 2 ) {
|
|
unsigned short bits0, bits1;
|
|
float d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11;
|
|
const idVec3 &v0 = verts[i+0].xyz;
|
|
const idVec3 &v1 = verts[i+1].xyz;
|
|
|
|
d0 = planes[0][0] * v0[0] + planes[0][1] * v0[1] + planes[0][2] * v0[2] + planes[0][3];
|
|
d1 = planes[1][0] * v0[0] + planes[1][1] * v0[1] + planes[1][2] * v0[2] + planes[1][3];
|
|
d2 = planes[2][0] * v0[0] + planes[2][1] * v0[1] + planes[2][2] * v0[2] + planes[2][3];
|
|
d3 = planes[3][0] * v0[0] + planes[3][1] * v0[1] + planes[3][2] * v0[2] + planes[3][3];
|
|
|
|
d4 = planes[4][0] * v0[0] + planes[4][1] * v0[1] + planes[4][2] * v0[2] + planes[4][3];
|
|
d5 = planes[5][0] * v0[0] + planes[5][1] * v0[1] + planes[5][2] * v0[2] + planes[5][3];
|
|
d10 = planes[4][0] * v1[0] + planes[4][1] * v1[1] + planes[4][2] * v1[2] + planes[4][3];
|
|
d11 = planes[5][0] * v1[0] + planes[5][1] * v1[1] + planes[5][2] * v1[2] + planes[5][3];
|
|
|
|
d6 = planes[0][0] * v1[0] + planes[0][1] * v1[1] + planes[0][2] * v1[2] + planes[0][3];
|
|
d7 = planes[1][0] * v1[0] + planes[1][1] * v1[1] + planes[1][2] * v1[2] + planes[1][3];
|
|
d8 = planes[2][0] * v1[0] + planes[2][1] * v1[1] + planes[2][2] * v1[2] + planes[2][3];
|
|
d9 = planes[3][0] * v1[0] + planes[3][1] * v1[1] + planes[3][2] * v1[2] + planes[3][3];
|
|
|
|
bits0 = FLOATSIGNBITSET( d0 ) << (0+0);
|
|
bits0 |= FLOATSIGNBITSET( d1 ) << (0+1);
|
|
bits0 |= FLOATSIGNBITSET( d2 ) << (0+2);
|
|
bits0 |= FLOATSIGNBITSET( d3 ) << (0+3);
|
|
bits0 |= FLOATSIGNBITSET( d4 ) << (0+4);
|
|
bits0 |= FLOATSIGNBITSET( d5 ) << (0+5);
|
|
|
|
bits1 = FLOATSIGNBITSET( d6 ) << (8+0);
|
|
bits1 |= FLOATSIGNBITSET( d7 ) << (8+1);
|
|
bits1 |= FLOATSIGNBITSET( d8 ) << (8+2);
|
|
bits1 |= FLOATSIGNBITSET( d9 ) << (8+3);
|
|
bits1 |= FLOATSIGNBITSET( d10 ) << (8+4);
|
|
bits1 |= FLOATSIGNBITSET( d11 ) << (8+5);
|
|
|
|
*(unsigned short *)(cullBits + i) = ( bits0 | bits1 ) ^ 0x3F3F;
|
|
}
|
|
|
|
if ( numVerts & 1 ) {
|
|
byte bits;
|
|
float d0, d1, d2, d3, d4, d5;
|
|
const idVec3 &v = verts[numVerts - 1].xyz;
|
|
|
|
d0 = planes[0][0] * v[0] + planes[0][1] * v[1] + planes[0][2] * v[2] + planes[0][3];
|
|
d1 = planes[1][0] * v[0] + planes[1][1] * v[1] + planes[1][2] * v[2] + planes[1][3];
|
|
d2 = planes[2][0] * v[0] + planes[2][1] * v[1] + planes[2][2] * v[2] + planes[2][3];
|
|
d3 = planes[3][0] * v[0] + planes[3][1] * v[1] + planes[3][2] * v[2] + planes[3][3];
|
|
|
|
d4 = planes[4][0] * v[0] + planes[4][1] * v[1] + planes[4][2] * v[2] + planes[4][3];
|
|
d5 = planes[5][0] * v[0] + planes[5][1] * v[1] + planes[5][2] * v[2] + planes[5][3];
|
|
|
|
bits = FLOATSIGNBITSET( d0 ) << 0;
|
|
bits |= FLOATSIGNBITSET( d1 ) << 1;
|
|
bits |= FLOATSIGNBITSET( d2 ) << 2;
|
|
bits |= FLOATSIGNBITSET( d3 ) << 3;
|
|
|
|
bits |= FLOATSIGNBITSET( d4 ) << 4;
|
|
bits |= FLOATSIGNBITSET( d5 ) << 5;
|
|
|
|
cullBits[numVerts - 1] = bits ^ 0x3F; // flip lower 6 bits
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::OverlayPointCull
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::OverlayPointCull( byte *cullBits, idVec2 *texCoords, const idPlane *planes, const idDrawVert *verts, const int numVerts ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
mov eax, numVerts
|
|
mov edx, verts
|
|
mov esi, texCoords
|
|
mov edi, cullBits
|
|
|
|
mov ecx, planes
|
|
movss xmm4, [ecx+ 0]
|
|
movss xmm5, [ecx+16]
|
|
shufps xmm4, xmm5, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
movss xmm5, [ecx+ 4]
|
|
movss xmm6, [ecx+20]
|
|
shufps xmm5, xmm6, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
movss xmm6, [ecx+ 8]
|
|
movss xmm7, [ecx+24]
|
|
shufps xmm6, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
movss xmm7, [ecx+12]
|
|
movss xmm0, [ecx+28]
|
|
shufps xmm7, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 2, 0, 2 )
|
|
|
|
and eax, ~1
|
|
jz done2
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loopVert2:
|
|
movss xmm0, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm1, [edx+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm0, xmm4
|
|
movss xmm1, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm2, [edx+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm1, xmm5
|
|
movss xmm2, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm3, [edx+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
addps xmm0, xmm7
|
|
movaps [esi], xmm0
|
|
movaps xmm1, xmm0
|
|
movaps xmm2, SIMD_SP_one
|
|
subps xmm2, xmm0
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
shufps xmm1, xmm2, R_SHUFFLEPS( 2, 3, 2, 3 )
|
|
add edx, 2*DRAWVERT_SIZE
|
|
movmskps ecx, xmm0
|
|
mov byte ptr [edi+eax+0], cl
|
|
add esi, 4*4
|
|
movmskps ecx, xmm1
|
|
mov byte ptr [edi+eax+1], cl
|
|
add eax, 2
|
|
jl loopVert2
|
|
|
|
done2:
|
|
mov eax, numVerts
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm0, xmm4
|
|
movss xmm1, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm1, xmm5
|
|
movss xmm2, [edx+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm2, xmm6
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
addps xmm0, xmm7
|
|
movlps [esi], xmm0
|
|
movaps xmm1, xmm0
|
|
movaps xmm2, SIMD_SP_one
|
|
subps xmm2, xmm0
|
|
shufps xmm0, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
movmskps ecx, xmm0
|
|
mov byte ptr [edi], cl
|
|
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
const idPlane &p0 = planes[0];
|
|
const idPlane &p1 = planes[1];
|
|
|
|
for ( int i = 0; i < numVerts - 1; i += 2 ) {
|
|
unsigned short bits;
|
|
float d0, d1, d2, d3;
|
|
|
|
const idVec3 &v0 = verts[i+0].xyz;
|
|
const idVec3 &v1 = verts[i+1].xyz;
|
|
|
|
d0 = p0[0] * v0[0] + p0[1] * v0[1] + p0[2] * v0[2] + p0[3];
|
|
d1 = p1[0] * v0[0] + p1[1] * v0[1] + p1[2] * v0[2] + p1[3];
|
|
d2 = p0[0] * v1[0] + p0[1] * v1[1] + p0[2] * v1[2] + p0[3];
|
|
d3 = p1[0] * v1[0] + p1[1] * v1[1] + p1[2] * v1[2] + p1[3];
|
|
|
|
texCoords[i+0][0] = d0;
|
|
texCoords[i+0][1] = d1;
|
|
texCoords[i+1][0] = d2;
|
|
texCoords[i+1][1] = d3;
|
|
|
|
bits = FLOATSIGNBITSET( d0 ) << 0;
|
|
bits |= FLOATSIGNBITSET( d1 ) << 1;
|
|
bits |= FLOATSIGNBITSET( d2 ) << 8;
|
|
bits |= FLOATSIGNBITSET( d3 ) << 9;
|
|
|
|
d0 = 1.0f - d0;
|
|
d1 = 1.0f - d1;
|
|
d2 = 1.0f - d2;
|
|
d3 = 1.0f - d3;
|
|
|
|
bits |= FLOATSIGNBITSET( d0 ) << 2;
|
|
bits |= FLOATSIGNBITSET( d1 ) << 3;
|
|
bits |= FLOATSIGNBITSET( d2 ) << 10;
|
|
bits |= FLOATSIGNBITSET( d3 ) << 11;
|
|
|
|
*(unsigned short *)(cullBits + i) = bits;
|
|
}
|
|
|
|
if ( numVerts & 1 ) {
|
|
byte bits;
|
|
float d0, d1;
|
|
|
|
const idPlane &p0 = planes[0];
|
|
const idPlane &p1 = planes[1];
|
|
const idVec3 &v0 = verts[numVerts - 1].xyz;
|
|
|
|
d0 = p0[0] * v0[0] + p0[1] * v0[1] + p0[2] * v0[2] + p0[3];
|
|
d1 = p1[0] * v0[0] + p1[1] * v0[1] + p1[2] * v0[2] + p1[3];
|
|
|
|
texCoords[i][0] = d0;
|
|
texCoords[i][1] = d1;
|
|
|
|
bits = FLOATSIGNBITSET( d0 ) << 0;
|
|
bits |= FLOATSIGNBITSET( d1 ) << 1;
|
|
|
|
d0 = 1.0f - d0;
|
|
d1 = 1.0f - d1;
|
|
|
|
bits |= FLOATSIGNBITSET( d0 ) << 2;
|
|
bits |= FLOATSIGNBITSET( d1 ) << 3;
|
|
|
|
cullBits[numVerts - 1] = bits;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::DeriveTriPlanes
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::DeriveTriPlanes( idPlane *planes, const idDrawVert *verts, const int numVerts, const int *indexes, const int numIndexes ) {
|
|
#if 1
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
|
|
__asm {
|
|
mov eax, numIndexes
|
|
shl eax, 2
|
|
mov esi, verts
|
|
mov edi, indexes
|
|
mov edx, planes
|
|
|
|
add edi, eax
|
|
neg eax
|
|
|
|
add eax, 4*12
|
|
jge done4
|
|
|
|
loopPlane4:
|
|
mov ebx, [edi+eax-4*12+4]
|
|
imul ebx, DRAWVERT_SIZE
|
|
mov ecx, [edi+eax-4*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
movss xmm0, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
|
|
movss xmm1, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
|
|
movss xmm2, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
mov ebx, [edi+eax-4*12+8]
|
|
imul ebx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm3, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm3, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
|
|
movss xmm4, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm4, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
|
|
movss xmm5, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm5, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
mov ebx, [edi+eax-3*12+4]
|
|
imul ebx, DRAWVERT_SIZE
|
|
mov ecx, [edi+eax-3*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm0, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm1, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm2, xmm6
|
|
|
|
mov ebx, [edi+eax-3*12+8]
|
|
imul ebx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm3, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm4, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm5, xmm7
|
|
|
|
mov ebx, [edi+eax-2*12+4]
|
|
imul ebx, DRAWVERT_SIZE
|
|
mov ecx, [edi+eax-2*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm0, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm1, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm2, xmm6
|
|
|
|
mov ebx, [edi+eax-2*12+8]
|
|
imul ebx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm3, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm4, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm5, xmm7
|
|
|
|
mov ebx, [edi+eax-1*12+4]
|
|
imul ebx, DRAWVERT_SIZE
|
|
mov ecx, [edi+eax-1*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 3, 0, 1, 2 )
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm0, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm1, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm2, xmm6
|
|
|
|
mov ebx, [edi+eax-1*12+8]
|
|
imul ebx, DRAWVERT_SIZE
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
movss xmm3, xmm7
|
|
|
|
movss xmm6, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm6, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
movss xmm4, xmm6
|
|
|
|
movss xmm7, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm7, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
movss xmm5, xmm7
|
|
|
|
movaps xmm6, xmm4
|
|
mulps xmm6, xmm2
|
|
movaps xmm7, xmm5
|
|
mulps xmm7, xmm1
|
|
subps xmm6, xmm7
|
|
|
|
mulps xmm5, xmm0
|
|
mulps xmm2, xmm3
|
|
subps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm1
|
|
mulps xmm4, xmm0
|
|
subps xmm3, xmm4
|
|
|
|
movaps xmm0, xmm6
|
|
mulps xmm6, xmm6
|
|
movaps xmm1, xmm5
|
|
mulps xmm5, xmm5
|
|
movaps xmm2, xmm3
|
|
mulps xmm3, xmm3
|
|
|
|
addps xmm3, xmm5
|
|
addps xmm3, xmm6
|
|
rsqrtps xmm3, xmm3
|
|
|
|
add edx, 4*16
|
|
mov ecx, [edi+eax-1*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
mulps xmm0, xmm3
|
|
mulps xmm1, xmm3
|
|
mulps xmm2, xmm3
|
|
|
|
movss [edx-1*16+0], xmm0
|
|
movss [edx-1*16+4], xmm1
|
|
movss [edx-1*16+8], xmm2
|
|
|
|
mulss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
mulss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
mulss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
xorps xmm0, SIMD_SP_singleSignBitMask
|
|
subss xmm0, xmm1
|
|
subss xmm0, xmm2
|
|
movss [edx-1*16+12], xmm0
|
|
|
|
mov ecx, [edi+eax-2*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [edx-2*16+0], xmm0
|
|
movss [edx-2*16+4], xmm1
|
|
movss [edx-2*16+8], xmm2
|
|
|
|
mulss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
mulss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
mulss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
xorps xmm0, SIMD_SP_singleSignBitMask
|
|
subss xmm0, xmm1
|
|
subss xmm0, xmm2
|
|
movss [edx-2*16+12], xmm0
|
|
|
|
mov ecx, [edi+eax-3*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [edx-3*16+0], xmm0
|
|
movss [edx-3*16+4], xmm1
|
|
movss [edx-3*16+8], xmm2
|
|
|
|
mulss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
mulss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
mulss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
xorps xmm0, SIMD_SP_singleSignBitMask
|
|
subss xmm0, xmm1
|
|
subss xmm0, xmm2
|
|
movss [edx-3*16+12], xmm0
|
|
|
|
mov ecx, [edi+eax-4*12+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [edx-4*16+0], xmm0
|
|
movss [edx-4*16+4], xmm1
|
|
movss [edx-4*16+8], xmm2
|
|
|
|
mulss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
mulss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
mulss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
xorps xmm0, SIMD_SP_singleSignBitMask
|
|
subss xmm0, xmm1
|
|
subss xmm0, xmm2
|
|
movss [edx-4*16+12], xmm0
|
|
|
|
add eax, 4*12
|
|
jle loopPlane4
|
|
|
|
done4:
|
|
|
|
sub eax, 4*12
|
|
jge done
|
|
|
|
loopPlane1:
|
|
mov ebx, [edi+eax+4]
|
|
imul ebx, DRAWVERT_SIZE
|
|
mov ecx, [edi+eax+0]
|
|
imul ecx, DRAWVERT_SIZE
|
|
|
|
movss xmm0, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
|
|
movss xmm1, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
|
|
movss xmm2, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
mov ebx, [edi+eax+8]
|
|
imul ebx, DRAWVERT_SIZE
|
|
|
|
movss xmm3, [esi+ebx+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm3, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
|
|
movss xmm4, [esi+ebx+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm4, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
|
|
movss xmm5, [esi+ebx+DRAWVERT_XYZ_OFFSET+8]
|
|
subss xmm5, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
movss xmm6, xmm4
|
|
mulss xmm6, xmm2
|
|
movss xmm7, xmm5
|
|
mulss xmm7, xmm1
|
|
subss xmm6, xmm7
|
|
|
|
mulss xmm5, xmm0
|
|
mulss xmm2, xmm3
|
|
subss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm1
|
|
mulss xmm4, xmm0
|
|
subss xmm3, xmm4
|
|
|
|
movss xmm0, xmm6
|
|
mulss xmm6, xmm6
|
|
movss xmm1, xmm5
|
|
mulss xmm5, xmm5
|
|
movss xmm2, xmm3
|
|
mulss xmm3, xmm3
|
|
|
|
addss xmm3, xmm5
|
|
addss xmm3, xmm6
|
|
rsqrtss xmm3, xmm3
|
|
|
|
add edx, 1*16
|
|
|
|
mulss xmm0, xmm3
|
|
mulss xmm1, xmm3
|
|
mulss xmm2, xmm3
|
|
|
|
movss [edx-1*16+0], xmm0
|
|
movss [edx-1*16+4], xmm1
|
|
movss [edx-1*16+8], xmm2
|
|
|
|
mulss xmm0, [esi+ecx+DRAWVERT_XYZ_OFFSET+0]
|
|
mulss xmm1, [esi+ecx+DRAWVERT_XYZ_OFFSET+4]
|
|
mulss xmm2, [esi+ecx+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
xorps xmm0, SIMD_SP_singleSignBitMask
|
|
subss xmm0, xmm1
|
|
subss xmm0, xmm2
|
|
movss [edx-1*16+12], xmm0
|
|
|
|
add eax, 1*12
|
|
jl loopPlane1
|
|
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
int i, j;
|
|
|
|
for ( i = 0; i <= numIndexes - 12; i += 12 ) {
|
|
ALIGN16( float d0[4] );
|
|
ALIGN16( float d1[4] );
|
|
ALIGN16( float d2[4] );
|
|
ALIGN16( float d3[4] );
|
|
ALIGN16( float d4[4] );
|
|
ALIGN16( float d5[4] );
|
|
ALIGN16( float n0[4] );
|
|
ALIGN16( float n1[4] );
|
|
ALIGN16( float n2[4] );
|
|
|
|
for ( j = 0; j < 4; j++ ) {
|
|
const idDrawVert *a, *b, *c;
|
|
|
|
a = verts + indexes[i + j * 3 + 0];
|
|
b = verts + indexes[i + j * 3 + 1];
|
|
c = verts + indexes[i + j * 3 + 2];
|
|
|
|
d0[j] = b->xyz[0] - a->xyz[0];
|
|
d1[j] = b->xyz[1] - a->xyz[1];
|
|
d2[j] = b->xyz[2] - a->xyz[2];
|
|
|
|
d3[j] = c->xyz[0] - a->xyz[0];
|
|
d4[j] = c->xyz[1] - a->xyz[1];
|
|
d5[j] = c->xyz[2] - a->xyz[2];
|
|
}
|
|
|
|
ALIGN16( float tmp[4] );
|
|
|
|
n0[0] = d4[0] * d2[0];
|
|
n0[1] = d4[1] * d2[1];
|
|
n0[2] = d4[2] * d2[2];
|
|
n0[3] = d4[3] * d2[3];
|
|
|
|
n0[0] -= d5[0] * d1[0];
|
|
n0[1] -= d5[1] * d1[1];
|
|
n0[2] -= d5[2] * d1[2];
|
|
n0[3] -= d5[3] * d1[3];
|
|
|
|
n1[0] = d5[0] * d0[0];
|
|
n1[1] = d5[1] * d0[1];
|
|
n1[2] = d5[2] * d0[2];
|
|
n1[3] = d5[3] * d0[3];
|
|
|
|
n1[0] -= d3[0] * d2[0];
|
|
n1[1] -= d3[1] * d2[1];
|
|
n1[2] -= d3[2] * d2[2];
|
|
n1[3] -= d3[3] * d2[3];
|
|
|
|
n2[0] = d3[0] * d1[0];
|
|
n2[1] = d3[1] * d1[1];
|
|
n2[2] = d3[2] * d1[2];
|
|
n2[3] = d3[3] * d1[3];
|
|
|
|
n2[0] -= d4[0] * d0[0];
|
|
n2[1] -= d4[1] * d0[1];
|
|
n2[2] -= d4[2] * d0[2];
|
|
n2[3] -= d4[3] * d0[3];
|
|
|
|
tmp[0] = n0[0] * n0[0];
|
|
tmp[1] = n0[1] * n0[1];
|
|
tmp[2] = n0[2] * n0[2];
|
|
tmp[3] = n0[3] * n0[3];
|
|
|
|
tmp[0] += n1[0] * n1[0];
|
|
tmp[1] += n1[1] * n1[1];
|
|
tmp[2] += n1[2] * n1[2];
|
|
tmp[3] += n1[3] * n1[3];
|
|
|
|
tmp[0] += n2[0] * n2[0];
|
|
tmp[1] += n2[1] * n2[1];
|
|
tmp[2] += n2[2] * n2[2];
|
|
tmp[3] += n2[3] * n2[3];
|
|
|
|
tmp[0] = idMath::RSqrt( tmp[0] );
|
|
tmp[1] = idMath::RSqrt( tmp[1] );
|
|
tmp[2] = idMath::RSqrt( tmp[2] );
|
|
tmp[3] = idMath::RSqrt( tmp[3] );
|
|
|
|
n0[0] *= tmp[0];
|
|
n0[1] *= tmp[1];
|
|
n0[2] *= tmp[2];
|
|
n0[3] *= tmp[3];
|
|
|
|
n1[0] *= tmp[0];
|
|
n1[1] *= tmp[1];
|
|
n1[2] *= tmp[2];
|
|
n1[3] *= tmp[3];
|
|
|
|
n2[0] *= tmp[0];
|
|
n2[1] *= tmp[1];
|
|
n2[2] *= tmp[2];
|
|
n2[3] *= tmp[3];
|
|
|
|
|
|
for ( j = 0; j < 4; j++ ) {
|
|
const idDrawVert *a;
|
|
|
|
a = verts + indexes[i + j * 3];
|
|
|
|
planes->Normal()[0] = n0[j];
|
|
planes->Normal()[1] = n1[j];
|
|
planes->Normal()[2] = n2[j];
|
|
planes->FitThroughPoint( a->xyz );
|
|
planes++;
|
|
}
|
|
}
|
|
|
|
for ( ; i < numIndexes; i += 3 ) {
|
|
const idDrawVert *a, *b, *c;
|
|
float d0, d1, d2, d3, d4, d5;
|
|
float n0, n1, n2;
|
|
|
|
a = verts + indexes[i + 0];
|
|
b = verts + indexes[i + 1];
|
|
c = verts + indexes[i + 2];
|
|
|
|
d0 = b->xyz[0] - a->xyz[0];
|
|
d1 = b->xyz[1] - a->xyz[1];
|
|
d2 = b->xyz[2] - a->xyz[2];
|
|
|
|
d3 = c->xyz[0] - a->xyz[0];
|
|
d4 = c->xyz[1] - a->xyz[1];
|
|
d5 = c->xyz[2] - a->xyz[2];
|
|
|
|
float tmp;
|
|
|
|
n0 = d4 * d2 - d5 * d1;
|
|
n1 = d5 * d0 - d3 * d2;
|
|
n2 = d3 * d1 - d4 * d0;
|
|
|
|
tmp = idMath::RSqrt( n0 * n0 + n1 * n1 + n2 * n2 );
|
|
|
|
n0 *= tmp;
|
|
n1 *= tmp;
|
|
n2 *= tmp;
|
|
|
|
planes->Normal()[0] = n0;
|
|
planes->Normal()[1] = n1;
|
|
planes->Normal()[2] = n2;
|
|
planes->FitThroughPoint( a->xyz );
|
|
planes++;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::DeriveTangents
|
|
============
|
|
*/
|
|
//#define REFINE_TANGENT_SQUAREROOT
|
|
#define FIX_DEGENERATE_TANGENT
|
|
|
|
void VPCALL idSIMD_SSE::DeriveTangents( idPlane *planes, idDrawVert *verts, const int numVerts, const int *indexes, const int numIndexes ) {
|
|
int i;
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->normal == DRAWVERT_NORMAL_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[0] == DRAWVERT_TANGENT0_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[1] == DRAWVERT_TANGENT1_OFFSET );
|
|
|
|
assert( planes != NULL );
|
|
assert( verts != NULL );
|
|
assert( numVerts >= 0 );
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
__asm {
|
|
movaps xmm6, SIMD_SP_rsqrt_c0
|
|
movaps xmm7, SIMD_SP_rsqrt_c1
|
|
}
|
|
#endif
|
|
|
|
bool *used = (bool *)_alloca16( numVerts * sizeof( used[0] ) );
|
|
memset( used, 0, numVerts * sizeof( used[0] ) );
|
|
|
|
for ( i = 0; i <= numIndexes - 12; i += 12 ) {
|
|
idDrawVert *a, *b, *c;
|
|
ALIGN16( unsigned int signBit[4] );
|
|
ALIGN16( float d0[4] );
|
|
ALIGN16( float d1[4] );
|
|
ALIGN16( float d2[4] );
|
|
ALIGN16( float d3[4] );
|
|
ALIGN16( float d4[4] );
|
|
ALIGN16( float d5[4] );
|
|
ALIGN16( float d6[4] );
|
|
ALIGN16( float d7[4] );
|
|
ALIGN16( float d8[4] );
|
|
ALIGN16( float d9[4] );
|
|
ALIGN16( float n0[4] );
|
|
ALIGN16( float n1[4] );
|
|
ALIGN16( float n2[4] );
|
|
ALIGN16( float t0[4] );
|
|
ALIGN16( float t1[4] );
|
|
ALIGN16( float t2[4] );
|
|
ALIGN16( float t3[4] );
|
|
ALIGN16( float t4[4] );
|
|
ALIGN16( float t5[4] );
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
|
|
a = verts + indexes[i + j * 3 + 0];
|
|
b = verts + indexes[i + j * 3 + 1];
|
|
c = verts + indexes[i + j * 3 + 2];
|
|
|
|
d0[j] = b->xyz[0] - a->xyz[0];
|
|
d1[j] = b->xyz[1] - a->xyz[1];
|
|
d2[j] = b->xyz[2] - a->xyz[2];
|
|
d3[j] = b->st[0] - a->st[0];
|
|
d4[j] = b->st[1] - a->st[1];
|
|
|
|
d5[j] = c->xyz[0] - a->xyz[0];
|
|
d6[j] = c->xyz[1] - a->xyz[1];
|
|
d7[j] = c->xyz[2] - a->xyz[2];
|
|
d8[j] = c->st[0] - a->st[0];
|
|
d9[j] = c->st[1] - a->st[1];
|
|
}
|
|
|
|
#if 1
|
|
|
|
__asm {
|
|
// normal
|
|
movaps xmm0, d6
|
|
mulps xmm0, d2
|
|
movaps xmm1, d7
|
|
mulps xmm1, d1
|
|
subps xmm0, xmm1
|
|
|
|
movaps xmm1, d7
|
|
mulps xmm1, d0
|
|
movaps xmm2, d5
|
|
mulps xmm2, d2
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm2, d5
|
|
mulps xmm2, d1
|
|
movaps xmm3, d6
|
|
mulps xmm3, d0
|
|
subps xmm2, xmm3
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
mulps xmm0, xmm3
|
|
movaps n0, xmm0
|
|
mulps xmm1, xmm3
|
|
movaps n1, xmm1
|
|
mulps xmm2, xmm3
|
|
movaps n2, xmm2
|
|
|
|
// area sign bit
|
|
movaps xmm0, d3
|
|
mulps xmm0, d9
|
|
movaps xmm1, d4
|
|
mulps xmm1, d8
|
|
subps xmm0, xmm1
|
|
andps xmm0, SIMD_SP_signBitMask
|
|
movaps signBit, xmm0
|
|
|
|
// first tangent
|
|
movaps xmm0, d0
|
|
mulps xmm0, d9
|
|
movaps xmm1, d4
|
|
mulps xmm1, d5
|
|
subps xmm0, xmm1
|
|
|
|
movaps xmm1, d1
|
|
mulps xmm1, d9
|
|
movaps xmm2, d4
|
|
mulps xmm2, d6
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm2, d2
|
|
mulps xmm2, d9
|
|
movaps xmm3, d4
|
|
mulps xmm3, d7
|
|
subps xmm2, xmm3
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
xorps xmm3, signBit
|
|
|
|
mulps xmm0, xmm3
|
|
movaps t0, xmm0
|
|
mulps xmm1, xmm3
|
|
movaps t1, xmm1
|
|
mulps xmm2, xmm3
|
|
movaps t2, xmm2
|
|
|
|
// second tangent
|
|
movaps xmm0, d3
|
|
mulps xmm0, d5
|
|
movaps xmm1, d0
|
|
mulps xmm1, d8
|
|
subps xmm0, xmm1
|
|
|
|
movaps xmm1, d3
|
|
mulps xmm1, d6
|
|
movaps xmm2, d1
|
|
mulps xmm2, d8
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm2, d3
|
|
mulps xmm2, d7
|
|
movaps xmm3, d2
|
|
mulps xmm3, d8
|
|
subps xmm2, xmm3
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
xorps xmm3, signBit
|
|
|
|
mulps xmm0, xmm3
|
|
movaps t3, xmm0
|
|
mulps xmm1, xmm3
|
|
movaps t4, xmm1
|
|
mulps xmm2, xmm3
|
|
movaps t5, xmm2
|
|
}
|
|
|
|
#else
|
|
|
|
ALIGN16( float tmp[4] );
|
|
|
|
// normal
|
|
n0[0] = d6[0] * d2[0];
|
|
n0[1] = d6[1] * d2[1];
|
|
n0[2] = d6[2] * d2[2];
|
|
n0[3] = d6[3] * d2[3];
|
|
|
|
n0[0] -= d7[0] * d1[0];
|
|
n0[1] -= d7[1] * d1[1];
|
|
n0[2] -= d7[2] * d1[2];
|
|
n0[3] -= d7[3] * d1[3];
|
|
|
|
n1[0] = d7[0] * d0[0];
|
|
n1[1] = d7[1] * d0[1];
|
|
n1[2] = d7[2] * d0[2];
|
|
n1[3] = d7[3] * d0[3];
|
|
|
|
n1[0] -= d5[0] * d2[0];
|
|
n1[1] -= d5[1] * d2[1];
|
|
n1[2] -= d5[2] * d2[2];
|
|
n1[3] -= d5[3] * d2[3];
|
|
|
|
n2[0] = d5[0] * d1[0];
|
|
n2[1] = d5[1] * d1[1];
|
|
n2[2] = d5[2] * d1[2];
|
|
n2[3] = d5[3] * d1[3];
|
|
|
|
n2[0] -= d6[0] * d0[0];
|
|
n2[1] -= d6[1] * d0[1];
|
|
n2[2] -= d6[2] * d0[2];
|
|
n2[3] -= d6[3] * d0[3];
|
|
|
|
tmp[0] = n0[0] * n0[0];
|
|
tmp[1] = n0[1] * n0[1];
|
|
tmp[2] = n0[2] * n0[2];
|
|
tmp[3] = n0[3] * n0[3];
|
|
|
|
tmp[0] += n1[0] * n1[0];
|
|
tmp[1] += n1[1] * n1[1];
|
|
tmp[2] += n1[2] * n1[2];
|
|
tmp[3] += n1[3] * n1[3];
|
|
|
|
tmp[0] += n2[0] * n2[0];
|
|
tmp[1] += n2[1] * n2[1];
|
|
tmp[2] += n2[2] * n2[2];
|
|
tmp[3] += n2[3] * n2[3];
|
|
|
|
tmp[0] = idMath::RSqrt( tmp[0] );
|
|
tmp[1] = idMath::RSqrt( tmp[1] );
|
|
tmp[2] = idMath::RSqrt( tmp[2] );
|
|
tmp[3] = idMath::RSqrt( tmp[3] );
|
|
|
|
n0[0] *= tmp[0];
|
|
n0[1] *= tmp[1];
|
|
n0[2] *= tmp[2];
|
|
n0[3] *= tmp[3];
|
|
|
|
n1[0] *= tmp[0];
|
|
n1[1] *= tmp[1];
|
|
n1[2] *= tmp[2];
|
|
n1[3] *= tmp[3];
|
|
|
|
n2[0] *= tmp[0];
|
|
n2[1] *= tmp[1];
|
|
n2[2] *= tmp[2];
|
|
n2[3] *= tmp[3];
|
|
|
|
// area sign bit
|
|
tmp[0] = d3[0] * d9[0];
|
|
tmp[1] = d3[1] * d9[1];
|
|
tmp[2] = d3[2] * d9[2];
|
|
tmp[3] = d3[3] * d9[3];
|
|
|
|
tmp[0] -= d4[0] * d8[0];
|
|
tmp[1] -= d4[1] * d8[1];
|
|
tmp[2] -= d4[2] * d8[2];
|
|
tmp[3] -= d4[3] * d8[3];
|
|
|
|
signBit[0] = ( *(unsigned int *)&tmp[0] ) & ( 1 << 31 );
|
|
signBit[1] = ( *(unsigned int *)&tmp[1] ) & ( 1 << 31 );
|
|
signBit[2] = ( *(unsigned int *)&tmp[2] ) & ( 1 << 31 );
|
|
signBit[3] = ( *(unsigned int *)&tmp[3] ) & ( 1 << 31 );
|
|
|
|
// first tangent
|
|
t0[0] = d0[0] * d9[0];
|
|
t0[1] = d0[1] * d9[1];
|
|
t0[2] = d0[2] * d9[2];
|
|
t0[3] = d0[3] * d9[3];
|
|
|
|
t0[0] -= d4[0] * d5[0];
|
|
t0[1] -= d4[1] * d5[1];
|
|
t0[2] -= d4[2] * d5[2];
|
|
t0[3] -= d4[3] * d5[3];
|
|
|
|
t1[0] = d1[0] * d9[0];
|
|
t1[1] = d1[1] * d9[1];
|
|
t1[2] = d1[2] * d9[2];
|
|
t1[3] = d1[3] * d9[3];
|
|
|
|
t1[0] -= d4[0] * d6[0];
|
|
t1[1] -= d4[1] * d6[1];
|
|
t1[2] -= d4[2] * d6[2];
|
|
t1[3] -= d4[3] * d6[3];
|
|
|
|
t2[0] = d2[0] * d9[0];
|
|
t2[1] = d2[1] * d9[1];
|
|
t2[2] = d2[2] * d9[2];
|
|
t2[3] = d2[3] * d9[3];
|
|
|
|
t2[0] -= d4[0] * d7[0];
|
|
t2[1] -= d4[1] * d7[1];
|
|
t2[2] -= d4[2] * d7[2];
|
|
t2[3] -= d4[3] * d7[3];
|
|
|
|
tmp[0] = t0[0] * t0[0];
|
|
tmp[1] = t0[1] * t0[1];
|
|
tmp[2] = t0[2] * t0[2];
|
|
tmp[3] = t0[3] * t0[3];
|
|
|
|
tmp[0] += t1[0] * t1[0];
|
|
tmp[1] += t1[1] * t1[1];
|
|
tmp[2] += t1[2] * t1[2];
|
|
tmp[3] += t1[3] * t1[3];
|
|
|
|
tmp[0] += t2[0] * t2[0];
|
|
tmp[1] += t2[1] * t2[1];
|
|
tmp[2] += t2[2] * t2[2];
|
|
tmp[3] += t2[3] * t2[3];
|
|
|
|
tmp[0] = idMath::RSqrt( tmp[0] );
|
|
tmp[1] = idMath::RSqrt( tmp[1] );
|
|
tmp[2] = idMath::RSqrt( tmp[2] );
|
|
tmp[3] = idMath::RSqrt( tmp[3] );
|
|
|
|
*(unsigned int *)&tmp[0] ^= signBit[0];
|
|
*(unsigned int *)&tmp[1] ^= signBit[1];
|
|
*(unsigned int *)&tmp[2] ^= signBit[2];
|
|
*(unsigned int *)&tmp[3] ^= signBit[3];
|
|
|
|
t0[0] *= tmp[0];
|
|
t0[1] *= tmp[1];
|
|
t0[2] *= tmp[2];
|
|
t0[3] *= tmp[3];
|
|
|
|
t1[0] *= tmp[0];
|
|
t1[1] *= tmp[1];
|
|
t1[2] *= tmp[2];
|
|
t1[3] *= tmp[3];
|
|
|
|
t2[0] *= tmp[0];
|
|
t2[1] *= tmp[1];
|
|
t2[2] *= tmp[2];
|
|
t2[3] *= tmp[3];
|
|
|
|
// second tangent
|
|
t3[0] = d3[0] * d5[0];
|
|
t3[1] = d3[1] * d5[1];
|
|
t3[2] = d3[2] * d5[2];
|
|
t3[3] = d3[3] * d5[3];
|
|
|
|
t3[0] -= d0[0] * d8[0];
|
|
t3[1] -= d0[1] * d8[1];
|
|
t3[2] -= d0[2] * d8[2];
|
|
t3[3] -= d0[3] * d8[3];
|
|
|
|
t4[0] = d3[0] * d6[0];
|
|
t4[1] = d3[1] * d6[1];
|
|
t4[2] = d3[2] * d6[2];
|
|
t4[3] = d3[3] * d6[3];
|
|
|
|
t4[0] -= d1[0] * d8[0];
|
|
t4[1] -= d1[1] * d8[1];
|
|
t4[2] -= d1[2] * d8[2];
|
|
t4[3] -= d1[3] * d8[3];
|
|
|
|
t5[0] = d3[0] * d7[0];
|
|
t5[1] = d3[1] * d7[1];
|
|
t5[2] = d3[2] * d7[2];
|
|
t5[3] = d3[3] * d7[3];
|
|
|
|
t5[0] -= d2[0] * d8[0];
|
|
t5[1] -= d2[1] * d8[1];
|
|
t5[2] -= d2[2] * d8[2];
|
|
t5[3] -= d2[3] * d8[3];
|
|
|
|
tmp[0] = t3[0] * t3[0];
|
|
tmp[1] = t3[1] * t3[1];
|
|
tmp[2] = t3[2] * t3[2];
|
|
tmp[3] = t3[3] * t3[3];
|
|
|
|
tmp[0] += t4[0] * t4[0];
|
|
tmp[1] += t4[1] * t4[1];
|
|
tmp[2] += t4[2] * t4[2];
|
|
tmp[3] += t4[3] * t4[3];
|
|
|
|
tmp[0] += t5[0] * t5[0];
|
|
tmp[1] += t5[1] * t5[1];
|
|
tmp[2] += t5[2] * t5[2];
|
|
tmp[3] += t5[3] * t5[3];
|
|
|
|
tmp[0] = idMath::RSqrt( tmp[0] );
|
|
tmp[1] = idMath::RSqrt( tmp[1] );
|
|
tmp[2] = idMath::RSqrt( tmp[2] );
|
|
tmp[3] = idMath::RSqrt( tmp[3] );
|
|
|
|
*(unsigned int *)&tmp[0] ^= signBit[0];
|
|
*(unsigned int *)&tmp[1] ^= signBit[1];
|
|
*(unsigned int *)&tmp[2] ^= signBit[2];
|
|
*(unsigned int *)&tmp[3] ^= signBit[3];
|
|
|
|
t3[0] *= tmp[0];
|
|
t3[1] *= tmp[1];
|
|
t3[2] *= tmp[2];
|
|
t3[3] *= tmp[3];
|
|
|
|
t4[0] *= tmp[0];
|
|
t4[1] *= tmp[1];
|
|
t4[2] *= tmp[2];
|
|
t4[3] *= tmp[3];
|
|
|
|
t5[0] *= tmp[0];
|
|
t5[1] *= tmp[1];
|
|
t5[2] *= tmp[2];
|
|
t5[3] *= tmp[3];
|
|
|
|
#endif
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
|
|
const int v0 = indexes[i + j * 3 + 0];
|
|
const int v1 = indexes[i + j * 3 + 1];
|
|
const int v2 = indexes[i + j * 3 + 2];
|
|
|
|
a = verts + v0;
|
|
b = verts + v1;
|
|
c = verts + v2;
|
|
|
|
planes->Normal()[0] = n0[j];
|
|
planes->Normal()[1] = n1[j];
|
|
planes->Normal()[2] = n2[j];
|
|
planes->FitThroughPoint( a->xyz );
|
|
planes++;
|
|
|
|
if ( used[v0] ) {
|
|
a->normal[0] += n0[j];
|
|
a->normal[1] += n1[j];
|
|
a->normal[2] += n2[j];
|
|
|
|
a->tangents[0][0] += t0[j];
|
|
a->tangents[0][1] += t1[j];
|
|
a->tangents[0][2] += t2[j];
|
|
|
|
a->tangents[1][0] += t3[j];
|
|
a->tangents[1][1] += t4[j];
|
|
a->tangents[1][2] += t5[j];
|
|
} else {
|
|
a->normal[0] = n0[j];
|
|
a->normal[1] = n1[j];
|
|
a->normal[2] = n2[j];
|
|
|
|
a->tangents[0][0] = t0[j];
|
|
a->tangents[0][1] = t1[j];
|
|
a->tangents[0][2] = t2[j];
|
|
|
|
a->tangents[1][0] = t3[j];
|
|
a->tangents[1][1] = t4[j];
|
|
a->tangents[1][2] = t5[j];
|
|
|
|
used[v0] = true;
|
|
}
|
|
|
|
if ( used[v1] ) {
|
|
b->normal[0] += n0[j];
|
|
b->normal[1] += n1[j];
|
|
b->normal[2] += n2[j];
|
|
|
|
b->tangents[0][0] += t0[j];
|
|
b->tangents[0][1] += t1[j];
|
|
b->tangents[0][2] += t2[j];
|
|
|
|
b->tangents[1][0] += t3[j];
|
|
b->tangents[1][1] += t4[j];
|
|
b->tangents[1][2] += t5[j];
|
|
} else {
|
|
b->normal[0] = n0[j];
|
|
b->normal[1] = n1[j];
|
|
b->normal[2] = n2[j];
|
|
|
|
b->tangents[0][0] = t0[j];
|
|
b->tangents[0][1] = t1[j];
|
|
b->tangents[0][2] = t2[j];
|
|
|
|
b->tangents[1][0] = t3[j];
|
|
b->tangents[1][1] = t4[j];
|
|
b->tangents[1][2] = t5[j];
|
|
|
|
used[v1] = true;
|
|
}
|
|
|
|
if ( used[v2] ) {
|
|
c->normal[0] += n0[j];
|
|
c->normal[1] += n1[j];
|
|
c->normal[2] += n2[j];
|
|
|
|
c->tangents[0][0] += t0[j];
|
|
c->tangents[0][1] += t1[j];
|
|
c->tangents[0][2] += t2[j];
|
|
|
|
c->tangents[1][0] += t3[j];
|
|
c->tangents[1][1] += t4[j];
|
|
c->tangents[1][2] += t5[j];
|
|
} else {
|
|
c->normal[0] = n0[j];
|
|
c->normal[1] = n1[j];
|
|
c->normal[2] = n2[j];
|
|
|
|
c->tangents[0][0] = t0[j];
|
|
c->tangents[0][1] = t1[j];
|
|
c->tangents[0][2] = t2[j];
|
|
|
|
c->tangents[1][0] = t3[j];
|
|
c->tangents[1][1] = t4[j];
|
|
c->tangents[1][2] = t5[j];
|
|
|
|
used[v2] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( ; i < numIndexes; i += 3 ) {
|
|
idDrawVert *a, *b, *c;
|
|
ALIGN16( unsigned int signBit[4] );
|
|
float d0, d1, d2, d3, d4;
|
|
float d5, d6, d7, d8, d9;
|
|
float n0, n1, n2;
|
|
float t0, t1, t2;
|
|
float t3, t4, t5;
|
|
|
|
const int v0 = indexes[i + 0];
|
|
const int v1 = indexes[i + 1];
|
|
const int v2 = indexes[i + 2];
|
|
|
|
a = verts + v0;
|
|
b = verts + v1;
|
|
c = verts + v2;
|
|
|
|
d0 = b->xyz[0] - a->xyz[0];
|
|
d1 = b->xyz[1] - a->xyz[1];
|
|
d2 = b->xyz[2] - a->xyz[2];
|
|
d3 = b->st[0] - a->st[0];
|
|
d4 = b->st[1] - a->st[1];
|
|
|
|
d5 = c->xyz[0] - a->xyz[0];
|
|
d6 = c->xyz[1] - a->xyz[1];
|
|
d7 = c->xyz[2] - a->xyz[2];
|
|
d8 = c->st[0] - a->st[0];
|
|
d9 = c->st[1] - a->st[1];
|
|
|
|
#if 1
|
|
|
|
__asm {
|
|
// normal
|
|
movss xmm0, d6
|
|
mulss xmm0, d2
|
|
movss xmm1, d7
|
|
mulss xmm1, d1
|
|
subss xmm0, xmm1
|
|
|
|
movss xmm1, d7
|
|
mulss xmm1, d0
|
|
movss xmm2, d5
|
|
mulss xmm2, d2
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm2, d5
|
|
mulss xmm2, d1
|
|
movss xmm3, d6
|
|
mulss xmm3, d0
|
|
subss xmm2, xmm3
|
|
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
mulss xmm0, xmm3
|
|
movss n0, xmm0
|
|
mulss xmm1, xmm3
|
|
movss n1, xmm1
|
|
mulss xmm2, xmm3
|
|
movss n2, xmm2
|
|
|
|
// area sign bit
|
|
movss xmm0, d3
|
|
mulss xmm0, d9
|
|
movss xmm1, d4
|
|
mulss xmm1, d8
|
|
subss xmm0, xmm1
|
|
andps xmm0, SIMD_SP_signBitMask
|
|
movaps signBit, xmm0
|
|
|
|
// first tangent
|
|
movss xmm0, d0
|
|
mulss xmm0, d9
|
|
movss xmm1, d4
|
|
mulss xmm1, d5
|
|
subss xmm0, xmm1
|
|
|
|
movss xmm1, d1
|
|
mulss xmm1, d9
|
|
movss xmm2, d4
|
|
mulss xmm2, d6
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm2, d2
|
|
mulss xmm2, d9
|
|
movss xmm3, d4
|
|
mulss xmm3, d7
|
|
subss xmm2, xmm3
|
|
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
xorps xmm3, signBit
|
|
|
|
mulss xmm0, xmm3
|
|
movss t0, xmm0
|
|
mulss xmm1, xmm3
|
|
movss t1, xmm1
|
|
mulss xmm2, xmm3
|
|
movss t2, xmm2
|
|
|
|
// second tangent
|
|
movss xmm0, d3
|
|
mulss xmm0, d5
|
|
movss xmm1, d0
|
|
mulss xmm1, d8
|
|
subss xmm0, xmm1
|
|
|
|
movss xmm1, d3
|
|
mulss xmm1, d6
|
|
movss xmm2, d1
|
|
mulss xmm2, d8
|
|
subss xmm1, xmm2
|
|
|
|
movss xmm2, d3
|
|
mulss xmm2, d7
|
|
movss xmm3, d2
|
|
mulss xmm3, d8
|
|
subss xmm2, xmm3
|
|
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef FIX_DEGENERATE_TANGENT
|
|
xorps xmm4, xmm4
|
|
cmpeqps xmm4, xmm3
|
|
andps xmm4, SIMD_SP_tiny // if values are zero replace them with a tiny number
|
|
andps xmm3, SIMD_SP_absMask // make sure the values are positive
|
|
orps xmm3, xmm4
|
|
#endif
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
xorps xmm3, signBit
|
|
|
|
mulss xmm0, xmm3
|
|
movss t3, xmm0
|
|
mulss xmm1, xmm3
|
|
movss t4, xmm1
|
|
mulss xmm2, xmm3
|
|
movss t5, xmm2
|
|
}
|
|
|
|
#else
|
|
|
|
float tmp;
|
|
|
|
// normal
|
|
n0 = d6 * d2 - d7 * d1;
|
|
n1 = d7 * d0 - d5 * d2;
|
|
n2 = d5 * d1 - d6 * d0;
|
|
|
|
tmp = idMath::RSqrt( n0 * n0 + n1 * n1 + n2 * n2 );
|
|
|
|
n0 *= tmp;
|
|
n1 *= tmp;
|
|
n2 *= tmp;
|
|
|
|
// area sign bit
|
|
tmp = d3 * d9 - d4 * d8;
|
|
signBit[0] = ( *(unsigned int *)&tmp ) & ( 1 << 31 );
|
|
|
|
// first tangent
|
|
t0 = d0 * d9 - d4 * d5;
|
|
t1 = d1 * d9 - d4 * d6;
|
|
t2 = d2 * d9 - d4 * d7;
|
|
|
|
tmp = idMath::RSqrt( t0 * t0 + t1 * t1 + t2 * t2 );
|
|
*(unsigned int *)&tmp ^= signBit[0];
|
|
|
|
t0 *= tmp;
|
|
t1 *= tmp;
|
|
t2 *= tmp;
|
|
|
|
// second tangent
|
|
t3 = d3 * d5 - d0 * d8;
|
|
t4 = d3 * d6 - d1 * d8;
|
|
t5 = d3 * d7 - d2 * d8;
|
|
|
|
tmp = idMath::RSqrt( t3 * t3 + t4 * t4 + t5 * t5 );
|
|
*(unsigned int *)&tmp ^= signBit[0];
|
|
|
|
t3 *= tmp;
|
|
t4 *= tmp;
|
|
t5 *= tmp;
|
|
|
|
#endif
|
|
|
|
planes->Normal()[0] = n0;
|
|
planes->Normal()[1] = n1;
|
|
planes->Normal()[2] = n2;
|
|
planes->FitThroughPoint( a->xyz );
|
|
planes++;
|
|
|
|
if ( used[v0] ) {
|
|
a->normal[0] += n0;
|
|
a->normal[1] += n1;
|
|
a->normal[2] += n2;
|
|
|
|
a->tangents[0][0] += t0;
|
|
a->tangents[0][1] += t1;
|
|
a->tangents[0][2] += t2;
|
|
|
|
a->tangents[1][0] += t3;
|
|
a->tangents[1][1] += t4;
|
|
a->tangents[1][2] += t5;
|
|
} else {
|
|
a->normal[0] = n0;
|
|
a->normal[1] = n1;
|
|
a->normal[2] = n2;
|
|
|
|
a->tangents[0][0] = t0;
|
|
a->tangents[0][1] = t1;
|
|
a->tangents[0][2] = t2;
|
|
|
|
a->tangents[1][0] = t3;
|
|
a->tangents[1][1] = t4;
|
|
a->tangents[1][2] = t5;
|
|
|
|
used[v0] = true;
|
|
}
|
|
|
|
if ( used[v1] ) {
|
|
b->normal[0] += n0;
|
|
b->normal[1] += n1;
|
|
b->normal[2] += n2;
|
|
|
|
b->tangents[0][0] += t0;
|
|
b->tangents[0][1] += t1;
|
|
b->tangents[0][2] += t2;
|
|
|
|
b->tangents[1][0] += t3;
|
|
b->tangents[1][1] += t4;
|
|
b->tangents[1][2] += t5;
|
|
} else {
|
|
b->normal[0] = n0;
|
|
b->normal[1] = n1;
|
|
b->normal[2] = n2;
|
|
|
|
b->tangents[0][0] = t0;
|
|
b->tangents[0][1] = t1;
|
|
b->tangents[0][2] = t2;
|
|
|
|
b->tangents[1][0] = t3;
|
|
b->tangents[1][1] = t4;
|
|
b->tangents[1][2] = t5;
|
|
|
|
used[v1] = true;
|
|
}
|
|
|
|
if ( used[v2] ) {
|
|
c->normal[0] += n0;
|
|
c->normal[1] += n1;
|
|
c->normal[2] += n2;
|
|
|
|
c->tangents[0][0] += t0;
|
|
c->tangents[0][1] += t1;
|
|
c->tangents[0][2] += t2;
|
|
|
|
c->tangents[1][0] += t3;
|
|
c->tangents[1][1] += t4;
|
|
c->tangents[1][2] += t5;
|
|
} else {
|
|
c->normal[0] = n0;
|
|
c->normal[1] = n1;
|
|
c->normal[2] = n2;
|
|
|
|
c->tangents[0][0] = t0;
|
|
c->tangents[0][1] = t1;
|
|
c->tangents[0][2] = t2;
|
|
|
|
c->tangents[1][0] = t3;
|
|
c->tangents[1][1] = t4;
|
|
c->tangents[1][2] = t5;
|
|
|
|
used[v2] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::DeriveUnsmoothedTangents
|
|
============
|
|
*/
|
|
#define DERIVE_UNSMOOTHED_BITANGENT
|
|
|
|
void VPCALL idSIMD_SSE::DeriveUnsmoothedTangents( idDrawVert *verts, const dominantTri_s *dominantTris, const int numVerts ) {
|
|
int i, j;
|
|
|
|
for ( i = 0; i <= numVerts - 4; i += 4 ) {
|
|
ALIGN16( float s0[4] );
|
|
ALIGN16( float s1[4] );
|
|
ALIGN16( float s2[4] );
|
|
ALIGN16( float d0[4] );
|
|
ALIGN16( float d1[4] );
|
|
ALIGN16( float d2[4] );
|
|
ALIGN16( float d3[4] );
|
|
ALIGN16( float d4[4] );
|
|
ALIGN16( float d5[4] );
|
|
ALIGN16( float d6[4] );
|
|
ALIGN16( float d7[4] );
|
|
ALIGN16( float d8[4] );
|
|
ALIGN16( float d9[4] );
|
|
ALIGN16( float n0[4] );
|
|
ALIGN16( float n1[4] );
|
|
ALIGN16( float n2[4] );
|
|
ALIGN16( float t0[4] );
|
|
ALIGN16( float t1[4] );
|
|
ALIGN16( float t2[4] );
|
|
ALIGN16( float t3[4] );
|
|
ALIGN16( float t4[4] );
|
|
ALIGN16( float t5[4] );
|
|
|
|
for ( j = 0; j < 4; j++ ) {
|
|
const idDrawVert *a, *b, *c;
|
|
|
|
const dominantTri_s &dt = dominantTris[i+j];
|
|
|
|
s0[j] = dt.normalizationScale[0];
|
|
s1[j] = dt.normalizationScale[1];
|
|
s2[j] = dt.normalizationScale[2];
|
|
|
|
a = verts + i + j;
|
|
b = verts + dt.v2;
|
|
c = verts + dt.v3;
|
|
|
|
d0[j] = b->xyz[0] - a->xyz[0];
|
|
d1[j] = b->xyz[1] - a->xyz[1];
|
|
d2[j] = b->xyz[2] - a->xyz[2];
|
|
d3[j] = b->st[0] - a->st[0];
|
|
d4[j] = b->st[1] - a->st[1];
|
|
|
|
d5[j] = c->xyz[0] - a->xyz[0];
|
|
d6[j] = c->xyz[1] - a->xyz[1];
|
|
d7[j] = c->xyz[2] - a->xyz[2];
|
|
d8[j] = c->st[0] - a->st[0];
|
|
d9[j] = c->st[1] - a->st[1];
|
|
}
|
|
|
|
#if 1
|
|
|
|
__asm {
|
|
|
|
movaps xmm0, d6
|
|
mulps xmm0, d2
|
|
movaps xmm1, d7
|
|
mulps xmm1, d1
|
|
|
|
movaps xmm2, d7
|
|
mulps xmm2, d0
|
|
movaps xmm3, d5
|
|
mulps xmm3, d2
|
|
|
|
movaps xmm4, d5
|
|
mulps xmm4, d1
|
|
movaps xmm5, d6
|
|
mulps xmm5, d0
|
|
|
|
subps xmm0, xmm1
|
|
subps xmm2, xmm3
|
|
movaps xmm7, s2
|
|
subps xmm4, xmm5
|
|
|
|
mulps xmm0, xmm7
|
|
movaps n0, xmm0
|
|
mulps xmm2, xmm7
|
|
movaps n1, xmm2
|
|
mulps xmm4, xmm7
|
|
movaps n2, xmm4
|
|
|
|
movaps xmm0, d0
|
|
mulps xmm0, d9
|
|
movaps xmm1, d4
|
|
mulps xmm1, d5
|
|
|
|
movaps xmm2, d1
|
|
mulps xmm2, d9
|
|
movaps xmm3, d4
|
|
mulps xmm3, d6
|
|
|
|
movaps xmm4, d2
|
|
mulps xmm4, d9
|
|
movaps xmm5, d4
|
|
mulps xmm5, d7
|
|
|
|
subps xmm0, xmm1
|
|
subps xmm2, xmm3
|
|
movaps xmm7, s0
|
|
subps xmm4, xmm5
|
|
|
|
mulps xmm0, xmm7
|
|
movaps t0, xmm0
|
|
mulps xmm2, xmm7
|
|
movaps t1, xmm2
|
|
mulps xmm4, xmm7
|
|
movaps t2, xmm4
|
|
|
|
#ifndef DERIVE_UNSMOOTHED_BITANGENT
|
|
movaps xmm0, d3
|
|
mulps xmm0, d5
|
|
movaps xmm1, d0
|
|
mulps xmm1, d8
|
|
|
|
movaps xmm2, d3
|
|
mulps xmm2, d6
|
|
movaps xmm3, d1
|
|
mulps xmm3, d8
|
|
|
|
movaps xmm4, d3
|
|
mulps xmm4, d7
|
|
movaps xmm5, d2
|
|
mulps xmm5, d8
|
|
#else
|
|
movaps xmm0, n2
|
|
mulps xmm0, t1
|
|
movaps xmm1, n1
|
|
mulps xmm1, t2
|
|
|
|
movaps xmm2, n0
|
|
mulps xmm2, t2
|
|
movaps xmm3, n2
|
|
mulps xmm3, t0
|
|
|
|
movaps xmm4, n1
|
|
mulps xmm4, t0
|
|
movaps xmm5, n0
|
|
mulps xmm5, t1
|
|
#endif
|
|
subps xmm0, xmm1
|
|
subps xmm2, xmm3
|
|
movaps xmm7, s1
|
|
subps xmm4, xmm5
|
|
|
|
mulps xmm0, xmm7
|
|
movaps t3, xmm0
|
|
mulps xmm2, xmm7
|
|
movaps t4, xmm2
|
|
mulps xmm4, xmm7
|
|
movaps t5, xmm4
|
|
}
|
|
|
|
#else
|
|
|
|
n0[0] = d6[0] * d2[0];
|
|
n0[1] = d6[1] * d2[1];
|
|
n0[2] = d6[2] * d2[2];
|
|
n0[3] = d6[3] * d2[3];
|
|
|
|
n1[0] = d7[0] * d0[0];
|
|
n1[1] = d7[1] * d0[1];
|
|
n1[2] = d7[2] * d0[2];
|
|
n1[3] = d7[3] * d0[3];
|
|
|
|
n2[0] = d5[0] * d1[0];
|
|
n2[1] = d5[1] * d1[1];
|
|
n2[2] = d5[2] * d1[2];
|
|
n2[3] = d5[3] * d1[3];
|
|
|
|
n0[0] -= d7[0] * d1[0];
|
|
n0[1] -= d7[1] * d1[1];
|
|
n0[2] -= d7[2] * d1[2];
|
|
n0[3] -= d7[3] * d1[3];
|
|
|
|
n1[0] -= d5[0] * d2[0];
|
|
n1[1] -= d5[1] * d2[1];
|
|
n1[2] -= d5[2] * d2[2];
|
|
n1[3] -= d5[3] * d2[3];
|
|
|
|
n2[0] -= d6[0] * d0[0];
|
|
n2[1] -= d6[1] * d0[1];
|
|
n2[2] -= d6[2] * d0[2];
|
|
n2[3] -= d6[3] * d0[3];
|
|
|
|
n0[0] *= s2[0];
|
|
n0[1] *= s2[1];
|
|
n0[2] *= s2[2];
|
|
n0[3] *= s2[3];
|
|
|
|
n1[0] *= s2[0];
|
|
n1[1] *= s2[1];
|
|
n1[2] *= s2[2];
|
|
n1[3] *= s2[3];
|
|
|
|
n2[0] *= s2[0];
|
|
n2[1] *= s2[1];
|
|
n2[2] *= s2[2];
|
|
n2[3] *= s2[3];
|
|
|
|
t0[0] = d0[0] * d9[0];
|
|
t0[1] = d0[1] * d9[1];
|
|
t0[2] = d0[2] * d9[2];
|
|
t0[3] = d0[3] * d9[3];
|
|
|
|
t1[0] = d1[0] * d9[0];
|
|
t1[1] = d1[1] * d9[1];
|
|
t1[2] = d1[2] * d9[2];
|
|
t1[3] = d1[3] * d9[3];
|
|
|
|
t2[0] = d2[0] * d9[0];
|
|
t2[1] = d2[1] * d9[1];
|
|
t2[2] = d2[2] * d9[2];
|
|
t2[3] = d2[3] * d9[3];
|
|
|
|
t0[0] -= d4[0] * d5[0];
|
|
t0[1] -= d4[1] * d5[1];
|
|
t0[2] -= d4[2] * d5[2];
|
|
t0[3] -= d4[3] * d5[3];
|
|
|
|
t1[0] -= d4[0] * d6[0];
|
|
t1[1] -= d4[1] * d6[1];
|
|
t1[2] -= d4[2] * d6[2];
|
|
t1[3] -= d4[3] * d6[3];
|
|
|
|
t2[0] -= d4[0] * d7[0];
|
|
t2[1] -= d4[1] * d7[1];
|
|
t2[2] -= d4[2] * d7[2];
|
|
t2[3] -= d4[3] * d7[3];
|
|
|
|
t0[0] *= s0[0];
|
|
t0[1] *= s0[1];
|
|
t0[2] *= s0[2];
|
|
t0[3] *= s0[3];
|
|
|
|
t1[0] *= s0[0];
|
|
t1[1] *= s0[1];
|
|
t1[2] *= s0[2];
|
|
t1[3] *= s0[3];
|
|
|
|
t2[0] *= s0[0];
|
|
t2[1] *= s0[1];
|
|
t2[2] *= s0[2];
|
|
t2[3] *= s0[3];
|
|
|
|
#ifndef DERIVE_UNSMOOTHED_BITANGENT
|
|
t3[0] = d3[0] * d5[0];
|
|
t3[1] = d3[1] * d5[1];
|
|
t3[2] = d3[2] * d5[2];
|
|
t3[3] = d3[3] * d5[3];
|
|
|
|
t4[0] = d3[0] * d6[0];
|
|
t4[1] = d3[1] * d6[1];
|
|
t4[2] = d3[2] * d6[2];
|
|
t4[3] = d3[3] * d6[3];
|
|
|
|
t5[0] = d3[0] * d7[0];
|
|
t5[1] = d3[1] * d7[1];
|
|
t5[2] = d3[2] * d7[2];
|
|
t5[3] = d3[3] * d7[3];
|
|
|
|
t3[0] -= d0[0] * d8[0];
|
|
t3[1] -= d0[1] * d8[1];
|
|
t3[2] -= d0[2] * d8[2];
|
|
t3[3] -= d0[3] * d8[3];
|
|
|
|
t4[0] -= d1[0] * d8[0];
|
|
t4[1] -= d1[1] * d8[1];
|
|
t4[2] -= d1[2] * d8[2];
|
|
t4[3] -= d1[3] * d8[3];
|
|
|
|
t5[0] -= d2[0] * d8[0];
|
|
t5[1] -= d2[1] * d8[1];
|
|
t5[2] -= d2[2] * d8[2];
|
|
t5[3] -= d2[3] * d8[3];
|
|
#else
|
|
t3[0] = n2[0] * t1[0];
|
|
t3[1] = n2[1] * t1[1];
|
|
t3[2] = n2[2] * t1[2];
|
|
t3[3] = n2[3] * t1[3];
|
|
|
|
t4[0] = n0[0] * t2[0];
|
|
t4[1] = n0[1] * t2[1];
|
|
t4[2] = n0[2] * t2[2];
|
|
t4[3] = n0[3] * t2[3];
|
|
|
|
t5[0] = n1[0] * t0[0];
|
|
t5[1] = n1[1] * t0[1];
|
|
t5[2] = n1[2] * t0[2];
|
|
t5[3] = n1[3] * t0[3];
|
|
|
|
t3[0] -= n1[0] * t2[0];
|
|
t3[1] -= n1[1] * t2[1];
|
|
t3[2] -= n1[2] * t2[2];
|
|
t3[3] -= n1[3] * t2[3];
|
|
|
|
t4[0] -= n2[0] * t0[0];
|
|
t4[1] -= n2[1] * t0[1];
|
|
t4[2] -= n2[2] * t0[2];
|
|
t4[3] -= n2[3] * t0[3];
|
|
|
|
t5[0] -= n0[0] * t1[0];
|
|
t5[1] -= n0[1] * t1[1];
|
|
t5[2] -= n0[2] * t1[2];
|
|
t5[3] -= n0[3] * t1[3];
|
|
#endif
|
|
t3[0] *= s1[0];
|
|
t3[1] *= s1[1];
|
|
t3[2] *= s1[2];
|
|
t3[3] *= s1[3];
|
|
|
|
t4[0] *= s1[0];
|
|
t4[1] *= s1[1];
|
|
t4[2] *= s1[2];
|
|
t4[3] *= s1[3];
|
|
|
|
t5[0] *= s1[0];
|
|
t5[1] *= s1[1];
|
|
t5[2] *= s1[2];
|
|
t5[3] *= s1[3];
|
|
|
|
#endif
|
|
|
|
for ( j = 0; j < 4; j++ ) {
|
|
idDrawVert *a;
|
|
|
|
a = verts + i + j;
|
|
|
|
a->normal[0] = n0[j];
|
|
a->normal[1] = n1[j];
|
|
a->normal[2] = n2[j];
|
|
|
|
a->tangents[0][0] = t0[j];
|
|
a->tangents[0][1] = t1[j];
|
|
a->tangents[0][2] = t2[j];
|
|
|
|
a->tangents[1][0] = t3[j];
|
|
a->tangents[1][1] = t4[j];
|
|
a->tangents[1][2] = t5[j];
|
|
}
|
|
}
|
|
|
|
for ( ; i < numVerts; i++ ) {
|
|
idDrawVert *a, *b, *c;
|
|
float d0, d1, d2, d3, d4;
|
|
float d5, d6, d7, d8, d9;
|
|
float s0, s1, s2;
|
|
float n0, n1, n2;
|
|
float t0, t1, t2;
|
|
float t3, t4, t5;
|
|
|
|
const dominantTri_s &dt = dominantTris[i];
|
|
|
|
s0 = dt.normalizationScale[0];
|
|
s1 = dt.normalizationScale[1];
|
|
s2 = dt.normalizationScale[2];
|
|
|
|
a = verts + i;
|
|
b = verts + dt.v2;
|
|
c = verts + dt.v3;
|
|
|
|
d0 = b->xyz[0] - a->xyz[0];
|
|
d1 = b->xyz[1] - a->xyz[1];
|
|
d2 = b->xyz[2] - a->xyz[2];
|
|
d3 = b->st[0] - a->st[0];
|
|
d4 = b->st[1] - a->st[1];
|
|
|
|
d5 = c->xyz[0] - a->xyz[0];
|
|
d6 = c->xyz[1] - a->xyz[1];
|
|
d7 = c->xyz[2] - a->xyz[2];
|
|
d8 = c->st[0] - a->st[0];
|
|
d9 = c->st[1] - a->st[1];
|
|
|
|
#if 1
|
|
|
|
__asm {
|
|
|
|
movss xmm0, d6
|
|
mulss xmm0, d2
|
|
movss xmm1, d7
|
|
mulss xmm1, d1
|
|
|
|
movss xmm2, d7
|
|
mulss xmm2, d0
|
|
movss xmm3, d5
|
|
mulss xmm3, d2
|
|
|
|
movss xmm4, d5
|
|
mulss xmm4, d1
|
|
movss xmm5, d6
|
|
mulss xmm5, d0
|
|
|
|
subss xmm0, xmm1
|
|
subss xmm2, xmm3
|
|
movss xmm7, s2
|
|
subss xmm4, xmm5
|
|
|
|
mulss xmm0, xmm7
|
|
movss n0, xmm0
|
|
mulss xmm2, xmm7
|
|
movss n1, xmm2
|
|
mulss xmm4, xmm7
|
|
movss n2, xmm4
|
|
|
|
movss xmm0, d0
|
|
mulss xmm0, d9
|
|
movss xmm1, d4
|
|
mulss xmm1, d5
|
|
|
|
movss xmm2, d1
|
|
mulss xmm2, d9
|
|
movss xmm3, d4
|
|
mulss xmm3, d6
|
|
|
|
movss xmm4, d2
|
|
mulss xmm4, d9
|
|
movss xmm5, d4
|
|
mulss xmm5, d7
|
|
|
|
subss xmm0, xmm1
|
|
subss xmm2, xmm3
|
|
movss xmm7, s0
|
|
subss xmm4, xmm5
|
|
|
|
mulss xmm0, xmm7
|
|
movss t0, xmm0
|
|
mulss xmm2, xmm7
|
|
movss t1, xmm2
|
|
mulss xmm4, xmm7
|
|
movss t2, xmm4
|
|
|
|
#ifndef DERIVE_UNSMOOTHED_BITANGENT
|
|
movss xmm0, d3
|
|
mulss xmm0, d5
|
|
movss xmm1, d0
|
|
mulss xmm1, d8
|
|
|
|
movss xmm2, d3
|
|
mulss xmm2, d6
|
|
movss xmm3, d1
|
|
mulss xmm3, d8
|
|
|
|
movss xmm4, d3
|
|
mulss xmm4, d7
|
|
movss xmm5, d2
|
|
mulss xmm5, d8
|
|
#else
|
|
movss xmm0, n2
|
|
mulss xmm0, t1
|
|
movss xmm1, n1
|
|
mulss xmm1, t2
|
|
|
|
movss xmm2, n0
|
|
mulss xmm2, t2
|
|
movss xmm3, n2
|
|
mulss xmm3, t0
|
|
|
|
movss xmm4, n1
|
|
mulss xmm4, t0
|
|
movss xmm5, n0
|
|
mulss xmm5, t1
|
|
#endif
|
|
subss xmm0, xmm1
|
|
subss xmm2, xmm3
|
|
movss xmm7, s1
|
|
subss xmm4, xmm5
|
|
|
|
mulss xmm0, xmm7
|
|
movss t3, xmm0
|
|
mulss xmm2, xmm7
|
|
movss t4, xmm2
|
|
mulss xmm4, xmm7
|
|
movss t5, xmm4
|
|
}
|
|
|
|
#else
|
|
|
|
n0 = s2 * ( d6 * d2 - d7 * d1 );
|
|
n1 = s2 * ( d7 * d0 - d5 * d2 );
|
|
n2 = s2 * ( d5 * d1 - d6 * d0 );
|
|
|
|
t0 = s0 * ( d0 * d9 - d4 * d5 );
|
|
t1 = s0 * ( d1 * d9 - d4 * d6 );
|
|
t2 = s0 * ( d2 * d9 - d4 * d7 );
|
|
|
|
#ifndef DERIVE_UNSMOOTHED_BITANGENT
|
|
t3 = s1 * ( d3 * d5 - d0 * d8 );
|
|
t4 = s1 * ( d3 * d6 - d1 * d8 );
|
|
t5 = s1 * ( d3 * d7 - d2 * d8 );
|
|
#else
|
|
t3 = s1 * ( n2 * t1 - n1 * t2 );
|
|
t4 = s1 * ( n0 * t2 - n2 * t0 );
|
|
t5 = s1 * ( n1 * t0 - n0 * t1 );
|
|
#endif
|
|
|
|
#endif
|
|
|
|
a->normal[0] = n0;
|
|
a->normal[1] = n1;
|
|
a->normal[2] = n2;
|
|
|
|
a->tangents[0][0] = t0;
|
|
a->tangents[0][1] = t1;
|
|
a->tangents[0][2] = t2;
|
|
|
|
a->tangents[1][0] = t3;
|
|
a->tangents[1][1] = t4;
|
|
a->tangents[1][2] = t5;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::NormalizeTangents
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::NormalizeTangents( idDrawVert *verts, const int numVerts ) {
|
|
ALIGN16( float normal[12] );
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->normal == DRAWVERT_NORMAL_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[0] == DRAWVERT_TANGENT0_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[1] == DRAWVERT_TANGENT1_OFFSET );
|
|
|
|
assert( verts != NULL );
|
|
assert( numVerts >= 0 );
|
|
|
|
__asm {
|
|
mov eax, numVerts
|
|
test eax, eax
|
|
jz done
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
movaps xmm6, SIMD_SP_rsqrt_c0
|
|
movaps xmm7, SIMD_SP_rsqrt_c1
|
|
#endif
|
|
mov esi, verts
|
|
imul eax, DRAWVERT_SIZE
|
|
add esi, eax
|
|
neg eax
|
|
add eax, DRAWVERT_SIZE*4
|
|
jle loopVert4
|
|
|
|
sub eax, DRAWVERT_SIZE*4
|
|
jl loopVert1
|
|
|
|
loopVert4:
|
|
|
|
sub eax, DRAWVERT_SIZE*4
|
|
|
|
// normalize 4 idDrawVert::normal
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_NORMAL_OFFSET+0] // 0, X, X, X
|
|
movhps xmm0, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_NORMAL_OFFSET+0] // 0, X, 3, 4
|
|
movss xmm2, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_NORMAL_OFFSET+8] // 5, X, X, X
|
|
movhps xmm2, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_NORMAL_OFFSET+4] // 5, X, 1, 2
|
|
movss xmm4, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_NORMAL_OFFSET+0] // 6, X, X, X
|
|
movhps xmm4, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_NORMAL_OFFSET+0] // 6, X, 9, 10
|
|
movss xmm3, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_NORMAL_OFFSET+8] // 11, X, X, X
|
|
movhps xmm3, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_NORMAL_OFFSET+4] // 11, X, 7, 8
|
|
|
|
movaps xmm1, xmm0
|
|
movaps xmm5, xmm2
|
|
shufps xmm0, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // 0, 3, 6, 9
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 2, 5, 8, 11
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 3, 2, 2 ) // 4, 4, 1, 1
|
|
shufps xmm4, xmm3, R_SHUFFLEPS( 3, 3, 2, 2 ) // 10, 10, 7, 7
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 2, 0, 2, 0 ) // 1, 4, 7, 10
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
|
|
mulps xmm0, xmm3
|
|
mulps xmm1, xmm3
|
|
mulps xmm2, xmm3
|
|
|
|
// save the 4 idDrawVert::normal to project the tangents
|
|
|
|
movaps [normal+ 0], xmm0
|
|
movaps [normal+16], xmm1
|
|
movaps [normal+32], xmm2
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_NORMAL_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_NORMAL_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_NORMAL_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_NORMAL_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_NORMAL_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_NORMAL_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_NORMAL_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_NORMAL_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_NORMAL_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_NORMAL_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_NORMAL_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_NORMAL_OFFSET+8], xmm2
|
|
|
|
// project and normalize 4 idDrawVert::tangent[0]
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT0_OFFSET+0] // 0, X, X, X
|
|
movhps xmm0, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT0_OFFSET+0] // 0, X, 3, 4
|
|
movss xmm2, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT0_OFFSET+8] // 5, X, X, X
|
|
movhps xmm2, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT0_OFFSET+4] // 5, X, 1, 2
|
|
movss xmm4, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT0_OFFSET+0] // 6, X, X, X
|
|
movhps xmm4, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT0_OFFSET+0] // 6, X, 9, 10
|
|
movss xmm3, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT0_OFFSET+8] // 11, X, X, X
|
|
movhps xmm3, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT0_OFFSET+4] // 11, X, 7, 8
|
|
|
|
movaps xmm1, xmm0
|
|
movaps xmm5, xmm2
|
|
shufps xmm0, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // 0, 3, 6, 9
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 2, 5, 8, 11
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 3, 2, 2 ) // 4, 4, 1, 1
|
|
shufps xmm4, xmm3, R_SHUFFLEPS( 3, 3, 2, 2 ) // 10, 10, 7, 7
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 2, 0, 2, 0 ) // 1, 4, 7, 10
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, [normal+ 0]
|
|
mulps xmm4, [normal+16]
|
|
mulps xmm5, [normal+32]
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
movaps xmm4, xmm3
|
|
movaps xmm5, xmm3
|
|
mulps xmm3, [normal+ 0]
|
|
mulps xmm4, [normal+16]
|
|
mulps xmm5, [normal+32]
|
|
subps xmm0, xmm3
|
|
subps xmm1, xmm4
|
|
subps xmm2, xmm5
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
|
|
mulps xmm0, xmm3
|
|
mulps xmm1, xmm3
|
|
mulps xmm2, xmm3
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT0_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT0_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT0_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT0_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT0_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT0_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT0_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT0_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT0_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT0_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT0_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT0_OFFSET+8], xmm2
|
|
|
|
// project and normalize 4 idDrawVert::tangent[1]
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT1_OFFSET+0] // 0, X, X, X
|
|
movhps xmm0, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT1_OFFSET+0] // 0, X, 3, 4
|
|
movss xmm2, [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT1_OFFSET+8] // 5, X, X, X
|
|
movhps xmm2, [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT1_OFFSET+4] // 5, X, 1, 2
|
|
movss xmm4, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT1_OFFSET+0] // 6, X, X, X
|
|
movhps xmm4, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT1_OFFSET+0] // 6, X, 9, 10
|
|
movss xmm3, [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT1_OFFSET+8] // 11, X, X, X
|
|
movhps xmm3, [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT1_OFFSET+4] // 11, X, 7, 8
|
|
|
|
movaps xmm1, xmm0
|
|
movaps xmm5, xmm2
|
|
shufps xmm0, xmm4, R_SHUFFLEPS( 0, 2, 0, 2 ) // 0, 3, 6, 9
|
|
shufps xmm2, xmm3, R_SHUFFLEPS( 3, 0, 3, 0 ) // 2, 5, 8, 11
|
|
shufps xmm1, xmm5, R_SHUFFLEPS( 3, 3, 2, 2 ) // 4, 4, 1, 1
|
|
shufps xmm4, xmm3, R_SHUFFLEPS( 3, 3, 2, 2 ) // 10, 10, 7, 7
|
|
shufps xmm1, xmm4, R_SHUFFLEPS( 2, 0, 2, 0 ) // 1, 4, 7, 10
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, [normal+ 0]
|
|
mulps xmm4, [normal+16]
|
|
mulps xmm5, [normal+32]
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
movaps xmm4, xmm3
|
|
movaps xmm5, xmm3
|
|
mulps xmm3, [normal+ 0]
|
|
mulps xmm4, [normal+16]
|
|
mulps xmm5, [normal+32]
|
|
subps xmm0, xmm3
|
|
subps xmm1, xmm4
|
|
subps xmm2, xmm5
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
movaps xmm5, xmm2
|
|
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
mulps xmm5, xmm5
|
|
addps xmm3, xmm4
|
|
addps xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtps xmm4, xmm3
|
|
mulps xmm3, xmm4
|
|
mulps xmm3, xmm4
|
|
subps xmm3, xmm6
|
|
mulps xmm4, xmm7
|
|
mulps xmm3, xmm4
|
|
#else
|
|
rsqrtps xmm3, xmm3
|
|
#endif
|
|
|
|
mulps xmm0, xmm3
|
|
mulps xmm1, xmm3
|
|
mulps xmm2, xmm3
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT1_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT1_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*0+DRAWVERT_TANGENT1_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT1_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT1_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*1+DRAWVERT_TANGENT1_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT1_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT1_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*2+DRAWVERT_TANGENT1_OFFSET+8], xmm2
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT1_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT1_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_SIZE*3+DRAWVERT_TANGENT1_OFFSET+8], xmm2
|
|
|
|
add eax, DRAWVERT_SIZE*8
|
|
|
|
jle loopVert4
|
|
|
|
sub eax, DRAWVERT_SIZE*4
|
|
jge done
|
|
|
|
loopVert1:
|
|
|
|
// normalize one idDrawVert::normal
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_NORMAL_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_NORMAL_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_NORMAL_OFFSET+8]
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
|
|
mulss xmm0, xmm3
|
|
mulss xmm1, xmm3
|
|
mulss xmm2, xmm3
|
|
|
|
movss [esi+eax+DRAWVERT_NORMAL_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_NORMAL_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_NORMAL_OFFSET+8], xmm2
|
|
|
|
// project and normalize one idDrawVert::tangent[0]
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_TANGENT0_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_TANGENT0_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_TANGENT0_OFFSET+8]
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, [esi+eax+DRAWVERT_NORMAL_OFFSET+0]
|
|
mulss xmm4, [esi+eax+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulss xmm5, [esi+eax+DRAWVERT_NORMAL_OFFSET+8]
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
movss xmm4, xmm3
|
|
movss xmm5, xmm3
|
|
mulss xmm3, [esi+eax+DRAWVERT_NORMAL_OFFSET+0]
|
|
mulss xmm4, [esi+eax+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulss xmm5, [esi+eax+DRAWVERT_NORMAL_OFFSET+8]
|
|
subss xmm0, xmm3
|
|
subss xmm1, xmm4
|
|
subss xmm2, xmm5
|
|
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
|
|
mulss xmm0, xmm3
|
|
mulss xmm1, xmm3
|
|
mulss xmm2, xmm3
|
|
|
|
movss [esi+eax+DRAWVERT_TANGENT0_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_TANGENT0_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_TANGENT0_OFFSET+8], xmm2
|
|
|
|
// project and normalize one idDrawVert::tangent[1]
|
|
|
|
movss xmm0, [esi+eax+DRAWVERT_TANGENT1_OFFSET+0]
|
|
movss xmm1, [esi+eax+DRAWVERT_TANGENT1_OFFSET+4]
|
|
movss xmm2, [esi+eax+DRAWVERT_TANGENT1_OFFSET+8]
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, [esi+eax+DRAWVERT_NORMAL_OFFSET+0]
|
|
mulss xmm4, [esi+eax+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulss xmm5, [esi+eax+DRAWVERT_NORMAL_OFFSET+8]
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
movss xmm4, xmm3
|
|
movss xmm5, xmm3
|
|
mulss xmm3, [esi+eax+DRAWVERT_NORMAL_OFFSET+0]
|
|
mulss xmm4, [esi+eax+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulss xmm5, [esi+eax+DRAWVERT_NORMAL_OFFSET+8]
|
|
subss xmm0, xmm3
|
|
subss xmm1, xmm4
|
|
subss xmm2, xmm5
|
|
|
|
movss xmm3, xmm0
|
|
movss xmm4, xmm1
|
|
movss xmm5, xmm2
|
|
|
|
mulss xmm3, xmm3
|
|
mulss xmm4, xmm4
|
|
mulss xmm5, xmm5
|
|
addss xmm3, xmm4
|
|
addss xmm3, xmm5
|
|
|
|
#ifdef REFINE_TANGENT_SQUAREROOT
|
|
rsqrtss xmm4, xmm3
|
|
mulss xmm3, xmm4
|
|
mulss xmm3, xmm4
|
|
subss xmm3, xmm6
|
|
mulss xmm4, xmm7
|
|
mulss xmm3, xmm4
|
|
#else
|
|
rsqrtss xmm3, xmm3
|
|
#endif
|
|
|
|
mulss xmm0, xmm3
|
|
mulss xmm1, xmm3
|
|
mulss xmm2, xmm3
|
|
|
|
movss [esi+eax+DRAWVERT_TANGENT1_OFFSET+0], xmm0
|
|
movss [esi+eax+DRAWVERT_TANGENT1_OFFSET+4], xmm1
|
|
movss [esi+eax+DRAWVERT_TANGENT1_OFFSET+8], xmm2
|
|
|
|
add eax, DRAWVERT_SIZE
|
|
|
|
jl loopVert1
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CreateTextureSpaceLightVectors
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CreateTextureSpaceLightVectors( idVec3 *lightVectors, const idVec3 &lightOrigin, const idDrawVert *verts, const int numVerts, const int *indexes, const int numIndexes ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->normal == DRAWVERT_NORMAL_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[0] == DRAWVERT_TANGENT0_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[1] == DRAWVERT_TANGENT1_OFFSET );
|
|
|
|
bool *used = (bool *)_alloca16( numVerts * sizeof( used[0] ) );
|
|
memset( used, 0, numVerts * sizeof( used[0] ) );
|
|
|
|
for ( int i = numIndexes - 1; i >= 0; i-- ) {
|
|
used[indexes[i]] = true;
|
|
}
|
|
|
|
#if 0
|
|
|
|
__asm {
|
|
|
|
mov eax, numVerts
|
|
|
|
mov esi, used
|
|
add esi, eax
|
|
|
|
mov edi, verts
|
|
sub edi, DRAWVERT_SIZE
|
|
|
|
neg eax
|
|
dec eax
|
|
|
|
mov ecx, lightOrigin
|
|
movss xmm7, [ecx+0]
|
|
movhps xmm7, [ecx+4]
|
|
|
|
mov ecx, lightVectors
|
|
sub ecx, 3*4
|
|
|
|
loopVert:
|
|
inc eax
|
|
jge done
|
|
|
|
add edi, DRAWVERT_SIZE
|
|
add ecx, 3*4
|
|
|
|
cmp byte ptr [esi+eax], 0
|
|
je loopVert
|
|
|
|
movaps xmm0, xmm7
|
|
movss xmm1, [edi+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm1, [edi+DRAWVERT_XYZ_OFFSET+4]
|
|
subps xmm0, xmm1
|
|
|
|
// 0, X, 1, 2
|
|
// 3, X, 4, 5
|
|
// 6, X, 7, 8
|
|
|
|
movss xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+0]
|
|
movhps xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+4]
|
|
mulps xmm2, xmm0
|
|
|
|
movss xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+0]
|
|
movhps xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+4]
|
|
mulps xmm3, xmm0
|
|
|
|
movaps xmm5, xmm2 // xmm5 = 0, X, 1, 2
|
|
unpcklps xmm5, xmm3 // xmm5 = 0, 3, X, X
|
|
unpckhps xmm2, xmm3 // xmm2 = 1, 4, 2, 5
|
|
|
|
movss xmm4, [edi+DRAWVERT_NORMAL_OFFSET+0]
|
|
movhps xmm4, [edi+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulps xmm4, xmm0
|
|
|
|
movlhps xmm5, xmm4 // xmm5 = 0, 3, 6, X
|
|
movhlps xmm4, xmm2 // xmm4 = 2, 5, 7, 8
|
|
shufps xmm2, xmm4, R_SHUFFLEPS( 0, 1, 3, 2 ) // xmm2 = 2, 5, 8, 7
|
|
|
|
addps xmm5, xmm4
|
|
addps xmm5, xmm2
|
|
movlps [ecx+0], xmm5
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
movss [ecx+8], xmm5
|
|
|
|
jmp loopVert
|
|
|
|
done:
|
|
}
|
|
|
|
#elif 1
|
|
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
if ( !used[i] ) {
|
|
continue;
|
|
}
|
|
|
|
const idDrawVert *v = &verts[i];
|
|
idVec3 lightDir;
|
|
|
|
lightDir[0] = lightOrigin[0] - v->xyz[0];
|
|
lightDir[1] = lightOrigin[1] - v->xyz[1];
|
|
lightDir[2] = lightOrigin[2] - v->xyz[2];
|
|
|
|
lightVectors[i][0] = lightDir[0] * v->tangents[0][0] + lightDir[1] * v->tangents[0][1] + lightDir[2] * v->tangents[0][2];
|
|
lightVectors[i][1] = lightDir[0] * v->tangents[1][0] + lightDir[1] * v->tangents[1][1] + lightDir[2] * v->tangents[1][2];
|
|
lightVectors[i][2] = lightDir[0] * v->normal[0] + lightDir[1] * v->normal[1] + lightDir[2] * v->normal[2];
|
|
}
|
|
|
|
#elif 1
|
|
|
|
ALIGN16( int usedVertNums[4] );
|
|
ALIGN16( float lightDir0[4] );
|
|
ALIGN16( float lightDir1[4] );
|
|
ALIGN16( float lightDir2[4] );
|
|
ALIGN16( float normal0[4] );
|
|
ALIGN16( float normal1[4] );
|
|
ALIGN16( float normal2[4] );
|
|
ALIGN16( float tangent0[4] );
|
|
ALIGN16( float tangent1[4] );
|
|
ALIGN16( float tangent2[4] );
|
|
ALIGN16( float tangent3[4] );
|
|
ALIGN16( float tangent4[4] );
|
|
ALIGN16( float tangent5[4] );
|
|
idVec3 localLightOrigin = lightOrigin;
|
|
|
|
__asm {
|
|
|
|
xor ecx, ecx
|
|
mov eax, numVerts
|
|
|
|
mov esi, used
|
|
add esi, eax
|
|
|
|
mov edi, verts
|
|
sub edi, DRAWVERT_SIZE
|
|
|
|
neg eax
|
|
dec eax
|
|
|
|
loopVert4:
|
|
inc eax
|
|
jge done4
|
|
|
|
add edi, DRAWVERT_SIZE
|
|
|
|
cmp byte ptr [esi+eax], 0
|
|
je loopVert4
|
|
|
|
mov usedVertNums[ecx*4], eax
|
|
|
|
inc ecx
|
|
cmp ecx, 4
|
|
|
|
movss xmm0, localLightOrigin[0]
|
|
movss xmm1, localLightOrigin[4]
|
|
movss xmm2, localLightOrigin[8]
|
|
|
|
subss xmm0, [edi+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm1, [edi+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm2, [edi+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
movss lightDir0[ecx*4-4], xmm0
|
|
movss lightDir1[ecx*4-4], xmm1
|
|
movss lightDir2[ecx*4-4], xmm2
|
|
|
|
movss xmm3, [edi+DRAWVERT_NORMAL_OFFSET+0]
|
|
movss xmm4, [edi+DRAWVERT_NORMAL_OFFSET+4]
|
|
movss xmm5, [edi+DRAWVERT_NORMAL_OFFSET+8]
|
|
|
|
movss normal0[ecx*4-4], xmm3
|
|
movss normal1[ecx*4-4], xmm4
|
|
movss normal2[ecx*4-4], xmm5
|
|
|
|
movss xmm0, [edi+DRAWVERT_TANGENT0_OFFSET+0]
|
|
movss xmm1, [edi+DRAWVERT_TANGENT0_OFFSET+4]
|
|
movss xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+8]
|
|
|
|
movss tangent0[ecx*4-4], xmm0
|
|
movss tangent1[ecx*4-4], xmm1
|
|
movss tangent2[ecx*4-4], xmm2
|
|
|
|
movss xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+0]
|
|
movss xmm4, [edi+DRAWVERT_TANGENT1_OFFSET+4]
|
|
movss xmm5, [edi+DRAWVERT_TANGENT1_OFFSET+8]
|
|
|
|
movss tangent3[ecx*4-4], xmm3
|
|
movss tangent4[ecx*4-4], xmm4
|
|
movss tangent5[ecx*4-4], xmm5
|
|
|
|
jl loopVert4
|
|
|
|
movaps xmm0, lightDir0
|
|
movaps xmm1, lightDir1
|
|
movaps xmm2, lightDir2
|
|
|
|
movaps xmm3, tangent0
|
|
mulps xmm3, xmm0
|
|
movaps xmm4, tangent1
|
|
mulps xmm4, xmm1
|
|
movaps xmm5, tangent2
|
|
mulps xmm5, xmm2
|
|
|
|
addps xmm3, xmm4
|
|
addps xmm5, xmm3
|
|
|
|
movaps xmm3, tangent3
|
|
mulps xmm3, xmm0
|
|
movaps xmm4, tangent4
|
|
mulps xmm4, xmm1
|
|
movaps xmm6, tangent5
|
|
mulps xmm6, xmm2
|
|
|
|
addps xmm3, xmm4
|
|
addps xmm6, xmm3
|
|
|
|
mulps xmm0, normal0
|
|
mulps xmm1, normal1
|
|
mulps xmm2, normal2
|
|
|
|
addps xmm0, xmm1
|
|
addps xmm0, xmm2
|
|
|
|
mov ecx, numVerts
|
|
imul ecx, 12
|
|
mov edx, usedVertNums[0]
|
|
add ecx, lightVectors
|
|
imul edx, 12
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
imul edx, 12
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
imul edx, 12
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[12]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
imul edx, 12
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
|
|
xor ecx, ecx
|
|
jmp loopVert4
|
|
|
|
done4:
|
|
test ecx, ecx
|
|
jz done
|
|
xor eax, eax
|
|
mov edi, numVerts
|
|
imul edi, 12
|
|
add edi, lightVectors
|
|
|
|
loopVert1:
|
|
movss xmm0, lightDir0[eax*4]
|
|
movss xmm1, lightDir1[eax*4]
|
|
movss xmm2, lightDir2[eax*4]
|
|
|
|
mov edx, usedVertNums[eax*4]
|
|
imul edx, 12
|
|
|
|
movss xmm3, tangent0[eax*4]
|
|
mulss xmm3, xmm0
|
|
movss xmm4, tangent1[eax*4]
|
|
mulss xmm4, xmm1
|
|
movss xmm5, tangent2[eax*4]
|
|
mulss xmm5, xmm2
|
|
|
|
addss xmm3, xmm4
|
|
addss xmm5, xmm3
|
|
movss [edi+edx+0], xmm5
|
|
|
|
movss xmm3, tangent3[eax*4]
|
|
mulss xmm3, xmm0
|
|
movss xmm4, tangent4[eax*4]
|
|
mulss xmm4, xmm1
|
|
movss xmm6, tangent5[eax*4]
|
|
mulss xmm6, xmm2
|
|
|
|
addss xmm3, xmm4
|
|
addss xmm6, xmm3
|
|
movss [edi+edx+4], xmm6
|
|
|
|
mulss xmm0, normal0[eax*4]
|
|
mulss xmm1, normal1[eax*4]
|
|
mulss xmm2, normal2[eax*4]
|
|
|
|
addss xmm0, xmm1
|
|
addss xmm0, xmm2
|
|
movss [edi+edx+8], xmm0
|
|
|
|
inc eax
|
|
dec ecx
|
|
jg loopVert1
|
|
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
ALIGN16( float lightVectors0[4] );
|
|
ALIGN16( float lightVectors1[4] );
|
|
ALIGN16( float lightVectors2[4] );
|
|
int numUsedVerts = 0;
|
|
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
if ( !used[i] ) {
|
|
continue;
|
|
}
|
|
|
|
const idDrawVert *v = &verts[i];
|
|
|
|
lightDir0[numUsedVerts] = lightOrigin[0] - v->xyz[0];
|
|
lightDir1[numUsedVerts] = lightOrigin[1] - v->xyz[1];
|
|
lightDir2[numUsedVerts] = lightOrigin[2] - v->xyz[2];
|
|
|
|
normal0[numUsedVerts] = v->normal[0];
|
|
normal1[numUsedVerts] = v->normal[1];
|
|
normal2[numUsedVerts] = v->normal[2];
|
|
|
|
tangent0[numUsedVerts] = v->tangents[0][0];
|
|
tangent1[numUsedVerts] = v->tangents[0][1];
|
|
tangent2[numUsedVerts] = v->tangents[0][2];
|
|
|
|
tangent3[numUsedVerts] = v->tangents[1][0];
|
|
tangent4[numUsedVerts] = v->tangents[1][1];
|
|
tangent5[numUsedVerts] = v->tangents[1][2];
|
|
|
|
usedVertNums[numUsedVerts++] = i;
|
|
if ( numUsedVerts < 4 ) {
|
|
continue;
|
|
}
|
|
|
|
lightVectors0[0] = lightDir0[0] * tangent0[0];
|
|
lightVectors0[1] = lightDir0[1] * tangent0[1];
|
|
lightVectors0[2] = lightDir0[2] * tangent0[2];
|
|
lightVectors0[3] = lightDir0[3] * tangent0[3];
|
|
|
|
lightVectors0[0] += lightDir1[0] * tangent1[0];
|
|
lightVectors0[1] += lightDir1[1] * tangent1[1];
|
|
lightVectors0[2] += lightDir1[2] * tangent1[2];
|
|
lightVectors0[3] += lightDir1[3] * tangent1[3];
|
|
|
|
lightVectors0[0] += lightDir2[0] * tangent2[0];
|
|
lightVectors0[1] += lightDir2[1] * tangent2[1];
|
|
lightVectors0[2] += lightDir2[2] * tangent2[2];
|
|
lightVectors0[3] += lightDir2[3] * tangent2[3];
|
|
|
|
lightVectors1[0] = lightDir0[0] * tangent3[0];
|
|
lightVectors1[1] = lightDir0[1] * tangent3[1];
|
|
lightVectors1[2] = lightDir0[2] * tangent3[2];
|
|
lightVectors1[3] = lightDir0[3] * tangent3[3];
|
|
|
|
lightVectors1[0] += lightDir1[0] * tangent4[0];
|
|
lightVectors1[1] += lightDir1[1] * tangent4[1];
|
|
lightVectors1[2] += lightDir1[2] * tangent4[2];
|
|
lightVectors1[3] += lightDir1[3] * tangent4[3];
|
|
|
|
lightVectors1[0] += lightDir2[0] * tangent5[0];
|
|
lightVectors1[1] += lightDir2[1] * tangent5[1];
|
|
lightVectors1[2] += lightDir2[2] * tangent5[2];
|
|
lightVectors1[3] += lightDir2[3] * tangent5[3];
|
|
|
|
lightVectors2[0] = lightDir0[0] * normal0[0];
|
|
lightVectors2[1] = lightDir0[1] * normal0[1];
|
|
lightVectors2[2] = lightDir0[2] * normal0[2];
|
|
lightVectors2[3] = lightDir0[3] * normal0[3];
|
|
|
|
lightVectors2[0] += lightDir1[0] * normal1[0];
|
|
lightVectors2[1] += lightDir1[1] * normal1[1];
|
|
lightVectors2[2] += lightDir1[2] * normal1[2];
|
|
lightVectors2[3] += lightDir1[3] * normal1[3];
|
|
|
|
lightVectors2[0] += lightDir2[0] * normal2[0];
|
|
lightVectors2[1] += lightDir2[1] * normal2[1];
|
|
lightVectors2[2] += lightDir2[2] * normal2[2];
|
|
lightVectors2[3] += lightDir2[3] * normal2[3];
|
|
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
int n = usedVertNums[j];
|
|
|
|
lightVectors[n][0] = lightVectors0[j];
|
|
lightVectors[n][1] = lightVectors1[j];
|
|
lightVectors[n][2] = lightVectors2[j];
|
|
}
|
|
|
|
numUsedVerts = 0;
|
|
}
|
|
|
|
for ( int i = 0; i < numUsedVerts; i++ ) {
|
|
|
|
lightVectors0[i] = lightDir0[i] * tangent0[i] + lightDir1[i] * tangent1[i] + lightDir2[i] * tangent2[i];
|
|
lightVectors1[i] = lightDir0[i] * tangent3[i] + lightDir1[i] * tangent4[i] + lightDir2[i] * tangent5[i];
|
|
lightVectors2[i] = lightDir0[i] * normal0[i] + lightDir1[i] * normal1[i] + lightDir2[i] * normal2[i];
|
|
|
|
int n = usedVertNums[i];
|
|
lightVectors[n][0] = lightVectors0[i];
|
|
lightVectors[n][1] = lightVectors1[i];
|
|
lightVectors[n][2] = lightVectors2[i];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CreateSpecularTextureCoords
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::CreateSpecularTextureCoords( idVec4 *texCoords, const idVec3 &lightOrigin, const idVec3 &viewOrigin, const idDrawVert *verts, const int numVerts, const int *indexes, const int numIndexes ) {
|
|
|
|
assert( sizeof( idDrawVert ) == DRAWVERT_SIZE );
|
|
assert( (int)&((idDrawVert *)0)->xyz == DRAWVERT_XYZ_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->normal == DRAWVERT_NORMAL_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[0] == DRAWVERT_TANGENT0_OFFSET );
|
|
assert( (int)&((idDrawVert *)0)->tangents[1] == DRAWVERT_TANGENT1_OFFSET );
|
|
|
|
bool *used = (bool *)_alloca16( numVerts * sizeof( used[0] ) );
|
|
memset( used, 0, numVerts * sizeof( used[0] ) );
|
|
|
|
for ( int i = numIndexes - 1; i >= 0; i-- ) {
|
|
used[indexes[i]] = true;
|
|
}
|
|
|
|
#if 0
|
|
|
|
__asm {
|
|
|
|
mov eax, numVerts
|
|
|
|
mov esi, used
|
|
add esi, eax
|
|
|
|
mov edi, verts
|
|
sub edi, DRAWVERT_SIZE
|
|
|
|
neg eax
|
|
dec eax
|
|
|
|
mov ecx, viewOrigin
|
|
movss xmm6, [ecx+0]
|
|
movhps xmm6, [ecx+4]
|
|
|
|
mov ecx, lightOrigin
|
|
movss xmm7, [ecx+0]
|
|
movhps xmm7, [ecx+4]
|
|
|
|
mov ecx, texCoords
|
|
sub ecx, 4*4
|
|
|
|
loopVert:
|
|
inc eax
|
|
jge done
|
|
|
|
add edi, DRAWVERT_SIZE
|
|
add ecx, 4*4
|
|
|
|
cmp byte ptr [esi+eax], 0
|
|
je loopVert
|
|
|
|
movaps xmm0, xmm7
|
|
movaps xmm1, xmm6
|
|
movss xmm2, [edi+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm2, [edi+DRAWVERT_XYZ_OFFSET+4]
|
|
subps xmm0, xmm2
|
|
subps xmm1, xmm2
|
|
|
|
movaps xmm3, xmm0
|
|
movaps xmm4, xmm1
|
|
mulps xmm3, xmm3
|
|
mulps xmm4, xmm4
|
|
|
|
// 0, X, 1, 2
|
|
// 3, X, 4, 5
|
|
|
|
movaps xmm5, xmm3 // xmm5 = 0, X, 1, 2
|
|
unpcklps xmm5, xmm4 // xmm5 = 0, 3, X, X
|
|
unpckhps xmm3, xmm4 // xmm3 = 1, 4, 2, 5
|
|
movhlps xmm4, xmm3 // xmm4 = 2, 5, 4, 5
|
|
|
|
addps xmm5, xmm3
|
|
addps xmm5, xmm4
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
rsqrtps xmm5, xmm5
|
|
|
|
movaps xmm4, xmm5
|
|
shufps xmm4, xmm4, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
|
|
mulps xmm0, xmm4
|
|
mulps xmm1, xmm5
|
|
addps xmm0, xmm1
|
|
|
|
movss xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+0]
|
|
movhps xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+4]
|
|
mulps xmm2, xmm0
|
|
|
|
movss xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+0]
|
|
movhps xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+4]
|
|
mulps xmm3, xmm0
|
|
|
|
movss xmm4, [edi+DRAWVERT_NORMAL_OFFSET+0]
|
|
movhps xmm4, [edi+DRAWVERT_NORMAL_OFFSET+4]
|
|
mulps xmm4, xmm0
|
|
|
|
movaps xmm5, xmm2 // xmm5 = 0, X, 1, 2
|
|
unpcklps xmm5, xmm3 // xmm5 = 0, 3, X, X
|
|
unpckhps xmm2, xmm3 // xmm2 = 1, 4, 2, 5
|
|
|
|
movlhps xmm5, xmm4 // xmm5 = 0, 3, 6, X
|
|
movhlps xmm4, xmm2 // xmm4 = 2, 5, 7, 8
|
|
shufps xmm2, xmm4, R_SHUFFLEPS( 0, 1, 3, 2 ) // xmm2 = 2, 5, 8, 7
|
|
|
|
movaps xmm3, SIMD_SP_one
|
|
|
|
addps xmm5, xmm4
|
|
addps xmm5, xmm2
|
|
movaps [ecx+0], xmm5
|
|
movss [ecx+12], xmm3
|
|
|
|
jmp loopVert
|
|
|
|
done:
|
|
}
|
|
|
|
#elif 0
|
|
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
if ( !used[i] ) {
|
|
continue;
|
|
}
|
|
|
|
const idDrawVert *v = &verts[i];
|
|
|
|
idVec3 lightDir = lightOrigin - v->xyz;
|
|
idVec3 viewDir = viewOrigin - v->xyz;
|
|
|
|
float ilength;
|
|
|
|
ilength = idMath::RSqrt( lightDir[0] * lightDir[0] + lightDir[1] * lightDir[1] + lightDir[2] * lightDir[2] );
|
|
lightDir[0] *= ilength;
|
|
lightDir[1] *= ilength;
|
|
lightDir[2] *= ilength;
|
|
|
|
ilength = idMath::RSqrt( viewDir[0] * viewDir[0] + viewDir[1] * viewDir[1] + viewDir[2] * viewDir[2] );
|
|
viewDir[0] *= ilength;
|
|
viewDir[1] *= ilength;
|
|
viewDir[2] *= ilength;
|
|
|
|
lightDir += viewDir;
|
|
|
|
texCoords[i][0] = lightDir[0] * v->tangents[0][0] + lightDir[1] * v->tangents[0][1] + lightDir[2] * v->tangents[0][2];
|
|
texCoords[i][1] = lightDir[0] * v->tangents[1][0] + lightDir[1] * v->tangents[1][1] + lightDir[2] * v->tangents[1][2];
|
|
texCoords[i][2] = lightDir[0] * v->normal[0] + lightDir[1] * v->normal[1] + lightDir[2] * v->normal[2];
|
|
texCoords[i][3] = 1.0f;
|
|
}
|
|
|
|
|
|
#elif 1
|
|
|
|
ALIGN16( int usedVertNums[4] );
|
|
ALIGN16( float lightDir0[4] );
|
|
ALIGN16( float lightDir1[4] );
|
|
ALIGN16( float lightDir2[4] );
|
|
ALIGN16( float viewDir0[4] );
|
|
ALIGN16( float viewDir1[4] );
|
|
ALIGN16( float viewDir2[4] );
|
|
ALIGN16( float normal0[4] );
|
|
ALIGN16( float normal1[4] );
|
|
ALIGN16( float normal2[4] );
|
|
ALIGN16( float tangent0[4] );
|
|
ALIGN16( float tangent1[4] );
|
|
ALIGN16( float tangent2[4] );
|
|
ALIGN16( float tangent3[4] );
|
|
ALIGN16( float tangent4[4] );
|
|
ALIGN16( float tangent5[4] );
|
|
idVec3 localLightOrigin = lightOrigin;
|
|
idVec3 localViewOrigin = viewOrigin;
|
|
|
|
__asm {
|
|
|
|
xor ecx, ecx
|
|
mov eax, numVerts
|
|
|
|
mov esi, used
|
|
add esi, eax
|
|
|
|
mov edi, verts
|
|
sub edi, DRAWVERT_SIZE
|
|
|
|
neg eax
|
|
dec eax
|
|
|
|
loopVert4:
|
|
inc eax
|
|
jge done4
|
|
|
|
add edi, DRAWVERT_SIZE
|
|
|
|
cmp byte ptr [esi+eax], 0
|
|
je loopVert4
|
|
|
|
mov usedVertNums[ecx*4], eax
|
|
|
|
inc ecx
|
|
cmp ecx, 4
|
|
|
|
movss xmm3, localLightOrigin[0]
|
|
movss xmm4, localLightOrigin[4]
|
|
movss xmm5, localLightOrigin[8]
|
|
|
|
subss xmm3, [edi+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm4, [edi+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm5, [edi+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
movss lightDir0[ecx*4-4], xmm3
|
|
movss lightDir1[ecx*4-4], xmm4
|
|
movss lightDir2[ecx*4-4], xmm5
|
|
|
|
movss xmm0, localViewOrigin[0]
|
|
movss xmm1, localViewOrigin[4]
|
|
movss xmm2, localViewOrigin[8]
|
|
|
|
subss xmm0, [edi+DRAWVERT_XYZ_OFFSET+0]
|
|
subss xmm1, [edi+DRAWVERT_XYZ_OFFSET+4]
|
|
subss xmm2, [edi+DRAWVERT_XYZ_OFFSET+8]
|
|
|
|
movss viewDir0[ecx*4-4], xmm0
|
|
movss viewDir1[ecx*4-4], xmm1
|
|
movss viewDir2[ecx*4-4], xmm2
|
|
|
|
movss xmm3, [edi+DRAWVERT_NORMAL_OFFSET+0]
|
|
movss xmm4, [edi+DRAWVERT_NORMAL_OFFSET+4]
|
|
movss xmm5, [edi+DRAWVERT_NORMAL_OFFSET+8]
|
|
|
|
movss normal0[ecx*4-4], xmm3
|
|
movss normal1[ecx*4-4], xmm4
|
|
movss normal2[ecx*4-4], xmm5
|
|
|
|
movss xmm0, [edi+DRAWVERT_TANGENT0_OFFSET+0]
|
|
movss xmm1, [edi+DRAWVERT_TANGENT0_OFFSET+4]
|
|
movss xmm2, [edi+DRAWVERT_TANGENT0_OFFSET+8]
|
|
|
|
movss tangent0[ecx*4-4], xmm0
|
|
movss tangent1[ecx*4-4], xmm1
|
|
movss tangent2[ecx*4-4], xmm2
|
|
|
|
movss xmm3, [edi+DRAWVERT_TANGENT1_OFFSET+0]
|
|
movss xmm4, [edi+DRAWVERT_TANGENT1_OFFSET+4]
|
|
movss xmm5, [edi+DRAWVERT_TANGENT1_OFFSET+8]
|
|
|
|
movss tangent3[ecx*4-4], xmm3
|
|
movss tangent4[ecx*4-4], xmm4
|
|
movss tangent5[ecx*4-4], xmm5
|
|
|
|
jl loopVert4
|
|
|
|
movaps xmm6, lightDir0
|
|
movaps xmm0, xmm6
|
|
mulps xmm6, xmm6
|
|
movaps xmm7, lightDir1
|
|
movaps xmm1, xmm7
|
|
mulps xmm7, xmm7
|
|
addps xmm6, xmm7
|
|
movaps xmm5, lightDir2
|
|
movaps xmm2, xmm5
|
|
mulps xmm5, xmm5
|
|
addps xmm6, xmm5
|
|
rsqrtps xmm6, xmm6
|
|
|
|
mulps xmm0, xmm6
|
|
mulps xmm1, xmm6
|
|
mulps xmm2, xmm6
|
|
|
|
movaps xmm3, viewDir0
|
|
movaps xmm7, xmm3
|
|
mulps xmm7, xmm7
|
|
movaps xmm4, viewDir1
|
|
movaps xmm6, xmm4
|
|
mulps xmm6, xmm6
|
|
addps xmm7, xmm6
|
|
movaps xmm5, viewDir2
|
|
movaps xmm6, xmm5
|
|
mulps xmm6, xmm6
|
|
addps xmm7, xmm6
|
|
rsqrtps xmm7, xmm7
|
|
|
|
mulps xmm3, xmm7
|
|
addps xmm0, xmm3
|
|
mulps xmm4, xmm7
|
|
addps xmm1, xmm4
|
|
mulps xmm5, xmm7
|
|
addps xmm2, xmm5
|
|
|
|
movaps xmm3, tangent0
|
|
mulps xmm3, xmm0
|
|
movaps xmm4, tangent1
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movaps xmm5, tangent2
|
|
mulps xmm5, xmm2
|
|
addps xmm5, xmm3
|
|
|
|
movaps xmm3, tangent3
|
|
mulps xmm3, xmm0
|
|
movaps xmm4, tangent4
|
|
mulps xmm4, xmm1
|
|
addps xmm3, xmm4
|
|
movaps xmm6, tangent5
|
|
mulps xmm6, xmm2
|
|
addps xmm6, xmm3
|
|
|
|
mulps xmm0, normal0
|
|
mulps xmm1, normal1
|
|
addps xmm0, xmm1
|
|
mulps xmm2, normal2
|
|
addps xmm0, xmm2
|
|
|
|
mov ecx, numVerts
|
|
shl ecx, 4
|
|
mov edx, usedVertNums[0]
|
|
add ecx, texCoords
|
|
shl edx, 4
|
|
movss xmm3, SIMD_SP_one
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
movss [ecx+edx+12], xmm3
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shl edx, 4
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
movss [ecx+edx+12], xmm3
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[8]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shl edx, 4
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
movss [ecx+edx+12], xmm3
|
|
|
|
shufps xmm5, xmm5, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
mov edx, usedVertNums[12]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
shl edx, 4
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 1, 2, 3, 0 )
|
|
|
|
movss [ecx+edx+0], xmm5
|
|
movss [ecx+edx+4], xmm6
|
|
movss [ecx+edx+8], xmm0
|
|
movss [ecx+edx+12], xmm3
|
|
|
|
xor ecx, ecx
|
|
jmp loopVert4
|
|
|
|
done4:
|
|
test ecx, ecx
|
|
jz done
|
|
xor eax, eax
|
|
mov edi, numVerts
|
|
shl edi, 4
|
|
add edi, texCoords
|
|
|
|
loopVert1:
|
|
movss xmm6, lightDir0[eax*4]
|
|
movss xmm0, xmm6
|
|
mulss xmm6, xmm6
|
|
movss xmm7, lightDir1[eax*4]
|
|
movss xmm1, xmm7
|
|
mulss xmm7, xmm7
|
|
addss xmm6, xmm7
|
|
movss xmm5, lightDir2[eax*4]
|
|
movss xmm2, xmm5
|
|
mulss xmm5, xmm5
|
|
addss xmm6, xmm5
|
|
rsqrtss xmm6, xmm6
|
|
|
|
mulss xmm0, xmm6
|
|
mulss xmm1, xmm6
|
|
mulss xmm2, xmm6
|
|
|
|
movss xmm3, viewDir0[eax*4]
|
|
movss xmm7, xmm3
|
|
mulss xmm7, xmm7
|
|
movss xmm4, viewDir1[eax*4]
|
|
movss xmm6, xmm4
|
|
mulss xmm6, xmm6
|
|
addss xmm7, xmm6
|
|
movss xmm5, viewDir2[eax*4]
|
|
movss xmm6, xmm5
|
|
mulss xmm6, xmm6
|
|
addss xmm7, xmm6
|
|
rsqrtss xmm7, xmm7
|
|
|
|
mulss xmm3, xmm7
|
|
addss xmm0, xmm3
|
|
mulss xmm4, xmm7
|
|
addss xmm1, xmm4
|
|
mulss xmm5, xmm7
|
|
addss xmm2, xmm5
|
|
|
|
mov edx, usedVertNums[eax*4]
|
|
shl edx, 4
|
|
|
|
movss xmm3, tangent0[eax*4]
|
|
mulss xmm3, xmm0
|
|
movss xmm4, tangent1[eax*4]
|
|
mulss xmm4, xmm1
|
|
addss xmm3, xmm4
|
|
movss xmm5, tangent2[eax*4]
|
|
mulss xmm5, xmm2
|
|
addss xmm5, xmm3
|
|
movss [edi+edx+0], xmm5
|
|
|
|
movss xmm3, tangent3[eax*4]
|
|
mulss xmm3, xmm0
|
|
movss xmm4, tangent4[eax*4]
|
|
mulss xmm4, xmm1
|
|
addss xmm3, xmm4
|
|
movss xmm6, tangent5[eax*4]
|
|
mulss xmm6, xmm2
|
|
addss xmm6, xmm3
|
|
movss [edi+edx+4], xmm6
|
|
|
|
mulss xmm0, normal0[eax*4]
|
|
mulss xmm1, normal1[eax*4]
|
|
addss xmm0, xmm1
|
|
mulss xmm2, normal2[eax*4]
|
|
addss xmm0, xmm2
|
|
movss [edi+edx+8], xmm0
|
|
|
|
movss xmm3, SIMD_SP_one
|
|
movss [edi+edx+12], xmm3
|
|
|
|
inc eax
|
|
dec ecx
|
|
jg loopVert1
|
|
|
|
done:
|
|
}
|
|
|
|
#else
|
|
|
|
ALIGN16( int usedVertNums[4] );
|
|
ALIGN16( float lightDir0[4] );
|
|
ALIGN16( float lightDir1[4] );
|
|
ALIGN16( float lightDir2[4] );
|
|
ALIGN16( float viewDir0[4] );
|
|
ALIGN16( float viewDir1[4] );
|
|
ALIGN16( float viewDir2[4] );
|
|
ALIGN16( float normal0[4] );
|
|
ALIGN16( float normal1[4] );
|
|
ALIGN16( float normal2[4] );
|
|
ALIGN16( float tangent0[4] );
|
|
ALIGN16( float tangent1[4] );
|
|
ALIGN16( float tangent2[4] );
|
|
ALIGN16( float tangent3[4] );
|
|
ALIGN16( float tangent4[4] );
|
|
ALIGN16( float tangent5[4] );
|
|
ALIGN16( float texCoords0[4] );
|
|
ALIGN16( float texCoords1[4] );
|
|
ALIGN16( float texCoords2[4] );
|
|
idVec3 localLightOrigin = lightOrigin;
|
|
idVec3 localViewOrigin = viewOrigin;
|
|
int numUsedVerts = 0;
|
|
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
if ( !used[i] ) {
|
|
continue;
|
|
}
|
|
|
|
const idDrawVert *v = &verts[i];
|
|
|
|
lightDir0[numUsedVerts] = localLightOrigin[0] - v->xyz[0];
|
|
lightDir1[numUsedVerts] = localLightOrigin[1] - v->xyz[1];
|
|
lightDir2[numUsedVerts] = localLightOrigin[2] - v->xyz[2];
|
|
|
|
viewDir0[numUsedVerts] = localViewOrigin[0] - v->xyz[0];
|
|
viewDir1[numUsedVerts] = localViewOrigin[1] - v->xyz[1];
|
|
viewDir2[numUsedVerts] = localViewOrigin[2] - v->xyz[2];
|
|
|
|
normal0[numUsedVerts] = v->normal[0];
|
|
normal1[numUsedVerts] = v->normal[1];
|
|
normal2[numUsedVerts] = v->normal[2];
|
|
|
|
tangent0[numUsedVerts] = v->tangents[0][0];
|
|
tangent1[numUsedVerts] = v->tangents[0][1];
|
|
tangent2[numUsedVerts] = v->tangents[0][2];
|
|
|
|
tangent3[numUsedVerts] = v->tangents[1][0];
|
|
tangent4[numUsedVerts] = v->tangents[1][1];
|
|
tangent5[numUsedVerts] = v->tangents[1][2];
|
|
|
|
usedVertNums[numUsedVerts++] = i;
|
|
if ( numUsedVerts < 4 ) {
|
|
continue;
|
|
}
|
|
|
|
ALIGN16( float temp[4] );
|
|
|
|
temp[0] = lightDir0[0] * lightDir0[0];
|
|
temp[1] = lightDir0[1] * lightDir0[1];
|
|
temp[2] = lightDir0[2] * lightDir0[2];
|
|
temp[3] = lightDir0[3] * lightDir0[3];
|
|
|
|
temp[0] += lightDir1[0] * lightDir1[0];
|
|
temp[1] += lightDir1[1] * lightDir1[1];
|
|
temp[2] += lightDir1[2] * lightDir1[2];
|
|
temp[3] += lightDir1[3] * lightDir1[3];
|
|
|
|
temp[0] += lightDir2[0] * lightDir2[0];
|
|
temp[1] += lightDir2[1] * lightDir2[1];
|
|
temp[2] += lightDir2[2] * lightDir2[2];
|
|
temp[3] += lightDir2[3] * lightDir2[3];
|
|
|
|
temp[0] = idMath::RSqrt( temp[0] );
|
|
temp[1] = idMath::RSqrt( temp[1] );
|
|
temp[2] = idMath::RSqrt( temp[2] );
|
|
temp[3] = idMath::RSqrt( temp[3] );
|
|
|
|
lightDir0[0] *= temp[0];
|
|
lightDir0[1] *= temp[1];
|
|
lightDir0[2] *= temp[2];
|
|
lightDir0[3] *= temp[3];
|
|
|
|
lightDir1[0] *= temp[0];
|
|
lightDir1[1] *= temp[1];
|
|
lightDir1[2] *= temp[2];
|
|
lightDir1[3] *= temp[3];
|
|
|
|
lightDir2[0] *= temp[0];
|
|
lightDir2[1] *= temp[1];
|
|
lightDir2[2] *= temp[2];
|
|
lightDir2[3] *= temp[3];
|
|
|
|
temp[0] = viewDir0[0] * viewDir0[0];
|
|
temp[1] = viewDir0[1] * viewDir0[1];
|
|
temp[2] = viewDir0[2] * viewDir0[2];
|
|
temp[3] = viewDir0[3] * viewDir0[3];
|
|
|
|
temp[0] += viewDir1[0] * viewDir1[0];
|
|
temp[1] += viewDir1[1] * viewDir1[1];
|
|
temp[2] += viewDir1[2] * viewDir1[2];
|
|
temp[3] += viewDir1[3] * viewDir1[3];
|
|
|
|
temp[0] += viewDir2[0] * viewDir2[0];
|
|
temp[1] += viewDir2[1] * viewDir2[1];
|
|
temp[2] += viewDir2[2] * viewDir2[2];
|
|
temp[3] += viewDir2[3] * viewDir2[3];
|
|
|
|
temp[0] = idMath::RSqrt( temp[0] );
|
|
temp[1] = idMath::RSqrt( temp[1] );
|
|
temp[2] = idMath::RSqrt( temp[2] );
|
|
temp[3] = idMath::RSqrt( temp[3] );
|
|
|
|
viewDir0[0] *= temp[0];
|
|
viewDir0[1] *= temp[1];
|
|
viewDir0[2] *= temp[2];
|
|
viewDir0[3] *= temp[3];
|
|
|
|
viewDir1[0] *= temp[0];
|
|
viewDir1[1] *= temp[1];
|
|
viewDir1[2] *= temp[2];
|
|
viewDir1[3] *= temp[3];
|
|
|
|
viewDir2[0] *= temp[0];
|
|
viewDir2[1] *= temp[1];
|
|
viewDir2[2] *= temp[2];
|
|
viewDir2[3] *= temp[3];
|
|
|
|
lightDir0[0] += viewDir0[0];
|
|
lightDir0[1] += viewDir0[1];
|
|
lightDir0[2] += viewDir0[2];
|
|
lightDir0[3] += viewDir0[3];
|
|
|
|
lightDir1[0] += viewDir1[0];
|
|
lightDir1[1] += viewDir1[1];
|
|
lightDir1[2] += viewDir1[2];
|
|
lightDir1[3] += viewDir1[3];
|
|
|
|
lightDir2[0] += viewDir2[0];
|
|
lightDir2[1] += viewDir2[1];
|
|
lightDir2[2] += viewDir2[2];
|
|
lightDir2[3] += viewDir2[3];
|
|
|
|
texCoords0[0] = lightDir0[0] * tangent0[0];
|
|
texCoords0[1] = lightDir0[1] * tangent0[1];
|
|
texCoords0[2] = lightDir0[2] * tangent0[2];
|
|
texCoords0[3] = lightDir0[3] * tangent0[3];
|
|
|
|
texCoords0[0] += lightDir1[0] * tangent1[0];
|
|
texCoords0[1] += lightDir1[1] * tangent1[1];
|
|
texCoords0[2] += lightDir1[2] * tangent1[2];
|
|
texCoords0[3] += lightDir1[3] * tangent1[3];
|
|
|
|
texCoords0[0] += lightDir2[0] * tangent2[0];
|
|
texCoords0[1] += lightDir2[1] * tangent2[1];
|
|
texCoords0[2] += lightDir2[2] * tangent2[2];
|
|
texCoords0[3] += lightDir2[3] * tangent2[3];
|
|
|
|
texCoords1[0] = lightDir0[0] * tangent3[0];
|
|
texCoords1[1] = lightDir0[1] * tangent3[1];
|
|
texCoords1[2] = lightDir0[2] * tangent3[2];
|
|
texCoords1[3] = lightDir0[3] * tangent3[3];
|
|
|
|
texCoords1[0] += lightDir1[0] * tangent4[0];
|
|
texCoords1[1] += lightDir1[1] * tangent4[1];
|
|
texCoords1[2] += lightDir1[2] * tangent4[2];
|
|
texCoords1[3] += lightDir1[3] * tangent4[3];
|
|
|
|
texCoords1[0] += lightDir2[0] * tangent5[0];
|
|
texCoords1[1] += lightDir2[1] * tangent5[1];
|
|
texCoords1[2] += lightDir2[2] * tangent5[2];
|
|
texCoords1[3] += lightDir2[3] * tangent5[3];
|
|
|
|
texCoords2[0] = lightDir0[0] * normal0[0];
|
|
texCoords2[1] = lightDir0[1] * normal0[1];
|
|
texCoords2[2] = lightDir0[2] * normal0[2];
|
|
texCoords2[3] = lightDir0[3] * normal0[3];
|
|
|
|
texCoords2[0] += lightDir1[0] * normal1[0];
|
|
texCoords2[1] += lightDir1[1] * normal1[1];
|
|
texCoords2[2] += lightDir1[2] * normal1[2];
|
|
texCoords2[3] += lightDir1[3] * normal1[3];
|
|
|
|
texCoords2[0] += lightDir2[0] * normal2[0];
|
|
texCoords2[1] += lightDir2[1] * normal2[1];
|
|
texCoords2[2] += lightDir2[2] * normal2[2];
|
|
texCoords2[3] += lightDir2[3] * normal2[3];
|
|
|
|
for ( int j = 0; j < 4; j++ ) {
|
|
int n = usedVertNums[j];
|
|
|
|
texCoords[n][0] = texCoords0[j];
|
|
texCoords[n][1] = texCoords1[j];
|
|
texCoords[n][2] = texCoords2[j];
|
|
texCoords[n][3] = 1.0f;
|
|
}
|
|
|
|
numUsedVerts = 0;
|
|
}
|
|
|
|
for ( int i = 0; i < numUsedVerts; i++ ) {
|
|
float temp;
|
|
|
|
temp = lightDir0[i] * lightDir0[i] + lightDir1[i] * lightDir1[i] + lightDir2[i] * lightDir2[i];
|
|
temp = idMath::RSqrt( temp );
|
|
|
|
lightDir0[i] *= temp;
|
|
lightDir1[i] *= temp;
|
|
lightDir2[i] *= temp;
|
|
|
|
temp = viewDir0[i] * viewDir0[i] + viewDir1[i] * viewDir1[i] + viewDir2[i] * viewDir2[i];
|
|
temp = idMath::RSqrt( temp );
|
|
|
|
viewDir0[i] *= temp;
|
|
viewDir1[i] *= temp;
|
|
viewDir2[i] *= temp;
|
|
|
|
lightDir0[i] += viewDir0[i];
|
|
lightDir1[i] += viewDir1[i];
|
|
lightDir2[i] += viewDir2[i];
|
|
|
|
texCoords0[i] = lightDir0[i] * tangent0[i] + lightDir1[i] * tangent1[i] + lightDir2[i] * tangent2[i];
|
|
texCoords1[i] = lightDir0[i] * tangent3[i] + lightDir1[i] * tangent4[i] + lightDir2[i] * tangent5[i];
|
|
texCoords2[i] = lightDir0[i] * normal0[i] + lightDir1[i] * normal1[i] + lightDir2[i] * normal2[i];
|
|
|
|
int n = usedVertNums[i];
|
|
texCoords[n][0] = texCoords0;
|
|
texCoords[n][1] = texCoords1;
|
|
texCoords[n][2] = texCoords2;
|
|
texCoords[n][3] = 1.0f;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CreateShadowCache
|
|
============
|
|
*/
|
|
int VPCALL idSIMD_SSE::CreateShadowCache( idVec4 *vertexCache, int *vertRemap, const idVec3 &lightOrigin, const idDrawVert *verts, const int numVerts ) {
|
|
#if 1
|
|
int outVerts;
|
|
|
|
__asm {
|
|
push ebx
|
|
|
|
mov esi, lightOrigin
|
|
movaps xmm5, SIMD_SP_lastOne
|
|
movss xmm6, [esi+0]
|
|
movhps xmm6, [esi+4]
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 2, 3, 1 )
|
|
orps xmm6, SIMD_SP_lastOne
|
|
movaps xmm7, xmm6
|
|
|
|
xor ebx, ebx
|
|
xor ecx, ecx
|
|
|
|
mov edx, vertRemap
|
|
mov esi, verts
|
|
mov edi, vertexCache
|
|
mov eax, numVerts
|
|
and eax, ~3
|
|
jz done4
|
|
shl eax, 2
|
|
add edx, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
prefetchnta [edx+128]
|
|
prefetchnta [esi+4*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET]
|
|
|
|
cmp dword ptr [edx+eax+0], ebx
|
|
jne skip1
|
|
|
|
mov dword ptr [edx+eax+0], ecx
|
|
movss xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
add ecx, 2
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 3, 0, 1 );
|
|
orps xmm0, xmm5
|
|
movaps [edi+0*16], xmm0
|
|
subps xmm0, xmm6
|
|
movaps [edi+1*16], xmm0
|
|
add edi, 2*16
|
|
|
|
skip1:
|
|
cmp dword ptr [edx+eax+4], ebx
|
|
jne skip2
|
|
|
|
mov dword ptr [edx+eax+4], ecx
|
|
movss xmm1, [esi+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm1, [esi+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
add ecx, 2
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 3, 1 )
|
|
orps xmm1, xmm5
|
|
movaps [edi+0*16], xmm1
|
|
subps xmm1, xmm7
|
|
movaps [edi+1*16], xmm1
|
|
add edi, 2*16
|
|
|
|
skip2:
|
|
cmp dword ptr [edx+eax+8], ebx
|
|
jne skip3
|
|
|
|
mov dword ptr [edx+eax+8], ecx
|
|
movss xmm2, [esi+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm2, [esi+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
add ecx, 2
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 3, 0, 1 );
|
|
orps xmm2, xmm5
|
|
movaps [edi+0*16], xmm2
|
|
subps xmm2, xmm6
|
|
movaps [edi+1*16], xmm2
|
|
add edi, 2*16
|
|
|
|
skip3:
|
|
cmp dword ptr [edx+eax+12], ebx
|
|
jne skip4
|
|
|
|
mov dword ptr [edx+eax+12], ecx
|
|
movss xmm3, [esi+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm3, [esi+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
add ecx, 2
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 2, 3, 1 )
|
|
orps xmm3, xmm5
|
|
movaps [edi+0*16], xmm3
|
|
subps xmm3, xmm7
|
|
movaps [edi+1*16], xmm3
|
|
add edi, 2*16
|
|
|
|
skip4:
|
|
add esi, 4*DRAWVERT_SIZE
|
|
add eax, 4*4
|
|
jl loop4
|
|
|
|
done4:
|
|
mov eax, numVerts
|
|
and eax, 3
|
|
jz done1
|
|
shl eax, 2
|
|
add edx, eax
|
|
neg eax
|
|
|
|
loop1:
|
|
cmp dword ptr [edx+eax+0], ebx
|
|
jne skip0
|
|
|
|
mov dword ptr [edx+eax+0], ecx
|
|
movss xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
add ecx, 2
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
orps xmm0, xmm5
|
|
movaps [edi+0*16], xmm0
|
|
subps xmm0, xmm6
|
|
movaps [edi+1*16], xmm0
|
|
add edi, 2*16
|
|
|
|
skip0:
|
|
|
|
add esi, DRAWVERT_SIZE
|
|
add eax, 4
|
|
jl loop1
|
|
|
|
done1:
|
|
pop ebx
|
|
mov outVerts, ecx
|
|
}
|
|
return outVerts;
|
|
|
|
#else
|
|
|
|
int outVerts = 0;
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
if ( vertRemap[i] ) {
|
|
continue;
|
|
}
|
|
const float *v = verts[i].xyz.ToFloatPtr();
|
|
vertexCache[outVerts+0][0] = v[0];
|
|
vertexCache[outVerts+0][1] = v[1];
|
|
vertexCache[outVerts+0][2] = v[2];
|
|
vertexCache[outVerts+0][3] = 1.0f;
|
|
|
|
// R_SetupProjection() builds the projection matrix with a slight crunch
|
|
// for depth, which keeps this w=0 division from rasterizing right at the
|
|
// wrap around point and causing depth fighting with the rear caps
|
|
vertexCache[outVerts+1][0] = v[0] - lightOrigin[0];
|
|
vertexCache[outVerts+1][1] = v[1] - lightOrigin[1];
|
|
vertexCache[outVerts+1][2] = v[2] - lightOrigin[2];
|
|
vertexCache[outVerts+1][3] = 0.0f;
|
|
vertRemap[i] = outVerts;
|
|
outVerts += 2;
|
|
}
|
|
return outVerts;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::CreateVertexProgramShadowCache
|
|
============
|
|
*/
|
|
int VPCALL idSIMD_SSE::CreateVertexProgramShadowCache( idVec4 *vertexCache, const idDrawVert *verts, const int numVerts ) {
|
|
#if 1
|
|
|
|
__asm {
|
|
movaps xmm4, SIMD_SP_lastOne
|
|
movaps xmm5, xmm4
|
|
movaps xmm6, xmm4
|
|
movaps xmm7, xmm4
|
|
|
|
mov esi, verts
|
|
mov edi, vertexCache
|
|
mov eax, numVerts
|
|
and eax, ~3
|
|
jz done4
|
|
shl eax, 5
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loop4:
|
|
prefetchnta [esi+4*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET]
|
|
|
|
movss xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 3, 0, 1 );
|
|
movaps [edi+eax+1*16], xmm0
|
|
orps xmm0, xmm4
|
|
movaps [edi+eax+0*16], xmm0
|
|
|
|
movss xmm1, [esi+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm1, [esi+1*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 2, 3, 1 )
|
|
movaps [edi+eax+3*16], xmm1
|
|
orps xmm1, xmm5
|
|
movaps [edi+eax+2*16], xmm1
|
|
|
|
movss xmm2, [esi+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm2, [esi+2*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 2, 3, 0, 1 );
|
|
movaps [edi+eax+5*16], xmm2
|
|
orps xmm2, xmm6
|
|
movaps [edi+eax+4*16], xmm2
|
|
|
|
movss xmm3, [esi+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
movhps xmm3, [esi+3*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+4]
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 0, 2, 3, 1 )
|
|
movaps [edi+eax+7*16], xmm3
|
|
orps xmm3, xmm7
|
|
movaps [edi+eax+6*16], xmm3
|
|
|
|
add esi, 4*DRAWVERT_SIZE
|
|
add eax, 4*8*4
|
|
jl loop4
|
|
|
|
done4:
|
|
mov eax, numVerts
|
|
and eax, 3
|
|
jz done1
|
|
shl eax, 5
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loop1:
|
|
movss xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+8]
|
|
movhps xmm0, [esi+0*DRAWVERT_SIZE+DRAWVERT_XYZ_OFFSET+0]
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 3, 0, 1 );
|
|
movaps [edi+eax+1*16], xmm0
|
|
orps xmm0, xmm4
|
|
movaps [edi+eax+0*16], xmm0
|
|
|
|
add esi, DRAWVERT_SIZE
|
|
add eax, 8*4
|
|
jl loop1
|
|
|
|
done1:
|
|
}
|
|
return numVerts * 2;
|
|
|
|
#else
|
|
|
|
for ( int i = 0; i < numVerts; i++ ) {
|
|
const float *v = verts[i].xyz.ToFloatPtr();
|
|
vertexCache[i*2+0][0] = v[0];
|
|
vertexCache[i*2+0][1] = v[1];
|
|
vertexCache[i*2+0][2] = v[2];
|
|
vertexCache[i*2+0][3] = 1.0f;
|
|
|
|
vertexCache[i*2+1][0] = v[0];
|
|
vertexCache[i*2+1][1] = v[1];
|
|
vertexCache[i*2+1][2] = v[2];
|
|
vertexCache[i*2+1][3] = 0.0f;
|
|
}
|
|
return numVerts * 2;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample11kHzMonoPCMTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample11kHzMonoPCMTo44kHz( float *dest, const short *src, const int numSamples ) {
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 2*4*4
|
|
|
|
movsx ecx, word ptr [esi+eax+0]
|
|
cvtsi2ss xmm0, ecx
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi-2*4*4+0], xmm0
|
|
movhps [edi-2*4*4+8], xmm0
|
|
|
|
movsx edx, word ptr [esi+eax+2]
|
|
cvtsi2ss xmm1, edx
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi-1*4*4+0], xmm1
|
|
movhps [edi-1*4*4+8], xmm1
|
|
|
|
add eax, 2*2
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movsx ecx, word ptr [esi]
|
|
cvtsi2ss xmm0, ecx
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi+0], xmm0
|
|
movhps [edi+8], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample11kHzStereoPCMTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample11kHzStereoPCMTo44kHz( float *dest, const short *src, const int numSamples ) {
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
|
|
mov eax, numSamples
|
|
test eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 8*4
|
|
|
|
movsx ecx, word ptr [esi+eax+0]
|
|
cvtsi2ss xmm0, ecx
|
|
|
|
movsx edx, word ptr [esi+eax+2]
|
|
cvtsi2ss xmm1, edx
|
|
|
|
unpcklps xmm0, xmm1
|
|
|
|
movlps [edi-8*4+0], xmm0
|
|
movlps [edi-8*4+8], xmm0
|
|
movlps [edi-4*4+0], xmm0
|
|
movlps [edi-4*4+8], xmm0
|
|
|
|
add eax, 2*2
|
|
jl loop2
|
|
|
|
done2:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample22kHzMonoPCMTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample22kHzMonoPCMTo44kHz( float *dest, const short *src, const int numSamples ) {
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 4*4
|
|
|
|
movsx ecx, word ptr [esi+eax+0]
|
|
cvtsi2ss xmm0, ecx
|
|
|
|
movsx edx, word ptr [esi+eax+2]
|
|
cvtsi2ss xmm1, edx
|
|
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi-4*4+0], xmm0
|
|
movhps [edi-4*4+8], xmm0
|
|
|
|
add eax, 2*2
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movsx ecx, word ptr [esi]
|
|
cvtsi2ss xmm0, ecx
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample22kHzStereoPCMTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample22kHzStereoPCMTo44kHz( float *dest, const short *src, const int numSamples ) {
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
|
|
mov eax, numSamples
|
|
test eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 4*4
|
|
|
|
movsx ecx, word ptr [esi+eax+0]
|
|
cvtsi2ss xmm0, ecx
|
|
movss [edi-4*4], xmm0
|
|
movss [edi-2*4], xmm0
|
|
|
|
movsx edx, word ptr [esi+eax+2]
|
|
cvtsi2ss xmm1, edx
|
|
movss [edi-3*4], xmm1
|
|
movss [edi-1*4], xmm1
|
|
|
|
add eax, 2*2
|
|
jl loop2
|
|
|
|
done2:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample44kHzMonoPCMTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample44kHzMonoPCMTo44kHz( float *dest, const short *src, const int numSamples ) {
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 2*4
|
|
|
|
movsx ecx, word ptr [esi+eax+0]
|
|
cvtsi2ss xmm0, ecx
|
|
movss [edi-2*4], xmm0
|
|
|
|
movsx edx, word ptr [esi+eax+2]
|
|
cvtsi2ss xmm1, edx
|
|
movss [edi-1*4], xmm1
|
|
|
|
add eax, 2*2
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movsx ecx, word ptr [esi]
|
|
cvtsi2ss xmm0, ecx
|
|
movss [edi], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::UpSamplePCMTo44kHz
|
|
|
|
Duplicate samples for 44kHz output.
|
|
============
|
|
*/
|
|
void idSIMD_SSE::UpSamplePCMTo44kHz( float *dest, const short *src, const int numSamples, const int kHz, const int numChannels ) {
|
|
if ( kHz == 11025 ) {
|
|
if ( numChannels == 1 ) {
|
|
SSE_UpSample11kHzMonoPCMTo44kHz( dest, src, numSamples );
|
|
} else {
|
|
SSE_UpSample11kHzStereoPCMTo44kHz( dest, src, numSamples );
|
|
}
|
|
} else if ( kHz == 22050 ) {
|
|
if ( numChannels == 1 ) {
|
|
SSE_UpSample22kHzMonoPCMTo44kHz( dest, src, numSamples );
|
|
} else {
|
|
SSE_UpSample22kHzStereoPCMTo44kHz( dest, src, numSamples );
|
|
}
|
|
} else if ( kHz == 44100 ) {
|
|
SSE_UpSample44kHzMonoPCMTo44kHz( dest, src, numSamples );
|
|
} else {
|
|
assert( 0 );
|
|
}
|
|
}
|
|
|
|
|
|
// DG: at least in the 22KHz Stereo OGG case with numSamples % 4 != 0 this is broken (writes 4 floats too much which can destroy the stack, see #303),
|
|
// so let's just not use it anymore its MSVC+32bit only anyway and I doubt it gets noticable speedups, so I don't feel like trying to understand and fix it..
|
|
#if 0
|
|
/*
|
|
============
|
|
SSE_UpSample11kHzMonoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample11kHzMonoOGGTo44kHz( float *dest, const float *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
movss xmm7, constant
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 2
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 2*16
|
|
|
|
movss xmm0, [esi+eax+0]
|
|
mulss xmm0, xmm7
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi-32], xmm0
|
|
movlps [edi-24], xmm0
|
|
|
|
movss xmm1, [esi+eax+4]
|
|
mulss xmm1, xmm7
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi-16], xmm1
|
|
movlps [edi- 8], xmm1
|
|
|
|
add eax, 2*4
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [esi]
|
|
mulss xmm0, xmm7
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi+0], xmm0
|
|
movlps [edi+8], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample11kHzStereoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample11kHzStereoOGGTo44kHz( float *dest, const float * const *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
__asm {
|
|
mov esi, src
|
|
mov ecx, [esi+0]
|
|
mov edx, [esi+4]
|
|
mov edi, dest
|
|
movss xmm7, constant
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 4*16
|
|
|
|
movlps xmm0, [ecx+eax]
|
|
movlps xmm1, [edx+eax]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi-8*8], xmm0
|
|
movlps [edi-7*8], xmm0
|
|
movlps [edi-6*8], xmm0
|
|
movlps [edi-5*8], xmm0
|
|
movhps [edi-4*8], xmm0
|
|
movhps [edi-3*8], xmm0
|
|
movhps [edi-2*8], xmm0
|
|
movhps [edi-1*8], xmm0
|
|
|
|
add eax, 2*4
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [ecx]
|
|
movss xmm1, [edx]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi+0*8], xmm0
|
|
movlps [edi+1*8], xmm0
|
|
movlps [edi+2*8], xmm0
|
|
movlps [edi+3*8], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample22kHzMonoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample22kHzMonoOGGTo44kHz( float *dest, const float *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
__asm {
|
|
mov esi, src
|
|
mov edi, dest
|
|
movss xmm7, constant
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 2
|
|
add esi, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 2*8
|
|
|
|
movss xmm0, [esi+eax+0]
|
|
movss xmm1, [esi+eax+4]
|
|
shufps xmm0, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm0, xmm7
|
|
movlps [edi-16], xmm0
|
|
movhps [edi- 8], xmm0
|
|
|
|
add eax, 2*4
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [esi]
|
|
mulss xmm0, xmm7
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
movlps [edi+0], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample22kHzStereoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample22kHzStereoOGGTo44kHz( float *dest, const float * const *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
__asm {
|
|
mov esi, src
|
|
mov ecx, [esi+0]
|
|
mov edx, [esi+4]
|
|
mov edi, dest
|
|
movss xmm7, constant
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 2*16
|
|
|
|
movlps xmm0, [ecx+eax]
|
|
movlps xmm1, [edx+eax]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi-4*8], xmm0
|
|
movlps [edi-3*8], xmm0
|
|
movhps [edi-2*8], xmm0
|
|
movhps [edi-1*8], xmm0
|
|
|
|
add eax, 2*4
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [ecx]
|
|
movss xmm1, [edx]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi+0*8], xmm0
|
|
movlps [edi+1*8], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample44kHzMonoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample44kHzMonoOGGTo44kHz( float *dest, const float *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
KFLOAT_CA( mul, dest, src, constant, numSamples )
|
|
}
|
|
|
|
/*
|
|
============
|
|
SSE_UpSample44kHzStereoOGGTo44kHz
|
|
============
|
|
*/
|
|
static void SSE_UpSample44kHzStereoOGGTo44kHz( float *dest, const float * const *src, const int numSamples ) {
|
|
float constant = 32768.0f;
|
|
__asm {
|
|
mov esi, src
|
|
mov ecx, [esi+0]
|
|
mov edx, [esi+4]
|
|
mov edi, dest
|
|
movss xmm7, constant
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
|
|
mov eax, numSamples
|
|
and eax, ~1
|
|
jz done2
|
|
shl eax, 1
|
|
add ecx, eax
|
|
add edx, eax
|
|
neg eax
|
|
|
|
align 16
|
|
loop2:
|
|
add edi, 16
|
|
|
|
movlps xmm0, [ecx+eax]
|
|
movlps xmm1, [edx+eax]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi-2*8], xmm0
|
|
movhps [edi-1*8], xmm0
|
|
|
|
add eax, 2*4
|
|
jl loop2
|
|
|
|
done2:
|
|
mov eax, numSamples
|
|
and eax, 1
|
|
jz done
|
|
|
|
movss xmm0, [ecx]
|
|
movss xmm1, [edx]
|
|
unpcklps xmm0, xmm1
|
|
mulps xmm0, xmm7
|
|
movlps [edi+0*8], xmm0
|
|
|
|
done:
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::UpSampleOGGTo44kHz
|
|
|
|
Duplicate samples for 44kHz output.
|
|
============
|
|
*/
|
|
void idSIMD_SSE::UpSampleOGGTo44kHz( float *dest, const float * const *ogg, const int numSamples, const int kHz, const int numChannels ) {
|
|
if ( kHz == 11025 ) {
|
|
if ( numChannels == 1 ) {
|
|
SSE_UpSample11kHzMonoOGGTo44kHz( dest, ogg[0], numSamples );
|
|
} else {
|
|
SSE_UpSample11kHzStereoOGGTo44kHz( dest, ogg, numSamples );
|
|
}
|
|
} else if ( kHz == 22050 ) {
|
|
if ( numChannels == 1 ) {
|
|
SSE_UpSample22kHzMonoOGGTo44kHz( dest, ogg[0], numSamples );
|
|
} else {
|
|
SSE_UpSample22kHzStereoOGGTo44kHz( dest, ogg, numSamples );
|
|
}
|
|
} else if ( kHz == 44100 ) {
|
|
if ( numChannels == 1 ) {
|
|
SSE_UpSample44kHzMonoOGGTo44kHz( dest, ogg[0], numSamples );
|
|
} else {
|
|
SSE_UpSample44kHzStereoOGGTo44kHz( dest, ogg, numSamples );
|
|
}
|
|
} else {
|
|
assert( 0 );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MixSoundTwoSpeakerMono
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MixSoundTwoSpeakerMono( float *mixBuffer, const float *samples, const int numSamples, const float lastV[2], const float currentV[2] ) {
|
|
#if 1
|
|
|
|
ALIGN16( float incs[2] );
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incs[0] = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incs[1] = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
|
|
__asm {
|
|
mov eax, MIXBUFFER_SAMPLES
|
|
mov edi, mixBuffer
|
|
mov esi, samples
|
|
shl eax, 2
|
|
add esi, eax
|
|
neg eax
|
|
|
|
mov ecx, lastV
|
|
movlps xmm6, [ecx]
|
|
xorps xmm7, xmm7
|
|
movhps xmm7, incs
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
addps xmm6, xmm7
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 2, 3, 2, 3 )
|
|
addps xmm7, xmm7
|
|
|
|
loop16:
|
|
add edi, 4*4*4
|
|
|
|
movaps xmm0, [esi+eax+0*4*4]
|
|
movaps xmm1, xmm0
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
mulps xmm0, xmm6
|
|
addps xmm0, [edi-4*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-4*4*4], xmm0
|
|
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 2, 3, 3 )
|
|
mulps xmm1, xmm6
|
|
addps xmm1, [edi-3*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-3*4*4], xmm1
|
|
|
|
movaps xmm2, [esi+eax+1*4*4]
|
|
movaps xmm3, xmm2
|
|
shufps xmm2, xmm2, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
mulps xmm2, xmm6
|
|
addps xmm2, [edi-2*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-2*4*4], xmm2
|
|
|
|
shufps xmm3, xmm3, R_SHUFFLEPS( 2, 2, 3, 3 )
|
|
mulps xmm3, xmm6
|
|
addps xmm3, [edi-1*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-1*4*4], xmm3
|
|
|
|
add eax, 2*4*4
|
|
|
|
jl loop16
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
float incL;
|
|
float incR;
|
|
float sL0, sL1;
|
|
float sR0, sR1;
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incL = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incR = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
|
|
sL0 = lastV[0];
|
|
sR0 = lastV[1];
|
|
sL1 = lastV[0] + incL;
|
|
sR1 = lastV[1] + incR;
|
|
|
|
incL *= 2;
|
|
incR *= 2;
|
|
|
|
for( i = 0; i < MIXBUFFER_SAMPLES; i += 2 ) {
|
|
mixBuffer[i*2+0] += samples[i+0] * sL0;
|
|
mixBuffer[i*2+1] += samples[i+0] * sR0;
|
|
mixBuffer[i*2+2] += samples[i+1] * sL1;
|
|
mixBuffer[i*2+3] += samples[i+1] * sR1;
|
|
sL0 += incL;
|
|
sR0 += incR;
|
|
sL1 += incL;
|
|
sR1 += incR;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MixSoundTwoSpeakerStereo
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MixSoundTwoSpeakerStereo( float *mixBuffer, const float *samples, const int numSamples, const float lastV[2], const float currentV[2] ) {
|
|
#if 1
|
|
|
|
ALIGN16( float incs[2] );
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incs[0] = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incs[1] = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
|
|
__asm {
|
|
mov eax, MIXBUFFER_SAMPLES
|
|
mov edi, mixBuffer
|
|
mov esi, samples
|
|
shl eax, 3
|
|
add esi, eax
|
|
neg eax
|
|
|
|
mov ecx, lastV
|
|
movlps xmm6, [ecx]
|
|
xorps xmm7, xmm7
|
|
movhps xmm7, incs
|
|
shufps xmm6, xmm6, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
addps xmm6, xmm7
|
|
shufps xmm7, xmm7, R_SHUFFLEPS( 2, 3, 2, 3 )
|
|
addps xmm7, xmm7
|
|
|
|
loop16:
|
|
add edi, 4*4*4
|
|
|
|
movaps xmm0, [esi+eax+0*4*4]
|
|
mulps xmm0, xmm6
|
|
addps xmm0, [edi-4*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-4*4*4], xmm0
|
|
|
|
movaps xmm2, [esi+eax+1*4*4]
|
|
mulps xmm2, xmm6
|
|
addps xmm2, [edi-3*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-3*4*4], xmm2
|
|
|
|
movaps xmm3, [esi+eax+2*4*4]
|
|
mulps xmm3, xmm6
|
|
addps xmm3, [edi-2*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-2*4*4], xmm3
|
|
|
|
movaps xmm4, [esi+eax+3*4*4]
|
|
mulps xmm4, xmm6
|
|
addps xmm4, [edi-1*4*4]
|
|
addps xmm6, xmm7
|
|
movaps [edi-1*4*4], xmm4
|
|
|
|
add eax, 4*4*4
|
|
|
|
jl loop16
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
float incL;
|
|
float incR;
|
|
float sL0, sL1;
|
|
float sR0, sR1;
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incL = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incR = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
|
|
sL0 = lastV[0];
|
|
sR0 = lastV[1];
|
|
sL1 = lastV[0] + incL;
|
|
sR1 = lastV[1] + incR;
|
|
|
|
incL *= 2;
|
|
incR *= 2;
|
|
|
|
for( i = 0; i < MIXBUFFER_SAMPLES; i += 2 ) {
|
|
mixBuffer[i*2+0] += samples[i*2+0] * sL0;
|
|
mixBuffer[i*2+1] += samples[i*2+1] * sR0;
|
|
mixBuffer[i*2+2] += samples[i*2+2] * sL1;
|
|
mixBuffer[i*2+3] += samples[i*2+3] * sR1;
|
|
sL0 += incL;
|
|
sR0 += incR;
|
|
sL1 += incL;
|
|
sR1 += incR;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MixSoundSixSpeakerMono
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MixSoundSixSpeakerMono( float *mixBuffer, const float *samples, const int numSamples, const float lastV[6], const float currentV[6] ) {
|
|
#if 1
|
|
|
|
ALIGN16( float incs[6] );
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incs[0] = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incs[1] = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
incs[2] = ( currentV[2] - lastV[2] ) / MIXBUFFER_SAMPLES;
|
|
incs[3] = ( currentV[3] - lastV[3] ) / MIXBUFFER_SAMPLES;
|
|
incs[4] = ( currentV[4] - lastV[4] ) / MIXBUFFER_SAMPLES;
|
|
incs[5] = ( currentV[5] - lastV[5] ) / MIXBUFFER_SAMPLES;
|
|
|
|
__asm {
|
|
mov eax, MIXBUFFER_SAMPLES
|
|
mov edi, mixBuffer
|
|
mov esi, samples
|
|
shl eax, 2
|
|
add esi, eax
|
|
neg eax
|
|
|
|
mov ecx, lastV
|
|
movlps xmm2, [ecx+ 0]
|
|
movhps xmm2, [ecx+ 8]
|
|
movlps xmm3, [ecx+16]
|
|
movaps xmm4, xmm2
|
|
shufps xmm3, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
shufps xmm4, xmm3, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
|
|
xorps xmm5, xmm5
|
|
movhps xmm5, incs
|
|
movlps xmm7, incs+8
|
|
movhps xmm7, incs+16
|
|
addps xmm3, xmm5
|
|
addps xmm4, xmm7
|
|
shufps xmm5, xmm7, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
movaps xmm6, xmm7
|
|
shufps xmm6, xmm5, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
addps xmm5, xmm5
|
|
addps xmm6, xmm6
|
|
addps xmm7, xmm7
|
|
|
|
loop24:
|
|
add edi, 6*16
|
|
|
|
movaps xmm0, [esi+eax]
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 0, 0 )
|
|
mulps xmm1, xmm2
|
|
addps xmm1, [edi-6*16]
|
|
addps xmm2, xmm5
|
|
movaps [edi-6*16], xmm1
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 0, 1, 1 )
|
|
mulps xmm1, xmm3
|
|
addps xmm1, [edi-5*16]
|
|
addps xmm3, xmm6
|
|
movaps [edi-5*16], xmm1
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 1, 1, 1, 1 )
|
|
mulps xmm1, xmm4
|
|
addps xmm1, [edi-4*16]
|
|
addps xmm4, xmm7
|
|
movaps [edi-4*16], xmm1
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 2, 2, 2 )
|
|
mulps xmm1, xmm2
|
|
addps xmm1, [edi-3*16]
|
|
addps xmm2, xmm5
|
|
movaps [edi-3*16], xmm1
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 2, 2, 3, 3 )
|
|
mulps xmm1, xmm3
|
|
addps xmm1, [edi-2*16]
|
|
addps xmm3, xmm6
|
|
movaps [edi-2*16], xmm1
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 3, 3, 3, 3 )
|
|
mulps xmm0, xmm4
|
|
addps xmm0, [edi-1*16]
|
|
addps xmm4, xmm7
|
|
movaps [edi-1*16], xmm0
|
|
|
|
add eax, 4*4
|
|
|
|
jl loop24
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
float sL0, sL1, sL2, sL3, sL4, sL5, sL6, sL7, sL8, sL9, sL10, sL11;
|
|
float incL0, incL1, incL2, incL3, incL4, incL5;
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
|
|
incL0 = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incL1 = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
incL2 = ( currentV[2] - lastV[2] ) / MIXBUFFER_SAMPLES;
|
|
incL3 = ( currentV[3] - lastV[3] ) / MIXBUFFER_SAMPLES;
|
|
incL4 = ( currentV[4] - lastV[4] ) / MIXBUFFER_SAMPLES;
|
|
incL5 = ( currentV[5] - lastV[5] ) / MIXBUFFER_SAMPLES;
|
|
|
|
sL0 = lastV[0];
|
|
sL1 = lastV[1];
|
|
sL2 = lastV[2];
|
|
sL3 = lastV[3];
|
|
sL4 = lastV[4];
|
|
sL5 = lastV[5];
|
|
|
|
sL6 = lastV[0] + incL0;
|
|
sL7 = lastV[1] + incL1;
|
|
sL8 = lastV[2] + incL2;
|
|
sL9 = lastV[3] + incL3;
|
|
sL10 = lastV[4] + incL4;
|
|
sL11 = lastV[5] + incL5;
|
|
|
|
incL0 *= 2;
|
|
incL1 *= 2;
|
|
incL2 *= 2;
|
|
incL3 *= 2;
|
|
incL4 *= 2;
|
|
incL5 *= 2;
|
|
|
|
for( i = 0; i <= MIXBUFFER_SAMPLES - 2; i += 2 ) {
|
|
mixBuffer[i*6+ 0] += samples[i+0] * sL0;
|
|
mixBuffer[i*6+ 1] += samples[i+0] * sL1;
|
|
mixBuffer[i*6+ 2] += samples[i+0] * sL2;
|
|
mixBuffer[i*6+ 3] += samples[i+0] * sL3;
|
|
|
|
mixBuffer[i*6+ 4] += samples[i+0] * sL4;
|
|
mixBuffer[i*6+ 5] += samples[i+0] * sL5;
|
|
mixBuffer[i*6+ 6] += samples[i+1] * sL6;
|
|
mixBuffer[i*6+ 7] += samples[i+1] * sL7;
|
|
|
|
mixBuffer[i*6+ 8] += samples[i+1] * sL8;
|
|
mixBuffer[i*6+ 9] += samples[i+1] * sL9;
|
|
mixBuffer[i*6+10] += samples[i+1] * sL10;
|
|
mixBuffer[i*6+11] += samples[i+1] * sL11;
|
|
|
|
sL0 += incL0;
|
|
sL1 += incL1;
|
|
sL2 += incL2;
|
|
sL3 += incL3;
|
|
|
|
sL4 += incL4;
|
|
sL5 += incL5;
|
|
sL6 += incL0;
|
|
sL7 += incL1;
|
|
|
|
sL8 += incL2;
|
|
sL9 += incL3;
|
|
sL10 += incL4;
|
|
sL11 += incL5;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MixSoundSixSpeakerStereo
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MixSoundSixSpeakerStereo( float *mixBuffer, const float *samples, const int numSamples, const float lastV[6], const float currentV[6] ) {
|
|
#if 1
|
|
|
|
ALIGN16( float incs[6] );
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
assert( SPEAKER_RIGHT == 1 );
|
|
assert( SPEAKER_BACKRIGHT == 5 );
|
|
|
|
incs[0] = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incs[1] = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
incs[2] = ( currentV[2] - lastV[2] ) / MIXBUFFER_SAMPLES;
|
|
incs[3] = ( currentV[3] - lastV[3] ) / MIXBUFFER_SAMPLES;
|
|
incs[4] = ( currentV[4] - lastV[4] ) / MIXBUFFER_SAMPLES;
|
|
incs[5] = ( currentV[5] - lastV[5] ) / MIXBUFFER_SAMPLES;
|
|
|
|
__asm {
|
|
mov eax, MIXBUFFER_SAMPLES
|
|
mov edi, mixBuffer
|
|
mov esi, samples
|
|
shl eax, 3
|
|
add esi, eax
|
|
neg eax
|
|
|
|
mov ecx, lastV
|
|
movlps xmm2, [ecx+ 0]
|
|
movhps xmm2, [ecx+ 8]
|
|
movlps xmm3, [ecx+16]
|
|
movaps xmm4, xmm2
|
|
shufps xmm3, xmm2, R_SHUFFLEPS( 0, 1, 0, 1 )
|
|
shufps xmm4, xmm3, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
|
|
xorps xmm5, xmm5
|
|
movhps xmm5, incs
|
|
movlps xmm7, incs+ 8
|
|
movhps xmm7, incs+16
|
|
addps xmm3, xmm5
|
|
addps xmm4, xmm7
|
|
shufps xmm5, xmm7, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
movaps xmm6, xmm7
|
|
shufps xmm6, xmm5, R_SHUFFLEPS( 2, 3, 0, 1 )
|
|
addps xmm5, xmm5
|
|
addps xmm6, xmm6
|
|
addps xmm7, xmm7
|
|
|
|
loop12:
|
|
add edi, 3*16
|
|
|
|
movaps xmm0, [esi+eax+0]
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 1, 0, 0 )
|
|
mulps xmm1, xmm2
|
|
addps xmm1, [edi-3*16]
|
|
addps xmm2, xmm5
|
|
movaps [edi-3*16], xmm1
|
|
|
|
movaps xmm1, xmm0
|
|
shufps xmm1, xmm1, R_SHUFFLEPS( 0, 1, 2, 3 )
|
|
mulps xmm1, xmm3
|
|
addps xmm1, [edi-2*16]
|
|
addps xmm3, xmm6
|
|
movaps [edi-2*16], xmm1
|
|
|
|
add eax, 4*4
|
|
|
|
shufps xmm0, xmm0, R_SHUFFLEPS( 2, 2, 2, 3 )
|
|
mulps xmm0, xmm4
|
|
addps xmm0, [edi-1*16]
|
|
addps xmm4, xmm7
|
|
movaps [edi-1*16], xmm0
|
|
|
|
jl loop12
|
|
|
|
emms
|
|
}
|
|
|
|
#else
|
|
|
|
int i;
|
|
float sL0, sL1, sL2, sL3, sL4, sL5, sL6, sL7, sL8, sL9, sL10, sL11;
|
|
float incL0, incL1, incL2, incL3, incL4, incL5;
|
|
|
|
assert( numSamples == MIXBUFFER_SAMPLES );
|
|
assert( SPEAKER_RIGHT == 1 );
|
|
assert( SPEAKER_BACKRIGHT == 5 );
|
|
|
|
incL0 = ( currentV[0] - lastV[0] ) / MIXBUFFER_SAMPLES;
|
|
incL1 = ( currentV[1] - lastV[1] ) / MIXBUFFER_SAMPLES;
|
|
incL2 = ( currentV[2] - lastV[2] ) / MIXBUFFER_SAMPLES;
|
|
incL3 = ( currentV[3] - lastV[3] ) / MIXBUFFER_SAMPLES;
|
|
incL4 = ( currentV[4] - lastV[4] ) / MIXBUFFER_SAMPLES;
|
|
incL5 = ( currentV[5] - lastV[5] ) / MIXBUFFER_SAMPLES;
|
|
|
|
sL0 = lastV[0];
|
|
sL1 = lastV[1];
|
|
sL2 = lastV[2];
|
|
sL3 = lastV[3];
|
|
sL4 = lastV[4];
|
|
sL5 = lastV[5];
|
|
|
|
sL6 = lastV[0] + incL0;
|
|
sL7 = lastV[1] + incL1;
|
|
sL8 = lastV[2] + incL2;
|
|
sL9 = lastV[3] + incL3;
|
|
sL10 = lastV[4] + incL4;
|
|
sL11 = lastV[5] + incL5;
|
|
|
|
incL0 *= 2;
|
|
incL1 *= 2;
|
|
incL2 *= 2;
|
|
incL3 *= 2;
|
|
incL4 *= 2;
|
|
incL5 *= 2;
|
|
|
|
for( i = 0; i <= MIXBUFFER_SAMPLES - 2; i += 2 ) {
|
|
mixBuffer[i*6+ 0] += samples[i*2+0+0] * sL0;
|
|
mixBuffer[i*6+ 1] += samples[i*2+0+1] * sL1;
|
|
mixBuffer[i*6+ 2] += samples[i*2+0+0] * sL2;
|
|
mixBuffer[i*6+ 3] += samples[i*2+0+0] * sL3;
|
|
|
|
mixBuffer[i*6+ 4] += samples[i*2+0+0] * sL4;
|
|
mixBuffer[i*6+ 5] += samples[i*2+0+1] * sL5;
|
|
mixBuffer[i*6+ 6] += samples[i*2+2+0] * sL6;
|
|
mixBuffer[i*6+ 7] += samples[i*2+2+1] * sL7;
|
|
|
|
mixBuffer[i*6+ 8] += samples[i*2+2+0] * sL8;
|
|
mixBuffer[i*6+ 9] += samples[i*2+2+0] * sL9;
|
|
mixBuffer[i*6+10] += samples[i*2+2+0] * sL10;
|
|
mixBuffer[i*6+11] += samples[i*2+2+1] * sL11;
|
|
|
|
sL0 += incL0;
|
|
sL1 += incL1;
|
|
sL2 += incL2;
|
|
sL3 += incL3;
|
|
|
|
sL4 += incL4;
|
|
sL5 += incL5;
|
|
sL6 += incL0;
|
|
sL7 += incL1;
|
|
|
|
sL8 += incL2;
|
|
sL9 += incL3;
|
|
sL10 += incL4;
|
|
sL11 += incL5;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
============
|
|
idSIMD_SSE::MixedSoundToSamples
|
|
============
|
|
*/
|
|
void VPCALL idSIMD_SSE::MixedSoundToSamples( short *samples, const float *mixBuffer, const int numSamples ) {
|
|
#if 1
|
|
|
|
assert( ( numSamples % MIXBUFFER_SAMPLES ) == 0 );
|
|
|
|
__asm {
|
|
|
|
mov eax, numSamples
|
|
mov edi, mixBuffer
|
|
mov esi, samples
|
|
shl eax, 2
|
|
add edi, eax
|
|
neg eax
|
|
|
|
loop16:
|
|
|
|
movaps xmm0, [edi+eax+0*16]
|
|
movaps xmm2, [edi+eax+1*16]
|
|
movaps xmm4, [edi+eax+2*16]
|
|
movaps xmm6, [edi+eax+3*16]
|
|
|
|
add esi, 4*4*2
|
|
|
|
movhlps xmm1, xmm0
|
|
movhlps xmm3, xmm2
|
|
movhlps xmm5, xmm4
|
|
movhlps xmm7, xmm6
|
|
|
|
prefetchnta [edi+eax+64]
|
|
|
|
cvtps2pi mm0, xmm0
|
|
cvtps2pi mm2, xmm2
|
|
cvtps2pi mm4, xmm4
|
|
cvtps2pi mm6, xmm6
|
|
|
|
prefetchnta [edi+eax+128]
|
|
|
|
cvtps2pi mm1, xmm1
|
|
cvtps2pi mm3, xmm3
|
|
cvtps2pi mm5, xmm5
|
|
cvtps2pi mm7, xmm7
|
|
|
|
add eax, 4*16
|
|
|
|
packssdw mm0, mm1
|
|
packssdw mm2, mm3
|
|
packssdw mm4, mm5
|
|
packssdw mm6, mm7
|
|
|
|
movq [esi-4*4*2], mm0
|
|
movq [esi-3*4*2], mm2
|
|
movq [esi-2*4*2], mm4
|
|
movq [esi-1*4*2], mm6
|
|
|
|
jl loop16
|
|
|
|
emms
|
|
}
|
|
|
|
#else
|
|
|
|
for ( int i = 0; i < numSamples; i++ ) {
|
|
if ( mixBuffer[i] <= -32768.0f ) {
|
|
samples[i] = -32768;
|
|
} else if ( mixBuffer[i] >= 32767.0f ) {
|
|
samples[i] = 32767;
|
|
} else {
|
|
samples[i] = (short) mixBuffer[i];
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
#endif /* _MSC_VER */
|