parent
5f05a5e953
commit
96963f88cc
13 changed files with 320 additions and 246 deletions
@ -0,0 +1,183 @@ |
|||||||
|
namespace glm{ |
||||||
|
namespace detail |
||||||
|
{ |
||||||
|
#if(GLM_COMPILER & GLM_COMPILER_VC) |
||||||
|
#pragma warning(push) |
||||||
|
#pragma warning(disable : 4510 4512 4610) |
||||||
|
#endif |
||||||
|
|
||||||
|
union ieee754_QNAN |
||||||
|
{ |
||||||
|
const float f; |
||||||
|
struct i |
||||||
|
{ |
||||||
|
const unsigned int mantissa:23, exp:8, sign:1; |
||||||
|
}; |
||||||
|
|
||||||
|
ieee754_QNAN() : f(0.0)/*, mantissa(0x7FFFFF), exp(0xFF), sign(0x0)*/ {} |
||||||
|
}; |
||||||
|
|
||||||
|
#if(GLM_COMPILER & GLM_COMPILER_VC) |
||||||
|
#pragma warning(pop) |
||||||
|
#endif |
||||||
|
|
||||||
|
static const __m128 GLM_VAR_USED zero = _mm_setzero_ps(); |
||||||
|
static const __m128 GLM_VAR_USED one = _mm_set_ps1(1.0f); |
||||||
|
static const __m128 GLM_VAR_USED minus_one = _mm_set_ps1(-1.0f); |
||||||
|
static const __m128 GLM_VAR_USED two = _mm_set_ps1(2.0f); |
||||||
|
static const __m128 GLM_VAR_USED three = _mm_set_ps1(3.0f); |
||||||
|
|
||||||
|
static const ieee754_QNAN absMask; |
||||||
|
static const __m128 GLM_VAR_USED abs4Mask = _mm_set_ps1(absMask.f); |
||||||
|
static const __m128 GLM_VAR_USED _epi32_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000))); |
||||||
|
static const __m128 GLM_VAR_USED _ps_2pow23 = _mm_set_ps1(8388608.0f); |
||||||
|
static const __m128 GLM_VAR_USED _ps_1 = _mm_set_ps1(1.0f); |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 abs_ps(__m128 x) |
||||||
|
{ |
||||||
|
return _mm_and_ps(abs4Mask, x); |
||||||
|
} |
||||||
|
|
||||||
|
//sign |
||||||
|
GLM_FUNC_QUALIFIER __m128 sgn_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 Neg = _mm_set1_ps(-1.0f); |
||||||
|
__m128 Pos = _mm_set1_ps(1.0f); |
||||||
|
|
||||||
|
__m128 Cmp0 = _mm_cmplt_ps(x, zero); |
||||||
|
__m128 Cmp1 = _mm_cmpgt_ps(x, zero); |
||||||
|
|
||||||
|
__m128 And0 = _mm_and_ps(Cmp0, Neg); |
||||||
|
__m128 And1 = _mm_and_ps(Cmp1, Pos); |
||||||
|
|
||||||
|
return _mm_or_ps(And0, And1); |
||||||
|
} |
||||||
|
|
||||||
|
//round |
||||||
|
GLM_FUNC_QUALIFIER __m128 rnd_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 and0 = _mm_and_ps(_epi32_sign_mask, x); |
||||||
|
__m128 or0 = _mm_or_ps(and0, _ps_2pow23); |
||||||
|
__m128 add0 = _mm_add_ps(x, or0); |
||||||
|
__m128 sub0 = _mm_sub_ps(add0, or0); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
//floor |
||||||
|
GLM_FUNC_QUALIFIER __m128 flr_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 rnd0 = rnd_ps(x); |
||||||
|
__m128 cmp0 = _mm_cmplt_ps(x, rnd0); |
||||||
|
__m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1); |
||||||
|
__m128 sub0 = _mm_sub_ps(rnd0, and0); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
//trunc |
||||||
|
//GLM_FUNC_QUALIFIER __m128 _mm_trc_ps(__m128 v) |
||||||
|
//{ |
||||||
|
// return __m128(); |
||||||
|
//} |
||||||
|
|
||||||
|
//roundEven |
||||||
|
GLM_FUNC_QUALIFIER __m128 rde_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 and0 = _mm_and_ps(_epi32_sign_mask, x); |
||||||
|
__m128 or0 = _mm_or_ps(and0, _ps_2pow23); |
||||||
|
__m128 add0 = _mm_add_ps(x, or0); |
||||||
|
__m128 sub0 = _mm_sub_ps(add0, or0); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 ceil_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 rnd0 = rnd_ps(x); |
||||||
|
__m128 cmp0 = _mm_cmpgt_ps(x, rnd0); |
||||||
|
__m128 and0 = _mm_and_ps(cmp0, _ps_1); |
||||||
|
__m128 add0 = _mm_add_ps(rnd0, and0); |
||||||
|
return add0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 frc_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 flr0 = flr_ps(x); |
||||||
|
__m128 sub0 = _mm_sub_ps(x, flr0); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 mod_ps(__m128 x, __m128 y) |
||||||
|
{ |
||||||
|
__m128 div0 = _mm_div_ps(x, y); |
||||||
|
__m128 flr0 = flr_ps(div0); |
||||||
|
__m128 mul0 = _mm_mul_ps(y, flr0); |
||||||
|
__m128 sub0 = _mm_sub_ps(x, mul0); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 clp_ps(__m128 v, __m128 minVal, __m128 maxVal) |
||||||
|
{ |
||||||
|
__m128 min0 = _mm_min_ps(v, maxVal); |
||||||
|
__m128 max0 = _mm_max_ps(min0, minVal); |
||||||
|
return max0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 mix_ps(__m128 v1, __m128 v2, __m128 a) |
||||||
|
{ |
||||||
|
__m128 sub0 = _mm_sub_ps(one, a); |
||||||
|
__m128 mul0 = _mm_mul_ps(v1, sub0); |
||||||
|
__m128 mul1 = _mm_mul_ps(v2, a); |
||||||
|
__m128 add0 = _mm_add_ps(mul0, mul1); |
||||||
|
return add0; |
||||||
|
} |
||||||
|
|
||||||
|
//step |
||||||
|
GLM_FUNC_QUALIFIER __m128 stp_ps(__m128 edge, __m128 x) |
||||||
|
{ |
||||||
|
__m128 cmp = _mm_cmple_ps(x, edge); |
||||||
|
if(_mm_movemask_ps(cmp) == 0) |
||||||
|
return one; |
||||||
|
else |
||||||
|
return zero; |
||||||
|
} |
||||||
|
|
||||||
|
// smoothstep |
||||||
|
GLM_FUNC_QUALIFIER __m128 ssp_ps(__m128 edge0, __m128 edge1, __m128 x) |
||||||
|
{ |
||||||
|
__m128 sub0 = _mm_sub_ps(x, edge0); |
||||||
|
__m128 sub1 = _mm_sub_ps(edge1, edge0); |
||||||
|
__m128 div0 = _mm_sub_ps(sub0, sub1); |
||||||
|
__m128 clp0 = clp_ps(div0, zero, one); |
||||||
|
__m128 mul0 = _mm_mul_ps(two, clp0); |
||||||
|
__m128 sub2 = _mm_sub_ps(three, mul0); |
||||||
|
__m128 mul1 = _mm_mul_ps(clp0, clp0); |
||||||
|
__m128 mul2 = _mm_mul_ps(mul1, sub2); |
||||||
|
return mul2; |
||||||
|
} |
||||||
|
|
||||||
|
/// \todo |
||||||
|
//GLM_FUNC_QUALIFIER __m128 sse_nan_ps(__m128 x) |
||||||
|
//{ |
||||||
|
// __m128 empty; |
||||||
|
// return empty; |
||||||
|
//} |
||||||
|
|
||||||
|
/// \todo |
||||||
|
//GLM_FUNC_QUALIFIER __m128 sse_inf_ps(__m128 x) |
||||||
|
//{ |
||||||
|
// __m128 empty; |
||||||
|
// return empty; |
||||||
|
//} |
||||||
|
|
||||||
|
// SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration |
||||||
|
// By Elan Ruskin, http://assemblyrequired.crashworks.org/ |
||||||
|
GLM_FUNC_QUALIFIER __m128 sqrt_wip_ss(__m128 x) |
||||||
|
{ |
||||||
|
__m128 const recip = _mm_rsqrt_ss(x); // "estimate" opcode |
||||||
|
__m128 const half = _mm_set_ps1(0.5f); |
||||||
|
__m128 const halfrecip = _mm_mul_ss(half, recip); |
||||||
|
__m128 const threeminus_xrr = _mm_sub_ss(three, _mm_mul_ss(x, _mm_mul_ss (recip, recip))); |
||||||
|
return _mm_mul_ss(halfrecip, threeminus_xrr); |
||||||
|
} |
||||||
|
|
||||||
|
}//namespace detail |
||||||
|
}//namespace glm |
@ -0,0 +1,119 @@ |
|||||||
|
namespace glm{ |
||||||
|
namespace detail |
||||||
|
{ |
||||||
|
#if GLM_ARCH & GLM_ARCH_AVX |
||||||
|
GLM_FUNC_QUALIFIER __m128 dot_ps(__m128 v1, __m128 v2) |
||||||
|
{ |
||||||
|
return _mm_dp_ps(v1, v2, 0xff); |
||||||
|
} |
||||||
|
#else |
||||||
|
GLM_FUNC_QUALIFIER __m128 dot_ps(__m128 v1, __m128 v2) |
||||||
|
{ |
||||||
|
__m128 mul0 = _mm_mul_ps(v1, v2); |
||||||
|
__m128 swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); |
||||||
|
__m128 add0 = _mm_add_ps(mul0, swp0); |
||||||
|
__m128 swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); |
||||||
|
__m128 add1 = _mm_add_ps(add0, swp1); |
||||||
|
return add1; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 dot_ss(__m128 v1, __m128 v2) |
||||||
|
{ |
||||||
|
__m128 mul0 = _mm_mul_ps(v1, v2); |
||||||
|
__m128 mov0 = _mm_movehl_ps(mul0, mul0); |
||||||
|
__m128 add0 = _mm_add_ps(mov0, mul0); |
||||||
|
__m128 swp1 = _mm_shuffle_ps(add0, add0, 1); |
||||||
|
__m128 add1 = _mm_add_ss(add0, swp1); |
||||||
|
return add1; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 len_ps(__m128 x) |
||||||
|
{ |
||||||
|
__m128 dot0 = dot_ps(x, x); |
||||||
|
__m128 sqt0 = _mm_sqrt_ps(dot0); |
||||||
|
return sqt0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 dst_ps(__m128 p0, __m128 p1) |
||||||
|
{ |
||||||
|
__m128 sub0 = _mm_sub_ps(p0, p1); |
||||||
|
__m128 len0 = len_ps(sub0); |
||||||
|
return len0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 xpd_ps(__m128 v1, __m128 v2) |
||||||
|
{ |
||||||
|
__m128 swp0 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
__m128 swp1 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 swp2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 0, 2, 1)); |
||||||
|
__m128 swp3 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 1, 0, 2)); |
||||||
|
__m128 mul0 = _mm_mul_ps(swp0, swp3); |
||||||
|
__m128 mul1 = _mm_mul_ps(swp1, swp2); |
||||||
|
__m128 sub0 = _mm_sub_ps(mul0, mul1); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 nrm_ps(__m128 v) |
||||||
|
{ |
||||||
|
__m128 dot0 = dot_ps(v, v); |
||||||
|
__m128 isr0 = _mm_rsqrt_ps(dot0); |
||||||
|
__m128 mul0 = _mm_mul_ps(v, isr0); |
||||||
|
return mul0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 ffd_ps(__m128 N, __m128 I, __m128 Nref) |
||||||
|
{ |
||||||
|
__m128 dot0 = dot_ps(Nref, I); |
||||||
|
__m128 sgn0 = sgn_ps(dot0); |
||||||
|
__m128 mul0 = _mm_mul_ps(sgn0, glm::detail::minus_one); |
||||||
|
__m128 mul1 = _mm_mul_ps(N, mul0); |
||||||
|
return mul1; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 rfe_ps(__m128 I, __m128 N) |
||||||
|
{ |
||||||
|
__m128 dot0 = dot_ps(N, I); |
||||||
|
__m128 mul0 = _mm_mul_ps(N, dot0); |
||||||
|
__m128 mul1 = _mm_mul_ps(mul0, glm::detail::two); |
||||||
|
__m128 sub0 = _mm_sub_ps(I, mul1); |
||||||
|
return sub0; |
||||||
|
} |
||||||
|
|
||||||
|
GLM_FUNC_QUALIFIER __m128 rfa_ps(__m128 I, __m128 N, __m128 eta) |
||||||
|
{ |
||||||
|
__m128 dot0 = dot_ps(N, I); |
||||||
|
__m128 mul0 = _mm_mul_ps(eta, eta); |
||||||
|
__m128 mul1 = _mm_mul_ps(dot0, dot0); |
||||||
|
__m128 sub0 = _mm_sub_ps(glm::detail::one, mul0); |
||||||
|
__m128 sub1 = _mm_sub_ps(glm::detail::one, mul1); |
||||||
|
__m128 mul2 = _mm_mul_ps(sub0, sub1); |
||||||
|
|
||||||
|
if(_mm_movemask_ps(_mm_cmplt_ss(mul2, glm::detail::zero)) == 0) |
||||||
|
return glm::detail::zero; |
||||||
|
|
||||||
|
__m128 sqt0 = _mm_sqrt_ps(mul2); |
||||||
|
__m128 mul3 = _mm_mul_ps(eta, dot0); |
||||||
|
__m128 add0 = _mm_add_ps(mul3, sqt0); |
||||||
|
__m128 mul4 = _mm_mul_ps(add0, N); |
||||||
|
__m128 mul5 = _mm_mul_ps(eta, I); |
||||||
|
__m128 sub2 = _mm_sub_ps(mul5, mul4); |
||||||
|
|
||||||
|
return sub2; |
||||||
|
} |
||||||
|
|
||||||
|
template <> |
||||||
|
struct compute_dot<tvec4, float, simd> |
||||||
|
{ |
||||||
|
GLM_FUNC_QUALIFIER static float call(tvec4<float, simd> const& x, tvec4<float, simd> const& y) |
||||||
|
{ |
||||||
|
__m128 const dot0 = dot_ss(x.data, y.data); |
||||||
|
|
||||||
|
float Result = 0; |
||||||
|
_mm_store_ss(&Result, dot0); |
||||||
|
return Result; |
||||||
|
} |
||||||
|
}; |
||||||
|
}//namespace detail |
||||||
|
}//namespace glm |
||||||
|
|
@ -1,38 +0,0 @@ |
|||||||
namespace glm{ |
|
||||||
namespace detail |
|
||||||
{ |
|
||||||
GLM_FUNC_QUALIFIER __m128 dot_ps(__m128 v1, __m128 v2) |
|
||||||
{ |
|
||||||
__m128 mul0 = _mm_mul_ps(v1, v2); |
|
||||||
__m128 swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); |
|
||||||
__m128 add0 = _mm_add_ps(mul0, swp0); |
|
||||||
__m128 swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); |
|
||||||
__m128 add1 = _mm_add_ps(add0, swp1); |
|
||||||
return add1; |
|
||||||
} |
|
||||||
|
|
||||||
GLM_FUNC_QUALIFIER __m128 dot_ss(__m128 v1, __m128 v2) |
|
||||||
{ |
|
||||||
__m128 mul0 = _mm_mul_ps(v1, v2); |
|
||||||
__m128 mov0 = _mm_movehl_ps(mul0, mul0); |
|
||||||
__m128 add0 = _mm_add_ps(mov0, mul0); |
|
||||||
__m128 swp1 = _mm_shuffle_ps(add0, add0, 1); |
|
||||||
__m128 add1 = _mm_add_ss(add0, swp1); |
|
||||||
return add1; |
|
||||||
} |
|
||||||
|
|
||||||
template <> |
|
||||||
struct compute_dot<tvec4, float, simd> |
|
||||||
{ |
|
||||||
GLM_FUNC_QUALIFIER static float call(tvec4<float, simd> const& x, tvec4<float, simd> const& y) |
|
||||||
{ |
|
||||||
__m128 const dot0 = dot_ss(x.data, y.data); |
|
||||||
|
|
||||||
float Result = 0; |
|
||||||
_mm_store_ss(&Result, dot0); |
|
||||||
return Result; |
|
||||||
} |
|
||||||
}; |
|
||||||
}//namespace detail |
|
||||||
}//namespace glm |
|
||||||
|
|
Loading…
Reference in New Issue