• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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