From aadc346f43f744a7890b8c2e9be00a7e349dab8d Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Thu, 11 Dec 2025 02:12:21 +0300 Subject: [PATCH] What I have been doing for two months could actually be have been done in one day effortlessly --- CMakeLists.txt | 2 +- src/l1/anne/margaret/margaret_misc.h | 1 + src/l1_5/anne/margaret.h | 1 - src/l2/margaret/allocator_base.h | 6 + src/l2/margaret/vulkan_buffer_claire.h | 397 ++++++++++-------- ...memory_claire.h => vulkan_images_claire.h} | 34 +- src/l2/margaret/vulkan_memory.h | 3 +- src/l2/tests/data_structures/t2.c | 120 +++++- 8 files changed, 372 insertions(+), 192 deletions(-) rename src/l2/margaret/{vulkan_memory_claire.h => vulkan_images_claire.h} (94%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37a54ee..95a8639 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -l #add_executable(l2t0_2 src/l2/tests/data_structures/t0_2.c) // todo: I will get back add_executable(l2t0 src/l2/tests/data_structures/t0.c) add_executable(l2t0_3 src/l2/tests/data_structures/t0_3.c) -add_executable(l2t2 src/l2/tests/data_structures/t2.c) +#add_executable(l2t2 src/l2/tests/data_structures/t2.c) #add_executable(l2t0 src/l2/tests/data_structures/t0.c) #add_executable(l2t1 src/l2/tests/data_structures/t1.c) diff --git a/src/l1/anne/margaret/margaret_misc.h b/src/l1/anne/margaret/margaret_misc.h index edacaf4..49f2506 100644 --- a/src/l1/anne/margaret/margaret_misc.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -22,6 +22,7 @@ void generate_margaret_eve_for_vulkan_utils() { .T = cstr("BufRBTreeByLenRespAlign_SetMargaretFreeSegment")}); generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretImgAllocatorOneBlock"), true, false); + generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretBufAllocatorOneBlock"), true, false); } diff --git a/src/l1_5/anne/margaret.h b/src/l1_5/anne/margaret.h index 8478ef7..423d59a 100644 --- a/src/l1_5/anne/margaret.h +++ b/src/l1_5/anne/margaret.h @@ -22,7 +22,6 @@ void generate_l1_5_template_instantiations_for_margaret(){ /* comparison takes additional U8 parameter */ .alternative_less = cstr("MargaretFreeSegment_less_len"), .alternative_comp_set_name_embed = cstr("Len"), - .guest_data_T = cstr("U8"), }); } diff --git a/src/l2/margaret/allocator_base.h b/src/l2/margaret/allocator_base.h index c9efa1d..d47207b 100644 --- a/src/l2/margaret/allocator_base.h +++ b/src/l2/margaret/allocator_base.h @@ -38,4 +38,10 @@ bool MargaretFreeSegment_less_resp_align(const MargaretFreeSegment* A, const Mar #include "../../../gen/l1/eve/margaret/VecMargaretFreeSegment.h" #include "../../../gen/l1/eve/margaret/OptionMargaretFreeSegment.h" +U64 margaret_bump_buffer_size_to_alignment(U64 A, U8 alignment_exp){ + if (A & ((1ull << alignment_exp) - 1)) + A = A - (A & ((1ull << alignment_exp) - 1)) + (1ull << alignment_exp); + return A; +} + #endif diff --git a/src/l2/margaret/vulkan_buffer_claire.h b/src/l2/margaret/vulkan_buffer_claire.h index 32db8e9..02a29ba 100644 --- a/src/l2/margaret/vulkan_buffer_claire.h +++ b/src/l2/margaret/vulkan_buffer_claire.h @@ -8,187 +8,244 @@ typedef struct { U64 block; U64 start; + U64 len; } MargaretBufAllocation; +typedef struct { + BufRBTree_MapU64ToU64 occupants; + U64 capacity; + U64 occupation_counter; + VkDeviceMemory mem_hand; + VkBuffer buf_hand; + void* mapped_memory; +} MargaretBufAllocatorOneBlock; + +void MargaretBufAllocatorOneBlock_drop(MargaretBufAllocatorOneBlock self){ + BufRBTree_MapU64ToU64_drop(self.occupants); +} + +#include "../../../gen/l1/eve/margaret/VecMargaretBufAllocatorOneBlock.h" +#include "../../../gen/l1/VecAndSpan_U8.h" +#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLen_SetMargaretFreeSegment.h" + +typedef struct{ + VecMargaretBufAllocatorOneBlock blocks; + BufRBTreeByLen_SetMargaretFreeSegment mem_free_space; + VkDevice device; + VkPhysicalDevice physical_device; + VkBufferUsageFlags usage; + U8 memory_type_id; + U8 alignment_exp; + bool host_visible; +} MargaretBufAllocator; +void MargaretBufAllocator__erase_gap(MargaretBufAllocator* self, U64 block_id, U64 start, U64 len){ + if (len == 0) + return; + bool eret = BufRBTreeByLen_SetMargaretFreeSegment_erase(&self->mem_free_space, + &(MargaretFreeSegment){.block = block_id, .start = start, .len = len}); + assert(eret); + MargaretBufAllocatorOneBlock* BLOCK = VecMargaretBufAllocatorOneBlock_mat(&self->blocks, block_id); + BLOCK->occupation_counter += len; + assert(BLOCK->occupation_counter <= BLOCK->capacity); +} + +void MargaretBufAllocator__insert_gap(MargaretBufAllocator* self, U64 block_id, U64 start, U64 len){ + if (len == 0) + return; + bool iret = BufRBTreeByLen_SetMargaretFreeSegment_insert(&self->mem_free_space, + (MargaretFreeSegment){.block = block_id, .start = start, .len = len}); + assert(iret); + MargaretBufAllocatorOneBlock* BLOCK = VecMargaretBufAllocatorOneBlock_mat(&self->blocks, block_id); + assert(len <= BLOCK->occupation_counter); + BLOCK->occupation_counter -= len; +} + +OptionMargaretFreeSegment MargaretBufAllocator__search_gap(MargaretBufAllocator* self, U64 req_size){ + assert(req_size % (1ull << self->alignment_exp) == 0); + U64 sit = BufRBTreeByLen_SetMargaretFreeSegment_find_min_grtr_or_eq(&self->mem_free_space, + &(MargaretFreeSegment){.len = req_size}); + if (sit == 0) + return None_MargaretFreeSegment(); + return Some_MargaretFreeSegment(*BufRBTreeByLen_SetMargaretFreeSegment_at_iter(&self->mem_free_space, sit)); +} + +void MargaretBufAllocator__add_block(MargaretBufAllocator* self, U64 capacity){ + VkBuffer buffer; + check(vkCreateBuffer(self->device, &(VkBufferCreateInfo){ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = capacity, + .usage = self->usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE + }, NULL, &buffer) == VK_SUCCESS); + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements(self->device, buffer, &memory_requirements); + VkDeviceMemory memory; + check(vkAllocateMemory(self->device, &(VkMemoryAllocateInfo){ + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = self->memory_type_id + }, NULL, &memory) == VK_SUCCESS); + check(vkBindBufferMemory(self->device, buffer, memory, 0) == VK_SUCCESS); + void* mapped_memory = NULL; + if (self->host_visible) { + check(vkMapMemory(self->device, memory, 0, capacity, 0, &mapped_memory) == VK_SUCCESS); + } + VecMargaretBufAllocatorOneBlock_append(&self->blocks, (MargaretBufAllocatorOneBlock){ + .occupants = BufRBTree_MapU64ToU64_new_reserved(1), + .capacity = capacity, + .occupation_counter = 0, + .mem_hand = memory, .buf_hand = buffer, .mapped_memory = mapped_memory + }); +} + +MargaretBufAllocator MargaretBufAllocator_new( + VkDevice device, VkPhysicalDevice physical_device, + VkBufferUsageFlags usage, U8 memory_type_id, U8 alignment_exp, bool host_visible, U64 initial_block_size + ){ + MargaretBufAllocator self = { + .blocks = VecMargaretBufAllocatorOneBlock_new(), + .mem_free_space = BufRBTreeByLen_SetMargaretFreeSegment_new_reserved(1), + .device = device, .physical_device = physical_device, .usage = usage, .memory_type_id = memory_type_id, + .alignment_exp = alignment_exp, .host_visible = host_visible + }; + MargaretBufAllocator__add_block(&self, initial_block_size); + MargaretBufAllocator__insert_gap(&self, 0, 0, initial_block_size); + return self; +} + +void MargaretBufAllocator__put_buf_to_a_gap(MargaretBufAllocator* self, MargaretFreeSegment segment, U64 req_size){ + assert(req_size <= segment.len); + MargaretBufAllocator__erase_gap(self, segment.block, segment.start, segment.len); + MargaretBufAllocator__insert_gap(self, segment.block, + segment.start + req_size, segment.start + segment.len - req_size); + BufRBTree_MapU64ToU64* images = &VecMargaretBufAllocatorOneBlock_mat(&self->blocks, segment.block)->occupants; + bool iret = BufRBTree_MapU64ToU64_insert(images, segment.start, req_size); + assert(iret); +} + +U64Segment MargaretBufAllocator__get_left_free_space( + const MargaretBufAllocator* self, const MargaretBufAllocation* allocation){ + const MargaretBufAllocatorOneBlock* block = VecMargaretBufAllocatorOneBlock_at(&self->blocks, allocation->block); + U64 occ_start = allocation->start; + U64 prev_occ_it = BufRBTree_MapU64ToU64_find_max_less(&block->occupants, allocation->start); + if (prev_occ_it != 0) { + U64 prev_occ_start; + U64 prev_occ_taken_size; + BufRBTree_MapU64ToU64_at_iter(&block->occupants, prev_occ_it, &prev_occ_start, &prev_occ_taken_size); + + assert(prev_occ_start + prev_occ_taken_size <= occ_start); + 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 MargaretBufAllocator__get_right_free_space( + const MargaretBufAllocator* self, const MargaretBufAllocation* allocation){ + const MargaretBufAllocatorOneBlock* block = VecMargaretBufAllocatorOneBlock_at(&self->blocks, allocation->block); + U64 occ_start = allocation->start; + U64 occ_taken_size = allocation->len; + + U64 next_occ_it = BufRBTree_MapU64ToU64_find_min_grtr(&block->occupants, allocation->start); + if (next_occ_it != 0) { + U64 next_occ_start; + U64 next_occ_taken_size; + BufRBTree_MapU64ToU64_at_iter(&block->occupants, 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 = block->capacity - (occ_start + occ_taken_size)}; +} +void MargaretBufAllocator_drop(MargaretBufAllocator self){ + for (size_t bi = 0; bi < self.blocks.len; bi++) { + vkDestroyBuffer(self.device, self.blocks.buf[bi].buf_hand, NULL); + vkFreeMemory(self.device, self.blocks.buf[bi].mem_hand, NULL); + } + VecMargaretBufAllocatorOneBlock_drop(self.blocks); + BufRBTreeByLen_SetMargaretFreeSegment_drop(self.mem_free_space); +} +void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretBufAllocation allocation){ + U64Segment left_free_space = MargaretBufAllocator__get_left_free_space(self, &allocation); + U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, &allocation); + MargaretBufAllocator__erase_gap(self, allocation.block, left_free_space.start, left_free_space.len); + MargaretBufAllocator__erase_gap(self, allocation.block, right_free_space.start, right_free_space.len); + MargaretBufAllocator__insert_gap(self, allocation.block, + left_free_space.start, + right_free_space.start + right_free_space.len - left_free_space.start); +} +NODISCARD MargaretBufAllocation MargaretBufAllocator_alloc(MargaretBufAllocator* self, U64 req_size){ + req_size = margaret_bump_buffer_size_to_alignment(req_size, self->alignment_exp); -// 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; -// } + VkPhysicalDeviceMaintenance3Properties maintenance3_properties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, + }; + VkPhysicalDeviceProperties2 properties = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &maintenance3_properties, + }; + vkGetPhysicalDeviceProperties2(self->physical_device, &properties); -// MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request( -// MargaretMemAllocator* self, MargaretMemAllocatorRequests* requests -// ){ + check(req_size <= maintenance3_properties.maxMemoryAllocationSize); + OptionMargaretFreeSegment free_gap = MargaretBufAllocator__search_gap(self, req_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(req_size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize)); + MargaretBufAllocator__add_block(self, new_capacity); + U64 bid = self->blocks.len; + MargaretBufAllocator__insert_gap(self, bid, req_size, new_capacity - req_size); + MargaretBufAllocatorOneBlock* block = VecMargaretBufAllocatorOneBlock_mat(&self->blocks, free_gap.some.block); + block->occupation_counter = req_size; + bool iret = BufRBTree_MapU64ToU64_insert(&block->occupants, 0, req_size); + assert(iret); + } -// -// /* 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; -// } + MargaretBufAllocator__put_buf_to_a_gap(self, free_gap.some, req_size); + return (MargaretBufAllocation){.block = free_gap.some.block, .start = free_gap.some.start, req_size}; +} + +void MargaretBufAllocator_shrink(MargaretBufAllocator* self, MargaretBufAllocation* allocation, U64 smaller_size){ + smaller_size = margaret_bump_buffer_size_to_alignment(smaller_size, self->alignment_exp); + assert(smaller_size > 0); + assert(smaller_size <= allocation->len); + + U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, allocation); + MargaretBufAllocator__erase_gap(self, allocation->block, right_free_space.start, right_free_space.len); + MargaretBufAllocator__insert_gap(self, allocation->block, + allocation->start + smaller_size, + right_free_space.len + (allocation->len - smaller_size)); + + allocation->len = smaller_size; +} + +/* It actually may returns a 'null-MargaretBuf-allocation' : if return value .len field is zero it means + * that expansion in-place was possible and the allocator argument was updated with a new size and nothing was returned. + * But if ret value .len field is non-zero it means a valid MargaretBufAllocation object was returned and the + * `allocation` argument was untouched. It remains a valid object, you need to deallocate it yourself + */ +NODISCARD MargaretBufAllocation MargaretBufAllocator_expand(MargaretBufAllocator* self, MargaretBufAllocation* allocation, U64 bigger_size){ + bigger_size = margaret_bump_buffer_size_to_alignment(bigger_size, self->alignment_exp); + + U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, allocation); + if (allocation->start + bigger_size > right_free_space.start + right_free_space.len){ + return MargaretBufAllocator_alloc(self, bigger_size); + } + MargaretBufAllocator__erase_gap(self, allocation->block, right_free_space.start, right_free_space.len); + MargaretBufAllocator__insert_gap(self, allocation->block, + allocation->start + bigger_size, + right_free_space.len + (allocation->len - bigger_size)); + + allocation->len = bigger_size; + return (MargaretBufAllocation){0}; +} #endif \ No newline at end of file diff --git a/src/l2/margaret/vulkan_memory_claire.h b/src/l2/margaret/vulkan_images_claire.h similarity index 94% rename from src/l2/margaret/vulkan_memory_claire.h rename to src/l2/margaret/vulkan_images_claire.h index 6a55094..b570373 100644 --- a/src/l2/margaret/vulkan_memory_claire.h +++ b/src/l2/margaret/vulkan_images_claire.h @@ -230,8 +230,7 @@ void MargaretMemFreeSpaceManager_drop(MargaretMemFreeSpaceManager self){ VecU8_drop(self.set_present); } -void MargaretMemFreeSpaceManager_erase( - MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ +void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ if (len == 0) return; assert(man->set_present.len > 0); @@ -246,8 +245,7 @@ void MargaretMemFreeSpaceManager_erase( } } -void MargaretMemFreeSpaceManager_insert( - MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ +void MargaretMemFreeSpaceManager_insert(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 */ @@ -286,7 +284,6 @@ OptionMargaretFreeSegment MargaretMemFreeSpaceManager_search( /* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */ typedef struct { - U64 total_capacity; VecMargaretImgAllocatorOneBlock blocks; MargaretMemFreeSpaceManager mem_free_space; VkDevice device; @@ -308,26 +305,23 @@ void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, U64 block_id, BLOCK->occupation_counter -= len; } -/* Returns id of the new block */ -U64 MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){ +void 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){ - + VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size + ){ MargaretImgAllocator self = { .blocks = VecMargaretImgAllocatorOneBlock_new(), .mem_free_space = MargaretMemFreeSpaceManager_new(), @@ -404,6 +398,9 @@ U64Segment MargaretImgAllocator__get_right_free_space( } void MargaretImgAllocator_drop(MargaretImgAllocator self){ + for (size_t bi = 0; bi < self.blocks.len; bi++) { + vkFreeMemory(self.device, self.blocks.buf[bi].mem_hand, NULL); + } VecMargaretImgAllocatorOneBlock_drop(self.blocks); MargaretMemFreeSpaceManager_drop(self.mem_free_space); } @@ -421,7 +418,7 @@ void MargaretImgAllocator_free(MargaretImgAllocator* self, MargaretImgAllocation right_free_space.start + right_free_space.len - left_free_space.start); } -MargaretImgAllocation MargaretImgAllocator_alloc( +NODISCARD MargaretImgAllocation MargaretImgAllocator_alloc( MargaretImgAllocator* self, U64 width, U64 height, VkFormat format, VkImageUsageFlags usage_flags, VkImageLayout current_layout ){ @@ -462,13 +459,14 @@ MargaretImgAllocation MargaretImgAllocator_alloc( 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__add_block(self, new_capacity); + U64 bid = self->blocks.len; 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); + MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, free_gap.some.block); + block->occupation_counter = mem_requirements.size; + bool iret = BufRBTree_MapU64ToU64_insert(&block->images, 0, mem_requirements.size); + assert(iret); + check(vkBindImageMemory(self->device, fresh_img, block->mem_hand, 0) == VK_SUCCESS); } U64 aligned_pos = MargaretImgAllocator__add_img_given_gap(self, free_gap.some, mem_requirements.size, alignment_exp); diff --git a/src/l2/margaret/vulkan_memory.h b/src/l2/margaret/vulkan_memory.h index 61f7f24..5825a50 100644 --- a/src/l2/margaret/vulkan_memory.h +++ b/src/l2/margaret/vulkan_memory.h @@ -2,6 +2,7 @@ #define prototype1_src_l2_margaret_vulkan_memory_h #include -#include "vulkan_memory_claire.h" +#include "vulkan_images_claire.h" +#include "vulkan_buffer_claire.h" #endif \ No newline at end of file diff --git a/src/l2/tests/data_structures/t2.c b/src/l2/tests/data_structures/t2.c index 2d69d3f..5bf01fc 100644 --- a/src/l2/tests/data_structures/t2.c +++ b/src/l2/tests/data_structures/t2.c @@ -235,6 +235,23 @@ 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; @@ -242,9 +259,110 @@ 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); -#include "../../margaret/vulkan_memory_claire.h" +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" +// #include "../../margaret/vulkan_me" int main(){ return 0;