diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-19 17:24:23 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-19 17:24:23 -0500 |
| commit | 9aa1204378c451923b2fb2f0363579e4ce59c23a (patch) | |
| tree | 61c581ad72823ea5e11f671387f09d5fab343e6c /src/font.cpp | |
| parent | f7ff00ed46d93c9ec3e8981c7f9b596b68adce82 (diff) | |
pke: first-pass unregister string render + cleanup
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 83 |
1 files changed, 58 insertions, 25 deletions
diff --git a/src/font.cpp b/src/font.cpp index 5b59dc8..0e69dd6 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -10,6 +10,9 @@ #include <vulkan/vulkan_core.h> // TODO threading +// suggestions: +// easy: give ft a mutex and lock for critical work +// ft->bindings.instance* counter and length make atomic const char *PKE_PROJECT_FONT_TITLE = "title: "; const char *PKE_PROJECT_FONT_TEXTURE_HANDLE = "texture_handle: "; @@ -175,6 +178,7 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta } void FontType_Init() { + ftd.h_ft = FontTypeIndex{0}; ftd.n_ft = FontTypeIndex{5}; ftd.arr_ft = pk_new<FontType>(5); for (FontTypeIndex_T i = 0; i < 5; ++i) { @@ -192,15 +196,20 @@ void FontType_Teardown() { if (ftd.arr_ft != nullptr) pk_delete(ftd.arr_ft, (FontTypeIndex_T)ftd.n_ft); } +// TODO - Memory Pressure +// 2025-02-19 - JCB +// Font buffers only grow and never shrink. +// Consider checking if we can shrink buffers. void FontType_Tick(double delta) { (void)delta; VkResult vkResult; FontInstanceBufferItem *fibis = nullptr; size_t index; + FontType *ft; FontRender *fr; for (FontTypeIndex_T i = 0; i < (FontTypeIndex_T)ftd.h_ft; ++i) { index = 0; - FontType *ft = &ftd.arr_ft[i]; + ft = &ftd.arr_ft[i]; if (ft->last_graphics_resize_index == pkeRuntime.graphics.resize_index) continue; if (ft->bindings.instanceCounter == 0) @@ -209,7 +218,7 @@ void FontType_Tick(double delta) { // TODO specific bucket fibis = pk_new<FontInstanceBufferItem>(ft->bindings.instanceCounter); - for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->n_render; ++k) { + for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->h_render; ++k) { fr = &ft->renders[k]; FontType_Inner_CalcTransforms(ft, fr, &fibis[index]); index += fr->n_glyphs; @@ -319,7 +328,7 @@ void FontType_Deserialize(std::ifstream &stream) { uint64_t prefixLen = strlen(PKE_PROJECT_FONT_TITLE); title.length = strlen(readLine + prefixLen); title.reserved = title.length + 1; - title.val = pk_new<char>(title.reserved, pkeSettings.mem.bkt); + title.val = pk_new<char>(title.reserved); strncpy(const_cast<char*>(title.val), readLine + prefixLen, title.reserved); continue; } @@ -422,10 +431,12 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle const Asset *fontTexture = AM_Get(fontTextureHandle); FontTypeIndex idx = ftd.h_ft; ftd.h_ft += FontTypeIndex{1}; - if (ftd.h_ft > ftd.n_ft && idx > FontTypeIndex{0}) { + if (ftd.h_ft >= ftd.n_ft) { ftd.n_ft += FontTypeIndex{5}; FontType *arr = pk_new<FontType>((FontTypeIndex_T)ftd.n_ft); - memcpy(arr, ftd.arr_ft, sizeof(FontType) * (FontTypeIndex_T)idx); + if (idx > FontTypeIndex{0}) { + memcpy(arr, ftd.arr_ft, sizeof(FontType) * (FontTypeIndex_T)idx); + } if (ftd.arr_ft != nullptr && ftd.arr_ft != CAFE_BABE(FontType)) pk_delete<FontType>(ftd.arr_ft, (FontTypeIndex_T)idx); ftd.arr_ft = arr; } @@ -436,6 +447,7 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle ft->fontTextureAssetHandle = fontTextureHandle; ft->glyphDetailsAssetHandle = glyphsHandle; ft->renders = pk_new<FontRender>(startingGlyphCount); + ft->h_render = FontRenderIndex{0}; ft->n_render = FontRenderIndex{startingGlyphCount}; ft->msdf_settings = *msdf_settings; ft->spacing = *spacing; @@ -961,7 +973,7 @@ void FontType_Unload(FontTypeIndex idx) { // TODO specific bucket if (ft->renders != nullptr) { - for (FontRenderIndex_T i = 0; i < (FontRenderIndex_T)ft->n_render; ++i) { + for (FontRenderIndex_T i = 0; i < (FontRenderIndex_T)ft->h_render; ++i) { if (ft->renders[i].glyph_indices != nullptr) { pk_delete<uint32_t>(ft->renders[i].glyph_indices, ft->renders[i].n_glyphs); } @@ -1015,6 +1027,7 @@ void FontType_Unload(FontTypeIndex idx) { ft->bindings.instanceBD.firstBinding = 0; ft->bindings.instanceBD.bindingCount = 0; ft->bindings.instanceCounter = 0; + ft->bindings.instanceLength = 0; ft->bindings.instanceBD.offsets[0] = 0; if (ft->gr.textureImageView != VK_NULL_HANDLE) @@ -1039,25 +1052,31 @@ void FontType_Unload(FontTypeIndex idx) { if (ft->title.reserved != 0 && ft->title.val != nullptr) { pk_delete<char>(ft->title.val, ft->title.reserved); + ft->title.val = nullptr; + ft->title.length = 0; } } // TODO perf? -// Every time new text is added, we're creating a new buffer and shuffling data -// This could probably be shortened or deferred by creating a larger-than-needed -// buffer. -// TODO threading -FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, FontRenderSettings *settings) { +// 2025-02-19 - JCB +// We only create a new buffer if it is needed. +// However, the new buffer is exactly the length it needs to be and no greater. +// Consider using a heuristic to allocate a buffer larger than needed. +// At the time of writing, the only way to do this is to un-register text. +FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, FontRenderSettings *settings) { assert(settings != nullptr); + PKVK_TmpBufferDetails tmpBufferDetails{}; + VkDeviceSize byteCount; VkResult vkResult; FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx_ft]; FontRender *fr; FontGlyphChar *fgc; - FontRenderIndex idx_fr = ft->n_render; uint32_t i, ii, u, count; int32_t l, m, r; + FontRenderIndex idx_fr = ft->h_render; + ft->h_render += FontRenderIndex{1}; - if (ft->n_render > ft->h_render) { + if (ft->h_render >= ft->n_render) { ft->n_render += FontRenderIndex{5}; FontRender *arr = pk_new<FontRender>((FontRenderIndex_T)ft->n_render); memcpy(arr, ft->renders, sizeof(FontRender) * (FontRenderIndex_T)idx_fr); @@ -1065,8 +1084,8 @@ FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, Font ft->renders = arr; } fr = &ft->renders[(FontRenderIndex_T)idx_fr]; - fr->index_ft = idx_ft; - fr->index_fr = idx_fr; + fr->handle.index_ft = idx_ft; + fr->handle.index_fr = idx_fr; fr->settings = *settings; // insert new characters into tmp buffer @@ -1115,13 +1134,12 @@ FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, Font } VkDeviceSize item_count_orig = ft->bindings.instanceCounter; - VkDeviceSize item_count_new = ft->bindings.instanceCounter + count; + VkDeviceSize item_length_new = PK_MAX(ft->bindings.instanceLength, ft->bindings.instanceCounter + count); // copy existing buffer to new buffer // create new buffer - VkDeviceSize byteCount = sizeof(FontInstanceBufferItem) * item_count_new; - PKVK_TmpBufferDetails tmpBufferDetails{}; - { + if (ft->bindings.instanceLength != item_length_new) { + byteCount = sizeof(FontInstanceBufferItem) * item_length_new; VkBuffer newBuffer; VkBufferCreateInfo bufferCI; bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -1174,7 +1192,7 @@ FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, Font VkBufferCopy vk_buffer_copy{}; vk_buffer_copy.srcOffset = 0; vk_buffer_copy.dstOffset = 0; - vk_buffer_copy.size = sizeof(FontInstanceBufferItem) * item_count_orig; + vk_buffer_copy.size = sizeof(FontInstanceBufferItem) * ft->bindings.instanceCounter; vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, ft->bindings.instanceBD.buffer, newBuffer, 1, &vk_buffer_copy); vkResult = vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); @@ -1204,8 +1222,9 @@ FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, Font ft->gr.deviceMemoryInst = new_memory; ft->bindings.instanceBD.buffer = newBuffer; - ft->bindings.instanceCounter = item_count_new; } + ft->bindings.instanceLength = item_length_new; + ft->bindings.instanceCounter += count; // create tmp local buffer & copy data to graphics card byteCount = sizeof(FontInstanceBufferItem) * count; @@ -1249,11 +1268,25 @@ FontRender FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str, Font } PKVK_EndBuffer(tmpBufferDetails); - return *fr; + return fr->handle; } -void FontType_RemoveStringRender(FontRender fr) { - (void)fr; +void FontType_RemoveStringRender(FontRenderHandle handle) { + FontRender *fr; + uint32_t buffer_start_index; // TODO - // FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)fr.index_ft]; + FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)handle.index_ft]; + // hack, but works + assert(ft->last_graphics_resize_index > 0); + ft->last_graphics_resize_index -= 1; + + fr = &ft->renders[(FontRenderIndex_T)handle.index_fr]; + ft->bindings.instanceCounter -= fr->n_glyphs; + buffer_start_index = fr->buffer_start_index; + fr->n_glyphs = 0; + for (FontRenderIndex_T i = (FontRenderIndex_T)handle.index_fr + 1; FontRenderIndex{i} < ft->h_render; ++i) { + fr = &ft->renders[i]; + fr->buffer_start_index = buffer_start_index; + buffer_start_index += fr->n_glyphs; + } } |
