1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * @brief Utilities used by SWR core.
27 ******************************************************************************/
31 #include <type_traits>
33 #include "common/os.h"
34 #include "common/intrin.h"
35 #include "common/swr_assert.h"
46 #if ENABLE_AVX512_SIMD16
57 // helper function to unroll loops
58 template<int Begin
, int End
, int Step
= 1>
60 template<typename Lambda
>
61 INLINE
static void step(Lambda
& func
) {
63 UnrollerL
<Begin
+ Step
, End
, Step
>::step(func
);
67 template<int End
, int Step
>
68 struct UnrollerL
<End
, End
, Step
> {
69 template<typename Lambda
>
70 static void step(Lambda
& func
) {
74 // helper function to unroll loops, with mask to skip specific iterations
75 template<int Begin
, int End
, int Step
= 1, int Mask
= 0x7f>
76 struct UnrollerLMask
{
77 template<typename Lambda
>
78 INLINE
static void step(Lambda
& func
) {
79 if(Mask
& (1 << Begin
))
83 UnrollerL
<Begin
+ Step
, End
, Step
>::step(func
);
87 template<int End
, int Step
, int Mask
>
88 struct UnrollerLMask
<End
, End
, Step
, Mask
> {
89 template<typename Lambda
>
90 static void step(Lambda
& func
) {
94 // general CRC compute
96 uint32_t ComputeCRC(uint32_t crc
, const void *pData
, uint32_t size
)
98 #if defined(_WIN64) || defined(__x86_64__)
99 uint32_t sizeInQwords
= size
/ sizeof(uint64_t);
100 uint32_t sizeRemainderBytes
= size
% sizeof(uint64_t);
101 uint64_t* pDataWords
= (uint64_t*)pData
;
102 for (uint32_t i
= 0; i
< sizeInQwords
; ++i
)
104 crc
= (uint32_t)_mm_crc32_u64(crc
, *pDataWords
++);
107 uint32_t sizeInDwords
= size
/ sizeof(uint32_t);
108 uint32_t sizeRemainderBytes
= size
% sizeof(uint32_t);
109 uint32_t* pDataWords
= (uint32_t*)pData
;
110 for (uint32_t i
= 0; i
< sizeInDwords
; ++i
)
112 crc
= _mm_crc32_u32(crc
, *pDataWords
++);
116 uint8_t* pRemainderBytes
= (uint8_t*)pDataWords
;
117 for (uint32_t i
= 0; i
< sizeRemainderBytes
; ++i
)
119 crc
= _mm_crc32_u8(crc
, *pRemainderBytes
++);
125 //////////////////////////////////////////////////////////////////////////
126 /// Check specified bit within a data word
127 //////////////////////////////////////////////////////////////////////////
128 template <typename T
>
130 static bool CheckBit(T word
, uint32_t bit
)
132 return 0 != (word
& (T(1) << bit
));
135 //////////////////////////////////////////////////////////////////////////
136 /// Add byte offset to any-type pointer
137 //////////////////////////////////////////////////////////////////////////
138 template <typename T
>
140 static T
* PtrAdd(T
* p
, intptr_t offset
)
142 intptr_t intp
= reinterpret_cast<intptr_t>(p
);
143 return reinterpret_cast<T
*>(intp
+ offset
);
146 //////////////////////////////////////////////////////////////////////////
148 //////////////////////////////////////////////////////////////////////////
149 template <typename T
>
151 static bool IsPow2(T value
)
153 return value
== (value
& (T(0) - value
));
156 //////////////////////////////////////////////////////////////////////////
157 /// Align down to specified alignment
158 /// Note: IsPow2(alignment) MUST be true
159 //////////////////////////////////////////////////////////////////////////
160 template <typename T1
, typename T2
>
162 static T1
AlignDownPow2(T1 value
, T2 alignment
)
164 SWR_ASSERT(IsPow2(alignment
));
165 return value
& ~T1(alignment
- 1);
168 //////////////////////////////////////////////////////////////////////////
169 /// Align up to specified alignment
170 /// Note: IsPow2(alignment) MUST be true
171 //////////////////////////////////////////////////////////////////////////
172 template <typename T1
, typename T2
>
174 static T1
AlignUpPow2(T1 value
, T2 alignment
)
176 return AlignDownPow2(value
+ T1(alignment
- 1), alignment
);
179 //////////////////////////////////////////////////////////////////////////
180 /// Align up ptr to specified alignment
181 /// Note: IsPow2(alignment) MUST be true
182 //////////////////////////////////////////////////////////////////////////
183 template <typename T1
, typename T2
>
185 static T1
* AlignUpPow2(T1
* value
, T2 alignment
)
187 return reinterpret_cast<T1
*>(
188 AlignDownPow2(reinterpret_cast<uintptr_t>(value
) + uintptr_t(alignment
- 1), alignment
));
191 //////////////////////////////////////////////////////////////////////////
192 /// Align down to specified alignment
193 //////////////////////////////////////////////////////////////////////////
194 template <typename T1
, typename T2
>
196 static T1
AlignDown(T1 value
, T2 alignment
)
198 if (IsPow2(alignment
)) { return AlignDownPow2(value
, alignment
); }
199 return value
- T1(value
% alignment
);
202 //////////////////////////////////////////////////////////////////////////
203 /// Align down to specified alignment
204 //////////////////////////////////////////////////////////////////////////
205 template <typename T1
, typename T2
>
207 static T1
* AlignDown(T1
* value
, T2 alignment
)
209 return (T1
*)AlignDown(uintptr_t(value
), alignment
);
212 //////////////////////////////////////////////////////////////////////////
213 /// Align up to specified alignment
214 /// Note: IsPow2(alignment) MUST be true
215 //////////////////////////////////////////////////////////////////////////
216 template <typename T1
, typename T2
>
218 static T1
AlignUp(T1 value
, T2 alignment
)
220 return AlignDown(value
+ T1(alignment
- 1), alignment
);
223 //////////////////////////////////////////////////////////////////////////
224 /// Align up to specified alignment
225 /// Note: IsPow2(alignment) MUST be true
226 //////////////////////////////////////////////////////////////////////////
227 template <typename T1
, typename T2
>
229 static T1
* AlignUp(T1
* value
, T2 alignment
)
231 return AlignDown(PtrAdd(value
, alignment
- 1), alignment
);
234 //////////////////////////////////////////////////////////////////////////
235 /// Helper structure used to access an array of elements that don't
236 /// correspond to a typical word size.
237 //////////////////////////////////////////////////////////////////////////
238 template<typename T
, size_t BitsPerElementT
, size_t ArrayLenT
>
242 static const size_t BITS_PER_WORD
= sizeof(size_t) * 8;
243 static const size_t ELEMENTS_PER_WORD
= BITS_PER_WORD
/ BitsPerElementT
;
244 static const size_t NUM_WORDS
= (ArrayLenT
+ ELEMENTS_PER_WORD
- 1) / ELEMENTS_PER_WORD
;
245 static const size_t ELEMENT_MASK
= (size_t(1) << BitsPerElementT
) - 1;
247 static_assert(ELEMENTS_PER_WORD
* BitsPerElementT
== BITS_PER_WORD
,
248 "Element size must an integral fraction of pointer size");
250 size_t m_words
[NUM_WORDS
] = {};
254 T
operator[] (size_t elementIndex
) const
256 size_t word
= m_words
[elementIndex
/ ELEMENTS_PER_WORD
];
257 word
>>= ((elementIndex
% ELEMENTS_PER_WORD
) * BitsPerElementT
);
258 return T(word
& ELEMENT_MASK
);
262 // Ranged integer argument for TemplateArgUnroller
263 template <uint32_t TMin
, uint32_t TMax
>
269 // Recursive template used to auto-nest conditionals. Converts dynamic boolean function
270 // arguments to static template arguments.
271 template <typename TermT
, typename
... ArgsB
>
272 struct TemplateArgUnroller
274 //-----------------------------------------
276 //-----------------------------------------
278 // Last Arg Terminator
279 static typename
TermT::FuncType
GetFunc(bool bArg
)
283 return TermT::template GetFunc
<ArgsB
..., std::true_type
>();
286 return TermT::template GetFunc
<ArgsB
..., std::false_type
>();
289 // Recursively parse args
290 template <typename
... TArgsT
>
291 static typename
TermT::FuncType
GetFunc(bool bArg
, TArgsT
... remainingArgs
)
295 return TemplateArgUnroller
<TermT
, ArgsB
..., std::true_type
>::GetFunc(remainingArgs
...);
298 return TemplateArgUnroller
<TermT
, ArgsB
..., std::false_type
>::GetFunc(remainingArgs
...);
301 //-----------------------------------------
302 // Integer value (within specified range)
303 //-----------------------------------------
305 // Last Arg Terminator
306 template <uint32_t TMin
, uint32_t TMax
>
307 static typename
TermT::FuncType
GetFunc(IntArg
<TMin
, TMax
> iArg
)
309 if (iArg
.val
== TMax
)
311 return TermT::template GetFunc
<ArgsB
..., std::integral_constant
<uint32_t, TMax
>>();
315 return TemplateArgUnroller
<TermT
, ArgsB
...>::GetFunc(IntArg
<TMin
, TMax
-1>{iArg
.val
});
317 SWR_ASSUME(false); return nullptr;
319 template <uint32_t TVal
>
320 static typename
TermT::FuncType
GetFunc(IntArg
<TVal
, TVal
> iArg
)
322 SWR_ASSERT(iArg
.val
== TVal
);
323 return TermT::template GetFunc
<ArgsB
..., std::integral_constant
<uint32_t, TVal
>>();
326 // Recursively parse args
327 template <uint32_t TMin
, uint32_t TMax
, typename
... TArgsT
>
328 static typename
TermT::FuncType
GetFunc(IntArg
<TMin
, TMax
> iArg
, TArgsT
... remainingArgs
)
330 if (iArg
.val
== TMax
)
332 return TemplateArgUnroller
<TermT
, ArgsB
..., std::integral_constant
<uint32_t, TMax
>>::GetFunc(remainingArgs
...);
336 return TemplateArgUnroller
<TermT
, ArgsB
...>::GetFunc(IntArg
<TMin
, TMax
- 1>{iArg
.val
}, remainingArgs
...);
338 SWR_ASSUME(false); return nullptr;
340 template <uint32_t TVal
, typename
... TArgsT
>
341 static typename
TermT::FuncType
GetFunc(IntArg
<TVal
, TVal
> iArg
, TArgsT
... remainingArgs
)
343 SWR_ASSERT(iArg
.val
== TVal
);
344 return TemplateArgUnroller
<TermT
, ArgsB
..., std::integral_constant
<uint32_t, TVal
>>::GetFunc(remainingArgs
...);
348 //////////////////////////////////////////////////////////////////////////
349 /// Helpers used to get / set environment variable
350 //////////////////////////////////////////////////////////////////////////
351 static INLINE
std::string
GetEnv(const std::string
& variableName
)
355 DWORD valueSize
= GetEnvironmentVariableA(variableName
.c_str(), nullptr, 0);
356 if (!valueSize
) return output
;
357 output
.resize(valueSize
- 1); // valueSize includes null, output.resize() does not
358 GetEnvironmentVariableA(variableName
.c_str(), &output
[0], valueSize
);
360 output
= getenv(variableName
.c_str());
366 static INLINE
void SetEnv(const std::string
& variableName
, const std::string
& value
)
369 SetEnvironmentVariableA(variableName
.c_str(), value
.c_str());
371 setenv(variableName
.c_str(), value
.c_str(), true);