| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -316,6 +316,26 @@ void object_update_mappings(Material material, Object object, uint32_t frame_num
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  map_iterator_free(mapping_iterator);
 | 
					 | 
					 | 
					 | 
					  map_iterator_free(mapping_iterator);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					VkSemaphore* create_semaphores(VkDevice device, VkSemaphoreCreateFlags flags, uint32_t count) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkSemaphore* semaphores = malloc(sizeof(VkSemaphore)*count);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(semaphores == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkSemaphoreCreateInfo semaphore_info = {};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  semaphore_info.flags = flags;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < count; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkResult result = vkCreateSemaphore(device, &semaphore_info, 0, &semaphores[i]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      free(semaphores);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return semaphores;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkFormat find_depth_format(VkPhysicalDevice physical_device, uint32_t num_requested, VkFormat* requested, VkImageTiling tiling, VkFormatFeatureFlags features) {
 | 
					 | 
					 | 
					 | 
					VkFormat find_depth_format(VkPhysicalDevice physical_device, uint32_t num_requested, VkFormat* requested, VkImageTiling tiling, VkFormatFeatureFlags features) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < num_requested; i++) {
 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < num_requested; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    VkFormatProperties properties;
 | 
					 | 
					 | 
					 | 
					    VkFormatProperties properties;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -763,7 +783,6 @@ VkSwapchainKHR create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPr
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  swapchain_info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
 | 
					 | 
					 | 
					 | 
					  swapchain_info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  swapchain_info.presentMode = present_mode;
 | 
					 | 
					 | 
					 | 
					  swapchain_info.presentMode = present_mode;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  swapchain_info.clipped = VK_TRUE;
 | 
					 | 
					 | 
					 | 
					  swapchain_info.clipped = VK_TRUE;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  swapchain_info.oldSwapchain = old_swapchain;
 | 
					 | 
					 | 
					 | 
					  swapchain_info.oldSwapchain = old_swapchain;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkSwapchainKHR swapchain;
 | 
					 | 
					 | 
					 | 
					  VkSwapchainKHR swapchain;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1167,7 +1186,7 @@ VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQu
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
 | 
					 | 
					 | 
					 | 
					  return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family) {
 | 
					 | 
					 | 
					 | 
					VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
 | 
					 | 
					 | 
					 | 
					  VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkImageMemoryBarrier barrier = {
 | 
					 | 
					 | 
					 | 
					  VkImageMemoryBarrier barrier = {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1178,7 +1197,7 @@ VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .dstQueueFamilyIndex = dest_family,
 | 
					 | 
					 | 
					 | 
					    .dstQueueFamilyIndex = dest_family,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .image = image,
 | 
					 | 
					 | 
					 | 
					    .image = image,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .subresourceRange = {
 | 
					 | 
					 | 
					 | 
					    .subresourceRange = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
 | 
					 | 
					 | 
					 | 
					      .aspectMask = aspect_flags,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      .levelCount = 1,
 | 
					 | 
					 | 
					 | 
					      .levelCount = 1,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      .layerCount = 1,
 | 
					 | 
					 | 
					 | 
					      .layerCount = 1,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      .baseMipLevel = 0,
 | 
					 | 
					 | 
					 | 
					      .baseMipLevel = 0,
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1292,7 +1311,7 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return ret;
 | 
					 | 
					 | 
					 | 
					    return ret;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image.image, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, transfer_family, transfer_family);
 | 
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image.image, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, transfer_family, transfer_family, VK_IMAGE_ASPECT_COLOR_BIT);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1306,14 +1325,14 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return ret;
 | 
					 | 
					 | 
					 | 
					    return ret;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family);
 | 
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family, VK_IMAGE_ASPECT_COLOR_BIT);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return ret;
 | 
					 | 
					 | 
					 | 
					    return ret;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, graphics_pool, graphics_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family);
 | 
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(device, graphics_pool, graphics_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family, VK_IMAGE_ASPECT_COLOR_BIT);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
					 | 
					 | 
					 | 
					    deallocate_buffer(device, staging);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
					 | 
					 | 
					 | 
					    deallocate_image(device, image);
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1602,17 +1621,27 @@ int create_depth_image(VulkanContext* context) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    context->depth_image_view = depth_image_view;
 | 
					 | 
					 | 
					 | 
					    context->depth_image_view = depth_image_view;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  result = command_transition_image_layout(context->device, context->extra_graphics_pool, context->queues.graphics, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, context->depth_image, 0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, VK_IMAGE_ASPECT_DEPTH_BIT);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to transition depth image\n");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return 5;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return 0;
 | 
					 | 
					 | 
					 | 
					  return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkResult recreate_swap_chain(VulkanContext* context) {
 | 
					 | 
					 | 
					 | 
					VkResult recreate_swapchain(VulkanContext* context) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
 | 
					 | 
					 | 
					 | 
					    vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    vkDestroyImageView(context->device, context->swapchain_image_views[i], 0);
 | 
					 | 
					 | 
					 | 
					    vkDestroyImageView(context->device, context->swapchain_image_views[i], 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkDestroySwapchainKHR(context->device, context->swapchain, 0);
 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < context->max_frames_in_flight; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(context->swapchain_images);
 | 
					 | 
					 | 
					 | 
					    vkDestroySemaphore(context->device, context->image_available_semaphores[i], 0);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  //vkDestroySwapchainKHR(context->device, context->swapchain, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  //free(context->swapchain_images);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(context->swapchain_image_views);
 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_image_views);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(context->swapchain_framebuffers);
 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_framebuffers);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(context->swapchain_details.formats);
 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_details.formats);
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1665,6 +1694,14 @@ VkResult recreate_swap_chain(VulkanContext* context) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    context->swapchain_framebuffers = framebuffers;
 | 
					 | 
					 | 
					 | 
					    context->swapchain_framebuffers = framebuffers;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, context->max_frames_in_flight);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(ia_semaphores == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create vulkan image available semaphores\n");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->image_available_semaphores = ia_semaphores;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return VK_SUCCESS;
 | 
					 | 
					 | 
					 | 
					  return VK_SUCCESS;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1787,26 +1824,6 @@ VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_p
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return command_buffers;
 | 
					 | 
					 | 
					 | 
					  return command_buffers;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkSemaphore* create_semaphores(VkDevice device, VkSemaphoreCreateFlags flags, uint32_t count) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkSemaphore* semaphores = malloc(sizeof(VkSemaphore)*count);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(semaphores == 0) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return 0;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkSemaphoreCreateInfo semaphore_info = {};
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  semaphore_info.flags = flags;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < count; i++) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    VkResult result = vkCreateSemaphore(device, &semaphore_info, 0, &semaphores[i]);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      free(semaphores);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return 0;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return semaphores;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count) {
 | 
					 | 
					 | 
					 | 
					VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkFence* fences = malloc(sizeof(VkFence)*count);
 | 
					 | 
					 | 
					 | 
					  VkFence* fences = malloc(sizeof(VkFence)*count);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(fences == 0) {
 | 
					 | 
					 | 
					 | 
					  if(fences == 0) {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2406,6 +2423,18 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    context->depth_format = depth_format;
 | 
					 | 
					 | 
					 | 
					    context->depth_format = depth_format;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkCommandPoolCreateInfo extra_pool_info = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .queueFamilyIndex = context->queue_indices.graphics_family,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  result = vkCreateCommandPool(context->device, &extra_pool_info, 0, &context->extra_graphics_pool);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create extra graphics command pool\n");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(create_depth_image(context) != 0) {
 | 
					 | 
					 | 
					 | 
					  if(create_depth_image(context) != 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create depth image\n");
 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create depth image\n");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return 0;
 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2465,14 +2494,6 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    context->swapchain_command_buffers = swapchain_command_buffers;
 | 
					 | 
					 | 
					 | 
					    context->swapchain_command_buffers = swapchain_command_buffers;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkCommandPoolCreateInfo extra_pool_info = {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .queueFamilyIndex = context->queue_indices.graphics_family,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  };
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = vkCreateCommandPool(context->device, &extra_pool_info, 0, &context->extra_graphics_pool);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight);
 | 
					 | 
					 | 
					 | 
					  VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(ia_semaphores == 0) {
 | 
					 | 
					 | 
					 | 
					  if(ia_semaphores == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create vulkan image available semaphores\n");
 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create vulkan image available semaphores\n");
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3261,7 +3282,8 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    VkResult result = draw_frame(context, &scene, sizeof(materials)/sizeof(Material), materials, objects_counts, objects);
 | 
					 | 
					 | 
					 | 
					    VkResult result = draw_frame(context, &scene, sizeof(materials)/sizeof(Material), materials, objects_counts, objects);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
 | 
					 | 
					 | 
					 | 
					    if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      recreate_swap_chain(context);
 | 
					 | 
					 | 
					 | 
					      vkDeviceWaitIdle(context->device);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      recreate_swapchain(context);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					    } else if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      fprintf(stderr, "draw_frame error %d\n", result);
 | 
					 | 
					 | 
					 | 
					      fprintf(stderr, "draw_frame error %d\n", result);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return;
 | 
					 | 
					 | 
					 | 
					      return;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |