Limit convolution processing to the output ambisonic order
[openal-soft.git] / alc / cpu_caps.cpp
bloba480f77b58dc6d14593ec01d2242f51468249d84
2 #include "config.h"
4 #include "cpu_caps.h"
6 #ifdef HAVE_INTRIN_H
7 #include <intrin.h>
8 #endif
9 #ifdef HAVE_CPUID_H
10 #include <cpuid.h>
11 #endif
13 #include <cctype>
14 #include <string>
16 #include "alfstream.h"
17 #include "logging.h"
20 int CPUCapFlags{0};
22 namespace {
24 #if defined(HAVE_GCC_GET_CPUID) \
25 && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
26 using reg_type = unsigned int;
27 inline void get_cpuid(unsigned int f, reg_type *regs)
28 { __get_cpuid(f, &regs[0], &regs[1], &regs[2], &regs[3]); }
29 #define CAN_GET_CPUID
30 #elif defined(HAVE_CPUID_INTRINSIC) \
31 && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
32 using reg_type = int;
33 inline void get_cpuid(unsigned int f, reg_type *regs)
34 { (__cpuid)(regs, f); }
35 #define CAN_GET_CPUID
36 #endif
38 } // namespace
41 void FillCPUCaps(int capfilter)
43 int caps{0};
45 /* FIXME: We really should get this for all available CPUs in case different
46 * CPUs have different caps (is that possible on one machine?).
48 #ifdef CAN_GET_CPUID
49 union {
50 reg_type regs[4];
51 char str[sizeof(reg_type[4])];
52 } cpuinf[3]{};
54 get_cpuid(0, cpuinf[0].regs);
55 if(cpuinf[0].regs[0] == 0)
56 ERR("Failed to get CPUID\n");
57 else
59 const reg_type maxfunc{cpuinf[0].regs[0]};
61 get_cpuid(0x80000000, cpuinf[0].regs);
62 const reg_type maxextfunc{cpuinf[0].regs[0]};
64 TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc);
66 TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8);
67 if(maxextfunc >= 0x80000004)
69 get_cpuid(0x80000002, cpuinf[0].regs);
70 get_cpuid(0x80000003, cpuinf[1].regs);
71 get_cpuid(0x80000004, cpuinf[2].regs);
72 TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str);
75 if(maxfunc >= 1)
77 get_cpuid(1, cpuinf[0].regs);
78 if((cpuinf[0].regs[3]&(1<<25)))
79 caps |= CPU_CAP_SSE;
80 if((caps&CPU_CAP_SSE) && (cpuinf[0].regs[3]&(1<<26)))
81 caps |= CPU_CAP_SSE2;
82 if((caps&CPU_CAP_SSE2) && (cpuinf[0].regs[2]&(1<<0)))
83 caps |= CPU_CAP_SSE3;
84 if((caps&CPU_CAP_SSE3) && (cpuinf[0].regs[2]&(1<<19)))
85 caps |= CPU_CAP_SSE4_1;
88 #else
89 /* Assume support for whatever's supported if we can't check for it */
90 #if defined(HAVE_SSE4_1)
91 #warning "Assuming SSE 4.1 run-time support!"
92 caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
93 #elif defined(HAVE_SSE3)
94 #warning "Assuming SSE 3 run-time support!"
95 caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
96 #elif defined(HAVE_SSE2)
97 #warning "Assuming SSE 2 run-time support!"
98 caps |= CPU_CAP_SSE | CPU_CAP_SSE2;
99 #elif defined(HAVE_SSE)
100 #warning "Assuming SSE run-time support!"
101 caps |= CPU_CAP_SSE;
102 #endif
103 #endif
105 #ifdef HAVE_NEON
106 #ifdef __ARM_NEON
107 caps |= CPU_CAP_NEON;
108 #else
109 al::ifstream file{"/proc/cpuinfo"};
110 if(!file.is_open())
111 ERR("Failed to open /proc/cpuinfo, cannot check for NEON support\n");
112 else
114 std::string features;
116 auto getline = [](std::istream &f, std::string &output) -> bool
118 while(f.good() && f.peek() == '\n')
119 f.ignore();
120 return std::getline(f, output) && !output.empty();
122 while(getline(file, features))
124 if(features.compare(0, 10, "Features\t:", 10) == 0)
125 break;
127 file.close();
129 size_t extpos{9};
130 while((extpos=features.find("neon", extpos+1)) != std::string::npos)
132 if(std::isspace(features[extpos-1])
133 && (extpos+4 == features.length() || std::isspace(features[extpos+4])))
135 caps |= CPU_CAP_NEON;
136 break;
139 if(!(caps&CPU_CAP_NEON))
141 extpos = 9;
142 while((extpos=features.find("asimd", extpos+1)) != std::string::npos)
144 if(std::isspace(features[extpos-1])
145 && (extpos+5 == features.length() || std::isspace(features[extpos+5])))
147 caps |= CPU_CAP_NEON;
148 break;
153 #endif
154 #endif
156 TRACE("Extensions:%s%s%s%s%s%s\n",
157 ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""),
158 ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""),
159 ((capfilter&CPU_CAP_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""),
160 ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
161 ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +NEON" : " -NEON") : ""),
162 ((!capfilter) ? " -none-" : "")
164 CPUCapFlags = caps & capfilter;