| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -52,18 +52,37 @@ typedef struct AllocatedBufferStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkDeviceMemory memory;
 | 
					 | 
					 | 
					 | 
					  VkDeviceMemory memory;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} AllocatedBuffer;
 | 
					 | 
					 | 
					 | 
					} AllocatedBuffer;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					typedef struct MaterialStruct {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkPipelineLayout pipeline_layout;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkPipeline       pipeline;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} Material;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					typedef struct MeshStruct {
 | 
					 | 
					 | 
					 | 
					typedef struct MeshStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint32_t vertex_count;
 | 
					 | 
					 | 
					 | 
					  uint32_t vertex_count;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  AllocatedBuffer vertex_buffer;
 | 
					 | 
					 | 
					 | 
					  AllocatedBuffer vertex_buffer;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint32_t index_count;
 | 
					 | 
					 | 
					 | 
					  uint32_t index_count;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  AllocatedBuffer index_buffer;
 | 
					 | 
					 | 
					 | 
					  AllocatedBuffer index_buffer;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  void* data;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} Mesh;
 | 
					 | 
					 | 
					 | 
					} Mesh;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					typedef void (*MaterialBindFunc)(VkCommandBuffer, void*);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					typedef void (*MeshBindFunc)(Mesh, VkCommandBuffer, void*);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					typedef struct MaterialStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkPipelineLayout pipeline_layout;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkPipeline       pipeline;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  MaterialBindFunc material_bind;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  MeshBindFunc     mesh_bind;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  void* data;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} Material;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					typedef struct TextureMaterialDataStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // Store pool to allocate new texture descriptor sets
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} TextureMaterialData;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					typedef struct TextureMeshDataStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // Store allocated texture descriptor set
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} TextureMeshData;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					typedef struct VulkanContextStruct {
 | 
					 | 
					 | 
					 | 
					typedef struct VulkanContextStruct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkInstance instance;
 | 
					 | 
					 | 
					 | 
					  VkInstance instance;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkDebugUtilsMessengerEXT debug_messenger;
 | 
					 | 
					 | 
					 | 
					  VkDebugUtilsMessengerEXT debug_messenger;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -190,7 +209,7 @@ GLFWwindow* init_window(int width, int height) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  glfwSetErrorCallback(glfw_error);
 | 
					 | 
					 | 
					 | 
					  glfwSetErrorCallback(glfw_error);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
 | 
					 | 
					 | 
					 | 
					  glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
 | 
					 | 
					 | 
					 | 
					  glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  GLFWwindow* window = glfwCreateWindow(width, height, "Vulkan window", 0, 0);
 | 
					 | 
					 | 
					 | 
					  GLFWwindow* window = glfwCreateWindow(width, height, "Vulkan window", 0, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1188,18 +1207,84 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
 | 
					 | 
					 | 
					 | 
					void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer};
 | 
					 | 
					 | 
					 | 
					  VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkDeviceSize offsets[] = {0};
 | 
					 | 
					 | 
					 | 
					  VkDeviceSize offsets[] = {0};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
 | 
					 | 
					 | 
					 | 
					  vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
 | 
					 | 
					 | 
					 | 
					  vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
 | 
					 | 
					 | 
					 | 
					  vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    vkDestroyImageView(context->device, context->swapchain_image_views[i], 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  vkDestroySwapchainKHR(context->device, context->swapchain, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_images);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_image_views);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_framebuffers);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_details.formats);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  free(context->swapchain_details.present_modes);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  context->swapchain_extent = new_extent;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  SwapchainDetails swapchain_details = get_swapchain_details(context->physical_device, context->surface);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(swapchain_details.formats == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain_details = swapchain_details;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  context->swapchain_format = choose_swapchain_format(context->swapchain_details);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  context->swapchain_present_mode = choose_present_mode(context->swapchain_details);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  context->swapchain_extent = choose_swapchain_extent(context->swapchain_details);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkSwapchainKHR swapchain = create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->queue_indices, context->swapchain);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(swapchain == VK_NULL_HANDLE) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain = VK_NULL_HANDLE;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return VK_ERROR_INITIALIZATION_FAILED;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain = swapchain;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  SwapchainImages swapchain_images = get_swapchain_images(context->device, context->swapchain);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(swapchain_images.count == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return VK_ERROR_INITIALIZATION_FAILED;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain_images = swapchain_images.images;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain_image_count = swapchain_images.count;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkImageView* image_views = create_image_views(context->device, context->swapchain_image_count, context->swapchain_images, context->swapchain_format);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(image_views == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return VK_ERROR_INITIALIZATION_FAILED;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain_image_views = image_views;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->render_pass, context->swapchain_extent);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(framebuffers == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return VK_ERROR_INITIALIZATION_FAILED;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    context->swapchain_framebuffers = framebuffers;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  return VK_SUCCESS;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
 | 
					 | 
					 | 
					 | 
					void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
 | 
					 | 
					 | 
					 | 
					  vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &scene_ubo_descriptor, 0, 0);
 | 
					 | 
					 | 
					 | 
					  vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &scene_ubo_descriptor, 0, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(material.material_bind != 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    material.material_bind(command_buffer, material.data);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < mesh_count; i++) {
 | 
					 | 
					 | 
					 | 
					  for(uint32_t i = 0; i < mesh_count; i++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if(material.mesh_bind != 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      material.mesh_bind(meshes[i], command_buffer, material.data);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    record_command_buffer_mesh(meshes[i], command_buffer);
 | 
					 | 
					 | 
					 | 
					    record_command_buffer_mesh(meshes[i], command_buffer);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1341,7 +1426,21 @@ Mesh load_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex*
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return mesh;
 | 
					 | 
					 | 
					 | 
					  return mesh;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					Material create_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages, VkDescriptorSetLayout scene_ubo_layout, uint32_t set_count, VkDescriptorSetLayout* set_layouts, uint32_t pcr_count, VkPushConstantRange* pcrs) {
 | 
					 | 
					 | 
					 | 
					Material create_material(
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkDevice device,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkExtent2D extent,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkRenderPass render_pass,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    uint32_t shader_stage_count,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkPipelineShaderStageCreateInfo* shader_stages,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkDescriptorSetLayout scene_ubo_layout,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    uint32_t set_count,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkDescriptorSetLayout* set_layouts,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    uint32_t pcr_count,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkPushConstantRange* pcrs,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    MaterialBindFunc material_bind,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    MeshBindFunc mesh_bind,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    void* data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    ) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  Material zero_material = {
 | 
					 | 
					 | 
					 | 
					  Material zero_material = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .pipeline = VK_NULL_HANDLE,
 | 
					 | 
					 | 
					 | 
					    .pipeline = VK_NULL_HANDLE,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  };
 | 
					 | 
					 | 
					 | 
					  };
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1372,8 +1471,6 @@ Material create_material(VkDevice device, VkExtent2D extent, VkRenderPass render
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    free(all_pcrs);
 | 
					 | 
					 | 
					 | 
					    free(all_pcrs);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return zero_material;
 | 
					 | 
					 | 
					 | 
					    return zero_material;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(all_layouts);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  free(all_pcrs);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages);
 | 
					 | 
					 | 
					 | 
					  VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(pipeline == VK_NULL_HANDLE) {
 | 
					 | 
					 | 
					 | 
					  if(pipeline == VK_NULL_HANDLE) {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1383,6 +1480,9 @@ Material create_material(VkDevice device, VkExtent2D extent, VkRenderPass render
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  Material material = {
 | 
					 | 
					 | 
					 | 
					  Material material = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .pipeline_layout = pipeline_layout,
 | 
					 | 
					 | 
					 | 
					    .pipeline_layout = pipeline_layout,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    .pipeline = pipeline,
 | 
					 | 
					 | 
					 | 
					    .pipeline = pipeline,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .material_bind = material_bind,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .mesh_bind = mesh_bind,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    .data = data,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  };
 | 
					 | 
					 | 
					 | 
					  };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return material;
 | 
					 | 
					 | 
					 | 
					  return material;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1637,7 +1737,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  shader_stages[1].module = frag_shader;
 | 
					 | 
					 | 
					 | 
					  shader_stages[1].module = frag_shader;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  shader_stages[1].pName = "main";
 | 
					 | 
					 | 
					 | 
					  shader_stages[1].pName = "main";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0);
 | 
					 | 
					 | 
					 | 
					  Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0, 0, 0, 0);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
 | 
					 | 
					 | 
					 | 
					  if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create simple mesh material\n");
 | 
					 | 
					 | 
					 | 
					    fprintf(stderr, "failed to create simple mesh material\n");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return 0;
 | 
					 | 
					 | 
					 | 
					    return 0;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1666,11 +1766,18 @@ struct {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool down: 1;
 | 
					 | 
					 | 
					 | 
					  bool down: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool turn_left: 1;
 | 
					 | 
					 | 
					 | 
					  bool turn_left: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool turn_right: 1;
 | 
					 | 
					 | 
					 | 
					  bool turn_right: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  bool turn_up: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  bool turn_down: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} key_flags = {
 | 
					 | 
					 | 
					 | 
					} key_flags = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  .forward = false,
 | 
					 | 
					 | 
					 | 
					  .forward = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  .backward = false,
 | 
					 | 
					 | 
					 | 
					  .backward = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  .left = false,
 | 
					 | 
					 | 
					 | 
					  .left = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  .right = false,
 | 
					 | 
					 | 
					 | 
					  .right = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  .turn_left = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  .turn_right = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  .turn_up = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  .turn_down = false,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
 | 
					 | 
					 | 
					 | 
					void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1742,6 +1849,22 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      key_flags.turn_left = false;
 | 
					 | 
					 | 
					 | 
					      key_flags.turn_left = false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    break;
 | 
					 | 
					 | 
					 | 
					    break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  case GLFW_KEY_UP:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if(action == GLFW_PRESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      key_flags.turn_up = true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if(action == GLFW_RELEASE) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      key_flags.turn_up = false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  case GLFW_KEY_DOWN:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if(action == GLFW_PRESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      key_flags.turn_down = true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if(action == GLFW_RELEASE) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      key_flags.turn_down = false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1801,7 +1924,7 @@ VkResult update_scene_ubo(void** buffers, uint32_t frame_index, vec3 world_posit
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return VK_SUCCESS;
 | 
					 | 
					 | 
					 | 
					  return VK_SUCCESS;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					VkResult draw_frame(VulkanContext* context) {
 | 
					 | 
					 | 
					 | 
					VkResult draw_frame(GLFWwindow* window, VulkanContext* context) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  update_scene_ubo(context->scene_ubo_ptrs, context->current_frame, world_position, &rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01);
 | 
					 | 
					 | 
					 | 
					  update_scene_ubo(context->scene_ubo_ptrs, context->current_frame, world_position, &rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  VkResult result;
 | 
					 | 
					 | 
					 | 
					  VkResult result;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1810,13 +1933,19 @@ VkResult draw_frame(VulkanContext* context) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return result;
 | 
					 | 
					 | 
					 | 
					    return result;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]);
 | 
					 | 
					 | 
					 | 
					  uint32_t image_index;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					  result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, context->image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    int width, height;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    glfwGetWindowSize(window, &width, &height);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    VkExtent2D window_extent = {width, height};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recreate_swap_chain(context, window_extent);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    return result;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return result;
 | 
					 | 
					 | 
					 | 
					    return result;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint32_t image_index;
 | 
					 | 
					 | 
					 | 
					  result = vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, context->image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
					 | 
					 | 
					 | 
					  if(result != VK_SUCCESS) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return result;
 | 
					 | 
					 | 
					 | 
					    return result;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1866,7 +1995,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  while(!glfwWindowShouldClose(window)) {
 | 
					 | 
					 | 
					 | 
					  while(!glfwWindowShouldClose(window)) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    glfwPollEvents();
 | 
					 | 
					 | 
					 | 
					    glfwPollEvents();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    draw_frame(context);
 | 
					 | 
					 | 
					 | 
					    draw_frame(window, context);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    context->current_frame += 1;
 | 
					 | 
					 | 
					 | 
					    context->current_frame += 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if(context->current_frame >= context->max_frames_in_flight) {
 | 
					 | 
					 | 
					 | 
					    if(context->current_frame >= context->max_frames_in_flight) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      context->current_frame = 0;
 | 
					 | 
					 | 
					 | 
					      context->current_frame = 0;
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |