|  |  |  | @ -8,6 +8,7 @@ | 
		
	
		
			
				|  |  |  |  | #include "string.h" | 
		
	
		
			
				|  |  |  |  | #include "vk_mem_alloc.h" | 
		
	
		
			
				|  |  |  |  | #include "vulkan/vulkan_core.h" | 
		
	
		
			
				|  |  |  |  | #include "spng.h" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkShaderModule load_shader_file(const char* path, VkDevice device) { | 
		
	
		
			
				|  |  |  |  |   FILE* file; | 
		
	
	
		
			
				
					|  |  |  | @ -366,6 +367,134 @@ VkResult create_layer( | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult load_texture( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VmaAllocator allocator, | 
		
	
		
			
				|  |  |  |  |     UIContextStorage* context, | 
		
	
		
			
				|  |  |  |  |     uint32_t index, | 
		
	
		
			
				|  |  |  |  |     VkCommandPool transfer_pool, | 
		
	
		
			
				|  |  |  |  |     Queue transfer_queue, | 
		
	
		
			
				|  |  |  |  |     const char* png_path, | 
		
	
		
			
				|  |  |  |  |     TextureStorage* memory) { | 
		
	
		
			
				|  |  |  |  |   spng_ctx* spng = spng_ctx_new(0); | 
		
	
		
			
				|  |  |  |  |   if(spng == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   FILE* png_file = fopen(png_path, "rb"); | 
		
	
		
			
				|  |  |  |  |   if(png_file == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   fseek(png_file, 0, SEEK_END); | 
		
	
		
			
				|  |  |  |  |   int error = fseek(png_file, 0, SEEK_END); | 
		
	
		
			
				|  |  |  |  |   if(error != 0) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   size_t png_size = ftell(png_file); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   error = fseek(png_file, 0, SEEK_SET); | 
		
	
		
			
				|  |  |  |  |   if(error != 0) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   void* png = malloc(png_size); | 
		
	
		
			
				|  |  |  |  |   if(png == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   size_t read = fread(png, png_size, 1, png_file); | 
		
	
		
			
				|  |  |  |  |   if(read != png_size) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   fclose(png_file); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   spng_set_png_buffer(spng, png, png_size); | 
		
	
		
			
				|  |  |  |  |   size_t out_size; | 
		
	
		
			
				|  |  |  |  |   spng_decoded_image_size(spng, SPNG_FMT_RGBA8, &out_size); | 
		
	
		
			
				|  |  |  |  |   struct spng_ihdr ihdr; | 
		
	
		
			
				|  |  |  |  |   spng_get_ihdr(spng, &ihdr); | 
		
	
		
			
				|  |  |  |  |   void* image_buffer = malloc(out_size); | 
		
	
		
			
				|  |  |  |  |   if(image_buffer == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_UNKNOWN; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   spng_decode_image(spng, image_buffer, out_size, SPNG_FMT_RGBA8, 0); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageCreateInfo image_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | 
		
	
		
			
				|  |  |  |  |     .extent = { | 
		
	
		
			
				|  |  |  |  |       .width = ihdr.width, | 
		
	
		
			
				|  |  |  |  |       .height = ihdr.height, | 
		
	
		
			
				|  |  |  |  |       .depth = 1, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     .mipLevels = 1, | 
		
	
		
			
				|  |  |  |  |     .arrayLayers = 1, | 
		
	
		
			
				|  |  |  |  |     .format = VK_FORMAT_R8G8B8A8_SRGB, | 
		
	
		
			
				|  |  |  |  |     .tiling = VK_IMAGE_TILING_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 
		
	
		
			
				|  |  |  |  |     .samples = VK_SAMPLE_COUNT_1_BIT, | 
		
	
		
			
				|  |  |  |  |     .imageType = VK_IMAGE_TYPE_2D, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VmaAllocationCreateInfo memory_info = { | 
		
	
		
			
				|  |  |  |  |     .usage = VMA_MEMORY_USAGE_GPU_ONLY, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkBuffer transfer; | 
		
	
		
			
				|  |  |  |  |   VmaAllocation transfer_memory; | 
		
	
		
			
				|  |  |  |  |   void* mapped; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vmaCreateImage(allocator, &image_info, &memory_info, &memory->image, &memory->image_memory, NULL)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_transfer_buffer(allocator, sizeof(uint32_t)*ihdr.width*ihdr.height, &transfer, &transfer_memory, &mapped)); | 
		
	
		
			
				|  |  |  |  |   memcpy(mapped, image_buffer, sizeof(uint32_t)*ihdr.height*ihdr.width); | 
		
	
		
			
				|  |  |  |  |   VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageMemoryBarrier first_barrier = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 
		
	
		
			
				|  |  |  |  |     .image = memory->image, | 
		
	
		
			
				|  |  |  |  |     .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 
		
	
		
			
				|  |  |  |  |     .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |     .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | 
		
	
		
			
				|  |  |  |  |     .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | 
		
	
		
			
				|  |  |  |  |     .subresourceRange = { | 
		
	
		
			
				|  |  |  |  |       .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | 
		
	
		
			
				|  |  |  |  |       .levelCount = 1, | 
		
	
		
			
				|  |  |  |  |       .layerCount = 1, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     .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 = { | 
		
	
		
			
				|  |  |  |  |     .imageExtent = { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   vkCmdCopyBufferToImage(command_buffer, transfer, memory->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageMemoryBarrier second_barrier = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); | 
		
	
		
			
				|  |  |  |  |   vkQueueWaitIdle(transfer_queue.handle); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   destroy_transfer_buffer(allocator, transfer, transfer_memory); | 
		
	
		
			
				|  |  |  |  |   free(image_buffer); | 
		
	
		
			
				|  |  |  |  |   free(png); | 
		
	
		
			
				|  |  |  |  |   spng_ctx_free(spng); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult load_font( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VmaAllocator allocator, | 
		
	
	
		
			
				
					|  |  |  | @ -462,7 +591,6 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkImageCreateInfo image_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 
		
	
		
			
				|  |  |  |  |     .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | 
		
	
		
			
				|  |  |  |  |     .extent.depth  = 1, | 
		
	
		
			
				|  |  |  |  |     .extent.width  = info.width, | 
		
	
	
		
			
				
					|  |  |  | @ -564,8 +692,8 @@ VkResult load_font( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkSamplerCreateInfo sampler_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .magFilter = VK_FILTER_CUBIC_IMG, | 
		
	
		
			
				|  |  |  |  |     .minFilter = VK_FILTER_CUBIC_IMG, | 
		
	
		
			
				|  |  |  |  |     .magFilter = VK_FILTER_NEAREST, | 
		
	
		
			
				|  |  |  |  |     .minFilter = VK_FILTER_NEAREST, | 
		
	
		
			
				|  |  |  |  |     .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, | 
		
	
		
			
				|  |  |  |  |     .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, | 
		
	
		
			
				|  |  |  |  |     .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, | 
		
	
	
		
			
				
					|  |  |  | @ -754,8 +882,10 @@ VkResult create_ui_context( | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContext), &transfer, &transfer_memory, (void**)&mapped)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   memory->data.font_infos = buffer_address(device, memory->font_infos); | 
		
	
		
			
				|  |  |  |  |   memory->data.scale[0] = window_scale[0] / swapchain_extent.width; | 
		
	
		
			
				|  |  |  |  |   memory->data.scale[1] = window_scale[1] / swapchain_extent.height; | 
		
	
		
			
				|  |  |  |  |   memory->data.screen[0] = window_scale[0] / swapchain_extent.width; | 
		
	
		
			
				|  |  |  |  |   memory->data.screen[1] = window_scale[1] / swapchain_extent.height; | 
		
	
		
			
				|  |  |  |  |   memory->data.scale[0] = window_scale[0]; | 
		
	
		
			
				|  |  |  |  |   memory->data.scale[1] = window_scale[1]; | 
		
	
		
			
				|  |  |  |  |   memcpy(mapped, &memory->data, sizeof(UIContext)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); | 
		
	
	
		
			
				
					|  |  |  | @ -793,6 +923,29 @@ void set_ui_rect( | 
		
	
		
			
				|  |  |  |  |   drawable->code = 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void set_ui_image( | 
		
	
		
			
				|  |  |  |  |     float x, | 
		
	
		
			
				|  |  |  |  |     float y, | 
		
	
		
			
				|  |  |  |  |     float width, | 
		
	
		
			
				|  |  |  |  |     float height, | 
		
	
		
			
				|  |  |  |  |     float r, | 
		
	
		
			
				|  |  |  |  |     float g, | 
		
	
		
			
				|  |  |  |  |     float b, | 
		
	
		
			
				|  |  |  |  |     float a, | 
		
	
		
			
				|  |  |  |  |     uint32_t index, | 
		
	
		
			
				|  |  |  |  |     UIDrawable* drawable) { | 
		
	
		
			
				|  |  |  |  |   drawable->pos[0] = x; | 
		
	
		
			
				|  |  |  |  |   drawable->pos[1] = y; | 
		
	
		
			
				|  |  |  |  |   drawable->size[0] = width; | 
		
	
		
			
				|  |  |  |  |   drawable->size[1] = height; | 
		
	
		
			
				|  |  |  |  |   drawable->color[0] = r; | 
		
	
		
			
				|  |  |  |  |   drawable->color[1] = g; | 
		
	
		
			
				|  |  |  |  |   drawable->color[2] = b; | 
		
	
		
			
				|  |  |  |  |   drawable->color[3] = a; | 
		
	
		
			
				|  |  |  |  |   drawable->type = 2; | 
		
	
		
			
				|  |  |  |  |   drawable->code = index; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void set_ui_string( | 
		
	
		
			
				|  |  |  |  |     float x, | 
		
	
		
			
				|  |  |  |  |     float y, | 
		
	
	
		
			
				
					|  |  |  | 
 |