Various conversion to memory arena and misc clean up

This commit is contained in:
2026-08-16 22:10:51 -04:00
parent d1b7c5dbbe
commit 262d91dd49
11 changed files with 53 additions and 69 deletions
+5 -5
View File
@@ -47,10 +47,11 @@ namespace Juliet
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
};
extern JULIET_API IOStream* IOFromFile(String filename, String mode);
extern JULIET_API IOStream* IOFromFile(NonNullPtr<Arena> 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<const IOStreamInterface> streamInterface, NonNullPtr<IOStreamDataPayload> payload);
extern JULIET_API IOStream* IOFromInterface(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
NonNullPtr<IOStreamDataPayload> payload);
// Write formatted string into the stream.
extern JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
@@ -61,9 +62,8 @@ namespace Juliet
extern JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
// TODO : Use memory arena because that Allocates
extern JULIET_API ByteBuffer LoadFile(String filename);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, String filename);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<Arena> arena, NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
extern JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
} // namespace Juliet
+2 -3
View File
@@ -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> arena, HotReloadCode& code, String dllName,
String transientDllName, String lockFilename);
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
extern JULIET_API void LoadCode(HotReloadCode& code);
+20 -25
View File
@@ -1,15 +1,14 @@
#include <Core/HAL/IO/IOStream.h>
#include <Core/Common/String.h>
#include <Core/HAL/IO/IOStream_Private.h>
#include <Core/HAL/IO/IOStream_cpp.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h>
#include <Core/Thread/Thread.h>
namespace Juliet
{
IOStream* IOFromFile(String filename, String mode)
IOStream* IOFromFile(NonNullPtr<Arena> 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<const IOStreamInterface> streamInterface, NonNullPtr<IOStreamDataPayload> payload)
IOStream* IOFromInterface(NonNullPtr<Arena> arena, NonNullPtr<const IOStreamInterface> streamInterface,
NonNullPtr<IOStreamDataPayload> payload)
{
Assert(streamInterface->Version >= sizeof(*streamInterface.Get()));
auto stream = static_cast<IOStream*>(Calloc(1, sizeof(IOStream)));
auto stream = ArenaPushStruct<IOStream>(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> 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<IOStream> stream, bool closeStreamWhenDone)
ByteBuffer LoadFile(NonNullPtr<Arena> arena, NonNullPtr<IOStream> 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<size_t>(ssize);
data = static_cast<uint8*>(Malloc(static_cast<size_t>(size + 1)));
uint8* data = ArenaPushArray<uint8, false>(arena, size + 1);
if (!data)
{
return {};
}
size_t totalSize = 0;
while (true)
{
if (loadChunks)
{
if ((totalSize + kFileChunkSize) > size)
{
size = totalSize + kFileChunkSize;
newData = static_cast<uint8*>(Realloc(data, static_cast<size_t>(size + 1)));
if (!newData)
size = totalSize + kFileChunkSize;
// Not enough space, add some
uint8* newSpace = ArenaPushArray<uint8, false>(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<Byte*>(data);
resultBuffer.Size = totalSize;
ByteBuffer resultBuffer = {};
resultBuffer.Data = reinterpret_cast<Byte*>(data);
resultBuffer.Size = totalSize;
return resultBuffer;
}
@@ -224,7 +220,6 @@ namespace Juliet
{
result = stream->Interface.Close(stream->Data);
}
Free(stream.Get());
return result;
}
@@ -15,5 +15,5 @@ namespace Juliet
namespace Juliet::Internal
{
IOStream* IOFromFile(String filename, String mode);
IOStream* IOFromFile(NonNullPtr<Arena> arena, String filename, String mode);
} // namespace Juliet::Internal
@@ -4,7 +4,6 @@
#include <Core/HAL/Win32.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h>
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> 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<Win32IOStreamDataPayload*>(Calloc(1, sizeof(Win32IOStreamDataPayload)));
constexpr bool autoClose = true;
Win32IOStreamDataPayload* payload = ArenaPushStruct<Win32IOStreamDataPayload>(arena);
if (!payload)
{
if (autoClose)
@@ -263,14 +260,14 @@ namespace Juliet::Internal
payload->IsAppending = isAppending;
payload->ShouldAutoClose = autoClose;
payload->Data = static_cast<char*>(Malloc(kFileReadBufferSize));
payload->Data = ArenaPushArray<char, false>(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);
+1 -1
View File
@@ -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);
+6 -14
View File
@@ -9,10 +9,8 @@
namespace Juliet
{
void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename)
void InitHotReloadCode(NonNullPtr<Arena> 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<char*>(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_PARAM("DLL Path")));
code.DLLFullPath.Str = static_cast<char*>(
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<int>(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<char*>(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_PARAM("Lock File Path")));
code.LockFullPath.Str = static_cast<char*>(
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<int>(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)
@@ -6,6 +6,7 @@
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h>
#include <Core/Memory/MemoryArena.h>
#include <Core/Thread/ThreadContext.h>
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<char>(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)
+1 -1
View File
@@ -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);
+7 -4
View File
@@ -4,6 +4,8 @@
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Graphics/Graphics.h>
#include <Core/Thread/ThreadContext.h>
#include <Graphics/GraphicsDevice.h>
namespace Juliet
@@ -316,21 +318,22 @@ namespace Juliet
// Shaders
Shader* CreateShader(NonNullPtr<GraphicsDevice> 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;
}
+2 -2
View File
@@ -106,7 +106,7 @@ namespace
} // namespace
void JulietApplication::Init(NonNullPtr<Arena>)
void JulietApplication::Init(NonNullPtr<Arena> 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<Arena>)
GameCode.Functions = reinterpret_cast<void**>(&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;
}
}