diff options
Diffstat (limited to 'thirdparty/astcenc/astcenc_platform_isa_detection.cpp')
-rw-r--r-- | thirdparty/astcenc/astcenc_platform_isa_detection.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/thirdparty/astcenc/astcenc_platform_isa_detection.cpp b/thirdparty/astcenc/astcenc_platform_isa_detection.cpp new file mode 100644 index 0000000000..8ed98437ea --- /dev/null +++ b/thirdparty/astcenc/astcenc_platform_isa_detection.cpp @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2020-2022 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +/** + * @brief Platform-specific function implementations. + * + * This module contains functions for querying the host extended ISA support. + */ + +// Include before the defines below to pick up any auto-setup based on compiler +// built-in config, if not being set explicitly by the build system +#include "astcenc_internal.h" + +#if (ASTCENC_SSE > 0) || (ASTCENC_AVX > 0) || \ + (ASTCENC_POPCNT > 0) || (ASTCENC_F16C > 0) + +static bool g_init { false }; + +/** Does this CPU support SSE 4.1? Set to -1 if not yet initialized. */ +static bool g_cpu_has_sse41 { false }; + +/** Does this CPU support AVX2? Set to -1 if not yet initialized. */ +static bool g_cpu_has_avx2 { false }; + +/** Does this CPU support POPCNT? Set to -1 if not yet initialized. */ +static bool g_cpu_has_popcnt { false }; + +/** Does this CPU support F16C? Set to -1 if not yet initialized. */ +static bool g_cpu_has_f16c { false }; + +/* ============================================================================ + Platform code for Visual Studio +============================================================================ */ +#if !defined(__clang__) && defined(_MSC_VER) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <intrin.h> + +/** + * @brief Detect platform CPU ISA support and update global trackers. + */ +static void detect_cpu_isa() +{ + int data[4]; + + __cpuid(data, 0); + int num_id = data[0]; + + if (num_id >= 1) + { + __cpuidex(data, 1, 0); + // SSE41 = Bank 1, ECX, bit 19 + g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false; + // POPCNT = Bank 1, ECX, bit 23 + g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false; + // F16C = Bank 1, ECX, bit 29 + g_cpu_has_f16c = data[2] & (1 << 29) ? true : false; + } + + if (num_id >= 7) + { + __cpuidex(data, 7, 0); + // AVX2 = Bank 7, EBX, bit 5 + g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false; + } + + // Ensure state bits are updated before init flag is updated + MemoryBarrier(); + g_init = true; +} + +/* ============================================================================ + Platform code for GCC and Clang +============================================================================ */ +#else +#include <cpuid.h> + +/** + * @brief Detect platform CPU ISA support and update global trackers. + */ +static void detect_cpu_isa() +{ + unsigned int data[4]; + + if (__get_cpuid_count(1, 0, &data[0], &data[1], &data[2], &data[3])) + { + // SSE41 = Bank 1, ECX, bit 19 + g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false; + // POPCNT = Bank 1, ECX, bit 23 + g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false; + // F16C = Bank 1, ECX, bit 29 + g_cpu_has_f16c = data[2] & (1 << 29) ? true : false; + } + + g_cpu_has_avx2 = 0; + if (__get_cpuid_count(7, 0, &data[0], &data[1], &data[2], &data[3])) + { + // AVX2 = Bank 7, EBX, bit 5 + g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false; + } + + // Ensure state bits are updated before init flag is updated + __sync_synchronize(); + g_init = true; +} +#endif + +/* See header for documentation. */ +bool cpu_supports_popcnt() +{ + if (!g_init) + { + detect_cpu_isa(); + } + + return g_cpu_has_popcnt; +} + +/* See header for documentation. */ +bool cpu_supports_f16c() +{ + if (!g_init) + { + detect_cpu_isa(); + } + + return g_cpu_has_f16c; +} + +/* See header for documentation. */ +bool cpu_supports_sse41() +{ + if (!g_init) + { + detect_cpu_isa(); + } + + return g_cpu_has_sse41; +} + +/* See header for documentation. */ +bool cpu_supports_avx2() +{ + if (!g_init) + { + detect_cpu_isa(); + } + + return g_cpu_has_avx2; +} + +#endif |