VEX Engine
Retro looking game engine made in vulkan mostly because i wanted to understand it better.
Loading...
Searching...
No Matches
HardwareInfo.cpp
1#include "components/HardwareInfo.hpp"
2#include <sstream>
3#include <iomanip>
4#include <cstring>
5#include <vector>
6#include <algorithm>
7
8#ifdef _WIN32
9 #include <io.h>
10 #define WRITE_FUNC _write
11#else
12 #include <unistd.h>
13 #define WRITE_FUNC write
14#endif
15
16#define V_MAJOR(v) ((v) >> 22)
17#define V_MINOR(v) (((v) >> 12) & 0x3FF)
18#define V_PATCH(v) ((v) & 0xFFF)
19
20namespace vex {
21
22std::string HardwareInfo::CPUName = "";
23std::string HardwareInfo::SystemMemory = "";
24std::string HardwareInfo::GPUName = "Unknown GPU";
25std::string HardwareInfo::DriverVersion = "Unknown";
26std::string HardwareInfo::VulkanDeviceVersion = "0.0.0";
27std::string HardwareInfo::VulkanRequestedVersion = "0.0.0";
28VulkanFeatures HardwareInfo::GPUFeatures = {};
29
31 if (fd < 0) return;
32
33 auto safeWrite = [fd](const char* label, const std::string& val) {
34 if (!label) return;
35 WRITE_FUNC(fd, label, strlen(label));
36 if (!val.empty()) {
37 WRITE_FUNC(fd, val.c_str(), val.length());
38 } else {
39 WRITE_FUNC(fd, "Unknown", 7);
40 }
41 WRITE_FUNC(fd, "\n", 1);
42 };
43
44 auto safeWriteBool = [fd](const char* label, bool val) {
45 WRITE_FUNC(fd, label, strlen(label));
46 if (val) WRITE_FUNC(fd, "YES\n", 4);
47 else WRITE_FUNC(fd, "NO\n", 3);
48 };
49
50 const char* header = "\n=== SYSTEM INFO ===\n";
51 WRITE_FUNC(fd, header, strlen(header));
52
53 if(CPUName.empty()) DetectCPUName();
54 if(SystemMemory.empty()) DetectSystemMemory();
55
56 safeWrite("CPU: ", CPUName);
57 safeWrite("RAM: ", SystemMemory);
58 safeWriteBool("AVX2: ", HasAVX2());
59
60 safeWrite("GPU: ", GPUName);
61 safeWrite("Driver: ", DriverVersion);
62 safeWrite("Vulkan Device: ", VulkanDeviceVersion);
63 safeWrite("Vulkan Requested: ", VulkanRequestedVersion);
64
65 safeWriteBool("Feat: MultiDraw: ", GPUFeatures.multiDraw);
66 safeWriteBool("Feat: Indirect: ", GPUFeatures.indirectDraw);
67 safeWriteBool("Feat: Bindless: ", GPUFeatures.bindlessTextures);
68 safeWriteBool("Feat: Shader Params: ", GPUFeatures.shaderDrawParameters);
69}
70
71static std::string decodeDriverVersion(uint32_t vendorID, uint32_t v) {
72 if (vendorID == 0x10DE) {
73 int major = (v >> 22) & 0x3FF;
74 int minor = (v >> 14) & 0xFF;
75 int sub = (v >> 6) & 0xFF;
76 int patch = v & 0x3F;
77 std::stringstream ss;
78 ss << major << "." << minor << "." << sub << "." << patch;
79 return ss.str();
80 }
81
82#if defined(_WIN32)
83 if (vendorID == 0x8086) {
84 int major = (v >> 14);
85 int minor = v & 0x3FFF;
86 std::stringstream ss;
87 ss << major << "." << minor;
88 return ss.str();
89 }
90#endif
91
92 std::stringstream ss;
93 ss << V_MAJOR(v) << "." << V_MINOR(v) << "." << V_PATCH(v);
94 return ss.str();
95}
96
97void HardwareInfo::SetGPUInfo(const std::string& name, uint32_t vendorID, uint32_t driverVersion) {
98 GPUName = name;
99 DriverVersion = decodeDriverVersion(vendorID, driverVersion);
100}
101std::string HardwareInfo::GetGPUName() { return GPUName; }
102std::string HardwareInfo::GetDriverVersion() { return DriverVersion; }
103
104void HardwareInfo::SetVulkanVersions(const std::string& deviceVer, const std::string& requestedVer) {
105 VulkanDeviceVersion = deviceVer;
106 VulkanRequestedVersion = requestedVer;
107}
108std::string HardwareInfo::GetVulkanDeviceVersion() { return VulkanDeviceVersion; }
109std::string HardwareInfo::GetVulkanRequestedVersion() { return VulkanRequestedVersion; }
110
112 GPUFeatures = features;
113}
115
117 if (CPUName.empty()) DetectCPUName();
118 return CPUName;
119}
120
122 if (SystemMemory.empty()) DetectSystemMemory();
123 return SystemMemory;
124}
125
126void HardwareInfo::DetectCPUName() {
127 int info[4] = { -1 };
128 char brand[0x40];
129 memset(brand, 0, sizeof(brand));
130
131 CpuId(info, 0x80000000);
132 unsigned int nExIds = info[0];
133
134 if (nExIds >= 0x80000004) {
135 std::vector<int> cpuIds;
136 for (int i = 0x80000002; i <= 0x80000004; ++i) {
137 CpuId(info, i);
138 cpuIds.push_back(info[0]);
139 cpuIds.push_back(info[1]);
140 cpuIds.push_back(info[2]);
141 cpuIds.push_back(info[3]);
142 }
143 memcpy(brand, cpuIds.data(), sizeof(brand));
144 CPUName = std::string(brand);
145 } else {
146 CPUName = "Generic x86 CPU";
147 }
148
149 CPUName.erase(CPUName.find_last_not_of(' ') + 1);
150 CPUName.erase(0, CPUName.find_first_not_of(' '));
151}
152
153void HardwareInfo::DetectSystemMemory() {
154 uint64_t totalRam = 0;
155#ifdef _WIN32
156 MEMORYSTATUSEX status;
157 status.dwLength = sizeof(status);
158 GlobalMemoryStatusEx(&status);
159 totalRam = status.ullTotalPhys;
160#else
161 long pages = sysconf(_SC_PHYS_PAGES);
162 long pageSize = sysconf(_SC_PAGE_SIZE);
163 totalRam = pages * pageSize;
164#endif
165
166 double gb = static_cast<double>(totalRam) / (1024.0 * 1024.0 * 1024.0);
167 std::stringstream ss;
168 if (gb >= 1.0) {
169 ss << std::fixed << std::setprecision(1) << gb << " GB";
170 } else {
171 ss << (totalRam / (1024 * 1024)) << " MB";
172 }
173 SystemMemory = ss.str();
174}
175
176bool HardwareInfo::CheckHardwareSupport() {
177 int info[4];
178 CpuId(info, 1);
179
180 bool osUsesXsaveXrstore = (info[2] & (1 << 27)) != 0;
181 bool cpuHasAVX = (info[2] & (1 << 28)) != 0;
182
183 if (!osUsesXsaveXrstore || !cpuHasAVX) return false;
184
185 unsigned long long xcrFeatureMask = 0;
186 #ifdef _MSC_VER
187 xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
188 #else
189 __asm__ ("xgetbv" : "=A" (xcrFeatureMask) : "c" (0));
190 #endif
191
192 if ((xcrFeatureMask & 0x6) != 0x6) return false;
193
194 CpuId(info, 7);
195 bool cpuHasAVX2 = (info[1] & (1 << 5)) != 0;
196
197 return cpuHasAVX2;
198}
199
201 static bool supported = CheckHardwareSupport();
202 return supported;
203}
204
205} // namespace vex
static std::string GetVulkanDeviceVersion()
Retrieves the Vulkan version supported by the device.
static std::string GetCPUName()
Retrieves the name of the CPU.
static void SetVulkanVersions(const std::string &deviceVer, const std::string &requestedVer)
Sets the Vulkan API versions.
static bool HasAVX2()
Checks if the CPU supports the AVX2 instruction set.
static std::string GetVulkanRequestedVersion()
Retrieves the Vulkan version requested by the engine.
static void SetVulkanFeatures(const VulkanFeatures &features)
Sets the active Vulkan features.
static void SetGPUInfo(const std::string &name, uint32_t vendorID, uint32_t driverVersion)
Sets the stored GPU information.
static void PrintCrashDump(int fd)
Prints hardware information to a crash dump file descriptor.
static VulkanFeatures GetVulkanFeatures()
Retrieves the active Vulkan features.
static std::string GetGPUName()
Retrieves the name of the GPU.
static std::string GetDriverVersion()
Retrieves the GPU driver version.
static std::string GetSystemMemory()
Retrieves the total amount of system memory.
Holds the status of various Vulkan features.