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 <cassert>
19 #include <limits>
20 #include <type_traits>
21
22 // 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.
23 // 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.
24 #if defined(__GNUC__) && !defined(__clang__)
25 namespace {
26 enum E
27 {
28 };
29 static_assert(!std::numeric_limits<std::underlying_type<E>::type>::is_signed, "expected unscoped enum whose underlying type is not fixed to be unsigned");
30 } // namespace
31 # define ENUM_UNDERLYING_TYPE_UNSIGNED_INT
32 #else
33 # define ENUM_UNDERLYING_TYPE_UNSIGNED_INT : unsigned int
34 #endif
35
36 #if defined(_MSC_VER)
37 typedef signed __int8 int8_t;
38 typedef signed __int16 int16_t;
39 typedef signed __int32 int32_t;
40 typedef signed __int64 int64_t;
41 typedef unsigned __int8 uint8_t;
42 typedef unsigned __int16 uint16_t;
43 typedef unsigned __int32 uint32_t;
44 typedef unsigned __int64 uint64_t;
45 # define ALIGN(bytes, type) __declspec(align(bytes)) type
46 #else
47 # include <stdint.h>
48 # define ALIGN(bytes, type) type __attribute__((aligned(bytes)))
49 #endif
50
51 namespace sw {
52
53 // assert_cast<> is like a static_cast<> which asserts that no information was lost.
54 template<typename To, typename From>
assert_cast(From x)55 To assert_cast(From x)
56 {
57 To y = static_cast<To>(x);
58 assert(static_cast<From>(y) == x);
59
60 return y;
61 }
62
63 // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
bit_ceil(uint32_t i)64 constexpr inline uint32_t bit_ceil(uint32_t i)
65 {
66 i--;
67 i |= i >> 1;
68 i |= i >> 2;
69 i |= i >> 4;
70 i |= i >> 8;
71 i |= i >> 16;
72 i++;
73 return i;
74 }
75
76 typedef ALIGN(1, uint8_t) byte;
77 typedef ALIGN(2, uint16_t) word;
78 typedef ALIGN(4, uint32_t) dword;
79 typedef ALIGN(8, uint64_t) qword;
80 typedef ALIGN(1, int8_t) sbyte;
81
82 template<typename T, int N>
83 struct alignas(sizeof(T) * bit_ceil(N)) vec
84 {
85 vec() = default;
86
vecsw::vec87 constexpr explicit vec(T replicate)
88 {
89 for(int i = 0; i < N; i++)
90 {
91 v[i] = replicate;
92 }
93 }
94
95 template<typename... ARGS>
vecsw::vec96 constexpr vec(T arg0, ARGS... args)
97 : v{ arg0, args... }
98 {
99 }
100
101 // Require explicit use of replicate constructor.
102 vec &operator=(T) = delete;
103
operator []sw::vec104 T &operator[](int i)
105 {
106 return v[i];
107 }
108
operator []sw::vec109 const T &operator[](int i) const
110 {
111 return v[i];
112 }
113
114 T v[N];
115 };
116
117 template<typename T>
118 struct alignas(sizeof(T) * 4) vec<T, 4>
119 {
120 vec() = default;
121
vecsw::vec122 constexpr explicit vec(T replicate)
123 : x(replicate)
124 , y(replicate)
125 , z(replicate)
126 , w(replicate)
127 {
128 }
129
vecsw::vec130 constexpr vec(T x, T y, T z, T w)
131 : x(x)
132 , y(y)
133 , z(z)
134 , w(w)
135 {
136 }
137
138 // Require explicit use of replicate constructor.
139 vec &operator=(T) = delete;
140
operator []sw::vec141 T &operator[](int i)
142 {
143 return v[i];
144 }
145
operator []sw::vec146 const T &operator[](int i) const
147 {
148 return v[i];
149 }
150
151 union
152 {
153 T v[4];
154
155 struct
156 {
157 T x;
158 T y;
159 T z;
160 T w;
161 };
162 };
163 };
164
165 template<typename T, int N>
operator ==(const vec<T,N> & a,const vec<T,N> & b)166 bool operator==(const vec<T, N> &a, const vec<T, N> &b)
167 {
168 for(int i = 0; i < N; i++)
169 {
170 if(a.v[i] != b.v[i])
171 {
172 return false;
173 }
174 }
175
176 return true;
177 }
178
179 template<typename T, int N>
operator !=(const vec<T,N> & a,const vec<T,N> & b)180 bool operator!=(const vec<T, N> &a, const vec<T, N> &b)
181 {
182 return !(a == b);
183 }
184
185 template<typename T>
186 using vec2 = vec<T, 2>;
187 template<typename T>
188 using vec3 = vec<T, 3>; // aligned to 4 elements
189 template<typename T>
190 using vec4 = vec<T, 4>;
191 template<typename T>
192 using vec8 = vec<T, 8>;
193 template<typename T>
194 using vec16 = vec<T, 16>;
195
196 using int2 = vec2<int>;
197 using uint2 = vec2<unsigned int>;
198 using float2 = vec2<float>;
199 using dword2 = vec2<dword>;
200 using qword2 = vec2<qword>;
201
202 // Note: These vec3<T> types all use 4-element alignment - i.e. they have
203 // identical memory layout to vec4<T>, except they do not have a 4th component.
204 using int3 = vec3<int>;
205 using uint3 = vec3<unsigned int>;
206 using float3 = vec3<float>;
207 using dword3 = vec3<dword>;
208
209 using int4 = vec4<int>;
210 using uint4 = vec4<unsigned int>;
211 using float4 = vec4<float>;
212 using byte4 = vec4<byte>;
213 using sbyte4 = vec4<sbyte>;
214 using short4 = vec4<short>;
215 using ushort4 = vec4<unsigned short>;
216 using word4 = vec4<word>;
217 using dword4 = vec4<dword>;
218
219 using byte8 = vec8<byte>;
220 using sbyte8 = vec8<sbyte>;
221 using short8 = vec8<short>;
222 using ushort8 = vec8<unsigned short>;
223
224 using byte16 = vec16<byte>;
225 using sbyte16 = vec16<sbyte>;
226
vector(float x,float y,float z,float w)227 inline constexpr float4 vector(float x, float y, float z, float w)
228 {
229 return float4{ x, y, z, w };
230 }
231
replicate(float f)232 inline constexpr float4 replicate(float f)
233 {
234 return vector(f, f, f, f);
235 }
236
237 } // namespace sw
238
239 #endif // sw_Types_hpp
240