summaryrefslogtreecommitdiff
path: root/src/font.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-02-19 17:24:23 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-02-19 17:24:23 -0500
commit9aa1204378c451923b2fb2f0363579e4ce59c23a (patch)
tree61c581ad72823ea5e11f671387f09d5fab343e6c /src/font.cpp
parentf7ff00ed46d93c9ec3e8981c7f9b596b68adce82 (diff)
pke: first-pass unregister string render + cleanup
Diffstat (limited to 'src/font.cpp')
-rw-r--r--src/font.cpp83
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;
+ }
}