• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkCpu_DEFINED
9 #define SkCpu_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 struct SkCpu {
14     enum {
15         SSE1       = 1 << 0,
16         SSE2       = 1 << 1,
17         SSE3       = 1 << 2,
18         SSSE3      = 1 << 3,
19         SSE41      = 1 << 4,
20         SSE42      = 1 << 5,
21         AVX        = 1 << 6,
22         F16C       = 1 << 7,
23         FMA        = 1 << 8,
24         AVX2       = 1 << 9,
25         BMI1       = 1 << 10,
26         BMI2       = 1 << 11,
27         // Handy alias for all the cool Haswell+ instructions.
28         HSW = AVX2 | BMI1 | BMI2 | F16C | FMA,
29 
30         AVX512F    = 1 << 12,
31         AVX512DQ   = 1 << 13,
32         AVX512IFMA = 1 << 14,
33         AVX512PF   = 1 << 15,
34         AVX512ER   = 1 << 16,
35         AVX512CD   = 1 << 17,
36         AVX512BW   = 1 << 18,
37         AVX512VL   = 1 << 19,
38 
39         // Handy alias for all the cool Skylake Xeon+ instructions.
40         SKX = AVX512F  | AVX512DQ | AVX512CD | AVX512BW | AVX512VL,
41 
42         ERMS       = 1 << 20,
43     };
44     enum {
45         NEON     = 1 << 0,
46         NEON_FMA = 1 << 1,
47         VFP_FP16 = 1 << 2,
48         CRC32    = 1 << 3,
49         ASIMDHP  = 1 << 4,
50     };
51 
52     static void CacheRuntimeFeatures();
53     static bool Supports(uint32_t);
54 private:
55     static uint32_t gCachedFeatures;
56 };
57 
Supports(uint32_t mask)58 inline bool SkCpu::Supports(uint32_t mask) {
59     uint32_t features = gCachedFeatures;
60 
61     // If we mask in compile-time known lower limits, the compiler can
62     // often compile away this entire function.
63 #if SK_CPU_X86
64     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
65     features |= SSE1;
66     #endif
67     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
68     features |= SSE2;
69     #endif
70     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3
71     features |= SSE3;
72     #endif
73     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
74     features |= SSSE3;
75     #endif
76     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
77     features |= SSE41;
78     #endif
79     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42
80     features |= SSE42;
81     #endif
82     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX
83     features |= AVX;
84     #endif
85     // F16C goes here if we add SK_CPU_SSE_LEVEL_F16C
86     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
87     features |= AVX2;
88     #endif
89     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
90     features |= (AVX512F | AVX512DQ | AVX512CD | AVX512BW | AVX512VL);
91     #endif
92     // FMA doesn't fit neatly into this total ordering.
93     // It's available on Haswell+ just like AVX2, but it's technically a different bit.
94     // TODO: circle back on this if we find ourselves limited by lack of compile-time FMA
95 
96     #if defined(SK_CPU_LIMIT_AVX)
97     features &= (SSE1 | SSE2 | SSE3 | SSSE3 | SSE41 | SSE42 | AVX);
98     #elif defined(SK_CPU_LIMIT_SSE41)
99     features &= (SSE1 | SSE2 | SSE3 | SSSE3 | SSE41);
100     #elif defined(SK_CPU_LIMIT_SSE2)
101     features &= (SSE1 | SSE2);
102     #endif
103 
104 #else
105     #if defined(SK_ARM_HAS_NEON)
106     features |= NEON;
107     #endif
108 
109     #if defined(SK_CPU_ARM64)
110     features |= NEON|NEON_FMA|VFP_FP16;
111     #endif
112 
113     #if defined(SK_ARM_HAS_CRC32)
114     features |= CRC32;
115     #endif
116 
117 #endif
118     return (features & mask) == mask;
119 }
120 
121 #endif//SkCpu_DEFINED
122