1 /*
2  Copyright (c) 2013 yvt
3 
4  This file is part of OpenSpades.
5 
6  OpenSpades is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OpenSpades is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OpenSpades.  If not, see <http://www.gnu.org/licenses/>.
18 
19  */
20 
21 #pragma once
22 
23 #include <Core/CpuID.h>
24 
25 #if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)
26 #if defined(_MSC_VER)
27 // MSVC 2013 doesn't define __SSE__?
28 #define ENABLE_MMX 0
29 #define ENABLE_SSE 1
30 #define ENABLE_SSE2 1
31 #else
32 #define ENABLE_MMX 0 // FIXME: move this to the proper place
33 #ifdef __SSE__
34 #define ENABLE_SSE 1 // FIXME: move this to the proper place
35 #endif
36 #ifdef __SSE2__
37 #define ENABLE_SSE2 1 // FIXME: move this to the proper place
38 #endif
39 #endif
40 #endif
41 
42 #ifndef ENABLE_SSE
43 #define ENABLE_SSE 0
44 #endif
45 
46 #ifndef ENABLE_SSE2
47 #define ENABLE_SSE2 0
48 #endif
49 
50 #if ENABLE_SSE
51 #include <xmmintrin.h>
52 #endif
53 #if ENABLE_SSE2
54 #include <emmintrin.h>
55 #endif
56 
57 #include <Core/ConcurrentDispatch.h>
58 #include <Core/Debug.h>
59 #include <algorithm>
60 #include <cmath>
61 
62 // X11 macro
63 #undef None
64 
65 namespace spades {
66 	namespace draw {
67 		enum class SWFeatureLevel {
68 			None,
69 #if ENABLE_MMX
70 			MMX,
71 #endif
72 #if ENABLE_SSE
73 			SSE,
74 #endif
75 #if ENABLE_SSE2
76 			SSE2,
77 #endif
78 		};
79 
80 		static inline bool operator>(SWFeatureLevel a, SWFeatureLevel b) {
81 			return static_cast<int>(a) > static_cast<int>(b);
82 		}
83 		static inline bool operator>=(SWFeatureLevel a, SWFeatureLevel b) {
84 			return static_cast<int>(a) >= static_cast<int>(b);
85 		}
86 
87 		SWFeatureLevel DetectFeatureLevel();
88 
89 #if ENABLE_SSE // assume SSE availability (no checks!)
fastDiv(float a,float b)90 		static inline float fastDiv(float a, float b) {
91 			union {
92 				float tmp;
93 				__m128 mtmp;
94 			};
95 			tmp = b;
96 			mtmp = _mm_rcp_ss(mtmp);
97 			return a * tmp;
98 		}
fastRcp(float b)99 		static inline float fastRcp(float b) {
100 			union {
101 				float tmp;
102 				__m128 mtmp;
103 			};
104 			tmp = b;
105 			mtmp = _mm_rcp_ss(mtmp);
106 			return tmp;
107 		}
fastRSqrt(float v)108 		static inline float fastRSqrt(float v) {
109 			union {
110 				float tmp;
111 				__m128 mtmp;
112 			};
113 			tmp = v;
114 			mtmp = _mm_rsqrt_ss(mtmp);
115 			return tmp;
116 		}
117 #else
fastDiv(float a,float b)118 		static inline float fastDiv(float a, float b) { return a / b; }
fastRcp(float b)119 		static inline float fastRcp(float b) { return 1.f / b; }
fastRSqrt(float b)120 		static inline float fastRSqrt(float b) { return 1.f / sqrtf(b); }
121 #endif
fastSqrt(float s)122 		static inline float fastSqrt(float s) {
123 			if (s == 0.f)
124 				return 0.f;
125 			return s * fastRSqrt(s);
126 		}
127 	}
128 }
129