From d1b7c5dbbe87f961c083067946ed820803c29a26 Mon Sep 17 00:00:00 2001 From: Patedam Date: Sun, 16 Aug 2026 18:06:46 -0400 Subject: [PATCH] Adding scratch arena for main thread (and any thread in the future) Added some function based on raddbg code for string conversion and more. --- Game/Entity/EntityManager.cpp | 2 +- Game/game.cpp | 4 +- Juliet/include/Core/Common/CoreUtils.h | 26 ++++ Juliet/include/Core/Common/String.h | 44 ++++-- Juliet/include/Core/Memory/MemoryArena.h | 16 +- Juliet/include/Core/PCH.h | 2 + Juliet/include/Core/Thread/Thread.h | 6 +- Juliet/include/Core/Thread/ThreadContext.h | 24 +++ Juliet/src/Core/Common/String.cpp | 146 ++++++++++++++++-- Juliet/src/Core/HAL/Display/Display.cpp | 4 +- .../Core/HAL/Display/Win32/Win32Window.cpp | 2 +- Juliet/src/Core/HAL/Filesystem/Filesystem.cpp | 11 +- .../HAL/Filesystem/Win32/Win32Filesystem.cpp | 4 +- .../src/Core/HAL/IO/Win32/Win32IOStream.cpp | 24 +-- Juliet/src/Core/HAL/OS/OS.cpp | 14 +- Juliet/src/Core/HAL/OS/OS_Private.h | 5 +- Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp | 30 +++- Juliet/src/Core/HAL/Win32.h | 2 + Juliet/src/Core/HotReload/HotReload.cpp | 6 +- .../Core/HotReload/Win32/Win32HotReload.cpp | 6 +- Juliet/src/Core/ImGui/ImGuiService.cpp | 2 +- Juliet/src/Core/Logging/LogManager.cpp | 2 +- Juliet/src/Core/Memory/MemoryArena.cpp | 25 +-- Juliet/src/Core/Memory/MemoryArenaDebug.cpp | 10 +- Juliet/src/Core/Memory/MemoryArenaTests.cpp | 4 +- Juliet/src/Core/Thread/ThreadContext.cpp | 76 +++++++++ Juliet/src/Core/Thread/win32_thread.cpp | 63 ++++++++ Juliet/src/Engine/Debug/MemoryDebugger.cpp | 4 +- Juliet/src/Engine/Engine.cpp | 6 +- .../Graphics/D3D12/D3D12GraphicsDevice.cpp | 3 +- Juliet/src/Graphics/Graphics.cpp | 2 +- .../src/UnitTest/Container/VectorUnitTest.cpp | 4 +- 32 files changed, 477 insertions(+), 102 deletions(-) create mode 100644 Juliet/include/Core/Thread/ThreadContext.h create mode 100644 Juliet/src/Core/Thread/ThreadContext.cpp create mode 100644 Juliet/src/Core/Thread/win32_thread.cpp diff --git a/Game/Entity/EntityManager.cpp b/Game/Entity/EntityManager.cpp index 6cc6a88..d640be6 100644 --- a/Game/Entity/EntityManager.cpp +++ b/Game/Entity/EntityManager.cpp @@ -12,7 +12,7 @@ void InitEntityManager(Juliet::NonNullPtr world) newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities")); - newManager->Arena = Juliet::ArenaAllocate({} JULIET_DEBUG_PARAM("Entity Arena")); + newManager->Arena = Juliet::ArenaAllocate({ .Name = "Entity Arena" }); } void ShutdownEntityManager() diff --git a/Game/game.cpp b/Game/game.cpp index 4036be5..cee50c0 100644 --- a/Game/game.cpp +++ b/Game/game.cpp @@ -43,7 +43,7 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_ gGameState = params->GameState; if (!gGameState) { - Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_PARAM("Game Total Arena")); + Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Game Total Arena" }); auto* gameState = ArenaPushStruct(gameStateArena); gGameState = params->GameState = gameState; gameState->TotalArena = gameStateArena; @@ -57,7 +57,7 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_ ReserveCamera(4); // Bootstrap world - auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_PARAM("World Arena")); + auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "World Arena" }); World* world = ArenaPushStruct(worldArena JULIET_DEBUG_PARAM("World")); gameState->World = world; gameState->World->WorldArena = worldArena; diff --git a/Juliet/include/Core/Common/CoreUtils.h b/Juliet/include/Core/Common/CoreUtils.h index d6811d6..5c5ce40 100644 --- a/Juliet/include/Core/Common/CoreUtils.h +++ b/Juliet/include/Core/Common/CoreUtils.h @@ -202,4 +202,30 @@ namespace Juliet return "UnknownType"; #endif } + + inline uint16 safe_cast_uint16(uint32 value) + { + Assert(value <= uint16Max); + uint16 result = (uint16)value; + return result; + } + + const uint32 bitmask1 = 0b0000'0001; + const uint32 bitmask2 = 0b0000'0011; + const uint32 bitmask3 = 0b0000'0111; + const uint32 bitmask4 = 0b0000'1111; + const uint32 bitmask5 = 0b0001'1111; + const uint32 bitmask6 = 0b0011'1111; + const uint32 bitmask7 = 0b0111'1111; + const uint32 bitmask8 = 0b1111'1111; + const uint32 bitmask9 = 0x0000'01ff; + const uint32 bitmask10 = 0x0000'03ff; + const uint32 bitmask11 = 0x0000'07ff; + const uint32 bitmask12 = 0x0000'0fff; + const uint32 bitmask13 = 0x0000'1fff; + const uint32 bitmask14 = 0x0000'3fff; + const uint32 bitmask15 = 0x0000'7fff; + const uint32 bitmask16 = 0x0000'ffff; + // ... + const uint32 bitmask32 = 0xffff'ffff; } // namespace Juliet diff --git a/Juliet/include/Core/Common/String.h b/Juliet/include/Core/Common/String.h index 2008a8b..62b983c 100644 --- a/Juliet/include/Core/Common/String.h +++ b/Juliet/include/Core/Common/String.h @@ -19,7 +19,7 @@ namespace Juliet struct Arena; #define ConstString(str) { const_cast((str)), sizeof(str) - 1 } -#define CStr(str) ((str).Data) +#define CStr(str) ((str).Str) #define InplaceString(name, size) \ char name##_[size]; \ MemSet(name##_, 0, sizeof(uint32)); \ @@ -40,17 +40,30 @@ namespace Juliet // Represents a UTF-8 String. // Not null terminated. - struct String + struct String8 { - char* Data; + char* Str; size_t Size; }; + using String = String8; + + struct String16 + { + uint16* Str; + size_t Size; + }; struct StringBuffer : String { size_t Capacity; }; + struct UnicodeDecode + { + uint32 Increment; + uint32 Codepoint; + }; + constexpr uint32 kInvalidUTF8 = 0xFFFD; inline size_t StringLength(String str) @@ -75,13 +88,13 @@ namespace Juliet inline bool IsValid(String str) { - return str.Size > 0 && str.Data != nullptr && *str.Data; + return str.Size > 0 && str.Str != nullptr && *str.Str; } inline String WrapString(const char* str) { String result = {}; - result.Data = const_cast(str); + result.Str = const_cast(str); result.Size = str ? strlen(str) : 0; return result; } @@ -91,9 +104,9 @@ namespace Juliet String result = str; while (result.Size) { - if (*result.Data != c) + if (*result.Str != c) { - ++result.Data; + ++result.Str; --result.Size; } else @@ -150,7 +163,8 @@ namespace Juliet extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst, bool nullTerminate); extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate); - JULIET_API String StringCopy(NonNullPtr arena, String str); + JULIET_API String StringCopy(NonNullPtr arena, String str); + JULIET_API String16 str16_from_8(NonNullPtr arena, String8 str); template String Format(NonNullPtr arena, const char* formatStr, Args&&... args) @@ -158,6 +172,8 @@ namespace Juliet std::string result = std::vformat(formatStr, std::make_format_args(args...)); return StringCopy(arena, WrapString(result.c_str())); } + +#define juliet_snprintf snprintf } // namespace Juliet #ifdef UNIT_TEST @@ -169,12 +185,12 @@ namespace Juliet::UnitTest String s2 = ConstString("abcdefabcdef"); String s3 = ConstString("11111111111111111111"); - Assert(FindChar(s1, 'x').Data == nullptr); - Assert(FindChar(s2, 'y').Data == nullptr); - Assert(FindChar(s2, 'a').Data - s2.Data == 0); - Assert(FindChar(s2, 'd').Data - s2.Data == 3); - Assert(FindChar(s2, 'f').Data - s2.Data == 5); - Assert(FindChar(s3, '1').Data - s3.Data == 0); + Assert(FindChar(s1, 'x').Str == nullptr); + Assert(FindChar(s2, 'y').Str == nullptr); + Assert(FindChar(s2, 'a').Str - s2.Str == 0); + Assert(FindChar(s2, 'd').Str - s2.Str == 3); + Assert(FindChar(s2, 'f').Str - s2.Str == 5); + Assert(FindChar(s3, '1').Str - s3.Str == 0); } } // namespace Juliet::UnitTest #endif diff --git a/Juliet/include/Core/Memory/MemoryArena.h b/Juliet/include/Core/Memory/MemoryArena.h index 2f97176..da644c9 100644 --- a/Juliet/include/Core/Memory/MemoryArena.h +++ b/Juliet/include/Core/Memory/MemoryArena.h @@ -44,7 +44,7 @@ namespace Juliet JULIET_DEBUG_ONLY(Arena* GlobalNext;) JULIET_DEBUG_ONLY(Arena* GlobalPrev;) JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;) - JULIET_DEBUG_ONLY(const char* Name;) + const char* Name; }; static_assert(sizeof(Arena) <= k_ArenaHeaderSize); @@ -59,11 +59,13 @@ namespace Juliet uint64 ReserveSize = g_Arena_Default_Reserve_Size; uint64 CommitSize = g_Arena_Default_Commit_Size; + const char* Name; + // When false, will assert if a new block is reserved. JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;) }; - [[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params JULIET_DEBUG_PARAM(const char* name), + [[nodiscard]] JULIET_API Arena* ArenaAllocate(const ArenaParams& params, const std::source_location& loc = std::source_location::current()); JULIET_API void ArenaRelease(NonNullPtr arena); @@ -88,7 +90,7 @@ namespace Juliet { return Format(GetDebugInfoArena(), std::forward(firstDebugArg), std::forward(debugArgs)...) - .Data; + .Str; }())); } @@ -102,23 +104,23 @@ namespace Juliet { if constexpr (sizeof...(DebugArgs) > 0) { - return Format(GetDebugInfoArena(), std::forward(debugArgs)...).Data; + return Format(GetDebugInfoArena(), std::forward(debugArgs)...).Str; } return GetTypeName(); }()))); } - template + template [[nodiscard]] Type* ArenaPushArray(NonNullPtr arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs)) { return static_cast( ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), - true JULIET_DEBUG_PARAM( + shouldZero JULIET_DEBUG_PARAM( [&]() -> const char* { if constexpr (sizeof...(DebugArgs) > 0) { - return Format(GetDebugInfoArena(), std::forward(debugArgs)...).Data; + return Format(GetDebugInfoArena(), std::forward(debugArgs)...).Str; } return GetTypeName(); }()))); diff --git a/Juliet/include/Core/PCH.h b/Juliet/include/Core/PCH.h index e026445..6ccdc20 100644 --- a/Juliet/include/Core/PCH.h +++ b/Juliet/include/Core/PCH.h @@ -28,3 +28,5 @@ #include #include #include + +#include diff --git a/Juliet/include/Core/Thread/Thread.h b/Juliet/include/Core/Thread/Thread.h index 0d98049..6919e62 100644 --- a/Juliet/include/Core/Thread/Thread.h +++ b/Juliet/include/Core/Thread/Thread.h @@ -1,8 +1,12 @@ #pragma once +#include + namespace Juliet { - using Thread = std::thread; + uint32 thread_id(); + + void set_thread_name(String name); // TODO : Proper wait inline void wait_ms(int milliseconds) diff --git a/Juliet/include/Core/Thread/ThreadContext.h b/Juliet/include/Core/Thread/ThreadContext.h new file mode 100644 index 0000000..c35097a --- /dev/null +++ b/Juliet/include/Core/Thread/ThreadContext.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace Juliet +{ + struct thread_context + { + Arena* ScratchArenas[2]; + + char ThreadName[64]; + uint8 ThreadNameSize; + }; + + thread_context* thread_context_alloc(); + void thread_context_release(NonNullPtr ctx); + void thread_context_select(NonNullPtr ctx); + thread_context* thread_context_current(); + + Arena* thread_context_get_scratch(Arena** conflicts, size_t count); + TempArena scratch_begin(Arena** conflicts, size_t count); + void scratch_end(TempArena scratch); +} // namespace Juliet diff --git a/Juliet/src/Core/Common/String.cpp b/Juliet/src/Core/Common/String.cpp index 7b22baa..a7b9c17 100644 --- a/Juliet/src/Core/Common/String.cpp +++ b/Juliet/src/Core/Common/String.cpp @@ -60,6 +60,7 @@ namespace Juliet } } // namespace + // TODO: remove this as we convert to simple unicode decode / encode at the bottom uint32 StepUTF8(String& inStr) { // From rfc3629, the UTF-8 spec: @@ -92,7 +93,7 @@ namespace Juliet } if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx { - inStr.Data += 1; + inStr.Str += 1; inStr.Size -= 1; return octet; } @@ -104,7 +105,7 @@ namespace Juliet const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F); if (result >= 0x80) // If the result is smaller than 0x80 its an overlong! { - inStr.Data += 2; + inStr.Str += 2; inStr.Size -= 1; return result; } @@ -131,7 +132,7 @@ namespace Juliet { if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate { - inStr.Data += 3; + inStr.Str += 3; inStr.Size -= 1; return result; } @@ -164,7 +165,7 @@ namespace Juliet const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet; if (result >= 0x10000) // If smaller its an overlong { - inStr.Data += 4; + inStr.Str += 4; inStr.Size -= 1; return result; } @@ -180,7 +181,7 @@ namespace Juliet } LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s", isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false"); - inStr.Data += 1; + inStr.Str += 1; return kInvalidUTF8; } @@ -254,8 +255,8 @@ namespace Juliet { Assert(IsValid(src)); - const char* srcStr = src.Data; - char* dstStr = dst.Data; + const char* srcStr = src.Str; + char* dstStr = dst.Str; size_t remainingCapacity = dst.Capacity; uint32 character = 0; @@ -489,13 +490,138 @@ namespace Juliet return ConvertString(sourceFormat, destFormat, src, dst, nullTerminate); } + namespace + { + uint8 utf8_class[32] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 5, + }; + + UnicodeDecode utf8_decode(uint8* str, size_t max) + { + // From rfc3629, the UTF-8 spec: + // https://www.ietf.org/rfc/rfc3629.txt + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+--------------------------------------------- + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + UnicodeDecode result = { 1, uint32Max }; + uint8 byte = str[0]; + uint8 byte_class = utf8_class[byte >> 3]; + switch (byte_class) + { + case 1: + { + result.Codepoint = byte; + break; + } + case 2: + { + if (1 < max) + { + uint8 next_byte = str[1]; + if (utf8_class[next_byte >> 3] == 0) + { + result.Codepoint = (byte & bitmask5) << 6; + result.Codepoint |= (next_byte & bitmask6); + result.Increment = 2; + } + } + break; + } + case 3: + { + if (2 < max) + { + uint8 next_byte[2] = { str[1], str[2] }; + if (utf8_class[next_byte[0] >> 3] == 0 && utf8_class[next_byte[1] >> 3] == 0) + { + result.Codepoint = (byte & bitmask4) << 12; + result.Codepoint |= ((next_byte[0] & bitmask6) << 6); + result.Codepoint |= (next_byte[1] & bitmask6); + result.Increment = 3; + } + } + break; + } + case 4: + { + if (3 < max) + { + uint8 next_byte[3] = { str[1], str[2], str[3] }; + if (utf8_class[next_byte[0] >> 3] == 0 && utf8_class[next_byte[1] >> 3] == 0 && + utf8_class[next_byte[2] >> 3] == 0) + { + result.Codepoint = (byte & bitmask3) << 18; + result.Codepoint |= ((next_byte[0] & bitmask6) << 12); + result.Codepoint |= ((next_byte[1] & bitmask6) << 6); + result.Codepoint |= (next_byte[2] & bitmask6); + result.Increment = 4; + } + } + break; + } + } + return result; + } + + uint32 utf16_encode(uint16* str, uint32 codepoint) + { + Assert(str); + uint32 increment = 1; + if (codepoint == uint32Max) + { + str[0] = '?'; + } + else if (codepoint < 0x10000) + { + str[0] = (uint16)codepoint; + } + else + { + uint32 var = codepoint - 0x10000; + str[0] = safe_cast_uint16(0xD800 + (var >> 10)); + str[1] = safe_cast_uint16(0xDC00 + (var & bitmask10)); + increment = 2; + } + return increment; + } + } // namespace + String StringCopy(NonNullPtr arena, String str) { String result; result.Size = str.Size; - result.Data = static_cast(ArenaPush(arena, str.Size + 1, alignof(char), true JULIET_DEBUG_PARAM("String"))); - MemCopy(result.Data, str.Data, str.Size); - result.Data[result.Size] = 0; + result.Str = static_cast(ArenaPush(arena, str.Size + 1, alignof(char), true JULIET_DEBUG_PARAM("String"))); + MemCopy(result.Str, str.Str, str.Size); + result.Str[result.Size] = 0; + return result; + } + + String16 str16_from_8(NonNullPtr arena, String8 in) + { + String16 result = {}; + if (in.Size > 0) + { + size_t neededCapacity = in.Size * 2; + uint16* str = ArenaPushArray(arena, neededCapacity + 1); + uint8* inStr = (uint8*)in.Str; + uint8* inStrEnd = inStr + in.Size; + + UnicodeDecode consumed; + uint64 size = 0; + for (; inStr < inStrEnd; inStr += consumed.Increment) + { + consumed = utf8_decode(inStr, inStrEnd - inStr); + size += utf16_encode(str + size, consumed.Codepoint); + } + str[size] = 0; + ArenaPop(arena, (neededCapacity - size) * 2); + result = { str, size }; + } return result; } diff --git a/Juliet/src/Core/HAL/Display/Display.cpp b/Juliet/src/Core/HAL/Display/Display.cpp index fcc5eb0..c201461 100644 --- a/Juliet/src/Core/HAL/Display/Display.cpp +++ b/Juliet/src/Core/HAL/Display/Display.cpp @@ -23,7 +23,7 @@ namespace Juliet { Assert(!g_CurrentDisplayDevice); - Arena* arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Display System")); + Arena* arena = ArenaAllocate({ .Name = "Display System" }); DisplayDevice* candidateDevice = nullptr; DisplayDeviceFactory* candidateFactory = nullptr; @@ -80,7 +80,7 @@ namespace Juliet Assert(g_CurrentDisplayDevice->CreatePlatformWindow); Window window = {}; - window.Arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Window")); + window.Arena = ArenaAllocate({ .Name = "Window" }); window.Width = width; window.Height = height; diff --git a/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp b/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp index d4d39f3..0f3a429 100644 --- a/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp +++ b/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp @@ -59,7 +59,7 @@ namespace Juliet::Win32 int x = CW_USEDEFAULT, y = CW_USEDEFAULT; const int w = window->Width, h = window->Height; - HWND handle = CreateWindowExA(styleEx, WindowClassPtr, window->Title.Data, style, x, y, w, h, nullptr, nullptr, + HWND handle = CreateWindowExA(styleEx, WindowClassPtr, window->Title.Str, style, x, y, w, h, nullptr, nullptr, instance, nullptr); PumpEvents(self); diff --git a/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp b/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp index 5dc4947..fb9e636 100644 --- a/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp +++ b/Juliet/src/Core/HAL/Filesystem/Filesystem.cpp @@ -22,7 +22,7 @@ namespace Juliet DWORD attributes = GetFileAttributesA(path); return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY); } - } + } // namespace String GetBasePath() { @@ -71,10 +71,7 @@ namespace Juliet // Probe candidate paths for compiled shader directory // 1. Shipping layout: Assets/Shaders/ next to the exe // 2. Dev layout: ../../Assets/compiled/ (exe is in bin/x64Clang-/) - constexpr const char* kCandidates[] = { - "Assets/Shaders/", - "../../Assets/compiled/" - }; + constexpr const char* kCandidates[] = { "Assets/Shaders/", "../../Assets/compiled/" }; for (const char* candidate : kCandidates) { @@ -103,12 +100,12 @@ namespace Juliet if (IsValid(CachedBasePath)) { CachedBasePath.Size = 0; - SafeFree(CachedBasePath.Data); + SafeFree(CachedBasePath.Str); } if (IsValid(CachedAssetBasePath)) { CachedAssetBasePath.Size = 0; - SafeFree(CachedAssetBasePath.Data); + SafeFree(CachedAssetBasePath.Str); } } } // namespace Juliet diff --git a/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp b/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp index d361e83..3d0ab07 100644 --- a/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp +++ b/Juliet/src/Core/HAL/Filesystem/Win32/Win32Filesystem.cpp @@ -58,7 +58,7 @@ namespace Juliet::Platform bool IsAbsolutePath(String path) { - if (!path.Data || path.Size == 0) + if (!path.Str || path.Size == 0) { return false; } @@ -69,7 +69,7 @@ namespace Juliet::Platform // A disk designator with a backslash, for example "C:\" or "d:\". // A single backslash, for example, "\directory" or "\file.txt". This is also referred to as an absolute path. // We will only handle the first two. Single backslash is weird. - const char* pathStr = path.Data; + const char* pathStr = path.Str; size_t pathLen = path.Size; if (pathLen > 1) diff --git a/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp b/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp index 5b4ea20..571b0c2 100644 --- a/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp +++ b/Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp @@ -24,8 +24,8 @@ namespace Juliet::Internal int64 FileSize(NonNullPtr payload) { - auto win32Payload = static_cast(payload.Get()); - LARGE_INTEGER size; + Win32IOStreamDataPayload* win32Payload = static_cast(payload.Get()); + LARGE_INTEGER size; if (!GetFileSizeEx(win32Payload->Handle, &size)) { @@ -38,7 +38,7 @@ namespace Juliet::Internal int64 FileSeek(NonNullPtr payload, int64 offset, IOStreamSeekPivot pivot) { - auto win32Payload = static_cast(payload.Get()); + Win32IOStreamDataPayload* win32Payload = static_cast(payload.Get()); if ((pivot == IOStreamSeekPivot::Current) && (win32Payload->SizeLeft > 0)) { offset -= static_cast(win32Payload->SizeLeft); @@ -69,10 +69,10 @@ namespace Juliet::Internal size_t FileRead(NonNullPtr payload, void* outBuffer, size_t size, NonNullPtr status) { - auto win32Payload = static_cast(payload.Get()); - size_t totalNeed = size; - size_t totalRead = 0; - size_t sizeToReadAhead = 0; + Win32IOStreamDataPayload* win32Payload = static_cast(payload.Get()); + size_t totalNeed = size; + size_t totalRead = 0; + size_t sizeToReadAhead = 0; if (win32Payload->SizeLeft > 0) { uint8* data = static_cast(win32Payload->Data) + win32Payload->Size - win32Payload->SizeLeft; @@ -133,8 +133,8 @@ namespace Juliet::Internal size_t FileWrite(NonNullPtr payload, ByteBuffer inBuffer, NonNullPtr status) { - auto win32Payload = static_cast(payload.Get()); - DWORD bytes; + Win32IOStreamDataPayload* win32Payload = static_cast(payload.Get()); + DWORD bytes; if (win32Payload->SizeLeft) { @@ -204,12 +204,12 @@ namespace Juliet::Internal "Mode should have at most 2 characters, one being either r,w or a and the other can only be +"); if (modeLength == 1) { - Assert((mode.Data[0] == 'r' || mode.Data[0] == 'w' || mode.Data[0] == 'a') && + Assert((mode.Str[0] == 'r' || mode.Str[0] == 'w' || mode.Str[0] == 'a') && "Invalid Mode. First char is not r,w or a"); } else { - Assert((mode.Data[1] == '+' || mode.Data[1] == 'b') && "Invalid Mode. Second char is not +"); + Assert((mode.Str[1] == '+' || mode.Str[1] == 'b') && "Invalid Mode. Second char is not +"); } #endif @@ -238,7 +238,7 @@ namespace Juliet::Internal } constexpr bool autoClose = true; - auto payload = static_cast(Calloc(1, sizeof(Win32IOStreamDataPayload))); + Win32IOStreamDataPayload* payload = static_cast(Calloc(1, sizeof(Win32IOStreamDataPayload))); if (!payload) { if (autoClose) diff --git a/Juliet/src/Core/HAL/OS/OS.cpp b/Juliet/src/Core/HAL/OS/OS.cpp index dc1905e..d795b2d 100644 --- a/Juliet/src/Core/HAL/OS/OS.cpp +++ b/Juliet/src/Core/HAL/OS/OS.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace Juliet { @@ -61,7 +62,18 @@ namespace Juliet int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv) { - return Internal::OS_Main(entryPointFunc, argc, argv); + + int result = Internal::OS_Main(argc, argv); + if (result == 0) + { + set_thread_name(WrapString("main_thread")); + + result = entryPointFunc(argc, argv); + } + + Internal::OS_Main_Exit(); + + return result; } } // namespace Juliet diff --git a/Juliet/src/Core/HAL/OS/OS_Private.h b/Juliet/src/Core/HAL/OS/OS_Private.h index d16e6ed..6bdd625 100644 --- a/Juliet/src/Core/HAL/OS/OS_Private.h +++ b/Juliet/src/Core/HAL/OS/OS_Private.h @@ -22,6 +22,7 @@ namespace Juliet namespace Internal { - int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv); - } + int OS_Main(int argc, wchar_t** argv); + void OS_Main_Exit(); + } // namespace Internal } // namespace Juliet diff --git a/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp index 23723ea..6fc48bc 100644 --- a/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp +++ b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp @@ -1,17 +1,21 @@ #include #include +#include #include #include #include #include #include +#include namespace Juliet { + Win32_SetThreadDescription_FuncType* Win32_SetThreadDescription_Func = nullptr; + namespace { - global RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {}; - } + RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {}; + } // namespace namespace Memory::Internal { @@ -97,7 +101,9 @@ namespace Juliet namespace Internal { - int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv) + thread_local thread_context* mainThread = nullptr; + + int OS_Main(int argc, wchar_t** argv) { SetUnhandledExceptionFilter(&ExceptionFilter); @@ -109,6 +115,11 @@ namespace Juliet return EXIT_FAILURE; } + // Get some kernel32 functions + auto dynLib = LoadDynamicLibrary("kernel32.dll"); + Win32_SetThreadDescription_Func = + (Win32_SetThreadDescription_FuncType*)LoadFunction(dynLib, "SetThreadDescription"); + // Create a dummy socket to access RIO functions. Those will be used to do fine memory management { WSADATA WinSockData; @@ -121,8 +132,17 @@ namespace Juliet closesocket(Sock); } - int result = entryPointFunc(argc, argv); - return result; + mainThread = thread_context_alloc(); + thread_context_select(mainThread); + + return 0; + } + + void OS_Main_Exit() + { + Assert(mainThread); + thread_context_release(mainThread); + mainThread = nullptr; } } // namespace Internal } // namespace Juliet diff --git a/Juliet/src/Core/HAL/Win32.h b/Juliet/src/Core/HAL/Win32.h index 42d933d..e81b223 100644 --- a/Juliet/src/Core/HAL/Win32.h +++ b/Juliet/src/Core/HAL/Win32.h @@ -75,3 +75,5 @@ #undef min #undef max + +using Win32_SetThreadDescription_FuncType = HRESULT(HANDLE hThread, PCWSTR lpThreadDescription); diff --git a/Juliet/src/Core/HotReload/HotReload.cpp b/Juliet/src/Core/HotReload/HotReload.cpp index e0c409c..0c13956 100644 --- a/Juliet/src/Core/HotReload/HotReload.cpp +++ b/Juliet/src/Core/HotReload/HotReload.cpp @@ -11,7 +11,7 @@ namespace Juliet { void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename) { - code.Arena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_ONLY(, "Hot Reload")); + code.Arena = ArenaAllocate({ .ReserveSize = Megabytes(1), .Name = "Hot Reload" }); // Get the app base path and build the dll path from there. String basePath = GetBasePath(); @@ -25,7 +25,7 @@ namespace Juliet const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings - code.DLLFullPath.Data = + code.DLLFullPath.Str = static_cast(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_PARAM("DLL Path"))); int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName)); if (writtenSize < static_cast(dllFullPathLength) - 1) @@ -39,7 +39,7 @@ namespace Juliet // Lock filename path const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings - code.LockFullPath.Data = + code.LockFullPath.Str = static_cast(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_PARAM("Lock File Path"))); writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename)); if (writtenSize < static_cast(lockPathLength) - 1) diff --git a/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp b/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp index b40e778..7811744 100644 --- a/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp +++ b/Juliet/src/Core/HotReload/Win32/Win32HotReload.cpp @@ -34,11 +34,11 @@ namespace Juliet // TODO : Create and use a TransientAllocator // Create temp dll name - char* lockFilename = code.LockFullPath.Data; + char* lockFilename = code.LockFullPath.Str; WIN32_FILE_ATTRIBUTE_DATA Ignored; if (!GetFileAttributesExA(lockFilename, GetFileExInfoStandard, &Ignored)) { - const char* dllName = code.DLLFullPath.Data; + const char* dllName = code.DLLFullPath.Str; FILETIME lastWriteTime = GetLastWriteTime(dllName); ULARGE_INTEGER result{ .LowPart = lastWriteTime.dwLowDateTime, .HighPart = lastWriteTime.dwHighDateTime }; @@ -145,7 +145,7 @@ namespace Juliet codeLastWriteTime.dwHighDateTime = largeInt.HighPart; codeLastWriteTime.dwLowDateTime = largeInt.LowPart; - FILETIME lastWriteTime = GetLastWriteTime(code.DLLFullPath.Data); + FILETIME lastWriteTime = GetLastWriteTime(code.DLLFullPath.Str); int compare = CompareFileTime(&lastWriteTime, &codeLastWriteTime); return compare != 0; } diff --git a/Juliet/src/Core/ImGui/ImGuiService.cpp b/Juliet/src/Core/ImGui/ImGuiService.cpp index 3ea3f58..4883ca0 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({} JULIET_DEBUG_ONLY(, "ImGui")); + g_ImGuiArena = ArenaAllocate({ .Name = "Juliet" }); // Setup Allocator ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper, nullptr); diff --git a/Juliet/src/Core/Logging/LogManager.cpp b/Juliet/src/Core/Logging/LogManager.cpp index 70f4475..6c21644 100644 --- a/Juliet/src/Core/Logging/LogManager.cpp +++ b/Juliet/src/Core/Logging/LogManager.cpp @@ -59,7 +59,7 @@ namespace Juliet Logs* LogAllocate() { - Arena* arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Log Manager")); + Arena* arena = ArenaAllocate({ .Name = "Log Manager" }); Logs* logs = ArenaPushStruct(arena); logs->Arena = arena; return logs; diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp index cb2e37b..bc67799 100644 --- a/Juliet/src/Core/Memory/MemoryArena.cpp +++ b/Juliet/src/Core/Memory/MemoryArena.cpp @@ -18,17 +18,15 @@ namespace Juliet // https://github.com/EpicGamesExt/raddebugger/blob/master/src/base/base_arena.c - Arena* ArenaAllocate(const ArenaParams& params JULIET_DEBUG_ONLY(, const char* name), const std::source_location& loc) + 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); + Byte* baseMem = Memory::OS_Reserve(reserve_size); Memory::OS_Commit(baseMem, commit_size); Arena* arena = reinterpret_cast(baseMem); @@ -47,7 +45,16 @@ namespace Juliet arena->CanReserveMore = params.CanReserveMore; arena->FirstDebugInfo = nullptr; - DebugArenaSetDebugName(arena, name); + if (params.Name == nullptr) + { + arena->Name = "NoName"; + } + else + { + arena->Name = params.Name; + } + + DebugArenaSetDebugName(arena, arena->Name); DebugRegisterArena(arena); #endif @@ -112,8 +119,7 @@ namespace Juliet commitSize = AlignPow2(size + k_ArenaHeaderSize, align); } - newBlock = - ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize } JULIET_DEBUG_ONLY(, arena->Name)); + newBlock = ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize, .Name = arena->Name }); } newBlock->BasePosition = current->BasePosition + current->Reserved; @@ -151,8 +157,9 @@ namespace Juliet { result = reinterpret_cast(current) + positionPrePush; current->Position = positionPostPush; - - JULIET_DEBUG_ONLY(if (!IsDebugInfoArena(arena)) { DebugArenaAddDebugInfo(current, size, positionPrePush, tag); }) + + JULIET_DEBUG_ONLY( + if (!IsDebugInfoArena(arena)) { DebugArenaAddDebugInfo(current, size, positionPrePush, tag); }) if (sizeToZero != 0) { diff --git a/Juliet/src/Core/Memory/MemoryArenaDebug.cpp b/Juliet/src/Core/Memory/MemoryArenaDebug.cpp index 0e00b8f..fe9c09c 100644 --- a/Juliet/src/Core/Memory/MemoryArenaDebug.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaDebug.cpp @@ -24,8 +24,8 @@ namespace Juliet if (!g_DebugInfoArena) { // Create a dedicated arena for debug info - g_DebugInfoArena = ArenaAllocate( - { .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64) } JULIET_DEBUG_ONLY(, "Debug Info Arena")); + g_DebugInfoArena = + ArenaAllocate({ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64), .Name = "Debug Info Arena" }); } return ArenaPushStruct(g_DebugInfoArena JULIET_DEBUG_PARAM("ArenaDebugInfo")); @@ -35,8 +35,8 @@ namespace Juliet { if (!g_DebugInfoArena) { - g_DebugInfoArena = ArenaAllocate( - { .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64) } JULIET_DEBUG_ONLY(, "Debug Info Arena")); + g_DebugInfoArena = + ArenaAllocate({ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64), .Name = "Debug Info Arena" }); } return g_DebugInfoArena; } @@ -150,7 +150,7 @@ namespace Juliet if (tag) { String copiedTag = StringCopy(g_DebugInfoArena, WrapString(tag)); - info->Tag = copiedTag.Data; + info->Tag = copiedTag.Str; } else { diff --git a/Juliet/src/Core/Memory/MemoryArenaTests.cpp b/Juliet/src/Core/Memory/MemoryArenaTests.cpp index c4ce89c..ded87f8 100644 --- a/Juliet/src/Core/Memory/MemoryArenaTests.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaTests.cpp @@ -19,8 +19,8 @@ namespace Juliet::UnitTest printf("Running Paged Memory Arena Tests...\n"); // New Arena! - ArenaParams param{ .ReserveSize = Megabytes(64llu), .CommitSize = Kilobytes(64llu) }; - Arena* testArena = ArenaAllocate(param JULIET_DEBUG_ONLY(, "Test Arena")); + ArenaParams param{ .ReserveSize = Megabytes(64llu), .CommitSize = Kilobytes(64llu), .Name = "Test Arena" }; + Arena* testArena = ArenaAllocate(param); size_t pos = ArenaPos(testArena); Assert(pos == k_ArenaHeaderSize); diff --git a/Juliet/src/Core/Thread/ThreadContext.cpp b/Juliet/src/Core/Thread/ThreadContext.cpp new file mode 100644 index 0000000..7c1666b --- /dev/null +++ b/Juliet/src/Core/Thread/ThreadContext.cpp @@ -0,0 +1,76 @@ +#include + +#include + +namespace Juliet +{ + thread_local thread_context* local_thread_context; + + thread_context* thread_context_alloc() + { + thread_local char name[2][1024]; + juliet_snprintf(name[0], sizeof(name[0]), "Scratch/0[TID:%u]", thread_id()); + juliet_snprintf(name[1], sizeof(name[1]), "Scratch/1[TID:%u]", thread_id()); + Arena* arena_0 = ArenaAllocate({ .Name = name[0] }); + Arena* arena_1 = ArenaAllocate({ .Name = name[1] }); + + thread_context* ctx = ArenaPushStruct(arena_0); + ctx->ScratchArenas[0] = arena_0; + ctx->ScratchArenas[1] = arena_1; + return ctx; + } + + void thread_context_release(NonNullPtr ctx) + { + ArenaRelease(ctx->ScratchArenas[1]); + ArenaRelease(ctx->ScratchArenas[0]); + } + + void thread_context_select(NonNullPtr ctx) + { + local_thread_context = ctx.Get(); + } + + thread_context* thread_context_current() + { + Assert(local_thread_context); + return local_thread_context; + } + + Arena* thread_context_get_scratch(Arena** conflicts, size_t count) + { + thread_context* ctx = thread_context_current(); + Arena* result = nullptr; + Arena** arena_ptr = ctx->ScratchArenas; + for (size_t i = 0; i < ArraySize(ctx->ScratchArenas); i += 1, arena_ptr += 1) + { + Arena** conflict_ptr = conflicts; + bool has_conflict = false; + for (size_t j = 0; j < count; j += 1, conflict_ptr += 1) + { + if (*arena_ptr == *conflict_ptr) + { + has_conflict = true; + break; + } + } + if (!has_conflict) + { + result = *arena_ptr; + break; + } + } + return result; + } + + TempArena scratch_begin(Arena** conflicts, size_t count) + { + return ArenaTempBegin(thread_context_get_scratch(conflicts, count)); + } + + void scratch_end(TempArena scratch) + { + ArenaTempEnd(scratch); + } + +} // namespace Juliet diff --git a/Juliet/src/Core/Thread/win32_thread.cpp b/Juliet/src/Core/Thread/win32_thread.cpp new file mode 100644 index 0000000..fe7f236 --- /dev/null +++ b/Juliet/src/Core/Thread/win32_thread.cpp @@ -0,0 +1,63 @@ +#include + +#include +#include + +#include + +namespace Juliet +{ + uint32 thread_id() + { + uint32 id = GetCurrentThreadId(); + return id; + } + + extern Win32_SetThreadDescription_FuncType* Win32_SetThreadDescription_Func; + + void set_thread_name(String name) + { + TempArena scratch = scratch_begin(0, 0); + + // New way: + // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription + // Old way: + // https://learn.microsoft.com/fr-fr/previous-versions/visualstudio/visual-studio-2015/debugger/how-to-set-a-thread-name-in-native-code?view=vs-2015&redirectedfrom=MSDN + + if (Win32_SetThreadDescription_Func != nullptr) + { + String16 name16 = str16_from_8(scratch.Arena, name); + Win32_SetThreadDescription_Func(GetCurrentThread(), (WCHAR*)name16.Str); + } + + String8 name_copy = StringCopy(scratch.Arena, name); + +#pragma pack(push, 8) + struct THREADNAME_INFO + { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. + }; +#pragma pack(pop) + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = CStr(name_copy); + info.dwThreadID = thread_id(); + info.dwFlags = 0; +#pragma warning(push) +#pragma warning(disable : 6320 6322) + __try + { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } +#pragma warning(pop) + + scratch_end(scratch); + } + +} // namespace Juliet diff --git a/Juliet/src/Engine/Debug/MemoryDebugger.cpp b/Juliet/src/Engine/Debug/MemoryDebugger.cpp index c071695..eb24cd5 100644 --- a/Juliet/src/Engine/Debug/MemoryDebugger.cpp +++ b/Juliet/src/Engine/Debug/MemoryDebugger.cpp @@ -46,7 +46,7 @@ namespace Juliet::Debug { if (s_PagedArenaStates.Arena == nullptr) { - Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState States")); + Arena* pagedArenaStates = ArenaAllocate({ .Name = "DebugState States" }); s_PagedArenaStates.Create(pagedArenaStates); } @@ -105,7 +105,7 @@ namespace Juliet::Debug static VectorArena blocks; if (blocks.Arena == nullptr) { - Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState Blocks")); + Arena* pagedArenaStates = ArenaAllocate({ .Name = "DebugState Blocks" }); blocks.Create(pagedArenaStates); } blocks.Clear(); diff --git a/Juliet/src/Engine/Engine.cpp b/Juliet/src/Engine/Engine.cpp index 5c82091..dbe348d 100644 --- a/Juliet/src/Engine/Engine.cpp +++ b/Juliet/src/Engine/Engine.cpp @@ -151,10 +151,8 @@ namespace Juliet void InitializeEngine(JulietInit_Flags flags) { - EngineInstance.PlatformArena = - ArenaAllocate({ .ReserveSize = Megabytes(128) } JULIET_DEBUG_PARAM("Platform Arena")); - EngineInstance.AssetArena = - ArenaAllocate({ .ReserveSize = Megabytes(256) } JULIET_DEBUG_PARAM("Asset Arena")); + EngineInstance.PlatformArena = ArenaAllocate({ .ReserveSize = Megabytes(128), .Name = "Platform Arena" }); + EngineInstance.AssetArena = ArenaAllocate({ .ReserveSize = Megabytes(256), .Name = "Asset Arena" }); InitializeLogManager(); diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp index 7b26e82..0e3f07c 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp @@ -4230,7 +4230,6 @@ namespace Juliet driver->D3D12SerializeVersionedRootSignatureFct = nullptr; - Assert(ArenaPos(driver->DriverArena) == sizeof(D3D12Driver)); // Verify we didnt forget to release something ArenaRelease(driver->DriverArena); } @@ -4314,7 +4313,7 @@ namespace Juliet GraphicsDevice* D3D12_CreateGraphicsDevice(bool enableDebug) { - Arena* driverArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "D3D12 Driver Arena")); + Arena* driverArena = ArenaAllocate({ .Name = "D3D12 Driver Arena" }); D3D12Driver* driver = ArenaPushStruct(driverArena JULIET_DEBUG_PARAM("D3D12Driver struct")); driver->DriverArena = driverArena; diff --git a/Juliet/src/Graphics/Graphics.cpp b/Juliet/src/Graphics/Graphics.cpp index 04c7c8b..33b307e 100644 --- a/Juliet/src/Graphics/Graphics.cpp +++ b/Juliet/src/Graphics/Graphics.cpp @@ -328,7 +328,7 @@ namespace Juliet // TODO: Add path builder in the lib String base = GetBasePath(); char inplaceBuffer[256]; - snprintf(inplaceBuffer, sizeof(inplaceBuffer), "%s%s", base.Data, filename.Data); + snprintf(inplaceBuffer, sizeof(inplaceBuffer), "%s%s", base.Str, filename.Str); String absolutePath = WrapString(inplaceBuffer); shaderByteCode = LoadFile(absolutePath); } diff --git a/Juliet/src/UnitTest/Container/VectorUnitTest.cpp b/Juliet/src/UnitTest/Container/VectorUnitTest.cpp index c833a42..4a5c951 100644 --- a/Juliet/src/UnitTest/Container/VectorUnitTest.cpp +++ b/Juliet/src/UnitTest/Container/VectorUnitTest.cpp @@ -28,8 +28,8 @@ namespace Juliet::UnitTest void VectorUnitTest() { - ArenaParams params{}; - Arena* testArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorUnitTestArena")); + ArenaParams params{ .Name = "VectorUnitTestArena" }; + Arena* testArena = ArenaAllocate(params); // Test 1: Integer VectorArena (Basic Operations) {