|  |  |  | @ -52,7 +52,6 @@ GLFWwindow* init_window() { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   // TODO: recreate the framebuffer on resize
 | 
		
	
		
			
				|  |  |  |  |   glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   GLFWwindow* window = glfwCreateWindow(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT, "roleplay", 0, 0); | 
		
	
	
		
			
				
					|  |  |  | @ -61,7 +60,9 @@ GLFWwindow* init_window() { | 
		
	
		
			
				|  |  |  |  |   return window; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkShaderModule load_shader_file(const char* path, VkDevice device) { | 
		
	
		
			
				|  |  |  |  | VkShaderModule load_shader_file( | 
		
	
		
			
				|  |  |  |  |     const char* path, | 
		
	
		
			
				|  |  |  |  |     VkDevice device) { | 
		
	
		
			
				|  |  |  |  |   FILE* file; | 
		
	
		
			
				|  |  |  |  |   file = fopen(path, "rb"); | 
		
	
		
			
				|  |  |  |  |   if(file == 0) { | 
		
	
	
		
			
				
					|  |  |  | @ -104,7 +105,9 @@ VkShaderModule load_shader_file(const char* path, VkDevice device) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | bool check_validation_layers(const char ** layers, uint32_t num_layers) { | 
		
	
		
			
				|  |  |  |  | bool check_validation_layers( | 
		
	
		
			
				|  |  |  |  |     const char ** layers, | 
		
	
		
			
				|  |  |  |  |     uint32_t num_layers) { | 
		
	
		
			
				|  |  |  |  |   uint32_t layer_count; | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -195,7 +198,9 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( | 
		
	
		
			
				|  |  |  |  |   return VK_FALSE; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_debug_messenger(VkInstance instance, VkDebugUtilsMessengerEXT* debug_messenger) { | 
		
	
		
			
				|  |  |  |  | VkResult create_debug_messenger( | 
		
	
		
			
				|  |  |  |  |     VkInstance instance, | 
		
	
		
			
				|  |  |  |  |     VkDebugUtilsMessengerEXT* debug_messenger) { | 
		
	
		
			
				|  |  |  |  |   VkDebugUtilsMessengerCreateInfoEXT messenger_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, | 
		
	
		
			
				|  |  |  |  |     .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, | 
		
	
	
		
			
				
					|  |  |  | @ -212,7 +217,9 @@ VkResult create_debug_messenger(VkInstance instance, VkDebugUtilsMessengerEXT* d | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device) { | 
		
	
		
			
				|  |  |  |  | VkResult get_best_physical_device( | 
		
	
		
			
				|  |  |  |  |     VkInstance instance, | 
		
	
		
			
				|  |  |  |  |     VkPhysicalDevice* device) { | 
		
	
		
			
				|  |  |  |  |   uint32_t device_count = 0; | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkEnumeratePhysicalDevices(instance, &device_count, 0)); | 
		
	
	
		
			
				
					|  |  |  | @ -262,7 +269,13 @@ VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device) | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR surface, GPUQueue* graphics_queue, GPUQueue* present_queue, GPUQueue* transfer_queue, VkDevice* device) { | 
		
	
		
			
				|  |  |  |  | VkResult create_logical_device( | 
		
	
		
			
				|  |  |  |  |     VkPhysicalDevice physical_device, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceKHR surface, | 
		
	
		
			
				|  |  |  |  |     GPUQueue* graphics_queue, | 
		
	
		
			
				|  |  |  |  |     GPUQueue* present_queue, | 
		
	
		
			
				|  |  |  |  |     GPUQueue* transfer_queue, | 
		
	
		
			
				|  |  |  |  |     VkDevice* device) { | 
		
	
		
			
				|  |  |  |  |   if(graphics_queue == NULL || present_queue == NULL || transfer_queue == NULL || device == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_VALIDATION_FAILED_EXT; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -422,7 +435,11 @@ VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR su | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_memory_allocator(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, VmaAllocator* allocator) { | 
		
	
		
			
				|  |  |  |  | VkResult create_memory_allocator( | 
		
	
		
			
				|  |  |  |  |     VkInstance instance, | 
		
	
		
			
				|  |  |  |  |     VkPhysicalDevice physical_device, | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VmaAllocator* allocator) { | 
		
	
		
			
				|  |  |  |  |   VmaAllocatorCreateInfo allocator_create_info = { | 
		
	
		
			
				|  |  |  |  |     .vulkanApiVersion = VK_API_VERSION_1_2, | 
		
	
		
			
				|  |  |  |  |     .instance = instance, | 
		
	
	
		
			
				
					|  |  |  | @ -437,7 +454,10 @@ VkResult create_memory_allocator(VkInstance instance, VkPhysicalDevice physical_ | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult get_swapchain_details(VkPhysicalDevice physical_device, VkSurfaceKHR surface, SwapchainDetails* details) { | 
		
	
		
			
				|  |  |  |  | VkResult get_swapchain_details( | 
		
	
		
			
				|  |  |  |  |     VkPhysicalDevice physical_device, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceKHR surface, | 
		
	
		
			
				|  |  |  |  |     SwapchainDetails* details) { | 
		
	
		
			
				|  |  |  |  |   details->formats = 0; | 
		
	
		
			
				|  |  |  |  |   details->present_modes = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -495,13 +515,24 @@ VkExtent2D choose_swapchain_extent(SwapchainDetails swapchain_details) { | 
		
	
		
			
				|  |  |  |  |   return swapchain_details.capabilities.currentExtent; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentModeKHR present_mode, VkExtent2D extent, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR capabilities, uint32_t graphics_family_index, uint32_t present_family_index, VkSwapchainKHR* swapchain) { | 
		
	
		
			
				|  |  |  |  | VkResult create_swapchain( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceFormatKHR format, | 
		
	
		
			
				|  |  |  |  |     VkPresentModeKHR present_mode, | 
		
	
		
			
				|  |  |  |  |     VkExtent2D extent, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceKHR surface, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceCapabilitiesKHR capabilities, | 
		
	
		
			
				|  |  |  |  |     uint32_t graphics_family_index, | 
		
	
		
			
				|  |  |  |  |     uint32_t present_family_index, | 
		
	
		
			
				|  |  |  |  |     VkSwapchainKHR* swapchain) { | 
		
	
		
			
				|  |  |  |  |   uint32_t image_count = capabilities.minImageCount + 1; | 
		
	
		
			
				|  |  |  |  |   uint32_t max_images = capabilities.maxImageCount; | 
		
	
		
			
				|  |  |  |  |   if((max_images > 0) && (image_count > max_images)) { | 
		
	
		
			
				|  |  |  |  |     image_count = max_images; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkSwapchainKHR old_swapchain = *swapchain; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkSwapchainCreateInfoKHR swapchain_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, | 
		
	
		
			
				|  |  |  |  |     .surface = surface, | 
		
	
	
		
			
				
					|  |  |  | @ -515,7 +546,7 @@ VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentM | 
		
	
		
			
				|  |  |  |  |     .compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, | 
		
	
		
			
				|  |  |  |  |     .presentMode = present_mode, | 
		
	
		
			
				|  |  |  |  |     .clipped = VK_TRUE, | 
		
	
		
			
				|  |  |  |  |     .oldSwapchain = *swapchain, | 
		
	
		
			
				|  |  |  |  |     .oldSwapchain = old_swapchain, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   uint32_t queue_families[2] = {graphics_family_index, present_family_index}; | 
		
	
	
		
			
				
					|  |  |  | @ -536,7 +567,11 @@ VkResult create_swapchain(VkDevice device, VkSurfaceFormatKHR format, VkPresentM | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult get_swapchain_images(VkDevice device, VkSwapchainKHR swapchain, VkImage** images, uint32_t* image_count) { | 
		
	
		
			
				|  |  |  |  | VkResult get_swapchain_images( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkSwapchainKHR swapchain, | 
		
	
		
			
				|  |  |  |  |     VkImage** images, | 
		
	
		
			
				|  |  |  |  |     uint32_t* image_count) { | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(vkGetSwapchainImagesKHR(device, swapchain, image_count, 0)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -554,7 +589,12 @@ VkResult get_swapchain_images(VkDevice device, VkSwapchainKHR swapchain, VkImage | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_image_views(VkDevice device, uint32_t image_count, VkImage* images, VkSurfaceFormatKHR format, VkImageView** image_views) { | 
		
	
		
			
				|  |  |  |  | VkResult create_image_views( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     uint32_t image_count, | 
		
	
		
			
				|  |  |  |  |     VkImage* images, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceFormatKHR format, | 
		
	
		
			
				|  |  |  |  |     VkImageView** image_views) { | 
		
	
		
			
				|  |  |  |  |   *image_views = malloc(sizeof(VkImageView)*image_count); | 
		
	
		
			
				|  |  |  |  |   if(*image_views == 0) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_OUT_OF_HOST_MEMORY; | 
		
	
	
		
			
				
					|  |  |  | @ -591,7 +631,11 @@ VkResult create_image_views(VkDevice device, uint32_t image_count, VkImage* imag | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult find_depth_format(VkPhysicalDevice physical_device, VkImageTiling tiling, VkFormatFeatureFlags features, VkFormat* format) { | 
		
	
		
			
				|  |  |  |  | VkResult find_depth_format( | 
		
	
		
			
				|  |  |  |  |     VkPhysicalDevice physical_device, | 
		
	
		
			
				|  |  |  |  |     VkImageTiling tiling, | 
		
	
		
			
				|  |  |  |  |     VkFormatFeatureFlags features, | 
		
	
		
			
				|  |  |  |  |     VkFormat* format) { | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < depth_format_count; i++) { | 
		
	
		
			
				|  |  |  |  |     VkFormatProperties properties; | 
		
	
		
			
				|  |  |  |  |     vkGetPhysicalDeviceFormatProperties(physical_device, depth_formats[i], &properties); | 
		
	
	
		
			
				
					|  |  |  | @ -607,7 +651,11 @@ VkResult find_depth_format(VkPhysicalDevice physical_device, VkImageTiling tilin | 
		
	
		
			
				|  |  |  |  |   return VK_ERROR_VALIDATION_FAILED_EXT; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat depth_format, VkRenderPass* render_pass) { | 
		
	
		
			
				|  |  |  |  | VkResult create_render_pass( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkSurfaceFormatKHR format, | 
		
	
		
			
				|  |  |  |  |     VkFormat depth_format, | 
		
	
		
			
				|  |  |  |  |     VkRenderPass* render_pass) { | 
		
	
		
			
				|  |  |  |  |   VkAttachmentDescription attachments[] = { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .format = format.format, | 
		
	
	
		
			
				
					|  |  |  | @ -710,7 +758,14 @@ VkResult create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFormat | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_swapchain_framebuffers(VkDevice device, uint32_t image_count, VkImageView* image_views, VkImageView depth_image_view, VkRenderPass render_pass, VkExtent2D extent, VkFramebuffer** framebuffers) { | 
		
	
		
			
				|  |  |  |  | VkResult create_swapchain_framebuffers( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     uint32_t image_count, | 
		
	
		
			
				|  |  |  |  |     VkImageView* image_views, | 
		
	
		
			
				|  |  |  |  |     VkImageView depth_image_view, | 
		
	
		
			
				|  |  |  |  |     VkRenderPass render_pass, | 
		
	
		
			
				|  |  |  |  |     VkExtent2D extent, | 
		
	
		
			
				|  |  |  |  |     VkFramebuffer** framebuffers) { | 
		
	
		
			
				|  |  |  |  |   *framebuffers = malloc(sizeof(VkFramebuffer)*image_count); | 
		
	
		
			
				|  |  |  |  |   if(*framebuffers == 0) { | 
		
	
		
			
				|  |  |  |  |     return 0; | 
		
	
	
		
			
				
					|  |  |  | @ -778,7 +833,9 @@ VkSemaphore create_semaphore(VkDevice device) { | 
		
	
		
			
				|  |  |  |  |   return semaphore; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkFence create_fence(VkDevice device, VkFenceCreateFlags flags) { | 
		
	
		
			
				|  |  |  |  | VkFence create_fence( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkFenceCreateFlags flags) { | 
		
	
		
			
				|  |  |  |  |   VkFenceCreateInfo fence_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .flags = flags, | 
		
	
	
		
			
				
					|  |  |  | @ -793,7 +850,10 @@ VkFence create_fence(VkDevice device, VkFenceCreateFlags flags) { | 
		
	
		
			
				|  |  |  |  |   return fence; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_pool, uint32_t image_count)  { | 
		
	
		
			
				|  |  |  |  | VkCommandBuffer* create_command_buffers( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkCommandPool command_pool, | 
		
	
		
			
				|  |  |  |  |     uint32_t image_count)  { | 
		
	
		
			
				|  |  |  |  |   VkCommandBufferAllocateInfo alloc_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .commandPool = command_pool, | 
		
	
	
		
			
				
					|  |  |  | @ -814,7 +874,11 @@ VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_p | 
		
	
		
			
				|  |  |  |  |   return command_buffers; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_frame_context(VkDevice device, VmaAllocator allocator, VkCommandPool transfer_pool, FrameContext* frame) { | 
		
	
		
			
				|  |  |  |  | VkResult create_frame_context( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VmaAllocator allocator, | 
		
	
		
			
				|  |  |  |  |     VkCommandPool transfer_pool, | 
		
	
		
			
				|  |  |  |  |     FrameContext* frame) { | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   frame->ready = create_fence(device, VK_FENCE_CREATE_SIGNALED_BIT); | 
		
	
	
		
			
				
					|  |  |  | @ -852,7 +916,16 @@ VkResult create_frame_context(VkDevice device, VmaAllocator allocator, VkCommand | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult create_depth_image(VkDevice device, VkFormat depth_format, VkExtent2D swapchain_extent, VmaAllocator allocator, VkCommandPool extra_graphics_pool, GPUQueue graphics_queue, VkImage* depth_image, VmaAllocation* depth_image_memory, VkImageView* depth_image_view) { | 
		
	
		
			
				|  |  |  |  | VkResult create_depth_image( | 
		
	
		
			
				|  |  |  |  |     VkDevice device, | 
		
	
		
			
				|  |  |  |  |     VkFormat depth_format, | 
		
	
		
			
				|  |  |  |  |     VkExtent2D swapchain_extent, | 
		
	
		
			
				|  |  |  |  |     VmaAllocator allocator, | 
		
	
		
			
				|  |  |  |  |     VkCommandPool extra_graphics_pool, | 
		
	
		
			
				|  |  |  |  |     GPUQueue graphics_queue, | 
		
	
		
			
				|  |  |  |  |     VkImage* depth_image, | 
		
	
		
			
				|  |  |  |  |     VmaAllocation* depth_image_memory, | 
		
	
		
			
				|  |  |  |  |     VkImageView* depth_image_view) { | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  |     VkExtent3D depth_extent = { | 
		
	
		
			
				|  |  |  |  |     .width = swapchain_extent.width, | 
		
	
	
		
			
				
					|  |  |  | @ -956,30 +1029,76 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) { | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(create_frame_context(context->device, context->allocator, context->transfer_pool, &context->frame[i])); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_details(context->physical_device, context->surface, &context->swapchain_details)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_details( | 
		
	
		
			
				|  |  |  |  |         context->physical_device, | 
		
	
		
			
				|  |  |  |  |         context->surface, | 
		
	
		
			
				|  |  |  |  |         &context->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); | 
		
	
		
			
				|  |  |  |  |   context->framebuffer_recreated = true; | 
		
	
		
			
				|  |  |  |  |   context->swapchain = VK_NULL_HANDLE; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->graphics_queue.family, context->present_queue.family, &context->swapchain)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_images(context->device, context->swapchain, &context->swapchain_images, &context->swapchain_image_count)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_format, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_present_mode, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |         context->surface, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_details.capabilities, | 
		
	
		
			
				|  |  |  |  |         context->graphics_queue.family, | 
		
	
		
			
				|  |  |  |  |         context->present_queue.family, | 
		
	
		
			
				|  |  |  |  |         &context->swapchain)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_images( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->swapchain, | 
		
	
		
			
				|  |  |  |  |         &context->swapchain_images, | 
		
	
		
			
				|  |  |  |  |         &context->swapchain_image_count)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   context->swapchain_command_buffers = create_command_buffers(context->device, context->graphics_pool, context->swapchain_image_count); | 
		
	
		
			
				|  |  |  |  |   if(context->swapchain_command_buffers == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_VALIDATION_FAILED_EXT; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_image_views(context->device, context->swapchain_image_count, context->swapchain_images, context->swapchain_format, &context->swapchain_image_views)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(find_depth_format(context->physical_device, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, &context->depth_format)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_render_pass(context->device, context->swapchain_format, context->depth_format, &context->render_pass)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_depth_image(context->device, context->depth_format, context->swapchain_extent, context->allocator, context->extra_graphics_pool, context->graphics_queue, &context->depth_image, &context->depth_image_memory, &context->depth_image_view)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent, &context->swapchain_framebuffers)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_image_views( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_image_count, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_images, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_format, | 
		
	
		
			
				|  |  |  |  |         &context->swapchain_image_views)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(find_depth_format( | 
		
	
		
			
				|  |  |  |  |         context->physical_device, | 
		
	
		
			
				|  |  |  |  |         VK_IMAGE_TILING_OPTIMAL, | 
		
	
		
			
				|  |  |  |  |         VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, | 
		
	
		
			
				|  |  |  |  |         &context->depth_format)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_render_pass( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_format, | 
		
	
		
			
				|  |  |  |  |         context->depth_format, | 
		
	
		
			
				|  |  |  |  |         &context->render_pass)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_depth_image( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->depth_format, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |         context->allocator, | 
		
	
		
			
				|  |  |  |  |         context->extra_graphics_pool, | 
		
	
		
			
				|  |  |  |  |         context->graphics_queue, | 
		
	
		
			
				|  |  |  |  |         &context->depth_image, | 
		
	
		
			
				|  |  |  |  |         &context->depth_image_memory, | 
		
	
		
			
				|  |  |  |  |         &context->depth_image_view)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain_framebuffers( | 
		
	
		
			
				|  |  |  |  |         context->device, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_image_count, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_image_views, | 
		
	
		
			
				|  |  |  |  |         context->depth_image_view, | 
		
	
		
			
				|  |  |  |  |         context->render_pass, | 
		
	
		
			
				|  |  |  |  |         context->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |         &context->swapchain_framebuffers)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   context->current_frame = 0; | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
	
		
			
				
					|  |  |  | @ -1211,3 +1330,76 @@ VkResult add_transfer( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult recreate_framebuffer(RenderContext* gpu) { | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkDeviceWaitIdle(gpu->device); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < gpu->swapchain_image_count; i++) { | 
		
	
		
			
				|  |  |  |  |     vkDestroyFramebuffer(gpu->device, gpu->swapchain_framebuffers[i], NULL); | 
		
	
		
			
				|  |  |  |  |     vkDestroyImageView(gpu->device, gpu->swapchain_image_views[i], NULL); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkDestroyImageView(gpu->device, gpu->depth_image_view, NULL); | 
		
	
		
			
				|  |  |  |  |   vmaDestroyImage(gpu->allocator, gpu->depth_image, gpu->depth_image_memory); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   free(gpu->swapchain_images); | 
		
	
		
			
				|  |  |  |  |   free(gpu->swapchain_image_views); | 
		
	
		
			
				|  |  |  |  |   free(gpu->swapchain_framebuffers); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_details( | 
		
	
		
			
				|  |  |  |  |         gpu->physical_device, | 
		
	
		
			
				|  |  |  |  |         gpu->surface, | 
		
	
		
			
				|  |  |  |  |         &gpu->swapchain_details)) | 
		
	
		
			
				|  |  |  |  |   gpu->swapchain_format = choose_swapchain_format(gpu->swapchain_details); | 
		
	
		
			
				|  |  |  |  |   gpu->swapchain_present_mode = choose_present_mode(gpu->swapchain_details); | 
		
	
		
			
				|  |  |  |  |   gpu->swapchain_extent = choose_swapchain_extent(gpu->swapchain_details); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain( | 
		
	
		
			
				|  |  |  |  |       gpu->device, | 
		
	
		
			
				|  |  |  |  |       gpu->swapchain_format, | 
		
	
		
			
				|  |  |  |  |       gpu->swapchain_present_mode, | 
		
	
		
			
				|  |  |  |  |       gpu->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |       gpu->surface, | 
		
	
		
			
				|  |  |  |  |       gpu->swapchain_details.capabilities, | 
		
	
		
			
				|  |  |  |  |       gpu->graphics_queue.family, | 
		
	
		
			
				|  |  |  |  |       gpu->present_queue.family, | 
		
	
		
			
				|  |  |  |  |       &gpu->swapchain)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(get_swapchain_images( | 
		
	
		
			
				|  |  |  |  |       gpu->device, | 
		
	
		
			
				|  |  |  |  |       gpu->swapchain, | 
		
	
		
			
				|  |  |  |  |       &gpu->swapchain_images, | 
		
	
		
			
				|  |  |  |  |       &gpu->swapchain_image_count)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_image_views( | 
		
	
		
			
				|  |  |  |  |         gpu->device, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_image_count, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_images, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_format, | 
		
	
		
			
				|  |  |  |  |         &gpu->swapchain_image_views)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_depth_image( | 
		
	
		
			
				|  |  |  |  |         gpu->device,  | 
		
	
		
			
				|  |  |  |  |         gpu->depth_format, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |         gpu->allocator, | 
		
	
		
			
				|  |  |  |  |         gpu->extra_graphics_pool, | 
		
	
		
			
				|  |  |  |  |         gpu->graphics_queue, | 
		
	
		
			
				|  |  |  |  |         &gpu->depth_image, | 
		
	
		
			
				|  |  |  |  |         &gpu->depth_image_memory, | 
		
	
		
			
				|  |  |  |  |         &gpu->depth_image_view)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_swapchain_framebuffers( | 
		
	
		
			
				|  |  |  |  |         gpu->device, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_image_count, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_image_views, | 
		
	
		
			
				|  |  |  |  |         gpu->depth_image_view, | 
		
	
		
			
				|  |  |  |  |         gpu->render_pass, | 
		
	
		
			
				|  |  |  |  |         gpu->swapchain_extent, | 
		
	
		
			
				|  |  |  |  |         &gpu->swapchain_framebuffers)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   gpu->framebuffer_recreated = true; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return VK_SUCCESS; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |