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 | |
| parent | f7ff00ed46d93c9ec3e8981c7f9b596b68adce82 (diff) | |
pke: first-pass unregister string render + cleanup
Diffstat (limited to 'src')
| -rw-r--r-- | src/font.cpp | 83 | ||||
| -rw-r--r-- | src/font.hpp | 13 | ||||
| -rw-r--r-- | src/game.cpp | 7 |
3 files changed, 73 insertions, 30 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; + } } diff --git a/src/font.hpp b/src/font.hpp index 73ffd1d..9b43da2 100644 --- a/src/font.hpp +++ b/src/font.hpp @@ -20,6 +20,11 @@ enum FONT_RENDER_SURFACE_AREA_TYPE_FLAGS : uint8_t { FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_FLUID = (1 << 0) | (1 << 1), }; +struct FontRenderHandle { + FontTypeIndex index_ft; + FontRenderIndex index_fr; +}; + struct FontGlyphChar { double advance; glm::vec2 sprite_region_min; @@ -37,11 +42,10 @@ struct FontRenderSettings { FONT_RENDER_SURFACE_AREA_TYPE_FLAGS surface_area_type_flags; // TODO }; struct FontRender { + FontRenderHandle handle; uint32_t *glyph_indices; uint32_t n_glyphs; uint32_t buffer_start_index; - FontTypeIndex index_ft; - FontRenderIndex index_fr; FontRenderSettings settings; }; struct FontTypeMSDFSettings { @@ -88,6 +92,7 @@ struct FontType : public Entity_Base { BufferBindingDetails instanceBD; uint32_t indexCount = 0; uint32_t instanceCounter = 0; + uint32_t instanceLength = 0; } bindings; }; @@ -99,7 +104,7 @@ void FontType_Deserialize(std::ifstream &stream); FontType* FontType_GetFonts(FontTypeIndex &count); FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle, AssetHandle glyphsHandle, FontTypeMSDFSettings *msdf_settings, FontTypeSpacing *spacing); void FontType_Unload(FontTypeIndex idx); -FontRender FontType_AddStringRender(FontTypeIndex idx_ft, pk_str str, FontRenderSettings *settings); -void FontType_RemoveStringRender(FontRender fr); +FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, pk_str str, FontRenderSettings *settings); +void FontType_RemoveStringRender(FontRenderHandle fr); #endif /* PKE_FONT_TYPE_HPP */ diff --git a/src/game.cpp b/src/game.cpp index f3e52ce..f34edca 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -613,9 +613,10 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { pk_cstr test_text = cstring_to_pk_cstr("%+-*0123456789$"); // pk_cstr test_text = cstring_to_pk_cstr("$#"); // pk_cstr test_text = cstring_to_pk_cstr("$"); + pk_cstr test_text2 = cstring_to_pk_cstr("+0123456789 The quick brown fox jumped over the lazy dog."); FontTypeIndex font_type_count; FontRenderSettings fr_set; - fr_set.char_scale = 64.0; + fr_set.char_scale = 9 * 7.0; fr_set.line_height_scale = 1.0; fr_set.char_spacing_scale = 1.0; fr_set.surface_area_size.x = 1; @@ -626,6 +627,10 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { if ((FontType_GetFonts(font_type_count)); font_type_count != FontTypeIndex{0}) { FontType_AddStringRender(FontTypeIndex{0}, pk_cstr_to_pk_str(&test_text), &fr_set); } + if ((FontType_GetFonts(font_type_count)); font_type_count > FontTypeIndex{1}) { + fr_set.surface_area_pos.y *= 2; + FontType_AddStringRender(FontTypeIndex{1}, pk_cstr_to_pk_str(&test_text2), &fr_set); + } GameTimePoint lastTimePoint = pkeSettings.steadyClock.now(); double deltaTillNextRender = pkeSettings.deltaPerFrame; |
