From 49ee178eb638aabd12fee4ab39fffa6f043e1d75 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Tue, 4 Nov 2025 12:24:08 +0300 Subject: [PATCH] Saving progress on MargaretMemAllocator. The exam is near, can't do this anymore --- src/l1/anne/margaret/margaret_misc.h | 28 ++ src/l1/anne/util_temp_very_base.h | 8 - src/l1/codegen/util_template_inst.h | 2 +- src/l1/core/uint_segments.h | 65 ++--- src/l1/core/util.h | 13 + src/l1_5/anne/codegen.c | 2 + src/l1_5/anne/l1_5_templ_very_base.h | 29 -- src/l1_5/anne/margaret.h | 36 +++ .../codegen/rb_tree_set_map_template_inst.h | 2 +- src/l2/margaret/vulkan_memory_claire.h | 272 +++++++++++++++++- src/l2/tests/data_structures/t2.c | 7 +- 11 files changed, 381 insertions(+), 83 deletions(-) create mode 100644 src/l1_5/anne/margaret.h diff --git a/src/l1/anne/margaret/margaret_misc.h b/src/l1/anne/margaret/margaret_misc.h index ba4594e..f01bfe8 100644 --- a/src/l1/anne/margaret/margaret_misc.h +++ b/src/l1/anne/margaret/margaret_misc.h @@ -25,6 +25,34 @@ void generate_margaret_eve_for_vulkan_utils() { .collab_vec_span = true }); + /* For l2/margaret/vulkan_memory_claire.h */ + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufferKindDescription"), false, true); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + /* We won't need to clone this type, like, at all... It is actually clonable, but we just made + * it non-clonable */ + .T = cstr("BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment") + }); + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorOneBlock"), true, false); + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorOneMemType"), true, false); + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufferKindInfo"), true, false); + + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemoryOccupation"), true, false); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("MargaretMemoryOccupation"), .t_primitive = true}); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("RefMargaretMemoryOccupation"), .t_primitive = true}); + + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufferOccupationSubBuffer"), true, false); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("MargaretBufferOccupationSubBuffer"), .t_primitive = true}); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("RefMargaretBufferOccupationSubBuffer"), .t_primitive = true}); + + generate_eve_span_company_for_primitive(l, ns, cstr("MargaretFreeMemSegment"), true, false); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("MargaretFreeMemSegment"), .t_primitive = true}); + generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){ + .T = cstr("RefMargaretFreeMemSegment"), .t_primitive = true}); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretCommandForImageCopying"), true, true); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestAllocBuffer"), true, true); diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index b9bb910..afa16ce 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -51,14 +51,6 @@ void generate_util_temp_very_base_headers() { generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("CSTR"), cstr(""), true, false); - generate_util_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), - (util_templates_instantiation_options){.T = cstr("U64Segment"), .t_primitive = true, .vec_extended = true}); - generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), - (option_template_instantiation_op){.T = cstr("U64Segment"), .t_primitive = true}); - /* Required by BuffRBTree_Set */ - generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), - (option_template_instantiation_op){.T = cstr("RefU64Segment"), .t_primitive = true}); - generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_U8.h\""), true, false); generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 25fabab..97c8802 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -712,7 +712,7 @@ void generate_Option_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option VecU8 text = VecU8_from_cstr("/* Automatically generated file. Do not edit it.\n" " * Do not include it in more than one place */\n\n"); VecU8_append_vec(&text, generate_OptionT_struct_and_methods(op)); - VecU8 nt_path = VecU8_fmt("%s/eve/%s/Option%s%c", layer, bonus_ns, op.T, 0); + VecU8 nt_path = VecU8_fmt("%s/eve/%s/Option%s.h%c", layer, bonus_ns, op.T, 0); write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); VecU8_drop(nt_path); VecU8_drop(text); diff --git a/src/l1/core/uint_segments.h b/src/l1/core/uint_segments.h index 6d56c40..b7b3c5e 100644 --- a/src/l1/core/uint_segments.h +++ b/src/l1/core/uint_segments.h @@ -8,47 +8,44 @@ typedef struct { U64 len; } U64Segment; -bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B) { - return A->start == B->start; -} +// bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B) { +// return A->start == B->start; +// } -bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B) { - return A->start < B->start; -} +// bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B) { +// return A->start < B->start; +// } -bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B) { - return A->start == B->start && A->len == B->len; -} +// bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B) { +// return A->start == B->start && A->len == B->len; +// } -bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B) { - if (A->len == B->len) - return A->start < B->start; - return A->len < B->len; -} +// bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B) { +// if (A->len == B->len) +// return A->start < B->start; +// return A->len < B->len; +// } -U64 U64Segment_get_length_resp_alignment(const U64Segment* self, U8 alignment_exp) { - if (self->start & ((1ull << alignment_exp) - 1)) { - U64 pad_left = (1ull << alignment_exp) - (self->start & ((1ull << alignment_exp) - 1)); - return self->len >= pad_left ? self->len - pad_left : 0; +U64 U64Segment_get_length_resp_alignment(U64Segment self, U8 alignment_exp) { + if (self.start & ((1ull << alignment_exp) - 1)) { + U64 pad_left = (1ull << alignment_exp) - (self.start & ((1ull << alignment_exp) - 1)); + return self.len >= pad_left ? self.len - pad_left : 0; } - return self->len; + return self.len; } -bool U64Segment_equal_U64Segment_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { - U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); - U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); - return len_A == len_B && A->start == B->start; -} +// bool U64Segment_equal_U64Segment_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { +// U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); +// U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); +// return len_A == len_B && A->start == B->start; +// } -bool U64Segment_less_by_len_and_start_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { - U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); - U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); - if (len_A == len_B) - return A->start < B->start; - return len_A < len_B; -} - -/* Required by BuffRBTree_Set. That was a really tough decision */ -typedef const U64Segment* RefU64Segment; +// bool U64Segment_less_by_len_and_start_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { +// U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); +// U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); +// if (len_A == len_B) +// return A->start < B->start; +// return len_A < len_B; +// } #endif diff --git a/src/l1/core/util.h b/src/l1/core/util.h index 334d809..5d65057 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -69,6 +69,19 @@ float pow2f(float x) { return x * x; } +bool U64_is_2pow(U64 n){ + return n > 0 && (n & (n - 1) == 0); +} + +U8 U64_2pow_log(U64 n){ + U8 log = 0; + while (n > 1){ + n >>= 1; + log++; + } + return log; +} + typedef struct { U32 width; U32 height; diff --git a/src/l1_5/anne/codegen.c b/src/l1_5/anne/codegen.c index 71ce5d6..4f172b3 100644 --- a/src/l1_5/anne/codegen.c +++ b/src/l1_5/anne/codegen.c @@ -3,6 +3,7 @@ #include "marie/clipping.h" #include "liza.h" #include "l1_5_templ_very_base.h" +#include "margaret.h" int main() { mkdir_nofail("l1_5"); @@ -10,6 +11,7 @@ int main() { generate_marie_clipping_header(); generate_l1_5_liza_headers(); generate_l1_5_template_instantiation_for_base_types(); + generate_l1_5_template_instantiations_for_margaret(); finish_layer(cstr("l1_5")); return 0; } 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 14b8ea7..1899a6a 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -9,35 +9,6 @@ void generate_l1_5_template_instantiation_for_base_types(){ (set_instantiation_op){.T = cstr("U64"), .t_integer = true}); generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""), (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); - - SpanU8 u64seg_dep = cstr("#include \"../l1/VecU64Segment.h\"\n" - "#include \"../l1/OptionU64Segment.h\"\n" - "#include \"../l1/OptionRefU64Segment.h\""); - generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, - (set_instantiation_op){ - .T = cstr("U64Segment"), - .t_primitive = true, - .alternative_equal = cstr("U64Segment_equal_by_start"), - .alternative_less = cstr("U64Segment_less_by_start"), - .alternative_comp_set_name_embed = cstr("Start") - }); - generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, - (set_instantiation_op){ - .T = cstr("U64Segment"), - .t_primitive = true, - .alternative_less = cstr("U64Segment_less_by_len_and_start"), - .alternative_comp_set_name_embed = cstr("Len") - }); - generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, - (set_instantiation_op){ - .T = cstr("U64Segment"), - .t_primitive = true, - /* comparison takes additional U8 parameter */ - .alternative_less = cstr("U64Segment_less_by_len_and_start_resp_align"), - .alternative_equal = cstr("U64Segment_equal_U64Segment_resp_align"), - .alternative_comp_set_name_embed = cstr("LenRespAlign"), - .guest_data_T = cstr("U8") - }); } #endif diff --git a/src/l1_5/anne/margaret.h b/src/l1_5/anne/margaret.h new file mode 100644 index 0000000..61c7a50 --- /dev/null +++ b/src/l1_5/anne/margaret.h @@ -0,0 +1,36 @@ +#ifndef prototype1_src_l1_5_anne_margaret_h +#define prototype1_src_l1_5_anne_margaret_h + +#include "../codegen/rb_tree_set_map_template_inst.h" + +void generate_l1_5_template_instantiations_for_margaret(){ + SpanU8 l = cstr("l1_5"), ns = cstr("margaret"); + mkdir_nofail("l1_5/eve"); + mkdir_nofail("l1_5/eve/margaret"); + + /* For MargaretMemAllocator */ + generate_rb_tree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ + .T = cstr("MargaretFreeMemSegment"), + .t_primitive = true, + .alternative_less = cstr("MargaretFreeMemSegment_less"), + .alternative_equal = cstr("MargaretFreeMemSegment_equal"), + .alternative_comp_set_name_embed = cstr("Len") + }); + generate_rb_tree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ + .T = cstr("MargaretFreeMemSegment"), + .t_primitive = true, + /* comparison takes additional U8 parameter */ + .alternative_less = cstr("MargaretFreeMemSegment_less_resp_align"), + .alternative_equal = cstr("MargaretFreeMemSegment_equal_resp_align"), + .alternative_comp_set_name_embed = cstr("LenRespAlign"), + .guest_data_T = cstr("U8") + }); + generate_rb_tree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ + .T = cstr("MargaretMemoryOccupation"), .t_primitive = true, + }); + generate_rb_tree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){ + .T = cstr("MargaretBufferOccupationSubBuffer"), .t_primitive = true, + }); +} + +#endif \ No newline at end of file diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index c95e6e1..75e032e 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -583,7 +583,7 @@ void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, s VecU8 text = VecU8_from_cstr("/* Automatically generated file. Do not edit it.\n" " * Do not include it in more than one place */\n\n"); VecU8_append_vec(&text, generate_rb_tree_Set_template_instantiation(op)); - VecU8 nt_path = VecU8_fmt("%s/eve/%s/%s.h%c", layer, bonus_ns, op.T, get_name_of_rb_tree_set_structure(op)); + VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v.h%c", layer, bonus_ns, get_name_of_rb_tree_set_structure(op), 0); write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); VecU8_drop(nt_path); VecU8_drop(text); diff --git a/src/l2/margaret/vulkan_memory_claire.h b/src/l2/margaret/vulkan_memory_claire.h index d6eff6b..6fec63a 100644 --- a/src/l2/margaret/vulkan_memory_claire.h +++ b/src/l2/margaret/vulkan_memory_claire.h @@ -172,7 +172,7 @@ * const VkAllocationCallbacks* pAllocator) */ -#include "../../../l1/core/int_primitives.h" +#include "../../l1/core/int_primitives.h" /* MargaretMemAllocator assumes that your application tolerates existence of several * 'quiet' time phases, when no frames are in flight and all you do is relocate and defragment your memory */ @@ -184,7 +184,9 @@ typedef struct { VkMemoryPropertyFlags memory_properties; bool preserve_at_quiet; U64 inner_alignment; -} MargaretMemAllocatorBufferKindInfo; +} MargaretBufferKindDescription; + +#include "../../../gen/l1/eve/margaret/SpanMargaretBufferKindDescription.h" typedef struct { VkBuffer buffer; @@ -195,7 +197,7 @@ typedef struct { /* If your buffer kind requested VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, MargaretMemAllocator * will map all nubbles with it. Use `offset_in_device_memory_nubble` to access this buffer from cpu */ U8 memory_type_id; - U16 memory_allocation_id; + U32 memory_allocation_id; } MargaretMemAllocatorBufferPosition; typedef struct { @@ -251,6 +253,9 @@ typedef struct { /* That is our guy! */ typedef struct MargaretMemAllocator MargaretMemAllocator; +MargaretMemAllocator MargaretMemAllocator_new( + VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types, double alpha); + /* Vibe check */ bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, MargaretMemAllocatorRequest req); @@ -263,35 +268,286 @@ bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, Marg * actions with memory managed by Self would make any sense */ bool MargaretMemAllocator_carry_out_request(MargaretMemAllocator* self, VkCommandBuffer cmd_buff, bool silence); -// todo: add same shit for images in host visible buffer +void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self); + char* MargaretMemAllocator_get_host_visible_buffer_ptr( const MargaretMemAllocator* self, const MargaretMemAllocatorBufferPosition* pos); +// todo: add same shit for images in host visible buffer + +#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 28 /* ======= End of MargaretMemAllocator client interface ======== */ -#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 30 +#include "../../l1/core/uint_segments.h" +#include "../../l1/core/util.h" +#include "../../l1_5/core/rb_tree_node.h" typedef struct { + U64 width; + U64 height; + VkFormat format; + VkImageTiling tiling; + VkImageLayout current_layout; + VkImageUsageFlags usage_flags; + bool preserve_at_quiet; + VkImage image; + MargaretMemAllocatorImagePosition* ans; +} MargaretMemoryOccupationImage; +typedef struct { + U16 kind; + VkBuffer buffer; + U64 occupied_by_sub_buffers; + U64 capacity; +} MargaretMemoryOccupationBuffer; + +typedef enum { + MargaretMemoryOccupation_Image, + MargaretMemoryOccupation_Buffer, +} MargaretMemoryOccupation_variant; + +typedef struct { + MargaretMemoryOccupation_variant variant; + U64 start; + U64 taken_size; + union { + MargaretMemoryOccupationImage img; + MargaretMemoryOccupationBuffer buf; + }; +} MargaretMemoryOccupation; + +bool MargaretMemoryOccupation_equal_MargaretMemoryOccupation( + const MargaretMemoryOccupation* A, const MargaretMemoryOccupation* B + ){ + return A->start == B->start; +} + +bool MargaretMemoryOccupation_less_MargaretMemoryOccupation( + const MargaretMemoryOccupation* A, const MargaretMemoryOccupation* B + ){ + return A->start < B->start; +} + +/* Needed for Set */ +typedef const MargaretMemoryOccupation* RefMargaretMemoryOccupation; + +#include "../../../gen/l1/eve/margaret/VecMargaretMemoryOccupation.h" +#include "../../../gen/l1/eve/margaret/OptionMargaretMemoryOccupation.h" +#include "../../../gen/l1/eve/margaret/OptionRefMargaretMemoryOccupation.h" +#include "../../../gen/l1_5/eve/margaret/BuffRBTree_SetMargaretMemoryOccupation.h" + +typedef struct { + U64 start; + U64 length; + MargaretMemAllocatorBufferPosition* ans; +} MargaretBufferOccupationSubBuffer; + +bool MargaretBufferOccupationSubBuffer_equal_MargaretBufferOccupationSubBuffer( + const MargaretBufferOccupationSubBuffer* A, const MargaretBufferOccupationSubBuffer* B + ){ + return A->start == B->start; +} + +bool MargaretBufferOccupationSubBuffer_less_MargaretBufferOccupationSubBuffer( + const MargaretBufferOccupationSubBuffer* A, const MargaretBufferOccupationSubBuffer* B + ){ + return A->start < B->start; +} + +/* Needed for Set */ +typedef const MargaretBufferOccupationSubBuffer* RefMargaretBufferOccupationSubBuffer; + +#include "../../../gen/l1/eve/margaret/VecMargaretBufferOccupationSubBuffer.h" +#include "../../../gen/l1/eve/margaret/OptionMargaretBufferOccupationSubBuffer.h" +#include "../../../gen/l1/eve/margaret/OptionRefMargaretBufferOccupationSubBuffer.h" +#include "../../../gen/l1_5/eve/margaret/BuffRBTree_SetMargaretBufferOccupationSubBuffer.h" + +typedef struct { + BuffRBTree_SetMargaretMemoryOccupation occupied_memory; + BuffRBTree_SetMargaretBufferOccupationSubBuffer occupied_buffers; + U64 length; + U64 occupation_counter; + VkDeviceMemory mem_hand; + void* mapped_memory; } MargaretMemAllocatorOneBlock; +#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorOneBlock.h" + +/* Used to enumerate both free memory segments in VkDeviceMemory + * and free memory in buffers of some kind */ typedef struct { + U64 start; + U64 len; + /* If this value somehow got higher than zero, your life fucking sucks */ + U8 dev_mem_block; +} MargaretFreeMemSegment; -} MargaretMemAllocatorOneType; +bool MargaretFreeMemSegment_equal( + const MargaretFreeMemSegment* A, const MargaretFreeMemSegment* B + ){ + return A->len == B->len && A->dev_mem_block == B->dev_mem_block && A->start == B->start; +} +bool MargaretFreeMemSegment_less( + const MargaretFreeMemSegment* A, const MargaretFreeMemSegment* B + ){ + if (A->len == B->len) { + if (A->dev_mem_block == B->dev_mem_block) { + return A->start < B->start; + } + return A->dev_mem_block < B->dev_mem_block; + } + return A->len < B->len; +} + +bool MargaretFreeMemSegment_equal_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); + return A_len == B_len && A->dev_mem_block == B->dev_mem_block && A->start == B->start; +} + + +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 A->dev_mem_block < B->dev_mem_block; + } + return A_len < B_len; +} + +typedef const MargaretFreeMemSegment* RefMargaretFreeMemSegment; + +#include "../../../gen/l1/eve/margaret/VecMargaretFreeMemSegment.h" +#include "../../../gen/l1/eve/margaret/OptionMargaretFreeMemSegment.h" +#include "../../../gen/l1/eve/margaret/OptionRefMargaretFreeMemSegment.h" +#include "../../../gen/l1_5/eve/margaret/BuffRBTreeByLen_SetMargaretFreeMemSegment.h" +#include "../../../gen/l1_5/eve/margaret/BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment.h" +#include "../../../gen/l1/eve/margaret/OptionBuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment.h" + +typedef struct { + VecMargaretMemAllocatorOneBlock blocks; + OptionBuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment free_space_in_memory[MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP]; + VkMemoryPropertyFlags mem_properties; +} MargaretMemAllocatorOneMemType; + +#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorOneMemType.h" + +/* My template instantiator requires the drop method */ +void MargaretMemAllocatorOneMemType_drop(MargaretMemAllocatorOneMemType self){ + VecMargaretMemAllocatorOneBlock_drop(self.blocks); + // VecBuffRBTreeByLen_SetMargaretFreeMemSegment_drop(self.free_space_inside_buffers); + for (U8 alignment_exp = 0; alignment_exp < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; alignment_exp++) + OptionBuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_drop(self.free_space_in_memory[alignment_exp]); +} + +typedef struct { + VkMemoryPropertyFlags mem_properties; + VkBufferUsageFlags usage; + U8 chosen_memory_type; + U8 inner_alignment_exp; + U64 total_occupation; + BuffRBTreeByLen_SetMargaretFreeMemSegment free_space_inside_buffers; +} MargaretBufferKindInfo; + +#include "../../../gen/l1/eve/margaret/VecMargaretBufferKindInfo.h" + +/* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */ struct MargaretMemAllocator { - + VecMargaretMemAllocatorOneMemType mem_types; + VecMargaretBufferKindInfo buffer_types; + double alpha; + VkDevice device; + VkPhysicalDevice physical_device; }; +MargaretMemAllocator MargaretMemAllocator_new( + VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types, double alpha + ){ + VkPhysicalDeviceMemoryProperties phd_props; + vkGetPhysicalDeviceMemoryProperties(physical_device, &phd_props); + assert(phd_props.memoryTypeCount < VK_MAX_MEMORY_TYPES); + MargaretMemAllocator self = {.buffer_types = VecMargaretBufferKindInfo_new_zeroinit(buffer_types.len), + .alpha = alpha, .device = device, .physical_device = physical_device, + .mem_types = VecMargaretMemAllocatorOneMemType_new_zeroinit(phd_props.memoryTypeCount)}; + + for (size_t i = 0; i < buffer_types.len; i++) { + const MargaretBufferKindDescription* desc = &buffer_types.data[i]; + check(U64_is_2pow(desc->inner_alignment)); + /* We create a test buffer to check which memory types will support it. We decide the link between + * buffer kind and memory type PERMANENTLY. Yes, I don't care what the specification says, if your + * buffer memory type support changes with size, EAT A DICK, fuck you, get the segfault you deserve + */ + VkBufferCreateInfo crinfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = desc->inner_alignment, /* Why not */ + .usage = desc->usage_flags, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VkBuffer test_buffer; + if (vkCreateBuffer(device, &crinfo, NULL, &test_buffer) != VK_SUCCESS) + abortf("Kill yourself!\n"); + VkMemoryRequirements mem_requirements; + vkGetBufferMemoryRequirements(device, test_buffer, &mem_requirements); + U8 first_good_memory_type; + for (U8 mt = 0; mt < (U8)phd_props.memoryTypeCount; mt++) { + if ((mem_requirements.memoryTypeBits & (1u << mt)) != 0 && + (phd_props.memoryTypes[mt].propertyFlags & desc->memory_properties) == desc->memory_properties) { + first_good_memory_type = mt; + goto found_good_memory_type; + } + } + abortf("No good memory type for %" PRIu64 " buffer kind\n", i); + found_good_memory_type: + vkDestroyBuffer(device, test_buffer, NULL); + + self.buffer_types.buf[i] = (MargaretBufferKindInfo){ + .mem_properties = desc->memory_properties, .usage = desc->usage_flags, + .chosen_memory_type = first_good_memory_type, .inner_alignment_exp = U64_2pow_log(desc->inner_alignment), + .total_occupation = 0, .free_space_inside_buffers = BuffRBTreeByLen_SetMargaretFreeMemSegment_new() + }; + } + assert(self.mem_types.len == phd_props.memoryTypeCount); + for (U32 i = 0; i < phd_props.memoryTypeCount; i++) { + self.mem_types.buf[i].blocks = VecMargaretMemAllocatorOneBlock_new(); + for (U8 ae = 0; ae < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; ae++) { + self.mem_types.buf[i].free_space_in_memory[ae] = None_BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment(); + } + self.mem_types.buf[i].mem_properties = phd_props.memoryTypes[i].propertyFlags; + } + return self; +} + bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, MargaretMemAllocatorRequest req){ return false; + // todo } bool MargaretMemAllocator_carry_out_request(MargaretMemAllocator* self, VkCommandBuffer cmd_buff, bool silence){ return false; + // todo: add OLD flag to mem allocator and like uh, fuck this shit man bruh lol deng + // todo: +} + +void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self){ + // todo } char* MargaretMemAllocator_get_host_visible_buffer_ptr( const MargaretMemAllocator* self, const MargaretMemAllocatorBufferPosition* pos){ - return NULL; + check(pos->memory_type_id < VK_MAX_MEMORY_TYPES); + const MargaretMemAllocatorOneMemType* memtype = &self->mem_types.buf[pos->memory_type_id]; + check((memtype->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + check(pos->memory_allocation_id < memtype->blocks.len); + const MargaretMemAllocatorOneBlock* bl = &memtype->blocks.buf[pos->memory_allocation_id]; + assert(bl->mapped_memory); + /* We could check correctness of this position, but who cares, lol */ + return (char*)bl->mapped_memory + pos->offset_in_device_memory_nubble; } \ 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 aaa6ddb..4e1c894 100644 --- a/src/l2/tests/data_structures/t2.c +++ b/src/l2/tests/data_structures/t2.c @@ -1,4 +1,6 @@ -#include +#include "../../../l1/core/util.h" + +typedef U64 VkDeviceSize; typedef int VkResult; @@ -12,7 +14,6 @@ const VkStructureType VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 200; const VkStructureType VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 3000; typedef int VkBufferCreateFlags; -typedef int VkDeviceSize; typedef int VkBufferUsageFlags; typedef int VkSharingMode; @@ -39,6 +40,8 @@ typedef struct { typedef int VkMemoryPropertyFlags; +const VkMemoryPropertyFlags VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 184; + typedef struct { VkMemoryPropertyFlags propertyFlags; // ...