tweak SkVx to play nicely with others

Was starting to use this and ran into a few problems with clashing
symbols, namely SI and cast().  Seemed simple enough to not use SI,
and to move all the free-standing types into skvx: skvx::cast,
skvx::shuffle, etc.

Change-Id: Ia5d8ef6d0ae5375bf80d76be88d16f0c9cde56e7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/207340
Commit-Queue: Mike Klein <mtklein@google.com>
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Mike Klein 2019-04-10 12:40:31 -05:00 committed by Skia Commit-Bot
parent 13df106d59
commit da7b053527
2 changed files with 54 additions and 55 deletions

View File

@ -107,7 +107,6 @@ struct Vec<1,T> {
#endif
// Helps tamp down on the repetitive boilerplate.
#define SI static inline
#define SIT template < typename T> static inline
#define SINT template <int N, typename T> static inline
#define SINTU template <int N, typename T, typename U, \
@ -115,7 +114,7 @@ struct Vec<1,T> {
static inline
template <typename D, typename S>
SI D bit_pun(S s) {
static inline D bit_pun(S s) {
static_assert(sizeof(D) == sizeof(S), "");
D d;
memcpy(&d, &s, sizeof(D));
@ -160,7 +159,7 @@ SINT Vec<2*N,T> join(Vec<N,T> lo, Vec<N,T> hi) {
// For some reason some (new!) versions of GCC cannot seem to deduce N in the generic
// to_vec<N,T>() below for N=4 and T=float. This workaround seems to help...
SI Vec<4,float> to_vec(VExt<4,float> v) { return bit_pun<Vec<4,float>>(v); }
static inline Vec<4,float> to_vec(VExt<4,float> v) { return bit_pun<Vec<4,float>>(v); }
#endif
SINT VExt<N,T> to_vext(Vec<N,T> v) { return bit_pun<VExt<N,T>>(v); }
@ -368,20 +367,14 @@ SINTU Vec<N,T>& operator|=(Vec<N,T>& x, U y) { return (x = x | Vec<N,T>(y)); }
SINT Vec<N,T>& operator<<=(Vec<N,T>& x, int bits) { return (x = x << bits); }
SINT Vec<N,T>& operator>>=(Vec<N,T>& x, int bits) { return (x = x >> bits); }
} // namespace skvx
// These next few routines take extra template arguments that prevent
// argument-dependent lookup. They must live outside the skvx namespace,
// but since they operate only on skvx::Vec, that shouldn't be a big deal.
// cast() Vec<N,S> to Vec<N,D>, as if applying a C-cast to each lane.
template <typename D, typename S>
SI skvx::Vec<1,D> cast(skvx::Vec<1,S> src) { return (D)src.val; }
static inline Vec<1,D> cast(Vec<1,S> src) { return (D)src.val; }
template <typename D, int N, typename S>
SI skvx::Vec<N,D> cast(skvx::Vec<N,S> src) {
static inline Vec<N,D> cast(Vec<N,S> src) {
#if !defined(SKNX_NO_SIMD) && defined(__clang__)
return skvx::to_vec(__builtin_convertvector(skvx::to_vext(src), skvx::VExt<N,D>));
return to_vec(__builtin_convertvector(to_vext(src), VExt<N,D>));
#else
return join(cast<D>(src.lo), cast<D>(src.hi));
#endif
@ -395,57 +388,62 @@ SI skvx::Vec<N,D> cast(skvx::Vec<N,S> src) {
// shuffle<3,3,3,3> (rgba) ~> {A,A,A,A}
// The only real restriction is that the output also be a legal N=power-of-two sknx::Vec.
template <int... Ix, int N, typename T>
SI skvx::Vec<sizeof...(Ix),T> shuffle(skvx::Vec<N,T> x) {
static inline Vec<sizeof...(Ix),T> shuffle(Vec<N,T> x) {
return { x[Ix]... };
}
#if !defined(SKNX_NO_SIMD)
namespace skvx {
// Platform-specific specializations and overloads can now drop in here.
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
SI Vec<4,float> sqrt(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_sqrt_ps(bit_pun<__m128>(x)));
}
SI Vec<4,float> rsqrt(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_rsqrt_ps(bit_pun<__m128>(x)));
}
SI Vec<4,float> rcp(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_rcp_ps(bit_pun<__m128>(x)));
}
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
static inline Vec<4,float> sqrt(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_sqrt_ps(bit_pun<__m128>(x)));
}
static inline Vec<4,float> rsqrt(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_rsqrt_ps(bit_pun<__m128>(x)));
}
static inline Vec<4,float> rcp(Vec<4,float> x) {
return bit_pun<Vec<4,float>>(_mm_rcp_ps(bit_pun<__m128>(x)));
}
SI Vec<2,float> sqrt(Vec<2,float> x) { return shuffle<0,1>( sqrt(shuffle<0,1,0,1>(x))); }
SI Vec<2,float> rsqrt(Vec<2,float> x) { return shuffle<0,1>(rsqrt(shuffle<0,1,0,1>(x))); }
SI Vec<2,float> rcp(Vec<2,float> x) { return shuffle<0,1>( rcp(shuffle<0,1,0,1>(x))); }
#endif
static inline Vec<2,float> sqrt(Vec<2,float> x) {
return shuffle<0,1>( sqrt(shuffle<0,1,0,1>(x)));
}
static inline Vec<2,float> rsqrt(Vec<2,float> x) {
return shuffle<0,1>(rsqrt(shuffle<0,1,0,1>(x)));
}
static inline Vec<2,float> rcp(Vec<2,float> x) {
return shuffle<0,1>( rcp(shuffle<0,1,0,1>(x)));
}
#endif
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
SI Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(_mm_blendv_ps(bit_pun<__m128>(e),
bit_pun<__m128>(t),
bit_pun<__m128>(c)));
}
#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
SI Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(_mm_or_ps(_mm_and_ps (bit_pun<__m128>(c),
bit_pun<__m128>(t)),
_mm_andnot_ps(bit_pun<__m128>(c),
bit_pun<__m128>(e))));
}
#elif defined(SK_ARM_HAS_NEON)
SI Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(vbslq_f32(bit_pun<uint32x4_t> (c),
bit_pun<float32x4_t>(t),
bit_pun<float32x4_t>(e)));
}
#endif
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
static inline Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(_mm_blendv_ps(bit_pun<__m128>(e),
bit_pun<__m128>(t),
bit_pun<__m128>(c)));
}
#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
static inline Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(_mm_or_ps(_mm_and_ps (bit_pun<__m128>(c),
bit_pun<__m128>(t)),
_mm_andnot_ps(bit_pun<__m128>(c),
bit_pun<__m128>(e))));
}
#elif defined(SK_ARM_HAS_NEON)
static inline Vec<4,float> if_then_else(Vec<4,int> c, Vec<4,float> t, Vec<4,float> e) {
return bit_pun<Vec<4,float>>(vbslq_f32(bit_pun<uint32x4_t> (c),
bit_pun<float32x4_t>(t),
bit_pun<float32x4_t>(e)));
}
#endif
#endif // !defined(SKNX_NO_SIMD)
} // namespace skvx
#endif // !defined(SKNX_NO_SIMD)
#undef SINTU
#undef SINT
#undef SIT
#undef SI
#endif//SKVX_DEFINED

View File

@ -112,7 +112,7 @@ DEF_TEST(SkVx, r) {
REPORTER_ASSERT(r, all( rcp(float2{2,3}) < float2{1.0f,0.5f}));
REPORTER_ASSERT(r, all(rsqrt(float2{2,3}) < float2{1.0f,1.0f}));
REPORTER_ASSERT(r, all(cast<int>(float4{-1.5f,0.5f,1.0f,1.5f}) == int4{-1,0,1,1}));
REPORTER_ASSERT(r, all(skvx::cast<int>(float4{-1.5f,0.5f,1.0f,1.5f}) == int4{-1,0,1,1}));
float buf[] = {1,2,3,4,5,6};
REPORTER_ASSERT(r, all(float4::Load(buf) == float4{1,2,3,4}));
@ -128,10 +128,11 @@ DEF_TEST(SkVx, r) {
REPORTER_ASSERT(r, all(mad(float4{1,2,3,4}, 2.0f, 3.0f) == float4{5,7,9,11}));
REPORTER_ASSERT(r, all(shuffle<2,1,0,3> (float4{1,2,3,4}) == float4{3,2,1,4}));
REPORTER_ASSERT(r, all(shuffle<2,1> (float4{1,2,3,4}) == float2{3,2}));
REPORTER_ASSERT(r, all(shuffle<2,1,2,1,2,1,2,1>(float4{1,2,3,4}) == float8{3,2,3,2,3,2,3,2}));
REPORTER_ASSERT(r, all(shuffle<3,3,3,3> (float4{1,2,3,4}) == float4{4,4,4,4}));
REPORTER_ASSERT(r, all(skvx::shuffle<2,1,0,3> (float4{1,2,3,4}) == float4{3,2,1,4}));
REPORTER_ASSERT(r, all(skvx::shuffle<2,1> (float4{1,2,3,4}) == float2{3,2}));
REPORTER_ASSERT(r, all(skvx::shuffle<3,3,3,3> (float4{1,2,3,4}) == float4{4,4,4,4}));
REPORTER_ASSERT(r, all(skvx::shuffle<2,1,2,1,2,1,2,1>(float4{1,2,3,4})
== float8{3,2,3,2,3,2,3,2}));
// Test that mixed types can be used where they make sense. Mostly about ergonomics.
REPORTER_ASSERT(r, all(float4{1,2,3,4} < 5));