1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Windows: Added Windows ARM support to JUCE

This commit is contained in:
hogliux 2022-10-19 13:25:33 +02:00
parent 5f48ca7269
commit 2d42b9a44f
8 changed files with 189 additions and 93 deletions

View file

@ -171,7 +171,7 @@ public:
multiProcessorCompilationValue (config, Ids::multiProcessorCompilation, getUndoManager(), true), multiProcessorCompilationValue (config, Ids::multiProcessorCompilation, getUndoManager(), true),
intermediatesPathValue (config, Ids::intermediatesPath, getUndoManager()), intermediatesPathValue (config, Ids::intermediatesPath, getUndoManager()),
characterSetValue (config, Ids::characterSet, getUndoManager()), characterSetValue (config, Ids::characterSet, getUndoManager()),
architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), get64BitArchName()), architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), getIntel64BitArchName()),
fastMathValue (config, Ids::fastMath, getUndoManager()), fastMathValue (config, Ids::fastMath, getUndoManager()),
debugInformationFormatValue (config, Ids::debugInformationFormat, getUndoManager(), isDebug() ? "ProgramDatabase" : "None"), debugInformationFormatValue (config, Ids::debugInformationFormat, getUndoManager(), isDebug() ? "ProgramDatabase" : "None"),
pluginBinaryCopyStepValue (config, Ids::enablePluginBinaryCopyStep, getUndoManager(), false), pluginBinaryCopyStepValue (config, Ids::enablePluginBinaryCopyStep, getUndoManager(), false),
@ -201,8 +201,10 @@ public:
String getUnityPluginBinaryLocationString() const { return unityPluginBinaryLocation.get(); } String getUnityPluginBinaryLocationString() const { return unityPluginBinaryLocation.get(); }
String getIntermediatesPathString() const { return intermediatesPathValue.get(); } String getIntermediatesPathString() const { return intermediatesPathValue.get(); }
String getCharacterSetString() const { return characterSetValue.get(); } String getCharacterSetString() const { return characterSetValue.get(); }
String get64BitArchName() const { return "x64"; } String getIntel64BitArchName() const { return "x64"; }
String get32BitArchName() const { return "Win32"; } String getIntel32BitArchName() const { return "Win32"; }
String getArm64BitArchName() const { return "ARM64"; }
String getArm32BitArchName() const { return "ARM"; }
String getArchitectureString() const { return architectureTypeValue.get(); } String getArchitectureString() const { return architectureTypeValue.get(); }
String getDebugInformationFormatString() const { return debugInformationFormatValue.get(); } String getDebugInformationFormatString() const { return debugInformationFormatValue.get(); }
@ -211,14 +213,13 @@ public:
bool shouldLinkIncremental() const { return enableIncrementalLinkingValue.get(); } bool shouldLinkIncremental() const { return enableIncrementalLinkingValue.get(); }
bool isUsingRuntimeLibDLL() const { return useRuntimeLibDLLValue.get(); } bool isUsingRuntimeLibDLL() const { return useRuntimeLibDLLValue.get(); }
bool shouldUseMultiProcessorCompilation() const { return multiProcessorCompilationValue.get(); } bool shouldUseMultiProcessorCompilation() const { return multiProcessorCompilationValue.get(); }
bool is64Bit() const { return getArchitectureString() == get64BitArchName(); }
bool isFastMathEnabled() const { return fastMathValue.get(); } bool isFastMathEnabled() const { return fastMathValue.get(); }
bool isPluginBinaryCopyStepEnabled() const { return pluginBinaryCopyStepValue.get(); } bool isPluginBinaryCopyStepEnabled() const { return pluginBinaryCopyStepValue.get(); }
//============================================================================== //==============================================================================
String createMSVCConfigName() const String createMSVCConfigName() const
{ {
return getName() + "|" + (is64Bit() ? "x64" : "Win32"); return getName() + "|" + getArchitectureString();
} }
String getOutputFilename (const String& suffix, String getOutputFilename (const String& suffix,
@ -245,10 +246,9 @@ public:
addVisualStudioPluginInstallPathProperties (props); addVisualStudioPluginInstallPathProperties (props);
props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture", props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture",
{ get32BitArchName(), get64BitArchName() }, { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() },
{ get32BitArchName(), get64BitArchName() }), { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() }),
"Whether to use a 32-bit or 64-bit architecture."); "Which Windows architecture to use.");
props.add (new ChoicePropertyComponentWithEnablement (debugInformationFormatValue, props.add (new ChoicePropertyComponentWithEnablement (debugInformationFormatValue,
isDebug() ? isDebugValue : generateDebugSymbolsValue, isDebug() ? isDebugValue : generateDebugSymbolsValue,
@ -384,13 +384,26 @@ public:
void setPluginBinaryCopyLocationDefaults() void setPluginBinaryCopyLocationDefaults()
{ {
vstBinaryLocation.setDefault ((is64Bit() ? "%ProgramW6432%" : "%programfiles(x86)%") + String ("\\Steinberg\\Vstplugins")); const auto [programsFolderPath, commonsFolderPath] = [&]() -> std::tuple<String, String>
{
static const std::map<String, std::tuple<String, String>> options
{
{ "Win32", { "%programfiles(x86)%", "%CommonProgramFiles(x86)%" } },
{ "x64", { "%ProgramW6432%", "%CommonProgramW6432%" } },
{ "ARM", { "%programfiles(arm)%", "%CommonProgramFiles(arm)%" } },
{ "ARM64", { "%ProgramW6432%", "%CommonProgramW6432%" } }
};
auto prefix = is64Bit() ? "%CommonProgramW6432%" if (const auto iter = options.find (getArchitectureString()); iter != options.cend())
: "%CommonProgramFiles(x86)%"; return iter->second;
vst3BinaryLocation.setDefault (prefix + String ("\\VST3")); jassertfalse;
aaxBinaryLocation.setDefault (prefix + String ("\\Avid\\Audio\\Plug-Ins")); return { "%programfiles%", "%CommonProgramFiles%" };
}();
vstBinaryLocation.setDefault (programsFolderPath + String ("\\Steinberg\\Vstplugins"));
vst3BinaryLocation.setDefault (commonsFolderPath + String ("\\VST3"));
aaxBinaryLocation.setDefault (commonsFolderPath + String ("\\Avid\\Audio\\Plug-Ins"));
lv2BinaryLocation.setDefault ("%APPDATA%\\LV2"); lv2BinaryLocation.setDefault ("%APPDATA%\\LV2");
} }
@ -434,8 +447,7 @@ public:
auto* e = configsGroup->createNewChildElement ("ProjectConfiguration"); auto* e = configsGroup->createNewChildElement ("ProjectConfiguration");
e->setAttribute ("Include", config.createMSVCConfigName()); e->setAttribute ("Include", config.createMSVCConfigName());
e->createNewChildElement ("Configuration")->addTextElement (config.getName()); e->createNewChildElement ("Configuration")->addTextElement (config.getName());
e->createNewChildElement ("Platform")->addTextElement (config.is64Bit() ? config.get64BitArchName() e->createNewChildElement ("Platform")->addTextElement (config.getArchitectureString());
: config.get32BitArchName());
} }
} }
@ -662,7 +674,7 @@ public:
link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename); link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename);
link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows"); link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows");
if (! config.is64Bit()) if (config.getArchitectureString() == "Win32")
link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86"); link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
if (isUsingEditAndContinue) if (isUsingEditAndContinue)
@ -727,7 +739,7 @@ public:
build_tools::RelativePath::buildTargetFolder).toWindowsStyle()); build_tools::RelativePath::buildTargetFolder).toWindowsStyle());
} }
if (getTargetFileType() == staticLibrary && ! config.is64Bit()) if (getTargetFileType() == staticLibrary && config.getArchitectureString() == "Win32")
{ {
auto* lib = group->createNewChildElement ("Lib"); auto* lib = group->createNewChildElement ("Lib");
lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86"); lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
@ -1207,7 +1219,7 @@ public:
auto outputFilename = config.getOutputFilename (".aaxplugin", true, type); auto outputFilename = config.getOutputFilename (".aaxplugin", true, type);
auto bundleDir = getOwner().getOutDirFile (config, outputFilename); auto bundleDir = getOwner().getOutDirFile (config, outputFilename);
auto bundleContents = bundleDir + "\\Contents"; auto bundleContents = bundleDir + "\\Contents";
auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32"); auto archDir = bundleContents + String ("\\") + config.getArchitectureString();
auto executablePath = archDir + String ("\\") + outputFilename; auto executablePath = archDir + String ("\\") + outputFilename;
auto pkgScript = String ("copy /Y ") + getOutputFilePath (config).quoted() + String (" ") + executablePath.quoted() + String ("\r\ncall ") auto pkgScript = String ("copy /Y ") + getOutputFilePath (config).quoted() + String (" ") + executablePath.quoted() + String ("\r\ncall ")
@ -1285,7 +1297,7 @@ public:
auto bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false, type)); auto bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false, type));
auto bundleContents = bundleDir + "\\Contents"; auto bundleContents = bundleDir + "\\Contents";
auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32"); auto archDir = bundleContents + String ("\\") + config.getArchitectureString();
for (auto& folder : StringArray { bundleDir, bundleContents, archDir }) for (auto& folder : StringArray { bundleDir, bundleContents, archDir })
script += String ("if not exist \"") + folder + String ("\" mkdir \"") + folder + String ("\"\r\n"); script += String ("if not exist \"") + folder + String ("\" mkdir \"") + folder + String ("\"\r\n");

View file

@ -1430,34 +1430,44 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons
intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept
{ {
intptr_t fpsr = 0; intptr_t fpsr = 0;
#if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
fpsr = static_cast<intptr_t> (_mm_getcsr()); fpsr = static_cast<intptr_t> (_mm_getcsr());
#elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON
#if defined(__arm64__) || defined(__aarch64__) #if _MSC_VER
// _control87 returns static values for x86 bits that don't exist on arm
// to emulate x86 behaviour. We are only ever interested in de-normal bits
// so mask out only those.
fpsr = (intptr_t) (_control87 (0, 0) & _MCW_DN);
#else
#if JUCE_64BIT
asm volatile("mrs %0, fpcr" asm volatile("mrs %0, fpcr"
: "=r"(fpsr)); : "=r"(fpsr));
#elif JUCE_USE_ARM_NEON #elif JUCE_USE_ARM_NEON
asm volatile("vmrs %0, fpscr" asm volatile("vmrs %0, fpscr"
: "=r"(fpsr)); : "=r"(fpsr));
#endif #endif
#else
#if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
jassertfalse; // No support for getting the floating point status register for your platform
#endif
#endif #endif
#else
#if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))
jassertfalse; // No support for getting the floating point status register for your platform
#endif
#endif
return fpsr; return fpsr;
} }
void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept
{ {
#if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
// the volatile keyword here is needed to workaround a bug in AppleClang 13.0 // the volatile keyword here is needed to workaround a bug in AppleClang 13.0
// which aggressively optimises away the variable otherwise // which aggressively optimises away the variable otherwise
volatile auto fpsr_w = static_cast<uint32_t> (fpsr); volatile auto fpsr_w = static_cast<uint32_t> (fpsr);
_mm_setcsr (fpsr_w); _mm_setcsr (fpsr_w);
#elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON
#if defined(__arm64__) || defined(__aarch64__) #if _MSC_VER
_control87 ((unsigned int) fpsr, _MCW_DN);
#else
#if JUCE_64BIT
asm volatile("msr fpcr, %0" asm volatile("msr fpcr, %0"
: :
: "ri"(fpsr)); : "ri"(fpsr));
@ -1466,17 +1476,18 @@ void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) no
: :
: "ri"(fpsr)); : "ri"(fpsr));
#endif #endif
#else
#if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
jassertfalse; // No support for getting the floating point status register for your platform
#endif
ignoreUnused (fpsr);
#endif #endif
#else
#if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))
jassertfalse; // No support for getting the floating point status register for your platform
#endif
ignoreUnused (fpsr);
#endif
} }
void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
intptr_t mask = _MM_FLUSH_ZERO_MASK; intptr_t mask = _MM_FLUSH_ZERO_MASK;
#else /*JUCE_USE_ARM_NEON*/ #else /*JUCE_USE_ARM_NEON*/
@ -1484,7 +1495,7 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
#endif #endif
setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0)); setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0));
#else #else
#if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))
jassertfalse; // No support for flush to zero mode on your platform jassertfalse; // No support for flush to zero mode on your platform
#endif #endif
ignoreUnused (shouldEnable); ignoreUnused (shouldEnable);
@ -1493,7 +1504,7 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
intptr_t mask = 0x8040; intptr_t mask = 0x8040;
#else /*JUCE_USE_ARM_NEON*/ #else /*JUCE_USE_ARM_NEON*/
@ -1504,7 +1515,7 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool
#else #else
ignoreUnused (shouldDisable); ignoreUnused (shouldDisable);
#if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))
jassertfalse; // No support for disable denormals mode on your platform jassertfalse; // No support for disable denormals mode on your platform
#endif #endif
#endif #endif
@ -1512,7 +1523,7 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool
bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
intptr_t mask = 0x8040; intptr_t mask = 0x8040;
#else /*JUCE_USE_ARM_NEON*/ #else /*JUCE_USE_ARM_NEON*/
@ -1527,7 +1538,7 @@ bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept
ScopedNoDenormals::ScopedNoDenormals() noexcept ScopedNoDenormals::ScopedNoDenormals() noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
intptr_t mask = 0x8040; intptr_t mask = 0x8040;
#else /*JUCE_USE_ARM_NEON*/ #else /*JUCE_USE_ARM_NEON*/
@ -1541,7 +1552,7 @@ ScopedNoDenormals::ScopedNoDenormals() noexcept
ScopedNoDenormals::~ScopedNoDenormals() noexcept ScopedNoDenormals::~ScopedNoDenormals() noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
FloatVectorOperations::setFpStatusRegister (fpsr); FloatVectorOperations::setFpStatusRegister (fpsr);
#endif #endif
} }

View file

@ -261,7 +261,7 @@ public:
~ScopedNoDenormals() noexcept; ~ScopedNoDenormals() noexcept;
private: private:
#if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined (__arm64__) || defined (__aarch64__)) #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))
intptr_t fpsr; intptr_t fpsr;
#endif #endif
}; };

View file

@ -119,7 +119,7 @@ static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise,
/* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the
* 64 bit compiler and doesn't work on arm. */ * 64 bit compiler and doesn't work on arm. */
#if defined(_MSC_VER) && defined(_M_IX86) && !defined(_WIN32_WCE) #if (defined(_MSC_VER) && defined(_M_IX86) && !defined(_WIN32_WCE)) && (! JUCE_ARM)
# define VORBIS_FPU_CONTROL # define VORBIS_FPU_CONTROL
typedef ogg_int16_t vorbis_fpu_control; typedef ogg_int16_t vorbis_fpu_control;
@ -146,7 +146,7 @@ static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
/* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be /* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be
done safely because all x86_64 CPUs supports SSE2. */ done safely because all x86_64 CPUs supports SSE2. */
#if ((JUCE_MSVC && JUCE_64BIT) || (JUCE_GCC && defined (__x86_64__))) #if (((JUCE_MSVC && JUCE_64BIT) || (JUCE_GCC && defined (__x86_64__)))) && (! JUCE_ARM)
# define VORBIS_FPU_CONTROL # define VORBIS_FPU_CONTROL
typedef ogg_int16_t vorbis_fpu_control; typedef ogg_int16_t vorbis_fpu_control;

View file

@ -23,11 +23,6 @@
namespace juce namespace juce
{ {
#if JUCE_MSVC && ! defined (__INTEL_COMPILER)
#pragma intrinsic (__cpuid)
#pragma intrinsic (__rdtsc)
#endif
void Logger::outputDebugString (const String& text) void Logger::outputDebugString (const String& text)
{ {
OutputDebugString ((text + "\n").toWideCharPointer()); OutputDebugString ((text + "\n").toWideCharPointer());
@ -39,9 +34,50 @@ void Logger::outputDebugString (const String& text)
JUCE_API void juceDLL_free (void* block) { std::free (block); } JUCE_API void juceDLL_free (void* block) { std::free (block); }
#endif #endif
//============================================================================== static int findNumberOfPhysicalCores() noexcept
{
#if JUCE_MINGW
// Not implemented in MinGW
jassertfalse;
#if JUCE_MINGW || JUCE_CLANG return 1;
#else
DWORD bufferSize = 0;
GetLogicalProcessorInformation (nullptr, &bufferSize);
const auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
if (numBuffers == 0)
{
jassertfalse;
return 0;
};
HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);
if (! GetLogicalProcessorInformation (buffer, &bufferSize))
{
jassertfalse;
return 0;
}
return (int) std::count_if (buffer.get(), buffer.get() + numBuffers, [] (const auto& info)
{
return info.Relationship == RelationProcessorCore;
});
#endif // JUCE_MINGW
}
//==============================================================================
#if JUCE_INTEL
#if JUCE_MSVC && ! defined (__INTEL_COMPILER)
#pragma intrinsic (__cpuid)
#pragma intrinsic (__rdtsc)
#endif
#if JUCE_MINGW || JUCE_CLANG
static void callCPUID (int result[4], uint32 type) static void callCPUID (int result[4], uint32 type)
{ {
uint32 la = (uint32) result[0], lb = (uint32) result[1], uint32 la = (uint32) result[0], lb = (uint32) result[1],
@ -59,12 +95,12 @@ static void callCPUID (int result[4], uint32 type)
result[0] = (int) la; result[1] = (int) lb; result[0] = (int) la; result[1] = (int) lb;
result[2] = (int) lc; result[3] = (int) ld; result[2] = (int) lc; result[3] = (int) ld;
} }
#else #else
static void callCPUID (int result[4], int infoType) static void callCPUID (int result[4], int infoType)
{ {
__cpuid (result, infoType); __cpuid (result, infoType);
} }
#endif #endif
String SystemStats::getCpuVendor() String SystemStats::getCpuVendor()
{ {
@ -103,34 +139,6 @@ String SystemStats::getCpuModel()
return String (name).trim(); return String (name).trim();
} }
static int findNumberOfPhysicalCores() noexcept
{
#if JUCE_MINGW
// Not implemented in MinGW
jassertfalse;
return 1;
#else
int numPhysicalCores = 0;
DWORD bufferSize = 0;
GetLogicalProcessorInformation (nullptr, &bufferSize);
if (auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)))
{
HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);
if (GetLogicalProcessorInformation (buffer, &bufferSize))
for (size_t i = 0; i < numBuffers; ++i)
if (buffer[i].Relationship == RelationProcessorCore)
++numPhysicalCores;
}
return numPhysicalCores;
#endif // JUCE_MINGW
}
//==============================================================================
void CPUInformation::initialise() noexcept void CPUInformation::initialise() noexcept
{ {
int info[4] = { 0 }; int info[4] = { 0 };
@ -176,6 +184,49 @@ void CPUInformation::initialise() noexcept
if (numPhysicalCPUs <= 0) if (numPhysicalCPUs <= 0)
numPhysicalCPUs = numLogicalCPUs; numPhysicalCPUs = numLogicalCPUs;
} }
#elif JUCE_ARM
String SystemStats::getCpuVendor()
{
static const auto cpuVendor = []
{
static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\VendorIdentifier";
auto vendor = RegistryKeyWrapper::getValue (path, {}, 0).trim();
return vendor.isEmpty() ? String ("Unknown Vendor") : vendor;
}();
return cpuVendor;
}
String SystemStats::getCpuModel()
{
static const auto cpuModel = []
{
static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\ProcessorNameString";
auto model = RegistryKeyWrapper::getValue (path, {}, 0).trim();
return model.isEmpty() ? String ("Unknown Model") : model;
}();
return cpuModel;
}
void CPUInformation::initialise() noexcept
{
// Windows for arm requires at least armv7 which has neon support
hasNeon = true;
SYSTEM_INFO systemInfo;
GetNativeSystemInfo (&systemInfo);
numLogicalCPUs = (int) systemInfo.dwNumberOfProcessors;
numPhysicalCPUs = findNumberOfPhysicalCores();
if (numPhysicalCPUs <= 0)
numPhysicalCPUs = numLogicalCPUs;
}
#else
#error Unknown CPU architecture type
#endif
#if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
struct DebugFlagsInitialiser struct DebugFlagsInitialiser
@ -442,11 +493,21 @@ double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHa
//============================================================================== //==============================================================================
static int64 juce_getClockCycleCounter() noexcept static int64 juce_getClockCycleCounter() noexcept
{ {
#if JUCE_MSVC #if JUCE_MSVC
#if JUCE_INTEL
// MS intrinsics version... // MS intrinsics version...
return (int64) __rdtsc(); return (int64) __rdtsc();
#elif JUCE_ARM
#elif JUCE_GCC || JUCE_CLANG #if defined (_M_ARM)
return __rdpmccntr64();
#elif defined (_M_ARM64)
return _ReadStatusReg (ARM64_PMCCNTR_EL0);
#else
#error Unknown arm architecture
#endif
#endif
#elif JUCE_GCC || JUCE_CLANG
#if JUCE_INTEL
// GNU inline asm version... // GNU inline asm version...
unsigned int hi = 0, lo = 0; unsigned int hi = 0, lo = 0;
@ -462,9 +523,15 @@ static int64 juce_getClockCycleCounter() noexcept
: "cc", "eax", "ebx", "ecx", "edx", "memory"); : "cc", "eax", "ebx", "ecx", "edx", "memory");
return (int64) ((((uint64) hi) << 32) | lo); return (int64) ((((uint64) hi) << 32) | lo);
#else #elif JUCE_ARM
#error "unknown compiler?" int64 retval;
#endif
__asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r"(retval));
return retval;
#endif
#else
#error "unknown compiler?"
#endif
} }
int SystemStats::getCpuSpeedInMegahertz() int SystemStats::getCpuSpeedInMegahertz()

View file

@ -109,7 +109,11 @@
/** If defined, this indicates that the processor is little-endian. */ /** If defined, this indicates that the processor is little-endian. */
#define JUCE_LITTLE_ENDIAN 1 #define JUCE_LITTLE_ENDIAN 1
#define JUCE_INTEL 1 #if defined (_M_ARM) || defined (_M_ARM64) || defined (__arm__) || defined (__aarch64__)
#define JUCE_ARM 1
#else
#define JUCE_INTEL 1
#endif
#endif #endif
//============================================================================== //==============================================================================

View file

@ -79,13 +79,13 @@
#include "widgets/juce_Chorus.cpp" #include "widgets/juce_Chorus.cpp"
#if JUCE_USE_SIMD #if JUCE_USE_SIMD
#if defined(__i386__) || defined(__amd64__) || defined(_M_X64) || defined(_X86_) || defined(_M_IX86) #if JUCE_INTEL
#ifdef __AVX2__ #ifdef __AVX2__
#include "native/juce_avx_SIMDNativeOps.cpp" #include "native/juce_avx_SIMDNativeOps.cpp"
#else #else
#include "native/juce_sse_SIMDNativeOps.cpp" #include "native/juce_sse_SIMDNativeOps.cpp"
#endif #endif
#elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__) #elif JUCE_ARM
#include "native/juce_neon_SIMDNativeOps.cpp" #include "native/juce_neon_SIMDNativeOps.cpp"
#else #else
#error "SIMD register support not implemented for this platform" #error "SIMD register support not implemented for this platform"

View file

@ -74,7 +74,9 @@
#include <immintrin.h> #include <immintrin.h>
#endif #endif
#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) // it's ok to check for _M_ARM below as this is only defined on Windows for Arm 32-bit
// which has a minimum requirement of armv7, which supports neon.
#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) || defined (_M_ARM) || defined (_M_ARM64)
#ifndef JUCE_USE_SIMD #ifndef JUCE_USE_SIMD
#define JUCE_USE_SIMD 1 #define JUCE_USE_SIMD 1
@ -227,7 +229,7 @@ namespace juce
#else #else
#include "native/juce_sse_SIMDNativeOps.h" #include "native/juce_sse_SIMDNativeOps.h"
#endif #endif
#elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__) #elif JUCE_ARM
#include "native/juce_neon_SIMDNativeOps.h" #include "native/juce_neon_SIMDNativeOps.h"
#else #else
#error "SIMD register support not implemented for this platform" #error "SIMD register support not implemented for this platform"