|  |  | @ -1962,31 +1962,29 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count | 
			
		
	
		
		
			
				
					
					|  |  |  |   return fences; |  |  |  |   return fences; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Mesh load_texture_mesh(VkPhysicalDeviceMemoryProperties memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { |  |  |  | Mesh* load_texture_mesh(VkPhysicalDeviceMemoryProperties memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   Mesh mesh = {}; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.vertex_buffer.buffer = VK_NULL_HANDLE; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.vertex_buffer.memory = VK_NULL_HANDLE; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.index_buffer.buffer = VK_NULL_HANDLE; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.index_buffer.memory = VK_NULL_HANDLE; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |  |  |  |   AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(vertex_buffer.memory == VK_NULL_HANDLE) { |  |  |  |   if(vertex_buffer.memory == VK_NULL_HANDLE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return mesh; |  |  |  |     return 0; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.vertex_buffer = vertex_buffer; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.vertex_count = vertex_count; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   AllocatedBuffer index_buffer = create_populated_buffer(memories, device, (void*)indices, sizeof(uint16_t) * index_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); |  |  |  |   AllocatedBuffer index_buffer = create_populated_buffer(memories, device, (void*)indices, sizeof(uint16_t) * index_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(index_buffer.memory == VK_NULL_HANDLE) { |  |  |  |   if(index_buffer.memory == VK_NULL_HANDLE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     deallocate_buffer(device, vertex_buffer); |  |  |  |     deallocate_buffer(device, vertex_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |     AllocatedBuffer tmp = { .memory = VK_NULL_HANDLE, .buffer = VK_NULL_HANDLE}; |  |  |  |     return 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     mesh.vertex_buffer = tmp; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return mesh; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.index_buffer = index_buffer; |  |  |  |   Mesh* mesh = malloc(sizeof(Mesh)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   mesh.index_count = index_count; |  |  |  |   if(mesh == 0) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     deallocate_buffer(device, vertex_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     deallocate_buffer(device, index_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   mesh->vertex_buffer = vertex_buffer; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   mesh->vertex_count = vertex_count; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   mesh->index_buffer = index_buffer; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   mesh->index_count = index_count; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   return mesh; |  |  |  |   return mesh; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | @ -3167,120 +3165,48 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic | 
			
		
	
		
		
			
				
					
					|  |  |  |   return object; |  |  |  |   return object; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void main_loop(GLFWwindow* window, VulkanContext* context) { |  |  |  | Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight); |  |  |  |   Object zero = {}; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(scene.pool == VK_NULL_HANDLE) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to create simple mesh material\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPoolSize simple_pool_sizes[] = { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .descriptorCount = context->max_frames_in_flight, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     }, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPoolCreateInfo simple_pool_info = { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .poolSizeCount = 1, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .pPoolSizes = simple_pool_sizes, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .maxSets = context->max_frames_in_flight, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPool simple_pool; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkResult result = vkCreateDescriptorPool(context->device, &simple_pool_info, 0, &simple_pool); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(result != VK_SUCCESS) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to allocate simple_pool\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(triangle_object.attributes.buckets == 0) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to create simple mesh object\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(texture_mesh_material.pipeline == VK_NULL_HANDLE) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to create texture mesh material\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   Mesh triangle_mesh_textured = load_texture_mesh(context->memories, context->device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(triangle_mesh_textured.vertex_buffer.buffer == VK_NULL_HANDLE) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to load textured triangle mesh\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPoolSize TODO_sizes[] = { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .descriptorCount = context->max_frames_in_flight, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     }, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       .descriptorCount = context->max_frames_in_flight, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     }, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPoolCreateInfo TODO_info = { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .poolSizeCount = sizeof(TODO_sizes)/sizeof(VkDescriptorPoolSize), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .maxSets = context->max_frames_in_flight, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     .pPoolSizes = TODO_sizes, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorPool TODO_pool; |  |  |  |   Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   result = vkCreateDescriptorPool(context->device, &TODO_info, 0, &TODO_pool); |  |  |  |   if(mesh == 0) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(result != VK_SUCCESS) { |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to create temporary descriptor pool\n"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorSetLayout* TODO_layouts = malloc(sizeof(VkDescriptorSetLayout)*context->max_frames_in_flight); |  |  |  |   VkDescriptorSetLayout* layouts  = malloc(sizeof(VkDescriptorSetLayout)*max_frames_in_flight); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(TODO_layouts == 0) { |  |  |  |   if(layouts == 0) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to allocate temp buffer\n"); |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   for(uint32_t i = 0; i < context->max_frames_in_flight; i++) { |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     TODO_layouts[i] = texture_mesh_material.object_set_layout; |  |  |  |     layouts[i] = texture_mesh_material->object_set_layout; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorSetAllocateInfo TODO_alloc = { |  |  |  |   VkDescriptorSetAllocateInfo allocation_info = { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 
			
		
	
		
		
			
				
					
					|  |  |  |     .descriptorPool = TODO_pool, |  |  |  |     .descriptorPool = pool, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     .descriptorSetCount = context->max_frames_in_flight, |  |  |  |     .descriptorSetCount = max_frames_in_flight, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     .pSetLayouts = TODO_layouts, |  |  |  |     .pSetLayouts = layouts, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkDescriptorSet* TODO_sets = malloc(sizeof(VkDescriptorSet)*context->max_frames_in_flight); |  |  |  |   VkDescriptorSet* sets = malloc(sizeof(VkDescriptorSet)*max_frames_in_flight); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(TODO_sets == 0) { |  |  |  |   if(sets == 0) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to allocate temp buffer\n"); |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   result = vkAllocateDescriptorSets(context->device, &TODO_alloc, TODO_sets); |  |  |  |   VkResult result = vkAllocateDescriptorSets(device, &allocation_info, sets); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   if(result != VK_SUCCESS) { |  |  |  |   if(result != VK_SUCCESS) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to allocate TODO descriptors\n"); |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   Object triangle_object_textured = create_renderable(&triangle_mesh_textured, &texture_mesh_material, 1, TODO_sets, context->max_frames_in_flight); |  |  |  |   Object object = create_renderable(mesh, texture_mesh_material, 1, sets, max_frames_in_flight); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(triangle_object_textured.attributes.buckets == 0) { |  |  |  |   if(object.attributes.buckets == 0) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     fprintf(stderr, "failed to create renderable textured triangle object\n"); |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   Position* position = malloc(sizeof(Position)); |  |  |  |   Position* position = malloc(sizeof(Position)); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(position == 0) { |  |  |  |   if(position == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   glm_quat_identity(position->rotation); |  |  |  |   glm_quat_identity(position->rotation); | 
			
		
	
		
		
			
				
					
					|  |  |  |   position->scale[0] = 1.f; |  |  |  |   position->scale[0] = 1.f; | 
			
		
	
	
		
		
			
				
					|  |  | @ -3289,38 +3215,38 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   position->position[0] = 0.0f; |  |  |  |   position->position[0] = 0.0f; | 
			
		
	
		
		
			
				
					
					|  |  |  |   position->position[1] = 0.0f; |  |  |  |   position->position[1] = 0.0f; | 
			
		
	
		
		
			
				
					
					|  |  |  |   position->position[2] = 1.0f; |  |  |  |   position->position[2] = 1.0f; | 
			
		
	
		
		
			
				
					
					|  |  |  |   bool map_result = map_add(&triangle_object_textured.attributes, ATTRIBUTE_ID_POSITION, position); |  |  |  |   bool map_result = map_add(&object.attributes, ATTRIBUTE_ID_POSITION, position); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   if(map_result == 0) { |  |  |  |   if(map_result == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   AllocatedBuffer* triangle_ubos = allocate_buffers(context->memories, context->device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, context->max_frames_in_flight); |  |  |  |   AllocatedBuffer* ubos = allocate_buffers(memories, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(triangle_ubos == 0) { |  |  |  |   if(ubos == 0) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   MaybeValue maybe_descriptors = map_lookup(triangle_object_textured.attributes, ATTRIBUTE_ID_DESCRIPTORS); |  |  |  |   MaybeValue maybe_ptrs = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if(maybe_descriptors.has_value == false) { |  |  |  |   if(maybe_ptrs.has_value == false) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return; |  |  |  |     return zero; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   void*** descriptors = maybe_descriptors.value; |  |  |  |   void*** ptrs = maybe_ptrs.value; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   for(uint32_t i = 0; i < context->max_frames_in_flight; i++) { |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     VkResult result = vkMapMemory(context->device, triangle_ubos[i].memory, 0, sizeof(struct ModelUBO), 0, &descriptors[i][0]); |  |  |  |     VkResult result = vkMapMemory(device, ubos[i].memory, 0, sizeof(struct ModelUBO), 0, &ptrs[i][0]); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if(result != VK_SUCCESS) { |  |  |  |     if(result != VK_SUCCESS) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       return; |  |  |  |       return zero; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     VkDescriptorBufferInfo buffer_info = { |  |  |  |     VkDescriptorBufferInfo buffer_info = { | 
			
		
	
		
		
			
				
					
					|  |  |  |       .buffer = triangle_ubos[i].buffer, |  |  |  |       .buffer = ubos[i].buffer, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       .offset = 0, |  |  |  |       .offset = 0, | 
			
		
	
		
		
			
				
					
					|  |  |  |       .range = sizeof(struct ModelUBO), |  |  |  |       .range = sizeof(struct ModelUBO), | 
			
		
	
		
		
			
				
					
					|  |  |  |     }; |  |  |  |     }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     VkWriteDescriptorSet write_info = { |  |  |  |     VkWriteDescriptorSet write_info = { | 
			
		
	
		
		
			
				
					
					|  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 
			
		
	
		
		
			
				
					
					|  |  |  |       .dstSet = TODO_sets[i], |  |  |  |       .dstSet = sets[i], | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       .dstBinding = 1, |  |  |  |       .dstBinding = 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |       .dstArrayElement = 0, |  |  |  |       .dstArrayElement = 0, | 
			
		
	
		
		
			
				
					
					|  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
			
		
	
	
		
		
			
				
					|  |  | @ -3328,7 +3254,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       .pBufferInfo = &buffer_info, |  |  |  |       .pBufferInfo = &buffer_info, | 
			
		
	
		
		
			
				
					
					|  |  |  |     }; |  |  |  |     }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     vkUpdateDescriptorSets(context->device, 1, &write_info, 0, 0); |  |  |  |     vkUpdateDescriptorSets(device, 1, &write_info, 0, 0); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   VkExtent2D texture_size = { |  |  |  |   VkExtent2D texture_size = { | 
			
		
	
	
		
		
			
				
					|  |  | @ -3361,9 +3287,9 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, |  |  |  |     RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, | 
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   Texture test_texture = load_texture(context->memories, context->device, context->transfer_command_pool, context->queues.transfer, texture_size, 4, VK_FORMAT_R8G8B8A8_SRGB, texture_data); |  |  |  |   Texture test_texture = load_texture(memories, device, transfer_pool, transfer_queue, texture_size, 4, VK_FORMAT_R8G8B8A8_SRGB, texture_data); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   for(uint32_t i = 0; i < context->max_frames_in_flight; i++) { |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     VkDescriptorImageInfo image_info = { |  |  |  |     VkDescriptorImageInfo image_info = { | 
			
		
	
		
		
			
				
					
					|  |  |  |       .sampler = test_texture.sampler, |  |  |  |       .sampler = test_texture.sampler, | 
			
		
	
		
		
			
				
					
					|  |  |  |       .imageView = test_texture.view, |  |  |  |       .imageView = test_texture.view, | 
			
		
	
	
		
		
			
				
					|  |  | @ -3372,7 +3298,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     VkWriteDescriptorSet descriptor_write = {}; |  |  |  |     VkWriteDescriptorSet descriptor_write = {}; | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |  |  |  |     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.dstSet = TODO_sets[i]; |  |  |  |     descriptor_write.dstSet = sets[i]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.dstBinding = 0; |  |  |  |     descriptor_write.dstBinding = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.dstArrayElement = 0; |  |  |  |     descriptor_write.dstArrayElement = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |  |  |  |     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | 
			
		
	
	
		
		
			
				
					|  |  | @ -3381,7 +3307,86 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.pImageInfo = &image_info; |  |  |  |     descriptor_write.pImageInfo = &image_info; | 
			
		
	
		
		
			
				
					
					|  |  |  |     descriptor_write.pTexelBufferView = 0; |  |  |  |     descriptor_write.pTexelBufferView = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     vkUpdateDescriptorSets(context->device, 1, &descriptor_write, 0, 0); |  |  |  |     vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return object; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void main_loop(GLFWwindow* window, VulkanContext* context) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(scene.pool == VK_NULL_HANDLE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to create simple mesh material\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPoolSize simple_pool_sizes[] = { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .descriptorCount = context->max_frames_in_flight, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPoolCreateInfo simple_pool_info = { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .poolSizeCount = 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .pPoolSizes = simple_pool_sizes, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .maxSets = context->max_frames_in_flight, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPool simple_pool; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkResult result = vkCreateDescriptorPool(context->device, &simple_pool_info, 0, &simple_pool); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(result != VK_SUCCESS) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to allocate simple_pool\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(triangle_object.attributes.buckets == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to create simple mesh object\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(texture_mesh_material.pipeline == VK_NULL_HANDLE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to create texture mesh material\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPoolSize texture_pool_sizes[] = { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .descriptorCount = context->max_frames_in_flight, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       .descriptorCount = context->max_frames_in_flight, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPoolCreateInfo texture_pool_info = { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .poolSizeCount = sizeof(texture_pool_sizes)/sizeof(VkDescriptorPoolSize), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .maxSets = context->max_frames_in_flight, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     .pPoolSizes = texture_pool_sizes, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   VkDescriptorPool texture_pool; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   result = vkCreateDescriptorPool(context->device, &texture_pool_info, 0, &texture_pool); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(result != VK_SUCCESS) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to create temporary descriptor pool\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, texture_pool); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(triangle_object_textured.attributes.buckets == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fprintf(stderr, "failed to create texture mesh object\n"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   Object* objects[] = {&triangle_object_textured, &triangle_object}; |  |  |  |   Object* objects[] = {&triangle_object_textured, &triangle_object}; | 
			
		
	
	
		
		
			
				
					|  |  | 
 |