diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-04 19:17:59 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-04 19:17:59 -0500 |
| commit | 61e179f9580c985cb5ca80ea732fc7572d31c489 (patch) | |
| tree | 122ff15c6d94ce5aebff4ff6f1fc6d13317abe16 /src/font.cpp | |
| parent | a3fb454f9935960dc2d367455f891d8fedfb9016 (diff) | |
pke: chkpt: text rendering, no errors but blank
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 430 |
1 files changed, 334 insertions, 96 deletions
diff --git a/src/font.cpp b/src/font.cpp index 45569cb..6292039 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -1,12 +1,13 @@ #include "font.hpp" #include "asset-manager.hpp" -#include "helpers.hpp" +#include "dynamic-array.hpp" #include "pk.h" #include "window.hpp" #include "static-plane.hpp" #include "vendor-stb-image-include.h" #include "game-settings.hpp" +#include <vulkan/vulkan_core.h> // TODO threading @@ -23,11 +24,62 @@ struct FontTypeData { FontTypeIndex h_ft{0}; } ftd; +struct FontInstanceBufferItem { + glm::vec4 bg_color; + glm::vec4 fg_color; + glm::ivec4 bounds; + float width; +}; + +const VkDeviceSize instance_buffer_item_size = (sizeof(glm::vec4) * 3) + sizeof(float); + // BucketContainer<FontType, TextRenderHandle, 2> bktFont; +uint32_t utf8_to_unicode(const char* str, uint32_t &out) { + uint32_t i = 0; + out = 0; + + // Check the leading byte to determine the number of bytes in the character + if ((str[i] & 0x80) == 0) { + // 1 byte character (ASCII) + out = str[i]; + i = 1; + } else if ((str[i] & 0xE0) == 0xC0) { + // 2 byte character + out = str[i] & 0x1F; + out <<= 6; + out |= (str[i + 1] & 0x3F); + i = 2; + } else if ((str[i] & 0xF0) == 0xE0) { + // 3 byte character + out = str[i] & 0x0F; + out <<= 6; + out |= (str[i + 1] & 0x3F); + out <<= 6; + out |= (str[i + 2] & 0x3F); + i = 3; + } else if ((str[i] & 0xF8) == 0xF0) { + // 4 byte character + out = str[i] & 0x07; + out <<= 6; + out |= (str[i + 1] & 0x3F); + out <<= 6; + out |= (str[i + 2] & 0x3F); + out <<= 6; + out |= (str[i + 3] & 0x3F); + i = 4; + } else { + // Invalid UTF-8 byte sequence + out = 0; + return 0; + } + return i; +} + void FontType_Init() { - ftd.h_ft = FontTypeIndex{5}; + ftd.n_ft = FontTypeIndex{5}; ftd.arr_ft = pk_new<FontType>(5); + // memset(ftd.arr_ft, 0, sizeof(FontType) * 5); } void FontType_Teardown() { @@ -36,28 +88,33 @@ void FontType_Teardown() { for (i = FontTypeIndex{0}; i < ftd.h_ft; ++i) { FontType_Unload(i); ft = &ftd.arr_ft[(FontTypeIndex_T)i]; - pk_delete<FontRender>(ft->renders, (FontTypeIndex_T)ft->n_render); + if (ft->renders != nullptr) pk_delete<FontRender>(ft->renders, (FontTypeIndex_T)ft->n_render); } pk_delete(ftd.arr_ft, (FontTypeIndex_T)ftd.n_ft); } void FontType_Serialize(std::ofstream &stream, FontType *ft) { - NULL_CHAR_ARR(handleStr, 23); + NULL_CHAR_ARR(handleStr, AssetKeyLength + 2); + const Asset *txtr = AM_Get(ft->fontTextureAssetHandle); + const Asset *glyphs = AM_Get(ft->glyphDetailsAssetHandle); stream << PKE_PROJECT_FONT_TITLE << ft->title.val << std::endl; - snprintf(handleStr, 22, "0x%08X 0x%08X", ft->fontTextureAssetHandle.bucketIndex, ft->fontTextureAssetHandle.itemIndex); + snprintf(handleStr, AssetKeyLength + 1, "%s", txtr->key); stream << PKE_PROJECT_FONT_TEXTURE_HANDLE << handleStr << std::endl; - snprintf(handleStr, 22, "0x%08X 0x%08X", ft->fontTextureAssetHandle.bucketIndex, ft->glyphDetailsAssetHandle.itemIndex); + snprintf(handleStr, AssetKeyLength + 1, "%s", glyphs->key); stream << PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE << handleStr << std::endl; + AM_Release(ft->glyphDetailsAssetHandle); + AM_Release(ft->fontTextureAssetHandle); } void FontType_Deserialize(std::ifstream &stream) { + uint64_t i; NULL_CHAR_ARR(readLine, 128); pk_cstr title; - AssetHandle fontTextureHandle; - AssetHandle glyphDetailsHandle; + AssetKey fontTextureKey; + AssetKey glyphDetailsKey; while (memset(readLine, 0, 128), stream.getline(readLine, 128)) { if (strcmp("", readLine) == 0) { - FontType_RegisterFont(title, fontTextureHandle, glyphDetailsHandle); + FontType_RegisterFont(title, AM_GetHandle(fontTextureKey), AM_GetHandle(glyphDetailsKey)); return; } if (strstr(readLine, PKE_PROJECT_FONT_TITLE)) { @@ -70,22 +127,16 @@ void FontType_Deserialize(std::ifstream &stream) { } if (strstr(readLine, PKE_PROJECT_FONT_TEXTURE_HANDLE)) { uint64_t prefixLen = strlen(PKE_PROJECT_FONT_TEXTURE_HANDLE); - // 0x00000000 0x00000000 - readLine[prefixLen + 10] = '\0'; - STR2NUM_ERROR result1 = str2num(fontTextureHandle.bucketIndex, readLine + prefixLen + 2, 16); - STR2NUM_ERROR result2 = str2num(fontTextureHandle.itemIndex, readLine + prefixLen + 11, 16); - assert(result1 == STR2NUM_ERROR::SUCCESS); - assert(result2 == STR2NUM_ERROR::SUCCESS); + for (i = 0; i < AssetKeyLength; ++i) { + fontTextureKey[i] = readLine[prefixLen + i]; + } continue; } if (strstr(readLine, PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE)) { uint64_t prefixLen = strlen(PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE); - // 0x00000000 0x00000000 - readLine[prefixLen + 10] = '\0'; - STR2NUM_ERROR result1 = str2num(glyphDetailsHandle.bucketIndex, readLine + prefixLen + 2, 16); - STR2NUM_ERROR result2 = str2num(glyphDetailsHandle.itemIndex, readLine + prefixLen + 11, 16); - assert(result1 == STR2NUM_ERROR::SUCCESS); - assert(result2 == STR2NUM_ERROR::SUCCESS); + for (i = 0; i < AssetKeyLength; ++i) { + glyphDetailsKey[i] = readLine[prefixLen + i]; + } continue; } } @@ -108,23 +159,23 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle VkDeviceSize index; constexpr VkDeviceSize expectedBufferCount = 3; constexpr VkDeviceSize startingGlyphCount = 4; + assert(fontTextureHandle != AssetHandle_MAX); + assert(glyphsHandle != AssetHandle_MAX); VkMemoryRequirements combined_vert_mem_reqs; - VkMemoryRequirements combined_inst_mem_reqs; VkMemoryRequirements combined_texture_mem_reqs; const Asset *fontTexture = AM_Get(fontTextureHandle); - const Asset *glyphs = AM_Get(glyphsHandle); - if (ftd.h_ft > ftd.n_ft) { - index = (VkDeviceSize)ftd.n_ft; + FontTypeIndex idx = ftd.h_ft; + ftd.h_ft += FontTypeIndex{1}; + if (ftd.h_ft > ftd.n_ft && idx > FontTypeIndex{0}) { ftd.n_ft += FontTypeIndex{5}; FontType *arr = pk_new<FontType>((FontTypeIndex_T)ftd.n_ft); - memcpy(arr, ftd.arr_ft, sizeof(FontType) * index); - pk_delete<FontType>(ftd.arr_ft, index); + 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; } - FontTypeIndex idx = ftd.h_ft++; FontTypeIndex_T idx_t = (FontTypeIndex_T)idx; FontType *ft = &ftd.arr_ft[idx_t]; ft->title = title; @@ -133,9 +184,15 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle ft->renders = pk_new<FontRender>(startingGlyphCount); ft->n_render = FontRenderIndex{startingGlyphCount}; + const Asset *glyphs = AM_Get(glyphsHandle); + ft->n_glyphs = glyphs->size / sizeof(FontGlyphChar); + ft->glyphs = (FontGlyphChar*)glyphs->ptr; + int txtr_x, txtr_y, txtr_chan; stbi_uc *txtr_bytes = stbi_load_from_memory((unsigned char*)fontTexture->ptr, fontTexture->size, &txtr_x, &txtr_y, &txtr_chan, 4); + assert(txtr_bytes != nullptr); assert(txtr_chan == 4); + uint32_t imageSizeBytes = txtr_x * txtr_y * txtr_chan; /* * vulkan setup @@ -154,15 +211,15 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle */ // vertex { - for (uint64_t index = 0; index < expectedBufferCount; ++index) { - if (index == 0) { + for (uint64_t idx = 0; idx < expectedBufferCount; ++idx) { + if (idx == 0) { bufferCI.size = sizeof(glm::vec2) * 4; - } else if (index == 1) { + } else if (idx == 1) { bufferCI.size = sizeof(glm::vec2) * 4; - } else if (index == 2) { + } else if (idx == 2) { bufferCI.size = sizeof(uint16_t) * 6; } - if (index == 2) { + if (idx == 2) { bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; } else { bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; @@ -203,7 +260,7 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle imageCreateInfo.extent.depth = 1; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = global_sample_count; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -217,21 +274,6 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkImageSubresourceRange.baseArrayLayer = 0u; vkImageSubresourceRange.layerCount = 1u; - VkImageViewCreateInfo vkImageViewCreateInfo; - vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - vkImageViewCreateInfo.pNext = nullptr; - vkImageViewCreateInfo.flags = 0; - vkImageViewCreateInfo.image = ft->textureImage; - vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - vkImageViewCreateInfo.format = imageCreateInfo.format; - vkImageViewCreateInfo.components = VkComponentMapping { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }; - vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange; - VkImage tmpImage; vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &tmpImage); assert(vkResult == VK_SUCCESS); @@ -239,29 +281,9 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle VkMemoryRequirements imageMemoryRequirements; vkGetImageMemoryRequirements(vkDevice, tmpImage, &imageMemoryRequirements); - VkDeviceSize paddedImageSize = imageMemoryRequirements.size + (imageMemoryRequirements.alignment - (imageMemoryRequirements.size % imageMemoryRequirements.alignment)); - assert(paddedImageSize % imageMemoryRequirements.alignment == 0); + pk_arr_append(&arr_texture_mem_reqs, &imageMemoryRequirements); vkDestroyImage(vkDevice, tmpImage, vkAllocator); - - VkMemoryAllocateInfo vkMemoryAllocateInfo{}; - vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - vkMemoryAllocateInfo.pNext = nullptr; - vkMemoryAllocateInfo.allocationSize = paddedImageSize * swapchainLength; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemoryRequirements.memoryTypeBits, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - vkResult = vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryTexture); - assert(vkResult == VK_SUCCESS); - - vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &ft->textureImage); - assert(vkResult == VK_SUCCESS); - vkResult = vkBindImageMemory(vkDevice, ft->textureImage, ft->deviceMemoryTexture, 0); - assert(vkResult == VK_SUCCESS); - - vkImageViewCreateInfo.image = ft->textureImage; - vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &ft->textureImageView); - assert(vkResult == VK_SUCCESS); } /* @@ -278,14 +300,9 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_vert_mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryVert); - // inst - CalculateCombinedMemReqs(arr_inst_mem_reqs.next, (VkMemoryRequirements*)arr_inst_mem_reqs.data, combined_inst_mem_reqs); - vkMemoryAllocateInfo.allocationSize = combined_inst_mem_reqs.size; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_inst_mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryInst); - // texture CalculateCombinedMemReqs(arr_texture_mem_reqs.next, (VkMemoryRequirements*)arr_texture_mem_reqs.data, combined_texture_mem_reqs); + // assert(combined_texture_mem_reqs.size == fontTexture->size && "Size of image texture shouldn't change?"); vkMemoryAllocateInfo.allocationSize = combined_texture_mem_reqs.size; vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_texture_mem_reqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); if (vkMemoryAllocateInfo.memoryTypeIndex == 0) { @@ -420,18 +437,39 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkQueueWaitIdle(tmpBufferDetails.queue); } PKVK_EndBuffer(tmpBufferDetails); - // set up instance buffer - { - ft->bindings.instanceBufferMaxCount = startingGlyphCount; - bufferCI.size = combined_inst_mem_reqs.size; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &ft->bindings.instanceBD.buffer); - vkBindBufferMemory(vkDevice, ft->bindings.instanceBD.buffer, ft->deviceMemoryInst, 0); - } // texture // transition image layout and copy to buffer + tmpBufferDetails = {}; PKVK_BeginBuffer(transferFamilyIndex, combined_texture_mem_reqs.size, tmpBufferDetails); - memcpy(tmpBufferDetails.deviceData, txtr_bytes, combined_texture_mem_reqs.size); + memcpy(tmpBufferDetails.deviceData, txtr_bytes, imageSizeBytes); + free(txtr_bytes); { + VkDeviceSize paddedImageSize = combined_texture_mem_reqs.size + (combined_texture_mem_reqs.alignment - (combined_texture_mem_reqs.size % combined_texture_mem_reqs.alignment)); + assert(paddedImageSize % combined_texture_mem_reqs.alignment == 0); + + VkImageViewCreateInfo vkImageViewCreateInfo; + vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + vkImageViewCreateInfo.pNext = nullptr; + vkImageViewCreateInfo.flags = 0; + vkImageViewCreateInfo.image = ft->textureImage; + vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + vkImageViewCreateInfo.format = imageCreateInfo.format; + vkImageViewCreateInfo.components = VkComponentMapping { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }; + vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange; + + vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &ft->textureImage); + assert(vkResult == VK_SUCCESS); + vkResult = vkBindImageMemory(vkDevice, ft->textureImage, ft->deviceMemoryTexture, 0); + assert(vkResult == VK_SUCCESS); + + vkImageViewCreateInfo.image = ft->textureImage; + vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &ft->textureImageView); + assert(vkResult == VK_SUCCESS); + VkImageMemoryBarrier vkImageMemoryBarrier; vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; vkImageMemoryBarrier.pNext = nullptr; @@ -587,11 +625,11 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle assert(vkResult == VK_SUCCESS); VkWriteDescriptorSet *writeDescriptorSets = pk_new<VkWriteDescriptorSet>(swapchainLength); - for (long i = 0; i < 1 * swapchainLength; ++i) { + for (long i = 0; i < swapchainLength; ++i) { writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeDescriptorSets[i].pNext = nullptr; writeDescriptorSets[i].dstSet = nullptr; - writeDescriptorSets[i].dstBinding = i; + writeDescriptorSets[i].dstBinding = 0; writeDescriptorSets[i].dstArrayElement = 0; writeDescriptorSets[i].descriptorCount = 1; writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; @@ -612,20 +650,17 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkDescriptorBufferInfo[i].offset = 0; vkDescriptorBufferInfo[i].range = sizeof(UniformBufferObject); - long uboIndex = i * 2; - long samplerIndex = uboIndex + 1; - - writeDescriptorSets[uboIndex].pBufferInfo = &vkDescriptorBufferInfo[i]; - writeDescriptorSets[uboIndex].dstSet = ft->vkDescriptorSets[i]; - - writeDescriptorSets[samplerIndex].pImageInfo = &textureDescriptorInfo; - writeDescriptorSets[samplerIndex].dstSet = ft->vkDescriptorSets[i]; + writeDescriptorSets[i].pImageInfo = &textureDescriptorInfo; + writeDescriptorSets[i].dstSet = ft->vkDescriptorSets[i]; } - vkUpdateDescriptorSets(vkDevice, 2 * swapchainLength, writeDescriptorSets, 0, nullptr); + vkUpdateDescriptorSets(vkDevice, swapchainLength, writeDescriptorSets, 0, nullptr); pk_delete<VkDescriptorBufferInfo>(vkDescriptorBufferInfo, swapchainLength); pk_delete<VkWriteDescriptorSet>(writeDescriptorSets, swapchainLength); + AM_Release(fontTextureHandle); + AM_Release(glyphsHandle); + return idx; } @@ -698,3 +733,206 @@ void FontType_Unload(FontTypeIndex idx) { pk_delete<char>(ft->title.val, ft->title.reserved); } } + +// 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, pk_cstr cstr) { + VkResult vkResult; + FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx_ft]; + FontRender *fr; + FontGlyphChar *fgc; + FontRenderIndex idx_fr = ft->n_render; + DynArray<FontInstanceBufferItem> instance_buffer_items; + uint32_t i, ii, u, count; + int32_t l, m, r; + + if (ft->n_render > ft->h_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); + ft->renders = arr; + } + fr = &ft->renders[(FontRenderIndex_T)idx_fr]; + fr->len = cstr.length; + fr->index_ft = idx_ft; + fr->index_fr = idx_fr; + + // insert new characters into tmp buffer + instance_buffer_items.Reserve(cstr.length); + { + count = 0; + FontInstanceBufferItem *buf_item; + for (i = 0; i < cstr.length;) { + fgc = nullptr; + u = 0; + // determine unicode char + ii = utf8_to_unicode(&cstr.val[i], u); + if (ii == 0) { + fprintf(stderr, "failed to determine unicode for character: '%c'\n", cstr.val[i]); + i += 1; + continue; + } + i += ii; + count += 1; + + // 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' doesn't contain unicode character: '%u'\n", ft->title.val, u); + continue; + } + + buf_item = &instance_buffer_items.Push(); + buf_item->fg_color = glm::vec4(0.4, 0.5, 0.4, 0); + buf_item->bg_color = glm::vec4(1.0, 1.0, 1.0, 0); + buf_item->bounds = fgc->bounds; + buf_item->width = 10; + } + } + VkDeviceSize item_count_orig = ft->bindings.instanceBufferMaxCount; + VkDeviceSize item_count_new = ft->bindings.instanceBufferMaxCount + count; + + // copy existing buffer to new buffer + VkDeviceSize byteCount = instance_buffer_item_size * item_count_new; + PKVK_TmpBufferDetails tmpBufferDetails{}; + { + 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_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); + + 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); + + PKVK_BeginBuffer(transferFamilyIndex, byteCount, tmpBufferDetails, PKVK_TmpBufferFlags_NONE); + if (ft->bindings.instanceBD.buffer != VK_NULL_HANDLE) { + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + // TODO consider single-use? + vkCommandBufferBeginInfo.flags = 0; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); + + VkBufferCopy vk_buffer_copy{}; + vk_buffer_copy.srcOffset = 0; + vk_buffer_copy.dstOffset = 0; + vk_buffer_copy.size = instance_buffer_item_size * item_count_orig; + vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, ft->bindings.instanceBD.buffer, newBuffer, 1, &vk_buffer_copy); + + vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); + + 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; + vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(tmpBufferDetails.queue); + + } + PKVK_EndBuffer(tmpBufferDetails, PKVK_TmpBufferFlags_NONE); + if (ft->bindings.instanceBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.instanceBD.buffer, vkAllocator); + if (ft->deviceMemoryInst != VK_NULL_HANDLE) + vkFreeMemory(vkDevice, ft->deviceMemoryInst, vkAllocator); + + ft->deviceMemoryInst = new_memory; + ft->bindings.instanceBD.buffer = newBuffer; + ft->bindings.instanceBufferMaxCount = item_count_new; + } + + // create tmp local buffer & copy data to graphics card + byteCount = instance_buffer_item_size * 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; + vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); + + memcpy(tmpBufferDetails.deviceData, instance_buffer_items.GetPtr(), instance_buffer_items.Count() * instance_buffer_item_size); + + VkBufferCopy vk_buffer_copy{}; + vk_buffer_copy.srcOffset = 0; + vk_buffer_copy.dstOffset = instance_buffer_item_size * item_count_orig; + vk_buffer_copy.size = instance_buffer_item_size * count; + vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, tmpBufferDetails.buffer, ft->bindings.instanceBD.buffer, 1, &vk_buffer_copy); + + vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); + + 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; + vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(tmpBufferDetails.queue); + } + PKVK_EndBuffer(tmpBufferDetails); + + return *fr; +} + +void FontType_RemoveStringRender(FontRender fr) { + (void)fr; + // TODO + // FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)fr.index_ft]; +} |
