mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-14 17:16:58 +02:00
[qt] printout extra AVX512 CPU caps, printout all relevant extensions
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
91058d7383
commit
241c1423f7
3 changed files with 70 additions and 103 deletions
|
|
@ -65,17 +65,6 @@ static inline u64 xgetbv(u32 index) {
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
|
|
||||||
if (brand_string == "GenuineIntel") {
|
|
||||||
return Manufacturer::Intel;
|
|
||||||
} else if (brand_string == "AuthenticAMD") {
|
|
||||||
return Manufacturer::AMD;
|
|
||||||
} else if (brand_string == "HygonGenuine") {
|
|
||||||
return Manufacturer::Hygon;
|
|
||||||
}
|
|
||||||
return Manufacturer::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detects the various CPU features
|
// Detects the various CPU features
|
||||||
static CPUCaps Detect() {
|
static CPUCaps Detect() {
|
||||||
CPUCaps caps = {};
|
CPUCaps caps = {};
|
||||||
|
|
@ -94,8 +83,6 @@ static CPUCaps Detect() {
|
||||||
std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32));
|
std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32));
|
||||||
std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32));
|
std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32));
|
||||||
|
|
||||||
caps.manufacturer = CPUCaps::ParseManufacturer(caps.brand_string);
|
|
||||||
|
|
||||||
// Set reasonable default cpu string even if brand string not available
|
// Set reasonable default cpu string even if brand string not available
|
||||||
std::strncpy(caps.cpu_string, caps.brand_string, std::size(caps.brand_string));
|
std::strncpy(caps.cpu_string, caps.brand_string, std::size(caps.brand_string));
|
||||||
|
|
||||||
|
|
@ -134,14 +121,21 @@ static CPUCaps Detect() {
|
||||||
__cpuidex(cpu_id, 0x00000007, 0x00000000);
|
__cpuidex(cpu_id, 0x00000007, 0x00000000);
|
||||||
// Can't enable AVX{2,512} unless the XSAVE/XGETBV checks above passed
|
// Can't enable AVX{2,512} unless the XSAVE/XGETBV checks above passed
|
||||||
if (caps.avx) {
|
if (caps.avx) {
|
||||||
|
// ebx
|
||||||
caps.avx2 = Common::Bit<5>(cpu_id[1]);
|
caps.avx2 = Common::Bit<5>(cpu_id[1]);
|
||||||
caps.avx512f = Common::Bit<16>(cpu_id[1]);
|
caps.avx512f = Common::Bit<16>(cpu_id[1]);
|
||||||
caps.avx512dq = Common::Bit<17>(cpu_id[1]);
|
caps.avx512dq = Common::Bit<17>(cpu_id[1]);
|
||||||
caps.avx512cd = Common::Bit<28>(cpu_id[1]);
|
caps.avx512cd = Common::Bit<28>(cpu_id[1]);
|
||||||
caps.avx512bw = Common::Bit<30>(cpu_id[1]);
|
caps.avx512bw = Common::Bit<30>(cpu_id[1]);
|
||||||
caps.avx512vl = Common::Bit<31>(cpu_id[1]);
|
caps.avx512vl = Common::Bit<31>(cpu_id[1]);
|
||||||
|
// ecx
|
||||||
caps.avx512vbmi = Common::Bit<1>(cpu_id[2]);
|
caps.avx512vbmi = Common::Bit<1>(cpu_id[2]);
|
||||||
|
caps.avx512vbmi2 = Common::Bit<6>(cpu_id[2]);
|
||||||
|
caps.avx512vnni = Common::Bit<11>(cpu_id[2]);
|
||||||
caps.avx512bitalg = Common::Bit<12>(cpu_id[2]);
|
caps.avx512bitalg = Common::Bit<12>(cpu_id[2]);
|
||||||
|
caps.avx512popcntq = Common::Bit<14>(cpu_id[2]);
|
||||||
|
// edx
|
||||||
|
caps.avx512bf16 = Common::Bit<7>(cpu_id[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
caps.bmi1 = Common::Bit<3>(cpu_id[1]);
|
caps.bmi1 = Common::Bit<3>(cpu_id[1]);
|
||||||
|
|
@ -221,17 +215,15 @@ std::optional<int> GetProcessorCount() {
|
||||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
|
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||||
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
|
||||||
// Now query the core count.
|
// Now query the core count.
|
||||||
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
|
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
|
||||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return static_cast<int>(
|
return int(std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
||||||
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
return proc_info.Relationship == RelationProcessorCore;
|
||||||
return proc_info.Relationship == RelationProcessorCore;
|
}));
|
||||||
}));
|
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
const int thread_count = std::thread::hardware_concurrency();
|
const int thread_count = std::thread::hardware_concurrency();
|
||||||
std::ifstream smt("/sys/devices/system/cpu/smt/active");
|
std::ifstream smt("/sys/devices/system/cpu/smt/active");
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,6 @@ namespace Common {
|
||||||
|
|
||||||
/// x86/x64 CPU capabilities that may be detected by this module
|
/// x86/x64 CPU capabilities that may be detected by this module
|
||||||
struct CPUCaps {
|
struct CPUCaps {
|
||||||
|
|
||||||
enum class Manufacturer : u8 {
|
|
||||||
Unknown = 0,
|
|
||||||
Intel = 1,
|
|
||||||
AMD = 2,
|
|
||||||
Hygon = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
static Manufacturer ParseManufacturer(std::string_view brand_string);
|
|
||||||
|
|
||||||
Manufacturer manufacturer;
|
|
||||||
char brand_string[13];
|
char brand_string[13];
|
||||||
|
|
||||||
char cpu_string[48];
|
char cpu_string[48];
|
||||||
|
|
@ -36,45 +25,49 @@ struct CPUCaps {
|
||||||
u32 crystal_frequency;
|
u32 crystal_frequency;
|
||||||
u64 tsc_frequency; // Derived from the above three values
|
u64 tsc_frequency; // Derived from the above three values
|
||||||
|
|
||||||
bool sse : 1;
|
#define CPU_CAPS_LIST \
|
||||||
bool sse2 : 1;
|
CPU_CAPS_ELEM(sse) \
|
||||||
bool sse3 : 1;
|
CPU_CAPS_ELEM(sse2) \
|
||||||
bool ssse3 : 1;
|
CPU_CAPS_ELEM(sse3) \
|
||||||
bool sse4_1 : 1;
|
CPU_CAPS_ELEM(ssse3) \
|
||||||
bool sse4_2 : 1;
|
CPU_CAPS_ELEM(sse4_1) \
|
||||||
|
CPU_CAPS_ELEM(sse4_2) \
|
||||||
bool avx : 1;
|
CPU_CAPS_ELEM(avx) \
|
||||||
bool avx_vnni : 1;
|
CPU_CAPS_ELEM(avx_vnni) \
|
||||||
bool avx2 : 1;
|
CPU_CAPS_ELEM(avx2) \
|
||||||
bool avx512f : 1;
|
CPU_CAPS_ELEM(avx512f) \
|
||||||
bool avx512dq : 1;
|
CPU_CAPS_ELEM(avx512dq) \
|
||||||
bool avx512cd : 1;
|
CPU_CAPS_ELEM(avx512cd) \
|
||||||
bool avx512bw : 1;
|
CPU_CAPS_ELEM(avx512bw) \
|
||||||
bool avx512vl : 1;
|
CPU_CAPS_ELEM(avx512vl) \
|
||||||
bool avx512vbmi : 1;
|
CPU_CAPS_ELEM(avx512vbmi) \
|
||||||
bool avx512bitalg : 1;
|
CPU_CAPS_ELEM(avx512vbmi2) \
|
||||||
|
CPU_CAPS_ELEM(avx512vnni) \
|
||||||
bool aes : 1;
|
CPU_CAPS_ELEM(avx512bitalg) \
|
||||||
bool bmi1 : 1;
|
CPU_CAPS_ELEM(avx512popcntq) \
|
||||||
bool bmi2 : 1;
|
CPU_CAPS_ELEM(avx512bf16) \
|
||||||
bool f16c : 1;
|
CPU_CAPS_ELEM(aes) \
|
||||||
bool fma : 1;
|
CPU_CAPS_ELEM(bmi1) \
|
||||||
bool fma4 : 1;
|
CPU_CAPS_ELEM(bmi2) \
|
||||||
bool gfni : 1;
|
CPU_CAPS_ELEM(f16c) \
|
||||||
bool invariant_tsc : 1;
|
CPU_CAPS_ELEM(fma) \
|
||||||
bool lzcnt : 1;
|
CPU_CAPS_ELEM(fma4) \
|
||||||
bool monitorx : 1;
|
CPU_CAPS_ELEM(gfni) \
|
||||||
bool movbe : 1;
|
CPU_CAPS_ELEM(invariant_tsc) \
|
||||||
bool pclmulqdq : 1;
|
CPU_CAPS_ELEM(lzcnt) \
|
||||||
bool popcnt : 1;
|
CPU_CAPS_ELEM(monitorx) \
|
||||||
bool sha : 1;
|
CPU_CAPS_ELEM(movbe) \
|
||||||
bool waitpkg : 1;
|
CPU_CAPS_ELEM(pclmulqdq) \
|
||||||
|
CPU_CAPS_ELEM(popcnt) \
|
||||||
|
CPU_CAPS_ELEM(sha) \
|
||||||
|
CPU_CAPS_ELEM(waitpkg)
|
||||||
|
#define CPU_CAPS_ELEM(n) bool n : 1;
|
||||||
|
CPU_CAPS_LIST
|
||||||
|
#undef CPU_CAPS_ELEM
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/// Gets the supported capabilities of the host CPU
|
||||||
* Gets the supported capabilities of the host CPU
|
/// @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
||||||
* @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
|
||||||
*/
|
|
||||||
const CPUCaps& GetCPUCaps();
|
const CPUCaps& GetCPUCaps();
|
||||||
|
|
||||||
/// Detects CPU core count
|
/// Detects CPU core count
|
||||||
|
|
|
||||||
|
|
@ -488,49 +488,31 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||||
QtCommon::system->HIDCore().ReloadInputDevices();
|
QtCommon::system->HIDCore().ReloadInputDevices();
|
||||||
controller_dialog->refreshConfiguration();
|
controller_dialog->refreshConfiguration();
|
||||||
|
|
||||||
const auto branch_name = std::string(Common::g_scm_branch);
|
const auto yuzu_build = fmt::format("Eden | {}-{}", Common::g_scm_branch, Common::g_scm_desc);
|
||||||
const auto description = std::string(Common::g_scm_desc);
|
const auto override_build = fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), Common::g_build_id);
|
||||||
const auto build_id = std::string(Common::g_build_id);
|
|
||||||
|
|
||||||
const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description);
|
|
||||||
const auto override_build =
|
|
||||||
fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id);
|
|
||||||
const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build;
|
const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build;
|
||||||
const auto processor_count = std::thread::hardware_concurrency();
|
const auto processor_count = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version);
|
LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version);
|
||||||
LogRuntimes();
|
LogRuntimes();
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
const auto& caps = Common::GetCPUCaps();
|
auto const& caps = Common::GetCPUCaps();
|
||||||
std::string cpu_string = caps.cpu_string;
|
std::string ext_string{};
|
||||||
if (caps.avx || caps.avx2 || caps.avx512f) {
|
#define CPU_CAPS_ELEM(n) if (caps.n) ext_string += " | " #n;
|
||||||
cpu_string += " | AVX";
|
CPU_CAPS_LIST
|
||||||
if (caps.avx512f) {
|
#undef CPU_CAPS_ELEM
|
||||||
cpu_string += "512";
|
if (auto const processor_core = Common::GetProcessorCount()) {
|
||||||
} else if (caps.avx2) {
|
LOG_INFO(Frontend, "Host CPU: {} ({} cores, {} threads) {}", caps.cpu_string, *processor_core, processor_count, ext_string);
|
||||||
cpu_string += '2';
|
} else {
|
||||||
}
|
LOG_INFO(Frontend, "Host CPU: {} ({} threads) {}", caps.cpu_string, processor_count, ext_string);
|
||||||
if (caps.fma || caps.fma4) {
|
|
||||||
cpu_string += " | FMA";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_INFO(Frontend, "Host CPU: {}", cpu_string);
|
|
||||||
if (std::optional<int> processor_core = Common::GetProcessorCount()) {
|
|
||||||
LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count);
|
|
||||||
LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString());
|
LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString());
|
||||||
LOG_INFO(Frontend, "Host RAM: {:.2f} GiB",
|
LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
||||||
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
|
||||||
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
|
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms",
|
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count());
|
||||||
std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
|
QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
|
||||||
Common::Windows::SetCurrentTimerResolutionToMaximum())
|
|
||||||
.count());
|
|
||||||
QtCommon::system->CoreTiming().SetTimerResolutionNs(
|
|
||||||
Common::Windows::GetCurrentTimerResolution());
|
|
||||||
#endif
|
#endif
|
||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
|
|
||||||
|
|
@ -538,10 +520,10 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||||
|
|
||||||
#ifdef ENABLE_UPDATE_CHECKER
|
#ifdef ENABLE_UPDATE_CHECKER
|
||||||
if (UISettings::values.check_for_updates) {
|
if (UISettings::values.check_for_updates) {
|
||||||
update_future = QtConcurrent::run(
|
update_future = QtConcurrent::run([] -> std::optional<UpdateChecker::Update> {
|
||||||
[]() -> std::optional<UpdateChecker::Update> { return UpdateChecker::GetUpdate(); });
|
return UpdateChecker::GetUpdate();
|
||||||
update_watcher.connect(&update_watcher, &QFutureWatcher<QString>::finished, this,
|
});
|
||||||
&MainWindow::OnEmulatorUpdateAvailable);
|
update_watcher.connect(&update_watcher, &QFutureWatcher<QString>::finished, this, &MainWindow::OnEmulatorUpdateAvailable);
|
||||||
update_watcher.setFuture(update_future);
|
update_watcher.setFuture(update_future);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue