7e3db20826
Change-Id: I53c1845d985ac3e9708d952865009c0021f3bb4f
214 строки
6.5 KiB
C++
214 строки
6.5 KiB
C++
#ifndef HSA_RUNTIME_EXT_IMAGE_UTIL_H
|
|
#define HSA_RUNTIME_EXT_IMAGE_UTIL_H
|
|
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
|
|
#include "inc/hsa.h"
|
|
|
|
// A macro to disallow the copy and move constructor and operator= functions
|
|
// This should be used in the private: declarations for a class
|
|
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
|
TypeName(const TypeName&); \
|
|
TypeName(TypeName&&); \
|
|
void operator=(const TypeName&); \
|
|
void operator=(TypeName&&);
|
|
|
|
#if defined(_MSC_VER)
|
|
#define ALIGNED_(x) __declspec(align(x))
|
|
#else
|
|
#if defined(__GNUC__)
|
|
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
|
#endif // __GNUC__
|
|
#endif // _MSC_VER
|
|
|
|
#define MULTILINE(...) # __VA_ARGS__
|
|
|
|
#if defined(__GNUC__)
|
|
#include "mm_malloc.h"
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
#include <x86intrin.h>
|
|
#else
|
|
#error \
|
|
"Processor not identified. " \
|
|
"Need to provide a lightweight approximate clock interface (aka __rdtsc())."
|
|
#endif
|
|
|
|
namespace ext_image {
|
|
#define __forceinline __inline__ __attribute__((always_inline))
|
|
static __forceinline void __debugbreak() { __builtin_trap(); }
|
|
#define __declspec(x) __attribute__((x))
|
|
#undef __stdcall
|
|
#define __stdcall // __attribute__((__stdcall__))
|
|
#define __ALIGNED__(x) __attribute__((aligned(x)))
|
|
|
|
static __forceinline void* _aligned_malloc(size_t size, size_t alignment) {
|
|
return _mm_malloc(size, alignment);
|
|
}
|
|
static __forceinline void _aligned_free(void* ptr) { return _mm_free(ptr); }
|
|
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
|
#include "intrin.h"
|
|
#define __ALIGNED__(x) __declspec(align(x))
|
|
namespace ext_image {
|
|
#else
|
|
#error "Compiler and/or processor not identified."
|
|
#endif
|
|
|
|
/// @brief: Checks if a value is power of two, if it is, return true. Be careful
|
|
/// when passing 0.
|
|
/// @param: val(Input), the data to be checked.
|
|
/// @return: bool.
|
|
template <typename T>
|
|
static __forceinline bool IsPowerOfTwo(T val) {
|
|
return (val & (val - 1)) == 0;
|
|
}
|
|
|
|
/// @brief: Calculates the floor value aligned based on parameter of alignment.
|
|
/// If value is at the boundary of alignment, it is unchanged.
|
|
/// @param: value(Input), value to be calculated.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @return: T.
|
|
template <typename T>
|
|
static __forceinline T AlignDown(T value, size_t alignment) {
|
|
assert(IsPowerOfTwo(alignment));
|
|
return (T)(value & ~(alignment - 1));
|
|
}
|
|
|
|
/// @brief: Same as previous one, but first parameter becomes pointer, for more
|
|
/// info, see the previous desciption.
|
|
/// @param: value(Input), pointer to type T.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @return: T*, pointer to type T.
|
|
template <typename T>
|
|
static __forceinline T* AlignDown(T* value, size_t alignment) {
|
|
return (T*)AlignDown((intptr_t)value, alignment);
|
|
}
|
|
|
|
/// @brief: Calculates the ceiling value aligned based on parameter of
|
|
/// alignment.
|
|
/// If value is at the boundary of alignment, it is unchanged.
|
|
/// @param: value(Input), value to be calculated.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @param: T.
|
|
template <typename T>
|
|
static __forceinline T AlignUp(T value, size_t alignment) {
|
|
return AlignDown((T)(value + alignment - 1), alignment);
|
|
}
|
|
|
|
/// @brief: Same as previous one, but first parameter becomes pointer, for more
|
|
/// info, see the previous desciption.
|
|
/// @param: value(Input), pointer to type T.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @return: T*, pointer to type T.
|
|
template <typename T>
|
|
static __forceinline T* AlignUp(T* value, size_t alignment) {
|
|
return (T*)AlignDown((intptr_t)((uint8_t*)value + alignment - 1), alignment);
|
|
}
|
|
|
|
/// @brief: Checks if the input value is at the boundary of alignment, if it is,
|
|
/// @return true.
|
|
/// @param: value(Input), value to be checked.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @return: bool.
|
|
template <typename T>
|
|
static __forceinline bool IsMultipleOf(T value, size_t alignment) {
|
|
return (AlignUp(value, alignment) == value);
|
|
}
|
|
|
|
/// @brief: Same as previous one, but first parameter becomes pointer, for more
|
|
/// info, see the previous desciption.
|
|
/// @param: value(Input), pointer to type T.
|
|
/// @param: alignment(Input), alignment value.
|
|
/// @return: bool.
|
|
template <typename T>
|
|
static __forceinline bool IsMultipleOf(T* value, size_t alignment) {
|
|
return (AlignUp(value, alignment) == value);
|
|
}
|
|
|
|
static __forceinline uint32_t NextPow2(uint32_t value) {
|
|
if (value == 0) return 1;
|
|
uint32_t v = value - 1;
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return v + 1;
|
|
}
|
|
|
|
static __forceinline uint64_t NextPow2(uint64_t value) {
|
|
if (value == 0) return 1;
|
|
uint64_t v = value - 1;
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
v |= v >> 32;
|
|
return v + 1;
|
|
}
|
|
|
|
template<uint32_t lowBit, uint32_t highBit, typename T>
|
|
static __forceinline uint32_t BitSelect(T p) {
|
|
static_assert(sizeof(T) <= sizeof(uintptr_t), "Type out of range.");
|
|
static_assert(highBit < sizeof(uintptr_t)*8, "Bit index out of range.");
|
|
|
|
uintptr_t ptr = p;
|
|
if(highBit != (sizeof(uintptr_t)*8-1))
|
|
return (uint32_t)((ptr & ((1ull<<(highBit+1))-1)) >> lowBit);
|
|
else
|
|
return (uint32_t)(ptr >> lowBit);
|
|
}
|
|
|
|
inline uint32_t PtrLow16Shift8(const void* p) {
|
|
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
|
return (uint32_t)((ptr & 0xFFFFULL) >> 8);
|
|
}
|
|
|
|
inline uint32_t PtrHigh64Shift16(const void* p) {
|
|
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
|
return (uint32_t)((ptr & 0xFFFFFFFFFFFF0000ULL) >> 16);
|
|
}
|
|
|
|
inline uint32_t PtrLow40Shift8(const void* p) {
|
|
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
|
return (uint32_t)((ptr & 0xFFFFFFFFFFULL) >> 8);
|
|
}
|
|
|
|
inline uint32_t PtrHigh64Shift40(const void* p) {
|
|
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
|
return (uint32_t)((ptr & 0xFFFFFF0000000000ULL) >> 40);
|
|
}
|
|
|
|
inline uint32_t PtrLow32(const void* p) {
|
|
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(p));
|
|
}
|
|
|
|
inline uint32_t PtrHigh32(const void* p) {
|
|
uint32_t ptr = 0;
|
|
#ifdef HSA_LARGE_MODEL
|
|
ptr = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(p) >> 32);
|
|
#endif
|
|
return ptr;
|
|
}
|
|
|
|
/**
|
|
* Generic functor compatible with the STL algorithms that enables proper
|
|
* destruction of a container of pointers. If (for instance), \c v is a vector
|
|
* of pointers to objects of type T, then the destructors of the elements in
|
|
* \c v are invoked when calling
|
|
* \code{std::for_each(v.begin(), v.end(), DeleteObject())}
|
|
*
|
|
* The original code and further information about this function object can be
|
|
* found in "Effective STL", 1st edition, item 7.
|
|
*/
|
|
struct DeleteObject {
|
|
template<typename T>
|
|
void operator()(const T *ptr) const {
|
|
delete ptr;
|
|
}
|
|
};
|
|
} // namespace ext_image
|
|
|
|
#endif // HSA_RUNTIME_EXT_IMAGE_UTIL_H
|