This adds an sse42 cpu check on startup for both linux and windows, mac has been excluded, since there are no intel based macs that do not support SSE42. The way this works is, we count on the OS to initialize the shared libraries in the order they are linked (which currently holds true) before calling the initialization code in the main executable. This allows us to check the CPU before running any of the code in the main executable that might not be supported by the current isa. Changing those build flags is for a future PR, but for now and for future reference: blender_cpu_check must be build without optimized CPU flags so it'll be able to run on older CPUs. some code has been duplicated from blenlib, there's really no way around that since we cannot link blenlib as it may be build with optimized cpu flags. Windows currently gives a popup to inform the user, while linux reports to the console, there may be better ways to communicate with linux users with perhaps some generic GUI popup, but I'm unaware of these and will leave this for the linux platform maintainer to polish. Part of #116592 Pull Request: https://projects.blender.org/blender/blender/pulls/118054
107 lines
2.4 KiB
C++
107 lines
2.4 KiB
C++
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup creator
|
|
*/
|
|
#include <string>
|
|
|
|
#if defined(WIN32)
|
|
# include <Windows.h>
|
|
# include <intrin.h>
|
|
#endif
|
|
|
|
/* The code below is duplicated from system.c from bf_blenlib. This is on purpose, since bf_blenlib
|
|
* may be build with CPU flags that are not available on the current cpu so we can't link it. */
|
|
|
|
#if !defined(_WIN32)
|
|
static void __cpuid(
|
|
/* Cannot be const, because it is modified below.
|
|
* NOLINTNEXTLINE: readability-non-const-parameter. */
|
|
int data[4],
|
|
int selector)
|
|
{
|
|
# if defined(__x86_64__)
|
|
asm("cpuid" : "=a"(data[0]), "=b"(data[1]), "=c"(data[2]), "=d"(data[3]) : "a"(selector));
|
|
# else
|
|
(void)selector;
|
|
data[0] = data[1] = data[2] = data[3] = 0;
|
|
# endif
|
|
}
|
|
#endif
|
|
|
|
static int cpu_supports_sse42(void)
|
|
{
|
|
int result[4], num;
|
|
__cpuid(result, 0);
|
|
num = result[0];
|
|
|
|
if (num >= 1) {
|
|
__cpuid(result, 0x00000001);
|
|
return (result[2] & ((int)1 << 20)) != 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const char *cpu_brand_string(void)
|
|
{
|
|
static char buf[49] = {0};
|
|
int result[4] = {0};
|
|
__cpuid(result, 0x80000000);
|
|
if (result[0] >= (int)0x80000004) {
|
|
__cpuid((int *)(buf + 0), 0x80000002);
|
|
__cpuid((int *)(buf + 16), 0x80000003);
|
|
__cpuid((int *)(buf + 32), 0x80000004);
|
|
const char *buf_ptr = buf;
|
|
// Trim any leading spaces.
|
|
while (*buf_ptr == ' ') {
|
|
buf_ptr++;
|
|
}
|
|
return buf_ptr;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
extern "C" __declspec(dllexport) void cpu_check_win32()
|
|
{
|
|
# ifdef _M_X64
|
|
if (!cpu_supports_sse42()) {
|
|
std::string error_title = "Unsupported CPU - " + std::string(cpu_brand_string());
|
|
MessageBoxA(NULL,
|
|
"Blender requires a CPU with SSE42 support.",
|
|
error_title.c_str(),
|
|
MB_OK | MB_ICONERROR);
|
|
exit(-1);
|
|
}
|
|
# endif
|
|
}
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE /* hinstDLL */, DWORD fdwReason, LPVOID /* lpvReserved */)
|
|
{
|
|
switch (fdwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
cpu_check_win32();
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#else
|
|
# include <cstdio>
|
|
# include <cstdlib>
|
|
|
|
static __attribute__((constructor)) void cpu_check(void)
|
|
{
|
|
# ifdef __x86_64
|
|
if (!cpu_supports_sse42()) {
|
|
std::string error = "Unsupported CPU - " + std::string(cpu_brand_string()) +
|
|
"\nBlender requires a CPU with SSE42 support.";
|
|
printf("%s\n", error.c_str());
|
|
exit(-1);
|
|
}
|
|
return;
|
|
# endif
|
|
}
|
|
#endif
|