|  |  |  | @ -631,37 +631,26 @@ VkResult load_texture( | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult load_font( | 
		
	
		
			
				|  |  |  |  |     uint32_t index, | 
		
	
		
			
				|  |  |  |  |     const char* ttf_file, | 
		
	
		
			
				|  |  |  |  |     uint32_t size, | 
		
	
		
			
				|  |  |  |  |     VkBool32 antialias, | 
		
	
		
			
				|  |  |  |  |     FT_Library library, | 
		
	
		
			
				|  |  |  |  |     RenderContext* gpu, | 
		
	
		
			
				|  |  |  |  |     UIContext* context, | 
		
	
		
			
				|  |  |  |  |     uint32_t* index){ | 
		
	
		
			
				|  |  |  |  |     UIContext* context){ | 
		
	
		
			
				|  |  |  |  |   FT_Face face; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   int error; | 
		
	
		
			
				|  |  |  |  |   error = FT_New_Face(library, ttf_file, 0, &face); | 
		
	
		
			
				|  |  |  |  |   error = FT_New_Face(context->freetype, ttf_file, 0, &face); | 
		
	
		
			
				|  |  |  |  |   if(error != FT_Err_Ok) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   *index = 0xFFFFFFFF; | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < context->max_fonts; i++) { | 
		
	
		
			
				|  |  |  |  |     if(context->fonts[i].family == NULL) { | 
		
	
		
			
				|  |  |  |  |       context->fonts[i].family = malloc(strlen(face->family_name)+1); | 
		
	
		
			
				|  |  |  |  |       memcpy(&context->fonts[i].family, face->family_name, strlen(face->family_name)+1); | 
		
	
		
			
				|  |  |  |  |   context->fonts[index].family = malloc(strlen(face->family_name)+1); | 
		
	
		
			
				|  |  |  |  |   memcpy(&context->fonts[index].family, face->family_name, strlen(face->family_name)+1); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       context->fonts[i].style = malloc(strlen(face->style_name)+1); | 
		
	
		
			
				|  |  |  |  |       memcpy(&context->fonts[i].style, face->style_name, strlen(face->style_name)+1); | 
		
	
		
			
				|  |  |  |  |   context->fonts[index].style = malloc(strlen(face->style_name)+1); | 
		
	
		
			
				|  |  |  |  |   memcpy(&context->fonts[index].style, face->style_name, strlen(face->style_name)+1); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       *index = i; | 
		
	
		
			
				|  |  |  |  |       break; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   if(*index == 0xFFFFFFFF) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_OUT_OF_DEVICE_MEMORY; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   error = FT_Set_Pixel_Sizes(face, 0, size); | 
		
	
		
			
				|  |  |  |  |   if(error != FT_Err_Ok) { | 
		
	
	
		
			
				
					|  |  |  | @ -703,16 +692,16 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |   info.width = max_width; | 
		
	
		
			
				|  |  |  |  |   info.height = max_height; | 
		
	
		
			
				|  |  |  |  |   info.num_symbols = symbol_count; | 
		
	
		
			
				|  |  |  |  |   context->fonts[*index].num_symbols = symbol_count; | 
		
	
		
			
				|  |  |  |  |   context->fonts[index].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); | 
		
	
		
			
				|  |  |  |  |   context->fonts[*index].charmap = malloc(sizeof(uint32_t)*symbol_count); | 
		
	
		
			
				|  |  |  |  |   memcpy(context->fonts[*index].charmap, tmp_charmap, sizeof(uint32_t)*symbol_count); | 
		
	
		
			
				|  |  |  |  |   context->fonts[index].charmap = malloc(sizeof(uint32_t)*symbol_count); | 
		
	
		
			
				|  |  |  |  |   memcpy(context->fonts[index].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, context->fonts[*index].charmap[i]); | 
		
	
		
			
				|  |  |  |  |     glyph_index = FT_Get_Char_Index(face, context->fonts[index].charmap[i]); | 
		
	
		
			
				|  |  |  |  |     FT_Load_Glyph(face, glyph_index, load_flags); | 
		
	
		
			
				|  |  |  |  |     symbols[i].width = (float)face->glyph->bitmap.width/(float)max_width; | 
		
	
		
			
				|  |  |  |  |     symbols[i].height = (float)face->glyph->bitmap.rows/(float)max_height; | 
		
	
	
		
			
				
					|  |  |  | @ -735,7 +724,7 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUSymbol)*info.num_symbols, &context->fonts[*index].symbols, &context->fonts[*index].symbol_memory)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUSymbol)*info.num_symbols, &context->fonts[index].symbols, &context->fonts[index].symbol_memory)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageCreateInfo image_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 
		
	
	
		
			
				
					|  |  |  | @ -756,14 +745,14 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |     .usage = VMA_MEMORY_USAGE_GPU_ONLY, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vmaCreateImage(gpu->allocator, &image_info, &image_memory_info, &context->fonts[*index].image, &context->fonts[*index].image_memory, NULL)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vmaCreateImage(gpu->allocator, &image_info, &image_memory_info, &context->fonts[index].image, &context->fonts[index].image_memory, NULL)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkBuffer transfer; | 
		
	
		
			
				|  |  |  |  |   VmaAllocation transfer_memory; | 
		
	
		
			
				|  |  |  |  |   void* mapped; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(GPUFont) + image_size*info.num_symbols + sizeof(GPUSymbol)*info.num_symbols, &transfer, &transfer_memory, &mapped)); | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  | 	info.symbol_list = buffer_address(gpu->device, context->fonts[*index].symbols); | 
		
	
		
			
				|  |  |  |  | 	info.symbol_list = buffer_address(gpu->device, context->fonts[index].symbols); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   memcpy(mapped, images, image_size*info.num_symbols); | 
		
	
		
			
				|  |  |  |  |   memcpy(mapped + image_size*info.num_symbols, &info, sizeof(GPUFont)); | 
		
	
	
		
			
				
					|  |  |  | @ -773,12 +762,12 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |   free(symbols); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool); | 
		
	
		
			
				|  |  |  |  |   command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, *index*sizeof(GPUFont), sizeof(GPUFont)); | 
		
	
		
			
				|  |  |  |  |   command_copy_buffer(command_buffer, transfer, context->fonts[*index].symbols, image_size*info.num_symbols + sizeof(GPUFont), 0, sizeof(GPUSymbol)*info.num_symbols); | 
		
	
		
			
				|  |  |  |  |   command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, index*sizeof(GPUFont), sizeof(GPUFont)); | 
		
	
		
			
				|  |  |  |  |   command_copy_buffer(command_buffer, transfer, context->fonts[index].symbols, image_size*info.num_symbols + sizeof(GPUFont), 0, sizeof(GPUSymbol)*info.num_symbols); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageMemoryBarrier first_barrier = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[*index].image, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[index].image, | 
		
	
		
			
				|  |  |  |  |     .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 
		
	
		
			
				|  |  |  |  |     .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | 
		
	
	
		
			
				
					|  |  |  | @ -796,11 +785,11 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |     .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | 
		
	
		
			
				|  |  |  |  |     .imageExtent = image_info.extent, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   vkCmdCopyBufferToImage(command_buffer, transfer, context->fonts[*index].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); | 
		
	
		
			
				|  |  |  |  |   vkCmdCopyBufferToImage(command_buffer, transfer, context->fonts[index].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageMemoryBarrier second_barrier = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[*index].image, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[index].image, | 
		
	
		
			
				|  |  |  |  |     .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | 
		
	
	
		
			
				
					|  |  |  | @ -819,7 +808,7 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageViewCreateInfo view_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[*index].image, | 
		
	
		
			
				|  |  |  |  |     .image = context->fonts[index].image, | 
		
	
		
			
				|  |  |  |  |     .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | 
		
	
		
			
				|  |  |  |  |     .format = VK_FORMAT_R8G8B8A8_SRGB, | 
		
	
		
			
				|  |  |  |  |     .subresourceRange = { | 
		
	
	
		
			
				
					|  |  |  | @ -830,7 +819,7 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |       .baseArrayLayer = 0, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkCreateImageView(gpu->device, &view_info, NULL, &context->fonts[*index].view)) | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkCreateImageView(gpu->device, &view_info, NULL, &context->fonts[index].view)) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkSamplerCreateInfo sampler_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | 
		
	
	
		
			
				
					|  |  |  | @ -840,15 +829,15 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |     .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, | 
		
	
		
			
				|  |  |  |  |     .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkCreateSampler(gpu->device, &sampler_info, NULL, &context->fonts[*index].sampler)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkCreateSampler(gpu->device, &sampler_info, NULL, &context->fonts[index].sampler)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkDescriptorImageInfo desc_sampler_info = { | 
		
	
		
			
				|  |  |  |  |     .sampler = context->fonts[*index].sampler, | 
		
	
		
			
				|  |  |  |  |     .sampler = context->fonts[index].sampler, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkDescriptorImageInfo desc_texture_info = { | 
		
	
		
			
				|  |  |  |  |     .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .imageView = context->fonts[*index].view, | 
		
	
		
			
				|  |  |  |  |     .imageView = context->fonts[index].view, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkWriteDescriptorSet descriptor_writes[] = { | 
		
	
	
		
			
				
					|  |  |  | @ -856,7 +845,7 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 
		
	
		
			
				|  |  |  |  |       .dstSet = context->font_textures, | 
		
	
		
			
				|  |  |  |  |       .dstBinding = 0, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = *index, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = index, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .pImageInfo = &desc_texture_info, | 
		
	
	
		
			
				
					|  |  |  | @ -865,7 +854,7 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 
		
	
		
			
				|  |  |  |  |       .dstSet = context->font_samplers, | 
		
	
		
			
				|  |  |  |  |       .dstBinding = 0, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = *index, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = index, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .pImageInfo = &desc_sampler_info, | 
		
	
	
		
			
				
					|  |  |  | @ -1066,6 +1055,10 @@ VkResult create_ui_context( | 
		
	
		
			
				|  |  |  |  |     UIContext* context) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  |   if(FT_Init_FreeType(&context->freetype) != FT_Err_Ok) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUUIContext), &context->context, &context->context_memory));  | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUFont)*max_fonts, &context->font_infos, &context->font_infos_memory));  | 
		
	
	
		
			
				
					|  |  |  | @ -1113,13 +1106,13 @@ VkResult map_string( | 
		
	
		
			
				|  |  |  |  |     const char * text, | 
		
	
		
			
				|  |  |  |  |     uint32_t* buffer, | 
		
	
		
			
				|  |  |  |  |     uint32_t offset, | 
		
	
		
			
				|  |  |  |  |     uint32_t* charmap, | 
		
	
		
			
				|  |  |  |  |     uint32_t charmap_size) { | 
		
	
		
			
				|  |  |  |  |     uint32_t font, | 
		
	
		
			
				|  |  |  |  |     UIContext* context) { | 
		
	
		
			
				|  |  |  |  |   size_t i = 0; | 
		
	
		
			
				|  |  |  |  |   while(text[i] != '\0') { | 
		
	
		
			
				|  |  |  |  |     uint32_t mapped = 0xFFFFFFFF; | 
		
	
		
			
				|  |  |  |  |     for(uint32_t j = 0; j < charmap_size; j++) { | 
		
	
		
			
				|  |  |  |  |       if(charmap[j] == (uint32_t)text[i]) { | 
		
	
		
			
				|  |  |  |  |     for(uint32_t j = 0; j < context->fonts[font].num_symbols; j++) { | 
		
	
		
			
				|  |  |  |  |       if(context->fonts[font].charmap[j] == (uint32_t)text[i]) { | 
		
	
		
			
				|  |  |  |  |         mapped = j; | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
	
		
			
				
					|  |  |  | 
 |