Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/sys/sysinfo.cpp
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#if defined(__INTEL_LLVM_COMPILER)
5
// prevents "'__thiscall' calling convention is not supported for this target" warning from TBB
6
#pragma clang diagnostic push
7
#pragma clang diagnostic ignored "-Wignored-attributes"
8
#endif
9
10
#include "sysinfo.h"
11
#include "intrinsics.h"
12
#include "estring.h"
13
#include "ref.h"
14
#if defined(__FREEBSD__)
15
#include <sys/cpuset.h>
16
#include <pthread_np.h>
17
typedef cpuset_t cpu_set_t;
18
#endif
19
20
////////////////////////////////////////////////////////////////////////////////
21
/// All Platforms
22
////////////////////////////////////////////////////////////////////////////////
23
24
namespace embree
25
{
26
NullTy null;
27
28
std::string getPlatformName()
29
{
30
#if defined(__ANDROID__) && !defined(__64BIT__)
31
return "Android (32bit)";
32
#elif defined(__ANDROID__) && defined(__64BIT__)
33
return "Android (64bit)";
34
#elif defined(__LINUX__) && !defined(__64BIT__)
35
return "Linux (32bit)";
36
#elif defined(__LINUX__) && defined(__64BIT__)
37
return "Linux (64bit)";
38
#elif defined(__FREEBSD__) && !defined(__64BIT__)
39
return "FreeBSD (32bit)";
40
#elif defined(__FREEBSD__) && defined(__64BIT__)
41
return "FreeBSD (64bit)";
42
#elif defined(__CYGWIN__) && !defined(__64BIT__)
43
return "Cygwin (32bit)";
44
#elif defined(__CYGWIN__) && defined(__64BIT__)
45
return "Cygwin (64bit)";
46
#elif defined(__WIN32__) && !defined(__64BIT__)
47
return "Windows (32bit)";
48
#elif defined(__WIN32__) && defined(__64BIT__)
49
return "Windows (64bit)";
50
#elif defined(__MACOSX__) && !defined(__64BIT__)
51
return "Mac OS X (32bit)";
52
#elif defined(__MACOSX__) && defined(__64BIT__)
53
return "Mac OS X (64bit)";
54
#elif defined(__UNIX__) && !defined(__64BIT__)
55
return "Unix (32bit)";
56
#elif defined(__UNIX__) && defined(__64BIT__)
57
return "Unix (64bit)";
58
#else
59
return "Unknown";
60
#endif
61
}
62
63
std::string getCompilerName()
64
{
65
#if defined(__INTEL_COMPILER)
66
int icc_mayor = __INTEL_COMPILER / 100 % 100;
67
int icc_minor = __INTEL_COMPILER % 100;
68
std::string version = "Intel Compiler ";
69
version += toString(icc_mayor);
70
version += "." + toString(icc_minor);
71
#if defined(__INTEL_COMPILER_UPDATE)
72
version += "." + toString(__INTEL_COMPILER_UPDATE);
73
#endif
74
return version;
75
#elif defined(__clang__)
76
return "CLANG " __clang_version__;
77
#elif defined (__GNUC__)
78
return "GCC " __VERSION__;
79
#elif defined(_MSC_VER)
80
std::string version = toString(_MSC_FULL_VER);
81
version.insert(4,".");
82
version.insert(9,".");
83
version.insert(2,".");
84
return "Visual C++ Compiler " + version;
85
#else
86
return "Unknown Compiler";
87
#endif
88
}
89
90
std::string getCPUVendor()
91
{
92
#if defined(__X86_ASM__)
93
int cpuinfo[4];
94
__cpuid (cpuinfo, 0);
95
int name[4];
96
name[0] = cpuinfo[1];
97
name[1] = cpuinfo[3];
98
name[2] = cpuinfo[2];
99
name[3] = 0;
100
return (char*)name;
101
#elif defined(__ARM_NEON)
102
return "ARM";
103
#else
104
return "Unknown";
105
#endif
106
}
107
108
CPU getCPUModel()
109
{
110
#if defined(__X86_ASM__)
111
if (getCPUVendor() != "GenuineIntel")
112
return CPU::UNKNOWN;
113
114
int out[4];
115
__cpuid(out, 0);
116
if (out[0] < 1) return CPU::UNKNOWN;
117
__cpuid(out, 1);
118
119
/* please see CPUID documentation for these formulas */
120
uint32_t family_ID = (out[0] >> 8) & 0x0F;
121
uint32_t extended_family_ID = (out[0] >> 20) & 0xFF;
122
123
uint32_t model_ID = (out[0] >> 4) & 0x0F;
124
uint32_t extended_model_ID = (out[0] >> 16) & 0x0F;
125
126
uint32_t DisplayFamily = family_ID;
127
if (family_ID == 0x0F)
128
DisplayFamily += extended_family_ID;
129
130
uint32_t DisplayModel = model_ID;
131
if (family_ID == 0x06 || family_ID == 0x0F)
132
DisplayModel += extended_model_ID << 4;
133
134
uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0);
135
136
// Data from IntelĀ® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel)
137
if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE;
138
if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE;
139
if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE;
140
if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE;
141
if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE;
142
if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE;
143
if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE;
144
if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE;
145
if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE;
146
if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE;
147
if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE;
148
if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE;
149
if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE;
150
if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL;
151
if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL;
152
if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL;
153
if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL;
154
if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL;
155
if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL;
156
if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL;
157
if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL;
158
if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE;
159
if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE;
160
if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE;
161
if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE;
162
if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE;
163
if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM;
164
if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM;
165
if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM;
166
if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM;
167
if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM;
168
if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM;
169
if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM;
170
if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2;
171
if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2;
172
if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1;
173
174
if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL;
175
if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING;
176
177
#elif defined(__ARM_NEON)
178
return CPU::ARM;
179
#endif
180
181
return CPU::UNKNOWN;
182
}
183
184
std::string stringOfCPUModel(CPU model)
185
{
186
switch (model) {
187
case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake";
188
case CPU::CORE_ICE_LAKE : return "Core Ice Lake";
189
case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake";
190
case CPU::CORE_COMET_LAKE : return "Core Comet Lake";
191
case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake";
192
case CPU::CORE_KABY_LAKE : return "Core Kaby Lake";
193
case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake";
194
case CPU::CORE_SKY_LAKE : return "Core Sky Lake";
195
case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill";
196
case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing";
197
case CPU::XEON_BROADWELL : return "Xeon Broadwell";
198
case CPU::CORE_BROADWELL : return "Core Broadwell";
199
case CPU::XEON_HASWELL : return "Xeon Haswell";
200
case CPU::CORE_HASWELL : return "Core Haswell";
201
case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge";
202
case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge";
203
case CPU::SANDY_BRIDGE : return "Sandy Bridge";
204
case CPU::NEHALEM : return "Nehalem";
205
case CPU::CORE2 : return "Core2";
206
case CPU::CORE1 : return "Core";
207
case CPU::ARM : return "ARM";
208
case CPU::UNKNOWN : return "Unknown CPU";
209
}
210
return "Unknown CPU (error)";
211
}
212
213
#if defined(__X86_ASM__)
214
/* constants to access destination registers of CPUID instruction */
215
static const int EAX = 0;
216
static const int EBX = 1;
217
static const int ECX = 2;
218
static const int EDX = 3;
219
220
/* cpuid[eax=1].ecx */
221
static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;
222
static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;
223
static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;
224
static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;
225
static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;
226
//static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;
227
static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;
228
//static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;
229
static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;
230
static const int CPU_FEATURE_BIT_AVX = 1 << 28;
231
static const int CPU_FEATURE_BIT_F16C = 1 << 29;
232
static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;
233
234
/* cpuid[eax=1].edx */
235
static const int CPU_FEATURE_BIT_SSE = 1 << 25;
236
static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;
237
238
/* cpuid[eax=0x80000001].ecx */
239
static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;
240
241
/* cpuid[eax=7,ecx=0].ebx */
242
static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;
243
static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;
244
static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;
245
static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)
246
static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)
247
static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)
248
static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)
249
static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)
250
static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)
251
static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)
252
static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)
253
254
/* cpuid[eax=7,ecx=0].ecx */
255
static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)
256
#endif
257
258
#if defined(__X86_ASM__)
259
__noinline int64_t get_xcr0()
260
{
261
#if defined (__WIN32__) && !defined (__MINGW32__) && defined(_XCR_XFEATURE_ENABLED_MASK)
262
int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
263
xcr0 = _xgetbv(0);
264
return xcr0;
265
#else
266
int xcr0 = 0;
267
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
268
return xcr0;
269
#endif
270
}
271
#endif
272
273
int getCPUFeatures()
274
{
275
#if defined(__X86_ASM__)
276
/* cache CPU features access */
277
static int cpu_features = 0;
278
if (cpu_features)
279
return cpu_features;
280
281
/* get number of CPUID leaves */
282
int cpuid_leaf0[4];
283
__cpuid(cpuid_leaf0, 0x00000000);
284
unsigned nIds = cpuid_leaf0[EAX];
285
286
/* get number of extended CPUID leaves */
287
int cpuid_leafe[4];
288
__cpuid(cpuid_leafe, 0x80000000);
289
unsigned nExIds = cpuid_leafe[EAX];
290
291
/* get CPUID leaves for EAX = 1,7, and 0x80000001 */
292
int cpuid_leaf_1[4] = { 0,0,0,0 };
293
int cpuid_leaf_7[4] = { 0,0,0,0 };
294
int cpuid_leaf_e1[4] = { 0,0,0,0 };
295
if (nIds >= 1) __cpuid (cpuid_leaf_1,0x00000001);
296
#if _WIN32
297
#if _MSC_VER && (_MSC_FULL_VER < 160040219)
298
#elif defined(_MSC_VER)
299
if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);
300
#endif
301
#else
302
if (nIds >= 7) __cpuid_count(cpuid_leaf_7,0x00000007,0);
303
#endif
304
if (nExIds >= 0x80000001) __cpuid(cpuid_leaf_e1,0x80000001);
305
306
/* detect if OS saves XMM, YMM, and ZMM states */
307
bool xmm_enabled = true;
308
bool ymm_enabled = false;
309
bool zmm_enabled = false;
310
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {
311
int64_t xcr0 = get_xcr0();
312
xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */
313
ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */
314
zmm_enabled = ymm_enabled && ((xcr0 & 0xE0) == 0xE0); /* checks if OPMASK state, upper 256-bit of ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled in XCR0 */
315
}
316
if (xmm_enabled) cpu_features |= CPU_FEATURE_XMM_ENABLED;
317
if (ymm_enabled) cpu_features |= CPU_FEATURE_YMM_ENABLED;
318
if (zmm_enabled) cpu_features |= CPU_FEATURE_ZMM_ENABLED;
319
320
if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;
321
if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;
322
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;
323
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;
324
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;
325
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;
326
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;
327
328
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;
329
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;
330
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;
331
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;
332
if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;
333
if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;
334
if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;
335
if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;
336
337
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;
338
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;
339
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;
340
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;
341
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;
342
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;
343
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;
344
if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;
345
if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
346
347
#if defined(__MACOSX__)
348
if ( (cpu_features & CPU_FEATURE_AVX512F)
349
|| (cpu_features & CPU_FEATURE_AVX512DQ)
350
|| (cpu_features & CPU_FEATURE_AVX512CD)
351
|| (cpu_features & CPU_FEATURE_AVX512BW)
352
|| (cpu_features & CPU_FEATURE_AVX512VL) )
353
{
354
// on macOS AVX512 will be enabled automatically by the kernel when the first AVX512 instruction is called
355
// see https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L176
356
// therefore we ignore the state of XCR0
357
cpu_features |= CPU_FEATURE_ZMM_ENABLED;
358
}
359
#endif
360
return cpu_features;
361
362
#elif defined(__ARM_NEON) || defined(__EMSCRIPTEN__)
363
364
int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2;
365
cpu_features |= CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3|CPU_FEATURE_SSE42;
366
cpu_features |= CPU_FEATURE_XMM_ENABLED;
367
cpu_features |= CPU_FEATURE_YMM_ENABLED;
368
cpu_features |= CPU_FEATURE_SSE41 | CPU_FEATURE_RDRAND | CPU_FEATURE_F16C;
369
cpu_features |= CPU_FEATURE_POPCNT;
370
cpu_features |= CPU_FEATURE_AVX;
371
cpu_features |= CPU_FEATURE_AVX2;
372
cpu_features |= CPU_FEATURE_FMA3;
373
cpu_features |= CPU_FEATURE_LZCNT;
374
cpu_features |= CPU_FEATURE_BMI1;
375
cpu_features |= CPU_FEATURE_BMI2;
376
cpu_features |= CPU_FEATURE_NEON_2X;
377
return cpu_features;
378
379
#else
380
/* Unknown CPU. */
381
return 0;
382
#endif
383
}
384
385
std::string stringOfCPUFeatures(int features)
386
{
387
std::string str;
388
if (features & CPU_FEATURE_XMM_ENABLED) str += "XMM ";
389
if (features & CPU_FEATURE_YMM_ENABLED) str += "YMM ";
390
if (features & CPU_FEATURE_ZMM_ENABLED) str += "ZMM ";
391
if (features & CPU_FEATURE_SSE ) str += "SSE ";
392
if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";
393
if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";
394
if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";
395
if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";
396
if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";
397
if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";
398
if (features & CPU_FEATURE_AVX ) str += "AVX ";
399
if (features & CPU_FEATURE_F16C ) str += "F16C ";
400
if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";
401
if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";
402
if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";
403
if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";
404
if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";
405
if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";
406
if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";
407
if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";
408
if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";
409
if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";
410
if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";
411
if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";
412
if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
413
if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
414
if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
415
if (features & CPU_FEATURE_NEON) str += "NEON ";
416
if (features & CPU_FEATURE_NEON_2X) str += "2xNEON ";
417
return str;
418
}
419
420
std::string stringOfISA (int isa)
421
{
422
if (isa == SSE) return "SSE";
423
if (isa == SSE2) return "SSE2";
424
if (isa == SSE3) return "SSE3";
425
if (isa == SSSE3) return "SSSE3";
426
if (isa == SSE41) return "SSE4.1";
427
if (isa == SSE42) return "SSE4.2";
428
if (isa == AVX) return "AVX";
429
if (isa == AVX2) return "AVX2";
430
if (isa == AVX512) return "AVX512";
431
432
if (isa == NEON) return "NEON";
433
if (isa == NEON_2X) return "2xNEON";
434
return "UNKNOWN";
435
}
436
437
bool hasISA(int features, int isa) {
438
return (features & isa) == isa;
439
}
440
441
std::string supportedTargetList (int features)
442
{
443
std::string v;
444
if (hasISA(features,SSE)) v += "SSE ";
445
if (hasISA(features,SSE2)) v += "SSE2 ";
446
if (hasISA(features,SSE3)) v += "SSE3 ";
447
if (hasISA(features,SSSE3)) v += "SSSE3 ";
448
if (hasISA(features,SSE41)) v += "SSE4.1 ";
449
if (hasISA(features,SSE42)) v += "SSE4.2 ";
450
if (hasISA(features,AVX)) v += "AVX ";
451
if (hasISA(features,AVXI)) v += "AVXI ";
452
if (hasISA(features,AVX2)) v += "AVX2 ";
453
if (hasISA(features,AVX512)) v += "AVX512 ";
454
455
if (hasISA(features,NEON)) v += "NEON ";
456
if (hasISA(features,NEON_2X)) v += "2xNEON ";
457
return v;
458
}
459
}
460
461
////////////////////////////////////////////////////////////////////////////////
462
/// Windows Platform
463
////////////////////////////////////////////////////////////////////////////////
464
465
#if defined(__WIN32__)
466
467
#define WIN32_LEAN_AND_MEAN
468
#include <windows.h>
469
#include <psapi.h>
470
471
namespace embree
472
{
473
std::string getExecutableFileName() {
474
char filename[1024];
475
if (!GetModuleFileName(nullptr, filename, sizeof(filename)))
476
return std::string();
477
return std::string(filename);
478
}
479
480
unsigned int getNumberOfLogicalThreads()
481
{
482
static int nThreads = -1;
483
if (nThreads != -1) return nThreads;
484
485
typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
486
typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
487
HMODULE hlib = LoadLibrary("Kernel32");
488
GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
489
GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");
490
491
if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)
492
{
493
int groups = pGetActiveProcessorGroupCount();
494
int totalProcessors = 0;
495
for (int i = 0; i < groups; i++)
496
totalProcessors += pGetActiveProcessorCount(i);
497
nThreads = totalProcessors;
498
}
499
else
500
{
501
SYSTEM_INFO sysinfo;
502
GetSystemInfo(&sysinfo);
503
nThreads = sysinfo.dwNumberOfProcessors;
504
}
505
assert(nThreads);
506
return nThreads;
507
}
508
509
int getTerminalWidth()
510
{
511
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
512
if (handle == INVALID_HANDLE_VALUE) return 80;
513
CONSOLE_SCREEN_BUFFER_INFO info;
514
memset(&info,0,sizeof(info));
515
GetConsoleScreenBufferInfo(handle, &info);
516
return info.dwSize.X;
517
}
518
519
double getSeconds()
520
{
521
LARGE_INTEGER freq, val;
522
QueryPerformanceFrequency(&freq);
523
QueryPerformanceCounter(&val);
524
return (double)val.QuadPart / (double)freq.QuadPart;
525
}
526
527
void sleepSeconds(double t) {
528
Sleep(DWORD(1000.0*t));
529
}
530
531
size_t getVirtualMemoryBytes()
532
{
533
PROCESS_MEMORY_COUNTERS info;
534
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
535
return (size_t)info.QuotaPeakPagedPoolUsage;
536
}
537
538
size_t getResidentMemoryBytes()
539
{
540
PROCESS_MEMORY_COUNTERS info;
541
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
542
return (size_t)info.WorkingSetSize;
543
}
544
}
545
#endif
546
547
////////////////////////////////////////////////////////////////////////////////
548
/// Linux Platform
549
////////////////////////////////////////////////////////////////////////////////
550
551
#if defined(__LINUX__)
552
553
#include <stdio.h>
554
#include <unistd.h>
555
556
namespace embree
557
{
558
std::string getExecutableFileName()
559
{
560
std::string pid = "/proc/" + toString(getpid()) + "/exe";
561
char buf[4096];
562
memset(buf,0,sizeof(buf));
563
if (readlink(pid.c_str(), buf, sizeof(buf)-1) == -1)
564
return std::string();
565
return std::string(buf);
566
}
567
568
size_t getVirtualMemoryBytes()
569
{
570
size_t virt, resident, shared;
571
std::ifstream buffer("/proc/self/statm");
572
buffer >> virt >> resident >> shared;
573
return virt*sysconf(_SC_PAGE_SIZE);
574
}
575
576
size_t getResidentMemoryBytes()
577
{
578
size_t virt, resident, shared;
579
std::ifstream buffer("/proc/self/statm");
580
buffer >> virt >> resident >> shared;
581
return resident*sysconf(_SC_PAGE_SIZE);
582
}
583
}
584
585
#endif
586
587
////////////////////////////////////////////////////////////////////////////////
588
/// FreeBSD Platform
589
////////////////////////////////////////////////////////////////////////////////
590
591
#if defined (__FreeBSD__)
592
593
#include <sys/sysctl.h>
594
595
namespace embree
596
{
597
std::string getExecutableFileName()
598
{
599
const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
600
char buf[4096];
601
memset(buf,0,sizeof(buf));
602
size_t len = sizeof(buf)-1;
603
if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1)
604
return std::string();
605
return std::string(buf);
606
}
607
608
size_t getVirtualMemoryBytes() {
609
return 0;
610
}
611
612
size_t getResidentMemoryBytes() {
613
return 0;
614
}
615
}
616
617
#endif
618
619
////////////////////////////////////////////////////////////////////////////////
620
/// Mac OS X Platform
621
////////////////////////////////////////////////////////////////////////////////
622
623
#if defined(__MACOSX__)
624
625
#include <mach-o/dyld.h>
626
627
namespace embree
628
{
629
std::string getExecutableFileName()
630
{
631
char buf[4096];
632
uint32_t size = sizeof(buf);
633
if (_NSGetExecutablePath(buf, &size) != 0)
634
return std::string();
635
return std::string(buf);
636
}
637
638
size_t getVirtualMemoryBytes() {
639
return 0;
640
}
641
642
size_t getResidentMemoryBytes() {
643
return 0;
644
}
645
}
646
647
#endif
648
649
////////////////////////////////////////////////////////////////////////////////
650
/// Unix Platform
651
////////////////////////////////////////////////////////////////////////////////
652
653
#if defined(__UNIX__)
654
655
#include <unistd.h>
656
#include <sys/ioctl.h>
657
#include <sys/time.h>
658
#include <pthread.h>
659
660
#if defined(__EMSCRIPTEN__)
661
#include <emscripten.h>
662
663
extern "C" {
664
extern int godot_js_os_hw_concurrency_get();
665
}
666
#endif
667
668
namespace embree
669
{
670
unsigned int getNumberOfLogicalThreads()
671
{
672
static int nThreads = -1;
673
if (nThreads != -1) return nThreads;
674
675
#if defined(__MACOSX__) || defined(__ANDROID__)
676
nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
677
assert(nThreads);
678
#elif defined(__EMSCRIPTEN__)
679
nThreads = godot_js_os_hw_concurrency_get();
680
#if 0
681
// WebAssembly supports pthreads, but not pthread_getaffinity_np. Get the number of logical
682
// threads from the browser or Node.js using JavaScript.
683
nThreads = MAIN_THREAD_EM_ASM_INT({
684
const isBrowser = typeof window !== 'undefined';
685
const isNode = typeof process !== 'undefined' && process.versions != null &&
686
process.versions.node != null;
687
if (isBrowser) {
688
// Return 1 if the browser does not expose hardwareConcurrency.
689
return window.navigator.hardwareConcurrency || 1;
690
} else if (isNode) {
691
return require('os').cpus().length;
692
} else {
693
return 1;
694
}
695
});
696
#endif
697
#else
698
cpu_set_t set;
699
if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)
700
nThreads = CPU_COUNT(&set);
701
#endif
702
703
assert(nThreads);
704
return nThreads;
705
}
706
707
int getTerminalWidth()
708
{
709
struct winsize info;
710
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;
711
return info.ws_col;
712
}
713
714
double getSeconds() {
715
struct timeval tp; gettimeofday(&tp,nullptr);
716
return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
717
}
718
719
void sleepSeconds(double t) {
720
usleep(1000000.0*t);
721
}
722
}
723
#endif
724
725
#if defined(__INTEL_LLVM_COMPILER)
726
#pragma clang diagnostic pop
727
#endif
728
729