gallium: Enable ARM NEON CPU detection.
I wrote this code with reference to pixman, though I've only decided to cover Linux (what I'm testing) and Android (seems obvious enough). Linux has getauxval() as a cleaner interface to the /proc entry, but it's more glibc-specific and I didn't want to add detection for that. This will be used to enable NEON at runtime on ARMv6 builds of vc4. v2: Actually initialize the temp vars in the Android path (noticed by daniels) v3: Actually pull in the cpufeatures library (change by robher). Use O_CLOEXEC. Break out of the loop when we find our feature. v4: Drop VFP code, which was confused about what it was detecting and not actually used yet. Reviewed-by: Grazvydas Ignotas <notasas@gmail.com>
This commit is contained in:
@@ -48,6 +48,8 @@ endif
|
||||
LOCAL_MODULE := libmesa_gallium
|
||||
LOCAL_STATIC_LIBRARIES += libmesa_nir
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += cpufeatures
|
||||
|
||||
# generate sources
|
||||
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
|
||||
intermediates := $(call local-generated-sources-dir)
|
||||
|
@@ -59,12 +59,18 @@
|
||||
|
||||
#if defined(PIPE_OS_LINUX)
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
#endif
|
||||
|
||||
#ifdef PIPE_OS_UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(PIPE_OS_ANDROID)
|
||||
#include <cpu-features.h>
|
||||
#endif
|
||||
|
||||
#if defined(PIPE_OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#if defined(PIPE_CC_MSVC)
|
||||
@@ -294,6 +300,38 @@ PIPE_ALIGN_STACK static inline boolean sse2_has_daz(void)
|
||||
|
||||
#endif /* X86 or X86_64 */
|
||||
|
||||
#if defined(PIPE_ARCH_ARM)
|
||||
static void
|
||||
check_os_arm_support(void)
|
||||
{
|
||||
#if defined(PIPE_OS_ANDROID)
|
||||
AndroidCpuFamily cpu_family = android_getCpuFamily();
|
||||
uint64_t cpu_features = android_getCpuFeatures();
|
||||
|
||||
if (cpu_family == ANDROID_CPU_FAMILY_ARM) {
|
||||
if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)
|
||||
util_cpu_caps.has_neon = 1;
|
||||
}
|
||||
#elif defined(PIPE_OS_LINUX)
|
||||
Elf32_auxv_t aux;
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
while (read(fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) {
|
||||
if (aux.a_type == AT_HWCAP) {
|
||||
uint32_t hwcap = aux.a_un.a_val;
|
||||
|
||||
util_cpu_caps.has_neon = (hwcap >> 12) & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
#endif /* PIPE_OS_LINUX */
|
||||
}
|
||||
#endif /* PIPE_ARCH_ARM */
|
||||
|
||||
void
|
||||
util_cpu_detect(void)
|
||||
{
|
||||
@@ -443,6 +481,10 @@ util_cpu_detect(void)
|
||||
}
|
||||
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
|
||||
|
||||
#if defined(PIPE_ARCH_ARM)
|
||||
check_os_arm_support();
|
||||
#endif
|
||||
|
||||
#if defined(PIPE_ARCH_PPC)
|
||||
check_os_altivec_support();
|
||||
#endif /* PIPE_ARCH_PPC */
|
||||
@@ -471,6 +513,7 @@ util_cpu_detect(void)
|
||||
debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
|
||||
debug_printf("util_cpu_caps.has_xop = %u\n", util_cpu_caps.has_xop);
|
||||
debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
|
||||
debug_printf("util_cpu_caps.has_neon = %u\n", util_cpu_caps.has_neon);
|
||||
debug_printf("util_cpu_caps.has_daz = %u\n", util_cpu_caps.has_daz);
|
||||
debug_printf("util_cpu_caps.has_avx512f = %u\n", util_cpu_caps.has_avx512f);
|
||||
debug_printf("util_cpu_caps.has_avx512dq = %u\n", util_cpu_caps.has_avx512dq);
|
||||
|
@@ -72,6 +72,7 @@ struct util_cpu_caps {
|
||||
unsigned has_xop:1;
|
||||
unsigned has_altivec:1;
|
||||
unsigned has_daz:1;
|
||||
unsigned has_neon:1;
|
||||
|
||||
unsigned has_avx512f:1;
|
||||
unsigned has_avx512dq:1;
|
||||
|
Reference in New Issue
Block a user