|
|
|
@ -459,7 +459,79 @@ VkResult create_font_descriptor_pools(VkDevice device, uint32_t max_sets, VkDesc
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool, FontData* font, SymbolInfo* symbols, uint32_t* atlas, VkCommandPool transfer_pool, Queue transfer_queue, FontDescriptor* descriptor) {
|
|
|
|
|
VkResult load_font(VkDevice device, VmaAllocator allocator, VkDescriptorSetLayout layout, VkDescriptorPool pool,VkCommandPool transfer_pool, Queue transfer_queue, FT_Library library, const char* ttf_file, uint32_t size, uint32_t** charmap, FontDescriptor* descriptor) {
|
|
|
|
|
FT_Face face;
|
|
|
|
|
|
|
|
|
|
int error;
|
|
|
|
|
error = FT_New_Face(library, ttf_file, 0, &face);
|
|
|
|
|
if(error != FT_Err_Ok) {
|
|
|
|
|
return VK_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error = FT_Set_Pixel_Sizes(face, 0, size);
|
|
|
|
|
if(error != FT_Err_Ok) {
|
|
|
|
|
return VK_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t* tmp_charmap = malloc(sizeof(uint32_t)*face->num_glyphs);
|
|
|
|
|
SymbolInfo* symbols = malloc(sizeof(SymbolInfo)*face->num_glyphs);
|
|
|
|
|
FontUniform uniform;
|
|
|
|
|
|
|
|
|
|
uint32_t glyph_index;
|
|
|
|
|
uint32_t max_height = 0;
|
|
|
|
|
uint32_t max_width = 0;
|
|
|
|
|
uint32_t symbol_count = 0;
|
|
|
|
|
uint32_t c;
|
|
|
|
|
|
|
|
|
|
// TODO: worry about variants(that's why num_glyphs doesn't match symbol_count)
|
|
|
|
|
c = FT_Get_First_Char(face, &glyph_index);
|
|
|
|
|
for(uint32_t i = 0; i < face->num_glyphs; i++) {
|
|
|
|
|
if(glyph_index == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER | FT_RENDER_MODE_MONO);
|
|
|
|
|
uint32_t width = face->glyph->bitmap.width;
|
|
|
|
|
uint32_t height = face->glyph->bitmap.rows;
|
|
|
|
|
tmp_charmap[i] = c;
|
|
|
|
|
symbols[i].width = width;
|
|
|
|
|
symbols[i].height = height;
|
|
|
|
|
symbols[i].left = face->glyph->bitmap_left;
|
|
|
|
|
symbols[i].top = ((face->bbox.yMax*size)/face->units_per_EM) - face->glyph->bitmap_top;
|
|
|
|
|
symbols[i].advance = face->glyph->advance.x*16/face->units_per_EM;
|
|
|
|
|
max_width = width > max_width ? width : max_width;
|
|
|
|
|
max_height = height > max_height ? height : max_height;
|
|
|
|
|
symbol_count += 1;
|
|
|
|
|
c = FT_Get_Next_Char(face, c, &glyph_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uniform.width = max_width;
|
|
|
|
|
uniform.height = max_height;
|
|
|
|
|
uniform.num_symbols = symbol_count;
|
|
|
|
|
uint32_t image_size = max_width*max_height*sizeof(uint32_t);
|
|
|
|
|
uint32_t* images = malloc(image_size*symbol_count);
|
|
|
|
|
memset(images, 0x00, image_size*symbol_count);
|
|
|
|
|
*charmap = malloc(sizeof(uint32_t)*symbol_count);
|
|
|
|
|
memcpy(*charmap, tmp_charmap, sizeof(uint32_t)*symbol_count);
|
|
|
|
|
free(tmp_charmap);
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < symbol_count; i++) {
|
|
|
|
|
glyph_index = FT_Get_Char_Index(face, (*charmap)[i]);
|
|
|
|
|
FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER | FT_RENDER_MODE_MONO);
|
|
|
|
|
for(uint32_t y = 0; y < face->glyph->bitmap.rows; y++) {
|
|
|
|
|
for(uint32_t x = 0; x < face->glyph->bitmap.width; x++) {
|
|
|
|
|
if(face->glyph->bitmap.buffer[y*face->glyph->bitmap.width+x] != 0) {
|
|
|
|
|
images[max_width*max_height*i + max_width*y + x] = 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
error = FT_Done_Face(face);
|
|
|
|
|
if(error != FT_Err_Ok) {
|
|
|
|
|
return VK_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
VkDescriptorSetAllocateInfo set_allocate_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
|
|
@ -477,7 +549,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
|
|
|
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
|
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
|
.size = sizeof(SymbolInfo)*font->info.num_symbols,
|
|
|
|
|
.size = sizeof(SymbolInfo)*uniform.num_symbols,
|
|
|
|
|
};
|
|
|
|
|
VmaAllocationCreateInfo symbol_memory_info = {
|
|
|
|
|
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
|
|
|
|
@ -504,10 +576,10 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
|
|
|
.extent.depth = 1,
|
|
|
|
|
.extent.width = font->info.width,
|
|
|
|
|
.extent.height = font->info.height,
|
|
|
|
|
.extent.width = uniform.width,
|
|
|
|
|
.extent.height = uniform.height,
|
|
|
|
|
.mipLevels = 1,
|
|
|
|
|
.arrayLayers = 1,
|
|
|
|
|
.arrayLayers = uniform.num_symbols,
|
|
|
|
|
.format = VK_FORMAT_R8G8B8A8_SRGB,
|
|
|
|
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
@ -524,12 +596,11 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t image_size = sizeof(uint32_t)*font->info.width*font->info.height;
|
|
|
|
|
VkBufferCreateInfo staging_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
|
.size = sizeof(FontUniform) + image_size + sizeof(SymbolInfo)*font->info.num_symbols,
|
|
|
|
|
.size = sizeof(FontUniform) + image_size*uniform.num_symbols + sizeof(SymbolInfo)*uniform.num_symbols,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VmaAllocationCreateInfo staging_memory_info = {
|
|
|
|
@ -548,28 +619,30 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
memcpy(mapped_staging + image_size + sizeof(FontUniform), symbols, sizeof(SymbolInfo)*font->info.num_symbols);
|
|
|
|
|
memcpy(mapped_staging + image_size*uniform.num_symbols + sizeof(FontUniform), symbols, sizeof(SymbolInfo)*uniform.num_symbols);
|
|
|
|
|
VkBufferDeviceAddressInfo address_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
|
|
|
.buffer = descriptor->symbols,
|
|
|
|
|
};
|
|
|
|
|
font->info.symbol_list = vkGetBufferDeviceAddress(device, &address_info);
|
|
|
|
|
memcpy(mapped_staging + image_size, &font->info, sizeof(FontUniform));
|
|
|
|
|
memcpy(mapped_staging, atlas, image_size);
|
|
|
|
|
uniform.symbol_list = vkGetBufferDeviceAddress(device, &address_info);
|
|
|
|
|
memcpy(mapped_staging + image_size*uniform.num_symbols, &uniform, sizeof(FontUniform));
|
|
|
|
|
memcpy(mapped_staging, images, image_size*uniform.num_symbols);
|
|
|
|
|
vmaUnmapMemory(allocator, staging_memory);
|
|
|
|
|
free(images);
|
|
|
|
|
free(symbols);
|
|
|
|
|
|
|
|
|
|
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
|
|
|
|
|
|
|
|
|
|
VkBufferCopy uniform_copy_info = {
|
|
|
|
|
.size = sizeof(FontUniform),
|
|
|
|
|
.srcOffset = image_size,
|
|
|
|
|
.srcOffset = image_size*uniform.num_symbols,
|
|
|
|
|
.dstOffset = 0,
|
|
|
|
|
};
|
|
|
|
|
vkCmdCopyBuffer(command_buffer, staging_buffer, descriptor->uniform, 1, &uniform_copy_info);
|
|
|
|
|
|
|
|
|
|
VkBufferCopy symbol_copy_info = {
|
|
|
|
|
.size = sizeof(SymbolInfo)*font->info.num_symbols,
|
|
|
|
|
.srcOffset = image_size + sizeof(FontUniform),
|
|
|
|
|
.size = sizeof(SymbolInfo)*uniform.num_symbols,
|
|
|
|
|
.srcOffset = image_size*uniform.num_symbols + sizeof(FontUniform),
|
|
|
|
|
.dstOffset = 0,
|
|
|
|
|
};
|
|
|
|
|
vkCmdCopyBuffer(command_buffer, staging_buffer, descriptor->symbols, 1, &symbol_copy_info);
|
|
|
|
@ -583,14 +656,14 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.subresourceRange.levelCount = 1,
|
|
|
|
|
.subresourceRange.layerCount = 1,
|
|
|
|
|
.subresourceRange.layerCount = uniform.num_symbols,
|
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
|
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
|
};
|
|
|
|
|
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &first_barrier);
|
|
|
|
|
|
|
|
|
|
VkBufferImageCopy image_copy = {
|
|
|
|
|
.imageSubresource.layerCount = 1,
|
|
|
|
|
.imageSubresource.layerCount = uniform.num_symbols,
|
|
|
|
|
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.imageExtent = image_info.extent,
|
|
|
|
|
};
|
|
|
|
@ -605,7 +678,7 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.subresourceRange.levelCount = 1,
|
|
|
|
|
.subresourceRange.layerCount = 1,
|
|
|
|
|
.subresourceRange.layerCount = uniform.num_symbols,
|
|
|
|
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
|
};
|
|
|
|
@ -620,11 +693,11 @@ VkResult create_text_descriptor(VkDevice device, VmaAllocator allocator, VkDescr
|
|
|
|
|
VkImageViewCreateInfo view_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
|
.image = descriptor->image,
|
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
|
|
|
|
.format = VK_FORMAT_R8G8B8A8_SRGB,
|
|
|
|
|
.subresourceRange = {
|
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.layerCount = 1,
|
|
|
|
|
.layerCount = uniform.num_symbols,
|
|
|
|
|
.baseMipLevel = 0,
|
|
|
|
|
.levelCount = 1,
|
|
|
|
|
.baseArrayLayer = 0,
|
|
|
|
|