diff --git a/include/Nazara/Core/Core.hpp b/include/Nazara/Core/Core.hpp index e6584b7e2..ba3cc4c64 100644 --- a/include/Nazara/Core/Core.hpp +++ b/include/Nazara/Core/Core.hpp @@ -8,9 +8,11 @@ #define NAZARA_CORE_HPP #include +#include #include #include #include +#include namespace Nz { @@ -26,7 +28,11 @@ namespace Nz Core(Config /*config*/); ~Core(); + inline const HardwareInfo& GetHardwareInfo() const; + private: + std::optional m_hardwareInfo; + static Core* s_instance; }; } diff --git a/include/Nazara/Core/Core.inl b/include/Nazara/Core/Core.inl index fe6bebe5b..5049f916d 100644 --- a/include/Nazara/Core/Core.inl +++ b/include/Nazara/Core/Core.inl @@ -7,6 +7,10 @@ namespace Nz { + inline const HardwareInfo& Core::GetHardwareInfo() const + { + return *m_hardwareInfo; + } } #include diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index e1a9cb571..9107c5dc3 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -147,10 +147,13 @@ namespace Nz enum class ProcessorCap { x64, + AES, AVX, FMA3, FMA4, MMX, + Popcnt, + RDRAND, XOP, SSE, SSE2, @@ -169,14 +172,24 @@ namespace Nz { Unknown = -1, + ACRN, AMD, + Ao486, + AppleRosetta2, + Bhyve, Centaur, Cyrix, + Elbrus, + Hygon, + HyperV, Intel, KVM, - HyperV, + MicrosoftXTA, NSC, NexGen, + Parallels, + QEMU, + QNX, Rise, SIS, Transmeta, @@ -185,8 +198,9 @@ namespace Nz VMware, Vortex, XenHVM, + Zhaoxin, - Max = XenHVM + Max = Zhaoxin }; constexpr std::size_t ProcessorVendorCount = static_cast(ProcessorVendor::Max) + 1; diff --git a/include/Nazara/Core/HardwareInfo.hpp b/include/Nazara/Core/HardwareInfo.hpp index fa4f1d2bd..9b31186f0 100644 --- a/include/Nazara/Core/HardwareInfo.hpp +++ b/include/Nazara/Core/HardwareInfo.hpp @@ -10,33 +10,45 @@ #include #include #include -#include +#include +#include namespace Nz { class NAZARA_CORE_API HardwareInfo { public: - HardwareInfo() = delete; - ~HardwareInfo() = delete; + HardwareInfo(); + 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 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 IsInitialized(); - static void Uninitialize(); + HardwareInfo& operator=(const HardwareInfo&) = delete; + HardwareInfo& operator=(HardwareInfo&&) = delete; + + private: + void FetchCPUInfo(); + void FetchMemoryInfo(); + + std::array m_cpuCapabilities; + std::array m_cpuBrandString; + ProcessorVendor m_cpuVendor; + unsigned int m_cpuThreadCount; + UInt64 m_systemTotalMemory; }; } +#include + #endif // NAZARA_CORE_HARDWAREINFO_HPP diff --git a/include/Nazara/Core/HardwareInfo.inl b/include/Nazara/Core/HardwareInfo.inl new file mode 100644 index 000000000..95eb23f34 --- /dev/null +++ b/include/Nazara/Core/HardwareInfo.inl @@ -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 +#include +#include + +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 diff --git a/src/Nazara/Core/Core.cpp b/src/Nazara/Core/Core.cpp index 6c713d08d..eb9dac483 100644 --- a/src/Nazara/Core/Core.cpp +++ b/src/Nazara/Core/Core.cpp @@ -25,11 +25,14 @@ namespace Nz Log::Initialize(); LogInit(); + + m_hardwareInfo.emplace(); } Core::~Core() { - HardwareInfo::Uninitialize(); + m_hardwareInfo.reset(); + TaskScheduler::Uninitialize(); LogUninit(); Log::Uninitialize(); diff --git a/src/Nazara/Core/HardwareInfo.cpp b/src/Nazara/Core/HardwareInfo.cpp index 3b6ee1cd2..98d986615 100644 --- a/src/Nazara/Core/HardwareInfo.cpp +++ b/src/Nazara/Core/HardwareInfo.cpp @@ -3,8 +3,9 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include +#include +#include #include #include @@ -22,62 +23,76 @@ namespace Nz { 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 { - char vendor[13]; // +1 pour le \0 automatiquement ajouté par le compilateur + char vendor[13]; // +1 for the end of string character ProcessorVendor vendorEnum; }; - const char* s_vendorNames[] = - { - "Advanced Micro Devices", // ProcessorVendor::AMD - "Centaur Technology", // ProcessorVendor::Centaur - "Cyrix Corporation", // ProcessorVendor::Cyrix - "Intel Corporation", // ProcessorVendor::Intel - "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}, - {"AuthenticAMD", ProcessorVendor::AMD}, - {"CentaurHauls", ProcessorVendor::Centaur}, - {"CyrixInstead", ProcessorVendor::Cyrix}, - {"GenuineIntel", ProcessorVendor::Intel}, - {"GenuineTMx86", ProcessorVendor::Transmeta}, - {"Geode by NSC", ProcessorVendor::NSC}, - {"KVMKVMKVMKVM", ProcessorVendor::KVM}, - {"Microsoft Hv", ProcessorVendor::HyperV}, - {"NexGenDriven", ProcessorVendor::NexGen}, - {"RiseRiseRise", ProcessorVendor::Rise}, - {"SiS SiS SiS ", ProcessorVendor::SIS}, - {"TransmetaCPU", ProcessorVendor::Transmeta}, - {"UMC UMC UMC ", ProcessorVendor::UMC}, - {"VIA VIA VIA ", ProcessorVendor::VIA}, - {"VMwareVMware", ProcessorVendor::VMware}, - {"Vortex86 SoC", ProcessorVendor::Vortex}, - {"XenVMMXenVMM", ProcessorVendor::XenHVM} - }; - - ProcessorVendor s_vendorEnum = ProcessorVendor::Unknown; - bool s_capabilities[ProcessorCapCount] = {false}; - bool s_initialized = false; - - char s_brandString[48] = "Not initialized"; + constexpr frozen::unordered_map s_vendorStrings = frozen::make_unordered_map({ + { " Shanghai ", ProcessorVendor::Zhaoxin }, + { " KVMKVMKVM ", ProcessorVendor::KVM }, + { " QNXQVMBSQG ", ProcessorVendor::QNX }, + { " lrpepyh vr", ProcessorVendor::Parallels }, + { "ACRNACRNACRN", ProcessorVendor::ACRN }, + { "AMDisbetter!", ProcessorVendor::AMD }, + { "AuthenticAMD", ProcessorVendor::AMD }, + { "CentaurHauls", ProcessorVendor::Centaur }, + { "CyrixInstead", ProcessorVendor::Cyrix }, + { "E2K MACHINE", ProcessorVendor::Elbrus }, + { "GenuineIntel", ProcessorVendor::Intel }, + { "GenuineTMx86", ProcessorVendor::Transmeta }, + { "Geode by NSC", ProcessorVendor::NSC }, + { "HygonGenuine", ProcessorVendor::Hygon }, + { "KVMKVMKVMKVM", ProcessorVendor::KVM }, + { "Microsoft Hv", ProcessorVendor::HyperV }, + { "MicrosoftXTA", ProcessorVendor::MicrosoftXTA }, + { "NexGenDriven", ProcessorVendor::NexGen }, + { "RiseRiseRise", ProcessorVendor::Rise }, + { "SiS SiS SiS ", ProcessorVendor::SIS }, + { "TCGTCGTCGTCG", ProcessorVendor::QEMU }, + { "TransmetaCPU", ProcessorVendor::Transmeta }, + { "UMC UMC UMC ", ProcessorVendor::UMC }, + { "VIA VIA VIA ", ProcessorVendor::VIA }, + { "VMwareVMware", ProcessorVendor::VMware }, + { "VirtualApple", ProcessorVendor::AppleRosetta2 }, + { "Vortex86 SoC", ProcessorVendor::Vortex }, + { "XenVMMXenVMM", ProcessorVendor::XenHVM }, + { "bhyve bhyve ", ProcessorVendor::Bhyve }, + { "prl hyperv ", ProcessorVendor::Parallels }, //< endianness-fixed version of " lrpepyh vr" + }); } /*! @@ -86,238 +101,115 @@ namespace Nz * \brief Core class that represents the info we can get from hardware */ - /*! - * \brief Generates the cpuid instruction (available on x86 & x64) - * - * \param functionId Information to retrieve - * \param subFunctionId Additional code for information retrieval - * \param result Supported features of the CPU - */ + HardwareInfo::HardwareInfo() + { + FetchCPUInfo(); + FetchMemoryInfo(); + } + + 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]) { return HardwareInfoImpl::Cpuid(functionId, subFunctionId, result); } - /*! - * \brief Gets the brand of the processor - * \return String of the brand - * - * \remark Produces a NazaraError if not Initialize - */ - - std::string_view HardwareInfo::GetProcessorBrandString() - { - NAZARA_USE_ANONYMOUS_NAMESPACE - - if (!Initialize()) - NazaraError("Failed to initialize HardwareInfo"); - - return s_brandString; - } - - /*! - * \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()) - { - NazaraError("Cpuid is not supported"); - return false; - } - - s_initialized = true; - - UInt32 registers[4]; // To store our registers values (EAX, EBX, ECX and EDX) - - // Let's make it clearer - UInt32& eax = registers[0]; - UInt32& ebx = registers[1]; - UInt32& ecx = registers[2]; - 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}; - - // Identification of conceptor - s_vendorEnum = ProcessorVendor::Unknown; - for (const VendorString& vendorString : vendorStrings) - { - if (std::memcmp(manufacturerId, vendorString.vendor, 12) == 0) - { - s_vendorEnum = vendorString.vendorEnum; - break; - } - } - - if (eax >= 1) - { - // Retrieval of certain capacities of the processor (ECX and EDX, function 1) - HardwareInfoImpl::Cpuid(1, 0, registers); - - s_capabilities[UnderlyingCast(ProcessorCap::AVX)] = (ecx & (1U << 28)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::FMA3)] = (ecx & (1U << 12)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::MMX)] = (edx & (1U << 23)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE)] = (edx & (1U << 25)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE2)] = (edx & (1U << 26)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE3)] = (ecx & (1U << 0)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSSE3)] = (ecx & (1U << 9)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE41)] = (ecx & (1U << 19)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE42)] = (ecx & (1U << 20)) != 0; - } - - // Retrieval of biggest extended function handled (EAX, function 0x80000000) - HardwareInfoImpl::Cpuid(0x80000000, 0, registers); - - UInt32 maxSupportedExtendedFunction = eax; - if (maxSupportedExtendedFunction >= 0x80000001) - { - // Retrieval of extended capabilities of the processor (ECX and EDX, function 0x80000001) - HardwareInfoImpl::Cpuid(0x80000001, 0, registers); - - s_capabilities[UnderlyingCast(ProcessorCap::x64)] = (edx & (1U << 29)) != 0; // Support of 64bits, independent of the OS - s_capabilities[UnderlyingCast(ProcessorCap::FMA4)] = (ecx & (1U << 16)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::SSE4a)] = (ecx & (1U << 6)) != 0; - s_capabilities[UnderlyingCast(ProcessorCap::XOP)] = (ecx & (1U << 11)) != 0; - - if (maxSupportedExtendedFunction >= 0x80000004) - { - // Retrieval of the string describing the processor (EAX, EBX, ECX and EDX, - // functions from 0x80000002 to 0x80000004 inclusive) - char* ptr = &s_brandString[0]; - for (UInt32 code = 0x80000002; code <= 0x80000004; ++code) - { - HardwareInfoImpl::Cpuid(code, 0, registers); - std::memcpy(ptr, ®isters[0], 4*sizeof(UInt32)); // We add the 16 bytes to the string - - ptr += 4*sizeof(UInt32); - } - - // The character '\0' is already part of the string - } - } - - return true; - } - - /*! - * \brief Checks whether the instruction of cpuid is supported - * \return true if it the case - */ - bool HardwareInfo::IsCpuidSupported() { return HardwareInfoImpl::IsCpuidSupported(); } - /*! - * \brief Checks whether the class HardwareInfo is initialized - * \return true if it is initialized - */ - - bool HardwareInfo::IsInitialized() + void HardwareInfo::FetchCPUInfo() { NAZARA_USE_ANONYMOUS_NAMESPACE - return s_initialized; + m_cpuThreadCount = std::max(HardwareInfoImpl::GetProcessorCount(), 1U); + + m_cpuCapabilities.fill(false); + m_cpuVendor = ProcessorVendor::Unknown; + + std::strcpy(m_cpuBrandString.data(), "CPU from unknown vendor - cpuid not supported"); + + if (!HardwareInfoImpl::IsCpuidSupported()) + { + NazaraWarning("Cpuid is not supported"); + return; + } + + // To begin, we get the id of the constructor and the id of maximal functions supported by the CPUID + std::array registers; + HardwareInfoImpl::Cpuid(0, 0, registers.data()); + + UInt32& eax = registers[0]; + UInt32& ebx = registers[1]; + UInt32& ecx = registers[2]; + UInt32& edx = registers[3]; + + UInt32 manufacturerId[3] = { ebx, edx, ecx }; + frozen::string manufactorID(reinterpret_cast(&manufacturerId[0]), 12); + + if (auto vendorIt = s_vendorStrings.find(manufactorID); vendorIt != s_vendorStrings.end()) + m_cpuVendor = vendorIt->second; + else + m_cpuVendor = ProcessorVendor::Unknown; + + if (eax >= 1) + { + // Retrieval of certain capacities of the processor (ECX and EDX, function 1) + HardwareInfoImpl::Cpuid(1, 0, registers.data()); + + m_cpuCapabilities[UnderlyingCast(ProcessorCap::AES)] = (ecx & (1U << 25)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::AVX)] = (ecx & (1U << 28)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::FMA3)] = (ecx & (1U << 12)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::MMX)] = (edx & (1U << 23)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::Popcnt)] = (ecx & (1U << 23)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::RDRAND)] = (ecx & (1U << 30)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE)] = (edx & (1U << 25)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE2)] = (edx & (1U << 26)) != 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) + HardwareInfoImpl::Cpuid(0x80000000, 0, registers.data()); + + UInt32 maxSupportedExtendedFunction = eax; + if (maxSupportedExtendedFunction >= 0x80000001) + { + // Retrieval of extended capabilities of the processor (ECX and EDX, function 0x80000001) + HardwareInfoImpl::Cpuid(0x80000001, 0, registers.data()); + + m_cpuCapabilities[UnderlyingCast(ProcessorCap::x64)] = (edx & (1U << 29)) != 0; // Support of 64bits, doesn't mean executable is 64bits + m_cpuCapabilities[UnderlyingCast(ProcessorCap::FMA4)] = (ecx & (1U << 16)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::SSE4a)] = (ecx & (1U << 6)) != 0; + m_cpuCapabilities[UnderlyingCast(ProcessorCap::XOP)] = (ecx & (1U << 11)) != 0; + + if (maxSupportedExtendedFunction >= 0x80000004) + { + // Retrieval of the string describing the processor (EAX, EBX, ECX and EDX, functions from 0x80000002 to 0x80000004 inclusive) + char* ptr = &m_cpuBrandString[0]; + for (UInt32 code = 0x80000002; code <= 0x80000004; ++code) + { + HardwareInfoImpl::Cpuid(code, 0, registers.data()); + std::memcpy(ptr, ®isters[0], 4*sizeof(UInt32)); // We add the 16 bytes to the string + + ptr += 4 * sizeof(UInt32); + } + + // The character '\0' is already part of the string + } + } } - /*! - * \brief Unitializes the class HardwareInfo - */ - - void HardwareInfo::Uninitialize() + void HardwareInfo::FetchMemoryInfo() { - NAZARA_USE_ANONYMOUS_NAMESPACE - - // Nothing to do - s_initialized = false; + m_systemTotalMemory = HardwareInfoImpl::GetTotalMemory(); } } diff --git a/src/Nazara/Core/TaskScheduler.cpp b/src/Nazara/Core/TaskScheduler.cpp index a4d76bb84..a8585b0c3 100644 --- a/src/Nazara/Core/TaskScheduler.cpp +++ b/src/Nazara/Core/TaskScheduler.cpp @@ -3,8 +3,8 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include -#include #if defined(NAZARA_PLATFORM_WINDOWS) #include @@ -34,12 +34,12 @@ namespace Nz /*! * \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() { - return (s_workerCount > 0) ? s_workerCount : HardwareInfo::GetProcessorCount(); + return (s_workerCount > 0) ? s_workerCount : Core::Instance()->GetHardwareInfo().GetCpuThreadCount(); } /*! diff --git a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp index 9dadbea48..cb701f413 100644 --- a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp +++ b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp @@ -17,7 +17,7 @@ namespace Nz void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]) { #if defined(NAZARA_COMPILER_MSVC) - static_assert(sizeof(UInt32) == sizeof(int), "Assertion failed"); + static_assert(sizeof(UInt32) == sizeof(int)); // Use intrinsic function if available __cpuidex(reinterpret_cast(registers), static_cast(functionId), static_cast(subFunctionId)); diff --git a/xmake.lua b/xmake.lua index 4ba81f471..9a2a9f971 100644 --- a/xmake.lua +++ b/xmake.lua @@ -59,7 +59,7 @@ local modules = { add_syslinks("dl", "pthread") end end, - Packages = { "entt" }, + Packages = { "entt", "frozen" }, PublicPackages = { "nazarautils" } }, Graphics = {