dynamic glyph atlas creation

This commit is contained in:
jacob 2025-12-16 13:25:33 -06:00
parent 9fc666d49d
commit cbeafdb8fe
22 changed files with 277 additions and 159 deletions

View File

@ -428,9 +428,9 @@
#define countof(a) (sizeof(a) / sizeof((a)[0]))
#endif
//- IsArray
//- IsFixedArray
#define IsIndexable(a) (sizeof(a[0]) != 0)
#define IsArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a)))
#define IsFixedArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a)))
//- offsetof
#if !IsCompilerMsvc
@ -619,10 +619,9 @@
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
/* String from static array */
#define StringFromArray(a) \
#define StringFromFixedArray(a) \
( \
Assert(IsArray(a)), \
Assert(IsFixedArray(a)), \
((String) { .len = sizeof(a), .text = (u8 *)(a) }) \
)

View File

@ -18,7 +18,7 @@ Arena *AcquireArena(u64 reserve)
Panic(Lit("Failed to reserve memory"));
}
u64 reserved = reserve;
AddGstat(MemoryReserved, reserve);
AddGstat(ArenaMemoryReserved, reserve);
/* Commit initial block */
base = CommitMemory(base, ArenaBlockSize);
@ -32,7 +32,7 @@ Arena *AcquireArena(u64 reserve)
StaticAssert(sizeof(Arena) <= ArenaHeaderSize); /* Arena struct must fit in header */
AsanPoison(base + sizeof(Arena), ArenaBlockSize - sizeof(Arena));
AddGstat(MemoryCommitted, ArenaBlockSize);
AddGstat(ArenaMemoryCommitted, ArenaBlockSize);
AddGstat(NumArenas, 1);
/* Create & return arena header at beginning of block */
@ -46,8 +46,8 @@ Arena *AcquireArena(u64 reserve)
void ReleaseArena(Arena *arena)
{
AsanUnpoison(arena, arena->committed + ArenaHeaderSize);
AddGstat(MemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
AddGstat(MemoryReserved, -(i64)(arena->reserved));
AddGstat(ArenaMemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
AddGstat(ArenaMemoryReserved, -(i64)(arena->reserved));
AddGstat(NumArenas, -1);
ReleaseMemory(arena);
}
@ -115,7 +115,7 @@ void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
Panic(Lit("Failed to commit new memory block: System may be out of memory"));
}
arena->committed += commit_bytes;
AddGstat(MemoryCommitted, commit_bytes);
AddGstat(ArenaMemoryCommitted, commit_bytes);
AsanPoison(commit_address, commit_bytes);
}

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////
//~ Async callback
//~ Async types
Struct(AsyncTickCtx);
typedef void AsyncTickCallbackFunc(WaveLaneCtx *lane, AsyncTickCtx *tick);
@ -15,9 +15,6 @@ Struct(AsyncTickCallbackNode)
AsyncTickCallback callback;
};
////////////////////////////////////////////////////////////
//~ Async worker types
Struct(AsyncTickCtx)
{
Arena *arena;
@ -30,6 +27,15 @@ Struct(AsyncWorkerCtx)
AsyncTickCallback *callbacks;
};
Struct(AsyncCtx)
{
Mutex mutex;
u64 callback_nodes_count;
AsyncTickCallbackNode *first_callback_node;
AsyncTickCallbackNode *last_callback_node;
AsyncWorkerCtx worker_ctx;
};
////////////////////////////////////////////////////////////
//~ Bootstrap

View File

@ -8,9 +8,6 @@ Struct(CommandlineArg)
String value;
};
////////////////////////////////////////////////////////////
//~ Lookup types
Struct(CommandlineArgNode)
{
CommandlineArgNode *next;
@ -18,6 +15,13 @@ Struct(CommandlineArgNode)
CommandlineArg arg;
};
Struct(CmdLineCtx)
{
String *positional_args;
u64 positional_args_count;
CommandlineArgNode *arg_bins[1024];
};
////////////////////////////////////////////////////////////
//~ Bootstrap

View File

@ -1,4 +1,26 @@
/* Application-wide statistics */
/* Application wide statistics */
////////////////////////////////////////////////////////////
//~ Gstat types
Struct(GstatCtx)
{
Atomic64Padded SockBytesSent;
Atomic64Padded SockBytesReceived;
Atomic64Padded DebugSteps;
Atomic64Padded NumArenas;
Atomic64Padded ArenaMemoryCommitted;
Atomic64Padded ArenaMemoryReserved;
Atomic64Padded NumGpuArenas;
Atomic64Padded DedicatedGpuArenaMemoryCommitted;
Atomic64Padded SharedGpuArenaMemoryCommitted;
};
////////////////////////////////////////////////////////////
//~ Gstat ops
#if GstatIsEnabled

View File

@ -20,7 +20,7 @@ void SetMemoryReadWrite(void *address, u64 size);
#define MatchBytes(p1, p2, n) (CmpBytes((p1), (p2), (n)) == 0)
#define MatchStruct(p1, p2) MatchBytes((p1), (p2), sizeof(*p1))
#define ZeroBytes(ptr, count) SetBytes((ptr), 0, (count))
#define ZeroArray(a) Assert(IsArray(a)); ZeroBytes((a), sizeof((a)))
#define ZeroFixedArray(a) Assert(IsFixedArray(a)); ZeroBytes((a), sizeof((a)))
#define ZeroStructs(ptr, n) ZeroBytes((ptr), sizeof(*(ptr)) * (n))
#define ZeroStruct(ptr) ZeroStructs((ptr), 1)
#define CopyStructs(ptr_dst, ptr_src, n) CopyBytes((ptr_dst), (ptr_src), sizeof(*(ptr_dst)) * (n))

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////
//~ Resource cache types
//~ Resource types
Struct(ResourceEntry)
{
@ -17,6 +17,14 @@ Struct(ResourceEntryBin)
ResourceEntry *last;
};
Struct(ResourceCtx)
{
u64 entries_count;
ResourceEntry *first_entry;
ResourceEntry *last_entry;
ResourceEntryBin bins[4096];
};
////////////////////////////////////////////////////////////
//~ Bootstrap

View File

@ -3,43 +3,10 @@
Struct(BaseCtx)
{
/* Command line */
struct
{
String *positional_args;
u64 positional_args_count;
CommandlineArgNode *arg_bins[1024];
} cmdline;
/* Resources */
struct
{
u64 entries_count;
ResourceEntry *first_entry;
ResourceEntry *last_entry;
ResourceEntryBin bins[4096];
} resource;
/* Stats */
struct
{
Atomic64Padded SockBytesSent;
Atomic64Padded SockBytesReceived;
Atomic64Padded MemoryCommitted;
Atomic64Padded MemoryReserved;
Atomic64Padded NumArenas;
Atomic64Padded DebugSteps;
} gstat;
/* Async */
struct
{
Mutex mutex;
u64 callback_nodes_count;
AsyncTickCallbackNode *first_callback_node;
AsyncTickCallbackNode *last_callback_node;
AsyncWorkerCtx worker_ctx;
} async;
CmdLineCtx cmdline;
ResourceCtx resource;
GstatCtx gstat;
AsyncCtx async;
};
extern BaseCtx Base;

View File

@ -289,25 +289,25 @@ StringArray SplitString(Arena *arena, String str, String delim)
StringArray pieces = ZI;
pieces.strings = ArenaNext(arena, String);
i64 piece_start = 0;
for (i64 i = 0; i < (i64)str.len - (i64)delim.len; ++i)
for (i64 i = 0; i < (i64)str.len - (i64)delim.len;)
{
String cmp = ZI;
cmp.text = &str.text[i];
cmp.len = MinI64(str.len - i, delim.len);
b32 is_delimiter = MatchString(cmp, delim);
if (is_delimiter)
if (MatchString(cmp, delim))
{
String piece = ZI;
piece.text = &str.text[piece_start];
piece.len = i - piece_start;
i += delim.len;
piece_start = i;
if (piece.len > 0)
{
*PushStructNoZero(arena, String) = piece;
++pieces.count;
i += delim.len;
piece_start = i;
}
else
{
i += 1;
}
}
if (piece_start < (i64)str.len)
@ -321,6 +321,44 @@ StringArray SplitString(Arena *arena, String str, String delim)
return pieces;
}
String ReplaceString(Arena *arena, String str, String old_pattern, String new_pattern)
{
String result = ZI;
result.text = ArenaNext(arena, u8);
i64 piece_start = 0;
for (i64 i = 0; i < (i64)str.len - (i64)old_pattern.len;)
{
String cmp = ZI;
cmp.text = &str.text[i];
cmp.len = MinI64(str.len - i, old_pattern.len);
if (MatchString(cmp, old_pattern))
{
String piece = ZI;
piece.text = &str.text[piece_start];
piece.len = i - piece_start;
if (piece.len > 0)
{
result.len += PushString(arena, piece).len;
}
result.len += PushString(arena, new_pattern).len;
i += old_pattern.len;
piece_start = i;
}
else
{
i += 1;
}
}
if (piece_start < (i64)str.len)
{
String piece = ZI;
piece.text = &str.text[piece_start];
piece.len = str.len - piece_start;
result.len += PushString(arena, piece).len;
}
return result;
}
//- Indent
/* NOTE: Really slow */
@ -464,6 +502,17 @@ b32 StringEndsWith(String str, String substring)
return 0;
}
String StringFromArray(Arena *arena, StringArray a)
{
String result = ZI;
result.text = ArenaNext(arena, u8);
for (u64 string_idx = 0; string_idx < a.count; ++string_idx)
{
result.len += PushString(arena, a.strings[string_idx]).len;
}
return result;
}
////////////////////////////////////////////////////////////
//~ String list helpers

View File

@ -94,12 +94,14 @@ String CopyString(String dst, String src);
String RepeatString(Arena *arena, String src, u64 count);
String CatString(Arena *arena, String str1, String str2);
StringArray SplitString(Arena *arena, String str, String delim);
String ReplaceString(Arena *arena, String str, String old_pattern, String new_pattern);
String IndentString(Arena *arena, String str, u32 indent);
String LowerString(Arena *arena, String str);
b32 MatchString(String str1, String str2);
b32 StringContains(String str, String substring);
b32 StringBeginsWith(String str, String substring);
b32 StringEndsWith(String str, String substring);
String StringFromArray(Arena *arena, StringArray a);
////////////////////////////////////////////////////////////
//~ Trimming helpers

View File

@ -64,7 +64,7 @@ b32 Panic(String msg)
{
LogPanic(msg);
char msg_cstr[4096];
CstrFromStringToBuff(StringFromArray(msg_cstr), msg);
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
{
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);

View File

@ -176,7 +176,7 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
GC_Glyph *glyph = ready_glyphs[glyph_idx];
GC_RunRect *rect = &result.rects[glyph_idx];
rect->tex = glyph->tex_ref;
rect->tex = glyph->atlas->tex_ref;
rect->tex_slice = glyph->tex_slice;
rect->tex_slice_uv = glyph->tex_slice_uv;
@ -252,9 +252,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
WaveSync(lane);
//////////////////////////////
//- Rasterize glyphs
@ -288,22 +285,6 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
if (lane->idx == 0)
{
/* FIXME: Dynamic atlases */
/* Create atlas */
Vec2I32 atlas_dims = VEC2I32(8192, 8192);
if (G_IsResourceNil(GC.atlas))
{
G_ArenaHandle gpu_perm = G_PermArena();
GC.atlas = G_PushTexture2D(
gpu_perm,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas_dims,
/* FIXME: Do we need simultaneous access? */
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
);
GC.atlas_ref = G_PushTexture2DRef(gpu_perm, GC.atlas);
}
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
{
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
@ -313,23 +294,59 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
Vec2I32 image_dims = ttf_result.image_dims;
Vec2I32 atlas_offset = GC.atlas_pos;
GC.atlas_row_height = MaxI32(GC.atlas_row_height, image_dims.y);
if (atlas_offset.x + image_dims.x > atlas_dims.x);
/* TODO: Use a more efficient atlas packing algorithm for less wasted space `*/
GC_Atlas *atlas = GC.first_atlas;
b32 can_use_atlas = 0;
Vec2I32 pos_in_atlas = ZI;
while (can_use_atlas == 0)
{
GC.atlas_pos.x = 0;
GC.atlas_pos.y += GC.atlas_row_height;
GC.atlas_row_height = image_dims.y;
/* Create atlas */
if (!atlas)
{
Arena *perm = PermArena();
atlas = PushStruct(perm, GC_Atlas);
atlas->dims = VEC2I32(1024, 1024);
{
G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D(
gpu_perm,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
);
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex);
}
SllStackPush(GC.first_atlas, atlas);
++GC.atlases_count;
}
/* Determine pos in atlas */
pos_in_atlas = atlas->cur_pos;
atlas->cur_row_height = MaxI32(atlas->cur_row_height, image_dims.y);
if (pos_in_atlas.x + image_dims.x > atlas->dims.x);
{
atlas->cur_pos.x = 0;
atlas->cur_pos.y += atlas->cur_row_height;
atlas->cur_row_height = image_dims.y;
}
atlas->cur_pos.x += image_dims.x;
if (atlas->cur_pos.x < atlas->dims.x && atlas->cur_pos.y < atlas->dims.y)
{
can_use_atlas = 1;
}
else
{
atlas = 0;
}
}
GC.atlas_pos.x += image_dims.x;
/* Atlas info */
glyph->tex_ref = GC.atlas_ref;
glyph->tex_slice = RNG2I32(atlas_offset, AddVec2I32(atlas_offset, image_dims));
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas_dims.x;
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas_dims.x;
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas_dims.x;
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas_dims.x;
glyph->atlas = atlas;
glyph->tex_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas->dims.x;
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas->dims.x;
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas->dims.x;
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas->dims.x;
}
}
@ -346,7 +363,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
GC_Glyph *glyph = cmd->glyph;
ResourceKey resource = glyph->desc.font.r;
GC_GlyphDesc desc = glyph->desc;
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);
u32 *image_pixels = ttf_result.image_pixels;
Vec2I32 image_dims = ttf_result.image_dims;
@ -359,7 +376,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
G_CopyCpuToTexture(
cl,
GC.atlas, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
glyph->atlas->tex, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
RNG3I32(
VEC3I32(0, 0, 0),

View File

@ -6,6 +6,20 @@ Struct(GC_FontKey)
ResourceKey r;
};
////////////////////////////////////////////////////////////
//~ Atlas types
Struct(GC_Atlas)
{
GC_Atlas *next;
Vec2I32 dims;
G_ResourceHandle tex;
G_Texture2DRef tex_ref;
Vec2I32 cur_pos;
i32 cur_row_height;
};
////////////////////////////////////////////////////////////
//~ Glyph types
@ -35,7 +49,7 @@ Struct(GC_Glyph)
Rng2 bounds;
/* Atlas info */
G_Texture2DRef tex_ref;
GC_Atlas *atlas;
Rng2I32 tex_slice;
Rng2 tex_slice_uv;
};
@ -45,13 +59,6 @@ Struct(GC_GlyphBin)
GC_Glyph *first;
};
// Struct(GC_GlyphDescChunk)
// {
// GC_GlyphDescChunk *next;
// u64 descs_count;
// GC_GlyphDesc *descs;
// };
////////////////////////////////////////////////////////////
//~ Run types
@ -123,11 +130,8 @@ Struct(GC_Ctx)
Mutex glyphs_mutex;
GC_GlyphBin glyph_bins[16384];
/* TODO: Dynamic atlases */
G_ResourceHandle atlas;
G_Texture2DRef atlas_ref;
Vec2I32 atlas_pos;
i32 atlas_row_height;
u64 atlases_count;
GC_Atlas *first_atlas;
struct
{

View File

@ -764,6 +764,8 @@ G_ArenaHandle G_AcquireArena(void)
gpu_arena->resource_heaps[heap_idx].kind = (G_D12_ResourceHeapKind)heap_idx;
}
AddGstat(NumGpuArenas, 1);
return G_D12_MakeHandle(G_ArenaHandle, gpu_arena);
}
@ -772,6 +774,8 @@ void G_ReleaseArena(G_ArenaHandle arena)
/* TODO */
/* TODO: Unmap heaps */
/* TODO: Update gstats */
}
void G_ResetArena(G_CommandListHandle cl_handle, G_ArenaHandle arena_handle)
@ -788,51 +792,37 @@ void G_D12_ResetArena(G_D12_CmdList *cl, G_D12_Arena *gpu_arena)
{
/* TODO */
/* FIXME: Move descriptors into committed lists */
/* FIXME: Release id3d12 resource com object references */
// for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
// {
// G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
// heap->pos = 0;
// if (heap->first_reset_resource)
// {
// heap->last_reset_resource->next = heap->first_resource;
// }
// else
// {
// heap->first_reset_resource = heap->first_resource;
// }
// heap->last_reset_resource = heap->last_resource;
// heap->reset_resources_count += heap->resources_count;
// heap->resources_count = 0;
// heap->first_resource = 0;
// heap->last_resource = 0;
// }
for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
{
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
heap->pos = 0;
/* FIXME: Free list if this actually works */
if (heap->resources.first)
{
for (G_D12_Resource *resource = heap->resources.first; resource; resource = resource->next)
{
ID3D12Resource_Release(resource->d3d_resource);
}
if (gpu_arena->free_resources.last)
{
gpu_arena->free_resources.last->next = heap->resources.first;
}
else
{
gpu_arena->free_resources.first = heap->resources.first;
}
gpu_arena->free_resources.last = heap->resources.last;
gpu_arena->free_resources.count += heap->resources.count;
heap->resources.count = 0;
heap->resources.first = 0;
heap->resources.last = 0;
}
}
/* Push descriptors to cl reset list */
if (gpu_arena->descriptors.first)
{
if (cl->reset_descriptors.last)
{
@ -922,6 +912,14 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
d3d_desc.Flags |= D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; /* TODO: Remove this and support tier 1 resource heaps */
hr = ID3D12Device_CreateHeap(g->device, &d3d_desc, &IID_ID3D12Heap, (void **)&heap->d3d_heap);
heap->size = d3d_desc.SizeInBytes;
if (d3d_desc.Properties.Type == D3D12_HEAP_TYPE_DEFAULT)
{
AddGstat(DedicatedGpuArenaMemoryCommitted, heap->size);
}
else
{
AddGstat(SharedGpuArenaMemoryCommitted, heap->size);
}
}
/* Map heap resource */
@ -1074,6 +1072,14 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
// }
u64 pos_in_heap = 0;
ID3D12Resource *d3d_resource = 0;
resource = gpu_arena->free_resources.first;
if (resource)
{
SllQueuePop(gpu_arena->free_resources.first, gpu_arena->free_resources.last);
--gpu_arena->free_resources.count;
ZeroStruct(resource);
}
else
{
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
}

View File

@ -185,6 +185,8 @@ Struct(G_D12_Arena)
G_D12_DescriptorList descriptors;
G_D12_DescriptorList reset_descriptors_by_heap[G_D12_DescriptorHeapKind_Count];
G_D12_ResourceList free_resources;
G_D12_ResourceHeap resource_heaps[G_D12_ResourceHeapKind_Count];
};

View File

@ -867,7 +867,7 @@ void N_EndUpdate(N_Host *host)
{
u8 packet_flags = 0;
N_SndPacket *packet = N_PushSndPacket(channel, 0);
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
BB_Writer bw = BB_WriterFromBuff(&bb);
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
BB_WriteIBits(&bw, N_PacketKind_TryConnect, 8);
@ -880,7 +880,7 @@ void N_EndUpdate(N_Host *host)
{
u8 packet_flags = 0;
N_SndPacket *packet = N_PushSndPacket(channel, 0);
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
BB_Writer bw = BB_WriterFromBuff(&bb);
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
BB_WriteIBits(&bw, N_PacketKind_ConnectSuccess, 8);
@ -893,7 +893,7 @@ void N_EndUpdate(N_Host *host)
{
u8 packet_flags = 0;
N_SndPacket *packet = N_PushSndPacket(channel, 0);
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
BB_Writer bw = BB_WriterFromBuff(&bb);
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
BB_WriteIBits(&bw, N_PacketKind_Disconnect, 8);
@ -906,7 +906,7 @@ void N_EndUpdate(N_Host *host)
{
u8 packet_flags = 0;
N_SndPacket *packet = N_PushSndPacket(channel, 0);
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
BB_Writer bw = BB_WriterFromBuff(&bb);
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
BB_WriteIBits(&bw, N_PacketKind_Heartbeat, 8);
@ -944,7 +944,7 @@ void N_EndUpdate(N_Host *host)
}
}
N_SndPacket *packet = N_PushSndPacket(channel, is_reliable);
BB_Buff bb = BB_BuffFromString(StringFromArray(packet->data));
BB_Buff bb = BB_BuffFromString(StringFromFixedArray(packet->data));
BB_Writer bw = BB_WriterFromBuff(&bb);
BB_WriteUBits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
BB_WriteIBits(&bw, N_PacketKind_MsgChunk, 8);

View File

@ -552,6 +552,7 @@ void S_TickForever(WaveLaneCtx *lane)
LockTicketMutex(&shared->output_back_tm);
{
S_OutputState *output = &shared->output_states[shared->output_back_idx];
ResetArena(output->arena);
S_SnapshotNode *snapshot_node = PushStruct(output->arena, S_SnapshotNode);
S_Snapshot *snapshot = &snapshot_node->snapshot;
SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node);

View File

@ -409,6 +409,37 @@ void V_TickForever(WaveLaneCtx *lane)
V_BuildConsoleWidget(minimized);
}
//////////////////////////////
//- Build debug info
if (persist.show_console)
{
UI_PushCP(UI_BuildColumn());
{
{
{
UI_Push(FontSize, 32);
UI_BuildLabelF("CPU:");
UI_Pop(FontSize);
}
UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumArenas)));
UI_BuildLabelF(" Arena memory committed: %F MiB", FmtFloat((f64)GetGstat(ArenaMemoryCommitted) / 1024 / 1024));
UI_BuildLabelF(" Arena memory reserved: %F TiB", FmtFloat((f64)GetGstat(ArenaMemoryReserved) / 1024 / 1024 / 1024 / 1024));
}
{
{
UI_Push(FontSize, 32);
UI_BuildLabelF("GPU:");
UI_Pop(FontSize);
}
UI_BuildLabelF(" Arenas: %F", FmtSint(GetGstat(NumGpuArenas)));
UI_BuildLabelF(" Dedicated arena memory committed: %F MiB", FmtFloat((f64)GetGstat(DedicatedGpuArenaMemoryCommitted) / 1024 / 1024));
UI_BuildLabelF(" Shared arena memory committed: %F MiB", FmtFloat((f64)GetGstat(SharedGpuArenaMemoryCommitted) / 1024 / 1024));
}
}
UI_PopCP(UI_TopCP());
}
//////////////////////////////
//- Process vis commands

View File

@ -5,11 +5,11 @@ V_WidgetTheme V_GetWidgetTheme(void)
{
V_WidgetTheme theme = ZI;
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
// theme.font_size = 16;
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
theme.font_size = 64;
theme.font_size = 16;
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
// theme.font_size = 64;
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/roboto-med.ttf")));
// theme.font_size = 100;

View File

@ -29,7 +29,7 @@ TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
TAR_Header header = ZI;
BB_ReadBytes(&br, StringFromStruct(&header));
if (!MatchString(StringFromArray(header.ustar_indicator), Lit("ustar\0")))
if (!MatchString(StringFromFixedArray(header.ustar_indicator), Lit("ustar\0")))
{
/* Invalid header */
Assert(0);

View File

@ -367,7 +367,7 @@ UI_Style UI_PopStyle(UI_StyleDesc desc)
{
UI_StyleNode *n = stack->style_tops[kind];
result = n->style;
if (desc.use && n->pop_when_used)
if (desc.force_pop || (desc.use && n->pop_when_used))
{
stack->style_tops[kind] = n->next;
n->next = frame->first_free_style_node;

View File

@ -9,7 +9,7 @@ void WND_Bootstrap(void)
//- Initialize btn table
{
ZeroArray(g->vk_to_button);
ZeroFixedArray(g->vk_to_button);
for (u32 i = 'A', j = Button_A; i <= 'Z'; ++i, ++j)
{
g->vk_to_button[i] = (Button)j;