Skip to content

Commit

Permalink
CPU Info Shenanigans
Browse files Browse the repository at this point in the history
1. Add CPU detection
2. Turn on AVX flags at build time
3. If you are running on a non-AVX box pop a warning saying may not
   work in the future
4. move the FPUState stuff and reinstate it in XT while at it

Closes surge-synthesizer#4466
  • Loading branch information
baconpaul committed May 3, 2021
1 parent abe00ca commit b41e914
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 111 deletions.
20 changes: 18 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
add_compile_options(-msse2 -mfpmath=sse)
endif()
endif()

# Add AVX support
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#if defined(__x86_64__) || defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
#ifndef __AVX__
#error
#endif
#endif
int main() {}" COMPILER_HAS_AVX_OR_IS_ARM)
if (NOT COMPILER_HAS_AVX_OR_IS_ARM)
message(STATUS "Adding -mavx to allow __AVX__ compiles" )
add_compile_options("-mavx")
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Any Clang
add_compile_options(
Expand Down Expand Up @@ -76,7 +91,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
endif()

if(MSVC)
# MSVC and pretenders
add_compile_options(
-WX # treat all warnings as errors

Expand All @@ -97,6 +111,8 @@ if(MSVC)
/Zc:alignedNew
/bigobj

/arch:AVX

# Build with Multiple Processes (Clang-cl builds use Ninja instead)
$<$<CXX_COMPILER_ID:MSVC>:/MP>
)
Expand Down Expand Up @@ -269,11 +285,11 @@ set(SURGE_SHARED_SOURCES
src/common/dsp/Wavetable.cpp
src/common/dsp/WavetableOscillator.cpp
src/common/dsp/WindowOscillator.cpp
src/common/util/FpuState.cpp
src/common/vt_dsp/basic_dsp.cpp
src/common/vt_dsp/halfratefilter.cpp
src/common/vt_dsp/lipol.cpp
src/common/vt_dsp/macspecific.cpp
src/common/CPUFeatures.cpp
src/common/DebugHelpers.cpp
src/common/ModulatorPresetManager.cpp
src/common/Parameter.cpp
Expand Down
204 changes: 204 additions & 0 deletions src/common/CPUFeatures.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
** Surge Synthesizer is Free and Open Source Software
**
** Surge is made available under the Gnu General Public License, v3.0
** https://www.gnu.org/licenses/gpl-3.0.en.html
**
** Copyright 2004-2021 by various individuals as described by the Git transaction log
**
** All source at: https://github.com/surge-synthesizer/surge.git
**
** Surge was a commercial product from 2004-2018, with Copyright and ownership
** in that period held by Claes Johanson at Vember Audio. Claes made Surge
** open source in September 2018.
*/

#include "CPUFeatures.h"
#include "globals.h"

#if MAC
#include <sys/types.h>
#include <sys/sysctl.h>
#endif

#if LINUX
#include <fstream>
#endif

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace Surge
{
namespace CPUFeatures
{

#ifdef __GNUC__
// Thanks to https://gist.github.com/hi2p-perim/7855506
void __cpuid(int *cpuinfo, int info)
{
__asm__ __volatile__("xchg %%ebx, %%edi;"
"cpuid;"
"xchg %%ebx, %%edi;"
: "=a"(cpuinfo[0]), "=D"(cpuinfo[1]), "=c"(cpuinfo[2]), "=d"(cpuinfo[3])
: "0"(info));
}

unsigned long long _xgetbv(unsigned int index)
{
unsigned int eax, edx;
__asm__ __volatile__("xgetbv;" : "=a"(eax), "=d"(edx) : "c"(index));
return ((unsigned long long)edx << 32) | eax;
}

#endif

std::string cpuBrand()
{
std::string arch = "Unknown CPU";
#if MAC

char buffer[1024];
size_t bufsz = sizeof(buffer);
if (sysctlbyname("machdep.cpu.brand_string", (void *)(&buffer), &bufsz, nullptr, (size_t)0) < 0)
{
#if ARM_NEON
arch = "Apple Silicon";
#endif
}
else
{
arch = buffer;
#if ARM_NEON
arch += " (Apple Silicon)";
#endif
}

#elif WINDOWS
std::string platform = "Windows";

int CPUInfo[4] = {-1};
unsigned nExIds, i = 0;
char CPUBrandString[0x40];
// Get the information associated with each extended ID.
__cpuid(CPUInfo, 0x80000000);
nExIds = CPUInfo[0];
for (i = 0x80000000; i <= nExIds; ++i)
{
__cpuid(CPUInfo, i);
// Interpret CPU brand string
if (i == 0x80000002)
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
else if (i == 0x80000003)
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
else if (i == 0x80000004)
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
}
arch = CPUBrandString;
#elif LINUX
std::string platform = "Linux";

// Lets see what /proc/cpuinfo has to say for us
// on intels this is "model name"
auto pinfo = std::ifstream("/proc/cpuinfo");
if (pinfo.is_open())
{
std::string line;
while (std::getline(pinfo, line))
{
if (line.find("model name") == 0)
{
auto colon = line.find(":");
arch = line.substr(colon + 1);
break;
}
if (line.find("Model") == 0) // rasperry pi branch
{
auto colon = line.find(":");
arch = line.substr(colon + 1);
break;
}
}
}
pinfo.close();
#endif
return arch;
}

bool isArm()
{
#if ARM_NEON
return true;
#else
return false;
#endif
}
bool isX86()
{
#if ARM_NEON
return false;
#else
return true;
#endif
}
bool hasSSE2() { return true; }
bool hasAVX()
{
#if ARM_NEON
return true; // thanks simde
#else
#if MAC
return true;
#endif
#if WINDOWS || LINUX
bool avxSup;
int cpuinfo[4];
__cpuid(cpuinfo, 1);

avxSup = cpuinfo[2] & (1 << 28) || false;
bool osxsaveSup = cpuinfo[2] & (1 << 27) || false;
if (osxsaveSup && avxSup)
{
// _XCR_XFEATURE_ENABLED_MASK = 0
unsigned long long xcrFeatureMask = _xgetbv(0);
avxSup = (xcrFeatureMask & 0x6) == 0x6;
}
return avxSup;
#endif

#endif
}

#if !__AVX__
#error "You must compile SURGE with AVX support in compiler flags"
#endif

FPUStateGuard::FPUStateGuard()
{
#ifndef ARM_NEON
auto _SSE_Flags = 0x8040;
bool fpuExceptions = false;

priorS = _mm_getcsr();
if (fpuExceptions)
{
_mm_setcsr(((priorS & ~_MM_MASK_MASK) | _SSE_Flags) | _MM_EXCEPT_MASK); // all on
}
else
{
_mm_setcsr((priorS | _SSE_Flags) | _MM_MASK_MASK);
}

_MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST);
#endif
}

FPUStateGuard::~FPUStateGuard()
{
#ifndef ARM_NEON
_mm_setcsr(priorS);
#endif
}
} // namespace CPUFeatures
} // namespace Surge
41 changes: 41 additions & 0 deletions src/common/CPUFeatures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
** Surge Synthesizer is Free and Open Source Software
**
** Surge is made available under the Gnu General Public License, v3.0
** https://www.gnu.org/licenses/gpl-3.0.en.html
**
** Copyright 2004-2021 by various individuals as described by the Git transaction log
**
** All source at: https://github.com/surge-synthesizer/surge.git
**
** Surge was a commercial product from 2004-2018, with Copyright and ownership
** in that period held by Claes Johanson at Vember Audio. Claes made Surge
** open source in September 2018.
*/

#ifndef SURGE_XT_CPUFEATURES_H
#define SURGE_XT_CPUFEATURES_H

#include <string>

namespace Surge
{
namespace CPUFeatures
{
std::string cpuBrand();
bool isArm();
bool isX86();
bool hasSSE2();
bool hasAVX();

struct FPUStateGuard
{
FPUStateGuard();
~FPUStateGuard();

int priorS;
};
}; // namespace CPUFeatures
} // namespace Surge

#endif // SURGE_XT_CPUFEATURES_H
11 changes: 11 additions & 0 deletions src/common/SurgeSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "SurgeSynthesizer.h"
#include "DspUtilities.h"
#include <ctime>
#include "CPUFeatures.h"
#if MAC || LINUX
#include <pthread.h>
#else
Expand All @@ -38,6 +39,16 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, std::string suppliedData
: storage(suppliedDataPath), hpA(&storage), hpB(&storage), _parent(parent), halfbandA(6, true),
halfbandB(6, true), halfbandIN(6, true)
{
// Remember CPU features works on ARM also
if (!Surge::CPUFeatures::hasAVX())
{
storage.reportError(
"Surge XT in the future will require processor with AVX extensions. Surge Xt may"
" not work on this hardware in future versions. Enjoy Surge 1.9!",
"CPU Incompatability");
// Try anyway
}

switch_toggled_queued = false;
audio_processing_active = false;
halt_engine = false;
Expand Down
35 changes: 0 additions & 35 deletions src/common/util/FpuState.cpp

This file was deleted.

13 changes: 0 additions & 13 deletions src/common/util/FpuState.h

This file was deleted.

Loading

0 comments on commit b41e914

Please sign in to comment.