#ifndef HSA_RUNTIME_EXT_IMAGE_UTIL_H #define HSA_RUNTIME_EXT_IMAGE_UTIL_H #include #include #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 #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 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 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 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 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 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 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 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 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(p); return (uint32_t)((ptr & 0xFFFFULL) >> 8); } inline uint32_t PtrHigh64Shift16(const void* p) { uintptr_t ptr = reinterpret_cast(p); return (uint32_t)((ptr & 0xFFFFFFFFFFFF0000ULL) >> 16); } inline uint32_t PtrLow40Shift8(const void* p) { uintptr_t ptr = reinterpret_cast(p); return (uint32_t)((ptr & 0xFFFFFFFFFFULL) >> 8); } inline uint32_t PtrHigh64Shift40(const void* p) { uintptr_t ptr = reinterpret_cast(p); return (uint32_t)((ptr & 0xFFFFFF0000000000ULL) >> 40); } inline uint32_t PtrLow32(const void* p) { return static_cast(reinterpret_cast(p)); } inline uint32_t PtrHigh32(const void* p) { uint32_t ptr = 0; #ifdef HSA_LARGE_MODEL ptr = static_cast(reinterpret_cast(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 void operator()(const T *ptr) const { delete ptr; } }; } // namespace ext_image #endif // HSA_RUNTIME_EXT_IMAGE_UTIL_H