From 262d91dd49a778cf372b13e1ecedaa7a4ea35949 Mon Sep 17 00:00:00 2001 From: Patedam Date: Sun, 16 Aug 2026 22:10:51 -0400 Subject: [PATCH] Various conversion to memory arena and misc clean up --- Juliet/include/Core/HAL/IO/IOStream.h | 10 ++--- Juliet/include/Core/HotReload/HotReload.h | 5 +-- Juliet/src/Core/HAL/IO/IOStream.cpp | 45 +++++++++---------- .../IO/{IOStream_Private.h => IOStream_cpp.h} | 2 +- .../src/Core/HAL/IO/Win32/Win32IOStream.cpp | 13 +++--- Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp | 2 +- Juliet/src/Core/HotReload/HotReload.cpp | 20 +++------ .../Core/HotReload/Win32/Win32HotReload.cpp | 8 ++-- Juliet/src/Core/ImGui/ImGuiService.cpp | 2 +- Juliet/src/Graphics/Graphics.cpp | 11 +++-- JulietApp/main.cpp | 4 +- 11 files changed, 53 insertions(+), 69 deletions(-) rename Juliet/src/Core/HAL/IO/{IOStream_Private.h => IOStream_cpp.h} (80%) diff --git a/Juliet/include/Core/HAL/IO/IOStream.h b/Juliet/include/Core/HAL/IO/IOStream.h index e972e47..378b25c 100644 --- a/Juliet/include/Core/HAL/IO/IOStream.h +++ b/Juliet/include/Core/HAL/IO/IOStream.h @@ -47,10 +47,11 @@ namespace Juliet bool (*Close)(NonNullPtr data); }; - extern JULIET_API IOStream* IOFromFile(String filename, String mode); + extern JULIET_API IOStream* IOFromFile(NonNullPtr arena, String filename, String mode); // Let you use an interface to open any io. Is used internally by IOFromFile - extern JULIET_API IOStream* IOFromInterface(NonNullPtr streamInterface, NonNullPtr payload); + extern JULIET_API IOStream* IOFromInterface(NonNullPtr arena, NonNullPtr streamInterface, + NonNullPtr payload); // Write formatted string into the stream. extern JULIET_API size_t IOPrintf(NonNullPtr stream, _Printf_format_string_ const char* format, ...); @@ -61,9 +62,8 @@ namespace Juliet extern JULIET_API int64 IOSize(NonNullPtr stream); - // TODO : Use memory arena because that Allocates - extern JULIET_API ByteBuffer LoadFile(String filename); - extern JULIET_API ByteBuffer LoadFile(NonNullPtr stream, bool closeStreamWhenDone); + extern JULIET_API ByteBuffer LoadFile(NonNullPtr arena, String filename); + extern JULIET_API ByteBuffer LoadFile(NonNullPtr arena, NonNullPtr stream, bool closeStreamWhenDone); extern JULIET_API bool IOClose(NonNullPtr stream); } // namespace Juliet diff --git a/Juliet/include/Core/HotReload/HotReload.h b/Juliet/include/Core/HotReload/HotReload.h index 25dff9a..8aa724d 100644 --- a/Juliet/include/Core/HotReload/HotReload.h +++ b/Juliet/include/Core/HotReload/HotReload.h @@ -9,8 +9,6 @@ namespace Juliet struct HotReloadCode { - Arena* Arena; - String DLLFullPath; String LockFullPath; String TransientDLLName; @@ -28,7 +26,8 @@ namespace Juliet bool IsValid : 1; }; - extern JULIET_API void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename); + extern JULIET_API void InitHotReloadCode(NonNullPtr arena, HotReloadCode& code, String dllName, + String transientDllName, String lockFilename); extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code); extern JULIET_API void LoadCode(HotReloadCode& code); diff --git a/Juliet/src/Core/HAL/IO/IOStream.cpp b/Juliet/src/Core/HAL/IO/IOStream.cpp index 496c4ff..a59458d 100644 --- a/Juliet/src/Core/HAL/IO/IOStream.cpp +++ b/Juliet/src/Core/HAL/IO/IOStream.cpp @@ -1,15 +1,14 @@ #include #include -#include +#include #include #include -#include #include namespace Juliet { - IOStream* IOFromFile(String filename, String mode) + IOStream* IOFromFile(NonNullPtr arena, String filename, String mode) { if (!IsValid(filename)) { @@ -22,14 +21,14 @@ namespace Juliet return nullptr; } - return Internal::IOFromFile(filename, mode); + return Internal::IOFromFile(arena, filename, mode); } - IOStream* IOFromInterface(NonNullPtr streamInterface, NonNullPtr payload) + IOStream* IOFromInterface(NonNullPtr arena, NonNullPtr streamInterface, + NonNullPtr payload) { Assert(streamInterface->Version >= sizeof(*streamInterface.Get())); - - auto stream = static_cast(Calloc(1, sizeof(IOStream))); + auto stream = ArenaPushStruct(arena); if (stream) { IOStreamInterface* dstInterface = &stream->Interface; @@ -132,23 +131,19 @@ namespace Juliet return stream->Interface.Size(stream->Data); } - ByteBuffer LoadFile(String filename) + ByteBuffer LoadFile(NonNullPtr arena, String filename) { - IOStream* stream = IOFromFile(filename, WrapString("rb")); + IOStream* stream = IOFromFile(arena, filename, WrapString("rb")); if (!stream) { return {}; } - return LoadFile(stream, true); + return LoadFile(arena, stream, true); } - ByteBuffer LoadFile(NonNullPtr stream, bool closeStreamWhenDone) + ByteBuffer LoadFile(NonNullPtr arena, NonNullPtr stream, bool closeStreamWhenDone) { constexpr size_t kFileChunkSize = 1024; - uint8* data = nullptr; - uint8* newData = nullptr; - size_t totalSize = 0; - ByteBuffer resultBuffer = {}; auto deferred = Defer( [&]() @@ -168,26 +163,27 @@ namespace Juliet loadChunks = true; } size_t size = static_cast(ssize); - data = static_cast(Malloc(static_cast(size + 1))); + uint8* data = ArenaPushArray(arena, size + 1); if (!data) { return {}; } + size_t totalSize = 0; while (true) { if (loadChunks) { if ((totalSize + kFileChunkSize) > size) { - size = totalSize + kFileChunkSize; - newData = static_cast(Realloc(data, static_cast(size + 1))); - if (!newData) + size = totalSize + kFileChunkSize; + + // Not enough space, add some + uint8* newSpace = ArenaPushArray(arena, kFileChunkSize); + if (!newSpace) { - Free(data); return {}; } - data = newData; } } @@ -211,9 +207,9 @@ namespace Juliet // Adding null terminator data[totalSize] = '\0'; - resultBuffer.Data = reinterpret_cast(data); - resultBuffer.Size = totalSize; - + ByteBuffer resultBuffer = {}; + resultBuffer.Data = reinterpret_cast(data); + resultBuffer.Size = totalSize; return resultBuffer; } @@ -224,7 +220,6 @@ namespace Juliet { result = stream->Interface.Close(stream->Data); } - Free(stream.Get()); return result; } diff --git a/Juliet/src/Core/HAL/IO/IOStream_Private.h b/Juliet/src/Core/HAL/IO/IOStream_cpp.h similarity index 80% rename from Juliet/src/Core/HAL/IO/IOStream_Private.h rename to Juliet/src/Core/HAL/IO/IOStream_cpp.h index ad3d60d..6fdfb89 100644 --- a/Juliet/src/Core/HAL/IO/IOStream_Private.h +++ b/Juliet/src/Core/HAL/IO/IOStream_cpp.h @@ -15,5 +15,5 @@ namespace Juliet namespace Juliet::Internal { - IOStream* IOFromFile(String filename, String mode); + IOStream* IOFromFile(NonNullPtr arena, String filename, String mode); } // namespace Juliet::Internal diff --git a/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp b/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp index 571b0c2..201d453 100644 --- a/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp +++ b/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp @@ -4,7 +4,6 @@ #include #include #include -#include namespace Juliet::Internal { @@ -181,14 +180,12 @@ namespace Juliet::Internal } win32Payload->Handle = INVALID_HANDLE_VALUE; } - SafeFree(win32Payload->Data); - SafeFree(win32Payload); return true; } } // namespace - IOStream* IOFromFile(String filename, String mode) + IOStream* IOFromFile(NonNullPtr arena, String filename, String mode) { // "r" = reading, file must exist // "w" = writing, truncate existing, file may not exist @@ -237,8 +234,8 @@ namespace Juliet::Internal return nullptr; } - constexpr bool autoClose = true; - Win32IOStreamDataPayload* payload = static_cast(Calloc(1, sizeof(Win32IOStreamDataPayload))); + constexpr bool autoClose = true; + Win32IOStreamDataPayload* payload = ArenaPushStruct(arena); if (!payload) { if (autoClose) @@ -263,14 +260,14 @@ namespace Juliet::Internal payload->IsAppending = isAppending; payload->ShouldAutoClose = autoClose; - payload->Data = static_cast(Malloc(kFileReadBufferSize)); + payload->Data = ArenaPushArray(arena, kFileReadBufferSize); if (!payload->Data) { iface.Close(payload); return nullptr; } - IOStream* stream = IOFromInterface(&iface, payload); + IOStream* stream = IOFromInterface(arena, &iface, payload); if (!stream) { iface.Close(payload); diff --git a/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp index 6fc48bc..e19febf 100644 --- a/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp +++ b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp @@ -103,7 +103,7 @@ namespace Juliet { thread_local thread_context* mainThread = nullptr; - int OS_Main(int argc, wchar_t** argv) + int OS_Main([[maybe_unused]] int argc, [[maybe_unused]] wchar_t** argv) { SetUnhandledExceptionFilter(&ExceptionFilter); diff --git a/Juliet/src/Core/HotReload/HotReload.cpp b/Juliet/src/Core/HotReload/HotReload.cpp index 0c13956..919d6db 100644 --- a/Juliet/src/Core/HotReload/HotReload.cpp +++ b/Juliet/src/Core/HotReload/HotReload.cpp @@ -9,10 +9,8 @@ namespace Juliet { - void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename) + void InitHotReloadCode(NonNullPtr arena, HotReloadCode& code, String dllName, String transientDllName, String lockFilename) { - code.Arena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Hot Reload" }); - // Get the app base path and build the dll path from there. String basePath = GetBasePath(); size_t basePathLength = StringLength(basePath); @@ -25,12 +23,11 @@ namespace Juliet const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings - code.DLLFullPath.Str = - static_cast(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_PARAM("DLL Path"))); + code.DLLFullPath.Str = static_cast( + ArenaPush(arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_PARAM("Hot Reload DLL Path"))); int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName)); if (writtenSize < static_cast(dllFullPathLength) - 1) { - // Arena memory persists, no free needed Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path"); return; } @@ -39,13 +36,12 @@ namespace Juliet // Lock filename path const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings - code.LockFullPath.Str = - static_cast(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_PARAM("Lock File Path"))); + code.LockFullPath.Str = static_cast( + ArenaPush(arena, lockPathLength, alignof(char), true JULIET_DEBUG_PARAM("Hot Reload Lock File Path"))); writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename)); if (writtenSize < static_cast(lockPathLength) - 1) { code.LockFullPath.Size = 0; - // Arena memory persists, no free needed Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path"); return; } @@ -58,12 +54,8 @@ namespace Juliet { UnloadCode(code); - code.DLLFullPath.Size = 0; - // Arena memory persists until engine shutdown + code.DLLFullPath.Size = 0; code.LockFullPath.Size = 0; - // Arena memory persists until engine shutdown - - ArenaRelease(code.Arena); } void ReloadCode(HotReloadCode& code) diff --git a/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp b/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp index 7811744..5e54d79 100644 --- a/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp +++ b/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Juliet { @@ -31,9 +32,6 @@ namespace Juliet void LoadCode(HotReloadCode& code) { - // TODO : Create and use a TransientAllocator - // Create temp dll name - char* lockFilename = code.LockFullPath.Str; WIN32_FILE_ATTRIBUTE_DATA Ignored; if (!GetFileAttributesExA(lockFilename, GetFileExInfoStandard, &Ignored)) @@ -56,7 +54,7 @@ namespace Juliet basePathLength + StringLength(code.TransientDLLName) + /* _ */ 1 + kTempDLLBufferSizeForID + 1 /* \0 */; // Allocate from Scratch Arena (transient) - TempArena temp = ArenaTempBegin(code.Arena); + TempArena temp = scratch_begin(0, 0); auto tempDllPath = ArenaPushArray(temp.Arena, tempDllMaxBufferSize); for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt) @@ -97,7 +95,7 @@ namespace Juliet break; } } - ArenaTempEnd(temp); + scratch_end(temp); code.Dll = LoadDynamicLibrary(tempDllPath); if (code.Dll) diff --git a/Juliet/src/Core/ImGui/ImGuiService.cpp b/Juliet/src/Core/ImGui/ImGuiService.cpp index 4883ca0..3702aae 100644 --- a/Juliet/src/Core/ImGui/ImGuiService.cpp +++ b/Juliet/src/Core/ImGui/ImGuiService.cpp @@ -75,7 +75,7 @@ namespace Juliet::ImGuiService Assert(!g_Initialized); // Initialize ImGui Arena using Engine Pool - g_ImGuiArena = ArenaAllocate({ .Name = "Juliet" }); + g_ImGuiArena = ArenaAllocate({ .Name = "Imgui Allocator Arena" }); // Setup Allocator ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper, nullptr); diff --git a/Juliet/src/Graphics/Graphics.cpp b/Juliet/src/Graphics/Graphics.cpp index 33b307e..37ac71b 100644 --- a/Juliet/src/Graphics/Graphics.cpp +++ b/Juliet/src/Graphics/Graphics.cpp @@ -4,6 +4,8 @@ #include #include #include + +#include #include namespace Juliet @@ -316,21 +318,22 @@ namespace Juliet // Shaders Shader* CreateShader(NonNullPtr device, String filename, ShaderCreateInfo& shaderCreateInfo) { + TempArena fileArena = scratch_begin(0, 0); ByteBuffer shaderByteCode = {}; // Create path from filename if (IsAbsolutePath(filename)) { - shaderByteCode = LoadFile(filename); + shaderByteCode = LoadFile(fileArena.Arena, filename); } else { // TODO: Add path builder in the lib String base = GetBasePath(); char inplaceBuffer[256]; - snprintf(inplaceBuffer, sizeof(inplaceBuffer), "%s%s", base.Str, filename.Str); + juliet_snprintf(inplaceBuffer, sizeof(inplaceBuffer), "%s%s", base.Str, filename.Str); String absolutePath = WrapString(inplaceBuffer); - shaderByteCode = LoadFile(absolutePath); + shaderByteCode = LoadFile(fileArena.Arena, absolutePath); } if (!IsValid(shaderByteCode)) @@ -340,7 +343,7 @@ namespace Juliet Shader* shader = device->CreateShader(device->Driver, shaderByteCode, shaderCreateInfo JULIET_DEBUG_PARAM(filename)); - Free(shaderByteCode); + scratch_end(fileArena); return shader; } diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp index 4caa122..677426e 100644 --- a/JulietApp/main.cpp +++ b/JulietApp/main.cpp @@ -106,7 +106,7 @@ namespace } // namespace -void JulietApplication::Init(NonNullPtr) +void JulietApplication::Init(NonNullPtr platformArena) { Log(LogLevel::Message, LogCategory::Tool, "Initializing Juliet Application..."); Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath())); @@ -182,7 +182,7 @@ void JulietApplication::Init(NonNullPtr) GameCode.Functions = reinterpret_cast(&Game); GameCode.FunctionCount = ArraySize(GameFunctionTable); GameCode.FunctionNames = GameFunctionTable; - InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp")); + InitHotReloadCode(platformArena, GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp")); Running = GameCode.IsValid; } }