[Mesa-dev] [PATCH 1/2] gallium: Enable ARM NEON/VFP CPU detection.

Eric Anholt eric at anholt.net
Thu Apr 13 18:56:24 UTC 2017


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.
---
 src/gallium/auxiliary/util/u_cpu_detect.c | 46 +++++++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_cpu_detect.h |  2 ++
 2 files changed, 48 insertions(+)

diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index 845fc6b34d5c..fa123f78a526 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.c
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -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,40 @@ 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;
+   uint64_t cpu_features;
+
+   if (cpu_family == ANDROID_CPU_FAMILY_ARM) {
+      if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFPv3)
+         util_cpu_caps.has_vfp = 1;
+      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);
+    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_vfp = (hwcap >> 6) & 1;
+             util_cpu_caps.has_neon = (hwcap >> 12) & 1;
+          }
+       }
+       close (fd);
+    }
+#endif /* PIPE_OS_LINUX */
+}
+#endif /* PIPE_ARCH_ARM */
+
 void
 util_cpu_detect(void)
 {
@@ -443,6 +483,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 +515,8 @@ 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_vfp = %u\n", util_cpu_caps.has_vfp);
       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);
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.h b/src/gallium/auxiliary/util/u_cpu_detect.h
index 3bd7294f0759..de7fcdfa0cbe 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.h
+++ b/src/gallium/auxiliary/util/u_cpu_detect.h
@@ -72,6 +72,8 @@ struct util_cpu_caps {
    unsigned has_xop:1;
    unsigned has_altivec:1;
    unsigned has_daz:1;
+   unsigned has_neon:1;
+   unsigned has_vfp:1;
 
    unsigned has_avx512f:1;
    unsigned has_avx512dq:1;
-- 
2.11.0



More information about the mesa-dev mailing list