Diligent Engine  v.2.4.g
Win32PlatformMisc.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
30 #include "../../Basic/interface/BasicPlatformMisc.hpp"
31 #include "../../../Platforms/Basic/interface/DebugUtilities.hpp"
32 
33 #include <intrin.h>
34 
36 {
38  {
39  if (Val == 0) return 32;
40 
41  unsigned long MSB = 32;
42  _BitScanReverse(&MSB, Val);
44 
45  return MSB;
46  }
47 
49  {
50  if (Val == 0) return 64;
51 
52  unsigned long MSB = 64;
53 #if _WIN64
54  _BitScanReverse64(&MSB, Val);
55 #else
56  Diligent::Uint32 high = static_cast<Diligent::Uint32>((Val >> 32) & 0xFFFFFFFF);
57  if (high != 0)
58  {
59  MSB = 32 + GetMSB(high);
60  }
61  else
62  {
63  Diligent::Uint32 low = static_cast<Diligent::Uint32>(Val & 0xFFFFFFFF);
64  VERIFY_EXPR(low != 0);
65  MSB = GetMSB(low);
66  }
67 #endif
69 
70  return MSB;
71  }
72 
74  {
75  if (Val == 0) return 32;
76 
77  unsigned long LSB = 32;
78  _BitScanForward(&LSB, Val);
80 
81  return LSB;
82  }
83 
85  {
86  if (Val == 0) return 64;
87 
88  unsigned long LSB = 64;
89 #if _WIN64
90  _BitScanForward64(&LSB, Val);
91 #else
92  Diligent::Uint32 low = static_cast<Diligent::Uint32>(Val & 0xFFFFFFFF);
93  if (low != 0)
94  {
95  LSB = GetLSB(low);
96  }
97  else
98  {
99  Diligent::Uint32 high = static_cast<Diligent::Uint32>((Val >> 32) & 0xFFFFFFFF);
100  VERIFY_EXPR(high != 0);
101  LSB = 32 + GetLSB(high);
102  }
103 #endif
104 
106  return LSB;
107  }
108 
110  {
111 #if defined _M_ARM || defined _M_ARM64
112  // MSVC _CountOneBits intrinsics undefined for ARM64
113  // Cast bits to 8x8 datatype and use VCNT on result
114  const uint8x8_t Vsum = vcnt_u8(vcreate_u8(static_cast<uint64_t>(Val)));
115  // Pairwise sums: 8x8 -> 16x4 -> 32x2
116  auto Bits = static_cast<Diligent::Uint32>(vget_lane_u32(vpaddl_u16(vpaddl_u8(Vsum)), 0));
117 #else
118  auto Bits = __popcnt(Val);
119 #endif
121  return Bits;
122  }
123 
125  {
126 #if defined _M_ARM || defined _M_ARM64
127  // Cast bits to 8x8 datatype and use VCNT on result
128  const uint8x8_t Vsum = vcnt_u8(vcreate_u8(Val));
129  // Pairwise sums: 8x8 -> 16x4 -> 32x2 -> 64x1
130  auto Bits = static_cast<Diligent::Uint32>(vget_lane_u64(vpaddl_u32(vpaddl_u16(vpaddl_u8(Vsum))), 0));
131 #elif _WIN64
132  auto Bits = __popcnt64(Val);
133 #else
134  auto Bits =
135  CountOneBits(static_cast<Diligent::Uint32>((Val >> 0) & 0xFFFFFFFF)) +
136  CountOneBits(static_cast<Diligent::Uint32>((Val >> 32) & 0xFFFFFFFF));
137 #endif
139  return static_cast<Diligent::Uint32>(Bits);
140  }
141 };
Diligent::Uint64
uint64_t Uint64
64-bit unsigned integer
Definition: BasicTypes.h:50
WindowsMisc::CountOneBits
static Diligent::Uint32 CountOneBits(Diligent::Uint32 Val)
Definition: Win32PlatformMisc.hpp:109
WindowsMisc::GetMSB
static Diligent::Uint32 GetMSB(Diligent::Uint32 Val)
Definition: Win32PlatformMisc.hpp:37
BasicPlatformMisc::GetLSB
static Diligent::Uint32 GetLSB(Type Val)
Definition: BasicPlatformMisc.hpp:47
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
BasicPlatformMisc::GetMSB
static Diligent::Uint32 GetMSB(Type Val)
Definition: BasicPlatformMisc.hpp:35
WindowsMisc::GetLSB
static Diligent::Uint32 GetLSB(Diligent::Uint32 Val)
Definition: Win32PlatformMisc.hpp:73
BasicPlatformMisc
Definition: BasicPlatformMisc.hpp:32
BasicPlatformMisc::CountOneBits
static Diligent::Uint32 CountOneBits(Type Val)
Definition: BasicPlatformMisc.hpp:59
VERIFY_EXPR
#define VERIFY_EXPR(...)
Definition: DebugUtilities.hpp:79
WindowsMisc::GetLSB
static Diligent::Uint32 GetLSB(Diligent::Uint64 Val)
Definition: Win32PlatformMisc.hpp:84
WindowsMisc::CountOneBits
static Diligent::Uint32 CountOneBits(Diligent::Uint64 Val)
Definition: Win32PlatformMisc.hpp:124
WindowsMisc::GetMSB
static Diligent::Uint32 GetMSB(Diligent::Uint64 Val)
Definition: Win32PlatformMisc.hpp:48
WindowsMisc
Definition: Win32PlatformMisc.hpp:35