diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-23 21:57:31 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-23 21:57:31 -0500 |
| commit | e93eb289ca44e98967482ab80fd5329f85ccd03e (patch) | |
| tree | 4164b6d5b9ac2e40d18ec3eea52730c9f9606ccb /src/font.cpp | |
| parent | 846a6e1185417ee3e187edc06ef327d180bf0d9b (diff) | |
pke: first-pass 2d overlay render pass scaffolding
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000..d218430 --- /dev/null +++ b/src/font.cpp @@ -0,0 +1,638 @@ + +#include "font.hpp" +#include "asset-manager.hpp" +#include "pk.h" +#include "window.hpp" +#include "static-plane.hpp" +#include "vendor-stb-image-include.h" +// #include "bucketed-array.hpp" + +// TODO threading + +TypeSafeInt_B(FontTypeIndex); +TypeSafeInt_B(FontRenderIndex); + +struct FontTypeData { + FontType *arr_ft; + FontTypeIndex n_ft{0}; + FontTypeIndex h_ft{0}; +} ftd; + +// BucketContainer<FontType, TextRenderHandle, 2> bktFont; + +void FontType_Init() { + ftd.h_ft = FontTypeIndex{5}; + ftd.arr_ft = pk_new<FontType>(5); +} + +void FontType_Teardown() { + FontTypeIndex i; + FontType *ft; + 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); + } + pk_delete(ftd.arr_ft, (FontTypeIndex_T)ftd.n_ft); +} + +FontType* FontType_GetFonts(FontTypeIndex &count) +{ + count = ftd.h_ft; + return ftd.arr_ft; +} + +FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle, AssetHandle glyphsHandle) { + VkResult vkResult; + pk_arr arr_vert_mem_reqs; + memset(&arr_vert_mem_reqs, 0, sizeof(pk_arr)); + arr_vert_mem_reqs.alignment = alignof(VkMemoryRequirements); + arr_vert_mem_reqs.stride = sizeof(VkMemoryRequirements); + pk_arr arr_inst_mem_reqs(arr_vert_mem_reqs); + pk_arr arr_texture_mem_reqs(arr_vert_mem_reqs); + VkDeviceSize index; + constexpr VkDeviceSize expectedBufferCount = 3; + constexpr VkDeviceSize startingGlyphCount = 4; + + 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; + 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); + 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; + ft->fontTextureAssetKey = fontTextureHandle; + ft->glyphDetailsAssetKey = glyphsHandle; + ft->renders = pk_new<FontRender>(startingGlyphCount); + ft->n_render = FontRenderIndex{startingGlyphCount}; + + 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_chan == 4); + + /* + * vulkan setup + */ + VkBuffer buffer; + 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; + + /* + * Vulkan resource setup + */ + // vertex + { + for (uint64_t index = 0; index < expectedBufferCount; ++index) { + if (index == 0) { + bufferCI.size = sizeof(glm::vec2) * 4; + } else if (index == 1) { + bufferCI.size = sizeof(glm::vec2) * 4; + } else if (index == 2) { + bufferCI.size = sizeof(uint16_t) * 6; + } + if (index == 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; + } + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &buffer); + VkMemoryRequirements tmp; + vkGetBufferMemoryRequirements(vkDevice, buffer, &tmp); + pk_arr_append(&arr_vert_mem_reqs, &tmp); + vkDestroyBuffer(vkDevice, buffer, vkAllocator); + } + } + // instance + { + bufferCI.size = 0; + bufferCI.size += sizeof(glm::vec4); // fgColor + bufferCI.size += sizeof(glm::vec4); // bgColor + bufferCI.size += sizeof(glm::vec4); // sprite_region + bufferCI.size += sizeof(float); // width + bufferCI.size *= startingGlyphCount; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &buffer); + VkMemoryRequirements tmp; + vkGetBufferMemoryRequirements(vkDevice, buffer, &tmp); + pk_arr_append(&arr_inst_mem_reqs, &tmp); + vkDestroyBuffer(vkDevice, buffer, vkAllocator); + } + // texture + VkImageCreateInfo imageCreateInfo{}; + VkImageSubresourceRange vkImageSubresourceRange; + { + imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCreateInfo.pNext = nullptr; + imageCreateInfo.flags = 0; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB; + imageCreateInfo.extent.width = txtr_x; + imageCreateInfo.extent.height = txtr_y; + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = renderSampleCount; + 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; + imageCreateInfo.queueFamilyIndexCount = 0; + imageCreateInfo.pQueueFamilyIndices = nullptr; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + vkImageSubresourceRange.aspectMask = VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT; + vkImageSubresourceRange.baseMipLevel = 0u; + vkImageSubresourceRange.levelCount = 1u; + 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); + + VkMemoryRequirements imageMemoryRequirements; + vkGetImageMemoryRequirements(vkDevice, tmpImage, &imageMemoryRequirements); + + VkDeviceSize paddedImageSize = imageMemoryRequirements.size + (imageMemoryRequirements.alignment - (imageMemoryRequirements.size % imageMemoryRequirements.alignment)); + assert(paddedImageSize % imageMemoryRequirements.alignment == 0); + + vkDestroyImage(vkDevice, tmpImage, vkAllocator); + + VkMemoryAllocateInfo vkMemoryAllocateInfo{}; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = nullptr; + vkMemoryAllocateInfo.allocationSize = paddedImageSize * MAX_FRAMES_IN_FLIGHT; + 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); + } + + /* + * Vulkan memory allocation + */ + + VkMemoryAllocateInfo vkMemoryAllocateInfo; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = nullptr; + + // verts + CalculateCombinedMemReqs(arr_vert_mem_reqs.next, (VkMemoryRequirements*)arr_vert_mem_reqs.data, combined_vert_mem_reqs); + vkMemoryAllocateInfo.allocationSize = combined_vert_mem_reqs.size; + 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); + 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) { + vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_texture_mem_reqs.memoryTypeBits, 0); + } + vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryTexture); + + /* + * Vulkan data transfer + */ + VkBuffer transferBuffer; + VkDeviceMemory transferMemory; + void *deviceData; + VkDeviceSize runningOffset, alignmentPadding; + // vert + BeginTransferBuffer(combined_vert_mem_reqs.size, transferBuffer, transferMemory, deviceData); + { + index = 0; + runningOffset = 0; + + uint32_t offsetVert = runningOffset; + uint32_t sizeVert = sizeof(pkeIntrinsicsPlane.vert[0]) * 4; + ft->bindings.vertexBD.firstBinding = index; + ft->bindings.vertexBD.bindingCount = 1; + alignmentPadding = sizeVert % combined_vert_mem_reqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combined_vert_mem_reqs.alignment - alignmentPadding; + sizeVert += alignmentPadding; + bufferCI.size = sizeVert; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &ft->bindings.vertexBD.buffer); + vkBindBufferMemory(vkDevice, ft->bindings.vertexBD.buffer, ft->deviceMemoryVert, offsetVert); + runningOffset += sizeVert; + index += 1; + + // uv + uint32_t offsetUV = runningOffset; + uint32_t sizeUV = sizeof(pkeIntrinsicsPlane.uv[0]) * 4; + ft->bindings.uvBD.firstBinding = index; + ft->bindings.uvBD.bindingCount = 1; + alignmentPadding = sizeUV % combined_vert_mem_reqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combined_vert_mem_reqs.alignment - alignmentPadding; + sizeUV += alignmentPadding; + bufferCI.size = sizeUV; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &ft->bindings.uvBD.buffer); + vkBindBufferMemory(vkDevice, ft->bindings.uvBD.buffer, ft->deviceMemoryVert, offsetUV); + runningOffset += sizeUV; + index += 1; + + // 2023-09-27 - JCB + // I don't know where else to put this + ft->bindings.instanceBD.firstBinding = index; + ft->bindings.instanceBD.bindingCount = 1; + // no index += 1 because index just happens to be the right value here for + // the binding index, whereas binding the IndexBuffer doesn't need a binding index. + + // index + uint32_t offsetIndex = runningOffset; + uint32_t sizeIndex = sizeof(pkeIntrinsicsPlane.index[0]) * 6; + ft->bindings.indexBD.bindingCount = 1; + ft->bindings.indexCount = 6; + alignmentPadding = sizeIndex % combined_vert_mem_reqs.alignment; + alignmentPadding = alignmentPadding == 0 ? 0 : combined_vert_mem_reqs.alignment - alignmentPadding; + sizeIndex += alignmentPadding; + bufferCI.size = sizeIndex; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &ft->bindings.indexBD.buffer); + vkBindBufferMemory(vkDevice, ft->bindings.indexBD.buffer, ft->deviceMemoryVert, offsetIndex); + runningOffset += sizeIndex; + // index += 1; + + assert(runningOffset == combined_vert_mem_reqs.size); + + + runningOffset = 0; + + char *dstPtr = nullptr; + char *srcPtr = nullptr; + + dstPtr = static_cast<char *>(deviceData) + runningOffset; + srcPtr = reinterpret_cast<char *>(pkeIntrinsicsPlane.vert); + memcpy(dstPtr, srcPtr, sizeVert); + runningOffset += sizeVert; + + dstPtr = static_cast<char *>(deviceData) + runningOffset; + srcPtr = reinterpret_cast<char *>(pkeIntrinsicsPlane.uv); + memcpy(dstPtr, srcPtr, sizeUV); + runningOffset += sizeUV; + + dstPtr = static_cast<char *>(deviceData) + runningOffset; + srcPtr = reinterpret_cast<char *>(pkeIntrinsicsPlane.index); + memcpy(dstPtr, srcPtr, sizeIndex); + // runningOffset += sizeIndex; + + 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(transferCommandBuffer, &vkCommandBufferBeginInfo); + VkBufferCopy bufferCopys[expectedBufferCount]; + for (VkDeviceSize i = 0; i < expectedBufferCount; ++i) { + bufferCopys[i].dstOffset = 0; + } + index = 0; + bufferCopys[index].srcOffset = offsetVert; + bufferCopys[index].size = sizeVert; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, ft->bindings.vertexBD.buffer, 1, &bufferCopys[index]); + index+=1; + + bufferCopys[index].srcOffset = offsetUV; + bufferCopys[index].size = sizeUV; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, ft->bindings.uvBD.buffer, 1, &bufferCopys[index]); + index+=1; + + bufferCopys[index].srcOffset = offsetIndex; + bufferCopys[index].size = sizeIndex; + vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, ft->bindings.indexBD.buffer, 1, &bufferCopys[index]); + // index+=1; + + vkEndCommandBuffer(transferCommandBuffer); + + 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 = &transferCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(transferQueue); + } + EndTransferBuffer(transferBuffer, transferMemory); + // 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 + BeginTransferBuffer(combined_texture_mem_reqs.size, transferBuffer, transferMemory, deviceData); + memcpy(deviceData, txtr_bytes, combined_texture_mem_reqs.size); + { + VkImageMemoryBarrier vkImageMemoryBarrier; + vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + vkImageMemoryBarrier.pNext = nullptr; + vkImageMemoryBarrier.srcAccessMask = {}; + vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.image = ft->textureImage; + vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + // TODO MipMap + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + + vkBeginCommandBuffer(transferCommandBuffer, &vkCommandBufferBeginInfo); + + vkCmdPipelineBarrier(transferCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); + + VkBufferImageCopy vkBufferImageCopy; + vkBufferImageCopy.bufferOffset = 0; + vkBufferImageCopy.bufferRowLength = txtr_x; + vkBufferImageCopy.bufferImageHeight = txtr_y; + vkBufferImageCopy.imageSubresource = VkImageSubresourceLayers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }; + vkBufferImageCopy.imageOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }; + vkBufferImageCopy.imageExtent = VkExtent3D { + .width = static_cast<uint32_t>(txtr_x), + .height = static_cast<uint32_t>(txtr_y), + .depth = 1, + }; + vkCmdCopyBufferToImage(transferCommandBuffer, transferBuffer, ft->textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vkBufferImageCopy); + + vkEndCommandBuffer(transferCommandBuffer); + + 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 = &transferCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(transferQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(transferQueue); + vkResetCommandBuffer(transferCommandBuffer, 0); + } + EndTransferBuffer(transferBuffer, transferMemory); + { + VkImageMemoryBarrier vkImageMemoryBarrier; + vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + vkImageMemoryBarrier.pNext = nullptr; + vkImageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + vkImageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + vkImageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkImageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkImageMemoryBarrier.image = ft->textureImage; + vkImageMemoryBarrier.subresourceRange = VkImageSubresourceRange { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + // TODO MipMap + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + vkCommandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + + vkBeginCommandBuffer(graphicsCommandBuffer, &vkCommandBufferBeginInfo); + + vkCmdPipelineBarrier(graphicsCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkImageMemoryBarrier); + + vkEndCommandBuffer(graphicsCommandBuffer); + + 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 = &graphicsCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(graphicsQueue); + } + + /* + * Vulkan descriptor sets + */ + VkDescriptorPoolSize descriptorPoolSizes[1]; + descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorPoolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT; + + VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo; + vkDescriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + vkDescriptorPoolCreateInfo.pNext = nullptr; + vkDescriptorPoolCreateInfo.flags = 0; + vkDescriptorPoolCreateInfo.maxSets = MAX_FRAMES_IN_FLIGHT; + vkDescriptorPoolCreateInfo.poolSizeCount = (uint32_t)1; + vkDescriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes; + + // consider making me a global pool + vkResult = vkCreateDescriptorPool(vkDevice, &vkDescriptorPoolCreateInfo, vkAllocator, &ft->vkDescriptorPool); + assert(vkResult == VK_SUCCESS); + + VkDescriptorSetLayout descriptorSets[MAX_FRAMES_IN_FLIGHT]; + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + descriptorSets[i] = pkePipelines.descr_layouts.named.glyph; + } + VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo; + vkDescriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + vkDescriptorSetAllocateInfo.pNext = nullptr; + vkDescriptorSetAllocateInfo.descriptorPool = ft->vkDescriptorPool; + vkDescriptorSetAllocateInfo.descriptorSetCount = MAX_FRAMES_IN_FLIGHT; + vkDescriptorSetAllocateInfo.pSetLayouts = descriptorSets; + + ft->vkDescriptorSets = pk_new<VkDescriptorSet>(MAX_FRAMES_IN_FLIGHT); + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + ft->vkDescriptorSets[i] = VkDescriptorSet{}; + } + vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, ft->vkDescriptorSets); + assert(vkResult == VK_SUCCESS); + + VkWriteDescriptorSet writeDescriptorSets[1 * MAX_FRAMES_IN_FLIGHT]; + for (long i = 0; i < 1 * MAX_FRAMES_IN_FLIGHT; ++i) { + writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSets[i].pNext = nullptr; + writeDescriptorSets[i].dstSet = nullptr; + writeDescriptorSets[i].dstBinding = i; + writeDescriptorSets[i].dstArrayElement = 0; + writeDescriptorSets[i].descriptorCount = 1; + writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writeDescriptorSets[i].pImageInfo = nullptr; + writeDescriptorSets[i].pBufferInfo = nullptr; + writeDescriptorSets[i].pTexelBufferView = nullptr; + } + + VkDescriptorImageInfo textureDescriptorInfo; + textureDescriptorInfo.sampler = pkePipelines.vkSampler_Texture; + textureDescriptorInfo.imageView = ft->textureImageView; + textureDescriptorInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDescriptorBufferInfo vkDescriptorBufferInfo[MAX_FRAMES_IN_FLIGHT]; + + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + vkDescriptorBufferInfo[i].buffer = UniformBuffers[i]; + 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]; + } + + vkUpdateDescriptorSets(vkDevice, 2 * MAX_FRAMES_IN_FLIGHT, writeDescriptorSets, 0, nullptr); + + return idx; +} + +void FontType_Unload(FontTypeIndex idx) +{ + FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx]; + + if (ft->vkDescriptorSets != VK_NULL_HANDLE && ft->vkDescriptorPool != VK_NULL_HANDLE) { + // 2023-09-27 - JCB (copied from entities.cpp) + // We are not setting the pool flag for allowing freeing descriptor sets + // so all we need to do is destroy the pool + // If we switch to a global pool, we will need to free here, and + // destroy the pool outside of this loop + vkDestroyDescriptorPool(vkDevice, ft->vkDescriptorPool, vkAllocator); + ft->vkDescriptorSets = CAFE_BABE(VkDescriptorSet); + ft->vkDescriptorPool = VK_NULL_HANDLE; + } + + if (ft->bindings.vertexBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.vertexBD.buffer, vkAllocator); + ft->bindings.vertexBD.buffer = VK_NULL_HANDLE; + ft->bindings.vertexBD.firstBinding = 0; + ft->bindings.vertexBD.bindingCount = 0; + ft->bindings.vertexBD.offsets[0] = 0; + + if (ft->bindings.uvBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.uvBD.buffer, vkAllocator); + ft->bindings.uvBD.buffer = VK_NULL_HANDLE; + ft->bindings.uvBD.firstBinding = 0; + ft->bindings.uvBD.bindingCount = 0; + ft->bindings.uvBD.offsets[0] = 0; + + if (ft->bindings.indexBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.indexBD.buffer, vkAllocator); + ft->bindings.indexBD.buffer = VK_NULL_HANDLE; + ft->bindings.indexBD.bindingCount = 0; + ft->bindings.indexBD.offsets[0] = 0; + ft->bindings.indexCount = 0; + + if (ft->bindings.instanceBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.instanceBD.buffer, vkAllocator); + ft->bindings.instanceBD.buffer = VK_NULL_HANDLE; + ft->bindings.instanceBD.firstBinding = 0; + ft->bindings.instanceBD.bindingCount = 0; + ft->bindings.instanceCounter = 0; + ft->bindings.instanceBufferMaxCount = 0; + ft->bindings.instanceBD.offsets[0] = 0; + + if (ft->textureImageView != VK_NULL_HANDLE) + vkDestroyImageView(vkDevice, ft->textureImageView, vkAllocator); + ft->textureImageView = VK_NULL_HANDLE; + + if (ft->textureImage != VK_NULL_HANDLE) + vkDestroyImage(vkDevice, ft->textureImage, vkAllocator); + ft->textureImage = VK_NULL_HANDLE; + + if (ft->deviceMemoryInst != VK_NULL_HANDLE) + vkFreeMemory(vkDevice, ft->deviceMemoryInst, vkAllocator); + ft->deviceMemoryInst = VK_NULL_HANDLE; + + if (ft->deviceMemoryVert != VK_NULL_HANDLE) + vkFreeMemory(vkDevice, ft->deviceMemoryVert, vkAllocator); + ft->deviceMemoryVert = VK_NULL_HANDLE; + + if (ft->deviceMemoryTexture != VK_NULL_HANDLE) + vkFreeMemory(vkDevice, ft->deviceMemoryTexture, vkAllocator); + ft->deviceMemoryTexture = VK_NULL_HANDLE; +} |
