From 2367ce1e9da205790d67ef932c4789b3dff53672 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sat, 14 Feb 2026 03:00:03 +0300 Subject: [PATCH] MargaretImgAllocation now stores a direct pointer to MargaretImgAllocatorOneBlock. And both margaretImgAllocator and margaretBufAllocator blocks store pointers to allocators that created them. Memory allocators (buffer, images) are now stored on heap. Now I can do a simplification of allocations management: I don't need to pass allocator to allocation method. Though I hadn't refactored that yet... --- src/l1/anne/margaret/margaret_misc.h | 3 +- src/l2/alice/engine.h | 82 +++++++++--------- src/l2/margaret/vulkan_buffer_claire.h | 27 +++--- src/l2/margaret/vulkan_images_claire.h | 113 ++++++++++++++----------- 4 files changed, 123 insertions(+), 102 deletions(-) diff --git a/src/l1/anne/margaret/margaret_misc.h b/src/l1/anne/margaret/margaret_misc.h index 0323e51..55c0514 100644 --- a/src/l1/anne/margaret/margaret_misc.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -24,9 +24,10 @@ void generate_margaret_eve_for_vulkan_utils() { generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ .T = cstr("BufRBTreeByLenRespAlign_SetMargaretIAFreeSegment")}); - generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretImgAllocatorOneBlock"), true, false); generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretBufAllocatorOneBlock")}, true); + generate_List_templ_inst_eve_header(l, ns, (list_instantiation_op){.T = cstr("MargaretImgAllocatorOneBlock")}, true); + /* Used in utilities such as Abigail */ generate_guarded_span_company_for_primitive(l, ns, cstr("MargaretSubbuf"), cstr("#include \"../../../src/l2/margaret/vulkan_utils.h\"\n"), true, false); } diff --git a/src/l2/alice/engine.h b/src/l2/alice/engine.h index 06a0d28..953c99b 100644 --- a/src/l2/alice/engine.h +++ b/src/l2/alice/engine.h @@ -736,10 +736,10 @@ struct Alice { VkCommandBuffer device_local_mem_mv_command_buf; VkDescriptorPool descriptor_pool; // todo: write dynamic allocator wrapper for descriptor pools - MargaretImgAllocator dev_local_images; - MargaretBufAllocator dev_local_buffers; - MargaretBufAllocator storage_buffer; - MargaretBufAllocator staging_buffers; + MargaretImgAllocator* dev_local_images; + MargaretBufAllocator* dev_local_buffers; + MargaretBufAllocator* storage_buffer; + MargaretBufAllocator* staging_buffers; Jane_alice jane; // todo: figure out my own design MargaretSwapchainBundle swfb; @@ -783,8 +783,8 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic AliceGenericMeshHand* mm = &mm_node->el; mm->indexes = topology->indexes.len; mm->instance_attr.count = 0; - mm->instance_attr.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 200); - mm->instance_attr.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, 200); + mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 200); + mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 200); // todo: change this, I don't like this at all :( mm->pixels_diffuse = TextureDataR8G8B8A8_read_from_png_nofail(VecU8_to_span(&t_paths.diffuse_texture_path)); @@ -797,13 +797,13 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic GenericMeshVertex* staging_vbo; mm->vbo = Abigail_register_new_buffer(&alice->abigail, topology->vertices.len * sizeof(GenericMeshVertex), - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_buffers, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, (void**)&staging_vbo /* We return values here */); U32* staging_ebo; mm->ebo = Abigail_register_new_buffer(&alice->abigail, topology->indexes.len * sizeof(U32), - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_buffers, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, (void**)&staging_ebo /* We return values here */); void* diffuse_tex_staging; @@ -811,21 +811,21 @@ ListNodeAliceGenericMeshHand* Alice_add_generic_mesh(Alice* alice, const Generic mm->pixels_diffuse.width, mm->pixels_diffuse.height, sizeof(cvec4), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_images, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, &diffuse_tex_staging); void *normal_tex_staging; mm->normal_texture = Abigail_register_new_texture(&alice->abigail, mm->pixels_normal.width, mm->pixels_normal.height, sizeof(cvec4), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_images, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, &normal_tex_staging); void* specular_tex_staging; mm->specular_texture = Abigail_register_new_texture(&alice->abigail, mm->pixels_specular.width, mm->pixels_specular.height, sizeof(U8), VK_FORMAT_R8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_images, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_images, &specular_tex_staging); assert(mm->vbo.len >= topology->vertices.len * sizeof(GenericMeshVertex)); @@ -930,19 +930,19 @@ ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTo mm->indexes = topology->indexes.len; mm->instance_attr.count = 0; - mm->instance_attr.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 128); - mm->instance_attr.device_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, 128); + mm->instance_attr.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 128); + mm->instance_attr.device_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, 128); ShinyMeshVertex* staging_vbo; mm->vbo = Abigail_register_new_buffer(&alice->abigail, topology->vertices.len * sizeof(ShinyMeshVertex), - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_buffers, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, (void**)&staging_vbo); U32* staging_ebo; mm->ebo = Abigail_register_new_buffer(&alice->abigail, topology->indexes.len * sizeof(U32), - alice->transfer_command_buf, &alice->staging_buffers, &alice->dev_local_buffers, + alice->transfer_command_buf, alice->staging_buffers, alice->dev_local_buffers, (void**)&staging_ebo); assert(mm->vbo.len >= topology->vertices.len * sizeof(ShinyMeshVertex)); @@ -975,14 +975,14 @@ ListNodeAliceShinyMeshHand* Alice_add_shiny_mesh(Alice* alice, const ShinyMeshTo // todo: write deletion after I separate textures from Meshes void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) { AliceGenericMeshHand* mm = &hand->el; - MargaretBufAllocator_free(&alice->dev_local_buffers, mm->vbo); - MargaretBufAllocator_free(&alice->dev_local_buffers, mm->ebo); - MargaretImgAllocator_free(&alice->dev_local_images, mm->diffuse_texture.img.a); - MargaretImgAllocator_free(&alice->dev_local_images, mm->normal_texture.img.a); - MargaretImgAllocator_free(&alice->dev_local_images, mm->specular_texture.img.a); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->vbo); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->ebo); + MargaretImgAllocator_free(alice->dev_local_images, mm->diffuse_texture.img.a); + MargaretImgAllocator_free(alice->dev_local_images, mm->normal_texture.img.a); + MargaretImgAllocator_free(alice->dev_local_images, mm->specular_texture.img.a); - MargaretBufAllocator_free(&alice->staging_buffers, mm->instance_attr.staging); - MargaretBufAllocator_free(&alice->dev_local_buffers, mm->instance_attr.device_local); + MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); // todo: the problem is, here we don't free some memory stored in AliceGenericMeshHand to store texture. // todo: but the truth is: I am gonna get rid of pixels_{,,} fields very soon, so AliceGenericMeshHand would // todo: be primitive again, without stupid crap @@ -992,11 +992,11 @@ void Alice_delete_generic_mesh(Alice* alice, ListNodeAliceGenericMeshHand* hand) /* Be careful to only delete meshes when you actually allowed to do so */ void Alice_delete_shiny_mesh(Alice* alice, ListNodeAliceShinyMeshHand* hand) { AliceShinyMeshHand* mm = &hand->el; - MargaretBufAllocator_free(&alice->dev_local_buffers, hand->el.vbo); - MargaretBufAllocator_free(&alice->dev_local_buffers, hand->el.ebo); + MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.vbo); + MargaretBufAllocator_free(alice->dev_local_buffers, hand->el.ebo); - MargaretBufAllocator_free(&alice->staging_buffers, mm->instance_attr.staging); - MargaretBufAllocator_free(&alice->dev_local_buffers, mm->instance_attr.device_local); + MargaretBufAllocator_free(alice->staging_buffers, mm->instance_attr.staging); + MargaretBufAllocator_free(alice->dev_local_buffers, mm->instance_attr.device_local); ListAliceShinyMeshHand_erase_by_it(&alice->shiny_models, hand); } @@ -1007,7 +1007,7 @@ void AliceGenericMeshHand_resize_instance_arr(Alice* alice, AliceGenericMeshHand printf("Alice generic model instance staging Buffer: Gotta replace %lu with %lu\n", self->instance_attr.staging.len, needed_length); MargaretBufAllocator_expand_or_move_old_host_visible( - &alice->staging_buffers, &self->instance_attr.staging, needed_length); + alice->staging_buffers, &self->instance_attr.staging, needed_length); } self->instance_attr.count = new_count; } @@ -1016,7 +1016,7 @@ void AliceShinyMeshHand_resize_instance_arr(Alice* alice, AliceShinyMeshHand* se U64 needed_length = new_count * sizeof(ShinyMeshInstance); if (self->instance_attr.staging.len < needed_length) { MargaretBufAllocator_expand_or_move_old_host_visible( - &alice->staging_buffers, &self->instance_attr.staging, needed_length); + alice->staging_buffers, &self->instance_attr.staging, needed_length); } self->instance_attr.count = new_count; } @@ -1055,7 +1055,7 @@ void AliceScene__another_frame(Alice* alice) { AliceGenericMeshHand* mm = &mm_node->el; assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.staging.len); if (mm->instance_attr.count * sizeof(GenericMeshInstance) > mm->instance_attr.device_local.len) { - MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, + MargaretBufAllocator_expand_or_free_old(alice->dev_local_buffers, &mm->instance_attr.device_local, mm->instance_attr.count * sizeof(GenericMeshInstance)); } assert(mm->instance_attr.count * sizeof(GenericMeshInstance) <= mm->instance_attr.device_local.len); @@ -1069,7 +1069,7 @@ void AliceScene__another_frame(Alice* alice) { AliceShinyMeshHand* mm = &mm_node->el; assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.staging.len); if (mm->instance_attr.count * sizeof(ShinyMeshInstance) > mm->instance_attr.device_local.len) { - MargaretBufAllocator_expand_or_free_old(&alice->dev_local_buffers, &mm->instance_attr.device_local, + MargaretBufAllocator_expand_or_free_old(alice->dev_local_buffers, &mm->instance_attr.device_local, mm->instance_attr.count * sizeof(ShinyMeshInstance)); } assert(mm->instance_attr.count * sizeof(ShinyMeshInstance) <= mm->instance_attr.device_local.len); @@ -1095,7 +1095,7 @@ void AliceScene__another_frame(Alice* alice) { margaret_rec_cmd_copy_buffer_one_to_one(alice->transfer_command_buf, ubo_staging, ubo); if (point_lights_count * sizeof(Pipeline0PointLight) > point_lights->len) { - MargaretBufAllocator_expand_or_free_old(&alice->storage_buffer, point_lights, point_lights_count * sizeof(Pipeline0PointLight)); + MargaretBufAllocator_expand_or_free_old(alice->storage_buffer, point_lights, point_lights_count * sizeof(Pipeline0PointLight)); } assert(point_lights_count * sizeof(Pipeline0PointLight) <= point_lights->len); if (point_lights_count) { @@ -1347,7 +1347,7 @@ void alice_frame_drawing(Alice* alice) { mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix)); if (!alice->transfer_command_buf_already_reset) { - Abigail_wipe_old_staging(&alice->abigail, alice->device, &alice->staging_buffers); + Abigail_wipe_old_staging(&alice->abigail, alice->device, alice->staging_buffers); margaret_reset_and_begin_command_buffer(alice->transfer_command_buf); } else { alice->transfer_command_buf_already_reset = false; @@ -1858,26 +1858,26 @@ Alice* Alice_new(){ alice->generic_models = ListAliceGenericMeshHand_new(); alice->shiny_models = ListAliceShinyMeshHand_new(); - alice->pipeline0_light_conf.num_ubo_staging = MargaretBufAllocator_alloc(&alice->staging_buffers, sizeof(Pipeline0UBO)); - alice->pipeline0_light_conf.num_ubo_dev_local = MargaretBufAllocator_alloc(&alice->dev_local_buffers, sizeof(Pipeline0UBO)); + alice->pipeline0_light_conf.num_ubo_staging = MargaretBufAllocator_alloc(alice->staging_buffers, sizeof(Pipeline0UBO)); + alice->pipeline0_light_conf.num_ubo_dev_local = MargaretBufAllocator_alloc(alice->dev_local_buffers, sizeof(Pipeline0UBO)); Pipeline0UBO* ubo0 = (Pipeline0UBO*)MargaretSubbuf_get_mapped(&alice->pipeline0_light_conf.num_ubo_staging); ubo0->point_light_count = ubo0->spotlight_count = 0; alice->pipeline0_light_conf.point_lights.count = 0; - alice->pipeline0_light_conf.point_lights.staging = MargaretBufAllocator_alloc(&alice->staging_buffers, 1000); - alice->pipeline0_light_conf.point_lights.device_local = MargaretBufAllocator_alloc(&alice->storage_buffer, 1000); + alice->pipeline0_light_conf.point_lights.staging = MargaretBufAllocator_alloc(alice->staging_buffers, 1000); + alice->pipeline0_light_conf.point_lights.device_local = MargaretBufAllocator_alloc(alice->storage_buffer, 1000); alice->cam_info = AliceCamVerticalControl_new(); alice->rendering_config = AliceRenderConfig_new(); - alice->IT1_image = MargaretImgAllocator_alloc(&alice->dev_local_images, + alice->IT1_image = MargaretImgAllocator_alloc(alice->dev_local_images, MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->IT1_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - alice->zbuffer_image = MargaretImgAllocator_alloc(&alice->dev_local_images, + alice->zbuffer_image = MargaretImgAllocator_alloc(alice->dev_local_images, MAX_WIN_WIDTH, MAX_WIN_HEIGHT, alice->zbuffer_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); MargaretEngineReference engine_reference = { .device = alice->device, .physical_device = alice->physical_device, .transfer_cmd_buffer = alice->transfer_command_buf, - .dev_local_images = &alice->dev_local_images, .dev_local_buffers = &alice->dev_local_buffers, - .staging_buffers = &alice->staging_buffers, .descriptor_pool = alice->descriptor_pool, + .dev_local_images = alice->dev_local_images, .dev_local_buffers = alice->dev_local_buffers, + .staging_buffers = alice->staging_buffers, .descriptor_pool = alice->descriptor_pool, .linear_sampler = alice->linear_sampler, .nearest_sampler = alice->nearest_sampler }; @@ -1909,7 +1909,7 @@ void Alice_set_point_light_count(Alice* alice, U32 new_count){ U64 needed_length = new_count * sizeof(Pipeline0PointLight); MargaretSubbuf* point_lights_staging = &alice->pipeline0_light_conf.point_lights.staging; if (needed_length > alice->pipeline0_light_conf.point_lights.staging.len) { - MargaretBufAllocator_expand_or_move_old_host_visible(&alice->staging_buffers, point_lights_staging, needed_length); + MargaretBufAllocator_expand_or_move_old_host_visible(alice->staging_buffers, point_lights_staging, needed_length); alice_update_pipe0_set0_descr1(alice); } alice->pipeline0_light_conf.point_lights.count = new_count; diff --git a/src/l2/margaret/vulkan_buffer_claire.h b/src/l2/margaret/vulkan_buffer_claire.h index 1e7da56..155b6ad 100644 --- a/src/l2/margaret/vulkan_buffer_claire.h +++ b/src/l2/margaret/vulkan_buffer_claire.h @@ -34,13 +34,16 @@ typedef struct { U64 len; } MargaretSubbuf; -struct MargaretBufAllocatorOneBlock{ +typedef struct MargaretBufAllocator MargaretBufAllocator; + +struct MargaretBufAllocatorOneBlock { BufRBTree_MapU64ToU64 occupants; U64 capacity; U64 occupation_counter; VkDeviceMemory mem_hand; VkBuffer buf_hand; void* mapped_memory; + MargaretBufAllocator* p; }; void MargaretBufAllocatorOneBlock_drop(MargaretBufAllocatorOneBlock self){ @@ -52,7 +55,7 @@ void MargaretBufAllocatorOneBlock_drop(MargaretBufAllocatorOneBlock self){ #include "../../../gen/l1/eve/margaret/VecMargaretBAFreeSegment.h" #include "../../../gen/l1_5/eve/margaret/BufRBTreeByLen_SetMargaretBAFreeSegment.h" -typedef struct { +struct MargaretBufAllocator { ListMargaretBufAllocatorOneBlock blocks; BufRBTreeByLen_SetMargaretBAFreeSegment mem_free_space; VkDevice device; @@ -62,7 +65,7 @@ typedef struct { U8 alignment_exp; bool host_visible; bool ban_non_envisaged_blocks; -} MargaretBufAllocator; +}; void MargaretBufAllocator__erase_gap( @@ -121,25 +124,26 @@ void MargaretBufAllocator__add_block(MargaretBufAllocator* self, U64 capacity){ .occupants = BufRBTree_MapU64ToU64_new_reserved(1), .capacity = capacity, .occupation_counter = capacity, - .mem_hand = memory, .buf_hand = buffer, .mapped_memory = mapped_memory - }); + .mem_hand = memory, .buf_hand = buffer, .mapped_memory = mapped_memory, + .p = self }); } -MargaretBufAllocator MargaretBufAllocator_new( +MargaretBufAllocator* MargaretBufAllocator_new( VkDevice device, VkPhysicalDevice physical_device, VkBufferUsageFlags usage, U8 memory_type_id, U8 alignment_exp, bool host_visible, U64 initial_block_size, bool ban_non_envisaged_blocks ){ - MargaretBufAllocator self = { + MargaretBufAllocator* self = (MargaretBufAllocator*)safe_malloc(sizeof(MargaretBufAllocator)); + *self = (MargaretBufAllocator){ .blocks = ListMargaretBufAllocatorOneBlock_new(), .mem_free_space = BufRBTreeByLen_SetMargaretBAFreeSegment_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, .ban_non_envisaged_blocks = ban_non_envisaged_blocks, }; - MargaretBufAllocator__add_block(&self, initial_block_size); - MargaretBufAllocator__insert_gap(&self, &self.blocks.first->el, 0, initial_block_size); + MargaretBufAllocator__add_block(self, initial_block_size); + MargaretBufAllocator__insert_gap(self, &self->blocks.first->el, 0, initial_block_size); return self; } @@ -234,6 +238,7 @@ void MargaretBufAllocator_debug(const MargaretBufAllocator* self){ /* Free one subbuffer, not a whole MBA :) */ void MargaretBufAllocator_free(MargaretBufAllocator* self, MargaretSubbuf allocation){ + assert(allocation.block->p == self); // Vibe check U64Segment left_free_space = MargaretBufAllocator__get_left_free_space(self, &allocation); U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, &allocation); @@ -302,7 +307,9 @@ void MargaretBufAllocator_shrink(MargaretBufAllocator* self, MargaretSubbuf* all * `allocation` argument was untouched. It remains a valid object, you need to deallocate it yourself */ NODISCARD MargaretSubbuf MargaretBufAllocator_expand( - MargaretBufAllocator* self, MargaretSubbuf* allocation, U64 bigger_size){ + MargaretBufAllocator* self, MargaretSubbuf* allocation, U64 bigger_size + ){ + assert(allocation->block->p == self); // Vibe check bigger_size = margaret_bump_buffer_size_to_alignment(bigger_size, self->alignment_exp); U64Segment right_free_space = MargaretBufAllocator__get_right_free_space(self, allocation); diff --git a/src/l2/margaret/vulkan_images_claire.h b/src/l2/margaret/vulkan_images_claire.h index 377510c..875c8d3 100644 --- a/src/l2/margaret/vulkan_images_claire.h +++ b/src/l2/margaret/vulkan_images_claire.h @@ -176,8 +176,10 @@ #include "../../l1_5/core/buff_rb_tree_node.h" #include "../../../gen/l1_5/BufRBTree_MapU64ToU64.h" -typedef struct{ - U64 block; +typedef struct MargaretImgAllocatorOneBlock MargaretImgAllocatorOneBlock; + +typedef struct { + MargaretImgAllocatorOneBlock* block; U64 start; U64 len; } MargaretIAFreeSegment; @@ -199,7 +201,7 @@ bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const if (A->block == B->block) { return A->start < B->start; } - return A->block < B->block; + return (uintptr_t)A->block < (uintptr_t)B->block; } return A_len < B_len; } @@ -208,25 +210,28 @@ bool MargaretIAFreeSegment_less_resp_align(const MargaretIAFreeSegment* A, const /* Does not include all parameters needed for relocation. Because relocation is needed only * during controlled defragmentation */ typedef struct { - U64 block; + MargaretImgAllocatorOneBlock* block; VkImage image; U64 start; } MargaretImgAllocation; +typedef struct MargaretImgAllocator MargaretImgAllocator; + /* Not primitive */ -typedef struct { +struct MargaretImgAllocatorOneBlock { BufRBTree_MapU64ToU64 images; U64 capacity; U64 occupation_counter; VkDeviceMemory mem_hand; void* mapped_memory; -} MargaretImgAllocatorOneBlock; + MargaretImgAllocator* p; +}; void MargaretImgAllocatorOneBlock_drop(MargaretImgAllocatorOneBlock self){ BufRBTree_MapU64ToU64_drop(self.images); } -#include "../../../gen/l1/eve/margaret/VecMargaretImgAllocatorOneBlock.h" +#include "../../../gen/l1/eve/margaret/ListMargaretImgAllocatorOneBlock.h" #include "../../../gen/l1/VecAndSpan_U8.h" #include "../../../gen/l1/eve/margaret/VecMargaretIAFreeSegment.h" @@ -258,7 +263,9 @@ 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, + MargaretImgAllocatorOneBlock* block, U64 start, U64 len + ){ if (len == 0) return; assert(man->set_present.len > 0); @@ -273,7 +280,9 @@ void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 blo } } -void MargaretMemFreeSpaceManager_insert(MargaretMemFreeSpaceManager* man, U64 block, U64 start, U64 len){ +void MargaretMemFreeSpaceManager_insert(MargaretMemFreeSpaceManager* man, + MargaretImgAllocatorOneBlock* block, U64 start, U64 len + ){ if (len == 0) return; assert(man->set_present.len > 0); /* MargaretMemFreeSpaceManager will do that for us with 2^3 */ @@ -313,26 +322,28 @@ OptionMargaretIAFreeSegment MargaretMemFreeSpaceManager_search( } /* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */ -typedef struct { - VecMargaretImgAllocatorOneBlock blocks; +struct MargaretImgAllocator { + ListMargaretImgAllocatorOneBlock blocks; MargaretMemFreeSpaceManager mem_free_space; VkDevice device; VkPhysicalDevice physical_device; U8 memory_type_id; -} MargaretImgAllocator; +}; -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__erase_gap(MargaretImgAllocator* self, + MargaretImgAllocatorOneBlock* block, U64 start, U64 len + ){ + MargaretMemFreeSpaceManager_erase(&self->mem_free_space, block, start, len); + 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; +void MargaretImgAllocator__insert_gap(MargaretImgAllocator* self, + MargaretImgAllocatorOneBlock* block, U64 start, U64 len + ){ + MargaretMemFreeSpaceManager_insert(&self->mem_free_space, block, start, len); + assert(len <= block->occupation_counter); + block->occupation_counter -= len; } void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){ @@ -342,20 +353,20 @@ void MargaretImgAllocator__add_block(MargaretImgAllocator* self, U64 capacity){ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = capacity, .memoryTypeIndex = self->memory_type_id }, NULL, &memory) == VK_SUCCESS); - VecMargaretImgAllocatorOneBlock_append(&self->blocks, (MargaretImgAllocatorOneBlock){ + ListMargaretImgAllocatorOneBlock_insert(&self->blocks, (MargaretImgAllocatorOneBlock){ .images = BufRBTree_MapU64ToU64_new_reserved(1), .capacity = capacity, .occupation_counter = capacity, // sounds sus .mem_hand = memory, - .mapped_memory = NULL /* not supported */}); + .mapped_memory = NULL /* not supported */, .p = self }); } /* Idk where to put it */ void MargaretImgAllocator__debug(const MargaretImgAllocator* self){ printf("=============================== MargaretImgAllocator ============\n" "All blocks: { "); - for (size_t i = 0; i < self->blocks.len; i++) { - printf(" %lu/%lu ", self->blocks.buf[i].occupation_counter, self->blocks.buf[i].capacity); + for (ListNodeMargaretImgAllocatorOneBlock* i = 0; i; i = i->next) { + printf(" %lu/%lu ", i->el.occupation_counter, i->el.capacity); } printf("}\n"); for (size_t ai = 0; ai < self->mem_free_space.set_present.len; ai++) { @@ -367,24 +378,25 @@ void MargaretImgAllocator__debug(const MargaretImgAllocator* self){ assert(set->guest == alignment_exp); for (size_t i = 0; i < set->el.len; i++) { const MargaretIAFreeSegment *free_seg = &set->el.buf[i]; - printf(" Block %lu, start %lu, len %lu\n", free_seg->block, free_seg->start, free_seg->len); + printf(" Block %p, start %lu, len %lu\n", (void*)free_seg->block, free_seg->start, free_seg->len); } } } -MargaretImgAllocator MargaretImgAllocator_new( +MargaretImgAllocator* MargaretImgAllocator_new( VkDevice device, VkPhysicalDevice physical_device, U8 memory_type_id, U64 initial_block_size ){ - MargaretImgAllocator self = { - .blocks = VecMargaretImgAllocatorOneBlock_new(), + MargaretImgAllocator* self = (MargaretImgAllocator*)safe_malloc(sizeof(MargaretImgAllocator)); + *self = (MargaretImgAllocator){ + .blocks = ListMargaretImgAllocatorOneBlock_new(), .mem_free_space = MargaretMemFreeSpaceManager_new(), .device = device, .physical_device = physical_device, .memory_type_id = memory_type_id, }; - MargaretImgAllocator__add_block(&self, initial_block_size); - MargaretImgAllocator__insert_gap(&self, 0, 0, initial_block_size); - // MargaretImgAllocator__debug(&self); + MargaretImgAllocator__add_block(self, initial_block_size); + assert(self->blocks.first != NULL); + MargaretImgAllocator__insert_gap(self, &self->blocks.first->el, 0, initial_block_size); return self; } @@ -407,7 +419,7 @@ U64 MargaretImgAllocator__add_img_given_gap( MargaretImgAllocator__insert_gap(self, segment.block, aligned_start + required_size, gap_start + gap_len - (aligned_start + required_size)); - BufRBTree_MapU64ToU64* images = &VecMargaretImgAllocatorOneBlock_mat(&self->blocks, segment.block)->images; + BufRBTree_MapU64ToU64* images = &segment.block->images; bool iret = BufRBTree_MapU64ToU64_insert(images, aligned_start, required_size); assert(iret); return aligned_start; @@ -415,7 +427,7 @@ U64 MargaretImgAllocator__add_img_given_gap( U64Segment MargaretImgAllocator__get_left_free_space( const MargaretImgAllocator* self, MargaretImgAllocation allocation){ - const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block); + const MargaretImgAllocatorOneBlock* block = allocation.block; U64 occ_start = allocation.start; U64 prev_occ_it = BufRBTree_MapU64ToU64_find_max_less(&block->images, allocation.start); @@ -434,7 +446,7 @@ U64Segment MargaretImgAllocator__get_left_free_space( U64Segment MargaretImgAllocator__get_right_free_space( const MargaretImgAllocator* self, MargaretImgAllocation allocation){ - const MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_at(&self->blocks, allocation.block); + const MargaretImgAllocatorOneBlock* block = allocation.block; U64 occ_start = allocation.start; VkMemoryRequirements occ_memory_requirements; vkGetImageMemoryRequirements(self->device, allocation.image, &occ_memory_requirements); @@ -451,27 +463,29 @@ U64Segment MargaretImgAllocator__get_right_free_space( return (U64Segment){.start = occ_start + occ_taken_size, .len = block->capacity - (occ_start + occ_taken_size)}; } +/* Also frees blocks */ 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); + for (ListNodeMargaretImgAllocatorOneBlock* bi = self.blocks.first; bi; bi = bi->next) { + vkFreeMemory(self.device, bi->el.mem_hand, NULL); } - VecMargaretImgAllocatorOneBlock_drop(self.blocks); + ListMargaretImgAllocatorOneBlock_drop(self.blocks); MargaretMemFreeSpaceManager_drop(self.mem_free_space); } void MargaretImgAllocator_free(MargaretImgAllocator* self, MargaretImgAllocation allocation){ + assert(allocation.block->p == self); // Vibe check U64Segment left_free_space = MargaretImgAllocator__get_left_free_space(self, allocation); U64Segment right_free_space = MargaretImgAllocator__get_right_free_space(self, allocation); vkDestroyImage(self->device, allocation.image, NULL); - 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, + MargaretImgAllocatorOneBlock* block = allocation.block; + MargaretImgAllocator__erase_gap(self, block, left_free_space.start, left_free_space.len); + MargaretImgAllocator__erase_gap(self, block, right_free_space.start, right_free_space.len); + MargaretImgAllocator__insert_gap(self, block, left_free_space.start, right_free_space.start + right_free_space.len - left_free_space.start); - MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, allocation.block); bool eret = BufRBTree_MapU64ToU64_erase(&block->images, allocation.start); assert(eret); } @@ -514,24 +528,23 @@ NODISCARD MargaretImgAllocation MargaretImgAllocator__alloc( 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; + assert(self->blocks.first != NULL); + U64 pitch = self->blocks.first->el.capacity; // Old blocks remain intact U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(2 * pitch, maintenance3_properties.maxMemoryAllocationSize)); // U64 new_capacity = MAX_U64(mem_requirements.size, MIN_U64(pitch, maintenance3_properties.maxMemoryAllocationSize)); MargaretImgAllocator__add_block(self, new_capacity); - U64 bid = self->blocks.len - 1; - MargaretImgAllocator__insert_gap(self, bid, mem_requirements.size, new_capacity - mem_requirements.size); - MargaretImgAllocatorOneBlock* block = VecMargaretImgAllocatorOneBlock_mat(&self->blocks, bid); + MargaretImgAllocatorOneBlock* block = &self->blocks.first->el; + MargaretImgAllocator__insert_gap(self, block, mem_requirements.size, new_capacity - mem_requirements.size); 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); // MargaretImgAllocator__debug(self); - return (MargaretImgAllocation){.block = bid, fresh_img, 0}; + return (MargaretImgAllocation){.block = block, fresh_img, 0}; } 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; + VkDeviceMemory memory = free_gap.some.block->mem_hand; check(vkBindImageMemory(self->device, fresh_img, memory, aligned_pos) == VK_SUCCESS); // MargaretImgAllocator__debug(self); return (MargaretImgAllocation){.block = free_gap.some.block, .image = fresh_img, .start = aligned_pos};