• 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 <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