1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-23 23:04:36 +01:00

Move SSE41 and AVX2 detection into Platform namespace

This commit is contained in:
Aaron van Geffen
2024-07-12 14:36:45 +02:00
parent 6bea2e8190
commit e3bb105a06
9 changed files with 71 additions and 76 deletions

View File

@@ -17,6 +17,15 @@
# include <windows.h>
#endif
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
# include <cpuid.h>
# define OpenRCT2_CPUID_GNUC_X86
#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_X64) || defined(_M_IX86)) // VS2008
# include <intrin.h>
# include <nmmintrin.h>
# 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<uint32_t>(std::chrono::duration_cast<std::chrono::milliseconds>(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<int*>(cpuid_outdata), static_cast<int>(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