mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-02 09:03:37 +00:00
arm neon: add multivector versions of InverseTransformVectorNormalize
Arm neon performance is much better if more data can be loaded and processed. Four vectors. Opt level -O3 —————————————- runtime 100% - C function runtime 99% - Neon function runtime 56% - Neon 2x function runtime 36% - Neon 4x function Four vectors. Opt level -O2 —————————————- runtime 100% - C function runtime 71% - Neon function runtime 43% - Neon 2x function runtime 30% - Neon 4x function
This commit is contained in:
parent
79dca65a5d
commit
2acc3c7775
|
@ -87,3 +87,17 @@ End:
|
|||
}
|
||||
#endif // WIN32_ASM
|
||||
}
|
||||
|
||||
void InverseTransformVectorNormalize2x(float src0[3], float src1[3], float dst0[3], float dst1[3], float mtx[4][4] )
|
||||
{
|
||||
InverseTransformVectorNormalize(src0, dst0, mtx);
|
||||
InverseTransformVectorNormalize(src1, dst1, mtx);
|
||||
}
|
||||
|
||||
void InverseTransformVectorNormalize4x(float src0[3], float src1[3],float src2[3], float src3[3], float dst0[3], float dst1[3], float dst2[3], float dst3[3], float mtx[4][4] )
|
||||
{
|
||||
InverseTransformVectorNormalize(src0, dst0, mtx);
|
||||
InverseTransformVectorNormalize(src1, dst1, mtx);
|
||||
InverseTransformVectorNormalize(src2, dst2, mtx);
|
||||
InverseTransformVectorNormalize(src3, dst3, mtx);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ void MultMatrix(float m0[4][4], float m1[4][4], float dest[4][4]);
|
|||
void MultMatrix2(float m0[4][4], float m1[4][4]);
|
||||
void TransformVectorNormalize(float vec[3], float mtx[4][4]);
|
||||
void InverseTransformVectorNormalize(float src[3], float dst[3], float mtx[4][4]);
|
||||
void InverseTransformVectorNormalize2x(float src0[3], float src1[3], float dst0[3], float dst1[3], float mtx[4][4] );
|
||||
void InverseTransformVectorNormalize4x(float src0[3], float src1[3],float src2[3], float src3[3], float dst0[3], float dst1[3], float dst2[3], float dst3[3], float mtx[4][4] );
|
||||
void Normalize(float v[3]);
|
||||
float DotProduct(const float v0[3], const float v1[3]);
|
||||
|
||||
|
|
|
@ -139,3 +139,143 @@ void Normalize(float v[3])
|
|||
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
void InverseTransformVectorNormalize2x(float src0[3], float src1[3], float dst0[3], float dst1[3], float mtx[4][4] )
|
||||
{
|
||||
asm volatile (
|
||||
// Load src0
|
||||
"vld3.32 {d0[0],d1[0],d2[0]}, [%1] \n\t"
|
||||
// Load src1
|
||||
"vld3.32 {d0[1],d1[1],d2[1]}, [%3] \n\t"
|
||||
|
||||
// Load mtx
|
||||
"vld4.32 {d16, d18, d20, d22}, [%0]! \n\t"
|
||||
"vld4.32 {d17, d19, d21, d23}, [%0] \n\t"
|
||||
|
||||
// Multiply and add
|
||||
"vmul.f32 q2, q8, d0[0] \n\t" //q2 = q8*d0[0]
|
||||
"vmul.f32 q5, q8, d0[1] \n\t" //q5 = q8*d0[1]
|
||||
"vmla.f32 q2, q9, d1[0] \n\t" //q2 += q9*d1[0]
|
||||
"vmla.f32 q5, q9, d1[1] \n\t" //q5 += q9*d1[1]
|
||||
"vmla.f32 q2, q10, d2[0] \n\t" //q2 += q10*d2[0]
|
||||
"vmla.f32 q5, q10, d2[1] \n\t" //q5 += q10*d2[1]
|
||||
|
||||
// Normalize 2x
|
||||
"vmul.f32 d0, d4, d4 \n\t" //d0 = d4*d4
|
||||
"vmul.f32 d1, d10, d10 \n\t" //d1 = d10*d10
|
||||
"vpadd.f32 d0, d0, d0 \n\t" //d0 = d0[0] + d0[1]
|
||||
"vpadd.f32 d1, d1, d1 \n\t" //d1 = d1[0] + d1[1]
|
||||
"vmla.f32 d0, d5, d5 \n\t" //d0 += d5*d5
|
||||
"vmla.f32 d1, d11, d11 \n\t" //d1 += d11*d11
|
||||
|
||||
"vzip.32 d0, d1 \n\t" //d0[1] = d7[1];d7[1] = d0[1]
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
|
||||
"vmul.f32 q2, q2, d0[0] \n\t" //q2 = q2*d0[0]
|
||||
"vmul.f32 q5, q5, d0[1] \n\t" //q5 = q5*d0[1]
|
||||
|
||||
// Store dst0
|
||||
"vst1.32 {d4}, [%2]! \n\t" //dst = d4
|
||||
"vst1.32 {d5[0]}, [%2] \n\t" //dst += d5[0]
|
||||
// Store dst1
|
||||
"vst1.32 {d10}, [%4]! \n\t" //dst = d10
|
||||
"vst1.32 {d11[0]}, [%4] \n\t" //dst += d11[0]
|
||||
: "+r"(mtx), "+r"(src0), "+r"(dst0), "+r"(src1), "+r"(dst1) :
|
||||
: "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d16","d17","d18","d19",
|
||||
"d20","d21","d22","d23", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
void InverseTransformVectorNormalize4x(float src0[3], float src1[3],float src2[3], float src3[3], float dst0[3], float dst1[3], float dst2[3], float dst3[3], float mtx[4][4] )
|
||||
{
|
||||
asm volatile (
|
||||
// Load src0
|
||||
"vld3.32 {d0[0],d2[0],d4[0]}, [%1] \n\t"
|
||||
// Load src1
|
||||
"vld3.32 {d0[1],d2[1],d4[1]}, [%3] \n\t"
|
||||
// Load src2
|
||||
"vld3.32 {d1[0],d3[0],d5[0]}, [%5] \n\t"
|
||||
// Load src3
|
||||
"vld3.32 {d1[1],d3[1],d5[1]}, [%7] \n\t"
|
||||
|
||||
// Load mtx
|
||||
"vld4.32 {d16, d18, d20, d22}, [%0]! \n\t"
|
||||
"vld4.32 {d17, d19, d21, d23}, [%0] \n\t"
|
||||
|
||||
// Multiply and add
|
||||
"vmul.f32 q3, q8, d0[0] \n\t" //q3 = q8*d0[0]
|
||||
"vmul.f32 q4, q8, d0[1] \n\t" //q4 = q8*d0[1]
|
||||
"vmul.f32 q5, q8, d1[0] \n\t" //q5 = q8*d1[0]
|
||||
"vmul.f32 q6, q8, d1[1] \n\t" //q6 = q8*d1[1]
|
||||
"vmla.f32 q3, q9, d2[0] \n\t" //q3 += q9*d2[0]
|
||||
"vmla.f32 q4, q9, d2[1] \n\t" //q4 += q9*d2[1]
|
||||
"vmla.f32 q5, q9, d3[0] \n\t" //q5 += q9*d3[0]
|
||||
"vmla.f32 q6, q9, d3[1] \n\t" //q6 += q9*d3[1]
|
||||
"vmla.f32 q3, q10, d4[0] \n\t" //q3 += q10*d4[0]
|
||||
"vmla.f32 q4, q10, d4[1] \n\t" //q4 += q10*d4[1]
|
||||
"vmla.f32 q5, q10, d5[0] \n\t" //q5 += q10*d5[0]
|
||||
"vmla.f32 q6, q10, d5[1] \n\t" //q6 += q10*d5[1]
|
||||
|
||||
// Normalize 4x
|
||||
"vmul.f32 d0, d6, d6 \n\t" //d0 = d6*d6
|
||||
"vmul.f32 d1, d8, d8 \n\t" //d1 = d8*d8
|
||||
"vmul.f32 d2, d10, d10 \n\t" //d2 = d10*d10
|
||||
"vmul.f32 d3, d12, d12 \n\t" //d3 = d12*d12
|
||||
"vpadd.f32 d0, d0, d0 \n\t" //d0 = d0[0] + d0[1]
|
||||
"vpadd.f32 d1, d1, d1 \n\t" //d1 = d1[0] + d1[1]
|
||||
"vpadd.f32 d2, d2, d2 \n\t" //d2 = d2[0] + d2[1]
|
||||
"vpadd.f32 d3, d3, d3 \n\t" //d3 = d3[0] + d3[1]
|
||||
"vmla.f32 d0, d7, d7 \n\t" //d0 += d7*d7
|
||||
"vmla.f32 d1, d9, d9 \n\t" //d1 += d9*d9
|
||||
"vmla.f32 d2, d11, d11 \n\t" //d2 += d11*d11
|
||||
"vmla.f32 d3, d13, d13 \n\t" //d3 += d13*d13
|
||||
|
||||
"vzip.32 d0, d1 \n\t" //d0[1] = d7[1];d7[1] = d0[1]
|
||||
"vzip.32 d2, d3 \n\t" //d2[1] = d3[1];d3[1] = d2[1]
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vmov.f32 d3, d2 \n\t" //d3 = d2
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vrsqrte.f32 d2, d2 \n\t" //d2 = ~ 1.0 / sqrt(d2)
|
||||
"vmul.f32 d14, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vmul.f32 d16, d2, d3 \n\t" //d2 = d2 * d3
|
||||
"vrsqrts.f32 d15, d14, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vrsqrts.f32 d17, d16, d2 \n\t" //d17 = (3 - d2 * d16) / 2
|
||||
"vmul.f32 d0, d0, d15 \n\t" //d0 = d0 * d15
|
||||
"vmul.f32 d2, d2, d17 \n\t" //d2 = d2 * d17
|
||||
"vmul.f32 d14, d0, d1 \n\t" //d14 = d0 * d1
|
||||
"vmul.f32 d16, d2, d3 \n\t" //d16 = d2 * d3
|
||||
"vrsqrts.f32 d15, d14, d0 \n\t" //d15 = (3 - d0 * d14) / 2
|
||||
"vrsqrts.f32 d17, d16, d2 \n\t" //d17 = (3 - d2 * d16) / 2
|
||||
"vmul.f32 d0, d0, d15 \n\t" //d0 = d0 * d15
|
||||
"vmul.f32 d2, d2, d17 \n\t" //d2 = d2 * d17
|
||||
|
||||
"vmul.f32 q3, q3, d0[0] \n\t" //q2 = q2*d0[0]
|
||||
"vmul.f32 q4, q4, d0[1] \n\t" //q2 = q2*d0[0]
|
||||
"vmul.f32 q5, q5, d2[0] \n\t" //q2 = q2*d0[0]
|
||||
"vmul.f32 q6, q6, d2[1] \n\t" //q2 = q2*d0[0]
|
||||
|
||||
// Store dst0
|
||||
"vst1.32 {d6}, [%2]! \n\t" //dst0 = d4
|
||||
"vst1.32 {d7[0]}, [%2] \n\t" //dst0 += d5[0]
|
||||
// Store dst1
|
||||
"vst1.32 {d8}, [%4]! \n\t" //dst1 = d4
|
||||
"vst1.32 {d9[0]}, [%4] \n\t" //dst1 += d5[0]
|
||||
// Store dst2
|
||||
"vst1.32 {d10}, [%6]! \n\t" //dst2 = d4
|
||||
"vst1.32 {d11[0]}, [%6] \n\t" //dst2 += d5[0]
|
||||
// Store dst3
|
||||
"vst1.32 {d12}, [%8]! \n\t" //dst3 = d4
|
||||
"vst1.32 {d13[0]}, [%8] \n\t" //dst3 += d5[0]
|
||||
|
||||
: "+r"(mtx), "+r"(src0), "+r"(dst0), "+r"(src1), "+r"(dst1), "+r"(src2), "+r"(dst2), "+r"(src3), "+r"(dst3) :
|
||||
: "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d12","d13","d14","d15","d16","d17","d18","d19",
|
||||
"d20","d21","d22","d23", "memory"
|
||||
);
|
||||
}
|
||||
|
|
22
src/gSP.cpp
22
src/gSP.cpp
|
@ -902,8 +902,21 @@ void gSPLookAt( u32 _l, u32 _n )
|
|||
static
|
||||
void gSPUpdateLightVectors()
|
||||
{
|
||||
for (u32 l = 0; l < gSP.numLights; ++l)
|
||||
InverseTransformVectorNormalize(&gSP.lights[l].x, &gSP.lights[l].ix, gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
s32 count = gSP.numLights;
|
||||
while (count >= 4) {
|
||||
InverseTransformVectorNormalize4x(&gSP.lights[count-1].x, &gSP.lights[count-2].x,&gSP.lights[count-3].x, &gSP.lights[count-4].x,
|
||||
&gSP.lights[count-1].ix, &gSP.lights[count-2].ix,&gSP.lights[count-3].ix, &gSP.lights[count-4].ix,
|
||||
gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
count -= 4;
|
||||
}
|
||||
if (count >= 2){
|
||||
InverseTransformVectorNormalize2x(&gSP.lights[count - 1].x, &gSP.lights[count - 2].x,
|
||||
&gSP.lights[count - 1].ix, &gSP.lights[count - 2].ix,
|
||||
gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
count -= 2;
|
||||
}
|
||||
if (count == 1)
|
||||
InverseTransformVectorNormalize(&gSP.lights[0].x, &gSP.lights[0].ix, gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
gSP.changed ^= CHANGED_LIGHT;
|
||||
gSP.changed |= CHANGED_HW_LIGHT;
|
||||
}
|
||||
|
@ -912,8 +925,9 @@ static
|
|||
void gSPUpdateLookatVectors()
|
||||
{
|
||||
if (gSP.lookatEnable) {
|
||||
for (u32 l = 0; l < 2; ++l)
|
||||
InverseTransformVectorNormalize(&gSP.lookat[l].x, &gSP.lookat[l].ix, gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
InverseTransformVectorNormalize2x(&gSP.lookat[0].x, &gSP.lookat[1].x,
|
||||
&gSP.lookat[0].ix, &gSP.lookat[1].ix,
|
||||
gSP.matrix.modelView[gSP.matrix.modelViewi]);
|
||||
}
|
||||
gSP.changed ^= CHANGED_LOOKAT;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user