Files
test2/source/creator/creator_cpu_check.cc
Ray Molenkamp 0326b29899 Creator: Add CPU check on startup
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
2024-02-19 18:11:57 +01:00

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