Blender V4.3
system.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "util/system.h"
6
7#include "util/log.h"
8#include "util/string.h"
9#include "util/types.h"
10
11#include <OpenImageIO/sysutil.h>
12
13OIIO_NAMESPACE_USING
14
15#ifdef _WIN32
16# if (!defined(FREE_WINDOWS))
17# include <intrin.h>
18# endif
19# include "util/windows.h"
20#elif defined(__APPLE__)
21# include <sys/ioctl.h>
22# include <sys/sysctl.h>
23# include <sys/types.h>
24# include <unistd.h>
25#else
26# include <sys/ioctl.h>
27# include <unistd.h>
28#endif
29
31
33{
34 int columns = 0;
35
36#ifdef _WIN32
37 CONSOLE_SCREEN_BUFFER_INFO csbi;
38 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
39 columns = csbi.dwSize.X;
40 }
41#else
42 struct winsize w;
43 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
44 columns = w.ws_col;
45 }
46#endif
47
48 return (columns > 0) ? columns : 80;
49}
50
51/* Equivalent of Windows __cpuid for x86 processors on other platforms. */
52#if (!defined(_WIN32) || defined(FREE_WINDOWS)) && (defined(__x86_64__) || defined(__i386__))
53static void __cpuid(int data[4], int selector)
54{
55# if defined(__x86_64__)
56 asm("cpuid" : "=a"(data[0]), "=b"(data[1]), "=c"(data[2]), "=d"(data[3]) : "a"(selector));
57# elif defined(__i386__)
58 asm("pushl %%ebx \n\t"
59 "cpuid \n\t"
60 "movl %%ebx, %1 \n\t"
61 "popl %%ebx \n\t"
62 : "=a"(data[0]), "=r"(data[1]), "=c"(data[2]), "=d"(data[3])
63 : "a"(selector)
64 : "ebx");
65# else
66 data[0] = data[1] = data[2] = data[3] = 0;
67# endif
68}
69#endif
70
72{
73#if defined(__APPLE__)
74 /* Get from system on macOS. */
75 char modelname[512] = "";
76 size_t bufferlen = 512;
77 if (sysctlbyname("machdep.cpu.brand_string", &modelname, &bufferlen, NULL, 0) == 0) {
78 return modelname;
79 }
80#elif (defined(WIN32) || defined(__x86_64__) || defined(__i386__)) && !defined(_M_ARM64)
81 /* Get from intrinsics on Windows and x86. */
82 char buf[49] = {0};
83 int result[4] = {0};
84
85 __cpuid(result, 0x80000000);
86
87 if (result[0] != 0 && result[0] >= (int)0x80000004) {
88 __cpuid((int *)(buf + 0), 0x80000002);
89 __cpuid((int *)(buf + 16), 0x80000003);
90 __cpuid((int *)(buf + 32), 0x80000004);
91
92 string brand = buf;
93
94 /* Make it a bit more presentable. */
95 brand = string_remove_trademark(brand);
96
97 return brand;
98 }
99#elif defined(_M_ARM64)
100 DWORD processorNameStringLength = 255;
101 char processorNameString[255];
102 if (RegGetValueA(HKEY_LOCAL_MACHINE,
103 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
104 "ProcessorNameString",
105 RRF_RT_REG_SZ,
106 nullptr,
107 &processorNameString,
108 &processorNameStringLength) == ERROR_SUCCESS)
109 {
110 return processorNameString;
111 }
112#else
113 /* Get from /proc/cpuinfo on Unix systems. */
114 FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
115 if (cpuinfo != nullptr) {
116 char cpuinfo_buf[513] = "";
117 fread(cpuinfo_buf, sizeof(cpuinfo_buf) - 1, 1, cpuinfo);
118 fclose(cpuinfo);
119
120 char *modelname = strstr(cpuinfo_buf, "model name");
121 if (modelname != nullptr) {
122 modelname = strchr(modelname, ':');
123 if (modelname != nullptr) {
124 modelname += 2;
125 char *modelname_end = strchr(modelname, '\n');
126 if (modelname_end != nullptr) {
127 *modelname_end = '\0';
128 return modelname;
129 }
130 }
131 }
132 }
133#endif
134 return "Unknown CPU";
135}
136
138{
139 return (sizeof(void *) * 8);
140}
141
142#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
143
144struct CPUCapabilities {
145 bool sse42;
146 bool avx2;
147};
148
149static CPUCapabilities &system_cpu_capabilities()
150{
151 static CPUCapabilities caps = {};
152 static bool caps_init = false;
153
154 if (!caps_init) {
155 int result[4], num;
156
157 __cpuid(result, 0);
158 num = result[0];
159
160 if (num >= 1) {
161 __cpuid(result, 0x00000001);
162 const bool sse = (result[3] & ((int)1 << 25)) != 0;
163 const bool sse2 = (result[3] & ((int)1 << 26)) != 0;
164 const bool sse3 = (result[2] & ((int)1 << 0)) != 0;
165
166 const bool ssse3 = (result[2] & ((int)1 << 9)) != 0;
167 const bool sse41 = (result[2] & ((int)1 << 19)) != 0;
168 const bool sse42 = (result[2] & ((int)1 << 20)) != 0;
169
170 const bool fma3 = (result[2] & ((int)1 << 12)) != 0;
171 const bool os_uses_xsave_xrestore = (result[2] & ((int)1 << 27)) != 0;
172 const bool cpu_avx_support = (result[2] & ((int)1 << 28)) != 0;
173
174 /* Simplify to combined capabilities for which we specialize kernels. */
175 caps.sse42 = sse && sse2 && sse3 && ssse3 && sse41 && sse42;
176
177 if (os_uses_xsave_xrestore && cpu_avx_support) {
178 // Check if the OS will save the YMM registers
179 uint32_t xcr_feature_mask;
180# if defined(__GNUC__)
181 int edx; /* not used */
182 /* actual opcode for xgetbv */
183 __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr_feature_mask), "=d"(edx) : "c"(0));
184# elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
185 /* Minimum VS2010 SP1 compiler is required. */
186 xcr_feature_mask = (uint32_t)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
187# else
188 xcr_feature_mask = 0;
189# endif
190 const bool avx = (xcr_feature_mask & 0x6) == 0x6;
191 const bool f16c = (result[2] & ((int)1 << 29)) != 0;
192
193 __cpuid(result, 0x00000007);
194 bool bmi1 = (result[1] & ((int)1 << 3)) != 0;
195 bool bmi2 = (result[1] & ((int)1 << 8)) != 0;
196 bool avx2 = (result[1] & ((int)1 << 5)) != 0;
197
198 caps.avx2 = sse && sse2 && sse3 && ssse3 && sse41 && sse42 && avx && f16c && avx2 &&
199 fma3 && bmi1 && bmi2;
200 }
201 }
202
203 caps_init = true;
204 }
205
206 return caps;
207}
208
210{
211 CPUCapabilities &caps = system_cpu_capabilities();
212 return caps.sse42;
213}
214
216{
217 CPUCapabilities &caps = system_cpu_capabilities();
218 return caps.avx2;
219}
220#else
221
223{
224 return false;
225}
226
228{
229 return false;
230}
231
232#endif
233
235{
236#ifdef _WIN32
237 MEMORYSTATUSEX ram;
238 ram.dwLength = sizeof(ram);
239 GlobalMemoryStatusEx(&ram);
240 return ram.ullTotalPhys;
241#elif defined(__APPLE__)
242 uint64_t ram = 0;
243 size_t len = sizeof(ram);
244 if (sysctlbyname("hw.memsize", &ram, &len, NULL, 0) == 0) {
245 return ram;
246 }
247 return 0;
248#else
249 size_t ps = sysconf(_SC_PAGESIZE);
250 size_t pn = sysconf(_SC_PHYS_PAGES);
251 return ps * pn;
252#endif
253}
254
256{
257#ifdef _WIN32
258 return GetCurrentProcessId();
259#else
260 return getpid();
261#endif
262}
263
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define CCL_NAMESPACE_END
#define NULL
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90
string string_remove_trademark(const string &s)
Definition string.cpp:155
static void __cpuid(int data[4], int selector)
Definition system.c:105
size_t system_physical_ram()
Definition system.cpp:234
bool system_cpu_support_avx2()
Definition system.cpp:227
int system_cpu_bits()
Definition system.cpp:137
bool system_cpu_support_sse42()
Definition system.cpp:222
OIIO_NAMESPACE_USING CCL_NAMESPACE_BEGIN int system_console_width()
Definition system.cpp:32
string system_cpu_brand_string()
Definition system.cpp:71
uint64_t system_self_process_id()
Definition system.cpp:255