1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef sw_Types_hpp
16 #define sw_Types_hpp
17
18 #include <limits>
19 #include <type_traits>
20
21 // GCC warns against bitfields not fitting the entire range of an enum with a fixed underlying type of unsigned int, which gets promoted to an error with -Werror and cannot be suppressed.
22 // However, GCC already defaults to using unsigned int as the underlying type of an unscoped enum without a fixed underlying type. So we can just omit it.
23 #if defined(__GNUC__) && !defined(__clang__)
24 namespace {
25 enum E
26 {
27 };
28 static_assert(!std::numeric_limits<std::underlying_type<E>::type>::is_signed, "expected unscoped enum whose underlying type is not fixed to be unsigned");
29 } // namespace
30 # define ENUM_UNDERLYING_TYPE_UNSIGNED_INT
31 #else
32 # define ENUM_UNDERLYING_TYPE_UNSIGNED_INT : unsigned int
33 #endif
34
35 #if defined(_MSC_VER)
36 typedef signed __int8 int8_t;
37 typedef signed __int16 int16_t;
38 typedef signed __int32 int32_t;
39 typedef signed __int64 int64_t;
40 typedef unsigned __int8 uint8_t;
41 typedef unsigned __int16 uint16_t;
42 typedef unsigned __int32 uint32_t;
43 typedef unsigned __int64 uint64_t;
44 # define ALIGN(bytes, type) __declspec(align(bytes)) type
45 #else
46 # include <stdint.h>
47 # define ALIGN(bytes, type) type __attribute__((aligned(bytes)))
48 #endif
49
50 namespace sw {
51
52 // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
bit_ceil(uint32_t i)53 constexpr inline uint32_t bit_ceil(uint32_t i)
54 {
55 i--;
56 i |= i >> 1;
57 i |= i >> 2;
58 i |= i >> 4;
59 i |= i >> 8;
60 i |= i >> 16;
61 i++;
62 return i;
63 }
64
65 typedef ALIGN(1, uint8_t) byte;
66 typedef ALIGN(2, uint16_t) word;
67 typedef ALIGN(4, uint32_t) dword;
68 typedef ALIGN(8, uint64_t) qword;
69 typedef ALIGN(1, int8_t) sbyte;
70
71 template<typename T, int N>
72 struct alignas(sizeof(T) * bit_ceil(N)) vec
73 {
74 vec() = default;
75
vecsw::vec76 constexpr explicit vec(T replicate)
77 {
78 for(int i = 0; i < N; i++)
79 {
80 v[i] = replicate;
81 }
82 }
83
84 template<typename... ARGS>
vecsw::vec85 constexpr vec(T arg0, ARGS... args)
86 : v{ arg0, args... }
87 {
88 }
89
90 // Require explicit use of replicate constructor.
91 vec &operator=(T) = delete;
92
operator []sw::vec93 T &operator[](int i)
94 {
95 return v[i];
96 }
97
operator []sw::vec98 const T &operator[](int i) const
99 {
100 return v[i];
101 }
102
103 T v[N];
104 };
105
106 template<typename T>
107 struct alignas(sizeof(T) * 4) vec<T, 4>
108 {
109 vec() = default;
110
vecsw::vec111 constexpr explicit vec(T replicate)
112 : x(replicate)
113 , y(replicate)
114 , z(replicate)
115 , w(replicate)
116 {
117 }
118
vecsw::vec119 constexpr vec(T x, T y, T z, T w)
120 : x(x)
121 , y(y)
122 , z(z)
123 , w(w)
124 {
125 }
126
127 // Require explicit use of replicate constructor.
128 vec &operator=(T) = delete;
129
operator []sw::vec130 T &operator[](int i)
131 {
132 return v[i];
133 }
134
operator []sw::vec135 const T &operator[](int i) const
136 {
137 return v[i];
138 }
139
140 union
141 {
142 T v[4];
143
144 struct
145 {
146 T x;
147 T y;
148 T z;
149 T w;
150 };
151 };
152 };
153
154 template<typename T, int N>
operator ==(const vec<T,N> & a,const vec<T,N> & b)155 bool operator==(const vec<T, N> &a, const vec<T, N> &b)
156 {
157 for(int i = 0; i < N; i++)
158 {
159 if(a.v[i] != b.v[i])
160 {
161 return false;
162 }
163 }
164
165 return true;
166 }
167
168 template<typename T, int N>
operator !=(const vec<T,N> & a,const vec<T,N> & b)169 bool operator!=(const vec<T, N> &a, const vec<T, N> &b)
170 {
171 return !(a == b);
172 }
173
174 template<typename T>
175 using vec2 = vec<T, 2>;
176 template<typename T>
177 using vec3 = vec<T, 3>; // aligned to 4 elements
178 template<typename T>
179 using vec4 = vec<T, 4>;
180 template<typename T>
181 using vec8 = vec<T, 8>;
182 template<typename T>
183 using vec16 = vec<T, 16>;
184
185 using int2 = vec2<int>;
186 using uint2 = vec2<unsigned int>;
187 using float2 = vec2<float>;
188 using dword2 = vec2<dword>;
189 using qword2 = vec2<qword>;
190
191 // Note: These vec3<T> types all use 4-element alignment - i.e. they have
192 // identical memory layout to vec4<T>, except they do not have a 4th component.
193 using int3 = vec3<int>;
194 using uint3 = vec3<unsigned int>;
195 using float3 = vec3<float>;
196 using dword3 = vec3<dword>;
197
198 using int4 = vec4<int>;
199 using uint4 = vec4<unsigned int>;
200 using float4 = vec4<float>;
201 using byte4 = vec4<byte>;
202 using sbyte4 = vec4<sbyte>;
203 using short4 = vec4<short>;
204 using ushort4 = vec4<unsigned short>;
205 using word4 = vec4<word>;
206 using dword4 = vec4<dword>;
207
208 using byte8 = vec8<byte>;
209 using sbyte8 = vec8<sbyte>;
210 using short8 = vec8<short>;
211 using ushort8 = vec8<unsigned short>;
212
213 using byte16 = vec16<byte>;
214 using sbyte16 = vec16<sbyte>;
215
vector(float x,float y,float z,float w)216 inline constexpr float4 vector(float x, float y, float z, float w)
217 {
218 return float4{ x, y, z, w };
219 }
220
replicate(float f)221 inline constexpr float4 replicate(float f)
222 {
223 return vector(f, f, f, f);
224 }
225
226 } // namespace sw
227
228 #endif // sw_Types_hpp
229