summaryrefslogtreecommitdiff
path: root/src/font.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-06-16 09:51:00 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-06-16 09:51:00 -0400
commit66ebed74456f76277597b3b07f3e67cc45388ece (patch)
tree5e7d0c429867a294bca78269124954ce0a4823fc /src/font.cpp
parentc1ad6ceeb301bc1f2a4f850e08587748a6d9107b (diff)
pke: update FontRender text (editor: for ui-box)
Diffstat (limited to 'src/font.cpp')
-rw-r--r--src/font.cpp315
1 files changed, 124 insertions, 191 deletions
diff --git a/src/font.cpp b/src/font.cpp
index 1c06a06..9a0692c 100644
--- a/src/font.cpp
+++ b/src/font.cpp
@@ -295,20 +295,53 @@ void FontType_Tick(double delta) {
if (pkeSettings.rt.was_framebuffer_resized == false && ft->gr.should_update_instance_buffer == false) {
continue;
}
- if (ft->bindings.instance_counter == 0)
+
+ // TODO specific bucket
+ for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->h_render; ++k) {
+ index += ft->renders[k].n_glyphs;
+ }
+
+ if (index == 0) {
continue;
+ }
ft->gr.should_update_instance_buffer = false;
- // TODO specific bucket
- fibis = pk_new<FontInstanceBufferItem>(ft->bindings.instance_counter);
+ fibis = pk_new<FontInstanceBufferItem>(index);
+ ft->bindings.instance_counter = index;
+ index = 0;
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;
}
+ // check recreate buffer
+ if (ft->bindings.instance_buffer_max_count < index) {
+ if (ft->bindings.bd_instance.buffer != VK_NULL_HANDLE) {
+ vkDestroyBuffer(vkDevice, ft->bindings.bd_instance.buffer, vkAllocator);
+ ft->bindings.bd_instance.buffer = VK_NULL_HANDLE;
+ ft->bindings.bd_instance.offsets[0] = 0;
+ vkFreeMemory(vkDevice, ft->gr.deviceMemoryInst, vkAllocator);
+ ft->gr.deviceMemoryInst = VK_NULL_HANDLE;
+ }
+
+ pkvk_buffer_create_data create_data{};
+ create_data.buffer_byte_length[0] = sizeof(FontInstanceBufferItem) * ft->bindings.instance_counter;
+ create_data.n_buffers = 1;
+ create_data.index_instance = 0;
+ create_data.index_index = -1;
+
+ pkvk_buffer_create_data_out out{};
+ pkvk_buffer_create(&create_data, &out);
+
+ ft->bindings.bd_instance.buffer = out.buffers[0];
+ ft->gr.deviceMemoryInst = out.device_memory_instance;
+ ft->bindings.instance_buffer_max_count = out.memory_requirements_instance.size / sizeof(FontInstanceBufferItem);
+ }
+
PKVK_TmpBufferDetails tmpBufferDetails{};
PKVK_BeginBuffer(graphicsFamilyIndex, sizeof(FontInstanceBufferItem) * ft->bindings.instance_counter, tmpBufferDetails);
+ assert(tmpBufferDetails.buffer != VK_NULL_HANDLE);
{
VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -769,6 +802,42 @@ void FontType_Unload(FontTypeIndex idx) {
ECS_MarkForRemoval(ft);
}
+void FontType_cstr_to_unicode(const FontType &ft, pk_arr_t<uint32_t> &arr, const pk_cstr &str) {
+ uint32_t i, ii, u;
+ int32_t l, m, r;
+ FontGlyphChar *fgc;
+ for (i = 0; i < str.length;) {
+ fgc = nullptr;
+ u = 0;
+ // determine unicode char
+ ii = utf8_to_unicode(&str.val[i], u);
+ if (ii == 0) {
+ fprintf(stderr, "failed to determine unicode for character: at byte index: '%i'\n", i);
+ i += 1;
+ continue;
+ }
+ i += ii;
+
+ // binary search for glyph details
+ l = 0;
+ r = ft.n_glyphs - 1;
+ do {
+ m = l + (r-l)/2;
+ fgc = &ft.glyphs[m];
+ if (fgc->unicode < u)
+ l = m + 1;
+ else
+ r = m - 1;
+ } while (fgc->unicode != u && l <= r);
+
+ if (fgc->unicode != u) {
+ fprintf(stderr, "font: '%s' does not contain unicode character '%u'\n", ft.title.val, u);
+ continue;
+ }
+ pk_arr_append_t(&arr, uint32_t(m));
+ }
+}
+
// TODO perf?
// 2025-02-19 - JCB
// We only create a new buffer if it is needed.
@@ -777,22 +846,18 @@ void FontType_Unload(FontTypeIndex idx) {
// At the time of writing, the only way to do this is to un-register text.
FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_cstr &&str, FontRenderSettings *settings, Entity_Base *parent, pk_uuid uuid) {
assert(settings != nullptr);
- PKVK_TmpBufferDetails tmpBufferDetails{};
- VkDeviceSize byteCount;
- VkResult vkResult;
FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx_ft];
FontRender *fr;
- FontGlyphChar *fgc;
- uint32_t i, ii, u, count;
- int32_t l, m, r;
+ uint32_t i, count;
FontRenderIndex idx_fr = ft->h_render;
ft->h_render += FontRenderIndex{1};
if (ft->h_render >= ft->n_render) {
+ FontRenderIndex_T old_count{static_cast<FontRenderIndex_T>(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);
- pk_delete<FontRender>(ft->renders, (FontRenderIndex_T)idx_fr);
+ memcpy(arr, ft->renders, sizeof(FontRender) * old_count);
+ pk_delete<FontRender>(ft->renders, old_count);
ft->renders = arr;
}
fr = &ft->renders[(FontRenderIndex_T)idx_fr];
@@ -804,190 +869,28 @@ FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_cstr &&
fr->settings = *settings;
fr->text = str;
- if (window != NULL) {
- // insert new characters into tmp buffer
- {
- pk_arr_t<uint32_t> glyph_indices{};
- glyph_indices.bkt = pkeSettings.mem_bkt.game_transient;
- pk_arr_reserve(&glyph_indices, str.length);
- count = 0;
- for (i = 0; i < str.length;) {
- fgc = nullptr;
- u = 0;
- // determine unicode char
- ii = utf8_to_unicode(&str.val[i], u);
- if (ii == 0) {
- fprintf(stderr, "failed to determine unicode for character: at byte index: '%i'\n", i);
- i += 1;
- continue;
- }
- i += ii;
-
- // binary search for glyph details
- l = 0;
- r = ft->n_glyphs - 1;
- do {
- m = l + (r-l)/2;
- fgc = &ft->glyphs[m];
- if (fgc->unicode < u)
- l = m + 1;
- else
- r = m - 1;
- } while (fgc->unicode != u && l <= r);
-
- if (fgc->unicode != u) {
- fprintf(stderr, "font: '%s' does not contain unicode character '%u'\n", ft->title.val, u);
- continue;
- }
- count += 1;
- pk_arr_append_t(&glyph_indices, uint32_t(m));
- }
-
- // TODO specific bucket
- fr->n_glyphs = count;
- fr->glyph_indices = pk_new<uint32_t>(count);
- for (i = 0; i < count; ++i) {
- fr->glyph_indices[i] = glyph_indices[i];
- }
- glyph_indices.data = nullptr;
- }
-
- VkDeviceSize item_count_orig = ft->bindings.instance_counter;
- VkDeviceSize item_length_new = PK_MAX(ft->bindings.instance_buffer_max_count, ft->bindings.instance_counter + count);
-
- // copy existing buffer to new buffer
- // create new buffer
- if (ft->bindings.instance_buffer_max_count < item_length_new) {
- byteCount = sizeof(FontInstanceBufferItem) * item_length_new;
- VkBuffer newBuffer;
- VkBufferCreateInfo bufferCI;
- bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- bufferCI.pNext = nullptr;
- bufferCI.flags = {};
- bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- bufferCI.queueFamilyIndexCount = 1;
- bufferCI.pQueueFamilyIndices = &graphicsFamilyIndex;
- bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- bufferCI.size = byteCount;
- vkResult = vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &newBuffer);
- assert(vkResult == VK_SUCCESS);
-
- VkMemoryRequirements vkMemReqs;
- vkGetBufferMemoryRequirements(vkDevice, newBuffer, &vkMemReqs);
- assert(sizeof(FontInstanceBufferItem) % vkMemReqs.alignment == 0);
-
- vkDestroyBuffer(vkDevice, newBuffer, vkAllocator);
- newBuffer = VK_NULL_HANDLE;
-
- bufferCI.size = vkMemReqs.size + (vkMemReqs.alignment - (vkMemReqs.size & vkMemReqs.alignment));
- vkResult = vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &newBuffer);
- assert(vkResult == VK_SUCCESS);
-
- VkDeviceMemory new_memory;
- VkMemoryAllocateInfo vkMemoryAllocateInfo;
- vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- vkMemoryAllocateInfo.pNext = nullptr;
- vkMemoryAllocateInfo.allocationSize = bufferCI.size;
- vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
-
- vkResult = vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &new_memory);
- assert(vkResult == VK_SUCCESS);
-
- vkResult = vkBindBufferMemory(vkDevice, newBuffer, new_memory, 0);
- assert(vkResult == VK_SUCCESS);
-
- if (ft->bindings.bd_instance.buffer != VK_NULL_HANDLE && ft->bindings.instance_counter > 0) {
- PKVK_BeginBuffer(transferFamilyIndex, byteCount, tmpBufferDetails, PKVK_TmpBufferFlags_NONE);
-
- VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
- vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- vkCommandBufferBeginInfo.pNext = nullptr;
- // TODO consider single-use?
- vkCommandBufferBeginInfo.flags = 0;
- vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
- vkResult = vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo);
- assert(vkResult == VK_SUCCESS);
-
- VkBufferCopy vk_buffer_copy{};
- vk_buffer_copy.srcOffset = 0;
- vk_buffer_copy.dstOffset = 0;
- vk_buffer_copy.size = sizeof(FontInstanceBufferItem) * ft->bindings.instance_counter;
- assert(vk_buffer_copy.size != 0);
- vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, ft->bindings.bd_instance.buffer, newBuffer, 1, &vk_buffer_copy);
-
- vkResult = vkEndCommandBuffer(tmpBufferDetails.cmdBuffer);
- assert(vkResult == VK_SUCCESS);
-
- VkSubmitInfo submitInfo;
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.pNext = nullptr;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitSemaphores = nullptr;
- submitInfo.pWaitDstStageMask = nullptr;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer;
- submitInfo.signalSemaphoreCount = 0;
- submitInfo.pSignalSemaphores = nullptr;
- vkResult = vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr);
- assert(vkResult == VK_SUCCESS);
- vkResult = vkQueueWaitIdle(tmpBufferDetails.queue);
- assert(vkResult == VK_SUCCESS);
-
- PKVK_EndBuffer(tmpBufferDetails, PKVK_TmpBufferFlags_NONE);
- }
- if (ft->bindings.bd_instance.buffer != VK_NULL_HANDLE)
- vkDestroyBuffer(vkDevice, ft->bindings.bd_instance.buffer, vkAllocator);
- if (ft->gr.deviceMemoryInst != VK_NULL_HANDLE)
- vkFreeMemory(vkDevice, ft->gr.deviceMemoryInst, vkAllocator);
-
- ft->gr.deviceMemoryInst = new_memory;
- ft->bindings.bd_instance.buffer = newBuffer;
- }
- ft->bindings.instance_buffer_max_count = item_length_new;
- ft->bindings.instance_counter += count;
-
- // create tmp local buffer & copy data to graphics card
- byteCount = sizeof(FontInstanceBufferItem) * count;
- PKVK_BeginBuffer(transferFamilyIndex, byteCount, tmpBufferDetails);
- {
-
- VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
- vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- vkCommandBufferBeginInfo.pNext = nullptr;
- // TODO consider single-use?
- vkCommandBufferBeginInfo.flags = 0;
- vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
- vkResult = vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo);
- assert(vkResult == VK_SUCCESS);
-
- FontType_Inner_CalcTransforms(ft, fr, (FontInstanceBufferItem*)tmpBufferDetails.deviceData);
+ if (window == NULL) {
+ return fr->fr_handle;
+ }
- VkBufferCopy vk_buffer_copy{};
- vk_buffer_copy.srcOffset = 0;
- vk_buffer_copy.dstOffset = sizeof(FontInstanceBufferItem) * item_count_orig;
- vk_buffer_copy.size = sizeof(FontInstanceBufferItem) * count;
- vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, tmpBufferDetails.buffer, ft->bindings.bd_instance.buffer, 1, &vk_buffer_copy);
+ // insert new characters into tmp buffer
+ pk_arr_t<uint32_t> glyph_indices{};
+ glyph_indices.bkt = pkeSettings.mem_bkt.game_transient;
+ glyph_indices.next = 0; // hide garbage val warning
+ pk_arr_reserve(&glyph_indices, str.length);
- vkResult = vkEndCommandBuffer(tmpBufferDetails.cmdBuffer);
- assert(vkResult == VK_SUCCESS);
+ FontType_cstr_to_unicode(*ft, glyph_indices, str);
- VkSubmitInfo submitInfo;
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.pNext = nullptr;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitSemaphores = nullptr;
- submitInfo.pWaitDstStageMask = nullptr;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer;
- submitInfo.signalSemaphoreCount = 0;
- submitInfo.pSignalSemaphores = nullptr;
- vkResult = vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr);
- assert(vkResult == VK_SUCCESS);
- vkResult = vkQueueWaitIdle(tmpBufferDetails.queue);
- assert(vkResult == VK_SUCCESS);
- }
- PKVK_EndBuffer(tmpBufferDetails);
+ // TODO specific bucket
+ count = glyph_indices.next;
+ fr->n_glyphs = count;
+ fr->glyph_indices = pk_new<uint32_t>(count);
+ for (i = 0; i < count; ++i) {
+ fr->glyph_indices[i] = glyph_indices[i];
}
+ glyph_indices.data = nullptr;
+
+ ft->gr.should_update_instance_buffer = true;
return fr->fr_handle;
}
@@ -1008,6 +911,36 @@ void FontType_UpdateStringRender(FontRenderHandle frh, FontRenderSettings *setti
ft->renders[(FontRenderIndex_T)frh.index_fr].settings = *settings;
}
+void FontType_UpdateStringRenderText(FontRenderHandle frh, pk_cstr &&cstr) {
+ uint32_t i, count;
+ assert(frh.index_ft < ftd.h_ft);
+ FontType &ft = ftd.arr_ft[static_cast<FontTypeIndex_T>(frh.index_ft)];
+ assert(frh.index_fr < ft.h_render);
+ FontRender &fr = ft.renders[static_cast<FontRenderIndex_T>(frh.index_fr)];
+ pk_cstr old_str = fr.text;
+ if (window == NULL) {
+ return;
+ }
+ pk_arr_t<uint32_t> glyph_indices{};
+ glyph_indices.bkt = pkeSettings.mem_bkt.game_transient;
+ pk_arr_reserve(&glyph_indices, PK_MAX(1, fr.n_glyphs + (cstr.length - old_str.length)));
+
+ FontType_cstr_to_unicode(ft, glyph_indices, cstr);
+
+ // TODO specific bucket
+ count = glyph_indices.next;
+ fr.n_glyphs = count;
+ fr.glyph_indices = pk_new<uint32_t>(count);
+ for (i = 0; i < count; ++i) {
+ fr.glyph_indices[i] = glyph_indices[i];
+ }
+ glyph_indices.data = nullptr;
+ if (fr.text.reserved > 0 && fr.text.val != NULL) pk_delete<char>(fr.text.val, fr.text.reserved);
+ fr.text = cstr;
+
+ ft.gr.should_update_instance_buffer = true;
+}
+
void FontType_RemoveStringRender(FontRenderHandle handle) {
FontRender *fr;
uint32_t buffer_start_index;