From cbeafdb8fea8fb9a6e8b8d36b9f98d96c96edba1 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 16 Dec 2025 13:25:33 -0600 Subject: [PATCH] dynamic glyph atlas creation --- src/base/base.cgh | 9 ++- src/base/base_arena.c | 10 +-- src/base/base_async.h | 14 +++-- src/base/base_cmdline.h | 10 ++- src/base/base_gstat.h | 24 ++++++- src/base/base_memory.h | 2 +- src/base/base_resource.h | 10 ++- src/base/base_state.h | 41 ++---------- src/base/base_string.c | 65 ++++++++++++++++--- src/base/base_string.h | 2 + src/base/base_win32/base_win32.c | 2 +- src/glyph_cache/glyph_cache.c | 87 +++++++++++++++----------- src/glyph_cache/glyph_cache.h | 30 +++++---- src/gpu/gpu_dx12/gpu_dx12_core.c | 72 +++++++++++---------- src/gpu/gpu_dx12/gpu_dx12_core.h | 2 + src/net/net.c | 10 +-- src/pp/pp_sim/pp_sim_core.c | 1 + src/pp/pp_vis/pp_vis_core.c | 31 +++++++++ src/pp/pp_vis/pp_vis_widgets.c | 8 +-- src/tar/tar.c | 2 +- src/ui/ui_core.c | 2 +- src/window/window_win32/window_win32.c | 2 +- 22 files changed, 277 insertions(+), 159 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index d243024b..b64a74ce 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -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) }) \ ) diff --git a/src/base/base_arena.c b/src/base/base_arena.c index 1a94ee4a..70b35c67 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -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); } diff --git a/src/base/base_async.h b/src/base/base_async.h index 0214f645..0cba8c13 100644 --- a/src/base/base_async.h +++ b/src/base/base_async.h @@ -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 diff --git a/src/base/base_cmdline.h b/src/base/base_cmdline.h index 189a3f50..b8ac6c88 100644 --- a/src/base/base_cmdline.h +++ b/src/base/base_cmdline.h @@ -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 diff --git a/src/base/base_gstat.h b/src/base/base_gstat.h index 93d491f8..2cbaf12d 100644 --- a/src/base/base_gstat.h +++ b/src/base/base_gstat.h @@ -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 diff --git a/src/base/base_memory.h b/src/base/base_memory.h index 5dd1333a..5cfabc80 100644 --- a/src/base/base_memory.h +++ b/src/base/base_memory.h @@ -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)) diff --git a/src/base/base_resource.h b/src/base/base_resource.h index ef92eead..d44faeda 100644 --- a/src/base/base_resource.h +++ b/src/base/base_resource.h @@ -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 diff --git a/src/base/base_state.h b/src/base/base_state.h index 09b489d2..5d2c267f 100644 --- a/src/base/base_state.h +++ b/src/base/base_state.h @@ -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; diff --git a/src/base/base_string.c b/src/base/base_string.c index 439ef29f..046cb742 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -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; + *PushStructNoZero(arena, String) = piece; + ++pieces.count; i += delim.len; piece_start = i; - if (piece.len > 0) - { - *PushStructNoZero(arena, String) = piece; - ++pieces.count; - } + } + 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 diff --git a/src/base/base_string.h b/src/base/base_string.h index cf8da08e..a0853bdd 100644 --- a/src/base/base_string.h +++ b/src/base/base_string.h @@ -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 diff --git a/src/base/base_win32/base_win32.c b/src/base/base_win32/base_win32.c index 576769d3..6658ef27 100644 --- a/src/base/base_win32/base_win32.c +++ b/src/base/base_win32/base_win32.c @@ -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); diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index 7f29b345..42a97957 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -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), diff --git a/src/glyph_cache/glyph_cache.h b/src/glyph_cache/glyph_cache.h index 0aaf4a45..38384185 100644 --- a/src/glyph_cache/glyph_cache.h +++ b/src/glyph_cache/glyph_cache.h @@ -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 { diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index f1df6b3b..44bac27e 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -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 */ - for (G_D12_Resource *resource = heap->resources.first; resource; resource = resource->next) + if (heap->resources.first) { - ID3D12Resource_Release(resource->d3d_resource); + 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; } - 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); } diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.h b/src/gpu/gpu_dx12/gpu_dx12_core.h index a25f1bbd..7f3bf0c4 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.h +++ b/src/gpu/gpu_dx12/gpu_dx12_core.h @@ -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]; }; diff --git a/src/net/net.c b/src/net/net.c index 2a9c4978..bd2a63c6 100644 --- a/src/net/net.c +++ b/src/net/net.c @@ -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); diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index cbcd1eb3..2c1b55ca 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -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); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index e0deb429..9d8587c3 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -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 diff --git a/src/pp/pp_vis/pp_vis_widgets.c b/src/pp/pp_vis/pp_vis_widgets.c index ea8b603d..567cf8fe 100644 --- a/src/pp/pp_vis/pp_vis_widgets.c +++ b/src/pp/pp_vis/pp_vis_widgets.c @@ -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; diff --git a/src/tar/tar.c b/src/tar/tar.c index eb6ffb2f..a778f8b4 100644 --- a/src/tar/tar.c +++ b/src/tar/tar.c @@ -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); diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 01e9ddbe..34e7bb09 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -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; diff --git a/src/window/window_win32/window_win32.c b/src/window/window_win32/window_win32.c index cd1b2696..7eec90e2 100644 --- a/src/window/window_win32/window_win32.c +++ b/src/window/window_win32/window_win32.c @@ -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;