diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt index 434470b..27f123f 100644 --- a/common/rfb/CMakeLists.txt +++ b/common/rfb/CMakeLists.txt @@ -132,6 +132,8 @@ endif () find_package(PkgConfig REQUIRED) pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil libswscale) +pkg_check_modules(CPUID REQUIRED libcpuid) + find_package(TBB) if (TBB_FOUND) set(RFB_LIBRARIES ${RFB_LIBRARIES} tbb) @@ -150,9 +152,10 @@ target_include_directories(rfb PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tinyxml2 ${FFMPEG_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS} + ${CPUID_INCLUDE_DIRS} ) -target_link_libraries(rfb PUBLIC ${RFB_LIBRARIES} tinyxml2_objs) +target_link_libraries(rfb PUBLIC ${RFB_LIBRARIES} tinyxml2_objs ${TBB_LIBRARIES} ${CPUID_LIBRARIES}) if (UNIX) libtool_create_control_file(rfb) diff --git a/common/rfb/cpuid.cxx b/common/rfb/cpuid.cxx index c89f950..7976589 100644 --- a/common/rfb/cpuid.cxx +++ b/common/rfb/cpuid.cxx @@ -16,10 +16,12 @@ * USA. */ -#include +#include "cpuid.h" +#include +#include "LogWriter.h" -static uint32_t cpuid[4] = { 0 }; -static uint32_t extcpuid[4] = { 0 }; +static uint32_t cpuid[4] = {}; +static uint32_t extcpuid[4] = {}; static void getcpuid() { if (cpuid[0]) @@ -68,3 +70,28 @@ bool supportsAVX512f() { } }; // namespace rfb + +namespace cpu_info { + static rfb::LogWriter log("CpuFeatures"); + inline CpuFeatures::CpuFeatures() + { + if (!cpuid_present()) + { + log.error("CPU does not support CPUID."); + return; + } + + cpu_raw_data_t raw{}; + + if (cpuid_get_raw_data(&raw) < 0) + { + log.error("Cannot get CPUID raw data."); + return; + } + + if (cpu_identify(&raw, &data) < 0) + { + log.error("Cannot identify CPU."); + } + } +} // namespace cpu_info diff --git a/common/rfb/cpuid.h b/common/rfb/cpuid.h index c84b4a2..3b31d5b 100644 --- a/common/rfb/cpuid.h +++ b/common/rfb/cpuid.h @@ -19,10 +19,64 @@ #ifndef __RFB_CPUID_H__ #define __RFB_CPUID_H__ -namespace rfb { +#include +#include - bool supportsSSE2(); - bool supportsAVX512f(); -}; +namespace cpu_info { + //using namespace cpu_features; + //static const X86Info info = GetX86Info(); + // static const X86Microarchitecture uarch = GetX86Microarchitecture(&info); + //static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB; + + bool supportsSSE2(); + bool supportsAVX512f(); + + class CpuFeatures { + cpu_id_t data{}; + CpuFeatures(); + + public: + CpuFeatures(const CpuFeatures &) = delete; + CpuFeatures &operator=(const CpuFeatures &) = delete; + CpuFeatures(CpuFeatures &&) = delete; + CpuFeatures &operator=(CpuFeatures &&) = delete; + + static CpuFeatures &get() + { + static CpuFeatures instance{}; + return instance; + } + + [[nodiscard]] bool has_sse2() const { return data.flags[CPU_FEATURE_SSE2]; } + + [[nodiscard]] bool has_sse4_1() const { return data.flags[CPU_FEATURE_SSE4_1]; } + + [[nodiscard]] bool has_sse4_2() const { return data.flags[CPU_FEATURE_SSE4_2]; } + + [[nodiscard]] bool has_sse4a() const { return data.flags[CPU_FEATURE_SSE4A]; } + + [[nodiscard]] bool has_avx() const { return data.flags[CPU_FEATURE_AVX]; } + + [[nodiscard]] bool has_avx2() const { return data.flags[CPU_FEATURE_AVX2]; } + + [[nodiscard]] bool has_avx512f() const { return data.flags[CPU_FEATURE_AVX512F]; } + + [[nodiscard]] bool has_smt() const { return get_total_cpu_count() > get_cores_count(); } + + [[nodiscard]] uint16_t get_total_cpu_count() const { return std::max(1, data.total_logical_cpus); } + + [[nodiscard]] uint16_t get_cores_count() const { return std::max(1, data.num_cores); } + }; + + inline static const bool has_sse2 = CpuFeatures::get().has_sse2(); + inline static const bool has_sse4_1 = CpuFeatures::get().has_sse4_1(); + inline static const bool has_sse4_2 = CpuFeatures::get().has_sse4_2(); + inline static const bool has_sse4a = CpuFeatures::get().has_sse4a(); + inline static const bool has_avx = CpuFeatures::get().has_avx(); + inline static const bool has_avx2 = CpuFeatures::get().has_avx2(); + inline static const bool has_avx512f = CpuFeatures::get().has_avx512f(); + inline static const uint16_t cores_count = CpuFeatures::get().get_cores_count(); + inline static const uint16_t total_cpu_count = CpuFeatures::get().get_total_cpu_count(); +}; // namespace cpu_info #endif