mirror of
https://github.com/g-truc/glm.git
synced 2024-11-29 19:34:36 +00:00
constexpr simd vec: perf tuning for packed vec3
This commit is contained in:
parent
7f7eb3cd1b
commit
3e20cc6654
@ -109,15 +109,20 @@ namespace detail
|
||||
|
||||
# if GLM_ARCH & GLM_ARCH_SSE2_BIT
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if __x86_64__
|
||||
#define ATTR(size) __attribute__((packed,aligned(size)))
|
||||
#else
|
||||
#define ATTR(size)
|
||||
#endif
|
||||
template<typename T>
|
||||
struct storage<2, T, false>
|
||||
struct ATTR(sizeof(T)/2) storage<2, T, false>
|
||||
{
|
||||
typedef T type __attribute__((aligned(sizeof(T)),vector_size(2*sizeof(T))));
|
||||
typedef T type __attribute__((aligned(sizeof(T)/2),vector_size(2*sizeof(T))));
|
||||
};
|
||||
template<typename T>
|
||||
struct storage<1, T, false>
|
||||
struct ATTR(1) storage<1, T, false>
|
||||
{
|
||||
typedef T type __attribute__((aligned(1),vector_size(sizeof(T))));
|
||||
typedef T type;
|
||||
};
|
||||
template<typename T>
|
||||
struct storage<2, T, true>
|
||||
@ -129,6 +134,7 @@ namespace detail
|
||||
{
|
||||
typedef T type __attribute__((aligned(sizeof(T)),vector_size(sizeof(T))));
|
||||
};
|
||||
#undef ATTR
|
||||
#endif
|
||||
template<>
|
||||
struct storage<4, float, true>
|
||||
|
@ -9,47 +9,53 @@ namespace glm::detail
|
||||
using FirstTx = Tx0;
|
||||
};
|
||||
template <length_t Lx, typename Tx, qualifier Qx>
|
||||
using PaddedVec = PaddedGccVec<Lx, Tx, Qx, detail::BVecNeedsPadding<Lx, Tx, Qx>()>;
|
||||
using gcc_vec_t = PaddedVec<L, T, Q>::GccV;
|
||||
using GccVec = typename detail::GccVExt<Lx, Tx, Qx>::GccV;
|
||||
using gcc_vec_t = GccVec<L, T, Q>;
|
||||
using data_t = typename detail::storage<L, T, detail::is_aligned<Q>::value>::type;
|
||||
|
||||
static inline auto __attribute__((always_inline)) gcc_vec_to_data(PaddedVec<L, T, Q> v) {
|
||||
if constexpr (L == 3 && !BIsAlignedQ<Q>()) {
|
||||
data_t d;
|
||||
std::memcpy(&d, &v, sizeof(d));
|
||||
return d;
|
||||
} else {
|
||||
static inline auto __attribute__((always_inline)) gcc_vec_to_data(auto v) {
|
||||
static constexpr auto size = std::min(sizeof(v), sizeof(data_t));
|
||||
static constexpr auto biggerSize = std::max(sizeof(v), sizeof(data_t));
|
||||
if constexpr (size == biggerSize) {
|
||||
return std::bit_cast<data_t>(v);
|
||||
} else {
|
||||
data_t d;
|
||||
std::memcpy(&d, &v, size);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
static inline auto __attribute__((always_inline)) simd_ctor_scalar(arithmetic auto scalar) {
|
||||
PaddedVec<L, T, Q> v = {};
|
||||
v.gcc_vec = v.gcc_vec + ( (T)scalar );
|
||||
gcc_vec_t v = gcc_vec_t{} + ( (T)scalar );
|
||||
using Tx = decltype(scalar);
|
||||
scalar.Tx::~Tx();
|
||||
return gcc_vec_to_data(v);
|
||||
}
|
||||
|
||||
template <length_t Lx, typename Tx, qualifier Qx> requires (Lx == L)
|
||||
static inline auto __attribute__((always_inline)) simd_ctor(::glm::vec<Lx, Tx, Qx> v)
|
||||
{
|
||||
using OtherPaddedVec = PaddedVec<Lx, Tx, Qx>;
|
||||
OtherPaddedVec o = std::bit_cast<OtherPaddedVec>(v.data);
|
||||
PaddedVec<L, T, Q> converted = {.gcc_vec=__builtin_convertvector(o.gcc_vec, gcc_vec_t)};
|
||||
using OtherVec = GccVec<Lx, Tx, Qx>;
|
||||
OtherVec o;
|
||||
static constexpr auto size = std::min(sizeof(v.data), sizeof(o));
|
||||
std::memcpy(&o, &(v.data), size);
|
||||
using o_vec_t = decltype(v);
|
||||
v.o_vec_t::~o_vec_t();
|
||||
gcc_vec_t converted = __builtin_convertvector(o, gcc_vec_t);
|
||||
return gcc_vec_to_data(converted);
|
||||
}
|
||||
|
||||
template <length_t Lx, typename Tx, qualifier Qx> requires (Lx != L && Lx < L)
|
||||
static inline auto __attribute__((always_inline)) simd_ctor(::glm::vec<Lx, Tx, Qx> v)
|
||||
{
|
||||
using OtherPaddedVec = PaddedVec<Lx, Tx, Qx>;
|
||||
using OurSizeTheirType = PaddedVec<L, Tx, Qx>;
|
||||
OtherPaddedVec o = std::bit_cast<OtherPaddedVec>(v.data);
|
||||
OurSizeTheirType oExpanded = {};
|
||||
for (length_t i = 0; i < Lx; i++) {
|
||||
oExpanded.gcc_vec[i] = o.gcc_vec[i];
|
||||
}
|
||||
using OurSizeTheirType = GccVec<L, Tx, Qx>;
|
||||
static constexpr auto size = std::min(sizeof(OurSizeTheirType), sizeof(v.data));
|
||||
OurSizeTheirType oExpanded;
|
||||
std::memcpy(&oExpanded, &(v.data), size);
|
||||
using o_vec_t = decltype(v);
|
||||
v.o_vec_t::~o_vec_t();
|
||||
|
||||
PaddedVec<L, T, Q> converted = {.gcc_vec=__builtin_convertvector(oExpanded.gcc_vec, gcc_vec_t)};
|
||||
gcc_vec_t converted = __builtin_convertvector(oExpanded, gcc_vec_t);
|
||||
return gcc_vec_to_data(converted);
|
||||
}
|
||||
|
||||
@ -62,11 +68,13 @@ namespace glm::detail
|
||||
static inline auto __attribute__((always_inline)) simd_ctor_multi_scalars(A... scalars) requires ( isLengthOfVector<A...>() && SameArithmeticTypes<A...>())
|
||||
{
|
||||
//assuming that number of scalars is always the same as the length of the to-be-constructed vector
|
||||
using Tx = typename GetFirstType<A...>::FirstTx;
|
||||
using OtherPaddedVec = PaddedVec<L, Tx, Q>;
|
||||
typename OtherPaddedVec::GccV o = {Tx(scalars)...};
|
||||
PaddedVec<L, T, Q> converted = {.gcc_vec=__builtin_convertvector(o, gcc_vec_t)};
|
||||
return gcc_vec_to_data(converted);
|
||||
gcc_vec_t v;
|
||||
std::array<T, sizeof...(scalars)> pack{scalars...};
|
||||
for (int i = 0; i != sizeof...(scalars); i++ ) {
|
||||
v[i] = pack[i];
|
||||
pack[i].T::~T();
|
||||
}
|
||||
return gcc_vec_to_data(v);
|
||||
}
|
||||
};
|
||||
}
|
@ -94,9 +94,10 @@ namespace glm
|
||||
};
|
||||
}
|
||||
|
||||
/*template <length_t L, typename T, qualifier Q>
|
||||
using PaddedGccVec = detail::PaddedGccVec<L, T, Q, detail::BVecNeedsPadding<L, T, Q>()>;*/
|
||||
template <length_t L, typename T, qualifier Q>
|
||||
using PaddedGccVec = detail::PaddedGccVec<L, T, Q, detail::BVecNeedsPadding<L, T, Q>()>;
|
||||
|
||||
using GccVec = typename detail::GccVExt<L, T, Q>::GccV;
|
||||
template <length_t L, typename T, qualifier Q>
|
||||
using VecDataArray = detail::VecDataArray<L, T, Q, detail::BDataNeedsPadding<L, T, Q>()>;
|
||||
|
||||
@ -161,6 +162,7 @@ namespace glm
|
||||
switch (i)
|
||||
{
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
case 0:
|
||||
return x;
|
||||
case 1: {
|
||||
@ -192,6 +194,7 @@ namespace glm
|
||||
switch (i)
|
||||
{
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
case 0:
|
||||
return x;
|
||||
case 1: {
|
||||
@ -296,7 +299,7 @@ namespace glm
|
||||
{
|
||||
using VTX = decltype(vs0);
|
||||
if constexpr ( std::is_integral_v<VTX> || std::is_floating_point_v<VTX> ) {
|
||||
return RetArr<1>{vs0};
|
||||
return RetArr<1>{(T)vs0};
|
||||
} else if constexpr ( ( requires { VTX::k_len; }) ) {
|
||||
using Tx = VTX::value_type;
|
||||
using ArrX = VecDataArray<VTX::k_len, Tx, VTX::k_qual>;
|
||||
@ -323,7 +326,7 @@ namespace glm
|
||||
: EC<L, T, Q>
|
||||
{.data= [scalar...]() -> data_t
|
||||
{
|
||||
if (std::is_constant_evaluated()) {
|
||||
if (std::is_constant_evaluated() || (L == 3 && !BIsAlignedQ<Q>())) {
|
||||
DataArray a = {.p={ T(scalar)... }};
|
||||
return std::bit_cast<data_t>(a);
|
||||
} else {
|
||||
@ -454,7 +457,7 @@ namespace glm
|
||||
}
|
||||
|
||||
template<typename Tx>
|
||||
inline GLM_CONSTEXPR vec<L, T, Q> & operator*=(vec<L, Tx, Q> v)
|
||||
inline GLM_CONSTEXPR vec<L, T, Q> & operator*=(vec<L, Tx, Q> const& __restrict__ v) __restrict__
|
||||
{
|
||||
if constexpr (L < 3) {
|
||||
this->data *= v.data;
|
||||
@ -788,9 +791,12 @@ namespace glm
|
||||
}
|
||||
|
||||
|
||||
friend inline GLM_CONSTEXPR vec<L, T, Q> operator*(vec<L, T, Q> v1, vec<L, T, Q> v2)
|
||||
friend inline GLM_CONSTEXPR vec<L, T, Q> __attribute__((const, always_inline, nothrow, no_stack_protector)) operator*(vec<L, T, Q> v1, vec<L, T, Q> const& __restrict__ v2)
|
||||
{
|
||||
return vec<L, T, Q>(v1) *= v2;
|
||||
if constexpr (L == 3 && !BIsAlignedQ<Q>())
|
||||
return *(new (&v1) vec<L, T, Q>(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z));
|
||||
else
|
||||
return v1 *= v2;
|
||||
}
|
||||
|
||||
|
||||
@ -813,8 +819,11 @@ namespace glm
|
||||
}
|
||||
|
||||
template <length_t Lx>
|
||||
friend inline GLM_CONSTEXPR vec<L, T, Q> operator/(vec<Lx, T, Q> v1, vec<L, T, Q> v2) requires (!NotVec1<Lx> && NotVec1<L>)
|
||||
friend inline GLM_CONSTEXPR vec<L, T, Q> operator/(vec<Lx, T, Q> v1, vec<L, T, Q> && __restrict__ v2) requires (!NotVec1<Lx> && NotVec1<L>)
|
||||
{
|
||||
if constexpr (L == 3 && !BIsAlignedQ<Q>())
|
||||
return *(new (&v2) vec<L, T, Q>( v1.data / v2.x, v1.data/v2.y, v1.data/v2.z ));
|
||||
else
|
||||
return vec<L, T, Q>(v1.x) /= v2;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user