Updating memory arena by hand because Gemini did something weird.
Added some os functions for memory handling. Starting conversion to memory arena
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22823.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
@@ -7,11 +7,6 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Game", "Game\Game.vcxproj", "{B1D040D0-6C94-4F93-BC2A-7F5284B7D434}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JulietApp", "JulietApp\JulietApp.vcxproj", "{1DEE51CA-6C94-4F93-BC2A-7F5284B7D434}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{AB9C7E88-6C94-4F93-BC2A-7F5284B7D434} = {AB9C7E88-6C94-4F93-BC2A-7F5284B7D434}
|
||||
{C16FFE36-6C94-4F93-BC2A-7F5284B7D434} = {C16FFE36-6C94-4F93-BC2A-7F5284B7D434}
|
||||
{B1D040D0-6C94-4F93-BC2A-7F5284B7D434} = {B1D040D0-6C94-4F93-BC2A-7F5284B7D434}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Juliet", "Juliet\Juliet.vcxproj", "{AB9C7E88-6C94-4F93-BC2A-7F5284B7D434}"
|
||||
EndProject
|
||||
|
||||
@@ -72,12 +72,14 @@
|
||||
<CustomBuild Include="include\Core\HAL\Keyboard\KeyCode.h" />
|
||||
<CustomBuild Include="include\Core\HAL\Keyboard\ScanCode.h" />
|
||||
<CustomBuild Include="include\Core\HAL\Mouse\Mouse.h" />
|
||||
<CustomBuild Include="include\Core\HAL\OS\OS.h" />
|
||||
<CustomBuild Include="include\Core\HotReload\HotReload.h" />
|
||||
<CustomBuild Include="include\Core\ImGui\ImGuiService.h" />
|
||||
<CustomBuild Include="include\Core\ImGui\ImGuiTests.h" />
|
||||
<CustomBuild Include="include\Core\JulietInit.h" />
|
||||
<CustomBuild Include="include\Core\Logging\LogManager.h" />
|
||||
<CustomBuild Include="include\Core\Logging\LogTypes.h" />
|
||||
<CustomBuild Include="include\Core\Main.h" />
|
||||
<CustomBuild Include="include\Core\Math\MathUtils.h" />
|
||||
<CustomBuild Include="include\Core\Math\Matrix.h" />
|
||||
<CustomBuild Include="include\Core\Math\Shape.h" />
|
||||
@@ -140,6 +142,9 @@
|
||||
<CustomBuild Include="src\Core\HAL\IO\IOStream.cpp" />
|
||||
<CustomBuild Include="src\Core\HAL\IO\IOStream_Private.h" />
|
||||
<CustomBuild Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp" />
|
||||
<CustomBuild Include="src\Core\HAL\OS\OS.cpp" />
|
||||
<CustomBuild Include="src\Core\HAL\OS\OS_Private.h" />
|
||||
<CustomBuild Include="src\Core\HAL\OS\Win32\Win32OS.cpp" />
|
||||
<CustomBuild Include="src\Core\HAL\Win32.h" />
|
||||
<CustomBuild Include="src\Core\HotReload\HotReload.cpp" />
|
||||
<CustomBuild Include="src\Core\HotReload\Win32\Win32HotReload.cpp" />
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
<CustomBuild Include="include\Core\HAL\Mouse\Mouse.h">
|
||||
<Filter>include\Core\HAL\Mouse</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\HAL\OS\OS.h">
|
||||
<Filter>include\Core\HAL\OS</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\HotReload\HotReload.h">
|
||||
<Filter>include\Core\HotReload</Filter>
|
||||
</CustomBuild>
|
||||
@@ -82,6 +85,9 @@
|
||||
<CustomBuild Include="include\Core\Logging\LogTypes.h">
|
||||
<Filter>include\Core\Logging</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\Main.h">
|
||||
<Filter>include\Core</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\Math\MathUtils.h">
|
||||
<Filter>include\Core\Math</Filter>
|
||||
</CustomBuild>
|
||||
@@ -267,6 +273,15 @@
|
||||
<CustomBuild Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp">
|
||||
<Filter>src\Core\HAL\IO\Win32</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\HAL\OS\OS.cpp">
|
||||
<Filter>src\Core\HAL\OS</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\HAL\OS\OS_Private.h">
|
||||
<Filter>src\Core\HAL\OS</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\HAL\OS\Win32\Win32OS.cpp">
|
||||
<Filter>src\Core\HAL\OS\Win32</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\HAL\Win32.h">
|
||||
<Filter>src\Core\HAL</Filter>
|
||||
</CustomBuild>
|
||||
@@ -552,6 +567,11 @@
|
||||
<UniqueIdentifier>{4c7d6b5f-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="include\Core\HAL\OS">
|
||||
<UniqueIdentifier>{8d491e18-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="include\Core\HotReload">
|
||||
<UniqueIdentifier>{fe4e9898-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
@@ -672,6 +692,16 @@
|
||||
<UniqueIdentifier>{37523cd5-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="src\Core\HAL\OS">
|
||||
<UniqueIdentifier>{d679d621-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="src\Core\HAL\OS\Win32">
|
||||
<UniqueIdentifier>{f6713825-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="src\Core\HotReload">
|
||||
<UniqueIdentifier>{35231af8-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>
|
||||
|
||||
@@ -4,11 +4,16 @@
|
||||
#include <Juliet.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <source_location>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
|
||||
#define global static
|
||||
|
||||
#if JULIET_DEBUG
|
||||
#define JULIET_ASSERT_INTERNAL(expression, message) \
|
||||
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 4548)) do \
|
||||
@@ -100,4 +105,38 @@ namespace Juliet
|
||||
}
|
||||
|
||||
extern JULIET_API void Free(ByteBuffer& buffer);
|
||||
|
||||
template <std::integral T>
|
||||
[[nodiscard]] constexpr T AlignPow2(T x, T alignment)
|
||||
{
|
||||
// Safety Check:
|
||||
Assert(std::has_single_bit(static_cast<size_t>(alignment)));
|
||||
|
||||
return (x + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
// Move to another file dedicated to those
|
||||
#if defined(__clang__)
|
||||
#define COMPILER_CLANG 1
|
||||
#elif defined(_MSC_VER)
|
||||
#define COMPILER_MSVC 1
|
||||
#endif
|
||||
|
||||
// Undef anything not defined
|
||||
#if !defined(COMPILER_CLANG)
|
||||
#define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(COMPILER_MSVC)
|
||||
#define COMPILER_MSVC 0
|
||||
#endif
|
||||
|
||||
#if COMPILER_MSVC
|
||||
#define AlignOf(T) __alignof(T)
|
||||
#elif COMPILER_CLANG
|
||||
#define AlignOf(T) __alignof(T)
|
||||
#elif COMPILER_GCC
|
||||
#define AlignOf(T) __alignof__(T)
|
||||
#else
|
||||
#error AlignOf not defined for this compiler.
|
||||
#endif
|
||||
} // namespace Juliet
|
||||
|
||||
36
Juliet/include/Core/HAL/OS/OS.h
Normal file
36
Juliet/include/Core/HAL/OS/OS.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
Byte* OS_Reserve(size_t size);
|
||||
bool OS_Commit(Byte* ptr, size_t size);
|
||||
void OS_Release(Byte* ptr, size_t size);
|
||||
|
||||
template <typename Type>
|
||||
Type* OS_Reserve(size_t size)
|
||||
{
|
||||
return reinterpret_cast<Type*>(OS_Reserve(size));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
bool OS_Commit(Type* ptr, size_t size)
|
||||
{
|
||||
return OS_Commit(reinterpret_cast<Byte*>(ptr), size);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void OS_Release(Type* ptr, size_t size)
|
||||
{
|
||||
OS_Release(reinterpret_cast<Byte*>(ptr), size);
|
||||
}
|
||||
|
||||
} // namespace Memory
|
||||
|
||||
using EntryPointFunc = int (*)(int, wchar_t**);
|
||||
JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
||||
} // namespace Juliet
|
||||
@@ -6,7 +6,13 @@
|
||||
// TODO : Juliet strings
|
||||
#include <string>
|
||||
// TODO Juliet Containers + Allocators...
|
||||
// TODO: Juliet chrono, because it prevents me from doing #define global static
|
||||
#ifdef global
|
||||
#undef global
|
||||
#endif
|
||||
#include <chrono>
|
||||
#define global static
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace Juliet
|
||||
|
||||
47
Juliet/include/Core/Main.h
Normal file
47
Juliet/include/Core/Main.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
|
||||
extern int JulietMain(int, wchar_t**);
|
||||
|
||||
#if JULIET_WIN32
|
||||
#ifndef WINAPI
|
||||
#define WINAPI __stdcall
|
||||
#endif
|
||||
|
||||
#if COMPILER_MSVC
|
||||
#if UNICODE
|
||||
int wmain(int argc, wchar_t** argv)
|
||||
{
|
||||
return Juliet::Bootstrap(JulietMain, argc, argv);
|
||||
}
|
||||
#else
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return Juliet::Bootstrap(JulietMain, argc, argv);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef struct HINSTANCE__* HINSTANCE;
|
||||
typedef char* LPSTR;
|
||||
typedef wchar_t* PWSTR;
|
||||
|
||||
#if UNICODE
|
||||
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrev, PWSTR szCmdLine, int sw)
|
||||
#else
|
||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
|
||||
#endif
|
||||
{
|
||||
(void)hInst;
|
||||
(void)hPrev;
|
||||
(void)szCmdLine;
|
||||
(void)sw;
|
||||
return Juliet::Bootstrap(JulietMain, __argc, __wargv);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "Only windows main is implemented"
|
||||
#endif
|
||||
@@ -24,6 +24,18 @@ namespace Juliet
|
||||
return lhs < rhs ? rhs : lhs;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type ClampTop(Type value, Type X)
|
||||
{
|
||||
return Min(value, X);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type ClampBottom(Type value, Type X)
|
||||
{
|
||||
return Max(value, X);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
constexpr Type Clamp(Type val, Type min, Type max)
|
||||
{
|
||||
|
||||
@@ -2,12 +2,58 @@
|
||||
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/Common/NonNullPtr.h>
|
||||
#include <Core/Common/String.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
#include <Juliet.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
|
||||
constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
|
||||
constexpr global uint64 k_ArenaHeaderSize = 128;
|
||||
|
||||
// Refactor
|
||||
struct Arena
|
||||
{
|
||||
Arena* Previous;
|
||||
Arena* Current;
|
||||
|
||||
uint64 BasePosition;
|
||||
uint64 Position;
|
||||
uint64 Capacity;
|
||||
uint64 Alignment;
|
||||
|
||||
uint64 CommitSize;
|
||||
uint64 ReserveSize;
|
||||
|
||||
uint64 Committed;
|
||||
uint64 Reserved;
|
||||
};
|
||||
static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
|
||||
|
||||
struct ArenaParams
|
||||
{
|
||||
uint64 ReserveSize = g_Arena_Default_Reserve_Size;
|
||||
uint64 CommitSize = g_Arena_Default_Commit_Size;
|
||||
};
|
||||
|
||||
[[nodiscard]] Arena* ArenaAllocate(const ArenaParams& params = {},
|
||||
const std::source_location& loc = std::source_location::current());
|
||||
void ArenaRelease(NonNullPtr<Arena> arena);
|
||||
|
||||
// Raw Push, can be used but templated helpers exists below
|
||||
[[nodiscard]] void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align, bool shouldBeZeroed);
|
||||
void ArenaPopTo(NonNullPtr<Arena> arena, size_t position);
|
||||
void ArenaPop(NonNullPtr<Arena> arena, size_t amount);
|
||||
void ArenaClear(NonNullPtr<Arena> arena);
|
||||
[[nodiscard]] size_t ArenaPos(NonNullPtr<Arena> arena);
|
||||
|
||||
template <typename Type>
|
||||
[[nodiscard]] Type* ArenaPushStruct(NonNullPtr<Arena> arena)
|
||||
{
|
||||
return static_cast<Type*>(ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type), true));
|
||||
}
|
||||
|
||||
// --- Paged Memory Architecture ---
|
||||
struct ArenaAllocation
|
||||
@@ -25,23 +71,23 @@ namespace Juliet
|
||||
MemoryBlock* Next; // Next block in the chain (Arena) or FreeList (Pool)
|
||||
size_t TotalSize; // Total size of this block (including header)
|
||||
size_t Used; // Offset relative to the start of Data
|
||||
|
||||
|
||||
#if JULIET_DEBUG
|
||||
ArenaAllocation* FirstAllocation = nullptr;
|
||||
uint64 Pad; // Ensure 16-byte alignment (Size 40 -> 48)
|
||||
#endif
|
||||
|
||||
// Data follows immediately.
|
||||
// Data follows immediately.
|
||||
// We use a helper to access it to avoid C++ flexible array warning issues if strict
|
||||
uint8* GetData() { return reinterpret_cast<uint8*>(this + 1); }
|
||||
uint8* GetData() { return reinterpret_cast<uint8*>(this + 1); }
|
||||
const uint8* GetData() const { return reinterpret_cast<const uint8*>(this + 1); }
|
||||
};
|
||||
|
||||
struct MemoryPool
|
||||
{
|
||||
void* BaseAddress = nullptr;
|
||||
size_t TotalSize = 0;
|
||||
MemoryBlock* FreeList = nullptr;
|
||||
size_t TotalSize = 0;
|
||||
MemoryBlock* FreeList = nullptr;
|
||||
|
||||
[[nodiscard]] MemoryBlock* AllocateBlock(size_t minCapacity);
|
||||
void FreeBlock(MemoryBlock* block);
|
||||
@@ -52,7 +98,7 @@ namespace Juliet
|
||||
MemoryPool* BackingPool;
|
||||
MemoryBlock* CurrentBlock;
|
||||
MemoryBlock* FirstBlock;
|
||||
// Marker behavior is now tricky with pages.
|
||||
// Marker behavior is now tricky with pages.
|
||||
// Simple Marker = { Block*, Offset }
|
||||
};
|
||||
|
||||
@@ -62,12 +108,11 @@ namespace Juliet
|
||||
size_t Offset;
|
||||
};
|
||||
|
||||
|
||||
JULIET_API void MemoryArenaCreate(MemoryArena* arena, MemoryPool* pool);
|
||||
JULIET_API void MemoryArenaCreate(MemoryArena* arena, MemoryPool* pool);
|
||||
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment, String tag);
|
||||
JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment, String tag);
|
||||
JULIET_API bool ArenaPop(MemoryArena* arena, void* ptr, size_t size);
|
||||
JULIET_API void ArenaReset(MemoryArena* arena);
|
||||
JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment, String tag);
|
||||
JULIET_API bool ArenaPop(MemoryArena* arena, void* ptr, size_t size);
|
||||
JULIET_API void ArenaReset(MemoryArena* arena);
|
||||
JULIET_API ArenaMarker ArenaGetMarker(MemoryArena* arena);
|
||||
JULIET_API void ArenaResetToMarker(MemoryArena* arena, ArenaMarker marker);
|
||||
|
||||
|
||||
@@ -22,4 +22,6 @@ namespace Juliet
|
||||
// TODO: homemade versions
|
||||
#define MemSet memset
|
||||
#define MemCopy memcpy
|
||||
|
||||
#define MemoryZero(dst, size) MemSet(dst, 0, size)
|
||||
} // namespace Juliet
|
||||
|
||||
29
Juliet/src/Core/HAL/OS/OS.cpp
Normal file
29
Juliet/src/Core/HAL/OS/OS.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
#include <Core/HAL/OS/OS_Private.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
Byte* OS_Reserve(size_t size)
|
||||
{
|
||||
return Internal::OS_Reserve(size);
|
||||
}
|
||||
|
||||
bool OS_Commit(Byte* ptr, size_t size)
|
||||
{
|
||||
return Internal::OS_Commit(ptr, size);
|
||||
}
|
||||
|
||||
void OS_Release(Byte* ptr, size_t size)
|
||||
{
|
||||
Internal::OS_Release(ptr, size);
|
||||
}
|
||||
} // namespace Memory
|
||||
|
||||
int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
|
||||
{
|
||||
return Internal::OS_Main(entryPointFunc, argc, argv);
|
||||
}
|
||||
|
||||
} // namespace Juliet
|
||||
19
Juliet/src/Core/HAL/OS/OS_Private.h
Normal file
19
Juliet/src/Core/HAL/OS/OS_Private.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
Byte* OS_Reserve(size_t size);
|
||||
bool OS_Commit(Byte* ptr, size_t size);
|
||||
void OS_Release(Byte* ptr, size_t size);
|
||||
} // namespace Internal
|
||||
} // namespace Memory
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
|
||||
}
|
||||
} // namespace Juliet
|
||||
84
Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp
Normal file
84
Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
#include <Core/HAL/OS/OS_Private.h>
|
||||
#include <Core/HAL/Win32.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
namespace
|
||||
{
|
||||
global RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {};
|
||||
}
|
||||
|
||||
namespace Memory::Internal
|
||||
{
|
||||
Byte* OS_Reserve(size_t size)
|
||||
{
|
||||
auto result = static_cast<Byte*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool OS_Commit(Byte* ptr, size_t size)
|
||||
{
|
||||
bool result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != nullptr);
|
||||
|
||||
Assert(size <= static_cast<size_t>(MaxValueOf<DWORD>()));
|
||||
|
||||
w32_rio_functions.RIODeregisterBuffer(
|
||||
w32_rio_functions.RIORegisterBuffer(reinterpret_cast<PCHAR>(ptr), static_cast<DWORD>(size)));
|
||||
return result;
|
||||
}
|
||||
|
||||
void OS_Release(Byte* ptr, size_t size)
|
||||
{
|
||||
// size not used on windows
|
||||
std::ignore = size;
|
||||
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
} // namespace Memory::Internal
|
||||
|
||||
namespace
|
||||
{
|
||||
// Used to handle a crash/exception
|
||||
LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionPtrs)
|
||||
{
|
||||
(void)exceptionPtrs;
|
||||
// See for more info https://github.com/EpicGamesExt/raddebugger/blob/master/src/os/core/win32/os_core_win32.c
|
||||
ExitProcess(1);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
SetUnhandledExceptionFilter(&ExceptionFilter);
|
||||
|
||||
// Allow only one instance to be launched.
|
||||
CreateMutex(nullptr, false, L"Local\\Juliet.App");
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
MessageBox(nullptr, L"An instance of Juliet is already running.", L"Juliet", MB_OK | MB_ICONEXCLAMATION);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Create a dummy socket to access RIO functions. Those will be used to do fine memory management
|
||||
{
|
||||
WSADATA WinSockData;
|
||||
WSAStartup(MAKEWORD(2, 2), &WinSockData);
|
||||
GUID guid = WSAID_MULTIPLE_RIO;
|
||||
DWORD rio_byte = 0;
|
||||
SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
||||
(void**)&w32_rio_functions, sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
|
||||
closesocket(Sock);
|
||||
}
|
||||
|
||||
return entryPointFunc(argc, argv);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Juliet
|
||||
@@ -26,7 +26,7 @@
|
||||
#define WINVER _WIN32_WINNT
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#define NOIME
|
||||
@@ -66,6 +66,11 @@
|
||||
#define NOTAPE
|
||||
#define ANSI_ONLY
|
||||
|
||||
// Keep includes in that order
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include <MSWSock.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#undef min
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Core/HAL/Display/Display_Private.h>
|
||||
#include <Core/HAL/Filesystem/Filesystem_Private.h>
|
||||
#include <Core/JulietInit.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
|
||||
namespace Juliet
|
||||
@@ -41,11 +42,6 @@ namespace Juliet
|
||||
|
||||
void JulietInit(JulietInit_Flags flags)
|
||||
{
|
||||
// Mandatory systems
|
||||
MemoryArenasInit();
|
||||
|
||||
InitFilesystem();
|
||||
|
||||
// Optional systems
|
||||
if ((flags & JulietInit_Flags::Display) != JulietInit_Flags::None)
|
||||
{
|
||||
@@ -62,9 +58,6 @@ namespace Juliet
|
||||
DecrementSystemRefCount(JulietInit_Flags::Display);
|
||||
ShutdownDisplaySystem();
|
||||
}
|
||||
|
||||
ShutdownFilesystem();
|
||||
MemoryArenasShutdown();
|
||||
}
|
||||
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -4,10 +4,181 @@
|
||||
#include <Core/Memory/Utils.h>
|
||||
|
||||
#include <algorithm> // For std::max
|
||||
#include <Core/Common/NonNullPtr.h>
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
|
||||
// TODO Get page size from os kernel call (dwPageSize)
|
||||
namespace
|
||||
{
|
||||
constexpr uint64 k_PageSize = Kilobytes(4);
|
||||
} // namespace
|
||||
|
||||
// https://github.com/EpicGamesExt/raddebugger/blob/master/src/base/base_arena.c
|
||||
|
||||
Arena* ArenaAllocate(const ArenaParams& params, const std::source_location& loc)
|
||||
{
|
||||
Log(LogLevel::Message, LogCategory::Core, "Allocating from %s : %ul", loc.file_name(), loc.line());
|
||||
|
||||
Byte* baseMem = nullptr;
|
||||
|
||||
uint64 reserve_size = AlignPow2(params.ReserveSize, k_PageSize);
|
||||
uint64 commit_size = AlignPow2(params.CommitSize, k_PageSize);
|
||||
|
||||
// TODO: handle large pages
|
||||
baseMem = Memory::OS_Reserve(reserve_size);
|
||||
Memory::OS_Commit(baseMem, commit_size);
|
||||
|
||||
Arena* arena = reinterpret_cast<Arena*>(baseMem);
|
||||
arena->Current = arena;
|
||||
|
||||
arena->CommitSize = commit_size;
|
||||
arena->ReserveSize = reserve_size;
|
||||
|
||||
arena->Committed = commit_size;
|
||||
arena->Reserved = reserve_size;
|
||||
|
||||
arena->BasePosition = 0;
|
||||
arena->Position = k_ArenaHeaderSize;
|
||||
|
||||
return arena;
|
||||
}
|
||||
|
||||
void ArenaRelease(NonNullPtr<Arena> arena)
|
||||
{
|
||||
for (Arena *node = arena->Current, *previous = nullptr; node != nullptr; node = previous)
|
||||
{
|
||||
previous = node->Previous;
|
||||
Memory::OS_Release(node, node->Reserved);
|
||||
}
|
||||
}
|
||||
|
||||
void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align, bool shouldBeZeroed)
|
||||
{
|
||||
Arena* current = arena->Current;
|
||||
size_t positionPrePush = AlignPow2(current->Position, align);
|
||||
size_t positionPostPush = positionPrePush + size;
|
||||
|
||||
// If allowed and needed, add a new block and chain it to the arena.
|
||||
if (current->Reserved < positionPostPush /* flags : chaining allowed */)
|
||||
{
|
||||
Arena* newBlock = nullptr;
|
||||
// TODO : use the free list
|
||||
|
||||
if (newBlock == nullptr)
|
||||
{
|
||||
size_t reserveSize = current->ReserveSize;
|
||||
size_t commitSize = current->CommitSize;
|
||||
|
||||
if (size + k_ArenaHeaderSize > reserveSize)
|
||||
{
|
||||
reserveSize = AlignPow2(size + k_ArenaHeaderSize, align);
|
||||
commitSize = AlignPow2(size + k_ArenaHeaderSize, align);
|
||||
}
|
||||
newBlock = ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize });
|
||||
}
|
||||
|
||||
newBlock->BasePosition = current->BasePosition + current->Reserved;
|
||||
// Push on the linkedlist
|
||||
newBlock->Previous = arena->Current;
|
||||
arena->Current = newBlock;
|
||||
|
||||
// TODO: Think about ryan fleur way to push:
|
||||
// SLLStackPush_N(arena->current, new_block, prev);
|
||||
// #define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||
|
||||
current = newBlock;
|
||||
positionPrePush = AlignPow2(current->Position, align);
|
||||
positionPostPush = positionPrePush + size;
|
||||
}
|
||||
|
||||
size_t sizeToZero = 0;
|
||||
if (shouldBeZeroed)
|
||||
{
|
||||
sizeToZero = Min(current->Committed, positionPostPush) - positionPrePush;
|
||||
}
|
||||
|
||||
// If needed commit new pages
|
||||
if (current->Committed < positionPostPush)
|
||||
{
|
||||
size_t commitPostAligned = positionPostPush + current->CommitSize - 1;
|
||||
commitPostAligned -= commitPostAligned % current->CommitSize;
|
||||
size_t commitPostClamped = ClampTop(commitPostAligned, current->Reserved);
|
||||
// size_t commitSize = commitPostClamped - current->Committed;
|
||||
// Byte* commitPtr = reinterpret_cast<Byte*>(current) + current->Committed;
|
||||
|
||||
// TODO os_commit / commit_large
|
||||
// os_commit(commitPtr, commitSize);
|
||||
|
||||
current->Committed = commitPostClamped;
|
||||
}
|
||||
|
||||
// Push on the current block
|
||||
void* result = nullptr;
|
||||
if (current->Committed >= positionPostPush)
|
||||
{
|
||||
result = reinterpret_cast<Byte*>(current) + positionPrePush;
|
||||
current->Position = positionPostPush;
|
||||
if (sizeToZero != 0)
|
||||
{
|
||||
MemoryZero(result, sizeToZero);
|
||||
}
|
||||
}
|
||||
|
||||
// If alloc failed, log and assert
|
||||
if (result == nullptr) [[unlikely]]
|
||||
{
|
||||
Assert(false, "Fatal Allocation Failure - Unexpected allocation failure");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ArenaPopTo(NonNullPtr<Arena> arena, size_t position)
|
||||
{
|
||||
size_t bbbPosition = ClampBottom(k_ArenaHeaderSize, position);
|
||||
Arena* current = arena->Current;
|
||||
|
||||
// TODO : Free list
|
||||
for (Arena* previous = nullptr; current->BasePosition >= bbbPosition; current = previous)
|
||||
{
|
||||
previous = current->Previous;
|
||||
Memory::OS_Release(current, current->Reserved);
|
||||
}
|
||||
|
||||
arena->Current = current;
|
||||
size_t newPosition = bbbPosition - current->BasePosition;
|
||||
Assert(newPosition <= current->Position);
|
||||
current->Position = newPosition;
|
||||
}
|
||||
|
||||
void ArenaPop(NonNullPtr<Arena> arena, size_t amount)
|
||||
{
|
||||
size_t oldPosition = ArenaPos(arena);
|
||||
size_t newPosition = oldPosition;
|
||||
if (amount < oldPosition)
|
||||
{
|
||||
newPosition = oldPosition - amount;
|
||||
}
|
||||
ArenaPopTo(arena, newPosition);
|
||||
}
|
||||
|
||||
void ArenaClear(NonNullPtr<Arena> arena)
|
||||
{
|
||||
ArenaPopTo(arena, 0);
|
||||
}
|
||||
|
||||
size_t ArenaPos(NonNullPtr<Arena> arena)
|
||||
{
|
||||
Arena* current = arena->Current;
|
||||
size_t position = current->BasePosition + current->Position;
|
||||
return position;
|
||||
}
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
extern void TestMemoryArena();
|
||||
@@ -18,7 +189,10 @@ namespace Juliet
|
||||
#if JULIET_DEBUG
|
||||
static void FreeDebugAllocations(MemoryBlock* blk)
|
||||
{
|
||||
if (!blk) return;
|
||||
if (!blk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ArenaAllocation* curr = blk->FirstAllocation;
|
||||
while (curr)
|
||||
{
|
||||
@@ -188,23 +362,25 @@ namespace Juliet
|
||||
// Commit
|
||||
blk->Used += alignmentOffset;
|
||||
void* ptr = blk->GetData() + blk->Used;
|
||||
|
||||
|
||||
#if JULIET_DEBUG
|
||||
ArenaAllocation* node = (ArenaAllocation*)Malloc(sizeof(ArenaAllocation));
|
||||
node->Offset = blk->Used;
|
||||
node->Size = size;
|
||||
node->Tag = tag;
|
||||
node->Next = nullptr;
|
||||
|
||||
if (!blk->FirstAllocation) blk->FirstAllocation = node;
|
||||
node->Offset = blk->Used;
|
||||
node->Size = size;
|
||||
node->Tag = tag;
|
||||
node->Next = nullptr;
|
||||
|
||||
if (!blk->FirstAllocation)
|
||||
blk->FirstAllocation = node;
|
||||
else
|
||||
{
|
||||
ArenaAllocation* t = blk->FirstAllocation;
|
||||
while(t->Next) t = t->Next;
|
||||
t->Next = node;
|
||||
ArenaAllocation* t = blk->FirstAllocation;
|
||||
while (t->Next)
|
||||
t = t->Next;
|
||||
t->Next = node;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
blk->Used += size;
|
||||
|
||||
return ptr;
|
||||
@@ -234,7 +410,8 @@ namespace Juliet
|
||||
#if JULIET_DEBUG
|
||||
{
|
||||
ArenaAllocation* t = blk->FirstAllocation;
|
||||
while (t && t->Next) t = t->Next;
|
||||
while (t && t->Next)
|
||||
t = t->Next;
|
||||
if (t) t->Size += (newSize - oldSize);
|
||||
}
|
||||
#endif
|
||||
@@ -268,13 +445,24 @@ namespace Juliet
|
||||
blk->Used -= size;
|
||||
#if JULIET_DEBUG
|
||||
{
|
||||
ArenaAllocation* t = blk->FirstAllocation;
|
||||
ArenaAllocation* t = blk->FirstAllocation;
|
||||
ArenaAllocation* prev = nullptr;
|
||||
while (t && t->Next) { prev = t; t = t->Next; }
|
||||
if (t) {
|
||||
while (t && t->Next)
|
||||
{
|
||||
prev = t;
|
||||
t = t->Next;
|
||||
}
|
||||
if (t)
|
||||
{
|
||||
SafeFree(t);
|
||||
if (prev) prev->Next = nullptr;
|
||||
else blk->FirstAllocation = nullptr;
|
||||
if (prev)
|
||||
{
|
||||
prev->Next = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
blk->FirstAllocation = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,12 +7,56 @@
|
||||
|
||||
namespace Juliet::UnitTest
|
||||
{
|
||||
struct TestStruct
|
||||
{
|
||||
uint8 First;
|
||||
uint16 Second;
|
||||
};
|
||||
// Need access to internal Pool functions? They are in the header now!
|
||||
// MemoryPool is declared in header.
|
||||
void TestMemoryArena()
|
||||
{
|
||||
printf("Running Paged Memory Arena Tests...\n");
|
||||
|
||||
// New Arena!
|
||||
Arena* testArena = ArenaAllocate();
|
||||
|
||||
size_t pos = ArenaPos(testArena);
|
||||
Assert(pos == k_ArenaHeaderSize);
|
||||
|
||||
TestStruct* myStruct = ArenaPushStruct<TestStruct>(testArena);
|
||||
Assert(myStruct->First == 0);
|
||||
Assert(myStruct->Second == 0);
|
||||
pos = ArenaPos(testArena);
|
||||
Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct));
|
||||
|
||||
TestStruct* myStruct2 = ArenaPushStruct<TestStruct>(testArena);
|
||||
Assert(myStruct2->First == 0);
|
||||
Assert(myStruct2->Second == 0);
|
||||
|
||||
myStruct->First = 5;
|
||||
myStruct->Second = 125;
|
||||
myStruct2->First = 5;
|
||||
myStruct2->Second = 125;
|
||||
|
||||
ArenaClear(testArena);
|
||||
pos = ArenaPos(testArena);
|
||||
Assert(pos == k_ArenaHeaderSize);
|
||||
|
||||
myStruct = ArenaPushStruct<TestStruct>(testArena);
|
||||
Assert(myStruct->First == 0);
|
||||
Assert(myStruct->Second == 0);
|
||||
pos = ArenaPos(testArena);
|
||||
Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct));
|
||||
|
||||
TestStruct* myStruct3 = ArenaPushStruct<TestStruct>(testArena);
|
||||
Assert(myStruct3->First == 0);
|
||||
Assert(myStruct3->Second == 0);
|
||||
pos = ArenaPos(testArena);
|
||||
Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct) * 2);
|
||||
|
||||
ArenaRelease(testArena);
|
||||
|
||||
// Setup Pool and Arena for Pop Tests
|
||||
size_t testPoolSize = Megabytes(1);
|
||||
void* testBacking = Calloc(1, testPoolSize);
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
// Windows uses a non standard header to define its socket types.
|
||||
// Because of that we need to include those in this header.
|
||||
// TODO : implement for other platforms
|
||||
#if JULIET_WIN32
|
||||
|
||||
#include <WinSock2.h>
|
||||
|
||||
#else
|
||||
// UNIMPLEMENT_SOCKETS
|
||||
#endif
|
||||
// #if JULIET_WIN32
|
||||
// #include <WinSock2.h>
|
||||
// #else
|
||||
// // UNIMPLEMENT_SOCKETS
|
||||
// #endif
|
||||
|
||||
namespace Juliet::SocketImpl
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <Core/HAL/Win32.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Networking/Socket.h>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/HAL/Filesystem/Filesystem_Private.h>
|
||||
#include <Core/JulietInit.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
@@ -129,12 +130,18 @@ namespace Juliet
|
||||
void InitializeEngine(JulietInit_Flags flags)
|
||||
{
|
||||
InitializeLogManager();
|
||||
MemoryArenasInit();
|
||||
InitFilesystem();
|
||||
|
||||
JulietInit(flags);
|
||||
}
|
||||
|
||||
void ShutdownEngine()
|
||||
{
|
||||
JulietShutdown();
|
||||
|
||||
ShutdownFilesystem();
|
||||
MemoryArenasShutdown();
|
||||
ShutdownLogManager();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,15 @@
|
||||
}
|
||||
.LinkerOptions + .CRTLibs
|
||||
|
||||
// Pointing the entry point
|
||||
.SubSystem = ' /SUBSYSTEM:WINDOWS'
|
||||
If ( .BuildConfigName == 'Debug' )
|
||||
{
|
||||
^SubSystem = ' /SUBSYSTEM:WINDOWS' // We use console in debug
|
||||
|
||||
}
|
||||
.LinkerOptions + .SubSystem
|
||||
|
||||
// Manifest
|
||||
.LinkerAssemblyResources = .ManifestFile
|
||||
.LinkerOptions + ' /MANIFEST:EMBED'
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <Core/JulietInit.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Main.h>
|
||||
#include <Core/Math/Matrix.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
@@ -23,7 +24,6 @@
|
||||
#include <Juliet.h>
|
||||
|
||||
#ifdef JULIET_ENABLE_IMGUI
|
||||
#include <Graphics/ImGuiRenderer.h>
|
||||
#include <imgui.h>
|
||||
#endif
|
||||
|
||||
@@ -454,19 +454,8 @@ JulietApplication& GetEditorApplication()
|
||||
return EditorApplication;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char** /*argv*/)
|
||||
int JulietMain(int, wchar_t**)
|
||||
{
|
||||
// Allow only one instance to be launched.
|
||||
// Need to create Mutex code in the lib because i dont want to include windows.h in this file anymore
|
||||
// CreateMutex(0, false, L"Local\\Juliet.App");
|
||||
// if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
// {
|
||||
// MessageBox(nullptr, L"An instance of Juliet is already running.", L"Juliet", MB_OK | MB_ICONEXCLAMATION);
|
||||
// return EXIT_FAILURE;
|
||||
// }
|
||||
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
|
||||
if (__argc > 1)
|
||||
{
|
||||
for (int i = 1; i < __argc; ++i)
|
||||
|
||||
Reference in New Issue
Block a user