VMManager: MacOS CPU count detection

This commit is contained in:
TellowKrinkle 2022-12-04 19:48:07 -06:00 committed by refractionpcsx2
parent f3adb05b1c
commit a2c6e050d7
4 changed files with 138 additions and 0 deletions

View File

@ -127,6 +127,7 @@ target_sources(common PRIVATE
emitter/tools.h
emitter/x86emitter.h
emitter/x86types.h
Darwin/DarwinMisc.h
)
if(USE_VTUNE)

View File

@ -15,8 +15,11 @@
#if defined(__APPLE__)
#include "common/Darwin/DarwinMisc.h"
#include <cstring>
#include <cstdlib>
#include <optional>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <time.h>
@ -24,6 +27,7 @@
#include <IOKit/pwr_mgt/IOPMLib.h>
#include "common/Pcsx2Types.h"
#include "common/Console.h"
#include "common/General.h"
#include "common/Threading.h"
#include "common/WindowInfo.h"
@ -89,6 +93,20 @@ static std::string sysctl_str(int category, int name)
return std::string(buf, len > 0 ? len - 1 : 0);
}
static std::optional<u32> sysctlbyname_u32(const char* name)
{
u32 output;
size_t output_size = sizeof(output);
if (0 != sysctlbyname(name, &output, &output_size, nullptr, 0))
return std::nullopt;
if (output_size != sizeof(output))
{
DevCon.WriteLn("(DarwinMisc) sysctl %s gave unexpected size %zd", name, output_size);
return std::nullopt;
}
return output;
}
std::string GetOSVersionString()
{
std::string type = sysctl_str(CTL_KERN, KERN_OSTYPE);
@ -135,4 +153,46 @@ void Threading::SleepUntil(u64 ticks)
nanosleep(&ts, nullptr);
}
std::vector<DarwinMisc::CPUClass> DarwinMisc::GetCPUClasses()
{
std::vector<CPUClass> out;
if (std::optional<u32> nperflevels = sysctlbyname_u32("hw.nperflevels"))
{
char name[64];
for (u32 i = 0; i < *nperflevels; i++)
{
snprintf(name, sizeof(name), "hw.perflevel%u.physicalcpu", i);
std::optional<u32> physicalcpu = sysctlbyname_u32(name);
snprintf(name, sizeof(name), "hw.perflevel%u.logicalcpu", i);
std::optional<u32> logicalcpu = sysctlbyname_u32(name);
char levelname[64];
size_t levelname_size = sizeof(levelname);
snprintf(name, sizeof(name), "hw.perflevel%u.name", i);
if (0 != sysctlbyname(name, levelname, &levelname_size, nullptr, 0))
strcpy(levelname, "???");
if (!physicalcpu.has_value() || !logicalcpu.has_value())
{
Console.Warning("(DarwinMisc) Perf level %u is missing data on %s cpus!",
i, !physicalcpu.has_value() ? "physical" : "logical");
continue;
}
out.push_back({levelname, *physicalcpu, *logicalcpu});
}
}
else if (std::optional<u32> physcpu = sysctlbyname_u32("hw.physicalcpu"))
{
out.push_back({"Default", *physcpu, sysctlbyname_u32("hw.logicalcpu").value_or(0)});
}
else
{
Console.Warning("(DarwinMisc) Couldn't get cpu core count!");
}
return out;
}
#endif

View File

@ -0,0 +1,36 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef __APPLE__
#include <string>
#include <vector>
#include "common/Pcsx2Types.h"
namespace DarwinMisc {
struct CPUClass {
std::string name;
u32 num_physical;
u32 num_logical;
};
std::vector<CPUClass> GetCPUClasses();
}
#endif

View File

@ -77,6 +77,10 @@
#include <timeapi.h>
#endif
#ifdef __APPLE__
#include "common/Darwin/DarwinMisc.h"
#endif
#ifdef ENABLE_DISCORD_PRESENCE
#include "discord_rpc.h"
#endif
@ -2379,6 +2383,43 @@ static void SetMTVUAndAffinityControlDefault(SettingsInterface& si)
si.SetIntValue("EmuCore/GS", "extrathreads", extra_threads);
}
#elif defined(__APPLE__)
static u32 s_big_cores;
static u32 s_small_cores;
static void InitializeCPUInfo()
{
s_big_cores = 0;
s_small_cores = 0;
std::vector<DarwinMisc::CPUClass> classes = DarwinMisc::GetCPUClasses();
for (size_t i = 0; i < classes.size(); i++) {
const DarwinMisc::CPUClass& cls = classes[i];
const bool is_big = i == 0 || i < classes.size() - 1; // Assume only one group is small
DevCon.WriteLn("(VMManager) Found %u physical cores and %u logical cores in perf level %u (%s), assuming %s",
cls.num_physical, cls.num_logical, i, cls.name.c_str(), is_big ? "big" : "small");
(is_big ? s_big_cores : s_small_cores) += cls.num_physical;
}
}
static void SetMTVUAndAffinityControlDefault(SettingsInterface& si)
{
VMManager::EnsureCPUInfoInitialized();
Console.WriteLn("Detected %u big cores", s_big_cores);
if (s_big_cores >= 3)
{
Console.WriteLn(" So enabling MTVU.");
si.SetBoolValue("EmuCore/Speedhacks", "vuThread", true);
}
else
{
Console.WriteLn(" So disabling MTVU.");
si.SetBoolValue("EmuCore/Speedhacks", "vuThread", false);
}
}
#else
static void InitializeCPUInfo()