From 241c1423f76c0ed00a05888bedbe0688b0f665a7 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 26 Apr 2026 08:48:53 +0000 Subject: [PATCH] [qt] printout extra AVX512 CPU caps, printout all relevant extensions Signed-off-by: lizzie --- src/common/x64/cpu_detect.cpp | 30 +++++------- src/common/x64/cpu_detect.h | 89 ++++++++++++++++------------------- src/yuzu/main_window.cpp | 54 +++++++-------------- 3 files changed, 70 insertions(+), 103 deletions(-) diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp index 4cc42ccbd5..1ab62f2c98 100644 --- a/src/common/x64/cpu_detect.cpp +++ b/src/common/x64/cpu_detect.cpp @@ -65,17 +65,6 @@ static inline u64 xgetbv(u32 index) { 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 static CPUCaps Detect() { 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[8], &cpu_id[2], sizeof(u32)); - caps.manufacturer = CPUCaps::ParseManufacturer(caps.brand_string); - // Set reasonable default cpu string even if brand string not available 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); // Can't enable AVX{2,512} unless the XSAVE/XGETBV checks above passed if (caps.avx) { + // ebx caps.avx2 = Common::Bit<5>(cpu_id[1]); caps.avx512f = Common::Bit<16>(cpu_id[1]); caps.avx512dq = Common::Bit<17>(cpu_id[1]); caps.avx512cd = Common::Bit<28>(cpu_id[1]); caps.avx512bw = Common::Bit<30>(cpu_id[1]); caps.avx512vl = Common::Bit<31>(cpu_id[1]); + // ecx 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.avx512popcntq = Common::Bit<14>(cpu_id[2]); + // edx + caps.avx512bf16 = Common::Bit<7>(cpu_id[3]); } caps.bmi1 = Common::Bit<3>(cpu_id[1]); @@ -221,17 +215,15 @@ std::optional GetProcessorCount() { LOG_ERROR(Frontend, "Failed to query core count."); return std::nullopt; } - std::vector buffer( - length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + std::vector buffer(length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); // Now query the core count. if (!GetLogicalProcessorInformation(buffer.data(), &length)) { LOG_ERROR(Frontend, "Failed to query core count."); return std::nullopt; } - return static_cast( - std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) { - return proc_info.Relationship == RelationProcessorCore; - })); + return int(std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) { + return proc_info.Relationship == RelationProcessorCore; + })); #elif defined(__unix__) const int thread_count = std::thread::hardware_concurrency(); std::ifstream smt("/sys/devices/system/cpu/smt/active"); diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h index 756459417f..f0c6c5a9cd 100644 --- a/src/common/x64/cpu_detect.h +++ b/src/common/x64/cpu_detect.h @@ -12,17 +12,6 @@ namespace Common { /// x86/x64 CPU capabilities that may be detected by this module 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 cpu_string[48]; @@ -36,45 +25,49 @@ struct CPUCaps { u32 crystal_frequency; u64 tsc_frequency; // Derived from the above three values - bool sse : 1; - bool sse2 : 1; - bool sse3 : 1; - bool ssse3 : 1; - bool sse4_1 : 1; - bool sse4_2 : 1; - - bool avx : 1; - bool avx_vnni : 1; - bool avx2 : 1; - bool avx512f : 1; - bool avx512dq : 1; - bool avx512cd : 1; - bool avx512bw : 1; - bool avx512vl : 1; - bool avx512vbmi : 1; - bool avx512bitalg : 1; - - bool aes : 1; - bool bmi1 : 1; - bool bmi2 : 1; - bool f16c : 1; - bool fma : 1; - bool fma4 : 1; - bool gfni : 1; - bool invariant_tsc : 1; - bool lzcnt : 1; - bool monitorx : 1; - bool movbe : 1; - bool pclmulqdq : 1; - bool popcnt : 1; - bool sha : 1; - bool waitpkg : 1; +#define CPU_CAPS_LIST \ + CPU_CAPS_ELEM(sse) \ + CPU_CAPS_ELEM(sse2) \ + CPU_CAPS_ELEM(sse3) \ + CPU_CAPS_ELEM(ssse3) \ + CPU_CAPS_ELEM(sse4_1) \ + CPU_CAPS_ELEM(sse4_2) \ + CPU_CAPS_ELEM(avx) \ + CPU_CAPS_ELEM(avx_vnni) \ + CPU_CAPS_ELEM(avx2) \ + CPU_CAPS_ELEM(avx512f) \ + CPU_CAPS_ELEM(avx512dq) \ + CPU_CAPS_ELEM(avx512cd) \ + CPU_CAPS_ELEM(avx512bw) \ + CPU_CAPS_ELEM(avx512vl) \ + CPU_CAPS_ELEM(avx512vbmi) \ + CPU_CAPS_ELEM(avx512vbmi2) \ + CPU_CAPS_ELEM(avx512vnni) \ + CPU_CAPS_ELEM(avx512bitalg) \ + CPU_CAPS_ELEM(avx512popcntq) \ + CPU_CAPS_ELEM(avx512bf16) \ + CPU_CAPS_ELEM(aes) \ + CPU_CAPS_ELEM(bmi1) \ + CPU_CAPS_ELEM(bmi2) \ + CPU_CAPS_ELEM(f16c) \ + CPU_CAPS_ELEM(fma) \ + CPU_CAPS_ELEM(fma4) \ + CPU_CAPS_ELEM(gfni) \ + CPU_CAPS_ELEM(invariant_tsc) \ + CPU_CAPS_ELEM(lzcnt) \ + CPU_CAPS_ELEM(monitorx) \ + CPU_CAPS_ELEM(movbe) \ + 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 - * @return Reference to a CPUCaps struct with the detected host CPU capabilities - */ +/// Gets the supported capabilities of the host CPU +/// @return Reference to a CPUCaps struct with the detected host CPU capabilities const CPUCaps& GetCPUCaps(); /// Detects CPU core count diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp index 2e7cef0953..8c143af2f2 100644 --- a/src/yuzu/main_window.cpp +++ b/src/yuzu/main_window.cpp @@ -488,49 +488,31 @@ MainWindow::MainWindow(bool has_broken_vulkan) QtCommon::system->HIDCore().ReloadInputDevices(); controller_dialog->refreshConfiguration(); - const auto branch_name = std::string(Common::g_scm_branch); - const auto description = std::string(Common::g_scm_desc); - 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 = fmt::format("Eden | {}-{}", Common::g_scm_branch, 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 yuzu_build_version = override_build.empty() ? yuzu_build : override_build; const auto processor_count = std::thread::hardware_concurrency(); LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version); LogRuntimes(); #ifdef ARCHITECTURE_x86_64 - const auto& caps = Common::GetCPUCaps(); - std::string cpu_string = caps.cpu_string; - if (caps.avx || caps.avx2 || caps.avx512f) { - cpu_string += " | AVX"; - if (caps.avx512f) { - cpu_string += "512"; - } else if (caps.avx2) { - cpu_string += '2'; - } - if (caps.fma || caps.fma4) { - cpu_string += " | FMA"; - } - } - LOG_INFO(Frontend, "Host CPU: {}", cpu_string); - if (std::optional processor_core = Common::GetProcessorCount()) { - LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core); + auto const& caps = Common::GetCPUCaps(); + std::string ext_string{}; +#define CPU_CAPS_ELEM(n) if (caps.n) ext_string += " | " #n; + CPU_CAPS_LIST +#undef CPU_CAPS_ELEM + if (auto const processor_core = Common::GetProcessorCount()) { + LOG_INFO(Frontend, "Host CPU: {} ({} cores, {} threads) {}", caps.cpu_string, *processor_core, processor_count, ext_string); + } else { + LOG_INFO(Frontend, "Host CPU: {} ({} threads) {}", caps.cpu_string, processor_count, ext_string); } #endif - LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count); LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); - LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", - Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); + LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); #ifdef _WIN32 - LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", - std::chrono::duration_cast>( - Common::Windows::SetCurrentTimerResolutionToMaximum()) - .count()); - QtCommon::system->CoreTiming().SetTimerResolutionNs( - Common::Windows::GetCurrentTimerResolution()); + LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count()); + QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution()); #endif UpdateWindowTitle(); @@ -538,10 +520,10 @@ MainWindow::MainWindow(bool has_broken_vulkan) #ifdef ENABLE_UPDATE_CHECKER if (UISettings::values.check_for_updates) { - update_future = QtConcurrent::run( - []() -> std::optional { return UpdateChecker::GetUpdate(); }); - update_watcher.connect(&update_watcher, &QFutureWatcher::finished, this, - &MainWindow::OnEmulatorUpdateAvailable); + update_future = QtConcurrent::run([] -> std::optional { + return UpdateChecker::GetUpdate(); + }); + update_watcher.connect(&update_watcher, &QFutureWatcher::finished, this, &MainWindow::OnEmulatorUpdateAvailable); update_watcher.setFuture(update_future); } #endif