From 6f418827dc169130daa85e4e98240deedd8c7ed6 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Wed, 10 Dec 2025 21:32:16 +0300 Subject: [PATCH] I just realized I wasted 100 days of my life, of the most important period of my life on a useless shit that served no purpose. I just deleted MargaretMemAllocator --- src/l1/anne/margaret/margaret_misc.h | 20 +- src/l1/anne/util_temp_very_base.h | 22 +- src/l1/core/util.h | 5 + src/l1_5/anne/l1_5_templ_very_base.h | 6 +- src/l1_5/anne/margaret.h | 16 +- .../buff_rbtree_set_map_template_inst.h | 2 +- src/l2/margaret/allocator_base.h | 41 + src/l2/margaret/vulkan_buffer_claire.h | 194 +++ src/l2/margaret/vulkan_memory_claire.h | 1268 +++-------------- src/l2/tests/data_structures/t2.c | 117 -- 10 files changed, 430 insertions(+), 1261 deletions(-) create mode 100644 src/l2/margaret/allocator_base.h create mode 100644 src/l2/margaret/vulkan_buffer_claire.h diff --git a/src/l1/anne/margaret/margaret_misc.h b/src/l1/anne/margaret/margaret_misc.h index d887ae6..edacaf4 100644 --- a/src/l1/anne/margaret/margaret_misc.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -13,25 +13,15 @@ void generate_margaret_eve_for_vulkan_utils() { .mut_span = true, .collab_vec_span = true, .span_sort = true }); - /* For l2/margaret/vulkan_memory_claire.h */ - generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretMemAllocatorOneBlock")}, false); - - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeOccupant"), true, false); - generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ - .T = cstr("MargaretMemAllocatorRequestResizeBuffer"), .t_primitive = true, - .vec_extended = true /* We need unordered_pop to do some tomfoolery */}); - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestAllocBuffer"), true, false); - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestAllocImage"), true, false); - - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretFreeMemSegment"), true, false); + /* For l2/margaret/{ vulkan_img_claire.h , vulkan_buffer_claire.h } */ + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretFreeSegment"), true, false); generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ - .T = cstr("MargaretFreeMemSegment"), .t_primitive = true}); + .T = cstr("MargaretFreeSegment"), .t_primitive = true}); generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ - .T = cstr("BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment")}); + .T = cstr("BufRBTreeByLenRespAlign_SetMargaretFreeSegment")}); - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMABufferExpansionRecord"), true, false); - generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMANewMovedBufRecord"), true, false); + generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretImgAllocatorOneBlock"), true, false); } diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index bd667db..f510c23 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -48,31 +48,25 @@ void generate_util_temp_very_base_headers() { VecU8_drop(SpanT); VecU8_drop(dependency); } - generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), - cstr("CSTR"), cstr(""), true, false); + generate_guarded_span_company_for_primitive(l, ns, cstr("CSTR"), cstr(""), true, false); - generate_ResultType_templ_inst_guarded_header(cstr("l1"), cstr(""), + generate_ResultType_templ_inst_guarded_header(l, ns, cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_U8.h\""), true, false); - generate_ResultType_templ_inst_guarded_header(cstr("l1"), cstr(""), + generate_ResultType_templ_inst_guarded_header(l, ns, cstr(""), cstr("SpanU8"), cstr("#include \"VecAndSpan_U8.h\""), true, true); - generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("U32Segment"), + generate_guarded_span_company_for_primitive(l, ns, cstr("U32Segment"), cstr("#include \"../../src/l1/core/uint_segments.h\""), true, true); /* Not very basic but definitely very common */ - generate_guarded_span_company_for_non_primitive_clonable(cstr("l1"), cstr(""), cstr("TextureDataR8G8B8A8"), + generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8G8B8A8"), cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false); - generate_guarded_span_company_for_non_primitive_clonable(cstr("l1"), cstr(""), cstr("TextureDataR8G8B8"), + generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8G8B8"), cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false); - generate_guarded_span_company_for_non_primitive_clonable(cstr("l1"), cstr(""), cstr("TextureDataR8"), + generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8"), cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false); - generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("PostponedMemcpy"), cstr( - "typedef struct{\n" - SPACE "void* dest;\n" - SPACE "const void* src;\n" - SPACE "size_t n;\n" - "} PostponedMemcpy;\n"), true, false); + generate_guarded_span_company_for_primitive(l, ns, cstr("KVPU64ToU64"), cstr(""), true, false); } #endif \ No newline at end of file diff --git a/src/l1/core/util.h b/src/l1/core/util.h index 7c6291d..fa15ea2 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -87,6 +87,11 @@ typedef struct { U32 height; } SizeOfRectangleU32; +typedef struct{ + U64 key; + U64 value; +} KVPU64ToU64; + #define check(expr) if (!(expr)) { abortf("Assertion failed at %s : %d : " #expr "\n", __FILE__, __LINE__); } #endif diff --git a/src/l1_5/anne/l1_5_templ_very_base.h b/src/l1_5/anne/l1_5_templ_very_base.h index c7c39ac..9df1617 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -11,11 +11,15 @@ void generate_l1_5_template_instantiation_for_base_types(){ generate_buf_rbtree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""), (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); - // l1/core/int_primitives is included in l1_5/core/rb_tree_node.h, hence no additional dependencies needed + /* l1/core/utils.h is included in l1_5/core/rb_tree_node.h, hence no additional dependencies needed */ generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){ .T = cstr("U64"), .t_integer = true }, true); generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){ .T = cstr("S64"), .t_integer = true }, true); + + // todo: move vector declaration HERE + generate_buf_rbtree_Map_templ_inst_guarded_header(l, ns, cstr("#include \"../../gen/l1/VecKVPU64ToU64.h\"\n"), + (map_instantiation_op){.K = cstr("U64"), .k_integer = true, .V = cstr("U64"), .v_integer = true,}); } #endif diff --git a/src/l1_5/anne/margaret.h b/src/l1_5/anne/margaret.h index 755e4a6..8478ef7 100644 --- a/src/l1_5/anne/margaret.h +++ b/src/l1_5/anne/margaret.h @@ -9,17 +9,21 @@ void generate_l1_5_template_instantiations_for_margaret(){ mkdir_nofail("l1_5/eve"); mkdir_nofail("l1_5/eve/margaret"); - /* For MargaretMemAllocator */ + /* For l2/margaret/{ vulkan_img_claire.h , vulkan_buffer_claire.h } */ generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ - .T = cstr("MargaretFreeMemSegment"), .t_primitive = true, + .T = cstr("MargaretFreeSegment"), .t_primitive = true, /* comparison takes additional U8 parameter */ - .alternative_less = cstr("MargaretFreeMemSegment_less_resp_align"), + .alternative_less = cstr("MargaretFreeSegment_less_resp_align"), .alternative_comp_set_name_embed = cstr("LenRespAlign"), .guest_data_T = cstr("U8"), }); - generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){ - .K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMAOccupation"), .v_primitive = true, - }, true /* We want RBTreeNode_KVPU64ToMargaretMemoryOccupation to be generated here for us */ ); + generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ + .T = cstr("MargaretFreeSegment"), .t_primitive = true, + /* comparison takes additional U8 parameter */ + .alternative_less = cstr("MargaretFreeSegment_less_len"), + .alternative_comp_set_name_embed = cstr("Len"), + .guest_data_T = cstr("U8"), + }); } #endif \ No newline at end of file diff --git a/src/l1_5/codegen/buff_rbtree_set_map_template_inst.h b/src/l1_5/codegen/buff_rbtree_set_map_template_inst.h index 80fb5cc..20d6f3d 100644 --- a/src/l1_5/codegen/buff_rbtree_set_map_template_inst.h +++ b/src/l1_5/codegen/buff_rbtree_set_map_template_inst.h @@ -471,7 +471,7 @@ void codegen_append_buff_rbtree_map__method_at_iter(VecU8* res, map_instantiatio op.k_integer ? VecU8_from_span(op.K) : VecU8_fmt("const %s*", op.K), mut ? VecU8_fmt("%s*", op.V) : (op.v_integer ? VecU8_from_span(op.V) : VecU8_fmt("const %s*", op.V)), - op.k_integer ? cstr("") : cstr("&"), op.v_integer ? cstr("") : cstr("&"))); + op.k_integer ? cstr("") : cstr("&"), (op.v_integer && !mut) ? cstr("") : cstr("&"))); } NODISCARD VecU8 get_name_of_buf_rbtree_map_structure(map_instantiation_op op){ diff --git a/src/l2/margaret/allocator_base.h b/src/l2/margaret/allocator_base.h new file mode 100644 index 0000000..c9efa1d --- /dev/null +++ b/src/l2/margaret/allocator_base.h @@ -0,0 +1,41 @@ +#ifndef prototype1_src_l2_margaret_allocator_base_h +#define prototype1_src_l2_margaret_allocator_base_h + +#include "../../l1/core/uint_segments.h" +#include "../../l1/core/util.h" +#include "../../l1_5/core/buff_rb_tree_node.h" +#include "../../../gen/l1_5/BufRBTree_MapU64ToU64.h" + +typedef struct { + U64 block; + U64 start; + U64 len; +} MargaretFreeSegment; + +bool MargaretFreeSegment_less_len(const MargaretFreeSegment* A, const MargaretFreeSegment* B){ + if (A->len == B->len) { + if (A->block == B->block) { + return A->start < B->start; + } + return A->block < B->block; + } + return A->len < B->len; +} + +// todo: substitute U64Segment_get_length_resp_alignment by my own function +bool MargaretFreeSegment_less_resp_align(const MargaretFreeSegment* A, const MargaretFreeSegment* B, U8 alignment_exp){ + U64 A_len = U64Segment_get_length_resp_alignment((U64Segment){A->start, A->len}, alignment_exp); + U64 B_len = U64Segment_get_length_resp_alignment((U64Segment){B->start, B->len}, alignment_exp); + if (A_len == B_len) { + if (A->block == B->block) { + return A->start < B->start; + } + return A->block < B->block; + } + return A_len < B_len; +} + +#include "../../../gen/l1/eve/margaret/VecMargaretFreeSegment.h" +#include "../../../gen/l1/eve/margaret/OptionMargaretFreeSegment.h" + +#endif diff --git a/src/l2/margaret/vulkan_buffer_claire.h b/src/l2/margaret/vulkan_buffer_claire.h new file mode 100644 index 0000000..32db8e9 --- /dev/null +++ b/src/l2/margaret/vulkan_buffer_claire.h @@ -0,0 +1,194 @@ +#ifndef prototype1_src_l2_margaret_vulkan_buffer_claire_h +#define prototype1_src_l2_margaret_vulkan_buffer_claire_h + +// Same dependencies as vulkan memory allocator + +#include "allocator_base.h" + +typedef struct { + U64 block; + U64 start; +} MargaretBufAllocation; + + + + + + + + + +// void MargaretMemAllocator__shrink_some_buffer( +// MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it, size_t smaller_size +// ){ +// ListNodeMargaretMemAllocatorOneBlock* block_it = occ_it->value.block; +// MargaretMAOccupant* occ_me = &occ_it->value.me; +// assert(occ_me->variant == MargaretMemoryOccupation_Buffer); +// assert(occ_me->buf.capacity >= smaller_size); +// U64 buf_start = occ_it->key; +// U64 buf_taken_size = occ_it->value.taken_size; +// VkBuffer shorter_buf; +// check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ +// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +// .size = smaller_size, +// .usage = occ_me->buf.usage_flags, +// .sharingMode = VK_SHARING_MODE_EXCLUSIVE, +// }, NULL, &shorter_buf) == VK_SUCCESS); +// VkMemoryRequirements shorter_buf_req; +// vkGetBufferMemoryRequirements(self->device, shorter_buf, &shorter_buf_req); +// check(U64_is_2pow(shorter_buf_req.alignment)); +// check((shorter_buf_req.memoryTypeBits & self->memory_type_id)); +// check((buf_start & (shorter_buf_req.alignment - 1)) == 0) +// check(shorter_buf_req.size <= buf_taken_size); +// +// U64Segment right_free_space = MargaretMemAllocatorOneBlock_get_right_free_space(&block_it->el, occ_it); +// MargaretMemAllocator__erase_gap(self, block_it, right_free_space.start, right_free_space.len); +// MargaretMemAllocator__insert_gap(self, block_it, +// buf_start + shorter_buf_req.size, +// right_free_space.len + (buf_taken_size - shorter_buf_req.size)); +// +// vkDestroyBuffer(self->device, occ_me->buf.buffer, NULL); +// occ_it->value.taken_size = shorter_buf_req.size; +// occ_me->buf.buffer = shorter_buf; +// occ_me->buf.capacity = smaller_size; +// } + +// MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request( +// MargaretMemAllocator* self, MargaretMemAllocatorRequests* requests +// ){ + +// +// /* We first try to do all the expand_buf requests, that COULD be done using method 1 */ +// for (U64 rr = 0; rr < requests->expand_buf.len;) { +// U64 new_size = requests->expand_buf.buf[rr].new_size; +// RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->expand_buf.buf[rr].occ_it; +// +// U64 occ_start = occ_it->key; +// assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); +// MargaretMemoryOccupationBuffer* buf = &occ_it->value.me.buf; +// +// /* Method 1 */ +// U64Segment right_free_space = MargaretMemAllocatorOneBlock_get_right_free_space( +// &occ_it->value.block->el, occ_it); +// +// VkBuffer temp_buf_extension; +// check (vkCreateBuffer(self->device, &(VkBufferCreateInfo){ +// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +// .size = new_size, +// .usage = buf->usage_flags, +// .sharingMode = VK_SHARING_MODE_EXCLUSIVE, +// }, NULL, &temp_buf_extension) == VK_SUCCESS); +// VkMemoryRequirements temp_buf_extension_req; +// vkGetBufferMemoryRequirements(self->device, temp_buf_extension, &temp_buf_extension_req); +// check(U64_is_2pow(temp_buf_extension_req.alignment)); +// check((temp_buf_extension_req.memoryTypeBits & (1ull << self->memory_type_id)) > 0) +// if ((occ_start + temp_buf_extension_req.size > right_free_space.start + right_free_space.len) || +// ((occ_start & (temp_buf_extension_req.alignment - 1)) != 0) +// ){ +// vkDestroyBuffer(self->device, temp_buf_extension, NULL); +// rr++; +// continue; +// } +// MargaretMemAllocator__erase_gap(self, occ_it->value.block, right_free_space.start, right_free_space.len); +// MargaretMemAllocator__insert_gap(self, occ_it->value.block, +// occ_start + temp_buf_extension_req.size, +// right_free_space.start + right_free_space.len - (occ_start + temp_buf_extension_req.size)); +// VecMargaretMABufferExpansionRecord_append(&buffer_expansion_record, (MargaretMABufferExpansionRecord){ +// .old_capacity = buf->capacity, .occ_it = occ_it +// }); +// /* Success */ +// vkDestroyBuffer(self->device, buf->buffer, NULL); +// buf->capacity = new_size; +// buf->buffer = temp_buf_extension; +// occ_it->value.taken_size = temp_buf_extension_req.size; +// VecMargaretMemAllocatorRequestResizeBuffer_unordered_pop(&requests->expand_buf, rr); +// MargaretMemAllocator__bind_buffer_memory(self, occ_it); +// } +// +// check(vkResetCommandBuffer(self->command_buffer, 0) == VK_SUCCESS); +// check(vkBeginCommandBuffer(self->command_buffer, &(VkCommandBufferBeginInfo){ +// .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO +// }) == VK_SUCCESS); +// MargaretMemAllocatorDemands demands = 0; +// +// for (U64 ri = 0; ri < requests->expand_buf.len; ri++) { +// U64 larger_size = requests->expand_buf.buf[ri].new_size; +// RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->expand_buf.buf[ri].occ_it; +// assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); +// assert(larger_size >= occ_it->value.me.buf.capacity); +// +// VkBuffer bigger_buffer; +// check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ +// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +// .size = larger_size, +// .usage = occ_it->value.me.buf.usage_flags, +// .sharingMode = VK_SHARING_MODE_EXCLUSIVE, +// }, NULL, &bigger_buffer) == VK_SUCCESS); +// VkMemoryRequirements mem_requirements; +// vkGetBufferMemoryRequirements(self->device, bigger_buffer, &mem_requirements); +// +// check(U64_is_2pow(mem_requirements.alignment)); +// U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); +// OptionMargaretFreeMemSegment free_gap = +// MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); +// if (free_gap.variant == Option_None) { +// vkDestroyBuffer(self->device, bigger_buffer, NULL); +// return MargaretMemAllocator_request_needs_defragmentation(self, requests, buffer_expansion_record, 0, 0); +// } +// +// RBTreeNode_KVPU64ToMargaretMAOccupation* replacer = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); +// RBTree_MapU64ToMargaretMAOccupation* OLD_TREE = &occ_it->value.block->el.occupied_memory; +// RBTree_steal_neighbours(&OLD_TREE->root, OLD_TREE->NIL, &occ_it->base, &replacer->base); +// replacer->key = occ_it->key; +// replacer->value = occ_it->value; +// assert(replacer->value.me.variant == MargaretMemoryOccupation_Buffer); +// occ_it->value.me.buf.buffer = bigger_buffer; +// occ_it->value.me.buf.capacity = larger_size; +// +// MargaretMemAllocator__add_occupant_node_given_gap_any_type(self, occ_it, free_gap.some, mem_requirements.size, alignment_exp); +// MargaretMemAllocator__bind_buffer_memory(self, occ_it); +// +// VecMargaretMANewMovedBufRecord_append(&self->old_moved_buffers, +// (MargaretMANewMovedBufRecord){.replacement = replacer, .my_occ_it = occ_it}); +// if (replacer->value.me.buf.preserve_at_quiet) { +// demands = MARGARET_MA_DEMANDS_CMD_BUFFER_BIT; +// vkCmdCopyBuffer(self->command_buffer, replacer->value.me.buf.buffer, bigger_buffer, +// 1, &(VkBufferCopy){0, 0, replacer->value.me.buf.capacity}); +// } +// } +// +// for (U64 ri = 0; ri < requests->alloc_buf.len; ri++) { +// MargaretMemAllocatorRequestAllocBuffer* req = &requests->alloc_buf.buf[ri]; +// +// VkBuffer fresh_buf; +// check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ +// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +// .size = req->allocation_size, +// .usage = req->usage, +// .sharingMode = VK_SHARING_MODE_EXCLUSIVE, +// }, NULL, &fresh_buf) == VK_SUCCESS); +// VkMemoryRequirements mem_requirements; +// vkGetBufferMemoryRequirements(self->device, fresh_buf, &mem_requirements); +// check(U64_is_2pow(mem_requirements.alignment)); +// U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); +// OptionMargaretFreeMemSegment free_gap = +// MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); +// if (free_gap.variant == Option_None) { +// vkDestroyBuffer(self->device, fresh_buf, NULL); +// return MargaretMemAllocator_request_needs_defragmentation(self, requests, buffer_expansion_record, 0, 0); +// } +// +// RBTreeNode_KVPU64ToMargaretMAOccupation* new_node = req->new_node; /* It was allocated for us */ +// new_node->value.me = (MargaretMAOccupant){.variant = MargaretMemoryOccupation_Buffer, .buf = { +// .buffer = fresh_buf, .capacity = req->allocation_size, .preserve_at_quiet = req->allocation_size, +// .usage_flags = req->usage +// }}; +// MargaretMemAllocator__add_occupant_node_given_gap_any_type(self, new_node, free_gap.some, mem_requirements.size, alignment_exp); +// MargaretMemAllocator__bind_buffer_memory(self, new_node); +// } +// +// MargaretMemAllocatorRequests_sink(requests); +// return demands; +// } + +#endif \ No newline at end of file diff --git a/src/l2/margaret/vulkan_memory_claire.h b/src/l2/margaret/vulkan_memory_claire.h index 8b3f332..6a55094 100644 --- a/src/l2/margaret/vulkan_memory_claire.h +++ b/src/l2/margaret/vulkan_memory_claire.h @@ -175,267 +175,42 @@ // todo: get rid of this whole VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT crap. MargaretMA is for non-host-visible // todo: for staging buffers you better use MargaretBufferAllocator. Ou, yeah, I have yet to write them -#include "../../l1/core/int_primitives.h" -#include "../../../gen/l1/VecPostponedMemcpy.h" -/* Demands + Warnings */ -typedef U8 MargaretMemAllocatorDemands; -/* If we do defragmentation, MargaretMemAllocator warns us that for - * position-structures, that it filled, will be updated. If these values - * (buffer/image handlers + sub-buffer positions) are dependencies of other - * objects, these objects need to be updated (or rebuilt) */ -#define MARGARET_MA_DEMANDS_DEFRAGMENTATION_BIT 1 -/* If for some set of requests MargaretMemAllocator needs to execute some Vulkan copying commands, - * it will demand you to actually execute the command buffer that you gave it. If this is `true` it does - * not necessarily mean that defragmentation is happening right now, no, defragmentation is indicated by - * `MARGARET_MEM_ALLOCATOR_DEMANDS_DEFRAGMENTATION_BITS` warning bit, - * but if you are doing a DIRECT BUFFER (sub-buffer in terms of - * vulkan) RESIZE, this sub-buffer may be copied. - * It won't affect other data structures in your memory, - * of course, (still, notice that position of your sub-buffer will be updated). - */ -#define MARGARET_MA_DEMANDS_CMD_BUFFER_BIT 2 +// todo: fucking rewrite all of this. Yes, I want all of this shit rewritten -#define MARGARET_MA_DEMANDS_DEFRAGMENTATION (MARGARET_MA_DEMANDS_CMD_BUFFER_BIT | MARGARET_MA_DEMANDS_DEFRAGMENTATION_BIT) - -#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 21 - -#include "../../l1/core/uint_segments.h" -#include "../../l1/core/util.h" -#include "../../l1_5/core/buff_rb_tree_node.h" -#include "../../l1_5/core/rb_tree_node.h" +#include "allocator_base.h" +/* Does not include all parameters needed for relocation. Because relocation is needed only + * during controlled defragmentation */ typedef struct { - U64 width; - U64 height; - VkFormat format; - VkImageUsageFlags usage_flags; - - /* Layout after defragmentation + at which point in pipeline will the need this image (again, after defragmentation) */ - VkImageLayout current_layout; - VkPipelineStageFlags current_dest_stage_mask; - VkAccessFlags current_dest_access_mask; - bool preserve_at_quiet; + U64 block; VkImage image; -} MargaretMemoryOccupationImage; - -/* primitive */ -typedef struct { - VkBufferUsageFlags usage_flags; - bool preserve_at_quiet; - /* This is not a parameter of a buffer type. It is a special flag used during defragmentation to indicate - * that this buffer was already moved to 'new blocks' by expand_buf request - * and copying cycle should skip it. In other situations -> false */ - bool moved_already; - VkBuffer buffer; - U64 capacity; -} MargaretMemoryOccupationBuffer; - -typedef enum { - MargaretMemoryOccupation_Image, - MargaretMemoryOccupation_Buffer, -} MargaretMemoryOccupation_variant; - -typedef struct { - MargaretMemoryOccupation_variant variant; - union { - MargaretMemoryOccupationImage img; - MargaretMemoryOccupationBuffer buf; - }; -} MargaretMAOccupant; - -typedef struct ListNodeMargaretMemAllocatorOneBlock ListNodeMargaretMemAllocatorOneBlock; - -typedef struct { - // todo: remove this field, replace it's getter with a 'virtual' method that queries VkBuffer/VkImage VkMemoryRequirements - U64 taken_size; - ListNodeMargaretMemAllocatorOneBlock* block; - MargaretMAOccupant me; -} MargaretMAOccupation; - -#include "../../../gen/l1_5/eve/margaret/RBTree_MapU64ToMargaretMAOccupation.h" + U64 start; +} MargaretImgAllocation; /* Not primitive */ typedef struct { - RBTree_MapU64ToMargaretMAOccupation occupied_memory; + BufRBTree_MapU64ToU64 images; U64 capacity; - /* 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; -} MargaretMemAllocatorOneBlock; +} MargaretImgAllocatorOneBlock; -void MargaretMemAllocatorOneBlock_drop(MargaretMemAllocatorOneBlock self){ - RBTree_MapU64ToMargaretMAOccupation_drop(self.occupied_memory); +void MargaretMemAllocatorOneBlock_drop(MargaretImgAllocatorOneBlock self){ + BufRBTree_MapU64ToU64_drop(self.images); } -#include "../../../gen/l1/eve/margaret/ListMargaretMemAllocatorOneBlock.h" - -typedef RBTreeNode_KVPU64ToMargaretMAOccupation* MargaretMemAllocatorRequestFreeOccupant; -#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestFreeOccupant.h" - -typedef MargaretMemAllocatorRequestFreeOccupant MargaretMemAllocatorRequestFreeBuffer; -typedef MargaretMemAllocatorRequestFreeOccupant MargaretMemAllocatorRequestFreeImage; - -typedef struct{ - U64 new_size; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it; -} MargaretMemAllocatorRequestResizeBuffer; -#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestResizeBuffer.h" - -typedef struct { - U64 allocation_size; - VkBufferUsageFlags usage; - bool preserve_at_quiet; - /* Memory block owned by request. Doesn't contain information or even base rbtree structure */ - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node; -} MargaretMemAllocatorRequestAllocBuffer; -#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestAllocBuffer.h" - -typedef struct { - U64 width; - U64 height; - VkFormat format; - VkImageUsageFlags usage_flags; - VkImageLayout current_layout; - VkPipelineStageFlags current_dest_stage_mask; - VkAccessFlags current_dest_access_mask; - bool preserve_at_quiet; - /* Memory block owned by request. Doesn't contain information or even base rbtree structure */ - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node; -} MargaretMemAllocatorRequestAllocImage; -#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestAllocImage.h" - -typedef struct { - VecMargaretMemAllocatorRequestFreeOccupant free_buf; - VecMargaretMemAllocatorRequestFreeOccupant free_image; - VecMargaretMemAllocatorRequestResizeBuffer shrink_buf; - VecMargaretMemAllocatorRequestResizeBuffer expand_buf; - VecMargaretMemAllocatorRequestAllocBuffer alloc_buf; - VecMargaretMemAllocatorRequestAllocImage alloc_image; -} MargaretMemAllocatorRequests; - -#define MargaretMemAllocatorRequests_new() \ - (MargaretMemAllocatorRequests){ \ - VecMargaretMemAllocatorRequestFreeOccupant_new(), VecMargaretMemAllocatorRequestFreeOccupant_new(), \ - VecMargaretMemAllocatorRequestResizeBuffer_new(), VecMargaretMemAllocatorRequestResizeBuffer_new(), \ - VecMargaretMemAllocatorRequestAllocBuffer_new(), VecMargaretMemAllocatorRequestAllocImage_new() } - -void MargaretMemAllocatorRequests_sink(MargaretMemAllocatorRequests* self){ - VecMargaretMemAllocatorRequestFreeOccupant_sink(&self->free_buf, 0); - VecMargaretMemAllocatorRequestFreeOccupant_sink(&self->free_image, 0); - VecMargaretMemAllocatorRequestResizeBuffer_sink(&self->shrink_buf, 0); - VecMargaretMemAllocatorRequestResizeBuffer_sink(&self->expand_buf, 0); - VecMargaretMemAllocatorRequestAllocBuffer_sink(&self->alloc_buf, 0); - for (size_t i = 0; i < self->alloc_buf.len; i++) - free(self->alloc_buf.buf[i].new_node); - self->alloc_buf.len = 0; - for (size_t i = 0; i < self->alloc_image.len; i++) - free(self->alloc_image.buf[i].new_node); - self->alloc_image.len = 0; -} - -void MargaretMemAllocatorRequests_drop(MargaretMemAllocatorRequests self){ - VecMargaretMemAllocatorRequestFreeOccupant_drop(self.free_buf); - VecMargaretMemAllocatorRequestFreeOccupant_drop(self.free_image); - VecMargaretMemAllocatorRequestResizeBuffer_drop(self.shrink_buf); - VecMargaretMemAllocatorRequestResizeBuffer_drop(self.expand_buf); - for (size_t i = 0; i < self.alloc_buf.len; i++) - free(self.alloc_buf.buf[i].new_node); - for (size_t i = 0; i < self.alloc_image.len; i++) - free(self.alloc_image.buf[i].new_node); - VecMargaretMemAllocatorRequestAllocBuffer_drop(self.alloc_buf); - VecMargaretMemAllocatorRequestAllocImage_drop(self.alloc_image); -} - -void MargaretMemAllocatorRequests_free_buf( - MargaretMemAllocatorRequests* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it){ - - -} - -void MargaretMemAllocatorRequests_shrink_buf(MargaretMemAllocatorRequests* self, - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it, size_t new_size){ - VecMargaretMemAllocatorRequestResizeBuffer_append(&self->shrink_buf, - (MargaretMemAllocatorRequestResizeBuffer){.occ_it = occ_it, .new_size = new_size}); -} - -void MargaretMemAllocatorRequests_expand_buf(MargaretMemAllocatorRequests* self, - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it, size_t new_size){ - VecMargaretMemAllocatorRequestResizeBuffer_append(&self->expand_buf, - (MargaretMemAllocatorRequestResizeBuffer){.occ_it = occ_it, .new_size = new_size}); -} - -RBTreeNode_KVPU64ToMargaretMAOccupation* MargaretMemAllocatorRequests_alloc_buf( - MargaretMemAllocatorRequests* self, - U64 allocation_size, VkBufferUsageFlags usage, bool preserve_at_quiet - ){ - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); - VecMargaretMemAllocatorRequestAllocBuffer_append(&self->alloc_buf, (MargaretMemAllocatorRequestAllocBuffer){ - .allocation_size = allocation_size, .usage = usage, .preserve_at_quiet = preserve_at_quiet, .new_node = new_node - }); - return new_node; -} - -RBTreeNode_KVPU64ToMargaretMAOccupation* MargaretMemAllocatorRequests_alloc_image( - MargaretMemAllocatorRequests* self, U64 width, U64 height, VkFormat format, VkImageUsageFlags usage, - VkImageLayout current_layout, - VkPipelineStageFlags current_dest_stage_mask, VkAccessFlags current_dest_access_mask, - bool preserve_at_quiet){ - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); - VecMargaretMemAllocatorRequestAllocImage_append(&self->alloc_image, (MargaretMemAllocatorRequestAllocImage){ - .width = width, .height = height, .format = format, .usage_flags = usage, .current_layout = current_layout, - .current_dest_stage_mask = current_dest_stage_mask, .current_dest_access_mask = current_dest_access_mask, - .preserve_at_quiet = preserve_at_quiet, .new_node = new_node - }); - return new_node; -} - -typedef struct { - U64 start; - U64 len; - ListNodeMargaretMemAllocatorOneBlock* dev_mem_block; -} MargaretFreeMemSegment; - -bool MargaretFreeMemSegment_less_resp_align( - const MargaretFreeMemSegment* A, const MargaretFreeMemSegment* B, U8 alignment_exp - ){ - U64 A_len = U64Segment_get_length_resp_alignment((U64Segment){A->start, A->len}, alignment_exp); - U64 B_len = U64Segment_get_length_resp_alignment((U64Segment){B->start, B->len}, alignment_exp); - if (A_len == B_len) { - if (A->dev_mem_block == B->dev_mem_block) { - return A->start < B->start; - } - return (uintptr_t)A->dev_mem_block < (uintptr_t)B->dev_mem_block; - } - return A_len < B_len; -} - -#include "../../../gen/l1/eve/margaret/VecMargaretFreeMemSegment.h" -#include "../../../gen/l1/eve/margaret/OptionMargaretFreeMemSegment.h" -#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment.h" -#include "../../../gen/l1/eve/margaret/OptionBufRBTreeByLenRespAlign_SetMargaretFreeMemSegment.h" - -typedef struct { - U64 old_capacity; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it; -} MargaretMABufferExpansionRecord; -#include "../../../gen/l1/eve/margaret/VecMargaretMABufferExpansionRecord.h" - -typedef struct { - RBTreeNode_KVPU64ToMargaretMAOccupation* replacement; - /* Pointer points to the same address, but the neighbours+key+value at that address are different. - * We relocated out node, replacing it with a NEW node that holds the old buffer value and the old start U64 - */ - RBTreeNode_KVPU64ToMargaretMAOccupation* my_occ_it; -} MargaretMANewMovedBufRecord; -#include "../../../gen/l1/eve/margaret/VecMargaretMANewMovedBufRecord.h" - +#include "../../../gen/l1/eve/margaret/VecMargaretImgAllocatorOneBlock.h" #include "../../../gen/l1/VecAndSpan_U8.h" +#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLenRespAlign_SetMargaretFreeSegment.h" +#include "../../../gen/l1/eve/margaret/OptionBufRBTreeByLenRespAlign_SetMargaretFreeSegment.h" + +#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 28 /* Superstructure for managing free segments of memory of some type in ALL BLOCKS */ typedef struct { - OptionBufRBTreeByLenRespAlign_SetMargaretFreeMemSegment free_space_in_memory[MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP]; + OptionBufRBTreeByLenRespAlign_SetMargaretFreeSegment free_space_in_memory[MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP]; VecU8 set_present; } MargaretMemFreeSpaceManager; @@ -443,20 +218,20 @@ MargaretMemFreeSpaceManager MargaretMemFreeSpaceManager_new(){ MargaretMemFreeSpaceManager res = {.set_present = VecU8_new_zeroinit(1)}; res.set_present.buf[0] = 3; for (U8 algn = 0; algn < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; algn++) - res.free_space_in_memory[algn] = None_BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment(); - res.free_space_in_memory[3] = Some_BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment( - BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_new_reserved(3, 1)); + res.free_space_in_memory[algn] = None_BufRBTreeByLenRespAlign_SetMargaretFreeSegment(); + res.free_space_in_memory[3] = Some_BufRBTreeByLenRespAlign_SetMargaretFreeSegment( + BufRBTreeByLenRespAlign_SetMargaretFreeSegment_new_reserved(3, 1)); return res; } void MargaretMemFreeSpaceManager_drop(MargaretMemFreeSpaceManager self){ for (U8 alignment_exp = 0; alignment_exp < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; alignment_exp++) - OptionBufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_drop(self.free_space_in_memory[alignment_exp]); + OptionBufRBTreeByLenRespAlign_SetMargaretFreeSegment_drop(self.free_space_in_memory[alignment_exp]); VecU8_drop(self.set_present); } void MargaretMemFreeSpaceManager_erase( - MargaretMemFreeSpaceManager* man, ListNodeMargaretMemAllocatorOneBlock* dev_mem_block, U64 start, U64 len){ + MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ if (len == 0) return; assert(man->set_present.len > 0); @@ -464,15 +239,15 @@ void MargaretMemFreeSpaceManager_erase( U8 alignment = man->set_present.buf[aj]; assert(alignment < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP); assert(man->free_space_in_memory[alignment].variant == Option_Some); - bool eret = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_erase(& + bool eret = BufRBTreeByLenRespAlign_SetMargaretFreeSegment_erase(& man->free_space_in_memory[alignment].some, - &(MargaretFreeMemSegment){.dev_mem_block = dev_mem_block, .start = start, .len = len}); + &(MargaretFreeSegment){.block = block, .start = start, .len = len}); assert(eret); } } void MargaretMemFreeSpaceManager_insert( - MargaretMemFreeSpaceManager* man, ListNodeMargaretMemAllocatorOneBlock* dev_mem_block, U64 start, U64 len){ + MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ if (len == 0) return; assert(man->set_present.len > 0); /* MargaretMemFreeSpaceManager will do that for us with 2^3 */ @@ -480,391 +255,176 @@ void MargaretMemFreeSpaceManager_insert( U8 alignment = man->set_present.buf[aj]; assert(alignment < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP); assert(man->free_space_in_memory[alignment].variant == Option_Some); - bool iret = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(& - man->free_space_in_memory[alignment].some, (MargaretFreeMemSegment){start, len, dev_mem_block}); + bool iret = BufRBTreeByLenRespAlign_SetMargaretFreeSegment_insert(& + man->free_space_in_memory[alignment].some, (MargaretFreeSegment){.block = block, .start = start, .len = len}); assert(iret); } } -OptionMargaretFreeMemSegment MargaretMemFreeSpaceManager_search( +OptionMargaretFreeSegment MargaretMemFreeSpaceManager_search( MargaretMemFreeSpaceManager* man, U8 alignment_exp, U64 req_size) { check(alignment_exp < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP); if (man->free_space_in_memory[alignment_exp].variant == Option_None) { assert(man->set_present.len > 0); assert(man->free_space_in_memory[man->set_present.buf[0]].variant == Option_Some); - BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment* have = &man->free_space_in_memory[man->set_present.buf[0]].some; - man->free_space_in_memory[alignment_exp] = Some_BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment( - BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_new_reserved(alignment_exp, have->el.len)); + BufRBTreeByLenRespAlign_SetMargaretFreeSegment* have = &man->free_space_in_memory[man->set_present.buf[0]].some; + man->free_space_in_memory[alignment_exp] = Some_BufRBTreeByLenRespAlign_SetMargaretFreeSegment( + BufRBTreeByLenRespAlign_SetMargaretFreeSegment_new_reserved(alignment_exp, have->el.len)); for (size_t i = 0; i < have->el.len; i++) { - BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&man->free_space_in_memory[alignment_exp].some, - *VecMargaretFreeMemSegment_at(&have->el, i)); + BufRBTreeByLenRespAlign_SetMargaretFreeSegment_insert( + &man->free_space_in_memory[alignment_exp].some, *VecMargaretFreeSegment_at(&have->el, i)); } } assert(man->free_space_in_memory[alignment_exp].variant == Option_Some); - U64 sit = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_find_min_grtr_or_eq(&man->free_space_in_memory[alignment_exp].some, - &(MargaretFreeMemSegment){.start = 0, .len = req_size, .dev_mem_block = 0}); + U64 sit = BufRBTreeByLenRespAlign_SetMargaretFreeSegment_find_min_grtr_or_eq( + &man->free_space_in_memory[alignment_exp].some, &(MargaretFreeSegment){.len = req_size,}); if (sit == 0) - return None_MargaretFreeMemSegment(); - return Some_MargaretFreeMemSegment(*BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_at_iter( + return None_MargaretFreeSegment(); + return Some_MargaretFreeSegment(*BufRBTreeByLenRespAlign_SetMargaretFreeSegment_at_iter( &man->free_space_in_memory[alignment_exp].some, sit)); } /* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */ typedef struct { U64 total_capacity; - ListMargaretMemAllocatorOneBlock blocks; - /* old_blocks is usually empty. BUT! When you generated a defragmentation command buffer with - * MargaretMemAllocator_carry_out_request, this vector will be filled with old blocks, while - * `blocks` vector will be filled with newly created blocks. - * All references in `answer-structures` will be immediately modified, so that they would point - * to the right block. After you execute the command buffer, - * that MargaretMemAllocator_carry_out_request generates, you can (and should) wipe out old blocks - */ - ListMargaretMemAllocatorOneBlock old_blocks; - VecMargaretMANewMovedBufRecord old_moved_buffers; - + VecMargaretImgAllocatorOneBlock blocks; MargaretMemFreeSpaceManager mem_free_space; - VkDevice device; VkPhysicalDevice physical_device; - VkCommandBuffer command_buffer; - VkMemoryPropertyFlags mem_properties; U8 memory_type_id; -} MargaretMemAllocator; +} MargaretImgAllocator; -MargaretMemAllocator MargaretMemAllocator_new( - VkDevice device, VkPhysicalDevice physical_device, VkCommandBuffer command_buffer, - VkMemoryPropertyFlags mem_properties, U8 memory_type_id){ - MargaretMemAllocator self = { - .blocks = ListMargaretMemAllocatorOneBlock_new(), - .old_blocks = ListMargaretMemAllocatorOneBlock_new(), - .old_moved_buffers = VecMargaretMANewMovedBufRecord_new(), +void MargaretImgAllocator__erase_gap(MargaretImgAllocator* self, U64 block_id, U64 start, U64 len){ + MargaretMemFreeSpaceManager_erase(&self->mem_free_space, block_id, start, len); + MargaretImgAllocatorOneBlock* BLOCK = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, block_id); + BLOCK->occupation_counter += len; + assert(BLOCK->occupation_counter <= BLOCK->capacity); +} + +void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, U64 block_id, U64 start, U64 len){ + MargaretMemFreeSpaceManager_insert(&self->mem_free_space, block_id, start, len); + MargaretImgAllocatorOneBlock* BLOCK = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, block_id); + assert(len <= BLOCK->occupation_counter); + BLOCK->occupation_counter -= len; +} + +/* Returns id of the new block */ +U64 MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){ + VkDeviceMemory memory; + check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){ + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = capacity, .memoryTypeIndex = self->memory_type_id + }, NULL, &memory) == VK_SUCCESS); + U64 bid = self->blocks.len; + VecMargaretImgAllocatorOneBlock_append(&self->blocks, (MargaretImgAllocatorOneBlock){ + .images = BufRBTree_MapU64ToU64_new_reserved(1), + .capacity = capacity, + .occupation_counter = 0, + .mem_hand = memory, + .mapped_memory = NULL /* not supported */}); + return bid; +} + +MargaretImgAllocator MargaretImgAllocator_new( + VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size){ + + MargaretImgAllocator self = { + .blocks = VecMargaretImgAllocatorOneBlock_new(), .mem_free_space = MargaretMemFreeSpaceManager_new(), .device = device, .physical_device = physical_device, - .command_buffer = command_buffer, .memory_type_id = memory_type_id, - .mem_properties = mem_properties, }; - + MargaretImgAllocator__add_block(&self, initial_block_size); + MargaretImgAllocator__insert_gap(&self, 0, 0, initial_block_size); return self; } -void MargaretMemAllocator__erase_gap( - MargaretMemAllocator* self, ListNodeMargaretMemAllocatorOneBlock* block_it, U64 start, U64 len){ - MargaretMemFreeSpaceManager_erase(&self->mem_free_space, block_it, start, len); - block_it->el.occupation_counter += len; - assert(block_it->el.occupation_counter <= block_it->el.capacity); -} - -void MargaretMemAllocator__insert_gap( - MargaretMemAllocator* self, ListNodeMargaretMemAllocatorOneBlock* block_it, U64 start, U64 len){ - MargaretMemFreeSpaceManager_insert(&self->mem_free_space, block_it, start, len); - assert(len <= block_it->el.occupation_counter); - block_it->el.occupation_counter -= len; -} - -/* didn't generate it, so I am doing it myself */ -void RBTree_MapU64ToMargaretMAOccupation_insert_node( - RBTree_MapU64ToMargaretMAOccupation* self, RBTreeNode_KVPU64ToMargaretMAOccupation* node - ){ - node->base.left = node->base.right = self->NIL; - node->base.color = RBTREE_RED; - if (self->root == self->NIL) { - self->root = &node->base; - node->base.parent = self->NIL; - node->base.color = RBTREE_BLACK; - return; - } - RBTreeNode_KVPU64ToMargaretMAOccupation* cur = (RBTreeNode_KVPU64ToMargaretMAOccupation*)self->root; - while (true) { - if (node->key < cur->key) { - if (cur->base.left == self->NIL) { - node->base.parent = &cur->base; - cur->base.left = &node->base; - RBTree_fix_after_insert(&self->root, self->NIL, &node->base); - return; - } else { - cur = (RBTreeNode_KVPU64ToMargaretMAOccupation*)cur->base.left; - } - } else if (cur->key < node->key) { - if (cur->base.right == self->NIL) { - node->base.parent = &cur->base; - cur->base.right = &node->base; - RBTree_fix_after_insert(&self->root, self->NIL, &node->base); - return; - } else { - cur = (RBTreeNode_KVPU64ToMargaretMAOccupation*)cur->base.right; - } - } else - assert(false); - } -} - U64 margaret_get_alignment_left_padding(U64 unaligned_start, U8 alignment_exp){ U64 hit = unaligned_start & (1ull << alignment_exp) - 1; return (hit ? (1ull << alignment_exp) - hit : 0); } -/* This method works both for alloc_buffer/alloc_image requests and for expand_buf request (moving path). - * existing node carries information about occupant, but key (start pos), taken_size, block, are not filled, - * and this node is basically outside any tree */ -void MargaretMemAllocator__add_occupant_node_given_gap_any_type( - MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* existing_node, - MargaretFreeMemSegment segment, U64 required_size, U8 alignment_exp +U64 MargaretImgAllocator__add_img_given_gap( + MargaretImgAllocator* self, MargaretFreeSegment segment, U64 required_size, U8 alignment_exp ){ - ListNodeMargaretMemAllocatorOneBlock* block_it = segment.dev_mem_block; - RBTree_MapU64ToMargaretMAOccupation* block_occupied_memory = &block_it->el.occupied_memory; U64 gap_start = segment.start; U64 gap_len = segment.len; U64 af = margaret_get_alignment_left_padding(gap_start, alignment_exp); U64 aligned_start = gap_start + af; assert(aligned_start + required_size <= gap_start + gap_len); - MargaretMemAllocator__erase_gap(self, block_it, gap_start, gap_len); - MargaretMemAllocator__insert_gap(self, block_it, gap_start, af); - MargaretMemAllocator__insert_gap(self, block_it, aligned_start + required_size, + MargaretImgAllocator__erase_gap(self, segment.block, gap_start, gap_len); + MargaretImgAllocator__insert_gap(self, segment.block, gap_start, af); + MargaretImgAllocator__insert_gap(self, segment.block, aligned_start + required_size, gap_start + gap_len - (aligned_start + required_size)); - existing_node->key = aligned_start; - existing_node->value.taken_size = required_size; - existing_node->value.block = block_it; - - RBTree_MapU64ToMargaretMAOccupation_insert_node(block_occupied_memory, existing_node); + BufRBTree_MapU64ToU64* images = &VecMargaretImgAllocatorOneBlock_mat(&self->blocks, segment.block)->images; + bool iret = BufRBTree_MapU64ToU64_insert(images, aligned_start, required_size); + assert(iret); + return aligned_start; } +U64Segment MargaretImgAllocator__get_left_free_space( + const MargaretImgAllocator* self, MargaretImgAllocation allocation){ + const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block); + U64 occ_start = allocation.start; + U64 prev_occ_it = BufRBTree_MapU64ToU64_find_max_less(&block->images, allocation.start); + if (prev_occ_it != 0) { + U64 prev_occ_start; + U64 prev_occ_taken_size; + BufRBTree_MapU64ToU64_at_iter(&block->images, prev_occ_it, &prev_occ_start, &prev_occ_taken_size); -U64Segment MargaretMemAllocatorOneBlock_get_left_free_space( - const MargaretMemAllocatorOneBlock* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it){ - U64 occ_start = occ_it->key; - - RBTreeNode_KVPU64ToMargaretMAOccupation* prev_occ_it = - RBTree_MapU64ToMargaretMAOccupation_find_prev(&self->occupied_memory, occ_it); - if (prev_occ_it != NULL) { - U64 prev_occ_start = prev_occ_it->key; - U64 prev_occ_taken_size = prev_occ_it->value.taken_size; assert(prev_occ_start + prev_occ_taken_size <= occ_start); - return (U64Segment){.start = prev_occ_start + prev_occ_taken_size, + return (U64Segment){ + .start = prev_occ_start + prev_occ_taken_size, .len = occ_start - (prev_occ_start + prev_occ_taken_size)}; } return (U64Segment){.start = 0, .len = occ_start}; } -U64Segment MargaretMemAllocatorOneBlock_get_right_free_space( - const MargaretMemAllocatorOneBlock* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it){ - U64 occ_start = occ_it->key; - U64 occ_taken_size = occ_it->value.taken_size; +U64Segment MargaretImgAllocator__get_right_free_space( + const MargaretImgAllocator* self, MargaretImgAllocation allocation){ + const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block); + U64 occ_start = allocation.start; + VkMemoryRequirements occ_memory_requirements; + vkGetImageMemoryRequirements(self->device, allocation.image, &occ_memory_requirements); + U64 occ_taken_size = occ_memory_requirements.size; - RBTreeNode_KVPU64ToMargaretMAOccupation* next_occ_it = - RBTree_MapU64ToMargaretMAOccupation_find_next(&self->occupied_memory, occ_it); - if (next_occ_it != NULL) { - U64 next_occ_start = next_occ_it->key; + U64 next_occ_it = BufRBTree_MapU64ToU64_find_min_grtr(&block->images, allocation.start); + if (next_occ_it != 0) { + U64 next_occ_start; + U64 next_occ_taken_size; + BufRBTree_MapU64ToU64_at_iter(&block->images, next_occ_it, &next_occ_start, &next_occ_taken_size); assert(occ_start + occ_taken_size <= next_occ_start); return (U64Segment){.start = occ_start + occ_taken_size, .len = next_occ_start - (occ_start + occ_taken_size)}; } - return (U64Segment){.start = occ_start + occ_taken_size, .len = self->capacity - (occ_start + occ_taken_size)}; + return (U64Segment){.start = occ_start + occ_taken_size, .len = block->capacity - (occ_start + occ_taken_size)}; } -void MargaretMemAllocator__get_rid_of_memory_occupant_but_not_node( - MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* exile){ - MargaretMemAllocatorOneBlock* block = &exile->value.block->el; +void MargaretImgAllocator_drop(MargaretImgAllocator self){ + VecMargaretImgAllocatorOneBlock_drop(self.blocks); + MargaretMemFreeSpaceManager_drop(self.mem_free_space); +} - U64Segment left_free_space = MargaretMemAllocatorOneBlock_get_left_free_space(block, exile); - U64Segment right_free_space = MargaretMemAllocatorOneBlock_get_right_free_space(block, exile); +void MargaretImgAllocator_free(MargaretImgAllocator* self, MargaretImgAllocation allocation){ + U64Segment left_free_space = MargaretImgAllocator__get_left_free_space(self, allocation); + U64Segment right_free_space = MargaretImgAllocator__get_right_free_space(self, allocation); - const MargaretMAOccupant* occ = &exile->value.me; - if (occ->variant == MargaretMemoryOccupation_Buffer) { - vkDestroyBuffer(self->device, occ->buf.buffer, NULL); - } else if (occ->variant == MargaretMemoryOccupation_Image) { - vkDestroyImage(self->device, occ->img.image, NULL); - } + vkDestroyImage(self->device, allocation.image, NULL); - MargaretMemAllocator__erase_gap(self, exile->value.block, left_free_space.start, left_free_space.len); - MargaretMemAllocator__erase_gap(self, exile->value.block, right_free_space.start, right_free_space.len); - MargaretMemAllocator__insert_gap(self, exile->value.block, + MargaretImgAllocator__erase_gap(self, allocation.block, left_free_space.start, left_free_space.len); + MargaretImgAllocator__erase_gap(self, allocation.block, right_free_space.start, right_free_space.len); + MargaretImgAllocator__insert_gap(self, allocation.block, left_free_space.start, right_free_space.start + right_free_space.len - left_free_space.start); } -/* Either for temporary replacements of moved-expanded buffers, or for direct free_X requests */ -void MargaretMemAllocator__get_rid_of_memory_occupant_and_node( - MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* exile){ - MargaretMemAllocator__get_rid_of_memory_occupant_but_not_node(self, exile); - MargaretMemAllocatorOneBlock* block = &exile->value.block->el; - RBTree_MapU64ToMargaretMAOccupation_erase_by_iter(&block->occupied_memory, exile); -} - -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 (RBTreeNode_KVPU64ToMargaretMAOccupation* i = - RBTree_MapU64ToMargaretMAOccupation_find_min(&block->occupied_memory); i; - i = RBTree_MapU64ToMargaretMAOccupation_find_next(&block->occupied_memory, i)) - { - if (i->value.me.variant == MargaretMemoryOccupation_Buffer) { - vkDestroyBuffer(self->device, i->value.me.buf.buffer, NULL); - } else { - assert(i->value.me.variant == MargaretMemoryOccupation_Image); - vkDestroyImage(self->device, i->value.me.img.image, NULL); - } - } - vkFreeMemory(self->device, block->mem_hand, NULL); -} - -void MargaretMemAllocator_drop(MargaretMemAllocator self){ - for (ListNodeMargaretMemAllocatorOneBlock* block = self.old_blocks.first; block; block = block->next) { - ListNodeMargaretMemAllocatorOneBlock* next = block->next; - MargaretMemAllocator__clean_handlers_in_block(&self, &block->el); - free(block); - block = next; - } - for (ListNodeMargaretMemAllocatorOneBlock* block = self.blocks.first; block; block = block->next) { - ListNodeMargaretMemAllocatorOneBlock* next = block->next; - MargaretMemAllocator__clean_handlers_in_block(&self, &block->el); - free(block); - block = next; - } - VecMargaretMANewMovedBufRecord_drop(self.old_moved_buffers); - MargaretMemFreeSpaceManager_drop(self.mem_free_space); -} - -void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self){ - assert(self->old_blocks.first == NULL || self->old_moved_buffers.len == 0); - for (ListNodeMargaretMemAllocatorOneBlock* block = self->old_blocks.first; block; block = block->next) { - ListNodeMargaretMemAllocatorOneBlock* next = block->next; - MargaretMemAllocator__clean_handlers_in_block(self, &block->el); - free(block); - block = next; - } - self->old_blocks.first = NULL; - for (U64 ri = 0; ri < self->old_moved_buffers.len; ri++) { - MargaretMANewMovedBufRecord moved = self->old_moved_buffers.buf[ri]; - assert(moved.replacement->value.me.variant == MargaretMemoryOccupation_Buffer); - MargaretMemAllocator__get_rid_of_memory_occupant_and_node(self, moved.replacement); - } - VecMargaretMANewMovedBufRecord_sink(&self->old_moved_buffers, 0); -} - -void MargaretMemAllocator__shrink_some_buffer( - MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it, size_t smaller_size +MargaretImgAllocation MargaretImgAllocator_alloc( + MargaretImgAllocator* self, U64 width, U64 height, VkFormat format, + VkImageUsageFlags usage_flags, VkImageLayout current_layout ){ - ListNodeMargaretMemAllocatorOneBlock* block_it = occ_it->value.block; - MargaretMAOccupant* occ_me = &occ_it->value.me; - assert(occ_me->variant == MargaretMemoryOccupation_Buffer); - assert(occ_me->buf.capacity >= smaller_size); - U64 buf_start = occ_it->key; - U64 buf_taken_size = occ_it->value.taken_size; - VkBuffer shorter_buf; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = smaller_size, - .usage = occ_me->buf.usage_flags, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &shorter_buf) == VK_SUCCESS); - VkMemoryRequirements shorter_buf_req; - vkGetBufferMemoryRequirements(self->device, shorter_buf, &shorter_buf_req); - check(U64_is_2pow(shorter_buf_req.alignment)); - check((shorter_buf_req.memoryTypeBits & self->memory_type_id)); - check((buf_start & (shorter_buf_req.alignment - 1)) == 0) - check(shorter_buf_req.size <= buf_taken_size); - - U64Segment right_free_space = MargaretMemAllocatorOneBlock_get_right_free_space(&block_it->el, occ_it); - MargaretMemAllocator__erase_gap(self, block_it, right_free_space.start, right_free_space.len); - MargaretMemAllocator__insert_gap(self, block_it, - buf_start + shorter_buf_req.size, - right_free_space.len + (buf_taken_size - shorter_buf_req.size)); - - vkDestroyBuffer(self->device, occ_me->buf.buffer, NULL); - occ_it->value.taken_size = shorter_buf_req.size; - occ_me->buf.buffer = shorter_buf; - occ_me->buf.capacity = smaller_size; -} - -void MargaretMemAllocator__bind_buffer_memory(const MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it){ - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - check(vkBindBufferMemory(self->device, occ_it->value.me.buf.buffer, occ_it->value.block->el.mem_hand, occ_it->key) == VK_SUCCESS); -} - -void MargaretMemAllocator__bind_image_memory(const MargaretMemAllocator* self, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it){ - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Image); - check(vkBindImageMemory(self->device, occ_it->value.me.img.image, occ_it->value.block->el.mem_hand, occ_it->key) == VK_SUCCESS); -} - -void MargaretMemAllocator__thrust_a_block( - MargaretMemAllocator* self, ListNodeMargaretMemAllocatorOneBlock* cur_block, U64 capacity - ){ - check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){ - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .memoryTypeIndex = self->memory_type_id, - .allocationSize = capacity}, NULL, &cur_block->el.mem_hand) == VK_SUCCESS); - cur_block->el.capacity = capacity; - // todo: when I write MargaretBufAllocator and rewrite r0.c to use it, I will remove this whole "void* mapped_memory" crap - if (self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - check(vkMapMemory(self->device, cur_block->el.mem_hand, 0, VK_WHOLE_SIZE, - 0, &cur_block->el.mapped_memory) == VK_SUCCESS); - } - - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = RBTree_MapU64ToMargaretMAOccupation_find_min(&cur_block->el.occupied_memory); - while (occ_it) { - if (occ_it->value.me.variant == MargaretMemoryOccupation_Buffer) { - MargaretMemAllocator__bind_buffer_memory(self, occ_it); - } else { - MargaretMemAllocator__bind_image_memory(self, occ_it); - } - occ_it = RBTree_MapU64ToMargaretMAOccupation_find_next(&cur_block->el.occupied_memory, occ_it); - } -} - -/* Helper function for MargaretMemAllocator_request_needs_defragmentation */ -void MargaretMemAllocator__keep_building_up_cur_block( - MargaretMemAllocator* self, U64* cur_block_size_needed, ListNodeMargaretMemAllocatorOneBlock** cur_block, - U64* updated_total_capacity, - VkMemoryRequirements mem_requirements, RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it, - U64 maxMemoryAllocationSize - ){ - assert(*cur_block_size_needed < maxMemoryAllocationSize); - check(U64_is_2pow(mem_requirements.alignment)); - if (mem_requirements.size > maxMemoryAllocationSize) - abortf("Your object asks too much :(\n"); - U64 af = margaret_get_alignment_left_padding(*cur_block_size_needed, U64_2pow_log(mem_requirements.alignment)); - if (mem_requirements.size > maxMemoryAllocationSize) { - abortf("Your life sucks\n"); - } - if (*cur_block_size_needed + af + mem_requirements.size > maxMemoryAllocationSize) { - /* We use mem man method here directly because MMA__insert_gap has a side effect of requiring valid block */ - MargaretMemFreeSpaceManager_insert(&self->mem_free_space, *cur_block, - *cur_block_size_needed, maxMemoryAllocationSize - *cur_block_size_needed); - - MargaretMemAllocator__thrust_a_block(self, *cur_block, maxMemoryAllocationSize); - *updated_total_capacity += maxMemoryAllocationSize; - - *cur_block = (ListNodeMargaretMemAllocatorOneBlock*)safe_calloc(1, sizeof(ListNodeMargaretMemAllocatorOneBlock)); - (*cur_block)->el.occupied_memory = RBTree_MapU64ToMargaretMAOccupation_new(); - ListMargaretMemAllocatorOneBlock_insert_node(&self->blocks, *cur_block); - - *cur_block_size_needed = 0; - af = 0; - } - /* We use mem man method here directly because MMA__insert_gap has a side effect of requiring valid block, - * which is just not the case */ - MargaretMemFreeSpaceManager_insert(&self->mem_free_space, *cur_block, *cur_block_size_needed, af); - occ_it->key = *cur_block_size_needed + af; - occ_it->value.block = *cur_block; - occ_it->value.taken_size = mem_requirements.size; - RBTree_MapU64ToMargaretMAOccupation_insert_node(&(*cur_block)->el.occupied_memory, occ_it); - - /* Updating important counter */ - *cur_block_size_needed = *cur_block_size_needed + af + mem_requirements.size; -} - -MargaretMemAllocatorDemands MargaretMemAllocator_request_needs_defragmentation( - MargaretMemAllocator* self, MargaretMemAllocatorRequests* requests, - VecMargaretMABufferExpansionRecord buffer_expansion_record, - size_t alloc_buf_requests_require_cancel, size_t alloc_img_requests_require_cancel){ - VkPhysicalDeviceMaintenance3Properties maintenance3_properties = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, }; @@ -873,552 +433,46 @@ MargaretMemAllocatorDemands MargaretMemAllocator_request_needs_defragmentation( .pNext = &maintenance3_properties, }; vkGetPhysicalDeviceProperties2(self->physical_device, &properties); - check(vkResetCommandBuffer(self->command_buffer, 0) == VK_SUCCESS); - check(vkBeginCommandBuffer(self->command_buffer, &(VkCommandBufferBeginInfo){ - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO - }) == VK_SUCCESS); - /* You see, some of the expand_buffer requests were taken care of right away. And we popped them from - * request vector. Because we expanded buffer without moving it. Now we need to undo the expansions and - * regenerate expand_buffer request back in vector */ - for (size_t i = 0; i < buffer_expansion_record.len; i++) { - U64 old_capacity = buffer_expansion_record.buf[i].old_capacity; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = buffer_expansion_record.buf[i].occ_it; - assert(occ_it); - U64 needed_capacity = occ_it->value.me.buf.capacity; - MargaretMemAllocator__shrink_some_buffer(self, occ_it, old_capacity); - MargaretMemAllocator__bind_buffer_memory(self, occ_it); - VecMargaretMemAllocatorRequestResizeBuffer_append(&requests->expand_buf, - (MargaretMemAllocatorRequestResizeBuffer){.new_size = needed_capacity, .occ_it = occ_it}); - } - VecMargaretMABufferExpansionRecord_drop(buffer_expansion_record); - /* Also, if expand_buf request could not be carried out by simply expanding buffer, we would move it to - * another place. This could have happened prior to defragmentation call. - * Now we need to undo this. We store the record of such action in self->old_moved_buffers. The expand_buf - * request that resulted in such action is not popped, it is still in the vector. We just have to undo all - * changes. We moved occupant node to another place. leaving, `replacer` behind. It holds the original buffer. - * while our original node holds the new buffer, failed attempt to carry out request without defragmentation. - * We actually destroy the second (big) buffer and steal everything from replacer (stealing into original node) - */ - for (size_t i = 0; i < self->old_moved_buffers.len; i++) { - RBTreeNode_KVPU64ToMargaretMAOccupation* replacer = self->old_moved_buffers.buf[i].replacement; - RBTreeNode_KVPU64ToMargaretMAOccupation* my_occ_it = self->old_moved_buffers.buf[i].my_occ_it; - assert(replacer != NULL && my_occ_it != NULL); - assert(replacer->value.me.variant == MargaretMemoryOccupation_Buffer); - assert(my_occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); + VkImage fresh_img; + check(vkCreateImage(self->device, &(VkImageCreateInfo){ + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = format, + .extent = (VkExtent3D){.width = width, .height = height,.depth = 1,}, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = usage_flags, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .initialLayout = current_layout, + }, NULL, &fresh_img) == VK_SUCCESS); + VkMemoryRequirements mem_requirements; + vkGetImageMemoryRequirements(self->device, fresh_img, &mem_requirements); - RBTree_MapU64ToMargaretMAOccupation* OLD_TREE = &replacer->value.block->el.occupied_memory; - RBTree_MapU64ToMargaretMAOccupation* NEW_TREE = &my_occ_it->value.block->el.occupied_memory; - RBTree_erase_empty_by_iter(&NEW_TREE->root, NEW_TREE->NIL, &my_occ_it->base); - - MargaretMemAllocator__get_rid_of_memory_occupant_but_not_node(self, my_occ_it); - // my_occ_it remains correct - RBTree_steal_neighbours(&OLD_TREE->root, OLD_TREE->NIL, &replacer->base, &my_occ_it->base); - // now nobody knows about replacer - my_occ_it->key = replacer->key; - my_occ_it->value = replacer->value; - // now everything important was moved to my_occ_it. Replacer can be freed - free(replacer); - } - self->old_moved_buffers.len = 0; - - for (size_t i = 0; i < alloc_buf_requests_require_cancel; i++) { - RBTreeNode_KVPU64ToMargaretMAOccupation* given_occ_it = requests->alloc_buf.buf[i].new_node; - assert(given_occ_it && given_occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - MargaretMemAllocator__get_rid_of_memory_occupant_but_not_node(self, given_occ_it); - } - for (size_t i = 0; i < alloc_img_requests_require_cancel; i++) { - RBTreeNode_KVPU64ToMargaretMAOccupation* given_occ_it = requests->alloc_image.buf[i].new_node; - assert(given_occ_it && given_occ_it->value.me.variant == MargaretMemoryOccupation_Image); - MargaretMemAllocator__get_rid_of_memory_occupant_but_not_node(self, given_occ_it); + check(U64_is_2pow(mem_requirements.alignment)); + U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); + check(mem_requirements.size <= maintenance3_properties.maxMemoryAllocationSize); + OptionMargaretFreeSegment free_gap = + MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); + if (free_gap.variant == Option_None) { + assert(self->blocks.len > 0); + U64 pitch = self->blocks.buf[self->blocks.len - 1].capacity; + // Old blocks remain intact + U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize)); + U64 bid = MargaretImgAllocator__add_block(self, new_capacity); + MargaretImgAllocator__add_img_given_gap(self, + (MargaretFreeSegment){.block = bid, .start = 0, .len = new_capacity}, mem_requirements.size, alignment_exp); + MargaretImgAllocator__insert_gap(self, bid, mem_requirements.size, new_capacity - mem_requirements.size); + bool iret = BufRBTree_MapU64ToU64_insert(&self->blocks.buf[bid].images, 0, mem_requirements.size); + VkDeviceMemory memory = VecMargaretImgAllocatorOneBlock_at(&self->blocks, free_gap.some.block)->mem_hand; + check(vkBindImageMemory(self->device, fresh_img, memory, 0) == VK_SUCCESS); } - /* END OF REVERTING. WE REVERTED EVERYTHING */ - - /* We came here because we ran out of space. We defragment everything there is to defragment */ - assert(self->old_blocks.first == NULL); - self->old_blocks.first = self->blocks.first; - self->blocks.first = NULL; - // this variable will be updated later by `updated_total_capacity` - U64 old_total_capacity = self->total_capacity; - - /* Cleaning free space set from gaps of old blocks */ - for (ListNodeMargaretMemAllocatorOneBlock* block_it = self->old_blocks.first; block_it; block_it = block_it->next){ - RBTreeNode_KVPU64ToMargaretMAOccupation* cur = RBTree_MapU64ToMargaretMAOccupation_find_min( - &block_it->el.occupied_memory); - U64 prev_end = 0; - while (cur) { - MargaretMemAllocator__erase_gap(self, block_it, prev_end, cur->key - prev_end); - prev_end = cur->key + cur->value.taken_size; - cur = RBTree_MapU64ToMargaretMAOccupation_find_next(&block_it->el.occupied_memory, cur); - } - MargaretMemAllocator__erase_gap(self, block_it, prev_end, block_it->el.capacity - prev_end); - } - - U64 updated_total_capacity = 0; - /* It's used as a counter before the actual VkDeviceMemory is allocated. - * (To know how much memory needs to be allocated ) */ - U64 cur_block_size_needed = 0; - ListNodeMargaretMemAllocatorOneBlock* cur_block = safe_calloc(1, sizeof(ListNodeMargaretMemAllocatorOneBlock)); - cur_block->el.occupied_memory = RBTree_MapU64ToMargaretMAOccupation_new(); - ListMargaretMemAllocatorOneBlock_insert_node(&self->blocks, cur_block); - - MargaretMemAllocatorDemands demands = requests->expand_buf.len ? MARGARET_MA_DEMANDS_CMD_BUFFER_BIT : 0; - - for (size_t i = 0; i < requests->expand_buf.len; i++) { - U64 needed_buf_capacity = requests->expand_buf.buf[i].new_size; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->expand_buf.buf[i].occ_it; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - - RBTreeNode_KVPU64ToMargaretMAOccupation* replacer = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); - { - RBTree_MapU64ToMargaretMAOccupation* OLD_TREE = &occ_it->value.block->el.occupied_memory; - RBTree_steal_neighbours(&OLD_TREE->root, OLD_TREE->NIL, &occ_it->base, &replacer->base); - } - replacer->key = occ_it->key; - replacer->value = occ_it->value; - replacer->value.me.buf.moved_already = true; - - VkBuffer fresh_buf; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = replacer->value.me.buf.usage_flags, - .size = needed_buf_capacity, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE - }, NULL, &fresh_buf) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(self->device, fresh_buf, &mem_requirements); - - occ_it->value.me.buf.buffer = fresh_buf; - occ_it->value.me.buf.capacity = needed_buf_capacity; - - MargaretMemAllocator__keep_building_up_cur_block(self, - &cur_block_size_needed, &cur_block, &updated_total_capacity, mem_requirements, - occ_it, maintenance3_properties.maxMemoryAllocationSize); - - if (occ_it->value.me.buf.preserve_at_quiet) { - vkCmdCopyBuffer(self->command_buffer, replacer->value.me.buf.buffer, occ_it->value.me.buf.buffer, 1, &(VkBufferCopy){ - .srcOffset = 0, .dstOffset = 0, .size = replacer->value.me.buf.capacity}); - } - } - - for (size_t i = 0; i < requests->alloc_buf.len; i++) { - MargaretMemAllocatorRequestAllocBuffer* req = &requests->alloc_buf.buf[i]; - U64 needed_buf_capacity = req->allocation_size; - - VkBuffer fresh_buf; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = req->usage, - .size = needed_buf_capacity, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE - }, NULL, &fresh_buf) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(self->device, fresh_buf, &mem_requirements); - - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = req->new_node; /* It was allocated for us */ - occ_it->value.me.variant = MargaretMemoryOccupation_Buffer; - occ_it->value.me.buf.buffer = fresh_buf; - occ_it->value.me.buf.capacity = needed_buf_capacity; - occ_it->value.me.buf.usage_flags = req->usage; - occ_it->value.me.buf.preserve_at_quiet = req->preserve_at_quiet; - occ_it->value.me.buf.moved_already = false; - - MargaretMemAllocator__keep_building_up_cur_block(self, &cur_block_size_needed, - &cur_block, &updated_total_capacity, mem_requirements, - occ_it, maintenance3_properties.maxMemoryAllocationSize); - } - - for (size_t i = 0; i < requests->alloc_image.len; i++) { - MargaretMemAllocatorRequestAllocImage* req = &requests->alloc_image.buf[i]; - - VkImage fresh_image; - check(vkCreateImage(self->device, &(VkImageCreateInfo){ - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = req->format, - .extent = (VkExtent3D){ .width = req->width, .height = req->height, .depth = 1, }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = req->usage_flags, - .initialLayout = req->current_layout, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &fresh_image) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetImageMemoryRequirements(self->device, fresh_image, &mem_requirements); - - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = req->new_node; - occ_it->value.me.variant = MargaretMemoryOccupation_Image; - occ_it->value.me.img = (MargaretMemoryOccupationImage){ - .width = req->width, .height = req->height, .usage_flags = req->usage_flags, - .current_layout = req->current_layout, .current_dest_stage_mask = req->current_dest_stage_mask, - .current_dest_access_mask = req->current_dest_access_mask, - .format = req->format, .image = fresh_image, - .preserve_at_quiet = req->preserve_at_quiet - }; - MargaretMemAllocator__keep_building_up_cur_block(self, &cur_block_size_needed, - &cur_block, &updated_total_capacity, mem_requirements, - occ_it, maintenance3_properties.maxMemoryAllocationSize); - } - - /* We move blocks here, but not because some request asked, no, we migrate all unmoved blocks from */ - for (ListNodeMargaretMemAllocatorOneBlock* block_it = self->old_blocks.first; block_it; block_it = block_it->next) { - RBTree_MapU64ToMargaretMAOccupation* OLD_TREE = &block_it->el.occupied_memory; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = RBTree_MapU64ToMargaretMAOccupation_find_min(OLD_TREE); - if (occ_it) - demands |= MARGARET_MA_DEMANDS_CMD_BUFFER_BIT; - while (occ_it) { - if (occ_it->value.me.variant == MargaretMemoryOccupation_Buffer && occ_it->value.me.buf.moved_already) { - occ_it = RBTree_MapU64ToMargaretMAOccupation_find_next(OLD_TREE, occ_it); - continue; - } - RBTreeNode_KVPU64ToMargaretMAOccupation* replacer = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); - RBTree_steal_neighbours(&OLD_TREE->root, OLD_TREE->NIL, &occ_it->base, &replacer->base); - replacer->key = occ_it->key; - replacer->value = occ_it->value; - - if (replacer->value.me.variant == MargaretMemoryOccupation_Buffer) { - VkBuffer fresh_buf; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = replacer->value.me.buf.usage_flags, - .size = replacer->value.me.buf.capacity, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE - }, NULL, &fresh_buf) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(self->device, fresh_buf, &mem_requirements); - - occ_it->value.me.buf.buffer = fresh_buf; - - /* This function changes occ_it->taken_size and, of course, occ_it->block */ - MargaretMemAllocator__keep_building_up_cur_block(self, &cur_block_size_needed, - &cur_block, &updated_total_capacity, mem_requirements, - occ_it, maintenance3_properties.maxMemoryAllocationSize); - - if (occ_it->value.me.buf.preserve_at_quiet) { - vkCmdCopyBuffer(self->command_buffer, replacer->value.me.buf.buffer, occ_it->value.me.buf.buffer, 1, &(VkBufferCopy){ - .srcOffset = 0, .dstOffset = 0, .size = replacer->value.me.buf.capacity}); - } - } else { - VkImage fresh_image; - check(vkCreateImage(self->device, &(VkImageCreateInfo){ - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = replacer->value.me.img.format, - .extent = (VkExtent3D){ - .width = replacer->value.me.img.width, .height = replacer->value.me.img.height, .depth = 1, - }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = replacer->value.me.img.usage_flags, - .initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &fresh_image) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetImageMemoryRequirements(self->device, fresh_image, &mem_requirements); - - occ_it->value.me.img.image = fresh_image; - MargaretMemAllocator__keep_building_up_cur_block(self, &cur_block_size_needed, - &cur_block, &updated_total_capacity, mem_requirements, - occ_it, maintenance3_properties.maxMemoryAllocationSize); - - if (occ_it->value.me.img.preserve_at_quiet) { - VkImageMemoryBarrier first_barriers[2] = { - (VkImageMemoryBarrier){ /* Source image */ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = replacer->value.me.img.image, - .subresourceRange = (VkImageSubresourceRange){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, - .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1, - }, - }, - (VkImageMemoryBarrier){ /* Destination image */ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = occ_it->value.me.img.image, - .subresourceRange = (VkImageSubresourceRange){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, - .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1, - }, - } - }; - vkCmdPipelineBarrier(self->command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0 /* Flags */, 0, NULL /* not here */, 0, NULL /* not here */, - 2, first_barriers); - vkCmdCopyImage(self->command_buffer, replacer->value.me.img.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - fresh_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &(VkImageCopy){ - .srcSubresource = (VkImageSubresourceLayers){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, - .baseArrayLayer = 0, .layerCount = 1, - }, - .srcOffset = {0, 0, 0}, - .dstSubresource = (VkImageSubresourceLayers){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, - .baseArrayLayer = 0, .layerCount = 1, - }, - .dstOffset = {0, 0, 0}, - .extent = (VkExtent3D){ - .width = replacer->value.me.img.width, .height = replacer->value.me.img.height, - .depth = 1 - } - }); - VkImageMemoryBarrier finishing_barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = occ_it->value.me.img.current_dest_access_mask, - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .newLayout = occ_it->value.me.img.current_layout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = occ_it->value.me.img.image, - .subresourceRange = (VkImageSubresourceRange){ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, - .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1, - }, - }; - vkCmdPipelineBarrier(self->command_buffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, occ_it->value.me.img.current_dest_stage_mask, - 0 /* Flags*/, 0, NULL, 0, NULL, 1, &finishing_barrier); - } - } - - occ_it = RBTree_MapU64ToMargaretMAOccupation_find_next(OLD_TREE, replacer); - } - } - - assert(cur_block_size_needed > 0 && cur_block_size_needed <= maintenance3_properties.maxMemoryAllocationSize); - /* Finalizing the very last MMA block */ - U64 desirable_gain = 2 * old_total_capacity; - U64 shizhlyazhki = desirable_gain > updated_total_capacity ? desirable_gain - updated_total_capacity : 0; - U64 fin_block_capacity = MIN_U64(maintenance3_properties.maxMemoryAllocationSize, - MAX_U64(cur_block_size_needed, shizhlyazhki)); - - MargaretMemAllocator__thrust_a_block(self, cur_block, fin_block_capacity); - - updated_total_capacity += fin_block_capacity; - self->total_capacity = updated_total_capacity; - MargaretMemAllocatorRequests_sink(requests); - assert(self->old_moved_buffers.len == 0); - return demands | MARGARET_MA_DEMANDS_DEFRAGMENTATION_BIT; -} - -MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request( - MargaretMemAllocator* self, MargaretMemAllocatorRequests* requests - ){ - MargaretMemAllocator_wipe_old(self); - for (size_t i = 0; i < requests->free_buf.len; i++) { - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->free_buf.buf[i]; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - MargaretMemAllocator__get_rid_of_memory_occupant_and_node(self, occ_it); - } - for (size_t i = 0; i < requests->free_image.len; i++) { - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->free_image.buf[i]; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Image); - MargaretMemAllocator__get_rid_of_memory_occupant_and_node(self, occ_it); - } - for (size_t i = 0; i < requests->shrink_buf.len; i++) { - MargaretMemAllocatorRequestResizeBuffer req = (requests->shrink_buf.buf[i]); - MargaretMemAllocator__shrink_some_buffer(self, req.occ_it, req.new_size); - MargaretMemAllocator__bind_buffer_memory(self, req.occ_it); - } - - VecMargaretMABufferExpansionRecord buffer_expansion_record = VecMargaretMABufferExpansionRecord_new(); - assert(self->old_moved_buffers.len == 0); - - /* We first try to do all the expand_buf requests, that COULD be done using method 1 */ - for (U64 rr = 0; rr < requests->expand_buf.len;) { - U64 new_size = requests->expand_buf.buf[rr].new_size; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->expand_buf.buf[rr].occ_it; - - U64 occ_start = occ_it->key; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - MargaretMemoryOccupationBuffer* buf = &occ_it->value.me.buf; - - /* Method 1 */ - U64Segment right_free_space = MargaretMemAllocatorOneBlock_get_right_free_space( - &occ_it->value.block->el, occ_it); - - VkBuffer temp_buf_extension; - check (vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = new_size, - .usage = buf->usage_flags, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &temp_buf_extension) == VK_SUCCESS); - VkMemoryRequirements temp_buf_extension_req; - vkGetBufferMemoryRequirements(self->device, temp_buf_extension, &temp_buf_extension_req); - check(U64_is_2pow(temp_buf_extension_req.alignment)); - check((temp_buf_extension_req.memoryTypeBits & (1ull << self->memory_type_id)) > 0) - if ((occ_start + temp_buf_extension_req.size > right_free_space.start + right_free_space.len) || - ((occ_start & (temp_buf_extension_req.alignment - 1)) != 0) - ){ - vkDestroyBuffer(self->device, temp_buf_extension, NULL); - rr++; - continue; - } - MargaretMemAllocator__erase_gap(self, occ_it->value.block, right_free_space.start, right_free_space.len); - MargaretMemAllocator__insert_gap(self, occ_it->value.block, - occ_start + temp_buf_extension_req.size, - right_free_space.start + right_free_space.len - (occ_start + temp_buf_extension_req.size)); - VecMargaretMABufferExpansionRecord_append(&buffer_expansion_record, (MargaretMABufferExpansionRecord){ - .old_capacity = buf->capacity, .occ_it = occ_it - }); - /* Success */ - vkDestroyBuffer(self->device, buf->buffer, NULL); - buf->capacity = new_size; - buf->buffer = temp_buf_extension; - occ_it->value.taken_size = temp_buf_extension_req.size; - VecMargaretMemAllocatorRequestResizeBuffer_unordered_pop(&requests->expand_buf, rr); - MargaretMemAllocator__bind_buffer_memory(self, occ_it); - } - - check(vkResetCommandBuffer(self->command_buffer, 0) == VK_SUCCESS); - check(vkBeginCommandBuffer(self->command_buffer, &(VkCommandBufferBeginInfo){ - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO - }) == VK_SUCCESS); - MargaretMemAllocatorDemands demands = 0; - - for (U64 ri = 0; ri < requests->expand_buf.len; ri++) { - U64 larger_size = requests->expand_buf.buf[ri].new_size; - RBTreeNode_KVPU64ToMargaretMAOccupation* occ_it = requests->expand_buf.buf[ri].occ_it; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - assert(larger_size >= occ_it->value.me.buf.capacity); - - VkBuffer bigger_buffer; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = larger_size, - .usage = occ_it->value.me.buf.usage_flags, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &bigger_buffer) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(self->device, bigger_buffer, &mem_requirements); - - check(U64_is_2pow(mem_requirements.alignment)); - U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); - OptionMargaretFreeMemSegment free_gap = - MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); - if (free_gap.variant == Option_None) { - vkDestroyBuffer(self->device, bigger_buffer, NULL); - return MargaretMemAllocator_request_needs_defragmentation(self, requests, buffer_expansion_record, 0, 0); - } - - RBTreeNode_KVPU64ToMargaretMAOccupation* replacer = safe_malloc(sizeof(RBTreeNode_KVPU64ToMargaretMAOccupation)); - RBTree_MapU64ToMargaretMAOccupation* OLD_TREE = &occ_it->value.block->el.occupied_memory; - RBTree_steal_neighbours(&OLD_TREE->root, OLD_TREE->NIL, &occ_it->base, &replacer->base); - replacer->key = occ_it->key; - replacer->value = occ_it->value; - assert(replacer->value.me.variant == MargaretMemoryOccupation_Buffer); - occ_it->value.me.buf.buffer = bigger_buffer; - occ_it->value.me.buf.capacity = larger_size; - - MargaretMemAllocator__add_occupant_node_given_gap_any_type(self, occ_it, free_gap.some, mem_requirements.size, alignment_exp); - MargaretMemAllocator__bind_buffer_memory(self, occ_it); - - VecMargaretMANewMovedBufRecord_append(&self->old_moved_buffers, - (MargaretMANewMovedBufRecord){.replacement = replacer, .my_occ_it = occ_it}); - if (replacer->value.me.buf.preserve_at_quiet) { - demands = MARGARET_MA_DEMANDS_CMD_BUFFER_BIT; - vkCmdCopyBuffer(self->command_buffer, replacer->value.me.buf.buffer, bigger_buffer, - 1, &(VkBufferCopy){0, 0, replacer->value.me.buf.capacity}); - } - } - - for (U64 ri = 0; ri < requests->alloc_buf.len; ri++) { - MargaretMemAllocatorRequestAllocBuffer* req = &requests->alloc_buf.buf[ri]; - - VkBuffer fresh_buf; - check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = req->allocation_size, - .usage = req->usage, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }, NULL, &fresh_buf) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(self->device, fresh_buf, &mem_requirements); - check(U64_is_2pow(mem_requirements.alignment)); - U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); - OptionMargaretFreeMemSegment free_gap = - MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); - if (free_gap.variant == Option_None) { - vkDestroyBuffer(self->device, fresh_buf, NULL); - return MargaretMemAllocator_request_needs_defragmentation(self, requests, buffer_expansion_record, 0, 0); - } - - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node = req->new_node; /* It was allocated for us */ - new_node->value.me = (MargaretMAOccupant){.variant = MargaretMemoryOccupation_Buffer, .buf = { - .buffer = fresh_buf, .capacity = req->allocation_size, .preserve_at_quiet = req->allocation_size, - .usage_flags = req->usage - }}; - MargaretMemAllocator__add_occupant_node_given_gap_any_type(self, new_node, free_gap.some, mem_requirements.size, alignment_exp); - MargaretMemAllocator__bind_buffer_memory(self, new_node); - } - - for (U64 ri = 0; ri < requests->alloc_image.len; ri++) { - MargaretMemAllocatorRequestAllocImage* req = &requests->alloc_image.buf[ri]; - - VkImage fresh_img; - check(vkCreateImage(self->device, &(VkImageCreateInfo){ - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = req->format, - .extent = (VkExtent3D){.width = req->width, .height = req->height,.depth = 1,}, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = req->usage_flags, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .initialLayout = req->current_layout, - }, NULL, &fresh_img) == VK_SUCCESS); - VkMemoryRequirements mem_requirements; - vkGetImageMemoryRequirements(self->device, fresh_img, &mem_requirements); - - check(U64_is_2pow(mem_requirements.alignment)); - U8 alignment_exp = U64_2pow_log(mem_requirements.alignment); - OptionMargaretFreeMemSegment free_gap = - MargaretMemFreeSpaceManager_search(&self->mem_free_space, alignment_exp, mem_requirements.size); - if (free_gap.variant == Option_None) { - vkDestroyImage(self->device, fresh_img, NULL); - return MargaretMemAllocator_request_needs_defragmentation(self, requests, buffer_expansion_record, 0, 0); - } - - RBTreeNode_KVPU64ToMargaretMAOccupation* new_node = req->new_node; /* MMARequests class allocated it for us */ - new_node->value.me = (MargaretMAOccupant){.variant = MargaretMemoryOccupation_Image, .img = { - .image = fresh_img, .width = req->width, .height = req->height, .format = req->format, - .usage_flags = req->usage_flags, .current_layout = req->current_layout, - .current_dest_stage_mask = req->current_dest_stage_mask, - .current_dest_access_mask = req->current_dest_access_mask, .preserve_at_quiet = req->preserve_at_quiet - }}; - MargaretMemAllocator__add_occupant_node_given_gap_any_type(self, new_node, free_gap.some, mem_requirements.size, alignment_exp); - MargaretMemAllocator__bind_buffer_memory(self, new_node); - } - - MargaretMemAllocatorRequests_sink(requests); - return demands; -} - -typedef RBTreeNode_KVPU64ToMargaretMAOccupation* MargaretMAIterator; - -char* MargaretMAIterator_get_mapped(MargaretMAIterator occ_it){ - const MargaretMemAllocatorOneBlock* bl = &occ_it->value.block->el; - assert(occ_it->value.me.variant == MargaretMemoryOccupation_Buffer); - assert(bl->mapped_memory); - return (char*)bl->mapped_memory + occ_it->key; + U64 aligned_pos = MargaretImgAllocator__add_img_given_gap(self, free_gap.some, mem_requirements.size, alignment_exp); + VkDeviceMemory memory = VecMargaretImgAllocatorOneBlock_at(&self->blocks, free_gap.some.block)->mem_hand; + check(vkBindImageMemory(self->device, fresh_img, memory, aligned_pos) == VK_SUCCESS); + return (MargaretImgAllocation){.block = free_gap.some.block, .image = fresh_img, .start = aligned_pos}; } diff --git a/src/l2/tests/data_structures/t2.c b/src/l2/tests/data_structures/t2.c index 5af0ab2..2d69d3f 100644 --- a/src/l2/tests/data_structures/t2.c +++ b/src/l2/tests/data_structures/t2.c @@ -235,23 +235,6 @@ void vkGetPhysicalDeviceProperties2( typedef int VkCommandBufferResetFlags; -VkResult vkResetCommandBuffer( - VkCommandBuffer commandBuffer, - VkCommandBufferResetFlags flags); - -typedef int VkCommandBufferUsageFlags; - -typedef struct VkCommandBufferBeginInfo { - VkStructureType sType; - const void* pNext; - VkCommandBufferUsageFlags flags; - const void* pInheritanceInfo; /* will be NULL */ -} VkCommandBufferBeginInfo; - -VkResult vkBeginCommandBuffer( - VkCommandBuffer commandBuffer, - const VkCommandBufferBeginInfo* pBeginInfo); - typedef int VkAccessFlags; const VkAccessFlags VK_ACCESS_TRANSFER_READ_BIT = 0x100; const VkAccessFlags VK_ACCESS_TRANSFER_WRITE_BIT = 0x100000; @@ -259,108 +242,8 @@ const VkAccessFlags VK_ACCESS_TRANSFER_WRITE_BIT = 0x100000; typedef int VkImageAspectFlags; const VkImageAspectFlags VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001; -typedef struct VkImageSubresourceRange { - VkImageAspectFlags aspectMask; - uint32_t baseMipLevel; - uint32_t levelCount; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceRange; - const uint32_t VK_QUEUE_FAMILY_IGNORED = (~0U); -typedef struct VkImageMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier; - -typedef int VkPipelineStageFlags; -const VkPipelineStageFlags VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x1; -const VkPipelineStageFlags VK_PIPELINE_STAGE_TRANSFER_BIT = 0x2; - -typedef int VkDependencyFlags; - -void vkCmdPipelineBarrier( - VkCommandBuffer commandBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - uint32_t memoryBarrierCount, - const void* /* VkMemoryBarrier */ pMemoryBarriers, - uint32_t bufferMemoryBarrierCount, - const void* /* VkBufferMemoryBarrier */ pBufferMemoryBarriers, - uint32_t imageMemoryBarrierCount, - const VkImageMemoryBarrier* pImageMemoryBarriers); - -typedef struct VkImageSubresourceLayers { - VkImageAspectFlags aspectMask; - uint32_t mipLevel; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceLayers; - -typedef struct VkOffset3D { - int32_t x; - int32_t y; - int32_t z; -} VkOffset3D; - -typedef struct VkBufferImageCopy { - VkDeviceSize bufferOffset; - uint32_t bufferRowLength; - uint32_t bufferImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkBufferImageCopy; - -void vkCmdCopyBufferToImage( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkBufferImageCopy* pRegions); - -typedef struct VkBufferCopy { - VkDeviceSize srcOffset; - VkDeviceSize dstOffset; - VkDeviceSize size; -} VkBufferCopy; - -void vkCmdCopyBuffer( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkBuffer dstBuffer, - uint32_t regionCount, - const VkBufferCopy* pRegions); - -typedef struct VkImageCopy { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy; - -void vkCmdCopyImage( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkImageCopy* pRegions); - - #include "../../margaret/vulkan_memory_claire.h" int main(){