diff --git a/Source/Engine/Core/Utilities.h b/Source/Engine/Core/Utilities.h index 940647ed7..6f7eaab6e 100644 --- a/Source/Engine/Core/Utilities.h +++ b/Source/Engine/Core/Utilities.h @@ -91,12 +91,12 @@ namespace Utilities // Returns the amount of set bits in 32-bit integer. inline int32 CountBits(uint32 x) { - // [Reference: https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer] #ifdef __GNUC_ return __builtin_popcount(x); #elif _MSC_VER && PLATFORM_SIMD_SSE4_2 return __popcnt(x); #else + // [Reference: https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer] x = x - ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; @@ -104,6 +104,52 @@ namespace Utilities #endif } + // Returns the index of the highest set bit. Assumes input is non-zero. + inline uint32 HighestSetBit(uint32 x) + { +#if _MSC_VER + unsigned long result; + _BitScanReverse(&result, x); + return result; +#elif __clang__ + return 31 - __builtin_clz(x); +#else + // [Reference: http://graphics.stanford.edu/~seander/bithacks.html] + static const uint32 MultiplyDeBruijnBitPosition[32] = + { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return MultiplyDeBruijnBitPosition[(uint32)(v * 0x07C4ACDDU) >> 27]; +#endif + } + + // Returns the index of the lowest set bit. Assumes input is non-zero. + inline uint32 LowestSetBit(uint32 v) + { +#if _MSC_VER + unsigned long result; + _BitScanForward(&result, v); + return result; +#elif __clang__ + return __builtin_ctz(v); +#else + // [Reference: http://graphics.stanford.edu/~seander/bithacks.html] + static const uint32 MultiplyDeBruijnBitPosition[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + int32 w = v; + return MultiplyDeBruijnBitPosition[(uint32)((w & -w) * 0x077CB531U) >> 27]; +#endif + } + // Copy memory region but ignoring address sanatizer checks for memory regions. NO_SANITIZE_ADDRESS static void UnsafeMemoryCopy(void* dst, const void* src, uint64 size) {