diff --git a/src/l1/anne/margaret/margaret_misc.h b/src/l1/anne/margaret/margaret_misc.h index 45534b7..90dec03 100644 --- a/src/l1/anne/margaret/margaret_misc.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -56,8 +56,8 @@ void generate_margaret_eve_for_vulkan_utils() { .T = cstr("RefMutMargaretBufferOccupationSubBuffer"), .t_ptr = true}); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretFreeMemSegment"), true, false); - generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ - .T = cstr("MargaretFreeMemSegment"), .t_primitive = true}); + // generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + // .T = cstr("MargaretFreeMemSegment"), .t_primitive = true}); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeSubBuffer"), true, false); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeImage"), true, false); diff --git a/src/l1_5/anne/margaret.h b/src/l1_5/anne/margaret.h index dba375c..f12bd94 100644 --- a/src/l1_5/anne/margaret.h +++ b/src/l1_5/anne/margaret.h @@ -14,7 +14,8 @@ void generate_l1_5_template_instantiations_for_margaret(){ .t_primitive = true, .alternative_less = cstr("MargaretFreeMemSegment_less"), .alternative_equal = cstr("MargaretFreeMemSegment_equal"), - .alternative_comp_set_name_embed = cstr("Len") + .alternative_comp_set_name_embed = cstr("Len"), + .unconditional_equality = true, }); generate_rb_tree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ .T = cstr("MargaretFreeMemSegment"), @@ -23,7 +24,8 @@ void generate_l1_5_template_instantiations_for_margaret(){ .alternative_less = cstr("MargaretFreeMemSegment_less_resp_align"), .alternative_equal = cstr("MargaretFreeMemSegment_equal_resp_align"), .alternative_comp_set_name_embed = cstr("LenRespAlign"), - .guest_data_T = cstr("U8") + .guest_data_T = cstr("U8"), + .unconditional_equality = true, }); generate_rb_tree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){ .K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMemoryOccupation"), /* MargaretMemoryOccupation is not primitive */ diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index 0e9a666..a85e5f8 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -621,7 +621,6 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op op.T, op.T)); } - /* Erasing time!!!! */ codegen_append_rb_tree_map__method_empty_index_erase(&res, set); codegen_append_rb_tree_map__erase_kind_method(&res, map_op, set, cstr("erase"), vcstr("bool"), @@ -635,11 +634,9 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op VecU8_fmt("return None_%s();\n", op.T), VecU8_fmt("%s saved = self->el.buf[cur - 1];\n", op.T), VecU8_fmt("return Some_%s(saved);\n", op.T)); - } - /* We erased enough */ - if (!op.unconditional_equality) codegen_append_rb_tree_map__method_at(&res, map_op, set, false); + } VecU8_append_vec(&res, VecU8_fmt( "const %s* %s_at_iter(const %s* self, U64 it) {\n" /* op.T, set, set */ diff --git a/src/l2/margaret/vulkan_memory_claire.h b/src/l2/margaret/vulkan_memory_claire.h index f3d0028..f6074c6 100644 --- a/src/l2/margaret/vulkan_memory_claire.h +++ b/src/l2/margaret/vulkan_memory_claire.h @@ -379,6 +379,7 @@ typedef struct{ typedef struct { BuffRBTree_MapU64ToMargaretMemoryOccupation occupied_memory; U64 length; + /* I am 100% sure that this fields is useless rn. You might use it to show cool infographics on F3 screen */ U64 occupation_counter; VkDeviceMemory mem_hand; void* mapped_memory; @@ -516,12 +517,6 @@ struct MargaretMemAllocator { VkPhysicalDevice physical_device; }; -void MargaretMemAllocator_drop(MargaretMemAllocator self){ - // todo: first: drop absolutely everything - VecMargaretMemAllocatorOneBlock_drop(self.blocks); - MargaretMemFreeSpaceManager_drop(self.mem_free_space); -} - MargaretMemAllocator MargaretMemAllocator_new( VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types, VkMemoryPropertyFlags mem_properties, U8 memory_type_id @@ -552,6 +547,128 @@ MargaretMemAllocator MargaretMemAllocator_new( return self; } +void MargaretMemAllocator__erase_free_space_for_subbufers( + BuffRBTreeByLen_SetMargaretFreeMemSegment* free_space_inside_buffers, U64 start, U64 len, U32 dev_mem_block + ){ + if (len > 0) { + bool eret = BuffRBTreeByLen_SetMargaretFreeMemSegment_erase(free_space_inside_buffers, &(MargaretFreeMemSegment){ + .start = start, .len = len, .dev_mem_block = dev_mem_block}); + assert(eret); + } +} + +/* Don't forget that all the iterators for MMA maps for buffers and sets for free space just got invalidated */ +void MargaretMemAllocator__get_rid_of_sub_buffer(MargaretMemAllocator* self, U32 mem_block_id, U64 start){ + MargaretMemAllocatorOneBlock* block = VecMargaretMemAllocatorOneBlock_mat(&self->blocks, mem_block_id); + U64 occ_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_max_less_or_eq(&block->occupied_memory, 2); + U64 occ_start; + MargaretMemoryOccupation* occ_buf; + BuffRBTree_MapU64ToMargaretMemoryOccupation_mat_iter(&block->occupied_memory, occ_it, &occ_start, &occ_buf); + assert(occ_buf->variant == MargaretMemoryOccupation_Buffer); + MargaretMemoryOccupationBuffer* buf = &occ_buf->buf; + assert(occ_start <= start); + + MargaretBufferKindInfo* kindred = VecMargaretBufferKindInfo_mat(&self->buffer_types, buf->kind); + + U64 subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find(&buf->subbuffers, start - occ_start); + U64 subbuf_start; + const MargaretBufferOccupationSubBuffer* subbuf; + BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, subbuf_it, &subbuf_start, &subbuf); + assert(subbuf_start == start - occ_start); + assert(subbuf_start + subbuf->length <= buf->capacity); + assert(start + subbuf->length <= occ_start + buf->capacity); + kindred->total_occupation -= subbuf->length; + + U64 left_free_space_start, left_free_space_length; + + U64 prev_subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find_prev(&buf->subbuffers, subbuf_it); + if (prev_subbuf_it != 0) { + U64 prev_subbuf_start; + const MargaretBufferOccupationSubBuffer* prev_subbuf; + BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, prev_subbuf_it, &prev_subbuf_start, &prev_subbuf); + assert(prev_subbuf_start + prev_subbuf->length <= subbuf_start); + left_free_space_start = prev_subbuf_start + prev_subbuf->length; + left_free_space_length = subbuf_start - (prev_subbuf_start + prev_subbuf->length); + } else { + left_free_space_start = 0; + left_free_space_length = subbuf_start; + } + + U64 right_free_space_start, right_free_space_length; + + U64 next_subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find_next(&buf->subbuffers, subbuf_it); + if (next_subbuf_it != 0) { + U64 next_subbuf_start; + const MargaretBufferOccupationSubBuffer* next_subbuf; + BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, next_subbuf_it, &next_subbuf_start, &next_subbuf); + assert(subbuf_start + subbuf->length <= next_subbuf_start); + right_free_space_start = subbuf_start + subbuf->length; + right_free_space_length = next_subbuf_start - (subbuf_start + subbuf->length); + } else { + right_free_space_start = subbuf_start + subbuf->length; + right_free_space_length = buf->capacity - (subbuf_start + subbuf->length); + } + + /* all these iterators and pointers will get invalidated */ + /* Because MargaretBufferOccupationSubBuffer is primitive, we don't need to drop it before erasing */ + BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_empty_index_erase(&buf->subbuffers, subbuf_it); + /* all these iterators and pointers just got invalidated */ + + MargaretMemAllocator__erase_free_space_for_subbufers(&kindred->free_space_inside_buffers, + left_free_space_start, left_free_space_length, mem_block_id); + MargaretMemAllocator__erase_free_space_for_subbufers(&kindred->free_space_inside_buffers, + right_free_space_start, right_free_space_length, mem_block_id); + + if (buf->subbuffers.el.len == 0) { + /* We don't actually need to add the BIG free memory segment because we are already deleting the whole buffer */ + // todo: уебать буффер + } else { + bool iret = BuffRBTreeByLen_SetMargaretFreeMemSegment_insert(&kindred->free_space_inside_buffers, + (MargaretFreeMemSegment){.start = left_free_space_start, + .len = right_free_space_start + right_free_space_length - left_free_space_start, + .dev_mem_block = mem_block_id}); + assert(iret); + } +} + +/* This function puts block into invalid state. Which means block should already be in unusable state. + * This structure only wipes out vulkan handlers, destroyes buffers, images, and then destroys memory block + * It won't drop anything, you should do it after you called it. + * It is useful when dropping the whole allocator or when wiping old blocks + */ +void MargaretMemAllocator__clean_handlers_in_block(const MargaretMemAllocator* self, const MargaretMemAllocatorOneBlock* block){ + assert(((self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == + (block->mapped_memory != NULL)); + if (block->mapped_memory) + vkUnmapMemory(self->device, block->mapped_memory); + for (size_t i = 0; i < block->occupied_memory.el.len; i++) { + const MargaretMemoryOccupation* occ = &block->occupied_memory.el.buf[i].value; + if (occ->variant == MargaretMemoryOccupation_Buffer) { + const MargaretMemoryOccupationBuffer* wb = &occ->buf; + vkDestroyBuffer(self->device, wb->buffer, NULL); + } else if (occ->variant == MargaretMemoryOccupation_Image) { + const MargaretMemoryOccupationImage* wi = &occ->img; + vkDestroyImage(self->device, wi->image, NULL); + } + } + vkFreeMemory(self->device, block->mem_hand, NULL); +} + +void MargaretMemAllocator_drop(MargaretMemAllocator self){ + for (size_t blind = 0; blind < self.old_blocks.len; blind++) { + MargaretMemAllocator__clean_handlers_in_block(&self, &self.old_blocks.buf[blind]); + } + for (size_t blind = 0; blind < self.blocks.len; blind++) { + MargaretMemAllocator__clean_handlers_in_block(&self, &self.blocks.buf[blind]); + } + VecMargaretMemAllocatorOneBlock_drop(self.old_blocks); + VecMargaretMemAllocatorOneBlock_drop(self.blocks); + VecMargaretOldBufferResizeRecord_drop(self.old_buff_resize_record); + VecMargaretBufferKindInfo_drop(self.buffer_types); + MargaretMemFreeSpaceManager_drop(self.mem_free_space); +} + + MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request( MargaretMemAllocator* self, VkCommandBuffer cmd_buff, MargaretMemAllocatorRequest* request ){ @@ -561,44 +678,13 @@ MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request( void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self){ assert(!self->old_blocks.len || !self->old_buff_resize_record.len); for (size_t blind = 0; blind < self->old_blocks.len; blind++) { - MargaretMemAllocatorOneBlock* block = &self->old_blocks.buf[blind]; - assert(((self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == - (block->mapped_memory != NULL)); - if (block->mapped_memory) - vkUnmapMemory(self->device, block->mapped_memory); - { /* destroying images and buffers from this block. Binary tree detour takes O(n) time */ - U64 set_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_min(&block->occupied_memory); - while (set_it > 0) { - assert(set_it < block->occupied_memory.tree.len && set_it > 0); - U64 occ_start; - const MargaretMemoryOccupation* occ; - BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&block->occupied_memory, set_it, &occ_start, &occ); - if (occ->variant == MargaretMemoryOccupation_Buffer) { - const MargaretMemoryOccupationBuffer* wb = &occ->buf; - vkDestroyBuffer(self->device, wb->buffer, NULL); - } else if (occ->variant == MargaretMemoryOccupation_Image) { - const MargaretMemoryOccupationImage* wi = &occ->img; - vkDestroyImage(self->device, wi->image, NULL); - } - set_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_next(&block->occupied_memory, set_it); - } - } - vkFreeMemory(self->device, block->mem_hand, NULL); + MargaretMemAllocator__clean_handlers_in_block(self, &self->old_blocks.buf[blind]); } VecMargaretMemAllocatorOneBlock_sink(&self->old_blocks, 0); - - for (U64 ri = 0; ri < self->old_buff_resize_record.len; ri++) { const MargaretOldBufferResizeRecord* resize = &self->old_buff_resize_record.buf[ri]; if (resize->old_mem_block_id != resize->new_mem_block_id || resize->old_start != resize->new_start) { - MargaretMemAllocatorOneBlock* block = VecMargaretMemAllocatorOneBlock_mat(&self->blocks, resize->old_mem_block_id); - U64 occ_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_max_less_or_eq(&block->occupied_memory, 2); - U64 occ_start; - MargaretMemoryOccupation* occ; - BuffRBTree_MapU64ToMargaretMemoryOccupation_mat_iter(&block->occupied_memory, occ_it, &occ_start, &occ); - // todo: this fucker wants to be deleted. Do it for him. Maybe it will also carry the whole VkBuffer with - // him - // OptionMargaretBufferOccupationSubBuffer delete_me = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_pop(&self-> + MargaretMemAllocator__get_rid_of_sub_buffer(self, resize->old_mem_block_id, resize->old_start); } } VecMargaretOldBufferResizeRecord_sink(&self->old_buff_resize_record, 0);