Core: Rework HardwareInfo

This commit is contained in:
SirLynix 2022-09-24 15:52:29 +02:00
parent 9cd7976a91
commit 6d0b53b39e
10 changed files with 260 additions and 292 deletions

View File

@ -8,9 +8,11 @@
#define NAZARA_CORE_HPP #define NAZARA_CORE_HPP
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/ModuleBase.hpp> #include <Nazara/Core/ModuleBase.hpp>
#include <Nazara/Core/Modules.hpp> #include <Nazara/Core/Modules.hpp>
#include <Nazara/Utils/TypeList.hpp> #include <Nazara/Utils/TypeList.hpp>
#include <optional>
namespace Nz namespace Nz
{ {
@ -26,7 +28,11 @@ namespace Nz
Core(Config /*config*/); Core(Config /*config*/);
~Core(); ~Core();
inline const HardwareInfo& GetHardwareInfo() const;
private: private:
std::optional<HardwareInfo> m_hardwareInfo;
static Core* s_instance; static Core* s_instance;
}; };
} }

View File

@ -7,6 +7,10 @@
namespace Nz namespace Nz
{ {
inline const HardwareInfo& Core::GetHardwareInfo() const
{
return *m_hardwareInfo;
}
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -147,10 +147,13 @@ namespace Nz
enum class ProcessorCap enum class ProcessorCap
{ {
x64, x64,
AES,
AVX, AVX,
FMA3, FMA3,
FMA4, FMA4,
MMX, MMX,
Popcnt,
RDRAND,
XOP, XOP,
SSE, SSE,
SSE2, SSE2,
@ -169,14 +172,24 @@ namespace Nz
{ {
Unknown = -1, Unknown = -1,
ACRN,
AMD, AMD,
Ao486,
AppleRosetta2,
Bhyve,
Centaur, Centaur,
Cyrix, Cyrix,
Elbrus,
Hygon,
HyperV,
Intel, Intel,
KVM, KVM,
HyperV, MicrosoftXTA,
NSC, NSC,
NexGen, NexGen,
Parallels,
QEMU,
QNX,
Rise, Rise,
SIS, SIS,
Transmeta, Transmeta,
@ -185,8 +198,9 @@ namespace Nz
VMware, VMware,
Vortex, Vortex,
XenHVM, XenHVM,
Zhaoxin,
Max = XenHVM Max = Zhaoxin
}; };
constexpr std::size_t ProcessorVendorCount = static_cast<std::size_t>(ProcessorVendor::Max) + 1; constexpr std::size_t ProcessorVendorCount = static_cast<std::size_t>(ProcessorVendor::Max) + 1;

View File

@ -10,33 +10,45 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Enums.hpp> #include <Nazara/Core/Enums.hpp>
#include <string> #include <array>
#include <string_view>
namespace Nz namespace Nz
{ {
class NAZARA_CORE_API HardwareInfo class NAZARA_CORE_API HardwareInfo
{ {
public: public:
HardwareInfo() = delete; HardwareInfo();
~HardwareInfo() = delete; HardwareInfo(const HardwareInfo&) = delete;
HardwareInfo(HardwareInfo&&) = delete;
~HardwareInfo() = default;
inline const char* GetCpuBrandString() const;
inline unsigned int GetCpuThreadCount() const;
inline ProcessorVendor GetCpuVendor() const;
std::string_view GetCpuVendorName() const;
inline UInt64 GetSystemTotalMemory() const;
inline bool HasCapability(ProcessorCap capability) const;
static void Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4]); static void Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4]);
static std::string_view GetProcessorBrandString();
static unsigned int GetProcessorCount();
static ProcessorVendor GetProcessorVendor();
static std::string_view GetProcessorVendorName();
static UInt64 GetTotalMemory();
static bool HasCapability(ProcessorCap capability);
static bool Initialize();
static bool IsCpuidSupported(); static bool IsCpuidSupported();
static bool IsInitialized();
static void Uninitialize(); HardwareInfo& operator=(const HardwareInfo&) = delete;
HardwareInfo& operator=(HardwareInfo&&) = delete;
private:
void FetchCPUInfo();
void FetchMemoryInfo();
std::array<bool, ProcessorCapCount> m_cpuCapabilities;
std::array<char, 3 * 4 * 4> m_cpuBrandString;
ProcessorVendor m_cpuVendor;
unsigned int m_cpuThreadCount;
UInt64 m_systemTotalMemory;
}; };
} }
#include <Nazara/Core/HardwareInfo.inl>
#endif // NAZARA_CORE_HARDWAREINFO_HPP #endif // NAZARA_CORE_HARDWAREINFO_HPP

View File

@ -0,0 +1,37 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline const char* HardwareInfo::GetCpuBrandString() const
{
return m_cpuBrandString.data();
}
inline unsigned int HardwareInfo::GetCpuThreadCount() const
{
return m_cpuThreadCount;
}
inline ProcessorVendor HardwareInfo::GetCpuVendor() const
{
return m_cpuVendor;
}
inline UInt64 HardwareInfo::GetSystemTotalMemory() const
{
return m_systemTotalMemory;
}
inline bool HardwareInfo::HasCapability(ProcessorCap capability) const
{
return m_cpuCapabilities[UnderlyingCast(capability)];
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@ -25,11 +25,14 @@ namespace Nz
Log::Initialize(); Log::Initialize();
LogInit(); LogInit();
m_hardwareInfo.emplace();
} }
Core::~Core() Core::~Core()
{ {
HardwareInfo::Uninitialize(); m_hardwareInfo.reset();
TaskScheduler::Uninitialize(); TaskScheduler::Uninitialize();
LogUninit(); LogUninit();
Log::Uninitialize(); Log::Uninitialize();

View File

@ -3,8 +3,9 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/HardwareInfo.hpp> #include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <frozen/string.h>
#include <frozen/unordered_map.h>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -22,62 +23,76 @@ namespace Nz
{ {
namespace NAZARA_ANONYMOUS_NAMESPACE namespace NAZARA_ANONYMOUS_NAMESPACE
{ {
constexpr std::array s_vendorNames = {
std::string_view("ACRN"), // ProcessorVendor::ACRN
std::string_view("Advanced Micro Devices"), // ProcessorVendor::AMD
std::string_view("ao486"), // ProcessorVendor::Ao486
std::string_view("Apple Rosetta 2"), // ProcessorVendor::AppleRosetta2
std::string_view("bhyve"), // ProcessorVendor::Bhyve
std::string_view("Centaur Technology"), // ProcessorVendor::Centaur
std::string_view("Cyrix Corporation"), // ProcessorVendor::Cyrix
std::string_view("MCST Elbrus"), // ProcessorVendor::Elbrus
std::string_view("Hygon"), // ProcessorVendor::Hygon
std::string_view("Microsoft Hyper-V"), // ProcessorVendor::HyperV
std::string_view("Intel Corporation"), // ProcessorVendor::Intel
std::string_view("Kernel-based Virtual Machine"), // ProcessorVendor::KVM
std::string_view("Microsoft x86-to-ARM"), // ProcessorVendor::MicrosoftXTA
std::string_view("National Semiconductor"), // ProcessorVendor::NSC
std::string_view("NexGen"), // ProcessorVendor::NexGen
std::string_view("Parallels"), // ProcessorVendor::Parallels
std::string_view("QEMU"), // ProcessorVendor::QEMU
std::string_view("QNX Hypervisor"), // ProcessorVendor::QNX
std::string_view("Rise Technology"), // ProcessorVendor::Rise
std::string_view("Silicon Integrated Systems"), // ProcessorVendor::SiS
std::string_view("Transmeta Corporation"), // ProcessorVendor::Transmeta
std::string_view("United Microelectronics Corporation"), // ProcessorVendor::UMC
std::string_view("VIA Technologies"), // ProcessorVendor::VIA
std::string_view("VMware"), // ProcessorVendor::VMware
std::string_view("Vortex86"), // ProcessorVendor::Vortex
std::string_view("Xen"), // ProcessorVendor::XenHVM
std::string_view("Zhaoxin)") // ProcessorVendor::Zhaoxin
};
static_assert(s_vendorNames.size() == ProcessorVendorCount, "Processor vendor name array is incomplete");
struct VendorString struct VendorString
{ {
char vendor[13]; // +1 pour le \0 automatiquement ajouté par le compilateur char vendor[13]; // +1 for the end of string character
ProcessorVendor vendorEnum; ProcessorVendor vendorEnum;
}; };
const char* s_vendorNames[] = constexpr frozen::unordered_map s_vendorStrings = frozen::make_unordered_map<frozen::string, ProcessorVendor>({
{ { " Shanghai ", ProcessorVendor::Zhaoxin },
"Advanced Micro Devices", // ProcessorVendor::AMD { " KVMKVMKVM ", ProcessorVendor::KVM },
"Centaur Technology", // ProcessorVendor::Centaur { " QNXQVMBSQG ", ProcessorVendor::QNX },
"Cyrix Corporation", // ProcessorVendor::Cyrix { " lrpepyh vr", ProcessorVendor::Parallels },
"Intel Corporation", // ProcessorVendor::Intel { "ACRNACRNACRN", ProcessorVendor::ACRN },
"Kernel-based Virtual Machine", // ProcessorVendor::KVM
"Microsoft Hyper-V", // ProcessorVendor::HyperV
"National Semiconductor", // ProcessorVendor::NSC
"NexGen", // ProcessorVendor::NexGen
"Rise Technology", // ProcessorVendor::Rise
"Silicon Integrated Systems", // ProcessorVendor::SIS
"Transmeta Corporation", // ProcessorVendor::Transmeta
"United Microelectronics Corporation", // ProcessorVendor::UMC
"VIA Technologies", // ProcessorVendor::VIA
"VMware", // ProcessorVendor::VMware
"Vortex86", // ProcessorVendor::Vortex
"Xen" // ProcessorVendor::XenHVM
};
static_assert(sizeof(s_vendorNames)/sizeof(const char*) == ProcessorVendorCount, "Processor vendor name array is incomplete");
VendorString vendorStrings[] =
{
// Triés par ordre alphabétique (Majuscules primant sur minuscules)
{ "AMDisbetter!", ProcessorVendor::AMD }, { "AMDisbetter!", ProcessorVendor::AMD },
{ "AuthenticAMD", ProcessorVendor::AMD }, { "AuthenticAMD", ProcessorVendor::AMD },
{ "CentaurHauls", ProcessorVendor::Centaur }, { "CentaurHauls", ProcessorVendor::Centaur },
{ "CyrixInstead", ProcessorVendor::Cyrix }, { "CyrixInstead", ProcessorVendor::Cyrix },
{ "E2K MACHINE", ProcessorVendor::Elbrus },
{ "GenuineIntel", ProcessorVendor::Intel }, { "GenuineIntel", ProcessorVendor::Intel },
{ "GenuineTMx86", ProcessorVendor::Transmeta }, { "GenuineTMx86", ProcessorVendor::Transmeta },
{ "Geode by NSC", ProcessorVendor::NSC }, { "Geode by NSC", ProcessorVendor::NSC },
{ "HygonGenuine", ProcessorVendor::Hygon },
{ "KVMKVMKVMKVM", ProcessorVendor::KVM }, { "KVMKVMKVMKVM", ProcessorVendor::KVM },
{ "Microsoft Hv", ProcessorVendor::HyperV }, { "Microsoft Hv", ProcessorVendor::HyperV },
{ "MicrosoftXTA", ProcessorVendor::MicrosoftXTA },
{ "NexGenDriven", ProcessorVendor::NexGen }, { "NexGenDriven", ProcessorVendor::NexGen },
{ "RiseRiseRise", ProcessorVendor::Rise }, { "RiseRiseRise", ProcessorVendor::Rise },
{ "SiS SiS SiS ", ProcessorVendor::SIS }, { "SiS SiS SiS ", ProcessorVendor::SIS },
{ "TCGTCGTCGTCG", ProcessorVendor::QEMU },
{ "TransmetaCPU", ProcessorVendor::Transmeta }, { "TransmetaCPU", ProcessorVendor::Transmeta },
{ "UMC UMC UMC ", ProcessorVendor::UMC }, { "UMC UMC UMC ", ProcessorVendor::UMC },
{ "VIA VIA VIA ", ProcessorVendor::VIA }, { "VIA VIA VIA ", ProcessorVendor::VIA },
{ "VMwareVMware", ProcessorVendor::VMware }, { "VMwareVMware", ProcessorVendor::VMware },
{ "VirtualApple", ProcessorVendor::AppleRosetta2 },
{ "Vortex86 SoC", ProcessorVendor::Vortex }, { "Vortex86 SoC", ProcessorVendor::Vortex },
{"XenVMMXenVMM", ProcessorVendor::XenHVM} { "XenVMMXenVMM", ProcessorVendor::XenHVM },
}; { "bhyve bhyve ", ProcessorVendor::Bhyve },
{ "prl hyperv ", ProcessorVendor::Parallels }, //< endianness-fixed version of " lrpepyh vr"
ProcessorVendor s_vendorEnum = ProcessorVendor::Unknown; });
bool s_capabilities[ProcessorCapCount] = {false};
bool s_initialized = false;
char s_brandString[48] = "Not initialized";
} }
/*! /*!
@ -86,195 +101,103 @@ namespace Nz
* \brief Core class that represents the info we can get from hardware * \brief Core class that represents the info we can get from hardware
*/ */
/*! HardwareInfo::HardwareInfo()
* \brief Generates the cpuid instruction (available on x86 & x64) {
* FetchCPUInfo();
* \param functionId Information to retrieve FetchMemoryInfo();
* \param subFunctionId Additional code for information retrieval }
* \param result Supported features of the CPU
*/ std::string_view HardwareInfo::GetCpuVendorName() const
{
NAZARA_USE_ANONYMOUS_NAMESPACE
return s_vendorNames[UnderlyingCast(m_cpuVendor)];
}
void HardwareInfo::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4]) void HardwareInfo::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4])
{ {
return HardwareInfoImpl::Cpuid(functionId, subFunctionId, result); return HardwareInfoImpl::Cpuid(functionId, subFunctionId, result);
} }
/*! bool HardwareInfo::IsCpuidSupported()
* \brief Gets the brand of the processor {
* \return String of the brand return HardwareInfoImpl::IsCpuidSupported();
* }
* \remark Produces a NazaraError if not Initialize
*/
std::string_view HardwareInfo::GetProcessorBrandString() void HardwareInfo::FetchCPUInfo()
{ {
NAZARA_USE_ANONYMOUS_NAMESPACE NAZARA_USE_ANONYMOUS_NAMESPACE
if (!Initialize()) m_cpuThreadCount = std::max(HardwareInfoImpl::GetProcessorCount(), 1U);
NazaraError("Failed to initialize HardwareInfo");
return s_brandString; m_cpuCapabilities.fill(false);
} m_cpuVendor = ProcessorVendor::Unknown;
/*! std::strcpy(m_cpuBrandString.data(), "CPU from unknown vendor - cpuid not supported");
* \brief Gets the number of threads
* \return Number of threads available on the CPU
*
* \remark Doesn't need the initialization of HardwareInfo
*/
unsigned int HardwareInfo::GetProcessorCount()
{
static unsigned int processorCount = std::max(HardwareInfoImpl::GetProcessorCount(), 1U);
return processorCount;
}
/*!
* \brief Gets the processor vendor
* \return ProcessorVendor containing information the vendor
*
* \remark Produces a NazaraError if not Initialize
*/
ProcessorVendor HardwareInfo::GetProcessorVendor()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
if (!Initialize())
NazaraError("Failed to initialize HardwareInfo");
return s_vendorEnum;
}
/*!
* \brief Gets the vendor of the processor
* \return String of the vendor
*
* \remark Produces a NazaraError if not Initialize
*/
std::string_view HardwareInfo::GetProcessorVendorName()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
if (!Initialize())
NazaraError("Failed to initialize HardwareInfo");
return s_vendorNames[UnderlyingCast(s_vendorEnum)];
}
/*!
* \brief Gets the amount of total memory
* \return Number of total memory available
*
* \remark Doesn't need the initialization of HardwareInfo
*/
UInt64 HardwareInfo::GetTotalMemory()
{
static UInt64 totalMemory = HardwareInfoImpl::GetTotalMemory();
return totalMemory;
}
/*!
* \brief Checks whether the processor owns the capacity to handle certain instructions
* \return true If instructions supported
*
* \remark Produces a NazaraError if capability is a wrong enum with NAZARA_DEBUG defined
*/
bool HardwareInfo::HasCapability(ProcessorCap capability)
{
NAZARA_USE_ANONYMOUS_NAMESPACE
return s_capabilities[UnderlyingCast(capability)];
}
/*!
* \brief Initializes the HardwareInfo class
* \return true if successful
*
* \remark Produces a NazaraError if cpuid is not supported
*/
bool HardwareInfo::Initialize()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
if (IsInitialized())
return true;
if (!HardwareInfoImpl::IsCpuidSupported()) if (!HardwareInfoImpl::IsCpuidSupported())
{ {
NazaraError("Cpuid is not supported"); NazaraWarning("Cpuid is not supported");
return false; return;
} }
s_initialized = true; // To begin, we get the id of the constructor and the id of maximal functions supported by the CPUID
std::array<UInt32, 4> registers;
HardwareInfoImpl::Cpuid(0, 0, registers.data());
UInt32 registers[4]; // To store our registers values (EAX, EBX, ECX and EDX)
// Let's make it clearer
UInt32& eax = registers[0]; UInt32& eax = registers[0];
UInt32& ebx = registers[1]; UInt32& ebx = registers[1];
UInt32& ecx = registers[2]; UInt32& ecx = registers[2];
UInt32& edx = registers[3]; UInt32& edx = registers[3];
// To begin, we get the id of the constructor and the id of maximal functions supported by the CPUID
HardwareInfoImpl::Cpuid(0, 0, registers);
// Note the order: EBX, EDX, ECX
UInt32 manufacturerId[3] = { ebx, edx, ecx }; UInt32 manufacturerId[3] = { ebx, edx, ecx };
frozen::string manufactorID(reinterpret_cast<const char*>(&manufacturerId[0]), 12);
// Identification of conceptor if (auto vendorIt = s_vendorStrings.find(manufactorID); vendorIt != s_vendorStrings.end())
s_vendorEnum = ProcessorVendor::Unknown; m_cpuVendor = vendorIt->second;
for (const VendorString& vendorString : vendorStrings) else
{ m_cpuVendor = ProcessorVendor::Unknown;
if (std::memcmp(manufacturerId, vendorString.vendor, 12) == 0)
{
s_vendorEnum = vendorString.vendorEnum;
break;
}
}
if (eax >= 1) if (eax >= 1)
{ {
// Retrieval of certain capacities of the processor (ECX and EDX, function 1) // Retrieval of certain capacities of the processor (ECX and EDX, function 1)
HardwareInfoImpl::Cpuid(1, 0, registers); HardwareInfoImpl::Cpuid(1, 0, registers.data());
s_capabilities[UnderlyingCast(ProcessorCap::AVX)] = (ecx & (1U << 28)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::AES)] = (ecx & (1U << 25)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::FMA3)] = (ecx & (1U << 12)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::AVX)] = (ecx & (1U << 28)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::MMX)] = (edx & (1U << 23)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::FMA3)] = (ecx & (1U << 12)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE)] = (edx & (1U << 25)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::MMX)] = (edx & (1U << 23)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE2)] = (edx & (1U << 26)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::Popcnt)] = (ecx & (1U << 23)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE3)] = (ecx & (1U << 0)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::RDRAND)] = (ecx & (1U << 30)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSSE3)] = (ecx & (1U << 9)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE)] = (edx & (1U << 25)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE41)] = (ecx & (1U << 19)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE2)] = (edx & (1U << 26)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE42)] = (ecx & (1U << 20)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE3)] = (ecx & (1U << 0)) != 0;
m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSSE3)] = (ecx & (1U << 9)) != 0;
m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE41)] = (ecx & (1U << 19)) != 0;
m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE42)] = (ecx & (1U << 20)) != 0;
} }
// Retrieval of biggest extended function handled (EAX, function 0x80000000) // Retrieval of biggest extended function handled (EAX, function 0x80000000)
HardwareInfoImpl::Cpuid(0x80000000, 0, registers); HardwareInfoImpl::Cpuid(0x80000000, 0, registers.data());
UInt32 maxSupportedExtendedFunction = eax; UInt32 maxSupportedExtendedFunction = eax;
if (maxSupportedExtendedFunction >= 0x80000001) if (maxSupportedExtendedFunction >= 0x80000001)
{ {
// Retrieval of extended capabilities of the processor (ECX and EDX, function 0x80000001) // Retrieval of extended capabilities of the processor (ECX and EDX, function 0x80000001)
HardwareInfoImpl::Cpuid(0x80000001, 0, registers); HardwareInfoImpl::Cpuid(0x80000001, 0, registers.data());
s_capabilities[UnderlyingCast(ProcessorCap::x64)] = (edx & (1U << 29)) != 0; // Support of 64bits, independent of the OS m_cpuCapabilities[UnderlyingCast(ProcessorCap::x64)] = (edx & (1U << 29)) != 0; // Support of 64bits, doesn't mean executable is 64bits
s_capabilities[UnderlyingCast(ProcessorCap::FMA4)] = (ecx & (1U << 16)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::FMA4)] = (ecx & (1U << 16)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::SSE4a)] = (ecx & (1U << 6)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE4a)] = (ecx & (1U << 6)) != 0;
s_capabilities[UnderlyingCast(ProcessorCap::XOP)] = (ecx & (1U << 11)) != 0; m_cpuCapabilities[UnderlyingCast(ProcessorCap::XOP)] = (ecx & (1U << 11)) != 0;
if (maxSupportedExtendedFunction >= 0x80000004) if (maxSupportedExtendedFunction >= 0x80000004)
{ {
// Retrieval of the string describing the processor (EAX, EBX, ECX and EDX, // Retrieval of the string describing the processor (EAX, EBX, ECX and EDX, functions from 0x80000002 to 0x80000004 inclusive)
// functions from 0x80000002 to 0x80000004 inclusive) char* ptr = &m_cpuBrandString[0];
char* ptr = &s_brandString[0];
for (UInt32 code = 0x80000002; code <= 0x80000004; ++code) for (UInt32 code = 0x80000002; code <= 0x80000004; ++code)
{ {
HardwareInfoImpl::Cpuid(code, 0, registers); HardwareInfoImpl::Cpuid(code, 0, registers.data());
std::memcpy(ptr, &registers[0], 4*sizeof(UInt32)); // We add the 16 bytes to the string std::memcpy(ptr, &registers[0], 4*sizeof(UInt32)); // We add the 16 bytes to the string
ptr += 4 * sizeof(UInt32); ptr += 4 * sizeof(UInt32);
@ -283,41 +206,10 @@ namespace Nz
// The character '\0' is already part of the string // The character '\0' is already part of the string
} }
} }
return true;
} }
/*! void HardwareInfo::FetchMemoryInfo()
* \brief Checks whether the instruction of cpuid is supported
* \return true if it the case
*/
bool HardwareInfo::IsCpuidSupported()
{ {
return HardwareInfoImpl::IsCpuidSupported(); m_systemTotalMemory = HardwareInfoImpl::GetTotalMemory();
}
/*!
* \brief Checks whether the class HardwareInfo is initialized
* \return true if it is initialized
*/
bool HardwareInfo::IsInitialized()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
return s_initialized;
}
/*!
* \brief Unitializes the class HardwareInfo
*/
void HardwareInfo::Uninitialize()
{
NAZARA_USE_ANONYMOUS_NAMESPACE
// Nothing to do
s_initialized = false;
} }
} }

View File

@ -3,8 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/TaskScheduler.hpp> #include <Nazara/Core/TaskScheduler.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/TaskSchedulerImpl.hpp> #include <Nazara/Core/Win32/TaskSchedulerImpl.hpp>
@ -34,12 +34,12 @@ namespace Nz
/*! /*!
* \brief Gets the number of threads * \brief Gets the number of threads
* \return Number of threads, if none, the number of simulatenous threads on the processor is returned * \return Number of threads, if none, the number of logical threads on the processor is returned
*/ */
unsigned int TaskScheduler::GetWorkerCount() unsigned int TaskScheduler::GetWorkerCount()
{ {
return (s_workerCount > 0) ? s_workerCount : HardwareInfo::GetProcessorCount(); return (s_workerCount > 0) ? s_workerCount : Core::Instance()->GetHardwareInfo().GetCpuThreadCount();
} }
/*! /*!

View File

@ -17,7 +17,7 @@ namespace Nz
void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]) void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
{ {
#if defined(NAZARA_COMPILER_MSVC) #if defined(NAZARA_COMPILER_MSVC)
static_assert(sizeof(UInt32) == sizeof(int), "Assertion failed"); static_assert(sizeof(UInt32) == sizeof(int));
// Use intrinsic function if available // Use intrinsic function if available
__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId)); __cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));

View File

@ -59,7 +59,7 @@ local modules = {
add_syslinks("dl", "pthread") add_syslinks("dl", "pthread")
end end
end, end,
Packages = { "entt" }, Packages = { "entt", "frozen" },
PublicPackages = { "nazarautils" } PublicPackages = { "nazarautils" }
}, },
Graphics = { Graphics = {