diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-16 09:51:00 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-16 09:51:00 -0400 |
| commit | 66ebed74456f76277597b3b07f3e67cc45388ece (patch) | |
| tree | 5e7d0c429867a294bca78269124954ce0a4823fc /src/font.cpp | |
| parent | c1ad6ceeb301bc1f2a4f850e08587748a6d9107b (diff) | |
pke: update FontRender text (editor: for ui-box)
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 315 |
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; |
