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:
2026-01-31 23:20:26 -05:00
parent 0a75554071
commit 45ef1134f7
22 changed files with 647 additions and 64 deletions

View File

@@ -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

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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

View 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

View File

@@ -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

View 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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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
{

View File

@@ -1,3 +1,4 @@
#include <Core/HAL/Win32.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Networking/Socket.h>

View File

@@ -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();
}

View File

@@ -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'

View File

@@ -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)