SkCpu.h 3.0 KB

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