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:
@@ -12,7 +12,7 @@ void InitEntityManager(Juliet::NonNullPtr<World> 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()
|
||||
|
||||
+2
-2
@@ -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<GameState>(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<World>(worldArena JULIET_DEBUG_PARAM("World"));
|
||||
gameState->World = world;
|
||||
gameState->World->WorldArena = worldArena;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Juliet
|
||||
struct Arena;
|
||||
|
||||
#define ConstString(str) { const_cast<char*>((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,9 +40,16 @@ 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;
|
||||
};
|
||||
|
||||
@@ -51,6 +58,12 @@ namespace Juliet
|
||||
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<char*>(str);
|
||||
result.Str = const_cast<char*>(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
|
||||
@@ -151,6 +164,7 @@ namespace Juliet
|
||||
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 String16 str16_from_8(NonNullPtr<Arena> arena, String8 str);
|
||||
|
||||
template <typename... 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...));
|
||||
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
|
||||
|
||||
@@ -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> arena);
|
||||
|
||||
@@ -88,7 +90,7 @@ namespace Juliet
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<FirstDebugArg>(firstDebugArg),
|
||||
std::forward<DebugArgs>(debugArgs)...)
|
||||
.Data;
|
||||
.Str;
|
||||
}()));
|
||||
}
|
||||
|
||||
@@ -102,23 +104,23 @@ namespace Juliet
|
||||
{
|
||||
if constexpr (sizeof...(DebugArgs) > 0)
|
||||
{
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Data;
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
||||
}
|
||||
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))
|
||||
{
|
||||
return static_cast<Type*>(
|
||||
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>(debugArgs)...).Data;
|
||||
return Format(GetDebugInfoArena(), std::forward<DebugArgs>(debugArgs)...).Str;
|
||||
}
|
||||
return GetTypeName<Type>();
|
||||
}())));
|
||||
|
||||
@@ -28,3 +28,5 @@
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/String.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
using Thread = std::thread;
|
||||
uint32 thread_id();
|
||||
|
||||
void set_thread_name(String name);
|
||||
|
||||
// TODO : Proper wait
|
||||
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
|
||||
@@ -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> arena, String str)
|
||||
{
|
||||
String result;
|
||||
result.Size = str.Size;
|
||||
result.Data = static_cast<char*>(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<char*>(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> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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-<Config>/)
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Juliet::Internal
|
||||
|
||||
int64 FileSize(NonNullPtr<IOStreamDataPayload> payload)
|
||||
{
|
||||
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
|
||||
Win32IOStreamDataPayload* win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
|
||||
LARGE_INTEGER size;
|
||||
|
||||
if (!GetFileSizeEx(win32Payload->Handle, &size))
|
||||
@@ -38,7 +38,7 @@ namespace Juliet::Internal
|
||||
|
||||
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))
|
||||
{
|
||||
offset -= static_cast<int64>(win32Payload->SizeLeft);
|
||||
@@ -69,7 +69,7 @@ namespace Juliet::Internal
|
||||
|
||||
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 totalRead = 0;
|
||||
size_t sizeToReadAhead = 0;
|
||||
@@ -133,7 +133,7 @@ namespace Juliet::Internal
|
||||
|
||||
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;
|
||||
|
||||
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<Win32IOStreamDataPayload*>(Calloc(1, sizeof(Win32IOStreamDataPayload)));
|
||||
Win32IOStreamDataPayload* payload = static_cast<Win32IOStreamDataPayload*>(Calloc(1, sizeof(Win32IOStreamDataPayload)));
|
||||
if (!payload)
|
||||
{
|
||||
if (autoClose)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
#include <Core/HAL/OS/OS_Private.h>
|
||||
#include <Core/Thread/Thread.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/HAL/DynLib/DynamicLibrary.h>
|
||||
#include <Core/HAL/OS/OS.h>
|
||||
#include <Core/HAL/OS/OS_Private.h>
|
||||
#include <Core/HAL/Win32.h>
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Thread/ThreadContext.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -75,3 +75,5 @@
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
using Win32_SetThreadDescription_FuncType = HRESULT(HANDLE hThread, PCWSTR lpThreadDescription);
|
||||
|
||||
@@ -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<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));
|
||||
if (writtenSize < static_cast<int>(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<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));
|
||||
if (writtenSize < static_cast<int>(lockPathLength) - 1)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Logs>(arena);
|
||||
logs->Arena = arena;
|
||||
return logs;
|
||||
|
||||
@@ -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<Arena*>(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;
|
||||
@@ -152,7 +158,8 @@ namespace Juliet
|
||||
result = reinterpret_cast<Byte*>(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)
|
||||
{
|
||||
|
||||
@@ -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<ArenaDebugInfo>(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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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<const Arena*> blocks;
|
||||
if (blocks.Arena == nullptr)
|
||||
{
|
||||
Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState Blocks"));
|
||||
Arena* pagedArenaStates = ArenaAllocate({ .Name = "DebugState Blocks" });
|
||||
blocks.Create(pagedArenaStates);
|
||||
}
|
||||
blocks.Clear();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<D3D12Driver>(driverArena JULIET_DEBUG_PARAM("D3D12Driver struct"));
|
||||
|
||||
driver->DriverArena = driverArena;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user