Adding scratch arena for main thread (and any thread in the future)

Added some function based on raddbg code for string conversion and more.
This commit is contained in:
2026-08-16 18:06:46 -04:00
parent 3e7216f57d
commit d1b7c5dbbe
32 changed files with 477 additions and 102 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ void InitEntityManager(Juliet::NonNullPtr<World> world)
newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities")); 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() void ShutdownEntityManager()
+2 -2
View File
@@ -43,7 +43,7 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_
gGameState = params->GameState; gGameState = params->GameState;
if (!gGameState) 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<GameState>(gameStateArena); auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
gGameState = params->GameState = gameState; gGameState = params->GameState = gameState;
gameState->TotalArena = gameStateArena; gameState->TotalArena = gameStateArena;
@@ -57,7 +57,7 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_
ReserveCamera(4); ReserveCamera(4);
// Bootstrap world // 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<World>(worldArena JULIET_DEBUG_PARAM("World")); World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
gameState->World = world; gameState->World = world;
gameState->World->WorldArena = worldArena; gameState->World->WorldArena = worldArena;
+26
View File
@@ -202,4 +202,30 @@ namespace Juliet
return "UnknownType"; return "UnknownType";
#endif #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 } // namespace Juliet
+30 -14
View File
@@ -19,7 +19,7 @@ namespace Juliet
struct Arena; struct Arena;
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 } #define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
#define CStr(str) ((str).Data) #define CStr(str) ((str).Str)
#define InplaceString(name, size) \ #define InplaceString(name, size) \
char name##_[size]; \ char name##_[size]; \
MemSet(name##_, 0, sizeof(uint32)); \ MemSet(name##_, 0, sizeof(uint32)); \
@@ -40,17 +40,30 @@ namespace Juliet
// Represents a UTF-8 String. // Represents a UTF-8 String.
// Not null terminated. // Not null terminated.
struct String struct String8
{ {
char* Data; char* Str;
size_t Size; size_t Size;
}; };
using String = String8;
struct String16
{
uint16* Str;
size_t Size;
};
struct StringBuffer : String struct StringBuffer : String
{ {
size_t Capacity; size_t Capacity;
}; };
struct UnicodeDecode
{
uint32 Increment;
uint32 Codepoint;
};
constexpr uint32 kInvalidUTF8 = 0xFFFD; constexpr uint32 kInvalidUTF8 = 0xFFFD;
inline size_t StringLength(String str) inline size_t StringLength(String str)
@@ -75,13 +88,13 @@ namespace Juliet
inline bool IsValid(String str) 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) inline String WrapString(const char* str)
{ {
String result = {}; String result = {};
result.Data = const_cast<char*>(str); result.Str = const_cast<char*>(str);
result.Size = str ? strlen(str) : 0; result.Size = str ? strlen(str) : 0;
return result; return result;
} }
@@ -91,9 +104,9 @@ namespace Juliet
String result = str; String result = str;
while (result.Size) while (result.Size)
{ {
if (*result.Data != c) if (*result.Str != c)
{ {
++result.Data; ++result.Str;
--result.Size; --result.Size;
} }
else 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(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); extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst, bool nullTerminate);
JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str); JULIET_API String StringCopy(NonNullPtr<Arena> arena, String str);
JULIET_API String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
template <typename... Args> template <typename... Args>
String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args) String Format(NonNullPtr<Arena> arena, const char* formatStr, Args&&... args)
@@ -158,6 +172,8 @@ namespace Juliet
std::string result = std::vformat(formatStr, std::make_format_args(args...)); std::string result = std::vformat(formatStr, std::make_format_args(args...));
return StringCopy(arena, WrapString(result.c_str())); return StringCopy(arena, WrapString(result.c_str()));
} }
#define juliet_snprintf snprintf
} // namespace Juliet } // namespace Juliet
#ifdef UNIT_TEST #ifdef UNIT_TEST
@@ -169,12 +185,12 @@ namespace Juliet::UnitTest
String s2 = ConstString("abcdefabcdef"); String s2 = ConstString("abcdefabcdef");
String s3 = ConstString("11111111111111111111"); String s3 = ConstString("11111111111111111111");
Assert(FindChar(s1, 'x').Data == nullptr); Assert(FindChar(s1, 'x').Str == nullptr);
Assert(FindChar(s2, 'y').Data == nullptr); Assert(FindChar(s2, 'y').Str == nullptr);
Assert(FindChar(s2, 'a').Data - s2.Data == 0); Assert(FindChar(s2, 'a').Str - s2.Str == 0);
Assert(FindChar(s2, 'd').Data - s2.Data == 3); Assert(FindChar(s2, 'd').Str - s2.Str == 3);
Assert(FindChar(s2, 'f').Data - s2.Data == 5); Assert(FindChar(s2, 'f').Str - s2.Str == 5);
Assert(FindChar(s3, '1').Data - s3.Data == 0); Assert(FindChar(s3, '1').Str - s3.Str == 0);
} }
} // namespace Juliet::UnitTest } // namespace Juliet::UnitTest
#endif #endif
+9 -7
View File
@@ -44,7 +44,7 @@ namespace Juliet
JULIET_DEBUG_ONLY(Arena* GlobalNext;) JULIET_DEBUG_ONLY(Arena* GlobalNext;)
JULIET_DEBUG_ONLY(Arena* GlobalPrev;) JULIET_DEBUG_ONLY(Arena* GlobalPrev;)
JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;) JULIET_DEBUG_ONLY(ArenaDebugInfo* FirstDebugInfo;)
JULIET_DEBUG_ONLY(const char* Name;) const char* Name;
}; };
static_assert(sizeof(Arena) <= k_ArenaHeaderSize); static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
@@ -59,11 +59,13 @@ namespace Juliet
uint64 ReserveSize = g_Arena_Default_Reserve_Size; uint64 ReserveSize = g_Arena_Default_Reserve_Size;
uint64 CommitSize = g_Arena_Default_Commit_Size; uint64 CommitSize = g_Arena_Default_Commit_Size;
const char* Name;
// When false, will assert if a new block is reserved. // When false, will assert if a new block is reserved.
JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;) 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()); const std::source_location& loc = std::source_location::current());
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena); JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
@@ -88,7 +90,7 @@ namespace Juliet
{ {
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg), return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
std::forward<DebugArgs>(debugArgs)...) std::forward<DebugArgs>(debugArgs)...)
.Data; .Str;
}())); }()));
} }
@@ -102,23 +104,23 @@ namespace Juliet
{ {
if constexpr (sizeof...(DebugArgs) > 0) if constexpr (sizeof...(DebugArgs) > 0)
{ {
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data; return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
} }
return GetTypeName<Type>(); return GetTypeName<Type>();
}()))); }())));
} }
template <typename Type JULIET_DEBUG_ONLY(, typename... DebugArgs)> template <typename Type, bool shouldZero = true JULIET_DEBUG_ONLY(, typename... DebugArgs)>
[[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs)) [[nodiscard]] Type* ArenaPushArray(NonNullPtr<Arena> arena, size_t count JULIET_DEBUG_PARAM(DebugArgs&&... debugArgs))
{ {
return static_cast<Type*>( return static_cast<Type*>(
ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)), ArenaPush(arena, sizeof(Type) * count, Max(8ull, AlignOf(Type)),
true JULIET_DEBUG_PARAM( shouldZero JULIET_DEBUG_PARAM(
[&]() -> const char* [&]() -> const char*
{ {
if constexpr (sizeof...(DebugArgs) > 0) if constexpr (sizeof...(DebugArgs) > 0)
{ {
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data; return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
} }
return GetTypeName<Type>(); return GetTypeName<Type>();
}()))); }())));
+2
View File
@@ -28,3 +28,5 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include <Core/Common/CoreTypes.h>
+5 -1
View File
@@ -1,8 +1,12 @@
#pragma once #pragma once
#include <Core/Common/String.h>
namespace Juliet namespace Juliet
{ {
using Thread = std::thread; uint32 thread_id();
void set_thread_name(String name);
// TODO : Proper wait // TODO : Proper wait
inline void wait_ms(int milliseconds) inline void wait_ms(int milliseconds)
@@ -0,0 +1,24 @@
#pragma once
#include <Core/Common/CoreTypes.h>
#include <Core/Memory/MemoryArena.h>
namespace Juliet
{
struct thread_context
{
Arena* ScratchArenas[2];
char ThreadName[64];
uint8 ThreadNameSize;
};
thread_context* thread_context_alloc();
void thread_context_release(NonNullPtr<thread_context> ctx);
void thread_context_select(NonNullPtr<thread_context> 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
+136 -10
View File
@@ -60,6 +60,7 @@ namespace Juliet
} }
} // namespace } // namespace
// TODO: remove this as we convert to simple unicode decode / encode at the bottom
uint32 StepUTF8(String& inStr) uint32 StepUTF8(String& inStr)
{ {
// From rfc3629, the UTF-8 spec: // From rfc3629, the UTF-8 spec:
@@ -92,7 +93,7 @@ namespace Juliet
} }
if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx
{ {
inStr.Data += 1; inStr.Str += 1;
inStr.Size -= 1; inStr.Size -= 1;
return octet; return octet;
} }
@@ -104,7 +105,7 @@ namespace Juliet
const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F); const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F);
if (result >= 0x80) // If the result is smaller than 0x80 its an overlong! if (result >= 0x80) // If the result is smaller than 0x80 its an overlong!
{ {
inStr.Data += 2; inStr.Str += 2;
inStr.Size -= 1; inStr.Size -= 1;
return result; return result;
} }
@@ -131,7 +132,7 @@ namespace Juliet
{ {
if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate
{ {
inStr.Data += 3; inStr.Str += 3;
inStr.Size -= 1; inStr.Size -= 1;
return result; return result;
} }
@@ -164,7 +165,7 @@ namespace Juliet
const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet; const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet;
if (result >= 0x10000) // If smaller its an overlong if (result >= 0x10000) // If smaller its an overlong
{ {
inStr.Data += 4; inStr.Str += 4;
inStr.Size -= 1; inStr.Size -= 1;
return result; return result;
} }
@@ -180,7 +181,7 @@ namespace Juliet
} }
LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s", LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s",
isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false"); isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false");
inStr.Data += 1; inStr.Str += 1;
return kInvalidUTF8; return kInvalidUTF8;
} }
@@ -254,8 +255,8 @@ namespace Juliet
{ {
Assert(IsValid(src)); Assert(IsValid(src));
const char* srcStr = src.Data; const char* srcStr = src.Str;
char* dstStr = dst.Data; char* dstStr = dst.Str;
size_t remainingCapacity = dst.Capacity; size_t remainingCapacity = dst.Capacity;
uint32 character = 0; uint32 character = 0;
@@ -489,13 +490,138 @@ namespace Juliet
return ConvertString(sourceFormat, destFormat, src, dst, nullTerminate); 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> arena, String str) String StringCopy(NonNullPtr<Arena> arena, String str)
{ {
String result; String result;
result.Size = str.Size; result.Size = str.Size;
result.Data = static_cast<char*>(ArenaPush(arena, str.Size + 1, alignof(char), true JULIET_DEBUG_PARAM("String"))); result.Str = static_cast<char*>(ArenaPush(arena, str.Size + 1, alignof(char), true JULIET_DEBUG_PARAM("String")));
MemCopy(result.Data, str.Data, str.Size); MemCopy(result.Str, str.Str, str.Size);
result.Data[result.Size] = 0; result.Str[result.Size] = 0;
return result;
}
String16 str16_from_8(NonNullPtr<Arena> arena, String8 in)
{
String16 result = {};
if (in.Size > 0)
{
size_t neededCapacity = in.Size * 2;
uint16* str = ArenaPushArray<uint16, false>(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; return result;
} }
+2 -2
View File
@@ -23,7 +23,7 @@ namespace Juliet
{ {
Assert(!g_CurrentDisplayDevice); Assert(!g_CurrentDisplayDevice);
Arena* arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Display System")); Arena* arena = ArenaAllocate({ .Name = "Display System" });
DisplayDevice* candidateDevice = nullptr; DisplayDevice* candidateDevice = nullptr;
DisplayDeviceFactory* candidateFactory = nullptr; DisplayDeviceFactory* candidateFactory = nullptr;
@@ -80,7 +80,7 @@ namespace Juliet
Assert(g_CurrentDisplayDevice->CreatePlatformWindow); Assert(g_CurrentDisplayDevice->CreatePlatformWindow);
Window window = {}; Window window = {};
window.Arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Window")); window.Arena = ArenaAllocate({ .Name = "Window" });
window.Width = width; window.Width = width;
window.Height = height; window.Height = height;
@@ -59,7 +59,7 @@ namespace Juliet::Win32
int x = CW_USEDEFAULT, y = CW_USEDEFAULT; int x = CW_USEDEFAULT, y = CW_USEDEFAULT;
const int w = window->Width, h = window->Height; 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); instance, nullptr);
PumpEvents(self); PumpEvents(self);
@@ -22,7 +22,7 @@ namespace Juliet
DWORD attributes = GetFileAttributesA(path); DWORD attributes = GetFileAttributesA(path);
return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY); return (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY);
} }
} } // namespace
String GetBasePath() String GetBasePath()
{ {
@@ -71,10 +71,7 @@ namespace Juliet
// Probe candidate paths for compiled shader directory // Probe candidate paths for compiled shader directory
// 1. Shipping layout: Assets/Shaders/ next to the exe // 1. Shipping layout: Assets/Shaders/ next to the exe
// 2. Dev layout: ../../Assets/compiled/ (exe is in bin/x64Clang-<Config>/) // 2. Dev layout: ../../Assets/compiled/ (exe is in bin/x64Clang-<Config>/)
constexpr const char* kCandidates[] = { constexpr const char* kCandidates[] = { "Assets/Shaders/", "../../Assets/compiled/" };
"Assets/Shaders/",
"../../Assets/compiled/"
};
for (const char* candidate : kCandidates) for (const char* candidate : kCandidates)
{ {
@@ -103,12 +100,12 @@ namespace Juliet
if (IsValid(CachedBasePath)) if (IsValid(CachedBasePath))
{ {
CachedBasePath.Size = 0; CachedBasePath.Size = 0;
SafeFree(CachedBasePath.Data); SafeFree(CachedBasePath.Str);
} }
if (IsValid(CachedAssetBasePath)) if (IsValid(CachedAssetBasePath))
{ {
CachedAssetBasePath.Size = 0; CachedAssetBasePath.Size = 0;
SafeFree(CachedAssetBasePath.Data); SafeFree(CachedAssetBasePath.Str);
} }
} }
} // namespace Juliet } // namespace Juliet
@@ -58,7 +58,7 @@ namespace Juliet::Platform
bool IsAbsolutePath(String path) bool IsAbsolutePath(String path)
{ {
if (!path.Data || path.Size == 0) if (!path.Str || path.Size == 0)
{ {
return false; return false;
} }
@@ -69,7 +69,7 @@ namespace Juliet::Platform
// A disk designator with a backslash, for example "C:\" or "d:\". // 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. // 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. // 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; size_t pathLen = path.Size;
if (pathLen > 1) if (pathLen > 1)
+12 -12
View File
@@ -24,8 +24,8 @@ namespace Juliet::Internal
int64 FileSize(NonNullPtr<IOStreamDataPayload> payload) int64 FileSize(NonNullPtr<IOStreamDataPayload> payload)
{ {
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get()); Win32IOStreamDataPayload* win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
LARGE_INTEGER size; LARGE_INTEGER size;
if (!GetFileSizeEx(win32Payload->Handle, &size)) if (!GetFileSizeEx(win32Payload->Handle, &size))
{ {
@@ -38,7 +38,7 @@ namespace Juliet::Internal
int64 FileSeek(NonNullPtr<IOStreamDataPayload> payload, int64 offset, IOStreamSeekPivot pivot) int64 FileSeek(NonNullPtr<IOStreamDataPayload> payload, int64 offset, IOStreamSeekPivot pivot)
{ {
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get()); Win32IOStreamDataPayload* win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
if ((pivot == IOStreamSeekPivot::Current) && (win32Payload->SizeLeft > 0)) if ((pivot == IOStreamSeekPivot::Current) && (win32Payload->SizeLeft > 0))
{ {
offset -= static_cast<int64>(win32Payload->SizeLeft); offset -= static_cast<int64>(win32Payload->SizeLeft);
@@ -69,10 +69,10 @@ namespace Juliet::Internal
size_t FileRead(NonNullPtr<IOStreamDataPayload> payload, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status) size_t FileRead(NonNullPtr<IOStreamDataPayload> payload, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status)
{ {
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get()); Win32IOStreamDataPayload* win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
size_t totalNeed = size; size_t totalNeed = size;
size_t totalRead = 0; size_t totalRead = 0;
size_t sizeToReadAhead = 0; size_t sizeToReadAhead = 0;
if (win32Payload->SizeLeft > 0) if (win32Payload->SizeLeft > 0)
{ {
uint8* data = static_cast<uint8*>(win32Payload->Data) + win32Payload->Size - win32Payload->SizeLeft; uint8* data = static_cast<uint8*>(win32Payload->Data) + win32Payload->Size - win32Payload->SizeLeft;
@@ -133,8 +133,8 @@ namespace Juliet::Internal
size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status) size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status)
{ {
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get()); Win32IOStreamDataPayload* win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
DWORD bytes; DWORD bytes;
if (win32Payload->SizeLeft) 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 +"); "Mode should have at most 2 characters, one being either r,w or a and the other can only be +");
if (modeLength == 1) 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"); "Invalid Mode. First char is not r,w or a");
} }
else 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 #endif
@@ -238,7 +238,7 @@ namespace Juliet::Internal
} }
constexpr bool autoClose = true; constexpr bool autoClose = true;
auto payload = static_cast<Win32IOStreamDataPayload*>(Calloc(1, sizeof(Win32IOStreamDataPayload))); Win32IOStreamDataPayload* payload = static_cast<Win32IOStreamDataPayload*>(Calloc(1, sizeof(Win32IOStreamDataPayload)));
if (!payload) if (!payload)
{ {
if (autoClose) if (autoClose)
+13 -1
View File
@@ -1,5 +1,6 @@
#include <Core/HAL/OS/OS.h> #include <Core/HAL/OS/OS.h>
#include <Core/HAL/OS/OS_Private.h> #include <Core/HAL/OS/OS_Private.h>
#include <Core/Thread/Thread.h>
namespace Juliet namespace Juliet
{ {
@@ -61,7 +62,18 @@ namespace Juliet
int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv) 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 } // namespace Juliet
+3 -2
View File
@@ -22,6 +22,7 @@ namespace Juliet
namespace Internal 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 } // namespace Juliet
+25 -5
View File
@@ -1,17 +1,21 @@
#include <Core/Common/CoreTypes.h> #include <Core/Common/CoreTypes.h>
#include <Core/Common/CoreUtils.h> #include <Core/Common/CoreUtils.h>
#include <Core/HAL/DynLib/DynamicLibrary.h>
#include <Core/HAL/OS/OS.h> #include <Core/HAL/OS/OS.h>
#include <Core/HAL/OS/OS_Private.h> #include <Core/HAL/OS/OS_Private.h>
#include <Core/HAL/Win32.h> #include <Core/HAL/Win32.h>
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h> #include <Core/Logging/LogTypes.h>
#include <Core/Thread/ThreadContext.h>
namespace Juliet namespace Juliet
{ {
Win32_SetThreadDescription_FuncType* Win32_SetThreadDescription_Func = nullptr;
namespace namespace
{ {
global RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {}; RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {};
} } // namespace
namespace Memory::Internal namespace Memory::Internal
{ {
@@ -97,7 +101,9 @@ namespace Juliet
namespace Internal 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); SetUnhandledExceptionFilter(&ExceptionFilter);
@@ -109,6 +115,11 @@ namespace Juliet
return EXIT_FAILURE; 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 // Create a dummy socket to access RIO functions. Those will be used to do fine memory management
{ {
WSADATA WinSockData; WSADATA WinSockData;
@@ -121,8 +132,17 @@ namespace Juliet
closesocket(Sock); closesocket(Sock);
} }
int result = entryPointFunc(argc, argv); mainThread = thread_context_alloc();
return result; thread_context_select(mainThread);
return 0;
}
void OS_Main_Exit()
{
Assert(mainThread);
thread_context_release(mainThread);
mainThread = nullptr;
} }
} // namespace Internal } // namespace Internal
} // namespace Juliet } // namespace Juliet
+2
View File
@@ -75,3 +75,5 @@
#undef min #undef min
#undef max #undef max
using Win32_SetThreadDescription_FuncType = HRESULT(HANDLE hThread, PCWSTR lpThreadDescription);
+3 -3
View File
@@ -11,7 +11,7 @@ namespace Juliet
{ {
void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename) 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. // Get the app base path and build the dll path from there.
String basePath = GetBasePath(); String basePath = GetBasePath();
@@ -25,7 +25,7 @@ namespace Juliet
const size_t dllFullPathLength = const size_t dllFullPathLength =
basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings
code.DLLFullPath.Data = code.DLLFullPath.Str =
static_cast<char*>(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_PARAM("DLL Path"))); static_cast<char*>(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)); 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)
@@ -39,7 +39,7 @@ namespace Juliet
// Lock filename path // Lock filename path
const size_t lockPathLength = const size_t lockPathLength =
basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings
code.LockFullPath.Data = code.LockFullPath.Str =
static_cast<char*>(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_PARAM("Lock File Path"))); static_cast<char*>(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)); 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)
@@ -34,11 +34,11 @@ namespace Juliet
// TODO : Create and use a TransientAllocator // TODO : Create and use a TransientAllocator
// Create temp dll name // Create temp dll name
char* lockFilename = code.LockFullPath.Data; char* lockFilename = code.LockFullPath.Str;
WIN32_FILE_ATTRIBUTE_DATA Ignored; WIN32_FILE_ATTRIBUTE_DATA Ignored;
if (!GetFileAttributesExA(lockFilename, GetFileExInfoStandard, &Ignored)) if (!GetFileAttributesExA(lockFilename, GetFileExInfoStandard, &Ignored))
{ {
const char* dllName = code.DLLFullPath.Data; const char* dllName = code.DLLFullPath.Str;
FILETIME lastWriteTime = GetLastWriteTime(dllName); FILETIME lastWriteTime = GetLastWriteTime(dllName);
ULARGE_INTEGER result{ .LowPart = lastWriteTime.dwLowDateTime, .HighPart = lastWriteTime.dwHighDateTime }; ULARGE_INTEGER result{ .LowPart = lastWriteTime.dwLowDateTime, .HighPart = lastWriteTime.dwHighDateTime };
@@ -145,7 +145,7 @@ namespace Juliet
codeLastWriteTime.dwHighDateTime = largeInt.HighPart; codeLastWriteTime.dwHighDateTime = largeInt.HighPart;
codeLastWriteTime.dwLowDateTime = largeInt.LowPart; codeLastWriteTime.dwLowDateTime = largeInt.LowPart;
FILETIME lastWriteTime = GetLastWriteTime(code.DLLFullPath.Data); FILETIME lastWriteTime = GetLastWriteTime(code.DLLFullPath.Str);
int compare = CompareFileTime(&lastWriteTime, &codeLastWriteTime); int compare = CompareFileTime(&lastWriteTime, &codeLastWriteTime);
return compare != 0; return compare != 0;
} }
+1 -1
View File
@@ -75,7 +75,7 @@ namespace Juliet::ImGuiService
Assert(!g_Initialized); Assert(!g_Initialized);
// Initialize ImGui Arena using Engine Pool // Initialize ImGui Arena using Engine Pool
g_ImGuiArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "ImGui")); g_ImGuiArena = ArenaAllocate({ .Name = "Juliet" });
// Setup Allocator // Setup Allocator
ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper, nullptr); ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper, nullptr);
+1 -1
View File
@@ -59,7 +59,7 @@ namespace Juliet
Logs* LogAllocate() Logs* LogAllocate()
{ {
Arena* arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Log Manager")); Arena* arena = ArenaAllocate({ .Name = "Log Manager" });
Logs* logs = ArenaPushStruct<Logs>(arena); Logs* logs = ArenaPushStruct<Logs>(arena);
logs->Arena = arena; logs->Arena = arena;
return logs; return logs;
+15 -8
View File
@@ -18,17 +18,15 @@ namespace Juliet
// https://github.com/EpicGamesExt/raddebugger/blob/master/src/base/base_arena.c // 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()); 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 reserve_size = AlignPow2(params.ReserveSize, k_PageSize);
uint64 commit_size = AlignPow2(params.CommitSize, k_PageSize); uint64 commit_size = AlignPow2(params.CommitSize, k_PageSize);
// TODO: handle large pages // TODO: handle large pages
baseMem = Memory::OS_Reserve(reserve_size); Byte* baseMem = Memory::OS_Reserve(reserve_size);
Memory::OS_Commit(baseMem, commit_size); Memory::OS_Commit(baseMem, commit_size);
Arena* arena = reinterpret_cast<Arena*>(baseMem); Arena* arena = reinterpret_cast<Arena*>(baseMem);
@@ -47,7 +45,16 @@ namespace Juliet
arena->CanReserveMore = params.CanReserveMore; arena->CanReserveMore = params.CanReserveMore;
arena->FirstDebugInfo = nullptr; arena->FirstDebugInfo = nullptr;
DebugArenaSetDebugName(arena, name); if (params.Name == nullptr)
{
arena->Name = "NoName";
}
else
{
arena->Name = params.Name;
}
DebugArenaSetDebugName(arena, arena->Name);
DebugRegisterArena(arena); DebugRegisterArena(arena);
#endif #endif
@@ -112,8 +119,7 @@ namespace Juliet
commitSize = AlignPow2(size + k_ArenaHeaderSize, align); commitSize = AlignPow2(size + k_ArenaHeaderSize, align);
} }
newBlock = newBlock = ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize, .Name = arena->Name });
ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize } JULIET_DEBUG_ONLY(, arena->Name));
} }
newBlock->BasePosition = current->BasePosition + current->Reserved; newBlock->BasePosition = current->BasePosition + current->Reserved;
@@ -152,7 +158,8 @@ namespace Juliet
result = reinterpret_cast<Byte*>(current) + positionPrePush; result = reinterpret_cast<Byte*>(current) + positionPrePush;
current->Position = positionPostPush; 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) if (sizeToZero != 0)
{ {
+5 -5
View File
@@ -24,8 +24,8 @@ namespace Juliet
if (!g_DebugInfoArena) if (!g_DebugInfoArena)
{ {
// Create a dedicated arena for debug info // Create a dedicated arena for debug info
g_DebugInfoArena = ArenaAllocate( g_DebugInfoArena =
{ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64) } JULIET_DEBUG_ONLY(, "Debug Info Arena")); ArenaAllocate({ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64), .Name = "Debug Info Arena" });
} }
return ArenaPushStruct<ArenaDebugInfo>(g_DebugInfoArena JULIET_DEBUG_PARAM("ArenaDebugInfo")); return ArenaPushStruct<ArenaDebugInfo>(g_DebugInfoArena JULIET_DEBUG_PARAM("ArenaDebugInfo"));
@@ -35,8 +35,8 @@ namespace Juliet
{ {
if (!g_DebugInfoArena) if (!g_DebugInfoArena)
{ {
g_DebugInfoArena = ArenaAllocate( g_DebugInfoArena =
{ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64) } JULIET_DEBUG_ONLY(, "Debug Info Arena")); ArenaAllocate({ .ReserveSize = Megabytes(16), .CommitSize = Kilobytes(64), .Name = "Debug Info Arena" });
} }
return g_DebugInfoArena; return g_DebugInfoArena;
} }
@@ -150,7 +150,7 @@ namespace Juliet
if (tag) if (tag)
{ {
String copiedTag = StringCopy(g_DebugInfoArena, WrapString(tag)); String copiedTag = StringCopy(g_DebugInfoArena, WrapString(tag));
info->Tag = copiedTag.Data; info->Tag = copiedTag.Str;
} }
else else
{ {
+2 -2
View File
@@ -19,8 +19,8 @@ namespace Juliet::UnitTest
printf("Running Paged Memory Arena Tests...\n"); printf("Running Paged Memory Arena Tests...\n");
// New Arena! // New Arena!
ArenaParams param{ .ReserveSize = Megabytes(64llu), .CommitSize = Kilobytes(64llu) }; ArenaParams param{ .ReserveSize = Megabytes(64llu), .CommitSize = Kilobytes(64llu), .Name = "Test Arena" };
Arena* testArena = ArenaAllocate(param JULIET_DEBUG_ONLY(, "Test Arena")); Arena* testArena = ArenaAllocate(param);
size_t pos = ArenaPos(testArena); size_t pos = ArenaPos(testArena);
Assert(pos == k_ArenaHeaderSize); Assert(pos == k_ArenaHeaderSize);
+76
View File
@@ -0,0 +1,76 @@
#include <Core/Thread/ThreadContext.h>
#include <Core/Thread/Thread.h>
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<thread_context>(arena_0);
ctx->ScratchArenas[0] = arena_0;
ctx->ScratchArenas[1] = arena_1;
return ctx;
}
void thread_context_release(NonNullPtr<thread_context> ctx)
{
ArenaRelease(ctx->ScratchArenas[1]);
ArenaRelease(ctx->ScratchArenas[0]);
}
void thread_context_select(NonNullPtr<thread_context> 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
+63
View File
@@ -0,0 +1,63 @@
#include <Core/Thread/Thread.h>
#include <Core/HAL/Win32.h>
#include <Core/Thread/ThreadContext.h>
#include <processthreadsapi.h>
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
+2 -2
View File
@@ -46,7 +46,7 @@ namespace Juliet::Debug
{ {
if (s_PagedArenaStates.Arena == nullptr) if (s_PagedArenaStates.Arena == nullptr)
{ {
Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState States")); Arena* pagedArenaStates = ArenaAllocate({ .Name = "DebugState States" });
s_PagedArenaStates.Create(pagedArenaStates); s_PagedArenaStates.Create(pagedArenaStates);
} }
@@ -105,7 +105,7 @@ namespace Juliet::Debug
static VectorArena<const Arena*> blocks; static VectorArena<const Arena*> blocks;
if (blocks.Arena == nullptr) if (blocks.Arena == nullptr)
{ {
Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState Blocks")); Arena* pagedArenaStates = ArenaAllocate({ .Name = "DebugState Blocks" });
blocks.Create(pagedArenaStates); blocks.Create(pagedArenaStates);
} }
blocks.Clear(); blocks.Clear();
+2 -4
View File
@@ -151,10 +151,8 @@ namespace Juliet
void InitializeEngine(JulietInit_Flags flags) void InitializeEngine(JulietInit_Flags flags)
{ {
EngineInstance.PlatformArena = EngineInstance.PlatformArena = ArenaAllocate({ .ReserveSize = Megabytes(128), .Name = "Platform Arena" });
ArenaAllocate({ .ReserveSize = Megabytes(128) } JULIET_DEBUG_PARAM("Platform Arena")); EngineInstance.AssetArena = ArenaAllocate({ .ReserveSize = Megabytes(256), .Name = "Asset Arena" });
EngineInstance.AssetArena =
ArenaAllocate({ .ReserveSize = Megabytes(256) } JULIET_DEBUG_PARAM("Asset Arena"));
InitializeLogManager(); InitializeLogManager();
@@ -4230,7 +4230,6 @@ namespace Juliet
driver->D3D12SerializeVersionedRootSignatureFct = nullptr; driver->D3D12SerializeVersionedRootSignatureFct = nullptr;
Assert(ArenaPos(driver->DriverArena) == sizeof(D3D12Driver)); // Verify we didnt forget to release something
ArenaRelease(driver->DriverArena); ArenaRelease(driver->DriverArena);
} }
@@ -4314,7 +4313,7 @@ namespace Juliet
GraphicsDevice* D3D12_CreateGraphicsDevice(bool enableDebug) GraphicsDevice* D3D12_CreateGraphicsDevice(bool enableDebug)
{ {
Arena* driverArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "D3D12 Driver Arena")); Arena* driverArena = ArenaAllocate({ .Name = "D3D12 Driver Arena" });
D3D12Driver* driver = ArenaPushStruct<D3D12Driver>(driverArena JULIET_DEBUG_PARAM("D3D12Driver struct")); D3D12Driver* driver = ArenaPushStruct<D3D12Driver>(driverArena JULIET_DEBUG_PARAM("D3D12Driver struct"));
driver->DriverArena = driverArena; driver->DriverArena = driverArena;
+1 -1
View File
@@ -328,7 +328,7 @@ namespace Juliet
// TODO: Add path builder in the lib // TODO: Add path builder in the lib
String base = GetBasePath(); String base = GetBasePath();
char inplaceBuffer[256]; 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); String absolutePath = WrapString(inplaceBuffer);
shaderByteCode = LoadFile(absolutePath); shaderByteCode = LoadFile(absolutePath);
} }
@@ -28,8 +28,8 @@ namespace Juliet::UnitTest
void VectorUnitTest() void VectorUnitTest()
{ {
ArenaParams params{}; ArenaParams params{ .Name = "VectorUnitTestArena" };
Arena* testArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorUnitTestArena")); Arena* testArena = ArenaAllocate(params);
// Test 1: Integer VectorArena (Basic Operations) // Test 1: Integer VectorArena (Basic Operations)
{ {