#pragma once #ifndef _MSC_VER #include #else #include #endif #include "util_likely.h" namespace dxvk::bit { template T extract(T value, uint32_t fst, uint32_t lst) { return (value >> fst) & ~(~T(0) << (lst - fst + 1)); } template T popcnt(T value) { return value != 0 ? (value & 1) + popcnt(value >> 1) : 0; } inline uint32_t tzcnt(uint32_t n) { #if defined(_MSC_VER) return _tzcnt_u32(n); #elif defined(__BMI__) return __tzcnt_u32(n); #elif defined(__GNUC__) uint32_t res; uint32_t tmp; asm ( "mov $32, %1;" "bsf %2, %0;" "cmovz %1, %0;" : "=&r" (res), "=&r" (tmp) : "r" (n)); return res; #else uint32_t r = 31; n &= -n; r -= (n & 0x0000FFFF) ? 16 : 0; r -= (n & 0x00FF00FF) ? 8 : 0; r -= (n & 0x0F0F0F0F) ? 4 : 0; r -= (n & 0x33333333) ? 2 : 0; r -= (n & 0x55555555) ? 1 : 0; return n != 0 ? r : 32; #endif } template uint32_t pack(T& dst, uint32_t& shift, T src, uint32_t count) { constexpr uint32_t Bits = 8 * sizeof(T); if (likely(shift < Bits)) dst |= src << shift; shift += count; return shift > Bits ? shift - Bits : 0; } template uint32_t unpack(T& dst, T src, uint32_t& shift, uint32_t count) { constexpr uint32_t Bits = 8 * sizeof(T); if (likely(shift < Bits)) dst = (src >> shift) & ((T(1) << count) - 1); shift += count; return shift > Bits ? shift - Bits : 0; } }