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