diff --git a/.gitignore b/.gitignore index 3842ae8..bc2054b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ .vs/ # CMake generated files -Build/ -Install/ +out/ diff --git a/CMakeSettings.json b/CMakeSettings.json index 607fd69..aa69c5b 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -4,12 +4,33 @@ "name": "x64-Debug", "generator": "Ninja", "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\Build\\${name}", - "installRoot": "${projectDir}\\Install\\${name}", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", "cmakeCommandArgs": "", "buildCommandArgs": "", - "ctestCommandArgs": "" + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] + }, + { + "name": "Linux-GCC-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "cmakeExecutable": "cmake", + "remoteCopySourcesExclusionList": [ ".vs", ".git", "out" ], + "cmakeCommandArgs": "-D CMAKE_C_COMPILER=gcc-10 -D CMAKE_CXX_COMPILER=g++-10", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "linux_x64" ], + "remoteMachineName": "${defaultRemoteMachineName}", + "remoteCMakeListsRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/src", + "remoteBuildRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/build/${name}", + "remoteInstallRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/install/${name}", + "remoteCopySources": true, + "rsyncCommandArgs": "-t --delete --delete-excluded", + "remoteCopyBuildOutput": false, + "remoteCopySourcesMethod": "rsync", + "variables": [] } ] } \ No newline at end of file diff --git a/Redcraft.Core/Source/Private/HAL/Memory.cpp b/Redcraft.Core/Source/Private/HAL/Memory.cpp new file mode 100644 index 0000000..01add4d --- /dev/null +++ b/Redcraft.Core/Source/Private/HAL/Memory.cpp @@ -0,0 +1,75 @@ +#include "HAL/Memory.h" + +#include "Templates/Alignment.h" + +#ifdef PLATFORM_WINDOWS +#include +#endif + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +void* Malloc(size_t Count, uint32 Alignment) +{ + Alignment = Math::Max(Count >= 16 ? (uint32)16 : (uint32)8, Alignment); + + void* Result = nullptr; + +#ifdef PLATFORM_WINDOWS + if (Count != 0) Result = _aligned_malloc(Count, Alignment); +#else + void* Ptr = SystemMalloc(Count + Alignment + sizeof(void*) + sizeof(size_t)); + if (Ptr) + { + Result = Align((uint8*)Ptr + sizeof(void*) + sizeof(size_t), Alignment); + *((void**)((uint8*)Result - sizeof(void*))) = Ptr; + *((size_t*)((uint8*)Result - sizeof(void*) - sizeof(size_t))) = Count; + } +#endif + + return Result; +} + +void* Realloc(void* Ptr, size_t Count, uint32 Alignment) +{ + Alignment = Math::Max(Count >= 16 ? (uint32)16 : (uint32)8, Alignment); + + if (Ptr && Count) + { +#ifdef PLATFORM_WINDOWS + return _aligned_realloc(Ptr, Count, Alignment); +#else + void* Result = Malloc(Count, Alignment); + size_t PtrSize = *((size_t*)((uint8*)Ptr - sizeof(void*) - sizeof(size_t))); + Memcpy(Result, Ptr, Math::Min(Count, PtrSize)); + Free(Ptr); + return Result; +#endif + } + else if (Ptr == nullptr) + { + return Malloc(Count, Alignment); + } + else + { + Free(Ptr); + return nullptr; + } +} + +void Free(void* Ptr) +{ +#if PLATFORM_WINDOWS + _aligned_free(Ptr); +#else + SystemFree(*((void**)((uint8*)Ptr - sizeof(void*)))); +#endif +} + +size_t QuantizeSize(size_t Count, uint32 Alignment) +{ + return Count; +} + +NS_END(Memory) +NS_REDCRAFT_END diff --git a/Redcraft.Core/Source/Public/HAL/Memory.h b/Redcraft.Core/Source/Public/HAL/Memory.h new file mode 100644 index 0000000..0a6f002 --- /dev/null +++ b/Redcraft.Core/Source/Public/HAL/Memory.h @@ -0,0 +1,43 @@ +#pragma once + +#include "CoreTypes.h" + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +constexpr uint32 DEFAULT_ALIGNMENT = 0; +constexpr uint32 MIN_ALIGNMENT = 8; + +FORCEINLINE void* Memmove(void* Dest, const void* Src, size_t Count); +FORCEINLINE int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count); +FORCEINLINE void Memset(void* Dest, uint8 ValueToSet, size_t Count); +FORCEINLINE void* Memzero(void* Dest, size_t Count); +FORCEINLINE void* Memcpy(void* Dest, const void* Src, size_t Count); + +template +static FORCEINLINE void Memset(T& Src, uint8 ValueToSet); + +template +static FORCEINLINE void Memzero(T& Src); + +template +static FORCEINLINE void Memcpy(T& Dest, const T& Src); + +FORCEINLINE void* SystemMalloc(size_t Count); +FORCEINLINE void SystemFree(void* Ptr); + +REDCRAFTCORE_API void* Malloc(size_t Count, uint32 Alignment = DEFAULT_ALIGNMENT); +REDCRAFTCORE_API void* Realloc(void* Ptr, size_t Count, uint32 Alignment = DEFAULT_ALIGNMENT); +REDCRAFTCORE_API void Free(void* Ptr); +REDCRAFTCORE_API size_t QuantizeSize(size_t Count, uint32 Alignment = DEFAULT_ALIGNMENT); + +NS_END(Memory) +NS_REDCRAFT_END + +#include "HAL/Memory.inl" + +void* operator new(std::size_t Count) { return NS_REDCRAFT::Memory::Malloc(Count); }; +void* operator new(std::size_t Count, std::align_val_t Alignment) { return NS_REDCRAFT::Memory::Malloc(Count, (NS_REDCRAFT::uint32)Alignment); }; + +void operator delete(void* Ptr) noexcept { NS_REDCRAFT::Memory::Free(Ptr); } +void operator delete(void* Ptr, std::align_val_t Alignment) noexcept { NS_REDCRAFT::Memory::Free(Ptr); } diff --git a/Redcraft.Core/Source/Public/HAL/Memory.inl b/Redcraft.Core/Source/Public/HAL/Memory.inl new file mode 100644 index 0000000..6081455 --- /dev/null +++ b/Redcraft.Core/Source/Public/HAL/Memory.inl @@ -0,0 +1,67 @@ +#include "Math/MathUtility.h" +#include "Templates/TypeTraits.h" + +#include +#include + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +void* Memmove(void* Dest, const void* Src, size_t Count) +{ + return std::memmove(Dest, Src, Count); +} + +int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count) +{ + return std::memcmp(Buf1, Buf2, Count); +} + +void Memset(void* Dest, uint8 ValueToSet, size_t Count) +{ + std::memset(Dest, ValueToSet, Count); +} + +void* Memzero(void* Dest, size_t Count) +{ + return std::memset(Dest, 0, Count); +} + +void* Memcpy(void* Dest, const void* Src, size_t Count) +{ + return std::memcpy(Dest, Src, Count); +} + +template +static FORCEINLINE void Memset(T& Src, uint8 ValueToSet) +{ + static_assert(!TypeTraits::TIsPointer::Value, "For pointers use the three parameters function"); + Memset(&Src, ValueToSet, sizeof(T)); +} + +template +static FORCEINLINE void Memzero(T& Src) +{ + static_assert(!TypeTraits::TIsPointer::Value, "For pointers use the two parameters function"); + Memzero(&Src, sizeof(T)); +} + +template +static FORCEINLINE void Memcpy(T& Dest, const T& Src) +{ + static_assert(!TypeTraits::TIsPointer::Value, "For pointers use the three parameters function"); + Memcpy(&Dest, &Src, sizeof(T)); +} + +void* SystemMalloc(size_t Count) +{ + return std::malloc(Count); +} + +void SystemFree(void* Ptr) +{ + std::free(Ptr); +} + +NS_END(Memory) +NS_REDCRAFT_END diff --git a/Redcraft.Core/Source/Public/HAL/Platform.h b/Redcraft.Core/Source/Public/HAL/Platform.h index 265cd7a..8e4d478 100644 --- a/Redcraft.Core/Source/Public/HAL/Platform.h +++ b/Redcraft.Core/Source/Public/HAL/Platform.h @@ -2,6 +2,7 @@ #include "Misc/CoreDefines.h" +#include #include #include #include @@ -46,20 +47,36 @@ NS_REDCRAFT_BEGIN // Alignment. -#if defined(__clang__) +#if PLATFORM_WINDOWS - #define GCC_PACK(n) __attribute__((packed,aligned(n))) - #define GCC_ALIGN(n) __attribute__((aligned(n))) - - #if defined(_MSC_VER) - #define MS_ALIGN(n) __declspec(align(n)) + #if defined(__clang__) + + #define GCC_PACK(n) __attribute__((packed,aligned(n))) + #define GCC_ALIGN(n) __attribute__((aligned(n))) + + #if defined(_MSC_VER) + #define MS_ALIGN(n) __declspec(align(n)) + #endif + + #else + + #define GCC_PACK(n) + #define GCC_ALIGN(n) + #define MS_ALIGN(n) __declspec(align(n)) + #endif + +#elif PLATFORM_LINUX + + #define GCC_PACK(n) __attribute__((packed,aligned(n))) + #define GCC_ALIGN(n) __attribute__((aligned(n))) + #define MS_ALIGN(n) #else #define GCC_PACK(n) #define GCC_ALIGN(n) - #define MS_ALIGN(n) __declspec(align(n)) + #define MS_ALIGN(n) #endif @@ -114,10 +131,6 @@ typedef intptr_t ssize_t; typedef decltype(NULL) null_t; typedef std::nullptr_t nullptr_t; -// Alignment. - -typedef std::max_align_t max_align_t; - #if PLATFORM_LINUX #define PLATFORM_TCHAR_IS_CHAR16 1 #else diff --git a/Redcraft.Core/Source/Public/Math/MathUtility.h b/Redcraft.Core/Source/Public/Math/MathUtility.h new file mode 100644 index 0000000..19d11cb --- /dev/null +++ b/Redcraft.Core/Source/Public/Math/MathUtility.h @@ -0,0 +1,33 @@ +#pragma once + +#include "CoreTypes.h" + +NS_REDCRAFT_BEGIN +NS_BEGIN(Math) + +template +static constexpr FORCEINLINE T Abs(const T A) +{ + return (A >= (T)0) ? A : -A; +} + +template +static constexpr FORCEINLINE T Sign(const T A) +{ + return (A > (T)0) ? (T)1 : ((A < (T)0) ? (T)-1 : (T)0); +} + +template +static constexpr FORCEINLINE T Max(const T A, const T B) +{ + return (A >= B) ? A : B; +} + +template +static constexpr FORCEINLINE T Min(const T A, const T B) +{ + return (A <= B) ? A : B; +} + +NS_END(Math) +NS_REDCRAFT_END diff --git a/Redcraft.Core/Source/Public/Misc/CoreDefines.h b/Redcraft.Core/Source/Public/Misc/CoreDefines.h index ee6dfd7..341931b 100644 --- a/Redcraft.Core/Source/Public/Misc/CoreDefines.h +++ b/Redcraft.Core/Source/Public/Misc/CoreDefines.h @@ -9,6 +9,10 @@ #define NS_REDCRAFT_END NS_END(NS_REDCRAFT) #define NS_REDCRAFT_USING NS_USING(NS_REDCRAFT) +#define NS_PRIVATE Private +#define NS_PRIVATE_BEGIN NS_BEGIN(NS_PRIVATE) +#define NS_PRIVATE_END NS_END(NS_PRIVATE) + #define NS_STD_BEGIN NS_BEGIN(std) #define NS_STD_END NS_END(std) #define NS_STD_USING NS_USING(std) diff --git a/Redcraft.Core/Source/Public/Templates/Alignment.h b/Redcraft.Core/Source/Public/Templates/Alignment.h new file mode 100644 index 0000000..1f7645e --- /dev/null +++ b/Redcraft.Core/Source/Public/Templates/Alignment.h @@ -0,0 +1,44 @@ +#pragma once + +#pragma once + +#include "CoreTypes.h" +#include "Templates/TypeTraits.h" + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +template +FORCEINLINE constexpr T Align(T Val, uint64 Alignment) +{ + static_assert(TypeTraits::TIsIntegral::Value || TypeTraits::TIsPointer::Value, "Align expects an integer or pointer type"); + + return (T)(((uint64)Val + Alignment - 1) & ~(Alignment - 1)); +} + +template +FORCEINLINE constexpr T AlignDown(T Val, uint64 Alignment) +{ + static_assert(TypeTraits::TIsIntegral::Value || TypeTraits::TIsPointer::Value, "AlignDown expects an integer or pointer type"); + + return (T)(((uint64)Val) & ~(Alignment - 1)); +} + +template +FORCEINLINE constexpr bool IsAligned(T Val, uint64 Alignment) +{ + static_assert(TypeTraits::TIsIntegral::Value || TypeTraits::TIsPointer::Value, "IsAligned expects an integer or pointer type"); + + return !((uint64)Val & (Alignment - 1)); +} + +template +FORCEINLINE constexpr T AlignArbitrary(T Val, uint64 Alignment) +{ + static_assert(TypeTraits::TIsIntegral::Value || TypeTraits::TIsPointer::Value, "AlignArbitrary expects an integer or pointer type"); + + return (T)((((uint64)Val + Alignment - 1) / Alignment) * Alignment); +} + +NS_END(Memory) +NS_REDCRAFT_END diff --git a/Redcraft.Core/Source/Public/Templates/TypeTraits.h b/Redcraft.Core/Source/Public/Templates/TypeTraits.h index f04bb39..18433eb 100644 --- a/Redcraft.Core/Source/Public/Templates/TypeTraits.h +++ b/Redcraft.Core/Source/Public/Templates/TypeTraits.h @@ -84,7 +84,6 @@ template struct TExtent { static constexpr size_t Val template struct TIsSame { static constexpr bool Value = std::is_same_v; }; template struct TIsBaseOf { static constexpr bool Value = std::is_base_of_v; }; template struct TIsConvertible { static constexpr bool Value = std::is_convertible_v; }; -template struct TIsLayoutCompatible { static constexpr bool Value = std::is_layout_compatible_v; }; template struct TIsInvocable { static constexpr bool Value = std::is_invocable_v; }; template struct TIsInvocableResult { static constexpr bool Value = std::is_invocable_r_v; }; @@ -120,14 +119,14 @@ template struct TRemoveAllExtents { typedef typename std::remove_al // Miscellaneous transformations -template struct TAlignedStorage { typedef typename std::aligned_storage_t Type; }; -template struct TAlignedUnion { typedef typename std::aligned_union_t Type; }; -template struct TDecay { typedef typename std::decay_t Type; }; -template struct TRemoveCVRef { typedef typename std::remove_cvref_t Type; }; -template struct TConditional { typedef typename std::conditional_t Type; }; -template struct TCommonType { typedef typename std::common_type_t Type; }; -template struct TUnderlyingType { typedef typename std::underlying_type_t Type; }; -template struct TInvokeResult { typedef typename std::invoke_result_t Type; }; +template struct TAlignedStorage { typedef typename std::aligned_storage_t Type; }; +template struct TAlignedUnion { typedef typename std::aligned_union_t Type; }; +template struct TDecay { typedef typename std::decay_t Type; }; +template struct TRemoveCVRef { typedef typename std::remove_cvref_t Type; }; +template struct TConditional { typedef typename std::conditional_t Type; }; +template struct TCommonType { typedef typename std::common_type_t Type; }; +template struct TUnderlyingType { typedef typename std::underlying_type_t Type; }; +template struct TInvokeResult { typedef typename std::invoke_result_t Type; }; // Operations on traits diff --git a/Redcraft.Debug/Source/Main.cpp b/Redcraft.Debug/Source/Main.cpp index cbf1de9..deb8567 100644 --- a/Redcraft.Debug/Source/Main.cpp +++ b/Redcraft.Debug/Source/Main.cpp @@ -1,12 +1,18 @@ #include "CoreMinimal.h" +#include "HAL/Memory.h" #include #include +#include NS_STD_USING NS_REDCRAFT_USING int main() { + int32* Ptr = new int32; + *Ptr = 13; + cout << *Ptr << endl; + delete Ptr; return 0; }