From e3bb105a062786c30db3f7f75fefc206c15d1dfc Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Fri, 12 Jul 2024 14:36:45 +0200 Subject: [PATCH] Move SSE41 and AVX2 detection into Platform namespace --- src/openrct2/drawing/Drawing.Sprite.cpp | 1 - src/openrct2/drawing/Drawing.cpp | 5 +- src/openrct2/drawing/LightFX.cpp | 1 - src/openrct2/drawing/Weather.cpp | 1 - src/openrct2/drawing/X8DrawingEngine.cpp | 1 - src/openrct2/platform/Platform.Common.cpp | 66 +++++++++++++++++++++++ src/openrct2/platform/Platform.h | 3 ++ src/openrct2/util/Util.cpp | 66 ----------------------- src/openrct2/util/Util.h | 3 -- 9 files changed, 71 insertions(+), 76 deletions(-) diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index 7d5116f7d0..4c04e5b79c 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -20,7 +20,6 @@ #include "../rct1/Csg.h" #include "../sprites.h" #include "../ui/UiContext.h" -#include "../util/Util.h" #include "ScrollingText.h" #include diff --git a/src/openrct2/drawing/Drawing.cpp b/src/openrct2/drawing/Drawing.cpp index dcf00ed2f4..6ccb4fbd57 100644 --- a/src/openrct2/drawing/Drawing.cpp +++ b/src/openrct2/drawing/Drawing.cpp @@ -21,7 +21,6 @@ #include "../object/WaterEntry.h" #include "../platform/Platform.h" #include "../sprites.h" -#include "../util/Util.h" #include "../world/Climate.h" #include "../world/Location.hpp" #include "LightFX.h" @@ -668,12 +667,12 @@ ImageCatalogue ImageId::GetCatalogue() const static auto GetMaskFunction() { - if (AVX2Available()) + if (Platform::AVX2Available()) { LOG_VERBOSE("registering AVX2 mask function"); return MaskAvx2; } - else if (SSE41Available()) + else if (Platform::SSE41Available()) { LOG_VERBOSE("registering SSE4.1 mask function"); return MaskSse4_1; diff --git a/src/openrct2/drawing/LightFX.cpp b/src/openrct2/drawing/LightFX.cpp index 66891a2817..de1a192ce1 100644 --- a/src/openrct2/drawing/LightFX.cpp +++ b/src/openrct2/drawing/LightFX.cpp @@ -21,7 +21,6 @@ #include "../ride/Ride.h" #include "../ride/RideData.h" #include "../ride/Vehicle.h" -#include "../util/Util.h" #include "../world/Map.h" #include "Drawing.h" diff --git a/src/openrct2/drawing/Weather.cpp b/src/openrct2/drawing/Weather.cpp index 025b9b32de..649c69f022 100644 --- a/src/openrct2/drawing/Weather.cpp +++ b/src/openrct2/drawing/Weather.cpp @@ -16,7 +16,6 @@ #include "../ride/TrackDesign.h" #include "../scenario/Scenario.h" #include "../ui/UiContext.h" -#include "../util/Util.h" #include "../world/Climate.h" #include "Drawing.h" #include "IDrawingEngine.h" diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 5a5257c74c..bd750df6c8 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -17,7 +17,6 @@ #include "../interface/Window.h" #include "../scenes/intro/IntroScene.h" #include "../ui/UiContext.h" -#include "../util/Util.h" #include "Drawing.h" #include "IDrawingContext.h" #include "IDrawingEngine.h" diff --git a/src/openrct2/platform/Platform.Common.cpp b/src/openrct2/platform/Platform.Common.cpp index 72246ddd82..b4dbe62b63 100644 --- a/src/openrct2/platform/Platform.Common.cpp +++ b/src/openrct2/platform/Platform.Common.cpp @@ -17,6 +17,15 @@ # include #endif +#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +# include +# define OpenRCT2_CPUID_GNUC_X86 +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_X64) || defined(_M_IX86)) // VS2008 +# include +# include +# define OpenRCT2_CPUID_MSVC_X86 +#endif + #include "../Context.h" #include "../Game.h" #include "../core/File.h" @@ -138,4 +147,61 @@ namespace Platform return static_cast(std::chrono::duration_cast(processTime).count()); } +#ifdef OPENRCT2_X86 + static bool CPUIDX86(uint32_t* cpuid_outdata, int32_t eax) + { +# if defined(OpenRCT2_CPUID_GNUC_X86) + int ret = __get_cpuid(eax, &cpuid_outdata[0], &cpuid_outdata[1], &cpuid_outdata[2], &cpuid_outdata[3]); + return ret == 1; +# elif defined(OpenRCT2_CPUID_MSVC_X86) + __cpuid(reinterpret_cast(cpuid_outdata), static_cast(eax)); + return true; +# else + return false; +# endif + } +#endif // OPENRCT2_X86 + + bool SSE41Available() + { +#ifdef OPENRCT2_X86 + // SSE4.1 support is declared as the 19th bit of ECX with CPUID(EAX = 1). + uint32_t regs[4] = { 0 }; + if (CPUIDX86(regs, 1)) + { + return (regs[2] & (1 << 19)); + } +#endif + return false; + } + + bool AVX2Available() + { +#ifdef OPENRCT2_X86 + // For GCC and similar use the builtin function, as cpuid changed its semantics in + // https://github.com/gcc-mirror/gcc/commit/132fa33ce998df69a9f793d63785785f4b93e6f1 + // which causes it to ignore subleafs, but the new function is unavailable on + // Ubuntu 18.04's toolchains. +# if defined(OpenRCT2_CPUID_GNUC_X86) && (!defined(__FreeBSD__) || (__FreeBSD__ > 10)) + return __builtin_cpu_supports("avx2"); +# else + // AVX2 support is declared as the 5th bit of EBX with CPUID(EAX = 7, ECX = 0). + uint32_t regs[4] = { 0 }; + if (CPUIDX86(regs, 7)) + { + bool avxCPUSupport = (regs[1] & (1 << 5)) != 0; + if (avxCPUSupport) + { + // Need to check if OS also supports the register of xmm/ymm + // This check has to be conditional, otherwise INVALID_INSTRUCTION exception. + uint64_t xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); + avxCPUSupport = (xcrFeatureMask & 0x6) || false; + } + return avxCPUSupport; + } +# endif +#endif + return false; + } + } // namespace Platform diff --git a/src/openrct2/platform/Platform.h b/src/openrct2/platform/Platform.h index d62a9578cc..cb3910071e 100644 --- a/src/openrct2/platform/Platform.h +++ b/src/openrct2/platform/Platform.h @@ -124,6 +124,9 @@ namespace Platform uint32_t GetTicks(); void Sleep(uint32_t ms); + + bool SSE41Available(); + bool AVX2Available(); } // namespace Platform #ifdef __ANDROID__ diff --git a/src/openrct2/util/Util.cpp b/src/openrct2/util/Util.cpp index 76f85a86e3..a6b96f6aed 100644 --- a/src/openrct2/util/Util.cpp +++ b/src/openrct2/util/Util.cpp @@ -106,72 +106,6 @@ int32_t UtilBitScanForward(int64_t source) #endif } -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) -# include -# define OpenRCT2_CPUID_GNUC_X86 -#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_X64) || defined(_M_IX86)) // VS2008 -# include -# include -# define OpenRCT2_CPUID_MSVC_X86 -#endif - -#ifdef OPENRCT2_X86 -static bool CPUIDX86(uint32_t* cpuid_outdata, int32_t eax) -{ -# if defined(OpenRCT2_CPUID_GNUC_X86) - int ret = __get_cpuid(eax, &cpuid_outdata[0], &cpuid_outdata[1], &cpuid_outdata[2], &cpuid_outdata[3]); - return ret == 1; -# elif defined(OpenRCT2_CPUID_MSVC_X86) - __cpuid(reinterpret_cast(cpuid_outdata), static_cast(eax)); - return true; -# else - return false; -# endif -} -#endif // OPENRCT2_X86 - -bool SSE41Available() -{ -#ifdef OPENRCT2_X86 - // SSE4.1 support is declared as the 19th bit of ECX with CPUID(EAX = 1). - uint32_t regs[4] = { 0 }; - if (CPUIDX86(regs, 1)) - { - return (regs[2] & (1 << 19)); - } -#endif - return false; -} - -bool AVX2Available() -{ -#ifdef OPENRCT2_X86 - // For GCC and similar use the builtin function, as cpuid changed its semantics in - // https://github.com/gcc-mirror/gcc/commit/132fa33ce998df69a9f793d63785785f4b93e6f1 - // which causes it to ignore subleafs, but the new function is unavailable on - // Ubuntu 18.04's toolchains. -# if defined(OpenRCT2_CPUID_GNUC_X86) && (!defined(__FreeBSD__) || (__FreeBSD__ > 10)) - return __builtin_cpu_supports("avx2"); -# else - // AVX2 support is declared as the 5th bit of EBX with CPUID(EAX = 7, ECX = 0). - uint32_t regs[4] = { 0 }; - if (CPUIDX86(regs, 7)) - { - bool avxCPUSupport = (regs[1] & (1 << 5)) != 0; - if (avxCPUSupport) - { - // Need to check if OS also supports the register of xmm/ymm - // This check has to be conditional, otherwise INVALID_INSTRUCTION exception. - uint64_t xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); - avxCPUSupport = (xcrFeatureMask & 0x6) || false; - } - return avxCPUSupport; - } -# endif -#endif - return false; -} - /* Case insensitive logical compare */ // Example: // - Guest 10 diff --git a/src/openrct2/util/Util.h b/src/openrct2/util/Util.h index 9e235c8fa2..1e664f1fcc 100644 --- a/src/openrct2/util/Util.h +++ b/src/openrct2/util/Util.h @@ -24,9 +24,6 @@ int32_t MetresToFeet(int32_t metres); int32_t MphToKmph(int32_t mph); int32_t MphToDmps(int32_t mph); -bool SSE41Available(); -bool AVX2Available(); - int32_t UtilBitScanForward(int32_t source); int32_t UtilBitScanForward(int64_t source); int32_t StrLogicalCmp(char const* a, char const* b);