diff --git a/Sources/Plasma/CoreLib/CMakeLists.txt b/Sources/Plasma/CoreLib/CMakeLists.txt index e4cf8278..d99906de 100644 --- a/Sources/Plasma/CoreLib/CMakeLists.txt +++ b/Sources/Plasma/CoreLib/CMakeLists.txt @@ -15,6 +15,7 @@ set(CoreLib_SOURCES HeadSpin.cpp hsBitVector.cpp hsBounds.cpp + hsCpuID.cpp hsCritSect.cpp hsExceptionStack.cpp hsFastMath.cpp @@ -57,6 +58,7 @@ set(CoreLib_HEADERS hsBitVector.h hsBounds.h hsColorRGBA.h + hsCpuID.h hsCritSect.h hsExceptions.h hsFastMath.h diff --git a/Sources/Plasma/CoreLib/hsCpuID.cpp b/Sources/Plasma/CoreLib/hsCpuID.cpp new file mode 100644 index 00000000..12c99f9b --- /dev/null +++ b/Sources/Plasma/CoreLib/hsCpuID.cpp @@ -0,0 +1,71 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include + +#include "hsCpuID.h" + +hsCpuId::hsCpuId() { + const unsigned int sse1_flag = 1<<25; + const unsigned int sse2_flag = 1<<26; + const unsigned int sse3_flag = 1<<0; + const unsigned int ssse3_flag = 1<<9; + const unsigned int sse41_flag = 1<<19; + const unsigned int sse42_flag = 1<<20; + const unsigned int avx_flag = 1 << 28; + + unsigned int cpu_info[4]; + __cpuid((int*)cpu_info, 1); + has_sse1 = (cpu_info[3] & sse1_flag) || false; + has_sse2 = (cpu_info[3] & sse2_flag) || false; + has_sse3 = (cpu_info[2] & sse3_flag) || false; + has_ssse3 = (cpu_info[2] & ssse3_flag) || false; + has_sse41 = (cpu_info[2] & sse41_flag) || false; + has_sse42 = (cpu_info[2] & sse42_flag) || false; + has_avx = (cpu_info[2] & avx_flag) || false; +} + +const hsCpuId& hsCpuId::instance() +{ + static hsCpuId self; + return self; +} diff --git a/Sources/Plasma/CoreLib/hsCpuID.h b/Sources/Plasma/CoreLib/hsCpuID.h new file mode 100644 index 00000000..6c5f8385 --- /dev/null +++ b/Sources/Plasma/CoreLib/hsCpuID.h @@ -0,0 +1,182 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +////////////////////////////////////////////////////////////////////// +// +// hsCpuID - Processor feature detection and function dispatcher +// +// +// == Example Usage == +// +// #ifdef HS_SIMD_INCLUDE +// # include HS_SIMD_INCLUDE +// #endif +// +// float my_func_fpu() { +// ... +// } +// +// float my_func_avx() { +// #ifdef HS_AVX +// ... +// #endif +// } +// +// +// typedef float(*func_ptr)(); +// static hsFunctionDispatcher my_func; +// +// hsFunctionDispatcher float::my_func(float::my_func_fpu, 0, 0, 0, 0, 0, 0, float::my_func_avx); +// +////////////////////////////////////////////////////////////////////// + + + +#ifndef hsCpuID_inc +#define hsCpuID_inc + +#if defined __AVX__ || _MSC_VER >= 1600 +#define HS_AVX +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "immintrin.h" +#endif +#endif +#if defined __SSE4_2__ || _MSC_VER >= 1600 +#define HS_SSE42 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "nmmintrin.h" +#endif +#endif +#if defined __SSE4_1__ || _MSC_VER >= 1600 +#define HS_SSE41 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "smmintrin.h" +#endif +#endif +#if defined __SSSE3__ || _MSC_VER >= 1600 +#define HS_SSSE3 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "tmmintrin.h" +#endif +#endif +#if defined __SSE3__ || _MSC_VER >= 1400 +#define HS_SSE3 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "pmmintrin.h" +#endif +#endif +#if defined __SSE2__ || _MSC_VER >= 1300 +#define HS_SSE2 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "emmintrin.h" +#endif +#endif +#if defined __SSE__ || _MSC_VER >= 1300 +#define HS_SSE1 +#ifndef HS_SIMD_INCLUDE +# define HS_SIMD_INCLUDE "xmmintrin.h" +#endif +#endif + + +struct hsCpuId { + bool has_sse1; + bool has_sse2; + bool has_sse3; + bool has_ssse3; + bool has_sse41; + bool has_sse42; + bool has_avx; + + hsCpuId(); + static const hsCpuId& instance(); +}; + +template +struct hsFunctionDispatcher { + hsFunctionDispatcher(func_ptr fpu, func_ptr sse1=0, func_ptr sse2=0, func_ptr sse3=0, func_ptr ssse3=0, func_ptr sse41=0, func_ptr sse42=0, func_ptr avx=0) { + hsAssert(fpu, "FPU fallback function required."); + const hsCpuId& cpu = hsCpuId::instance(); +#ifdef HS_AVX + if (cpu.has_avx && avx) { + call = avx; + } else +#endif +#ifdef HS_SSE42 + if (cpu.has_sse42 && sse42) { + call = sse42; + } else +#endif +#ifdef HS_SSE41 + if (cpu.has_sse41 && sse41) { + call = sse41; + } else +#endif +#ifdef HS_SSSE3 + if (cpu.has_ssse3 && ssse3) { + call = ssse3; + } else +#endif +#ifdef HS_SSE3 + if (cpu.has_sse3 && sse3) { + call = sse3; + } else +#endif +#ifdef HS_SSE2 + if (cpu.has_sse2 && sse2) { + call = sse2; + } else +#endif +#ifdef HS_SSE1 + if (cpu.has_sse1 && sse1) { + call = sse1; + } else +#endif + { + call = fpu; + } + }; + func_ptr call; +}; + + +#endif // hsCpuID_inc \ No newline at end of file