diff --git a/include/private/SkVx.h b/include/private/SkVx.h index b2b19b7b62..adb6d8a2f2 100644 --- a/include/private/SkVx.h +++ b/include/private/SkVx.h @@ -49,7 +49,10 @@ struct Vec { // Other operations on Vec should be defined outside the type. Vec() = default; - Vec(T x) : lo(x), hi(x) {} + + template ::value>::type> + Vec(U x) : lo(x), hi(x) {} Vec(std::initializer_list xs) { T vals[N] = {0}; @@ -77,7 +80,10 @@ struct Vec<1,T> { T val; Vec() = default; - Vec(T x) : val(x) {} + + template ::value>::type> + Vec(U x) : val(x) {} Vec(std::initializer_list xs) : val(xs.size() ? *xs.begin() : 0) {} @@ -101,9 +107,12 @@ struct Vec<1,T> { #endif // Helps tamp down on the repetitive boilerplate. -#define SINT template static inline -#define SIT template < typename T> static inline -#define SI static inline +#define SI static inline +#define SIT template < typename T> static inline +#define SINT template static inline +#define SINTU template ::value>::type> \ + static inline template SI D bit_pun(S s) { @@ -296,46 +305,46 @@ SINT Vec mad(Vec f, // Scalar/vector operations just splat the scalar to a vector... -SINT Vec operator+ (T x, Vec y) { return Vec(x) + y; } -SINT Vec operator- (T x, Vec y) { return Vec(x) - y; } -SINT Vec operator* (T x, Vec y) { return Vec(x) * y; } -SINT Vec operator/ (T x, Vec y) { return Vec(x) / y; } -SINT Vec operator^ (T x, Vec y) { return Vec(x) ^ y; } -SINT Vec operator& (T x, Vec y) { return Vec(x) & y; } -SINT Vec operator| (T x, Vec y) { return Vec(x) | y; } -SINT Vec> operator==(T x, Vec y) { return Vec(x) == y; } -SINT Vec> operator!=(T x, Vec y) { return Vec(x) != y; } -SINT Vec> operator<=(T x, Vec y) { return Vec(x) <= y; } -SINT Vec> operator>=(T x, Vec y) { return Vec(x) >= y; } -SINT Vec> operator< (T x, Vec y) { return Vec(x) < y; } -SINT Vec> operator> (T x, Vec y) { return Vec(x) > y; } -SINT Vec min(T x, Vec y) { return min(Vec(x), y); } -SINT Vec max(T x, Vec y) { return max(Vec(x), y); } +SINTU Vec operator+ (U x, Vec y) { return Vec(x) + y; } +SINTU Vec operator- (U x, Vec y) { return Vec(x) - y; } +SINTU Vec operator* (U x, Vec y) { return Vec(x) * y; } +SINTU Vec operator/ (U x, Vec y) { return Vec(x) / y; } +SINTU Vec operator^ (U x, Vec y) { return Vec(x) ^ y; } +SINTU Vec operator& (U x, Vec y) { return Vec(x) & y; } +SINTU Vec operator| (U x, Vec y) { return Vec(x) | y; } +SINTU Vec> operator==(U x, Vec y) { return Vec(x) == y; } +SINTU Vec> operator!=(U x, Vec y) { return Vec(x) != y; } +SINTU Vec> operator<=(U x, Vec y) { return Vec(x) <= y; } +SINTU Vec> operator>=(U x, Vec y) { return Vec(x) >= y; } +SINTU Vec> operator< (U x, Vec y) { return Vec(x) < y; } +SINTU Vec> operator> (U x, Vec y) { return Vec(x) > y; } +SINTU Vec min(U x, Vec y) { return min(Vec(x), y); } +SINTU Vec max(U x, Vec y) { return max(Vec(x), y); } // ... and same deal for vector/scalar operations. -SINT Vec operator+ (Vec x, T y) { return x + Vec(y); } -SINT Vec operator- (Vec x, T y) { return x - Vec(y); } -SINT Vec operator* (Vec x, T y) { return x * Vec(y); } -SINT Vec operator/ (Vec x, T y) { return x / Vec(y); } -SINT Vec operator^ (Vec x, T y) { return x ^ Vec(y); } -SINT Vec operator& (Vec x, T y) { return x & Vec(y); } -SINT Vec operator| (Vec x, T y) { return x | Vec(y); } -SINT Vec> operator==(Vec x, T y) { return x == Vec(y); } -SINT Vec> operator!=(Vec x, T y) { return x != Vec(y); } -SINT Vec> operator<=(Vec x, T y) { return x <= Vec(y); } -SINT Vec> operator>=(Vec x, T y) { return x >= Vec(y); } -SINT Vec> operator< (Vec x, T y) { return x < Vec(y); } -SINT Vec> operator> (Vec x, T y) { return x > Vec(y); } -SINT Vec min(Vec x, T y) { return min(x, Vec(y)); } -SINT Vec max(Vec x, T y) { return max(x, Vec(y)); } +SINTU Vec operator+ (Vec x, U y) { return x + Vec(y); } +SINTU Vec operator- (Vec x, U y) { return x - Vec(y); } +SINTU Vec operator* (Vec x, U y) { return x * Vec(y); } +SINTU Vec operator/ (Vec x, U y) { return x / Vec(y); } +SINTU Vec operator^ (Vec x, U y) { return x ^ Vec(y); } +SINTU Vec operator& (Vec x, U y) { return x & Vec(y); } +SINTU Vec operator| (Vec x, U y) { return x | Vec(y); } +SINTU Vec> operator==(Vec x, U y) { return x == Vec(y); } +SINTU Vec> operator!=(Vec x, U y) { return x != Vec(y); } +SINTU Vec> operator<=(Vec x, U y) { return x <= Vec(y); } +SINTU Vec> operator>=(Vec x, U y) { return x >= Vec(y); } +SINTU Vec> operator< (Vec x, U y) { return x < Vec(y); } +SINTU Vec> operator> (Vec x, U y) { return x > Vec(y); } +SINTU Vec min(Vec x, U y) { return min(x, Vec(y)); } +SINTU Vec max(Vec x, U y) { return max(x, Vec(y)); } // All vector/scalar combinations for mad() with at least one vector. -SINT Vec mad(T f, Vec m, Vec a) { return Vec(f)*m + a; } -SINT Vec mad(Vec f, T m, Vec a) { return f*Vec(m) + a; } -SINT Vec mad(Vec f, Vec m, T a) { return f*m + Vec(a); } -SINT Vec mad(Vec f, T m, T a) { return f*Vec(m) + Vec(a); } -SINT Vec mad(T f, Vec m, T a) { return Vec(f)*m + Vec(a); } -SINT Vec mad(T f, T m, Vec a) { return Vec(f)*Vec(m) + a; } +SINTU Vec mad(U f, Vec m, Vec a) { return Vec(f)*m + a; } +SINTU Vec mad(Vec f, U m, Vec a) { return f*Vec(m) + a; } +SINTU Vec mad(Vec f, Vec m, U a) { return f*m + Vec(a); } +SINTU Vec mad(Vec f, U m, U a) { return f*Vec(m) + Vec(a); } +SINTU Vec mad(U f, Vec m, U a) { return Vec(f)*m + Vec(a); } +SINTU Vec mad(U f, U m, Vec a) { return Vec(f)*Vec(m) + a; } // The various op= operators, for vectors... SINT Vec& operator+=(Vec& x, Vec y) { return (x = x + y); } @@ -347,13 +356,13 @@ SINT Vec& operator&=(Vec& x, Vec y) { return (x = x & y); } SINT Vec& operator|=(Vec& x, Vec y) { return (x = x | y); } // ... for scalars... -SINT Vec& operator+=(Vec& x, T y) { return (x = x + Vec(y)); } -SINT Vec& operator-=(Vec& x, T y) { return (x = x - Vec(y)); } -SINT Vec& operator*=(Vec& x, T y) { return (x = x * Vec(y)); } -SINT Vec& operator/=(Vec& x, T y) { return (x = x / Vec(y)); } -SINT Vec& operator^=(Vec& x, T y) { return (x = x ^ Vec(y)); } -SINT Vec& operator&=(Vec& x, T y) { return (x = x & Vec(y)); } -SINT Vec& operator|=(Vec& x, T y) { return (x = x | Vec(y)); } +SINTU Vec& operator+=(Vec& x, U y) { return (x = x + Vec(y)); } +SINTU Vec& operator-=(Vec& x, U y) { return (x = x - Vec(y)); } +SINTU Vec& operator*=(Vec& x, U y) { return (x = x * Vec(y)); } +SINTU Vec& operator/=(Vec& x, U y) { return (x = x / Vec(y)); } +SINTU Vec& operator^=(Vec& x, U y) { return (x = x ^ Vec(y)); } +SINTU Vec& operator&=(Vec& x, U y) { return (x = x & Vec(y)); } +SINTU Vec& operator|=(Vec& x, U y) { return (x = x | Vec(y)); } // ... and for shifts. SINT Vec& operator<<=(Vec& x, int bits) { return (x = x << bits); } @@ -434,6 +443,7 @@ namespace skvx { } // namespace skvx #endif // !defined(SKNX_NO_SIMD) +#undef SINTU #undef SINT #undef SIT #undef SI diff --git a/tests/SkVxTest.cpp b/tests/SkVxTest.cpp index 263c4192f4..61f6621cec 100644 --- a/tests/SkVxTest.cpp +++ b/tests/SkVxTest.cpp @@ -132,4 +132,14 @@ DEF_TEST(SkVx, r) { 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})); + + // Test that mixed types can be used where they make sense. Mostly about ergonomics. + REPORTER_ASSERT(r, all(float4{1,2,3,4} < 5)); + REPORTER_ASSERT(r, all( byte4{1,2,3,4} < 5)); + REPORTER_ASSERT(r, all( int4{1,2,3,4} < 5.0f)); + float4 five = 5; + REPORTER_ASSERT(r, all(five == 5.0f)); + REPORTER_ASSERT(r, all(five == 5)); + + REPORTER_ASSERT(r, all(max(2, min(float4{1,2,3,4}, 3)) == float4{2,2,3,3})); }