You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.7 KiB
86 lines
2.7 KiB
#pragma once |
|
|
|
#include <array> |
|
#ifdef _MSC_VER |
|
#include <intrin.h> |
|
#endif |
|
#ifdef __GNUG__ |
|
#include <cpuid.h> |
|
#endif |
|
|
|
namespace cpu_features { |
|
|
|
enum Features : uint64_t { |
|
None = 0, |
|
SSE = 1 << 0, |
|
SSE2 = 1 << 1, |
|
SSE3 = 1 << 2, |
|
SSSE3 = 1 << 3, |
|
SSE4_1 = 1 << 4, |
|
SSE4_2 = 1 << 5, |
|
AVX = 1 << 6, |
|
AVX2 = 1 << 7, |
|
AVX512F = 1 << 8, |
|
AVX512PF = 1 << 9, |
|
AVX512ER = 1 << 10, |
|
AVX512CD = 1 << 11, |
|
}; |
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
|
|
namespace detail { |
|
#ifdef _MSC_VER |
|
inline void cpuid(std::array<int, 4>& info, int level) { |
|
__cpuid(info.data(), level); |
|
} |
|
#endif |
|
#ifdef __GNUG__ |
|
inline void cpuid(std::array<int, 4>& info, int level) { |
|
auto ptr = reinterpret_cast<unsigned int*>(info.data()); |
|
if (level == 1) { |
|
__get_cpuid(level, &ptr[0], &ptr[1], &ptr[2], &ptr[3]); |
|
} else { |
|
__cpuid_count(level, 0, ptr[0], ptr[1], ptr[2], ptr[3]); |
|
} |
|
} |
|
#endif |
|
|
|
inline Features get_features_impl() { |
|
std::array<int, 4> info = {0}; |
|
cpuid(info, 0); |
|
int feature_levels = info[0]; |
|
|
|
// Feature level 1 always exists |
|
cpuid(info, 1); |
|
std::underlying_type_t<Features> features = Features::None; |
|
if (info[3] & (1 << 25)) { features |= Features::SSE; } |
|
if (info[3] & (1 << 26)) { features |= Features::SSE2; } |
|
if (info[2] & (1 << 0)) { features |= Features::SSE3; } |
|
if (info[2] & (1 << 9)) { features |= Features::SSSE3; } |
|
if (info[2] & (1 << 19)) { features |= Features::SSE4_1; } |
|
if (info[2] & (1 << 20)) { features |= Features::SSE4_2; } |
|
if (info[2] & (1 << 28)) { features |= Features::AVX; } |
|
|
|
// Feature level 7 |
|
if (feature_levels >= 7) { |
|
std::array<int, 4> info7 = {0}; |
|
cpuid(info7, 7); |
|
if (info7[1] & (1 << 5)) { features |= Features::AVX2; } |
|
if (info7[1] & (1 << 16)) { features |= Features::AVX512F; } |
|
if (info7[1] & (1 << 26)) { features |= Features::AVX512PF; } |
|
if (info7[1] & (1 << 27)) { features |= Features::AVX512ER; } |
|
if (info7[1] & (1 << 28)) { features |= Features::AVX512CD; } |
|
} |
|
|
|
return static_cast<Features>(features); |
|
} |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
|
|
inline Features get_features() { |
|
static Features s_features = detail::get_features_impl(); |
|
return s_features; |
|
} |
|
|
|
} |