Added a basic MemoryArena.

Added one scratch, one engine and one game arena.
Converted the game alloc to arena + the display stuff.
WIP

Made using Antigravity+gemini
This commit is contained in:
2026-01-17 21:09:23 -05:00
parent 98783b7e8f
commit f95ba51c13
28 changed files with 462 additions and 59 deletions

View File

@@ -0,0 +1,10 @@
---
trigger: always_on
---
No exceptions
Use [[nodiscard]]
auto is allowed but when its a pointer add the * and when reference adds the &
Member variable are CamelCase
Types are CamelCase
Functions are CamelCase.

View File

@@ -1,17 +1,15 @@
--- ---
description: Build the Juliet project using FastBuild description: Build the Juliet project using FastBuild
--- ---
// turbo-all
This workflow sets up the Juliet build environment and runs `fbuild`. This workflow sets up the Juliet build environment and runs `fbuild`.
1. To build a specific configuration (e.g., msvc-Debug): 1. To build a specific configuration (e.g., msvc-Debug):
// turbo
`cmd /c "misc\shell.bat & fbuild msvc-Debug"` `cmd /c "misc\shell.bat & fbuild msvc-Debug"`
2. To build the default (msvc): 2. To build the default (msvc):
// turbo
`cmd /c "misc\shell.bat & fbuild msvc"` `cmd /c "misc\shell.bat & fbuild msvc"`
3. To see all available targets: 3. To see all available targets:
// turbo `cmd /c "misc\shell.bat & fbuild -showtargets"`
`cmd /c "misc\shell.bat & fbuild -targets"`

View File

@@ -0,0 +1,6 @@
---
description: Launch the Juliet application
---
1. Run the launch script
misc\launch.bat autoclose

View File

@@ -1,9 +1,9 @@
--- ---
description: Recompile shaders for the Juliet project description: Recompile shaders for the Juliet project
--- ---
// turbo-all
This workflow recompiles all shaders using the `recompile_shaders.bat` script. This workflow recompiles all shaders using the `recompile_shaders.bat` script.
1. Recompile all shaders: 1. Recompile all shaders:
// turbo
`cmd /c "misc\shell.bat & misc\recompile_shaders.bat"` `cmd /c "misc\shell.bat & misc\recompile_shaders.bat"`

49
AgentData/MemoryArena.md Normal file
View File

@@ -0,0 +1,49 @@
# Memory System Status & Migration Plan
## Completed Work
### Core Systems
- **MemoryArena**: Implemented linear allocator with alignment, markers, and reset support.
- **Global Arenas**:
- `ScratchArena` (64MB): Transient per-frame memory.
- `EngineArena` (256MB): Persistent engine memory (internal).
- `GameArena` (512MB): Persistent game memory (exported to Game DLL).
- **Helpers**: Added `ArenaPushType<T>` and `ArenaPushArray<T>` with automatic zero-initialization.
### Migrated Subsystems
- **Display**: `Win32Window` and `Win32DisplayDevice` now use `EngineArena`.
- **Game Entities**: `Entity.h` uses `GameArena` for entity allocation; manual `free` calls removed from `game.cpp`.
## Remaining Work
The following subsystems still use legacy `malloc`/`calloc`/`realloc`/`free` and need to be migrated.
### Hot Reload System
- **Files**: `Core/HotReload/HotReload.cpp`, `Core/HotReload/Win32/Win32HotReload.cpp`
- **Allocations**: `DLLFullPath`, `LockFullPath`, `tempDllPath`.
- **Strategy**:
- Use `EngineArena` for persistent paths (`DLLFullPath`, `LockFullPath`).
- Use `ScratchArena` for temporary paths (`tempDllPath`).
### IO System
- **Files**: `Core/HAL/IO/IOStream.cpp`, `Core/HAL/IO/Win32/Win32IOStream.cpp`
- **Allocations**: `IOStream` instance, data buffers, `Win32IOStreamDataPayload`.
- **Challenge**: `Realloc` is used for growing buffers.
- **Strategy**:
- `IOStream` struct -> `ScratchArena` (if transient) or `EngineArena`.
- Buffers: Evaluate if `ArenaPush` with large enough capacity is sufficient, or implement a growable buffer on top of arena (or use `std::vector` with custom allocator if absolutely needed, but prefer simple fixed max size if possible).
### Graphics / Debug
- **Files**: `Graphics/DebugDisplayRenderer.cpp`
- **Allocations**: `DepthTestedVertices`, `OverlayVertices`.
- **Strategy**: Use `EngineArena` or a dedicated `RenderArena` if these are persistent. If per-frame, move to `ScratchArena`.
### Shader Compiler
- **Files**: `JulietShaderCompiler/ShaderCompiler.cpp`
- **Allocations**: Argument arrays, file buffers.
- **Strategy**: Use `ScratchArena` for all compilation tasks as they are transient.
### Filesystem
- **Files**: `Core/HAL/Filesystem/Filesystem.cpp`
- **Allocations**: `CachedBasePath`.
- **Strategy**: Migrate to `EngineArena` (persistent).

View File

@@ -3,6 +3,7 @@
#include <concepts> #include <concepts>
#include <Core/Common/CoreUtils.h> #include <Core/Common/CoreUtils.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/MemoryArena.h>
#include <Engine/Class.h> #include <Engine/Class.h>
#include <Entity/EntityManager.h> #include <Entity/EntityManager.h>
#include <type_traits> #include <type_traits>
@@ -17,6 +18,8 @@
constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \ constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \
const Juliet::Class* entity::Kind = &entityKind##entity; const Juliet::Class* entity::Kind = &entityKind##entity;
namespace Game namespace Game
{ {
using DerivedType = void*; using DerivedType = void*;
@@ -46,8 +49,9 @@ namespace Game
requires EntityConcept<EntityType> requires EntityConcept<EntityType>
EntityType* MakeEntity(EntityManager& manager, float x, float y) EntityType* MakeEntity(EntityManager& manager, float x, float y)
{ {
EntityType* result = static_cast<EntityType*>(Juliet::Calloc(1, sizeof(EntityType))); auto* arena = Juliet::GetGameArena();
Entity* base = result->Base = static_cast<Entity*>(Juliet::Calloc(1, sizeof(Entity))); EntityType* result = Juliet::ArenaPushType<EntityType>(arena);
Entity* base = result->Base = Juliet::ArenaPushType<Entity>(arena);
base->X = x; base->X = x;
base->Y = y; base->Y = y;
base->Derived = result; base->Derived = result;

View File

@@ -38,7 +38,7 @@
// Extra Compiler Options // Extra Compiler Options
.CompilerOptions + ' "-IJuliet/include"' .CompilerOptions + ' "-IJuliet/include"'
+ ' "-IGame"' + ' "-IGame"'
// + ' -DGAME_EXPORT' // I'm just always exporting anyway but just in case .CompilerOptions + ' -DJULIET_EXPORT'
#if __WINDOWS__ #if __WINDOWS__
.CompilerOptions + ' -DJULIET_WIN32' .CompilerOptions + ' -DJULIET_WIN32'

View File

@@ -4,11 +4,11 @@
#undef max #undef max
#include <Core/HAL/Filesystem/Filesystem.h> #include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/JulietInit.h>
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h> #include <Core/Memory/MemoryArena.h>
#include <Entity/Entity.h> #include <Entity/Entity.h>
#include <Entity/EntityManager.h> #include <Entity/EntityManager.h>
#include <Graphics/Graphics.h>
// Test code // Test code
namespace Game namespace Game
@@ -31,8 +31,21 @@ namespace Game
using namespace Juliet; using namespace Juliet;
extern "C" __declspec(dllexport) void __cdecl GameInit() extern "C" JULIET_API void GameInit(GameInitParams* /*params*/)
{ {
// Example allocation in GameArena
struct GameState
{
float TotalTime;
int Score;
};
auto* gameState = ArenaPushType<GameState>(GetGameArena());
gameState->TotalTime = 0.0f;
gameState->Score = 0;
printf("Game Arena Allocated: %p\n", gameState);
using namespace Game; using namespace Game;
// Entity Use case // Entity Use case
@@ -41,8 +54,8 @@ extern "C" __declspec(dllexport) void __cdecl GameInit()
Door* door = MakeEntity<Door>(manager, 10.0f, 2.0f); Door* door = MakeEntity<Door>(manager, 10.0f, 2.0f);
door->IsOpened = true; door->IsOpened = true;
Entity* ent = door->Base; Entity* ent = door->Base;
[[maybe_unused]] Door* stillDoor = DownCast<Door>(ent); [[maybe_unused]] Door* stillDoor = DownCast<Door>(ent);
Assert(door == stillDoor); Assert(door == stillDoor);
Rock* rock = MakeEntity<Rock>(manager, 1.f, 2.f); Rock* rock = MakeEntity<Rock>(manager, 1.f, 2.f);
@@ -51,20 +64,14 @@ extern "C" __declspec(dllexport) void __cdecl GameInit()
printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed"); printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed");
printf("Rock has %d health points\n", rock->Health); printf("Rock has %d health points\n", rock->Health);
// Have to manually free for now because im not using arenas or anything
free(door->Base);
free(door);
free(rock->Base);
free(rock);
} }
extern "C" __declspec(dllexport) void __cdecl GameShutdown() extern "C" JULIET_API void __cdecl GameShutdown()
{ {
printf("Shutting down game...\n"); printf("Shutting down game...\n");
} }
extern "C" __declspec(dllexport) void __cdecl GameUpdate([[maybe_unused]] float deltaTime) extern "C" JULIET_API void __cdecl GameUpdate([[maybe_unused]] float deltaTime)
{ {
//printf("Updating game...\n"); // printf("Updating game...\n");
} }

View File

@@ -57,6 +57,7 @@
<CustomBuild Include="include\Core\Math\Shape.h" /> <CustomBuild Include="include\Core\Math\Shape.h" />
<CustomBuild Include="include\Core\Math\Vector.h" /> <CustomBuild Include="include\Core\Math\Vector.h" />
<CustomBuild Include="include\Core\Memory\Allocator.h" /> <CustomBuild Include="include\Core\Memory\Allocator.h" />
<CustomBuild Include="include\Core\Memory\MemoryArena.h" />
<CustomBuild Include="include\Core\Memory\Utils.h" /> <CustomBuild Include="include\Core\Memory\Utils.h" />
<CustomBuild Include="include\Core\Networking\IPAddress.h" /> <CustomBuild Include="include\Core\Networking\IPAddress.h" />
<CustomBuild Include="include\Core\Networking\NetworkPacket.h" /> <CustomBuild Include="include\Core\Networking\NetworkPacket.h" />
@@ -118,6 +119,9 @@
<CustomBuild Include="src\Core\Math\Math_Private.h" /> <CustomBuild Include="src\Core\Math\Math_Private.h" />
<CustomBuild Include="src\Core\Math\MathRound.cpp" /> <CustomBuild Include="src\Core\Math\MathRound.cpp" />
<CustomBuild Include="src\Core\Memory\Allocator.cpp" /> <CustomBuild Include="src\Core\Memory\Allocator.cpp" />
<CustomBuild Include="src\Core\Memory\EngineArena.h" />
<CustomBuild Include="src\Core\Memory\MemoryArena.cpp" />
<CustomBuild Include="src\Core\Memory\MemoryArenaTests.cpp" />
<CustomBuild Include="src\Core\Networking\NetworkPacket.cpp" /> <CustomBuild Include="src\Core\Networking\NetworkPacket.cpp" />
<CustomBuild Include="src\Core\Networking\Socket.cpp" /> <CustomBuild Include="src\Core\Networking\Socket.cpp" />
<CustomBuild Include="src\Core\Networking\SocketPlatformImpl.h" /> <CustomBuild Include="src\Core\Networking\SocketPlatformImpl.h" />

View File

@@ -91,6 +91,9 @@
<CustomBuild Include="include\Core\Memory\Allocator.h"> <CustomBuild Include="include\Core\Memory\Allocator.h">
<Filter>include\Core\Memory</Filter> <Filter>include\Core\Memory</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="include\Core\Memory\MemoryArena.h">
<Filter>include\Core\Memory</Filter>
</CustomBuild>
<CustomBuild Include="include\Core\Memory\Utils.h"> <CustomBuild Include="include\Core\Memory\Utils.h">
<Filter>include\Core\Memory</Filter> <Filter>include\Core\Memory</Filter>
</CustomBuild> </CustomBuild>
@@ -273,6 +276,15 @@
<CustomBuild Include="src\Core\Memory\Allocator.cpp"> <CustomBuild Include="src\Core\Memory\Allocator.cpp">
<Filter>src\Core\Memory</Filter> <Filter>src\Core\Memory</Filter>
</CustomBuild> </CustomBuild>
<CustomBuild Include="src\Core\Memory\EngineArena.h">
<Filter>src\Core\Memory</Filter>
</CustomBuild>
<CustomBuild Include="src\Core\Memory\MemoryArena.cpp">
<Filter>src\Core\Memory</Filter>
</CustomBuild>
<CustomBuild Include="src\Core\Memory\MemoryArenaTests.cpp">
<Filter>src\Core\Memory</Filter>
</CustomBuild>
<CustomBuild Include="src\Core\Networking\NetworkPacket.cpp"> <CustomBuild Include="src\Core\Networking\NetworkPacket.cpp">
<Filter>src\Core\Networking</Filter> <Filter>src\Core\Networking</Filter>
</CustomBuild> </CustomBuild>

View File

@@ -13,6 +13,14 @@ namespace Juliet
All = 0xFb All = 0xFb
}; };
struct MemoryArena;
struct GameInitParams
{
MemoryArena* GameArena;
MemoryArena* ScratchArena;
};
void JulietInit(JulietInit_Flags flags); void JulietInit(JulietInit_Flags flags);
void JulietShutdown(); void JulietShutdown();
} // namespace Juliet } // namespace Juliet

View File

@@ -0,0 +1,61 @@
#pragma once
#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
#include <Core/Common/CoreUtils.h>
#include <Core/Memory/Utils.h>
namespace Juliet
{
struct MemoryArena
{
uint8* Data;
size_t Size;
size_t Offset;
};
JULIET_API void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size);
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment = 16);
JULIET_API void ArenaReset(MemoryArena* arena);
JULIET_API size_t ArenaGetMarker(MemoryArena* arena);
JULIET_API void ArenaResetToMarker(MemoryArena* arena, size_t marker);
// --- Global Arenas & Management ---
// Returns a global arena that resets every frame.
JULIET_API MemoryArena* GetScratchArena();
// Persistent game arena.
JULIET_API MemoryArena* GetGameArena();
// Internal engine function to reset the scratch arena.
JULIET_API void ScratchArenaReset();
// Internal engine function to initialize memory arenas.
void MemoryArenasInit();
// Internal engine function to shutdown memory arenas.
void MemoryArenasShutdown();
template <typename T>
inline T* ArenaPushType(MemoryArena* arena)
{
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T), alignof(T)));
if (result)
{
MemSet(result, 0, sizeof(T));
}
return result;
}
template <typename T>
inline T* ArenaPushArray(MemoryArena* arena, size_t count)
{
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T) * count, alignof(T)));
if (result)
{
MemSet(result, 0, sizeof(T) * count);
}
return result;
}
} // namespace Juliet

View File

@@ -2,6 +2,8 @@
#include <Core/HAL/Display/Display_Private.h> #include <Core/HAL/Display/Display_Private.h>
#include <Core/HAL/Display/DisplayDevice.h> #include <Core/HAL/Display/DisplayDevice.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Memory/EngineArena.h>
#include <format> #include <format>
namespace Juliet namespace Juliet
@@ -72,7 +74,8 @@ namespace Juliet
{ {
Assert(g_CurrentDisplayDevice->CreatePlatformWindow); Assert(g_CurrentDisplayDevice->CreatePlatformWindow);
auto window = static_cast<Window*>(Calloc(1, sizeof(Window))); MemoryArena* arena = GetEngineArena();
auto window = ArenaPushType<Window>(arena);
if (!window) if (!window)
{ {
return nullptr; return nullptr;
@@ -80,9 +83,8 @@ namespace Juliet
window->Width = width; window->Width = width;
window->Height = height; window->Height = height;
// TODO String creator that copy
auto titleLen = StringLength(title); auto titleLen = StringLength(title);
auto buffer = static_cast<char*>(Calloc(titleLen, sizeof(char))); auto buffer = ArenaPushArray<char>(arena, titleLen);
MemCopy(buffer, title, titleLen); MemCopy(buffer, title, titleLen);
window->Title.Data = buffer; window->Title.Data = buffer;
@@ -91,7 +93,8 @@ namespace Juliet
g_CurrentDisplayDevice->MainWindow = window; g_CurrentDisplayDevice->MainWindow = window;
if (!g_CurrentDisplayDevice->CreatePlatformWindow(g_CurrentDisplayDevice, window)) if (!g_CurrentDisplayDevice->CreatePlatformWindow(g_CurrentDisplayDevice, window))
{ {
// TODO : Destroy // Note: We don't "free" from arena easily, but since this is catastrophic
// and persistent, we just leak the small amount of arena space or handle it if we had a marker.
return nullptr; return nullptr;
} }
@@ -107,13 +110,12 @@ namespace Juliet
HideWindow(window); HideWindow(window);
// TODO : Free string function // We don't free from arena, these are persistent until shutdown.
SafeFree(window->Title.Data); window->Title.Data = nullptr;
window->Title.Size = 0; window->Title.Size = 0;
g_CurrentDisplayDevice->DestroyPlatformWindow(g_CurrentDisplayDevice, window); g_CurrentDisplayDevice->DestroyPlatformWindow(g_CurrentDisplayDevice, window);
Free(window.Get());
g_CurrentDisplayDevice->MainWindow = nullptr; g_CurrentDisplayDevice->MainWindow = nullptr;
} }

View File

@@ -2,6 +2,8 @@
#include <Core/HAL/Display/Win32/Win32DisplayEvent.h> #include <Core/HAL/Display/Win32/Win32DisplayEvent.h>
#include <Core/HAL/Display/Win32/Win32Window.h> #include <Core/HAL/Display/Win32/Win32Window.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/EngineArena.h>
#include <Core/Memory/Utils.h>
namespace Juliet::Win32 namespace Juliet::Win32
{ {
@@ -12,14 +14,12 @@ namespace Juliet::Win32
return true; return true;
} }
void Shutdown(NonNullPtr<DisplayDevice> /*self*/) {} void Shutdown(NonNullPtr<DisplayDevice> /*self*/) {}
void Free(NonNullPtr<DisplayDevice> self) void Free(NonNullPtr<DisplayDevice> /*self*/) {}
{
Juliet::Free(self.Get());
}
DisplayDevice* CreateDevice() DisplayDevice* CreateDevice()
{ {
auto device = static_cast<DisplayDevice*>(Calloc(1, sizeof(DisplayDevice))); auto device = ArenaPushType<DisplayDevice>(GetEngineArena());
if (!device) if (!device)
{ {
return nullptr; return nullptr;

View File

@@ -2,6 +2,8 @@
#include <Core/HAL/Display/Win32/Win32Window.h> #include <Core/HAL/Display/Win32/Win32Window.h>
#include <Core/HAL/Display/Window.h> #include <Core/HAL/Display/Window.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/EngineArena.h>
#include <Core/Memory/Utils.h>
namespace Juliet::Win32 namespace Juliet::Win32
{ {
@@ -12,7 +14,8 @@ namespace Juliet::Win32
bool SetupWindowState(NonNullPtr<DisplayDevice> /*self*/, NonNullPtr<Window> window, HWND handle) bool SetupWindowState(NonNullPtr<DisplayDevice> /*self*/, NonNullPtr<Window> window, HWND handle)
{ {
auto state = static_cast<Window32State*>(Calloc(1, sizeof(Window32State))); auto state = ArenaPushType<Window32State>(GetEngineArena());
window->State = state; window->State = state;
state->Handle = handle; state->Handle = handle;
state->Window = window; state->Window = window;
@@ -31,8 +34,6 @@ namespace Juliet::Win32
{ {
ReleaseDC(state->Handle, state->HDC); ReleaseDC(state->Handle, state->HDC);
DestroyWindow(state->Handle); DestroyWindow(state->Handle);
SafeFree(state);
} }
window->State = nullptr; window->State = nullptr;
} }

View File

@@ -3,6 +3,8 @@
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h> #include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/EngineArena.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Thread/Thread.h> #include <Core/Thread/Thread.h>
#define MAX_TRIES 100 #define MAX_TRIES 100
@@ -21,11 +23,11 @@ namespace Juliet
// First allocate all the full path. // First allocate all the full path.
// TODO: Add path composition into filesystem + string format + string builder // TODO: Add path composition into filesystem + string format + string builder
const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings
code.DLLFullPath.Data = static_cast<char*>(Calloc(dllFullPathLength, sizeof(char))); code.DLLFullPath.Data = ArenaPushArray<char>(GetEngineArena(), dllFullPathLength);
int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName)); int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName));
if (writtenSize < static_cast<int>(dllFullPathLength) - 1) if (writtenSize < static_cast<int>(dllFullPathLength) - 1)
{ {
SafeFree(code.DLLFullPath.Data); // Arena memory persists, no free needed
Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path"); Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path");
return; return;
} }
@@ -33,12 +35,12 @@ namespace Juliet
// Lock filename path // Lock filename path
const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings
code.LockFullPath.Data = static_cast<char*>(Calloc(lockPathLength, sizeof(char))); code.LockFullPath.Data = ArenaPushArray<char>(GetEngineArena(), lockPathLength);
writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename)); writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename));
if (writtenSize < static_cast<int>(lockPathLength) - 1) if (writtenSize < static_cast<int>(lockPathLength) - 1)
{ {
code.LockFullPath.Size = 0; code.LockFullPath.Size = 0;
SafeFree(code.LockFullPath.Data); // Arena memory persists, no free needed
Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path"); Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path");
return; return;
} }
@@ -52,9 +54,9 @@ namespace Juliet
UnloadCode(code); UnloadCode(code);
code.DLLFullPath.Size = 0; code.DLLFullPath.Size = 0;
SafeFree(code.DLLFullPath.Data); // Arena memory persists until engine shutdown
code.LockFullPath.Size = 0; code.LockFullPath.Size = 0;
SafeFree(code.LockFullPath.Data); // Arena memory persists until engine shutdown
} }
void ReloadCode(HotReloadCode& code) void ReloadCode(HotReloadCode& code)

View File

@@ -5,6 +5,7 @@
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h> #include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h> #include <Core/Memory/Allocator.h>
#include <Core/Memory/MemoryArena.h>
namespace Juliet namespace Juliet
{ {
@@ -53,7 +54,10 @@ namespace Juliet
const size_t tempDllMaxBufferSize = const size_t tempDllMaxBufferSize =
basePathLength + StringLength(code.TransientDLLName) + /* _ */ 1 + kTempDLLBufferSizeForID + 1 /* \0 */; basePathLength + StringLength(code.TransientDLLName) + /* _ */ 1 + kTempDLLBufferSizeForID + 1 /* \0 */;
auto tempDllPath = static_cast<char*>(Calloc(tempDllMaxBufferSize, sizeof(char)));
// Allocate from Scratch Arena (transient)
auto tempDllPath = ArenaPushArray<char>(GetScratchArena(), tempDllMaxBufferSize);
for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt) for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt)
{ {
// int to char // int to char
@@ -61,7 +65,7 @@ namespace Juliet
int idLength = snprintf(idToStr, sizeof(idToStr), "%u", code.UniqueID); int idLength = snprintf(idToStr, sizeof(idToStr), "%u", code.UniqueID);
if (idLength < 0) if (idLength < 0)
{ {
SafeFree(tempDllPath); // Scratch memory, no free needed
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path"); Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
return; return;
} }
@@ -70,14 +74,14 @@ namespace Juliet
CStr(code.TransientDLLName)); CStr(code.TransientDLLName));
if (writtenSize < 0) if (writtenSize < 0)
{ {
SafeFree(tempDllPath); // Scratch memory, no free needed
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path"); Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
return; return;
} }
if (static_cast<size_t>(writtenSize) + 1 < basePathLength + static_cast<size_t>(idLength) + code.TransientDLLName.Size) if (static_cast<size_t>(writtenSize) + 1 < basePathLength + static_cast<size_t>(idLength) + code.TransientDLLName.Size)
{ {
SafeFree(tempDllPath); // Scratch memory, no free needed
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path"); Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
return; return;
} }
@@ -109,7 +113,7 @@ namespace Juliet
} }
} }
SafeFree(tempDllPath); // Scratch memory, no free needed
} }
if (!code.IsValid) if (!code.IsValid)

View File

@@ -3,6 +3,7 @@
#include <Core/HAL/Display/Display_Private.h> #include <Core/HAL/Display/Display_Private.h>
#include <Core/HAL/Filesystem/Filesystem_Private.h> #include <Core/HAL/Filesystem/Filesystem_Private.h>
#include <Core/JulietInit.h> #include <Core/JulietInit.h>
#include <Core/Memory/MemoryArena.h>
namespace Juliet namespace Juliet
{ {
@@ -38,9 +39,22 @@ namespace Juliet
} }
} // namespace } // namespace
#if JULIET_DEBUG
namespace UnitTest
{
extern void TestMemoryArena();
}
#endif
void JulietInit(JulietInit_Flags flags) void JulietInit(JulietInit_Flags flags)
{ {
// Mandatory systems // Mandatory systems
MemoryArenasInit();
#if JULIET_DEBUG
UnitTest::TestMemoryArena();
#endif
InitFilesystem(); InitFilesystem();
// Optional systems // Optional systems
@@ -61,6 +75,7 @@ namespace Juliet
} }
ShutdownFilesystem(); ShutdownFilesystem();
MemoryArenasShutdown();
} }
} // namespace Juliet } // namespace Juliet

View File

@@ -0,0 +1,10 @@
#pragma once
#include <Core/Memory/MemoryArena.h>
namespace Juliet
{
// Persistent engine-only arena.
// Not exported to the Game DLL.
MemoryArena* GetEngineArena();
} // namespace Juliet

View File

@@ -0,0 +1,116 @@
#include <Core/Memory/Allocator.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Memory/Utils.h>
namespace Juliet
{
void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size)
{
Assert(arena);
Assert(backingMemory);
arena->Data = static_cast<uint8*>(backingMemory);
arena->Size = size;
arena->Offset = 0;
}
void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment)
{
Assert(arena);
// Alignment must be power of 2
Assert((alignment & (alignment - 1)) == 0);
size_t currentPtr = reinterpret_cast<size_t>(arena->Data + arena->Offset);
size_t offset = (currentPtr + (alignment - 1)) & ~(alignment - 1);
size_t newOffset = offset - reinterpret_cast<size_t>(arena->Data) + size;
if (newOffset > arena->Size)
{
Assert(false, "Memory Arena overflow");
return nullptr;
}
void* result = arena->Data + (offset - reinterpret_cast<size_t>(arena->Data));
arena->Offset = newOffset;
return result;
}
void ArenaReset(MemoryArena* arena)
{
Assert(arena);
arena->Offset = 0;
}
size_t ArenaGetMarker(MemoryArena* arena)
{
Assert(arena);
return arena->Offset;
}
void ArenaResetToMarker(MemoryArena* arena, size_t marker)
{
Assert(arena);
Assert(marker <= arena->Offset);
arena->Offset = marker;
}
// --- Global Arenas & Management ---
namespace
{
MemoryArena g_ScratchArena;
MemoryArena g_EngineArena;
MemoryArena g_GameArena;
void* g_ScratchBacking = nullptr;
void* g_EngineBacking = nullptr;
void* g_GameBacking = nullptr;
constexpr size_t kScratchSize = 64 * 1024 * 1024; // 64MB
constexpr size_t kEngineSize = 256 * 1024 * 1024; // 256MB
constexpr size_t kGameSize = 512 * 1024 * 1024; // 512MB
} // namespace
MemoryArena* GetScratchArena()
{
return &g_ScratchArena;
}
MemoryArena* GetEngineArena()
{
return &g_EngineArena;
}
MemoryArena* GetGameArena()
{
return &g_GameArena;
}
void ScratchArenaReset()
{
ArenaReset(&g_ScratchArena);
}
void MemoryArenasInit()
{
// TODO: Use the VirtualAlloc API for this on windows
g_ScratchBacking = Malloc(kScratchSize);
MemSet(g_ScratchBacking, 0, kScratchSize);
g_EngineBacking = Malloc(kEngineSize);
MemSet(g_EngineBacking, 0, kEngineSize);
g_GameBacking = Malloc(kGameSize);
MemSet(g_GameBacking, 0, kGameSize);
MemoryArenaCreate(&g_ScratchArena, g_ScratchBacking, kScratchSize);
MemoryArenaCreate(&g_EngineArena, g_EngineBacking, kEngineSize);
MemoryArenaCreate(&g_GameArena, g_GameBacking, kGameSize);
}
void MemoryArenasShutdown()
{
SafeFree(g_ScratchBacking);
SafeFree(g_EngineBacking);
SafeFree(g_GameBacking);
}
} // namespace Juliet

View File

@@ -0,0 +1,67 @@
#include <cstdio>
#include <Core/Common/CoreUtils.h>
#include <Core/Memory/MemoryArena.h>
#if JULIET_DEBUG
namespace Juliet::UnitTest
{
void TestMemoryArena()
{
// 1. Core Arena Functionality
uint8 buffer[1024];
MemoryArena arena;
MemoryArenaCreate(&arena, buffer, 1024);
Assert(arena.Offset == 0);
Assert(arena.Size == 1024);
void* p1 = ArenaPush(&arena, 100);
Assert(p1 != nullptr);
Assert(arena.Offset >= 100);
size_t marker = ArenaGetMarker(&arena);
void* p2 = ArenaPush(&arena, 200);
Assert(p2 != nullptr);
Assert(arena.Offset >= marker + 200);
ArenaResetToMarker(&arena, marker);
Assert(arena.Offset == marker);
ArenaReset(&arena);
Assert(arena.Offset == 0);
// 2. Alignment Test
void* p3 = ArenaPush(&arena, 1, 1);
[[maybe_unused]] size_t addr = reinterpret_cast<size_t>(p3);
void* p4 = ArenaPush(&arena, 1, 16);
size_t addr2 = reinterpret_cast<size_t>(p4);
Assert((addr2 % 16) == 0);
// 3. Template Helpers
struct TestData
{
int a;
float b;
};
TestData* data = ArenaPushType<TestData>(&arena);
Assert(data != nullptr);
data->a = 10;
data->b = 20.0f;
TestData* dataArray = ArenaPushArray<TestData>(&arena, 10);
Assert(dataArray != nullptr);
// 4. Scratch Arena
MemoryArena* scratch = GetScratchArena();
Assert(scratch != nullptr);
void* sp = ArenaPush(scratch, 100);
Assert(sp != nullptr);
ScratchArenaReset();
Assert(scratch->Offset == 0);
printf("All MemoryArena tests passed.\n");
}
} // namespace Juliet::UnitTest
#endif

View File

View File

@@ -4,6 +4,7 @@
.ProjectName = 'JulietApp' .ProjectName = 'JulietApp'
.ProjectPath = 'JulietApp' .ProjectPath = 'JulietApp'
.JulietIncludePath = ' "-IJuliet/include"' .JulietIncludePath = ' "-IJuliet/include"'
+ ' "-IJuliet/src"'
.ProjectDefPath = '$_WORKING_DIR_$/$ProjectName$/$ProjectName$.def' .ProjectDefPath = '$_WORKING_DIR_$/$ProjectName$/$ProjectName$.def'
// Library // Library

View File

@@ -376,7 +376,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;DEBUG;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;DEBUG;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions> <AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>
@@ -386,7 +386,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions> <AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>
@@ -396,7 +396,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions> <AdditionalOptions>/std:c++20 /wd5267 /wd4061 /wd4505 /wd4514 /wd4577 /wd4625 /wd4710 /wd4711 /wd4746 /wd4820 /wd5045 /wd5220 /wd5245 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>
@@ -406,7 +406,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;DEBUG;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;DEBUG;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 </AdditionalOptions> <AdditionalOptions>/std:c++20 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>
@@ -416,7 +416,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;PROFILING_ENABLED;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 </AdditionalOptions> <AdditionalOptions>/std:c++20 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>
@@ -426,7 +426,7 @@
<NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine> <NMakeBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache $(ProjectName)-$(Configuration)</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>cd $(SolutionDir) &amp; misc\fbuild -ide -dist -monitor -cache -clean $(ProjectName)-$(Configuration)</NMakeReBuildCommandLine>
<NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;JULIET_WIN32;</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32_LEAN_AND_MEAN;WIN32;_WIN32;__WINDOWS__;_HAS_EXCEPTIONS=0;WIN64;RELEASE;JULIET_WIN32;</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>..\;..\Juliet\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>..\;..\Juliet\include;..\Juliet\src;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared;</NMakeIncludeSearchPath>
<AdditionalOptions>/std:c++20 </AdditionalOptions> <AdditionalOptions>/std:c++20 </AdditionalOptions>
<LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory> <LocalDebuggerWorkingDirectory>$(SolutionDir)\bin\$(Configuration)\</LocalDebuggerWorkingDirectory>
<IntDir>$(SolutionDir)\Intermediate</IntDir> <IntDir>$(SolutionDir)\Intermediate</IntDir>

View File

@@ -17,6 +17,8 @@
#include <Core/Common/String.h> #include <Core/Common/String.h>
#include <Core/Memory/Utils.h> #include <Core/Memory/Utils.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Memory/EngineArena.h>
#include <cstdlib> #include <cstdlib>
// TODO : Replace with message box from framework + call main and not winmain + subsystem // TODO : Replace with message box from framework + call main and not winmain + subsystem
@@ -33,7 +35,7 @@ using namespace Juliet;
namespace namespace
{ {
using GameInit_t = void (*)(void); using GameInit_t = void (*)(GameInitParams*);
using GameShutdown_t = void (*)(void); using GameShutdown_t = void (*)(void);
using GameUpdate_t = void (*)(float deltaTime); using GameUpdate_t = void (*)(float deltaTime);
struct GameFunctionTable struct GameFunctionTable
@@ -158,7 +160,10 @@ void JulietApplication::Init()
InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp")); InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp"));
if ((Running = GameCode.IsValid)) if ((Running = GameCode.IsValid))
{ {
Game.Init(); GameInitParams params;
params.GameArena = GetGameArena();
params.ScratchArena = GetScratchArena();
Game.Init(&params);
} }
// Initialize DebugDisplay // Initialize DebugDisplay
@@ -383,6 +388,9 @@ void JulietApplication::Update()
// Submit Commands // Submit Commands
SubmitCommandLists(cmdList); SubmitCommandLists(cmdList);
// Reset Scratch Arena at the end of the frame
ScratchArenaReset();
} }
bool JulietApplication::IsRunning() bool JulietApplication::IsRunning()

View File

@@ -2,8 +2,21 @@
setlocal setlocal
:: --- 1. Argument Parsing Logic --- :: --- 1. Argument Parsing Logic ---
set "ARG1=%~1" set "ARG1="
set "ARG2=%~2" set "ARG2="
set "AUTOCLOSE=0"
for %%x in (%*) do (
if /I "%%~x"=="autoclose" (
set "AUTOCLOSE=1"
) else (
if not defined ARG1 (
set "ARG1=%%~x"
) else if not defined ARG2 (
set "ARG2=%%~x"
)
)
)
:: Set Defaults :: Set Defaults
set "COMPILER_TYPE=clang" set "COMPILER_TYPE=clang"
@@ -44,6 +57,12 @@ if exist "%APP_DIR%\%APP_EXE%" (
pushd "%APP_DIR%" pushd "%APP_DIR%"
start "" "%APP_EXE%" start "" "%APP_EXE%"
popd popd
if "%AUTOCLOSE%"=="1" (
echo [AUTOCLOSE] Waiting 5 seconds...
timeout /t 5 /nobreak >nul
taskkill /IM "%APP_EXE%" /F >nul 2>&1
)
) else ( ) else (
echo [ERROR] Executable not found at: %APP_DIR%\%APP_EXE% echo [ERROR] Executable not found at: %APP_DIR%\%APP_EXE%
echo Please build first: fbuild JulietApp-%PLATFORM%-%CONFIG% echo Please build first: fbuild JulietApp-%PLATFORM%-%CONFIG%

View File

@@ -73,5 +73,4 @@ for %%F in ("%SOURCE_DIR%\*.hlsl") do (
echo. echo.
echo Operation terminee. echo Operation terminee.
pause
endlocal endlocal