|  |  |  | @ -91,6 +91,7 @@ typedef struct MappingStruct { | 
		
	
		
			
				|  |  |  |  | #define ATTRIBUTE_ID_DESCRIPTORS     0x00000003 // void***(array of array of data pointers)
 | 
		
	
		
			
				|  |  |  |  | #define ATTRIBUTE_ID_DESCRIPTOR_SETS 0x00000004 // VkDescriptorSet*
 | 
		
	
		
			
				|  |  |  |  | #define ATTRIBUTE_ID_POSITION        0x00000005 // Position*
 | 
		
	
		
			
				|  |  |  |  | #define ATTRIBUTE_ID_PUSH_CONSTANTS  0x00000006 // void*
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct ObjectStruct { | 
		
	
		
			
				|  |  |  |  |   Map      attributes; | 
		
	
	
		
			
				
					|  |  |  | @ -105,13 +106,16 @@ typedef struct MeshTypeStruct { | 
		
	
		
			
				|  |  |  |  |   VkVertexInputAttributeDescription* attributes; | 
		
	
		
			
				|  |  |  |  | } MeshType; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | // Defines what descriptors are bound at two different upate rates for the pipeline
 | 
		
	
		
			
				|  |  |  |  | typedef struct PipelineLayoutStruct { | 
		
	
		
			
				|  |  |  |  |   uint32_t                      object_bindings_count; | 
		
	
		
			
				|  |  |  |  |   VkDescriptorSetLayoutBinding* object_bindings; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   uint32_t                      material_bindings_count; | 
		
	
		
			
				|  |  |  |  |   VkDescriptorSetLayoutBinding* material_bindings; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   uint32_t object_pcr_size; | 
		
	
		
			
				|  |  |  |  |   uint32_t material_pcr_size; | 
		
	
		
			
				|  |  |  |  |   Mapping object_pcr_mapping; | 
		
	
		
			
				|  |  |  |  | } PipelineLayout; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct MeshStruct { | 
		
	
	
		
			
				
					|  |  |  | @ -134,6 +138,9 @@ typedef struct MaterialStruct { | 
		
	
		
			
				|  |  |  |  |   uint32_t         material_descriptors_count; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Map              object_descriptor_mappings; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   PipelineLayout pipeline_layout; | 
		
	
		
			
				|  |  |  |  |   void* material_pcr_ptr; | 
		
	
		
			
				|  |  |  |  | } Material; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct VulkanContextStruct { | 
		
	
	
		
			
				
					|  |  |  | @ -190,7 +197,7 @@ typedef struct SceneContextStruct { | 
		
	
		
			
				|  |  |  |  |   VkDescriptorSet*      descriptors; | 
		
	
		
			
				|  |  |  |  |   GPUBuffer*            ubos; | 
		
	
		
			
				|  |  |  |  |   void**                ubo_ptrs; | 
		
	
		
			
				|  |  |  |  |   VkPushConstantRange   pcr; | 
		
	
		
			
				|  |  |  |  |   uint32_t              pcr_size; | 
		
	
		
			
				|  |  |  |  | } SceneContext; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct TextureVertex { | 
		
	
	
		
			
				
					|  |  |  | @ -208,6 +215,10 @@ struct ModelUBO { | 
		
	
		
			
				|  |  |  |  |   mat4 model; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct ObjectPC { | 
		
	
		
			
				|  |  |  |  |   mat4 model; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | struct SceneUBO { | 
		
	
		
			
				|  |  |  |  |   mat4 test; | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
	
		
			
				
					|  |  |  | @ -1550,11 +1561,22 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Mesh* mesh = maybe_mesh.value; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkBuffer vertex_buffers[] = {mesh->vertex_buffer.handle}; | 
		
	
		
			
				|  |  |  |  |   VkDeviceSize offsets[] = {0}; | 
		
	
		
			
				|  |  |  |  |   if(material.pipeline_layout.object_pcr_size > 0) { | 
		
	
		
			
				|  |  |  |  |     MaybeValue maybe_attribute = map_lookup(object.attributes, material.pipeline_layout.object_pcr_mapping.index); | 
		
	
		
			
				|  |  |  |  |     if(maybe_attribute.has_value == false) { | 
		
	
		
			
				|  |  |  |  |       return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); | 
		
	
		
			
				|  |  |  |  |   vkCmdBindIndexBuffer(command_buffer, mesh->index_buffer.handle, 0, VK_INDEX_TYPE_UINT16); | 
		
	
		
			
				|  |  |  |  |     MaybeValue maybe_pc = map_lookup(object.attributes, ATTRIBUTE_ID_PUSH_CONSTANTS); | 
		
	
		
			
				|  |  |  |  |     if(maybe_pc.has_value == false) { | 
		
	
		
			
				|  |  |  |  |       return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     void** pc_ptrs = maybe_pc.value; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     mapping_functions[material.pipeline_layout.object_pcr_mapping.mapping_type](pc_ptrs[frame_num], maybe_attribute.value); | 
		
	
		
			
				|  |  |  |  |     vkCmdPushConstants(command_buffer, material.layout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC) + material.pipeline_layout.material_pcr_size, material.pipeline_layout.object_pcr_size, pc_ptrs[frame_num]); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(material.object_set_layout != VK_NULL_HANDLE) { | 
		
	
		
			
				|  |  |  |  |     MaybeValue maybe_descriptors = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS); | 
		
	
	
		
			
				
					|  |  |  | @ -1564,16 +1586,25 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkDescriptorSet* descriptor_sets = maybe_descriptors.value; | 
		
	
		
			
				|  |  |  |  |     vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 2, 1, &descriptor_sets[frame_num], 0, 0); | 
		
	
		
			
				|  |  |  |  |   } else { | 
		
	
		
			
				|  |  |  |  |     fprintf(stderr, "test\n"); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkBuffer vertex_buffers[] = {mesh->vertex_buffer.handle}; | 
		
	
		
			
				|  |  |  |  |   VkDeviceSize offsets[] = {0}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); | 
		
	
		
			
				|  |  |  |  |   vkCmdBindIndexBuffer(command_buffer, mesh->index_buffer.handle, 0, VK_INDEX_TYPE_UINT16); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void command_draw_material(Material material, uint32_t object_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer) { | 
		
	
		
			
				|  |  |  |  |   vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); | 
		
	
		
			
				|  |  |  |  |   vkCmdPushConstants(command_buffer, material.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct ScenePC), scene_constants); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(material.material_pcr_ptr != NULL && material.pipeline_layout.material_pcr_size > 0) { | 
		
	
		
			
				|  |  |  |  |     vkCmdPushConstants(command_buffer, material.material_pcr_ptr, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC), material.pipeline_layout.material_pcr_size, material.material_pcr_ptr); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptors[frame_num], 0, 0); | 
		
	
		
			
				|  |  |  |  |   if(material.material_descriptors != 0) { | 
		
	
		
			
				|  |  |  |  |     vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 1, 1, &material.material_descriptors[frame_num], 0, 0); | 
		
	
	
		
			
				
					|  |  |  | @ -1737,13 +1768,22 @@ Object create_object(uint32_t max_frames_in_flight, uint32_t descriptor_count) { | 
		
	
		
			
				|  |  |  |  |   return ret; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_sets_count, VkDescriptorSet* descriptor_sets, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  | Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_sets_count, VkDescriptorSet* descriptor_sets, uint32_t pc_size, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  |   Object zero = { | 
		
	
		
			
				|  |  |  |  |     .attributes = { | 
		
	
		
			
				|  |  |  |  |       .buckets = 0, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   void** pc_ptrs = malloc(sizeof(void*)*max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(pc_ptrs == NULL) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
		
	
		
			
				|  |  |  |  |     pc_ptrs[i] = malloc(pc_size); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Object object = create_object(max_frames_in_flight, descriptor_sets_count); | 
		
	
		
			
				|  |  |  |  |   if(object.attributes.buckets == 0) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
	
		
			
				
					|  |  |  | @ -1770,6 +1810,13 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set | 
		
	
		
			
				|  |  |  |  |     map_destroy(object.attributes); | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   result = map_add(&object.attributes, ATTRIBUTE_ID_PUSH_CONSTANTS, pc_ptrs); | 
		
	
		
			
				|  |  |  |  |   if(result == false) { | 
		
	
		
			
				|  |  |  |  |     map_destroy(object.attributes); | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return object; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -1780,7 +1827,7 @@ Material create_material( | 
		
	
		
			
				|  |  |  |  |     uint32_t shader_stage_count, | 
		
	
		
			
				|  |  |  |  |     VkPipelineShaderStageCreateInfo* shader_stages, | 
		
	
		
			
				|  |  |  |  |     VkDescriptorSetLayout scene_ubo_layout, | 
		
	
		
			
				|  |  |  |  |     VkPushConstantRange scene_pcr, | 
		
	
		
			
				|  |  |  |  |     uint32_t scene_pcr_size, | 
		
	
		
			
				|  |  |  |  |     PipelineLayout pipeline_layout, | 
		
	
		
			
				|  |  |  |  |     MeshType mesh_type, | 
		
	
		
			
				|  |  |  |  |     uint32_t max_frames_in_flight, | 
		
	
	
		
			
				
					|  |  |  | @ -1876,13 +1923,19 @@ Material create_material( | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   VkDescriptorSetLayout all_layouts[3] = {scene_ubo_layout, material_set_layout, object_set_layout}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkPushConstantRange pcr = { | 
		
	
		
			
				|  |  |  |  |     .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | 
		
	
		
			
				|  |  |  |  |     .offset = 0, | 
		
	
		
			
				|  |  |  |  |     .size = scene_pcr_size + pipeline_layout.material_pcr_size + pipeline_layout.object_pcr_size, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkPipelineLayout layout; | 
		
	
		
			
				|  |  |  |  |   VkPipelineLayoutCreateInfo layout_info = { | 
		
	
		
			
				|  |  |  |  |     .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 
		
	
		
			
				|  |  |  |  |     .setLayoutCount = 3, | 
		
	
		
			
				|  |  |  |  |     .pSetLayouts = all_layouts, | 
		
	
		
			
				|  |  |  |  |     .pushConstantRangeCount = 1, | 
		
	
		
			
				|  |  |  |  |     .pPushConstantRanges = &scene_pcr, | 
		
	
		
			
				|  |  |  |  |     .pPushConstantRanges = &pcr, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   result = vkCreatePipelineLayout(device, &layout_info, 0, &layout); | 
		
	
	
		
			
				
					|  |  |  | @ -1906,12 +1959,14 @@ Material create_material( | 
		
	
		
			
				|  |  |  |  |     .material_descriptor_pool = material_descriptor_pool, | 
		
	
		
			
				|  |  |  |  |     .material_descriptors_count = max_frames_in_flight, | 
		
	
		
			
				|  |  |  |  |     .object_descriptor_mappings = object_descriptor_mappings, | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     .pipeline_layout = pipeline_layout, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return material; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  | Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t scene_pcr_size, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  |   VkShaderModule vert_shader = load_shader_file("shader_src/basic.vert.spv", device); | 
		
	
		
			
				|  |  |  |  |   VkShaderModule frag_shader = load_shader_file("shader_src/basic.frag.spv", device); | 
		
	
		
			
				|  |  |  |  |   VkPipelineShaderStageCreateInfo shader_stages[2] = { | 
		
	
	
		
			
				
					|  |  |  | @ -1929,7 +1984,6 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkVertexInputBindingDescription bindings[1] = { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .binding = 0, // Which buffer 'binding' to use
 | 
		
	
	
		
			
				
					|  |  |  | @ -1960,58 +2014,21 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende | 
		
	
		
			
				|  |  |  |  |     .attributes_count = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkDescriptorSetLayoutBinding object_set_bindings[] = { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .binding = 0, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
		
	
		
			
				|  |  |  |  |       .pImmutableSamplers = 0, | 
		
	
		
			
				|  |  |  |  |       .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   PipelineLayout simple_layout = { | 
		
	
		
			
				|  |  |  |  |     .object_bindings = object_set_bindings, | 
		
	
		
			
				|  |  |  |  |     .object_bindings_count = sizeof(object_set_bindings)/sizeof(VkDescriptorSetLayoutBinding), | 
		
	
		
			
				|  |  |  |  |     .object_pcr_size = sizeof(struct ObjectPC), | 
		
	
		
			
				|  |  |  |  |     .object_pcr_mapping = { | 
		
	
		
			
				|  |  |  |  |       .mapping_type = MAPPING_POSITION_TO_MATRIX, | 
		
	
		
			
				|  |  |  |  |       .index = ATTRIBUTE_ID_POSITION, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Map object_descriptor_mappings = map_create(8, 2); | 
		
	
		
			
				|  |  |  |  |   if(object_descriptor_mappings.buckets == 0) { | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Mapping* position_mapping = malloc(sizeof(Mapping)); | 
		
	
		
			
				|  |  |  |  |   if(position_mapping == 0) { | 
		
	
		
			
				|  |  |  |  |     map_destroy(object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX; | 
		
	
		
			
				|  |  |  |  |   position_mapping->index = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping); | 
		
	
		
			
				|  |  |  |  |   if(map_result != true) { | 
		
	
		
			
				|  |  |  |  |     map_destroy(object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |     free(position_mapping); | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |   Map object_descriptor_mappings = {0}; | 
		
	
		
			
				|  |  |  |  |   return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr_size, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  | Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t scene_pcr_size, uint32_t max_frames_in_flight) { | 
		
	
		
			
				|  |  |  |  |   VkShaderModule vert_shader = load_shader_file("shader_src/texture.vert.spv", device); | 
		
	
		
			
				|  |  |  |  |   if(vert_shader == VK_NULL_HANDLE) { | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   VkShaderModule frag_shader = load_shader_file("shader_src/texture.frag.spv", device); | 
		
	
		
			
				|  |  |  |  |   if(frag_shader == VK_NULL_HANDLE) { | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   VkPipelineShaderStageCreateInfo shader_stages[2] = { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 
		
	
	
		
			
				
					|  |  |  | @ -2065,13 +2082,6 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend | 
		
	
		
			
				|  |  |  |  |       .pImmutableSamplers = 0, | 
		
	
		
			
				|  |  |  |  |       .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .binding = 1, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
		
	
		
			
				|  |  |  |  |       .pImmutableSamplers = 0, | 
		
	
		
			
				|  |  |  |  |       .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   MeshType textured_mesh_type = { | 
		
	
	
		
			
				
					|  |  |  | @ -2084,32 +2094,16 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend | 
		
	
		
			
				|  |  |  |  |   PipelineLayout texture_layout = { | 
		
	
		
			
				|  |  |  |  |     .object_bindings_count = sizeof(mesh_set_bindings)/sizeof(VkDescriptorSetLayoutBinding), | 
		
	
		
			
				|  |  |  |  |     .object_bindings = mesh_set_bindings, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Map object_descriptor_mappings = map_create(8, 2); | 
		
	
		
			
				|  |  |  |  |   if(object_descriptor_mappings.buckets == 0) { | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Mapping* position_mapping = malloc(sizeof(Mapping)); | 
		
	
		
			
				|  |  |  |  |   if(position_mapping == 0) { | 
		
	
		
			
				|  |  |  |  |     map_destroy(object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX; | 
		
	
		
			
				|  |  |  |  |   position_mapping->index = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping); | 
		
	
		
			
				|  |  |  |  |   if(map_result != true) { | 
		
	
		
			
				|  |  |  |  |     map_destroy(object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |     free(position_mapping); | 
		
	
		
			
				|  |  |  |  |     Material tmp = {}; | 
		
	
		
			
				|  |  |  |  |     return tmp; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |     .object_pcr_size = sizeof(struct ObjectPC), | 
		
	
		
			
				|  |  |  |  |     .object_pcr_mapping = { | 
		
	
		
			
				|  |  |  |  |       .mapping_type = MAPPING_POSITION_TO_MATRIX, | 
		
	
		
			
				|  |  |  |  |       .index = ATTRIBUTE_ID_POSITION, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  |   Map object_descriptor_mappings = {0}; | 
		
	
		
			
				|  |  |  |  |   return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr_size, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult command_copy_to_buffer(VkDevice device, GPUBuffer staging, VkBuffer destination, void* data, VkDeviceSize size, VkDeviceSize offset, VkCommandPool pool, VkQueue queue) { | 
		
	
	
		
			
				
					|  |  |  | @ -2521,11 +2515,7 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert | 
		
	
		
			
				|  |  |  |  |     .descriptors = sets, | 
		
	
		
			
				|  |  |  |  |     .ubos = ubos, | 
		
	
		
			
				|  |  |  |  |     .ubo_ptrs = ubo_ptrs, | 
		
	
		
			
				|  |  |  |  |     .pcr = { | 
		
	
		
			
				|  |  |  |  |       .offset = 0, | 
		
	
		
			
				|  |  |  |  |       .size = sizeof(struct ScenePC), | 
		
	
		
			
				|  |  |  |  |       .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     .pcr_size = sizeof(struct ScenePC), | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return scene; | 
		
	
	
		
			
				
					|  |  |  | @ -2862,7 +2852,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Object object = create_renderable(mesh, simple_mesh_material, 1, sets, max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   Object object = create_renderable(mesh, simple_mesh_material, 1, sets, sizeof(struct ObjectPC), max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(object.attributes.buckets == 0) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -2883,45 +2873,6 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   GPUBuffer* position_buffers = malloc(sizeof(GPUBuffer)*max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(position_buffers == NULL) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
		
	
		
			
				|  |  |  |  |     result = gpu_buffer_malloc(device, transfer_memory, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &position_buffers[i]); | 
		
	
		
			
				|  |  |  |  |     if(result != VK_SUCCESS) { | 
		
	
		
			
				|  |  |  |  |       return zero; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   MaybeValue maybe_ptrs = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); | 
		
	
		
			
				|  |  |  |  |   if(maybe_ptrs.has_value == false) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   void*** ptrs = maybe_ptrs.value; | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
		
	
		
			
				|  |  |  |  |     *ptrs[i] = position_buffers[i].page->ptr + position_buffers[i].memory->offset; | 
		
	
		
			
				|  |  |  |  |     VkDescriptorBufferInfo buffer_info = { | 
		
	
		
			
				|  |  |  |  |       .buffer = position_buffers[i].handle, | 
		
	
		
			
				|  |  |  |  |       .offset = 0, | 
		
	
		
			
				|  |  |  |  |       .range = sizeof(struct ModelUBO), | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkWriteDescriptorSet write_info = { | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 
		
	
		
			
				|  |  |  |  |       .dstSet = sets[i], | 
		
	
		
			
				|  |  |  |  |       .dstBinding = 0, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = 0, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .pBufferInfo = &buffer_info, | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     vkUpdateDescriptorSets(device, 1, &write_info, 0, 0); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return object; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -2977,7 +2928,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Object object = create_renderable(mesh, texture_mesh_material, 1, sets, max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   Object object = create_renderable(mesh, texture_mesh_material, 1, sets, sizeof(struct ObjectPC), max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(object.attributes.buckets == 0) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -2998,47 +2949,6 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   GPUBuffer* position_buffers = malloc(sizeof(GPUBuffer)*max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(position_buffers == NULL) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
		
	
		
			
				|  |  |  |  |     result = gpu_buffer_malloc(device, transfer_memory, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &position_buffers[i]); | 
		
	
		
			
				|  |  |  |  |     if(result != VK_SUCCESS) { | 
		
	
		
			
				|  |  |  |  |       return zero; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   MaybeValue maybe_ptrs = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); | 
		
	
		
			
				|  |  |  |  |   if(maybe_ptrs.has_value == false) { | 
		
	
		
			
				|  |  |  |  |     return zero; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   void*** ptrs = maybe_ptrs.value; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   for(uint32_t i = 0; i < max_frames_in_flight; i++) { | 
		
	
		
			
				|  |  |  |  |     *ptrs[i] = position_buffers[i].page->ptr + position_buffers[i].memory->offset; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkDescriptorBufferInfo buffer_info = { | 
		
	
		
			
				|  |  |  |  |       .buffer = position_buffers[i].handle, | 
		
	
		
			
				|  |  |  |  |       .offset = 0, | 
		
	
		
			
				|  |  |  |  |       .range = sizeof(struct ModelUBO), | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkWriteDescriptorSet write_info = { | 
		
	
		
			
				|  |  |  |  |       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | 
		
	
		
			
				|  |  |  |  |       .dstSet = sets[i], | 
		
	
		
			
				|  |  |  |  |       .dstBinding = 1, | 
		
	
		
			
				|  |  |  |  |       .dstArrayElement = 0, | 
		
	
		
			
				|  |  |  |  |       .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | 
		
	
		
			
				|  |  |  |  |       .descriptorCount = 1, | 
		
	
		
			
				|  |  |  |  |       .pBufferInfo = &buffer_info, | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     vkUpdateDescriptorSets(device, 1, &write_info, 0, 0); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VkExtent2D texture_size = { | 
		
	
		
			
				|  |  |  |  |     .width = 10, | 
		
	
		
			
				|  |  |  |  |     .height = 10, | 
		
	
	
		
			
				
					|  |  |  | @ -3102,7 +3012,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
		
	
		
			
				|  |  |  |  |     return; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr_size, context->max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { | 
		
	
		
			
				|  |  |  |  |     fprintf(stderr, "failed to create simple mesh material\n"); | 
		
	
		
			
				|  |  |  |  |     return; | 
		
	
	
		
			
				
					|  |  |  | @ -3135,7 +3045,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
		
	
		
			
				|  |  |  |  |     return; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr_size, context->max_frames_in_flight); | 
		
	
		
			
				|  |  |  |  |   if(texture_mesh_material.pipeline == VK_NULL_HANDLE) { | 
		
	
		
			
				|  |  |  |  |     fprintf(stderr, "failed to create texture mesh material\n"); | 
		
	
		
			
				|  |  |  |  |     return; | 
		
	
	
		
			
				
					|  |  |  | @ -3146,10 +3056,6 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { | 
		
	
		
			
				|  |  |  |  |       .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 = { | 
		
	
	
		
			
				
					|  |  |  | 
 |