从网上看到说,VC会放弃对含有内联汇编代码的函数,这是错误的。
我试验了一下,VC照样会内联含有汇编代码的函数,只要汇编代码里面不要有跳转到C++代码段的指令就可以了。原因可能是你这样跳转,编译器的智商就不足够处理寄存器的恢复问题了。我不知道ICL会不会有能力处理这样的问题?
所以要内联,就要避免跳转到C++代码段,在汇编代码段内部的跳转是允许的。如果VC没有内联,你可以用__forceinline关键字,这样再长的汇编代码都会被内联,十分恐怖就是了。我原来怀疑是成员函数不能内联,后来发现跟这无关。但是成员函数不能使用naked声明,这是一个限制,只好不用了,但是照样可以把光线追踪的核心求交函数写的很完美,既不破坏OOP的设计,又能保持很高的效率,通过内联获得效率是很合算的,而通过汇编优化又是终极手段。
FORCEINLINE bool /*ASMDECL*/ RayTriangle::intersectEye( e_Ray *ray, e_RayState *state )
{
float dot_nd, t;
Vector3f hit, bary;
static const float _2 = 2.0f;
__asm {
/*push ebp ;
mov ebp, esp ;
sub esp, __LOCAL_SIZE ;
push esi ;
push edi ;
mov dword ptr this, ecx ;*/
// dot_nd = - ( normal.x * ray_dir.x + normal.y * ray_dir.y + normal.z * ray_dir.z );
// optimized version :
// xmm0 <--------------------------- 0
// xmm1
// xmm2
// xmm3 <--------------------------- ray->src
// xmm4 <--------------------------- ray->dir
// xmm5 <--------------------------- dot_nd
// xmm6 <--------------------------- t
// xmm7
xorps xmm0, xmm0 ;
mov edx, dword ptr ray ;
mov edi, dword ptr state ;
mov esi, dword ptr this ;
movaps xmm3, xmmword ptr [edx]e_Ray.src ;
movaps xmm4, xmmword ptr [edx]e_Ray.dir ;
movaps xmm5, xmmword ptr [esi]this.normal ;
movaps xmm6, xmm5 ;
prefetchnta byte ptr [esi+TYPE this] ;
movaps xmm7, xmm4 ;
mulps xmm5, xmm7 ;
movhlps xmm7, xmm5 ;
addss xmm7, xmm5 ;
shufps xmm5, xmm5, 1 ;
addss xmm7, xmm5 ;
movaps xmm5, xmm0 ;
subss xmm5, xmm7 ;
// if( dot_nd <= 0.0f )
comiss xmm0, xmm5 ;
// return false;
jae RETURN_FALSE ;
; 161 : t = ray_src.x * normal.x + ray_src.y * normal.y + ray_src.z * normal.z + normal.w;
movaps xmm7, xmm3 ;
mulps xmm7, xmm6 ;
movhlps xmm6, xmm7 ;
addss xmm6, xmm7 ;
shufps xmm7, xmm7, 253 ;
addss xmm6, xmm7 ;
movhlps xmm7, xmm7 ;
addss xmm6, xmm7 ;
// if( t <= t_near * dot_nd )
movss xmm7, dword ptr [edx]e_Ray.t_near ;
mulss xmm7, xmm5 ;
comiss xmm7, xmm6 ;
// return false;
jae RETURN_FALSE ;
// t_far = MIN( ray->t_far, state->t );
movss xmm7, dword ptr [edi]e_RayState.t ;
comiss xmm7, dword ptr [edx]e_Ray.t_far ;
jbe CASE_BELOW ;
movss xmm7, dword ptr [edx]e_Ray.t_far ;
CASE_BELOW:
// if( t >= t_far * dot_nd )
mulss xmm7, xmm5 ;
comiss xmm6, xmm7 ;
// return false;
jae RETURN_FALSE ;
// hit.arr[ projX ] = ray_src.arr[ projX ] * dot_nd + ray_dir.arr[ projX ] * t;
movzx eax, byte ptr [esi]this.projX ;
sal eax, 2 ;
movss xmm1, dword ptr [edx+eax]e_Ray.src ;
movss xmm2, dword ptr [edx+eax]e_Ray.dir ;
mulss xmm1, xmm5 ;
mulss xmm2, xmm6 ;
addss xmm1, xmm2 ;
movss dword ptr [hit+eax], xmm1 ;
// hit.arr[ projY ] = ray_src.arr[ projY ] * dot_nd + ray_dir.arr[ projY ] * t;
movzx ecx, byte ptr [esi]this.projY ;
sal ecx, 2 ;
movss xmm1, dword ptr [edx+ecx]e_Ray.src ;
movss xmm2, dword ptr [edx+ecx]e_Ray.dir ;
mulss xmm1, xmm5 ;
mulss xmm2, xmm6 ;
addss xmm1, xmm2 ;
movss dword ptr [hit+ecx], xmm1 ;
// bary.x = hit.arr[ projX ] * la.x + hit.arr[ projY ] * la.y + la.z * dot_nd;
movss xmm7, dword ptr [esi]this.la.x ;
movss xmm3, dword ptr [hit+eax] ;
mulss xmm7, xmm3 ;
movss xmm1, dword ptr [esi]this.la.y ;
movss xmm4, dword ptr [hit+ecx] ;
mulss xmm1, xmm4 ;
addss xmm7, xmm1 ;
movss xmm1, dword ptr [esi]this.la.z ;
mulss xmm1, xmm5 ;
addss xmm7, xmm1 ;
// if( bary.x < 0.0f || bary.x > dot_nd )
comiss xmm0, xmm7 ;
ja RETURN_FALSE ;
comiss xmm7, xmm5 ;
ja RETURN_FALSE ;
// bary.y = hit.arr[ projX ] * lb.x + hit.arr[ projY ] * lb.y + lb.z * dot_nd;
movss xmm2, dword ptr [esi]this.lb.x ;
mulss xmm2, xmm3 ;
movss xmm1, dword ptr [esi]this.lb.y ;
mulss xmm1, xmm4 ;
addss xmm2, xmm1 ;
movss xmm1, dword ptr [esi]this.lb.z ;
mulss xmm1, xmm5 ;
addss xmm2, xmm1 ;
// if( bary.y < 0.0f || bary.y > dot_nd )
comiss xmm0, xmm2 ;
ja RETURN_FALSE ;
comiss xmm2, xmm5 ;
ja RETURN_FALSE ;
// bary.z = dot_nd - bary.x - bary.y;
movaps xmm1, xmm5 ;
subss xmm1, xmm7 ;
subss xmm1, xmm2 ;
// if( bary.z < 0.0f || bary.z > dot_nd )
comiss xmm0, xmm1 ;
ja RETURN_FALSE ;
comiss xmm1, xmm5 ;
ja RETURN_FALSE ;
rcpss xmm3, xmm5 ;
// r * ( 2.0f - a * r );
movss xmm4, xmm3 ;
mulss xmm4, xmm5 ;
movss xmm0, dword ptr _2 ;
subss xmm0, xmm4 ;
mulss xmm0, xmm3 ;
mulss xmm6, xmm0 ;
movss dword ptr t, xmm6 ;
xorps xmm3, xmm3 ;
subss xmm3, xmm5 ;
movss dword ptr dot_nd, xmm3 ;
mulss xmm7, xmm0 ;
movss dword ptr bary.x, xmm7 ;
mulss xmm2, xmm0 ;
movss dword ptr bary.y, xmm2 ;
mulss xmm1, xmm0 ;
movss dword ptr bary.z, xmm1 ;
movss xmm3, dword ptr [hit+eax] ;
mulss xmm3, xmm0 ;
movss dword ptr [hit+eax], xmm3 ;
movss xmm4, dword ptr [hit+ecx] ;
mulss xmm4, xmm0 ;
movss dword ptr [hit+ecx], xmm4 ;
mov eax, dword ptr g_Rend.scene ;
movss xmm0, dword ptr [eax]e_Scene.opt.view.clip.min;
movss xmm2, dword ptr [eax]e_Scene.opt.view.clip.max;
movss xmm1, dword ptr [edx]e_Ray.dad ;
mulss xmm1, xmm6 ;
// if( dist < near_clip || dist > far_clip )
comiss xmm0, xmm1 ;
ja RETURN_FALSE ;
comiss xmm1, xmm2 ;
ja RETURN_FALSE ;
// hit.arr[ projZ ] = ray->src.arr[ projZ ] + ray->dir.arr[ projZ ] * t;
movzx ecx, byte ptr [esi]this.projZ ;
sal ecx, 2 ;
movss xmm0, dword ptr [edx+ecx]e_Ray.dir ;
mulss xmm0, xmm6 ;
addss xmm0, dword ptr [edx+ecx]e_Ray.src ;
movss dword ptr [hit+ecx], xmm0 ;
// state->normBary = bary;
mov ecx, dword ptr bary.x ;
mov dword ptr [edi]e_RayState.normBary.x, ecx;
mov edx, dword ptr bary.y ;
mov dword ptr [edi]e_RayState.normBary.y, edx;
mov ecx, dword ptr bary.z ;
mov dword ptr [edi]e_RayState.normBary.z, ecx;
// state->P = hit;
mov edx, dword ptr hit.x ;
mov dword ptr [edi]e_RayState.P.x, edx ;
mov ecx, dword ptr hit.y ;
mov dword ptr [edi]e_RayState.P.y, ecx ;
mov edx, dword ptr hit.z ;
mov dword ptr [edi]e_RayState.P.z, edx ;
// state->t = t;
mov ecx, dword ptr t ;
mov dword ptr [edi]e_RayState.t, ecx ;
// state->dotNd = dot_nd;
mov edx, dword ptr dot_nd ;
mov dword ptr [edi]e_RayState.dotNd, edx ;
mov al, 1 ;
jmp THE_END ;
RETURN_FALSE:
xor al, al ;
THE_END:
/*pop edi ;
pop esi ;
mov esp, ebp ;
pop ebp ;
ret 8 ;*/
} // __asm
}
{
float dot_nd, t;
Vector3f hit, bary;
static const float _2 = 2.0f;
__asm {
/*push ebp ;
mov ebp, esp ;
sub esp, __LOCAL_SIZE ;
push esi ;
push edi ;
mov dword ptr this, ecx ;*/
// dot_nd = - ( normal.x * ray_dir.x + normal.y * ray_dir.y + normal.z * ray_dir.z );
// optimized version :
// xmm0 <--------------------------- 0
// xmm1
// xmm2
// xmm3 <--------------------------- ray->src
// xmm4 <--------------------------- ray->dir
// xmm5 <--------------------------- dot_nd
// xmm6 <--------------------------- t
// xmm7
xorps xmm0, xmm0 ;
mov edx, dword ptr ray ;
mov edi, dword ptr state ;
mov esi, dword ptr this ;
movaps xmm3, xmmword ptr [edx]e_Ray.src ;
movaps xmm4, xmmword ptr [edx]e_Ray.dir ;
movaps xmm5, xmmword ptr [esi]this.normal ;
movaps xmm6, xmm5 ;
prefetchnta byte ptr [esi+TYPE this] ;
movaps xmm7, xmm4 ;
mulps xmm5, xmm7 ;
movhlps xmm7, xmm5 ;
addss xmm7, xmm5 ;
shufps xmm5, xmm5, 1 ;
addss xmm7, xmm5 ;
movaps xmm5, xmm0 ;
subss xmm5, xmm7 ;
// if( dot_nd <= 0.0f )
comiss xmm0, xmm5 ;
// return false;
jae RETURN_FALSE ;
; 161 : t = ray_src.x * normal.x + ray_src.y * normal.y + ray_src.z * normal.z + normal.w;
movaps xmm7, xmm3 ;
mulps xmm7, xmm6 ;
movhlps xmm6, xmm7 ;
addss xmm6, xmm7 ;
shufps xmm7, xmm7, 253 ;
addss xmm6, xmm7 ;
movhlps xmm7, xmm7 ;
addss xmm6, xmm7 ;
// if( t <= t_near * dot_nd )
movss xmm7, dword ptr [edx]e_Ray.t_near ;
mulss xmm7, xmm5 ;
comiss xmm7, xmm6 ;
// return false;
jae RETURN_FALSE ;
// t_far = MIN( ray->t_far, state->t );
movss xmm7, dword ptr [edi]e_RayState.t ;
comiss xmm7, dword ptr [edx]e_Ray.t_far ;
jbe CASE_BELOW ;
movss xmm7, dword ptr [edx]e_Ray.t_far ;
CASE_BELOW:
// if( t >= t_far * dot_nd )
mulss xmm7, xmm5 ;
comiss xmm6, xmm7 ;
// return false;
jae RETURN_FALSE ;
// hit.arr[ projX ] = ray_src.arr[ projX ] * dot_nd + ray_dir.arr[ projX ] * t;
movzx eax, byte ptr [esi]this.projX ;
sal eax, 2 ;
movss xmm1, dword ptr [edx+eax]e_Ray.src ;
movss xmm2, dword ptr [edx+eax]e_Ray.dir ;
mulss xmm1, xmm5 ;
mulss xmm2, xmm6 ;
addss xmm1, xmm2 ;
movss dword ptr [hit+eax], xmm1 ;
// hit.arr[ projY ] = ray_src.arr[ projY ] * dot_nd + ray_dir.arr[ projY ] * t;
movzx ecx, byte ptr [esi]this.projY ;
sal ecx, 2 ;
movss xmm1, dword ptr [edx+ecx]e_Ray.src ;
movss xmm2, dword ptr [edx+ecx]e_Ray.dir ;
mulss xmm1, xmm5 ;
mulss xmm2, xmm6 ;
addss xmm1, xmm2 ;
movss dword ptr [hit+ecx], xmm1 ;
// bary.x = hit.arr[ projX ] * la.x + hit.arr[ projY ] * la.y + la.z * dot_nd;
movss xmm7, dword ptr [esi]this.la.x ;
movss xmm3, dword ptr [hit+eax] ;
mulss xmm7, xmm3 ;
movss xmm1, dword ptr [esi]this.la.y ;
movss xmm4, dword ptr [hit+ecx] ;
mulss xmm1, xmm4 ;
addss xmm7, xmm1 ;
movss xmm1, dword ptr [esi]this.la.z ;
mulss xmm1, xmm5 ;
addss xmm7, xmm1 ;
// if( bary.x < 0.0f || bary.x > dot_nd )
comiss xmm0, xmm7 ;
ja RETURN_FALSE ;
comiss xmm7, xmm5 ;
ja RETURN_FALSE ;
// bary.y = hit.arr[ projX ] * lb.x + hit.arr[ projY ] * lb.y + lb.z * dot_nd;
movss xmm2, dword ptr [esi]this.lb.x ;
mulss xmm2, xmm3 ;
movss xmm1, dword ptr [esi]this.lb.y ;
mulss xmm1, xmm4 ;
addss xmm2, xmm1 ;
movss xmm1, dword ptr [esi]this.lb.z ;
mulss xmm1, xmm5 ;
addss xmm2, xmm1 ;
// if( bary.y < 0.0f || bary.y > dot_nd )
comiss xmm0, xmm2 ;
ja RETURN_FALSE ;
comiss xmm2, xmm5 ;
ja RETURN_FALSE ;
// bary.z = dot_nd - bary.x - bary.y;
movaps xmm1, xmm5 ;
subss xmm1, xmm7 ;
subss xmm1, xmm2 ;
// if( bary.z < 0.0f || bary.z > dot_nd )
comiss xmm0, xmm1 ;
ja RETURN_FALSE ;
comiss xmm1, xmm5 ;
ja RETURN_FALSE ;
rcpss xmm3, xmm5 ;
// r * ( 2.0f - a * r );
movss xmm4, xmm3 ;
mulss xmm4, xmm5 ;
movss xmm0, dword ptr _2 ;
subss xmm0, xmm4 ;
mulss xmm0, xmm3 ;
mulss xmm6, xmm0 ;
movss dword ptr t, xmm6 ;
xorps xmm3, xmm3 ;
subss xmm3, xmm5 ;
movss dword ptr dot_nd, xmm3 ;
mulss xmm7, xmm0 ;
movss dword ptr bary.x, xmm7 ;
mulss xmm2, xmm0 ;
movss dword ptr bary.y, xmm2 ;
mulss xmm1, xmm0 ;
movss dword ptr bary.z, xmm1 ;
movss xmm3, dword ptr [hit+eax] ;
mulss xmm3, xmm0 ;
movss dword ptr [hit+eax], xmm3 ;
movss xmm4, dword ptr [hit+ecx] ;
mulss xmm4, xmm0 ;
movss dword ptr [hit+ecx], xmm4 ;
mov eax, dword ptr g_Rend.scene ;
movss xmm0, dword ptr [eax]e_Scene.opt.view.clip.min;
movss xmm2, dword ptr [eax]e_Scene.opt.view.clip.max;
movss xmm1, dword ptr [edx]e_Ray.dad ;
mulss xmm1, xmm6 ;
// if( dist < near_clip || dist > far_clip )
comiss xmm0, xmm1 ;
ja RETURN_FALSE ;
comiss xmm1, xmm2 ;
ja RETURN_FALSE ;
// hit.arr[ projZ ] = ray->src.arr[ projZ ] + ray->dir.arr[ projZ ] * t;
movzx ecx, byte ptr [esi]this.projZ ;
sal ecx, 2 ;
movss xmm0, dword ptr [edx+ecx]e_Ray.dir ;
mulss xmm0, xmm6 ;
addss xmm0, dword ptr [edx+ecx]e_Ray.src ;
movss dword ptr [hit+ecx], xmm0 ;
// state->normBary = bary;
mov ecx, dword ptr bary.x ;
mov dword ptr [edi]e_RayState.normBary.x, ecx;
mov edx, dword ptr bary.y ;
mov dword ptr [edi]e_RayState.normBary.y, edx;
mov ecx, dword ptr bary.z ;
mov dword ptr [edi]e_RayState.normBary.z, ecx;
// state->P = hit;
mov edx, dword ptr hit.x ;
mov dword ptr [edi]e_RayState.P.x, edx ;
mov ecx, dword ptr hit.y ;
mov dword ptr [edi]e_RayState.P.y, ecx ;
mov edx, dword ptr hit.z ;
mov dword ptr [edi]e_RayState.P.z, edx ;
// state->t = t;
mov ecx, dword ptr t ;
mov dword ptr [edi]e_RayState.t, ecx ;
// state->dotNd = dot_nd;
mov edx, dword ptr dot_nd ;
mov dword ptr [edi]e_RayState.dotNd, edx ;
mov al, 1 ;
jmp THE_END ;
RETURN_FALSE:
xor al, al ;
THE_END:
/*pop edi ;
pop esi ;
mov esp, ebp ;
pop ebp ;
ret 8 ;*/
} // __asm
}