diff options
Diffstat (limited to 'gfx/wr/swgl/src/vector_type.h')
-rw-r--r-- | gfx/wr/swgl/src/vector_type.h | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/gfx/wr/swgl/src/vector_type.h b/gfx/wr/swgl/src/vector_type.h new file mode 100644 index 0000000000..43364ffcce --- /dev/null +++ b/gfx/wr/swgl/src/vector_type.h @@ -0,0 +1,563 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef __clang__ +# ifdef __SSE2__ +# include <xmmintrin.h> +# define USE_SSE2 1 +# endif +# ifdef __ARM_NEON +# include <arm_neon.h> +# define USE_NEON 1 +# endif +#endif + +namespace glsl { + +#ifdef __clang__ +template <typename T, int N> +using VectorType = T __attribute__((ext_vector_type(N))); + +# define CONVERT(vector, type) __builtin_convertvector(vector, type) +# define SHUFFLE(a, b, ...) __builtin_shufflevector(a, b, __VA_ARGS__) + +template <typename T> +SI VectorType<T, 4> combine(VectorType<T, 2> a, VectorType<T, 2> b) { + return __builtin_shufflevector(a, b, 0, 1, 2, 3); +} + +template <typename T> +SI VectorType<T, 8> combine(VectorType<T, 4> a, VectorType<T, 4> b) { + return __builtin_shufflevector(a, b, 0, 1, 2, 3, 4, 5, 6, 7); +} + +template <typename T> +SI VectorType<T, 16> combine(VectorType<T, 8> a, VectorType<T, 8> b) { + return __builtin_shufflevector(a, b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15); +} + +template <typename T> +SI VectorType<T, 2> lowHalf(VectorType<T, 4> a) { + return __builtin_shufflevector(a, a, 0, 1); +} + +template <typename T> +SI VectorType<T, 2> highHalf(VectorType<T, 4> a) { + return __builtin_shufflevector(a, a, 2, 3); +} + +template <typename T> +SI VectorType<T, 4> lowHalf(VectorType<T, 8> a) { + return __builtin_shufflevector(a, a, 0, 1, 2, 3); +} + +template <typename T> +SI VectorType<T, 4> highHalf(VectorType<T, 8> a) { + return __builtin_shufflevector(a, a, 4, 5, 6, 7); +} + +template <typename T> +SI VectorType<T, 8> lowHalf(VectorType<T, 16> a) { + return __builtin_shufflevector(a, a, 0, 1, 2, 3, 4, 5, 6, 7); +} + +template <typename T> +SI VectorType<T, 8> highHalf(VectorType<T, 16> a) { + return __builtin_shufflevector(a, a, 8, 9, 10, 11, 12, 13, 14, 15); +} + +template <typename T> +SI VectorType<T, 8> expand(VectorType<T, 4> a) { + return __builtin_shufflevector(a, a, 0, 1, 2, 3, -1, -1, -1, -1); +} +#else +template <typename T> +struct VectorMask { + typedef T type; +}; +template <> +struct VectorMask<uint32_t> { + typedef int32_t type; +}; +template <> +struct VectorMask<uint16_t> { + typedef int16_t type; +}; +template <> +struct VectorMask<uint8_t> { + typedef int8_t type; +}; +template <> +struct VectorMask<float> { + typedef int type; +}; + +template <typename T, int N> +struct VectorType { + enum { SIZE = N }; + + typedef T data_type __attribute__((vector_size(sizeof(T) * N))); + typedef typename VectorMask<T>::type mask_index; + typedef mask_index mask_type + __attribute__((vector_size(sizeof(mask_index) * N))); + typedef T half_type __attribute__((vector_size(sizeof(T) * (N / 2)))); + union { + data_type data; + struct { + T x, y, z, w; + }; + T elements[N]; + struct { + half_type low_half, high_half; + }; + }; + + VectorType() : data{0} {} + + constexpr VectorType(const VectorType& rhs) : data(rhs.data) {} + // GCC vector extensions only support broadcasting scalars on arithmetic ops, + // but not on initializers, hence the following... + constexpr VectorType(T n) : data((data_type){0} + n) {} + constexpr VectorType(T a, T b, T c, T d) : data{a, b, c, d} {} + constexpr VectorType(T a, T b, T c, T d, T e, T f, T g, T h) + : data{a, b, c, d, e, f, g, h} {} + constexpr VectorType(T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, + T l, T m, T n, T o, T p) + : data{a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p} {} + + SI VectorType wrap(const data_type& data) { + VectorType v; + v.data = data; + return v; + } + + T& operator[](size_t i) { return elements[i]; } + T operator[](size_t i) const { return elements[i]; } + + template <typename U> + operator VectorType<U, 2>() const { + return VectorType<U, 2>::wrap( + (typename VectorType<U, N>::data_type){U(x), U(y)}); + } + template <typename U> + operator VectorType<U, 4>() const { + return VectorType<U, 4>::wrap( + (typename VectorType<U, N>::data_type){U(x), U(y), U(z), U(w)}); + } + template <typename U> + operator VectorType<U, 8>() const { + return VectorType<U, 8>::wrap((typename VectorType<U, N>::data_type){ + U(elements[0]), U(elements[1]), U(elements[2]), U(elements[3]), + U(elements[4]), U(elements[5]), U(elements[6]), U(elements[7])}); + } + template <typename U> + operator VectorType<U, 16>() const { + return VectorType<U, 16>::wrap((typename VectorType<U, N>::data_type){ + U(elements[0]), + U(elements[1]), + U(elements[2]), + U(elements[3]), + U(elements[4]), + U(elements[5]), + U(elements[6]), + U(elements[7]), + U(elements[8]), + U(elements[9]), + U(elements[10]), + U(elements[11]), + U(elements[12]), + U(elements[13]), + U(elements[14]), + U(elements[15]), + }); + } + + VectorType operator-() const { return wrap(-data); } + VectorType operator~() const { return wrap(~data); } + + VectorType operator&(VectorType x) const { return wrap(data & x.data); } + VectorType operator&(T x) const { return wrap(data & x); } + VectorType operator|(VectorType x) const { return wrap(data | x.data); } + VectorType operator|(T x) const { return wrap(data | x); } + VectorType operator^(VectorType x) const { return wrap(data ^ x.data); } + VectorType operator^(T x) const { return wrap(data ^ x); } + VectorType operator<<(int x) const { return wrap(data << x); } + VectorType operator>>(int x) const { return wrap(data >> x); } + VectorType operator+(VectorType x) const { return wrap(data + x.data); } + VectorType operator+(T x) const { return wrap(data + x); } + friend VectorType operator+(T x, VectorType y) { return wrap(x + y.data); } + VectorType operator-(VectorType x) const { return wrap(data - x.data); } + VectorType operator-(T x) const { return wrap(data - x); } + friend VectorType operator-(T x, VectorType y) { return wrap(x - y.data); } + VectorType operator*(VectorType x) const { return wrap(data * x.data); } + VectorType operator*(T x) const { return wrap(data * x); } + friend VectorType operator*(T x, VectorType y) { return wrap(x * y.data); } + VectorType operator/(VectorType x) const { return wrap(data / x.data); } + VectorType operator/(T x) const { return wrap(data / x); } + friend VectorType operator/(T x, VectorType y) { return wrap(x / y.data); } + VectorType operator%(int x) const { return wrap(data % x); } + + VectorType& operator&=(VectorType x) { + data &= x.data; + return *this; + } + VectorType& operator|=(VectorType x) { + data |= x.data; + return *this; + } + VectorType& operator^=(VectorType x) { + data ^= x.data; + return *this; + } + VectorType& operator<<=(int x) { + data <<= x; + return *this; + } + VectorType& operator>>=(int x) { + data >>= x; + return *this; + } + VectorType& operator+=(VectorType x) { + data += x.data; + return *this; + } + VectorType& operator-=(VectorType x) { + data -= x.data; + return *this; + } + VectorType& operator*=(VectorType x) { + data *= x.data; + return *this; + } + VectorType& operator/=(VectorType x) { + data /= x.data; + return *this; + } + VectorType& operator%=(int x) { + data %= x; + return *this; + } + + VectorType<mask_type, N> operator==(VectorType x) const { + return VectorType<mask_type, N>::wrap(data == x.data); + } + VectorType<mask_type, N> operator!=(VectorType x) const { + return VectorType<mask_type, N>::wrap(data != x.data); + } + VectorType<mask_type, N> operator<(VectorType x) const { + return VectorType<mask_type, N>::wrap(data < x.data); + } + VectorType<mask_type, N> operator>(VectorType x) const { + return VectorType<mask_type, N>::wrap(data > x.data); + } + VectorType<mask_type, N> operator<=(VectorType x) const { + return VectorType<mask_type, N>::wrap(data <= x.data); + } + VectorType<mask_type, N> operator>=(VectorType x) const { + return VectorType<mask_type, N>::wrap(data >= x.data); + } + + VectorType operator!() const { return wrap(!data); } + VectorType operator&&(VectorType x) const { return wrap(data & x.data); } + VectorType operator||(VectorType x) const { return wrap(data | x.data); } + + VectorType& operator=(VectorType x) { + data = x.data; + return *this; + } + + VectorType<T, 4> shuffle(VectorType b, mask_index x, mask_index y, + mask_index z, mask_index w) const { + return VectorType<T, 4>::wrap(__builtin_shuffle( + data, b.data, (typename VectorType<T, 4>::mask_type){x, y, z, w})); + } + VectorType<T, 8> shuffle(VectorType b, mask_index x, mask_index y, + mask_index z, mask_index w, mask_index s, + mask_index t, mask_index u, mask_index v) const { + return VectorType<T, 8>::wrap(__builtin_shuffle( + data, b.data, + (typename VectorType<T, 8>::mask_type){x, y, z, w, s, t, u, v})); + } + VectorType<T, 16> shuffle(VectorType b, mask_index x, mask_index y, + mask_index z, mask_index w, mask_index s, + mask_index t, mask_index u, mask_index v, + mask_index i, mask_index j, mask_index k, + mask_index l, mask_index m, mask_index n, + mask_index o, mask_index p) const { + return VectorType<T, 16>::wrap( + __builtin_shuffle(data, b.data, + (typename VectorType<T, 16>::mask_type){ + x, y, z, w, s, t, u, v, i, j, k, l, m, n, o, p})); + } + + VectorType<T, 4> swizzle(mask_index x, mask_index y, mask_index z, + mask_index w) const { + return VectorType<T, 4>::wrap(__builtin_shuffle( + data, (typename VectorType<T, 4>::mask_type){x, y, z, w})); + } + VectorType<T, 8> swizzle(mask_index x, mask_index y, mask_index z, + mask_index w, mask_index s, mask_index t, + mask_index u, mask_index v) const { + return VectorType<T, 8>::wrap(__builtin_shuffle( + data, (typename VectorType<T, 8>::mask_type){x, y, z, w, s, t, u, v})); + } + + SI VectorType wrap(half_type low, half_type high) { + VectorType v; + v.low_half = low; + v.high_half = high; + return v; + } + + VectorType<T, N * 2> combine(VectorType high) const { + return VectorType<T, N * 2>::wrap(data, high.data); + } + +# define xxxx swizzle(0, 0, 0, 0) +# define yyyy swizzle(1, 1, 1, 1) +# define zzzz swizzle(2, 2, 2, 2) +# define wwww swizzle(3, 3, 3, 3) +# define xxyy swizzle(0, 0, 1, 1) +# define xxzz swizzle(0, 0, 2, 2) +# define yyww swizzle(1, 1, 3, 3) +# define zzww swizzle(2, 2, 3, 3) +# define xyxy swizzle(0, 1, 0, 1) +# define xzxz swizzle(0, 2, 0, 2) +# define ywyw swizzle(1, 3, 1, 3) +# define zwzw swizzle(2, 3, 2, 3) +# define zwxy swizzle(2, 3, 0, 1) +# define zyxw swizzle(2, 1, 0, 3) +# define xxyz swizzle(0, 0, 1, 2) +# define xyyz swizzle(0, 1, 1, 2) +# define xyzz swizzle(0, 1, 2, 2) +# define xzyw swizzle(0, 2, 1, 3) +# define yzwx swizzle(1, 2, 3, 0) +# define wxyz swizzle(3, 0, 1, 2) +# define wzyx swizzle(3, 2, 1, 0) +# define xxxxyyyy XXXXYYYY() + VectorType<T, 8> XXXXYYYY() const { + return swizzle(0, 0, 0, 0).combine(swizzle(1, 1, 1, 1)); + } +# define zzzzwwww ZZZZWWWW() + VectorType<T, 8> ZZZZWWWW() const { + return swizzle(2, 2, 2, 2).combine(swizzle(3, 3, 3, 3)); + } +# define xyzwxyzw XYZWXYZW() + VectorType<T, 8> XYZWXYZW() const { return combine(*this); } +# define xyxyxyxy XYXYXYXY() + VectorType<T, 8> XYXYXYXY() const { + return swizzle(0, 1, 0, 1).combine(swizzle(0, 1, 0, 1)); + } +# define zwzwzwzw ZWZWZWZW() + VectorType<T, 8> ZWZWZWZW() const { + return swizzle(2, 3, 2, 3).combine(swizzle(2, 3, 2, 3)); + } +# define xxyyzzww XXYYZZWW() + VectorType<T, 8> XXYYZZWW() const { + return swizzle(0, 0, 1, 1).combine(swizzle(2, 2, 3, 3)); + } +# define xxxxyyyyzzzzwwww XXXXYYYYZZZZWWWW() + VectorType<T, 16> XXXXYYYYZZZZWWWW() { + return XXXXYYYY().combine(ZZZZWWWW()); + } +}; + +template <typename T> +struct VectorType<T, 2> { + typedef T data_type __attribute__((vector_size(sizeof(T) * 2))); + union { + data_type data; + struct { + T x, y; + }; + T elements[2]; + }; + + SI VectorType wrap(const data_type& data) { + VectorType v; + v.data = data; + return v; + } + + VectorType operator&(VectorType x) const { return wrap(data & x.data); } + VectorType operator&(T x) const { return wrap(data & x); } + VectorType operator|(VectorType x) const { return wrap(data | x.data); } + VectorType operator|(T x) const { return wrap(data | x); } +}; + +# define CONVERT(vector, type) ((type)(vector)) +# define SHUFFLE(a, b, ...) a.shuffle(b, __VA_ARGS__) + +template <typename T, int N> +SI VectorType<T, N * 2> combine(VectorType<T, N> a, VectorType<T, N> b) { + return VectorType<T, N * 2>::wrap(a.data, b.data); +} + +template <typename T, int N> +SI VectorType<T, N / 2> lowHalf(VectorType<T, N> a) { + return VectorType<T, N / 2>::wrap(a.low_half); +} + +template <typename T, int N> +SI VectorType<T, N / 2> highHalf(VectorType<T, N> a) { + return VectorType<T, N / 2>::wrap(a.high_half); +} + +template <typename T, int N> +SI VectorType<T, N * 2> expand(VectorType<T, N> a) { + return combine(a, a); +} +#endif + +template <typename T, int N> +SI VectorType<T, N * 4> combine(VectorType<T, N> a, VectorType<T, N> b, + VectorType<T, N> c, VectorType<T, N> d) { + return combine(combine(a, b), combine(c, d)); +} + +template <typename T, int N> +SI VectorType<T, N> combineLow(VectorType<T, N> a, VectorType<T, N> b) { + return combine(lowHalf(a), lowHalf(b)); +} + +template <typename T, int N> +SI VectorType<T, N> combineHigh(VectorType<T, N> a, VectorType<T, N> b) { + return combine(highHalf(a), highHalf(b)); +} + +template <typename T, int N> +SI VectorType<T, N * 2> repeat2(VectorType<T, N> a) { + return combine(a, a); +} + +template <typename T, int N> +SI VectorType<T, N * 4> repeat4(VectorType<T, N> a) { + return combine(a, a, a, a); +} + +template <typename T> +SI VectorType<T, 4> zipLow(VectorType<T, 4> a, VectorType<T, 4> b) { + return SHUFFLE(a, b, 0, 4, 1, 5); +} + +template <typename T> +SI VectorType<T, 4> zipHigh(VectorType<T, 4> a, VectorType<T, 4> b) { + return SHUFFLE(a, b, 2, 6, 3, 7); +} + +template <typename T> +SI VectorType<T, 8> zipLow(VectorType<T, 8> a, VectorType<T, 8> b) { + return SHUFFLE(a, b, 0, 8, 1, 9, 2, 10, 3, 11); +} + +template <typename T> +SI VectorType<T, 8> zipHigh(VectorType<T, 8> a, VectorType<T, 8> b) { + return SHUFFLE(a, b, 4, 12, 5, 13, 6, 14, 7, 15); +} + +template <typename T> +SI VectorType<T, 16> zipLow(VectorType<T, 16> a, VectorType<T, 16> b) { + return SHUFFLE(a, b, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23); +} + +template <typename T> +SI VectorType<T, 16> zipHigh(VectorType<T, 16> a, VectorType<T, 16> b) { + return SHUFFLE(a, b, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, + 31); +} + +template <typename T> +SI VectorType<T, 8> zip2Low(VectorType<T, 8> a, VectorType<T, 8> b) { + return SHUFFLE(a, b, 0, 1, 8, 9, 2, 3, 10, 11); +} + +template <typename T> +SI VectorType<T, 8> zip2High(VectorType<T, 8> a, VectorType<T, 8> b) { + return SHUFFLE(a, b, 4, 5, 12, 13, 6, 7, 14, 15); +} + +#ifdef __clang__ +template <typename T> +SI VectorType<T, 8> zip(VectorType<T, 4> a, VectorType<T, 4> b) { + return SHUFFLE(a, b, 0, 4, 1, 5, 2, 6, 3, 7); +} + +template <typename T> +SI VectorType<T, 16> zip(VectorType<T, 8> a, VectorType<T, 8> b) { + return SHUFFLE(a, b, 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15); +} +#else +template <typename T, int N> +SI VectorType<T, N * 2> zip(VectorType<T, N> a, VectorType<T, N> b) { + return combine(zipLow(a, b), zipHigh(a, b)); +} +#endif + +template <typename T> +struct Unaligned { + template <typename P> + SI T load(const P* p) { + T v; + memcpy(&v, p, sizeof(v)); + return v; + } + + template <typename P> + SI void store(P* p, T v) { + memcpy(p, &v, sizeof(v)); + } +}; + +#ifndef __clang__ +template <typename T, int N> +struct Unaligned<VectorType<T, N>> { + template <typename P> + SI VectorType<T, N> load(const P* p) { + VectorType<T, N> v; + memcpy(v.elements, p, sizeof(v)); + return v; + } + + template <typename P> + SI void store(P* p, VectorType<T, N> v) { + memcpy(p, v.elements, sizeof(v)); + } +}; +#endif + +template <typename T, typename P> +SI T unaligned_load(const P* p) { + return Unaligned<T>::load(p); +} + +template <typename T, typename P> +SI void unaligned_store(P* p, T v) { + Unaligned<T>::store(p, v); +} + +template <typename D, typename S> +SI D bit_cast(const S& src) { + static_assert(sizeof(D) == sizeof(S), ""); + return unaligned_load<D>(&src); +} + +template <typename T> +using V2 = VectorType<T, 2>; +template <typename T> +using V4 = VectorType<T, 4>; +using Float = V4<float>; +using I32 = V4<int32_t>; +using I16 = V4<int16_t>; +using U64 = V4<uint64_t>; +using U32 = V4<uint32_t>; +using U16 = V4<uint16_t>; +using U8 = V4<uint8_t>; +using Bool = V4<int>; +template <typename T> +using V8 = VectorType<T, 8>; +template <typename T> +using V16 = VectorType<T, 16>; + +} // namespace glsl |