UraniumCompute 0.1.0
A GPU accelerated parallel task scheduler
Base.h
1#pragma once
2#include <UnCompute/Base/Logger.h>
3#include <UnCompute/Base/Platform.h>
4#include <UnCompute/Base/ResultCode.h>
5#include <atomic>
6#include <cassert>
7#include <cstdint>
8#include <string_view>
9
10namespace UN
11{
14 using Int8 = int8_t;
15 using Int16 = int16_t;
16 using Int32 = int32_t;
17 using Int64 = int64_t;
18
19 using UInt8 = uint8_t;
20 using UInt16 = uint16_t;
21 using UInt32 = uint32_t;
22 using UInt64 = uint64_t;
23
24 using Float32 = float;
25 using Float64 = double;
27
28 using USize = size_t;
29 using SSize = ptrdiff_t;
30
31 inline constexpr struct
32 {
33 int Major = 0, Minor = 1, Patch = 0;
34 } UnComputeVersion;
35
37 template<class T, class = std::enable_if_t<std::is_integral_v<T>, void>>
39 {
40 T m_SizeInBytes = 0;
41
42 public:
43 inline MemorySizeImpl() = default;
44
45 inline explicit MemorySizeImpl(T sizeInBytes)
46 : m_SizeInBytes(sizeInBytes)
47 {
48 }
49
50 template<class T1>
51 inline MemorySizeImpl& operator=(const MemorySizeImpl<T1>& other)
52 {
53 m_SizeInBytes = static_cast<T>(other.m_SizeInBytes);
54 }
55
56 inline MemorySizeImpl& operator=(const MemorySizeImpl& other) = default;
57 inline MemorySizeImpl& operator=(MemorySizeImpl&& other) noexcept = default;
58
59 inline MemorySizeImpl& operator=(const T& other)
60 {
61 m_SizeInBytes = other;
62 return *this;
63 }
64
66 inline T GetBytes() const
67 {
68 return m_SizeInBytes;
69 }
70 };
71
72 using MemorySize = MemorySizeImpl<USize>;
73 using MemorySize32 = MemorySizeImpl<UInt32>;
74 using MemorySize64 = MemorySizeImpl<UInt64>;
75
77 namespace Internal
78 {
84 struct SVWrapper
85 {
86 std::string_view value;
87 };
88
90 inline constexpr std::string_view TrimTypeName(std::string_view name)
91 {
92 name.remove_prefix(name.find_first_not_of(' '));
93 name.remove_suffix(name.length() - name.find_last_not_of(' ') - 1);
94 return name;
95 }
96
98 template<class T>
99 inline constexpr SVWrapper TypeNameImpl()
100 {
101#if UN_COMPILER_MSVC
102 std::string_view fn = __FUNCSIG__;
103 fn.remove_prefix(fn.find_first_of("<") + 1);
104 fn.remove_suffix(fn.length() - fn.find_last_of(">"));
105#else
106 std::string_view fn = __PRETTY_FUNCTION__;
107 fn.remove_prefix(fn.find_first_of('=') + 1);
108 fn.remove_suffix(fn.length() - fn.find_last_of(']'));
109#endif
110 return SVWrapper{ TrimTypeName(fn) };
111 }
112 } // namespace Internal
114
119 template<class T>
120 inline constexpr std::string_view TypeName()
121 {
122 return Internal::TypeNameImpl<T>().value;
123 }
124
126 inline constexpr USize MaximumAlignment = 16;
127
132 template<class T, class U = T>
133 inline T AlignUp(T x, U align)
134 {
135 return (x + (align - 1u)) & ~(align - 1u);
136 }
137
142 template<class T>
143 inline T* AlignUpPtr(const T* x, USize align)
144 {
145 return reinterpret_cast<T*>(AlignUp(reinterpret_cast<USize>(x), align));
146 }
147
152 template<UInt32 A, class T>
153 inline constexpr T AlignUp(T x)
154 {
155 return (x + (A - 1)) & ~(A - 1);
156 }
157
162 template<class T, class U = T>
163 inline T AlignDown(T x, U align)
164 {
165 return (x & ~(align - 1));
166 }
167
172 template<class T>
173 inline constexpr T* AlignDownPtr(const T* x, USize align)
174 {
175 return reinterpret_cast<T*>(AlignDown(reinterpret_cast<USize>(x), align));
176 }
177
182 template<UInt32 A, class T>
183 inline constexpr T AlignDown(T x)
184 {
185 return (x & ~(A - 1));
186 }
187
192 template<class T>
193 inline constexpr T MakeMask(T bitCount, T leftShift)
194 {
195 auto typeBitCount = sizeof(T) * 8;
196 auto mask = bitCount == typeBitCount ? static_cast<T>(-1) : ((1 << bitCount) - 1);
197 return static_cast<T>(mask << leftShift);
198 }
199
200 inline void HashCombine(std::size_t& /* seed */) {}
201
208 template<typename T, typename... Args>
209 inline void HashCombine(std::size_t& seed, const T& value, const Args&... args)
210 {
211 std::hash<T> hasher;
212 seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
213 HashCombine(seed, args...);
214 }
215
217#define UN_MAKE_HASHABLE(TypeName, Template, ...) \
218 namespace std \
219 { \
220 template<Template> \
221 struct hash<TypeName> \
222 { \
223 inline size_t operator()(const TypeName& value) const noexcept \
224 { \
225 size_t seed = 0; \
226 ::UN::HashCombine(seed, __VA_ARGS__); \
227 return seed; \
228 } \
229 }; \
230 }
231
232#if UN_DEBUG
234 inline constexpr bool ValidationEnabled = true;
235#else
237 inline constexpr bool ValidationEnabled = false;
238#endif
239
251 template<class TDest, class TSrc>
252 inline std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<TSrc>, std::remove_pointer_t<TDest>>
253 && std::is_pointer_v<TSrc> && std::is_pointer_v<TDest>,
254 TDest>
255 un_verify_cast(TSrc pSourceObject)
256 {
257 if constexpr (std::is_same_v<TSrc, TDest>)
258 {
259 return pSourceObject;
260 }
261
262 if constexpr (ValidationEnabled) // NOLINT
263 {
264 if (auto* result = dynamic_cast<TDest>(pSourceObject))
265 {
266 return result;
267 }
268
269 UN_Assert(false, "Verifying cast failed");
270 }
271
272 return static_cast<TDest>(pSourceObject);
273 }
274} // namespace UN
275
276template<class T>
277struct fmt::formatter<UN::MemorySizeImpl<T>> : fmt::formatter<std::string_view>
278{
279 template<typename FormatContext>
280 auto format(const UN::MemorySizeImpl<T>& size, FormatContext& ctx) const -> decltype(ctx.out())
281 {
282 UN::Int32 i = 0;
283 auto bytes = static_cast<UN::Float64>(size.GetBytes());
284
285 const char* units[] = { "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
286 while (bytes >= 1024)
287 {
288 bytes /= 1024;
289 i++;
290 }
291
292 return fmt::format_to(ctx.out(), "{:.2f}{}", bytes, units[i]);
293 }
294};
Stores memory size in bytes, this is useful to format human-readable memory sizes.
Definition: Base.h:39
T GetBytes() const
Get memory size in bytes.
Definition: Base.h:66
A simple std::string_view wrapper.
Definition: Base.h:85
std::string_view value
Actual value of the string view.
Definition: Base.h:86