early-access version 3114
This commit is contained in:
parent
725127cc61
commit
8c23201957
4 changed files with 65 additions and 4 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3113.
|
This is the source code for early-access 3114.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,27 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
#include "common/x64/cpu_detect.h"
|
#include "common/x64/cpu_detect.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
|
||||||
|
static inline u64 xgetbv(u32 index) {
|
||||||
|
return _xgetbv(index);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
|
@ -39,12 +52,11 @@ static inline void __cpuid(int info[4], u32 function_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _XCR_XFEATURE_ENABLED_MASK 0
|
#define _XCR_XFEATURE_ENABLED_MASK 0
|
||||||
static inline u64 _xgetbv(u32 index) {
|
static inline u64 xgetbv(u32 index) {
|
||||||
u32 eax, edx;
|
u32 eax, edx;
|
||||||
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
|
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
|
||||||
return ((u64)edx << 32) | eax;
|
return ((u64)edx << 32) | eax;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
@ -107,7 +119,7 @@ static CPUCaps Detect() {
|
||||||
// - Is the XSAVE bit set in CPUID?
|
// - Is the XSAVE bit set in CPUID?
|
||||||
// - XGETBV result has the XCR bit set.
|
// - XGETBV result has the XCR bit set.
|
||||||
if (Common::Bit<28>(cpu_id[2]) && Common::Bit<27>(cpu_id[2])) {
|
if (Common::Bit<28>(cpu_id[2]) && Common::Bit<27>(cpu_id[2])) {
|
||||||
if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) {
|
if ((xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) {
|
||||||
caps.avx = true;
|
caps.avx = true;
|
||||||
if (Common::Bit<12>(cpu_id[2]))
|
if (Common::Bit<12>(cpu_id[2]))
|
||||||
caps.fma = true;
|
caps.fma = true;
|
||||||
|
@ -192,4 +204,45 @@ const CPUCaps& GetCPUCaps() {
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<int> GetProcessorCount() {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// Get the buffer length.
|
||||||
|
DWORD length = 0;
|
||||||
|
GetLogicalProcessorInformation(nullptr, &length);
|
||||||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> 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<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");
|
||||||
|
char state = '0';
|
||||||
|
if (smt) {
|
||||||
|
smt.read(&state, sizeof(state));
|
||||||
|
}
|
||||||
|
switch (state) {
|
||||||
|
case '0':
|
||||||
|
return thread_count;
|
||||||
|
case '1':
|
||||||
|
return thread_count / 2;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Shame on you
|
||||||
|
return std::nullopt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
@ -74,4 +75,7 @@ struct CPUCaps {
|
||||||
*/
|
*/
|
||||||
const CPUCaps& GetCPUCaps();
|
const CPUCaps& GetCPUCaps();
|
||||||
|
|
||||||
|
/// Detects CPU core count
|
||||||
|
std::optional<int> GetProcessorCount();
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
|
@ -362,6 +362,10 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
|
||||||
}
|
}
|
||||||
LOG_INFO(Frontend, "Host CPU: {}", cpu_string);
|
LOG_INFO(Frontend, "Host CPU: {}", cpu_string);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (std::optional<int> processor_core = Common::GetProcessorCount()) {
|
||||||
|
LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core);
|
||||||
|
}
|
||||||
LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count);
|
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",
|
||||||
|
|
Loading…
Reference in a new issue