Compare commits

...

2 Commits

6 changed files with 266 additions and 487 deletions

View File

@ -27,50 +27,53 @@ void generate_margaret_eve_for_vulkan_utils() {
});
/* For l2/margaret/vulkan_memory_claire.h */
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufferKindDescription"), false, true);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretOldBufferResizeRecord"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretResizeToNascentRecord"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretSubBufRelocationRequest"), true, false);
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("VecMargaretSubBufRelocationRequest"), true, false);
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("BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment")
});
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MargaretMemAllocatorOneBlock"), .vec = true,
});
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretBufferKindInfo"), true, false);
/* It is actually an integer (pointer) */
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("MargaretMemAllocatorOneBlock"), true, false);
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("KVPU64ToMargaretMemoryOccupation"), true, false);
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("MargaretMemoryOccupation")});
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("RefMargaretMemoryOccupation"), .t_ptr = true});
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("RefMutMargaretMemoryOccupation"), .t_ptr = true});
generate_eve_span_company_for_primitive(l, ns, cstr("KVPU64ToMargaretBufferOccupationSubBuffer"), 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_ptr = true});
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("RefMutMargaretBufferOccupationSubBuffer"), .t_ptr = true});
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeOccupant"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestResizeBuffer"), true, false);
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);
// generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
// .T = cstr("MargaretFreeMemSegment"), .t_primitive = true});
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("MargaretFreeMemSegment"), .t_primitive = true});
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeSubBuffer"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeImage"), true, false);
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MargaretMemAllocatorRequestResizeSubBuffer"), .t_primitive = true, .vec_extended = true});
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestAllocSubBuffer"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestAllocImage"), true, false);
generate_eve_span_company_for_non_primitive_non_clonable(l, ns,
cstr("MargaretMemAllocatorRequestsForCertainBufferKindAllocation"), true, false);
generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
.T = cstr("BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment")});
// generate_eve_span_company_for_primitive(l, ns, cstr("MargaretOldBufferResizeRecord"), true, false);
// generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufRelocationRequest"), true, false);
//
// 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("BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment")
// });
// generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
// .T = cstr("MargaretMemAllocatorOneBlock"), .vec = true,
// });
//
// generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
// .T = cstr("MargaretMemoryOccupation")});
// generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
// .T = cstr("RefMargaretMemoryOccupation"), .t_ptr = true});
// generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
// .T = cstr("RefMutMargaretMemoryOccupation"), .t_ptr = true});
//
// generate_eve_span_company_for_primitive(l, ns, cstr("MargaretFreeMemSegment"), true, false);
// generate_Option_templ_inst_eve_header(l, ns, (option_template_instantiation_op){
// .T = cstr("MargaretFreeMemSegment"), .t_primitive = true});
//
// generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeBuffer"), true, false);
// generate_eve_span_company_for_primitive(l, ns, cstr("MargaretMemAllocatorRequestFreeImage"), true, false);
// generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
// .T = cstr("MargaretMemAllocatorRequestResizeBuffer"), .t_primitive = true, .vec_extended = true});
// 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_non_primitive_non_clonable(l, ns,
// cstr("MargaretMemAllocatorRequestsForCertainBufferKindAllocation"), true, false);
}

View File

@ -10,11 +10,6 @@ void generate_l1_5_template_instantiations_for_margaret(){
mkdir_nofail("l1_5/eve/margaret");
/* For MargaretMemAllocator */
generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
.T = cstr("MargaretFreeMemSegment"), .t_primitive = true,
.alternative_less = cstr("MargaretFreeMemSegment_less"),
.alternative_comp_set_name_embed = cstr("Len"),
});
generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
.T = cstr("MargaretFreeMemSegment"), .t_primitive = true,
/* comparison takes additional U8 parameter */
@ -23,12 +18,8 @@ void generate_l1_5_template_instantiations_for_margaret(){
.guest_data_T = cstr("U8"),
});
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
/* MargaretMemoryOccupation is not primitive */
.K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMemoryOccupation"),
.K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMemoryOccupation"), .v_primitive = true,
}, true /* We want RBTreeNode_KVPU64ToMargaretMemoryOccupation to be generated here for us */ );
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("U64"), .k_integer = true, .V = cstr("MargaretBufferOccupationSubBuffer"), .v_primitive = true,
}, true);
}
#endif

View File

@ -43,6 +43,8 @@ typedef struct {
SpanU8 alternative_comp_map_name_embed;
SpanU8 guest_data_T;
bool at, mat;
} map_instantiation_op;
void map_instantiation_op_fix(map_instantiation_op* self){

View File

@ -338,6 +338,9 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V)));
// todo: write _erase_by_iter method
// todo: rewrite _erase using _erase_by_it
VecU8_append_vec(res, VecU8_fmt(
"bool %s_erase(%s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
SPACE "U64 v = %s_find(self, key);\n" /* set */
@ -490,39 +493,47 @@ NODISCARD VecU8 generate_buf_rbtree_Map_template_instantiation(map_instantiation
// todo: write erase_substitute (only if v is not primitive) using try_insert
// todo: write pop_substitute using try_insert
if (!op.v_primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"bool %s_erase_substitute(%s* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
SPACE "U64 col = %s_try_insert(self, key, value);\n" /* map */
SPACE "if (col == 0)\n"
SPACE SPACE "return true;\n"
"%v" "%v" /* "" / drop col->key, "" / drop col->value */
SPACE "self->el.buf[col - 1].key = key;\n"
SPACE "self->el.buf[col - 1].value = value;\n"
SPACE "return false;\n"
"}\n\n",
map, map, op.K, op.V, map,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(self->el.buf[col - 1].key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(self->el.buf[col - 1].value);\n", op.V)));
}
// codegen_append_buf_rbtree_map__insert_kind_method(&res, op, map, cstr("erase_substitute"), vcstr("bool"),
// vcstr("return true;\n"),
// VecU8_fmt("%v%v"
// "self->el.buf[cur - 1].key = key;\n"
// "self->el.buf[cur - 1].value = value;\n"
// "return false;\n",
// op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1].key);\n", op.K),
// op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1].value);\n", op.V)
// ));
//
// codegen_append_buf_rbtree_map__insert_kind_method(&res, op, map, cstr("pop_substitute"),
// VecU8_fmt("Option%s", op.V),
// VecU8_fmt("return None_%s();\n", op.V),
// VecU8_fmt(
// "%v" "self->el.buf[cur - 1].key = key;\n" /**/
// "%s saved = self->el.buf[cur - 1].value;\n" /* op.V */
// "self->el.buf[cur - 1].value = value;\n"
// "return Some_%s(saved);\n", /* op.V */
// op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1].key);\n", op.K),
// op.V, op.V));
VecU8_append_vec(&res, VecU8_fmt(
"Option%s %s_pop_substitute(%s* self, %s key, %s value) {\n" /* op.V, map, map, op.K, op.V */
SPACE "U64 col = %s_try_insert(self, key, value);\n" /* map */
SPACE "if (col == 0)\n"
SPACE SPACE "return None_%s();\n" /* op.V */
"%s saved = self->el.buf[col - 1].value;\n" /* op.V */
"%v" /* "" / drop col->key */
SPACE "self->el.buf[col - 1].key = key;\n"
SPACE "self->el.buf[col - 1].value = value;\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, op.K, op.V,
map, op.V,
op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(self->el.buf[col - 1].key);\n", op.K),
op.V));
// todo: write _pop() using _erase_empty_by_index()
// codegen_append_buff_rbtree_map__erase_kind_method(&res, op, map, cstr("pop"),
// VecU8_fmt("Option%s", op.V),
// VecU8_fmt("return None_%s();\n", op.V),
// VecU8_fmt("%v" "%s saved = self->el.buf[cur - 1].value;\n",
// op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1].key);\n", op.K),
// op.V),
// VecU8_fmt("return Some_%s(saved);\n", op.V));
// todo: write _pop_by_iter method
codegen_append_buf_rbtree_map__method_at(&res, op, map, false);
codegen_append_buf_rbtree_map__method_at(&res, op, map, true);
// todo: write _pop method
if (op.at)
codegen_append_buf_rbtree_map__method_at(&res, op, map, false);
if (op.mat)
codegen_append_buf_rbtree_map__method_at(&res, op, map, true);
/* These functions break my design and return answer through pointers given in arguments. For greater good ofk */
codegen_append_buff_rbtree_map__method_at_iter(&res, op, map, false);

View File

@ -15,7 +15,7 @@ NODISCARD VecU8 codegen_rbtree__node_structure(map_instantiation_op op){
"typedef struct {\n"
SPACE "RBTreeNode base;\n"
SPACE "%s key;\n" /* op.K*/
"" /* "" / op.V value; */
"%v" /* "" / op.V value; */
"} %s;\n\n", /* node */
op.K, op.V.len > 0 ? VecU8_fmt(SPACE "%s value;\n", op.V) : vcstr(""),
node);
@ -99,8 +99,8 @@ void codegen_append_rbtree_map__structure_and_simplest_methods(
SPACE "}\n"
SPACE "free(self.NIL);\n"
"}\n\n", set, set,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_TT*)cur)->key);\n", op.K, TT),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_TT*)cur)->value);\n", op.V, TT)
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_%s*)cur)->key);\n", op.K, TT),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_%s*)cur)->value);\n", op.V, TT)
));
VecU8_append_vec(res, VecU8_fmt(
@ -253,7 +253,7 @@ void codegen_append_rbtree_map__structure_and_simplest_methods(
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_val(op)),
TT,
TT, TT, TT,
TT, op.v_primitive ? cstr("") : cstr(", .value = value")));
TT, op.V.len == 0 ? cstr("") : cstr(", .value = value")));
VecU8_append_vec(res, VecU8_fmt(
"bool %s_insert(%s* self, %v){\n" /* set, set, taking_t_argument */
@ -268,19 +268,27 @@ void codegen_append_rbtree_map__structure_and_simplest_methods(
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V)));
VecU8_append_vec(res, VecU8_fmt(
"void %s_erase_by_iter(%s* self, RBTreeNode_%s* it) {\n" /* set, set, TT */
SPACE "assert(it != NULL);\n"
"%v" /* "" / op.K_drop(it->key) */
"%v" /* "" / op.V_drop(it->value) */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)it);\n"
"}\n\n",
set, set, TT,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(it->value);\n", op.V)));
VecU8_append_vec(res, VecU8_fmt(
"bool %s_erase(%s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* TT, set */
SPACE "if (v == NULL)\n"
SPACE SPACE "return false;\n"
"%v" /* "" / op.K_drop(v->key) */
"%v" /* "" / op.V_drop(v->value) */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "%s_erase_by_iter(self, v);\n" /* set */
SPACE "return true;\n"
"}\n\n", set, set, codegen_rbtree_map__taking_ref_k_argument(op),
TT, set,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->value);\n", op.V)));
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
TT, set, set));
}
@ -360,7 +368,7 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
"}\n\n",
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
kvp, map, op.V,
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.V, op.V));
if (!op.v_primitive) {
@ -379,6 +387,9 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V)));
}
// todo: write _pop_by_it
// todo: rewrite pop using _pop_by_it
VecU8_append_vec(&res, VecU8_fmt(
"Option%s %s_pop(%s* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* kvp, map */
@ -386,14 +397,16 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
SPACE SPACE "return None_%s();\n" /* op.V */
"%v" /* "" / op.K_drop(v->key) */
"%s saved = v->value;\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, v);\n"
SPACE "return Some_%s();\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.V, op.V));
// todo: write generator for methods _at and _mat
return res;
}

View File

@ -174,95 +174,6 @@
#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 */
/* ======== End of MargaretMemAllocator backend interface ======== */
typedef struct {
VkBufferUsageFlags usage_flags;
VkMemoryPropertyFlags memory_properties;
bool preserve_at_quiet;
U64 inner_alignment;
} MargaretBufferKindDescription;
#include "../../../gen/l1/eve/margaret/SpanMargaretBufferKindDescription.h"
typedef struct {
VkBuffer buffer;
U64 offset;
/* Fun fact: Muller dictionary recognizes nubble, but not nubbin, while firefox spellchecker and clion
* recognize nubbin, but not nubble. But I prefer nubble more. */
U64 offset_in_device_memory_nubble;
/* 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 */
U32 memory_allocation_id;
} MargaretMemAllocatorSubBufferPosition;
typedef struct {
VkImage image;
U64 offset_in_device_memory_nubble;
U32 memory_allocation_id;
} MargaretMemAllocatorImagePosition;
typedef MargaretMemAllocatorSubBufferPosition* MargaretMemAllocatorRequestFreeSubBuffer;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestFreeSubBuffer.h"
typedef MargaretMemAllocatorImagePosition* MargaretMemAllocatorRequestFreeImage;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestFreeImage.h"
typedef struct {
MargaretMemAllocatorSubBufferPosition* prev_ans;
U64 new_size;
} MargaretMemAllocatorRequestResizeSubBuffer;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestResizeSubBuffer.h"
typedef struct {
/* We don't specify the buffer kind, because you should place this request in a vector,
* corresponding to needed buffer kind */
U64 size;
/* If I were you, I would just store this in heap and did not care */
MargaretMemAllocatorSubBufferPosition* ans;
} MargaretMemAllocatorRequestAllocSubBuffer;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestAllocSubBuffer.h"
typedef struct {
U64 width;
U64 height;
VkFormat format;
VkImageTiling tiling;
VkImageLayout initial_layout;
VkImageUsageFlags usage_flags;
VkMemoryPropertyFlags memory_properties;
bool preserve_at_quiet;
/* If I were you, I would just store this in heap and did not care*/
MargaretMemAllocatorImagePosition* ans;
} MargaretMemAllocatorRequestAllocImage;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestAllocImage.h"
/* It is users job to put resize and alloca requests for sub-buffers of type T to the corresponding request
* vectors for this exact type T */
typedef struct {
VecMargaretMemAllocatorRequestResizeSubBuffer expand;
VecMargaretMemAllocatorRequestAllocSubBuffer alloc;
} MargaretMemAllocatorRequestsForCertainBufferKindAllocation;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestsForCertainBufferKindAllocation.h"
typedef struct {
VecMargaretMemAllocatorRequestFreeSubBuffer free_subbuffer;
VecMargaretMemAllocatorRequestFreeImage free_image;
VecMargaretMemAllocatorRequestResizeSubBuffer shrink_subbuffer;
VecMargaretMemAllocatorRequestsForCertainBufferKindAllocation expand_alloc_buffer;
VecMargaretMemAllocatorRequestAllocImage alloc_image;
} MargaretMemAllocatorRequest;
/* That is our guy! */
typedef struct MargaretMemAllocator MargaretMemAllocator;
MargaretMemAllocator MargaretMemAllocator_new(
VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types,
VkMemoryPropertyFlags mem_properties, U8 memory_type_id);
/* Demands + Warnings */
typedef U8 MargaretMemAllocatorDemands;
/* If we do defragmentation, MargaretMemAllocator warns us that for
@ -281,25 +192,15 @@ typedef U8 MargaretMemAllocatorDemands;
*/
#define MARGARET_MEM_ALLOCATOR_DEMANDS_CMD_BUFFER 2
/* Appends copying commands into cmd_buff. It may append none. Defragmentation, device memory relocation
* need copying commands, but buffer resize may also require copying */
MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request(
MargaretMemAllocator* self, VkCommandBuffer cmd_buff, MargaretMemAllocatorRequest* request);
void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self);
char* MargaretMemAllocator_get_host_visible_buffer_ptr(
const MargaretMemAllocator* self, const MargaretMemAllocatorSubBufferPosition* pos);
#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 21
/* ======= End of MargaretMemAllocator client interface ======== */
#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"
typedef struct MargaretMemAllocatorOccupantPosition MargaretMemAllocatorOccupantPosition;
typedef struct {
U64 width;
U64 height;
@ -309,38 +210,15 @@ typedef struct {
VkImageUsageFlags usage_flags;
bool preserve_at_quiet;
VkImage image;
MargaretMemAllocatorImagePosition* ans;
MargaretMemAllocatorOccupantPosition* ans;
} MargaretMemoryOccupationImage;
/* Stored in MargaretMemoryOccupation::buf */
/* primitive */
typedef struct {
U64 length;
MargaretMemAllocatorSubBufferPosition* ans;
} MargaretBufferOccupationSubBuffer;
/* Needed for Map<U64, MargaretBufferOccupationSubBuffer> */
typedef const MargaretBufferOccupationSubBuffer* RefMargaretBufferOccupationSubBuffer;
typedef MargaretBufferOccupationSubBuffer* RefMutMargaretBufferOccupationSubBuffer;
typedef struct {
U64 key; /* start */
MargaretBufferOccupationSubBuffer value;
} KVPU64ToMargaretBufferOccupationSubBuffer;
#include "../../../gen/l1/eve/margaret/VecKVPU64ToMargaretBufferOccupationSubBuffer.h"
#include "../../../gen/l1/eve/margaret/OptionMargaretBufferOccupationSubBuffer.h"
#include "../../../gen/l1/eve/margaret/OptionRefMargaretBufferOccupationSubBuffer.h"
#include "../../../gen/l1/eve/margaret/OptionRefMutMargaretBufferOccupationSubBuffer.h"
#include "../../../gen/l1_5/eve/margaret/BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer.h"
/* Not primitive */
typedef struct {
U16 kind;
VkBufferUsageFlags usage_flags;
bool preserve_at_quiet;
VkBuffer buffer;
U64 capacity;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer subbuffers;
U64 capacity; /* Needed only for debugging purposes */
} MargaretMemoryOccupationBuffer;
typedef enum {
@ -350,6 +228,7 @@ typedef enum {
typedef struct {
U64 taken_size;
MargaretMemAllocatorOccupantPosition* ans;
MargaretMemoryOccupation_variant variant;
union {
MargaretMemoryOccupationImage img;
@ -357,29 +236,11 @@ typedef struct {
};
} MargaretMemoryOccupation;
void MargaretMemoryOccupation_drop(MargaretMemoryOccupation self){
if (self.variant == MargaretMemoryOccupation_Buffer) {
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_drop(self.buf.subbuffers);
}
}
/* Needed for Map<U64, MargaretMemoryOccupation> */
typedef const MargaretMemoryOccupation* RefMargaretMemoryOccupation;
typedef MargaretMemoryOccupation* RefMutMargaretMemoryOccupation;
typedef struct{
U64 key;
MargaretMemoryOccupation value;
} KVPU64ToMargaretMemoryOccupation;
#include "../../../gen/l1/eve/margaret/VecKVPU64ToMargaretMemoryOccupation.h"
#include "../../../gen/l1/eve/margaret/OptionMargaretMemoryOccupation.h"
#include "../../../gen/l1/eve/margaret/OptionRefMargaretMemoryOccupation.h"
#include "../../../gen/l1/eve/margaret/OptionRefMutMargaretMemoryOccupation.h"
#include "../../../gen/l1_5/eve/margaret/BuffRBTree_MapU64ToMargaretMemoryOccupation.h"
#include "../../../gen/l1_5/eve/margaret/RBTree_MapU64ToMargaretMemoryOccupation.h"
/* Not primitive */
typedef struct {
BuffRBTree_MapU64ToMargaretMemoryOccupation occupied_memory;
RBTree_MapU64ToMargaretMemoryOccupation occupied_memory;
U64 length;
/* I am 100% sure that this fields is useless rn. You might use it to show cool infographics on F3 screen */
U64 occupation_counter;
@ -387,14 +248,58 @@ typedef struct {
void* mapped_memory;
} MargaretMemAllocatorOneBlock;
void MargaretMemAllocatorOneBlock_drop(MargaretMemAllocatorOneBlock self){
BuffRBTree_MapU64ToMargaretMemoryOccupation_drop(self.occupied_memory);
RBTree_MapU64ToMargaretMemoryOccupation_drop(self.occupied_memory);
}
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorOneBlock.h"
/* Used to enumerate both free memory segments in VkDeviceMemory
* and free memory in buffers of some kind */
struct MargaretMemAllocatorOccupantPosition{
U64 device_mem_ind;
RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it;
};
typedef MargaretMemAllocatorOccupantPosition* MargaretMemAllocatorRequestFreeOccupant;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestFreeOccupant.h"
typedef MargaretMemAllocatorRequestFreeOccupant MargaretMemAllocatorRequestFreeBuffer;
typedef MargaretMemAllocatorRequestFreeOccupant MargaretMemAllocatorRequestFreeImage;
typedef struct{
U64 new_size;
MargaretMemAllocatorOccupantPosition* ans;
} MargaretMemAllocatorRequestResizeBuffer;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestResizeBuffer.h"
typedef struct {
VkBufferUsageFlags usage;
bool preserve_at_quiet;
MargaretMemAllocatorOccupantPosition* ans;
} MargaretMemAllocatorRequestAllocBuffer;
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorRequestAllocBuffer.h"
typedef struct {
U64 width;
U64 height;
VkFormat format;
VkImageTiling tiling;
VkImageLayout current_layout;
VkImageUsageFlags usage_flags;
bool preserve_at_quiet;
MargaretMemAllocatorOccupantPosition* ans;
} 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;
typedef struct {
U64 start;
U64 len;
@ -429,37 +334,35 @@ bool MargaretFreeMemSegment_less_resp_align(
}
#include "../../../gen/l1/eve/margaret/VecMargaretFreeMemSegment.h"
#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLen_SetMargaretFreeMemSegment.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{
U32 old_mem_block_id;
U64 old_start;
U64 old_len;
U32 new_mem_block_id;
U64 new_start;
U64 new_len;
} MargaretOldBufferResizeRecord;
#include "../../../gen/l1/eve/margaret/VecMargaretOldBufferResizeRecord.h"
typedef struct {
U32 old_mem_block_id;
U64 old_start;
U64 old_len;
U64 offset_in_nascent_buffer;
} MargaretResizeToNascentRecord;
#include "../../../gen/l1/eve/margaret/VecMargaretResizeToNascentRecord.h"
/* This is not a request from a user to MMA, this is a request from MMA to MMA-defragmentation subroutine */
typedef struct{
U64 old_size; /* in buffer in old VkDeviceMemory */
U64 new_size; /* in buffer in new VkDeviceMemory */
MargaretMemAllocatorSubBufferPosition* ans;
} MargaretSubBufRelocationRequest;
#include "../../../gen/l1/eve/margaret/VecMargaretSubBufRelocationRequest.h"
#include "../../../gen/l1/eve/margaret/VecVecMargaretSubBufRelocationRequest.h"
// typedef struct{
// U32 old_mem_block_id;
// U64 old_start;
// U64 old_len;
// U32 new_mem_block_id;
// U64 new_start;
// U64 new_len;
// } MargaretOldBufferResizeRecord;
// #include "../../../gen/l1/eve/margaret/VecMargaretOldBufferResizeRecord.h"
//
// typedef struct {
// U32 old_mem_block_id;
// U64 old_start;
// U64 old_len;
// U64 offset_in_nascent_buffer;
// } MargaretResizeToNascentRecord;
// #include "../../../gen/l1/eve/margaret/VecMargaretResizeToNascentRecord.h"
//
// /* This is not a request from a user to MMA, this is a request from MMA to MMA-defragmentation subroutine */
// typedef struct{
// U64 old_size; /* in buffer in old VkDeviceMemory */
// U64 new_size; /* in buffer in new VkDeviceMemory */
// MargaretMemAllocatorSubBufferPosition* ans;
// } MargaretSubBufRelocationRequest;
// #include "../../../gen/l1/eve/margaret/VecMargaretSubBufRelocationRequest.h"
#include "../../../gen/l1/VecAndSpan_U8.h"
@ -481,14 +384,14 @@ MargaretMemFreeSpaceManager MargaretMemFreeSpaceManager_new(){
void MargaretMemFreeSpaceManager_drop(MargaretMemFreeSpaceManager self){
for (U8 alignment_exp = 0; alignment_exp < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; alignment_exp++)
OptionBuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_drop(self.free_space_in_memory[alignment_exp]);
OptionBufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_drop(self.free_space_in_memory[alignment_exp]);
VecU8_drop(self.set_present);
}
void MargaretMemFreeSpaceManager_sink(MargaretMemFreeSpaceManager* self){
for (U8 ae = 0; ae < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; ae++)
if (self->free_space_in_memory[ae].variant == Option_Some)
BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_sink(&self->free_space_in_memory[ae].some);
BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_sink(&self->free_space_in_memory[ae].some);
}
void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 start, U64 len, U32 dev_mem_block){
@ -499,7 +402,7 @@ void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 sta
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 = BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_erase(&
bool eret = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_erase(&
man->free_space_in_memory[alignment].some, &(MargaretFreeMemSegment){start, len, dev_mem_block});
assert(eret);
}
@ -512,7 +415,7 @@ void MargaretMemFreeSpaceManager_insert(MargaretMemFreeSpaceManager* man, U64 st
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 = BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&
bool iret = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&
man->free_space_in_memory[alignment].some, (MargaretFreeMemSegment){start, len, dev_mem_block});
assert(iret);
}
@ -523,57 +426,25 @@ OptionMargaretFreeMemSegment MargaretMemFreeSpaceManager_search(MargaretMemFreeS
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);
BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment* have = &man->free_space_in_memory[man->set_present.buf[0]].some;
man->free_space_in_memory[alignment_exp] = Some_BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment(
BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_new_reserved(alignment_exp, have->el.len));
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));
for (size_t i = 0; i < have->el.len; i++) {
// MargaretFreeMemSegment
BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&man->free_space_in_memory[alignment_exp].some,
BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&man->free_space_in_memory[alignment_exp].some,
*VecMargaretFreeMemSegment_at(&have->el, i));
}
}
assert(man->free_space_in_memory[alignment_exp].variant == Option_Some);
U64 sit = BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_find_min_grtr_or_eq(&man->free_space_in_memory[alignment_exp].some,
U64 sit = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_find_min_grtr_or_eq(&man->free_space_in_memory[alignment_exp].some,
&(MargaretFreeMemSegment){.start = 0, .len = len, .dev_mem_block = 0});
if (sit == 0)
return None_MargaretFreeMemSegment();
return Some_MargaretFreeMemSegment(*BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_at_iter(
return Some_MargaretFreeMemSegment(*BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_at_iter(
&man->free_space_in_memory[alignment_exp].some, sit));
}
typedef struct {
VkBufferUsageFlags usage;
U8 inner_alignment_exp;
bool preserve_at_quiet;
U64 total_occupation;
BuffRBTreeByLen_SetMargaretFreeMemSegment free_space_inside_buffers;
} MargaretBufferKindInfo;
void MargaretBufferKindInfo_drop(MargaretBufferKindInfo self){
BuffRBTreeByLen_SetMargaretFreeMemSegment_drop(self.free_space_inside_buffers);
}
void MargaretBufferKindInfo_erase_free_space(MargaretBufferKindInfo* self, U64 start, U64 len, U32 dev_mem_block){
if (len == 0)
return;
bool eret = BuffRBTreeByLen_SetMargaretFreeMemSegment_erase(&self->free_space_inside_buffers,
&(MargaretFreeMemSegment){.start = start, .len = len, .dev_mem_block = dev_mem_block});
assert(eret);
}
void MargaretBufferKindInfo_insert_free_space(MargaretBufferKindInfo* self, U64 start, U64 len, U32 dev_mem_block){
if (len == 0)
return;
bool iret = BuffRBTreeByLen_SetMargaretFreeMemSegment_insert(&self->free_space_inside_buffers,
(MargaretFreeMemSegment){start, len, dev_mem_block});
assert(iret);
}
#include "../../../gen/l1/eve/margaret/VecMargaretBufferKindInfo.h"
/* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */
struct MargaretMemAllocator {
typedef struct {
VecMargaretMemAllocatorOneBlock 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
@ -583,28 +454,22 @@ struct MargaretMemAllocator {
* that MargaretMemAllocator_carry_out_request generates, you can (and should) wipe out old blocks
*/
VecMargaretMemAllocatorOneBlock old_blocks;
/* If your previous set of requests did not cause defragmentation, it could cause relocation of some data
* in a subbuffer that you wanted to resize */
VecMargaretOldBufferResizeRecord old_buff_resize_record;
MargaretMemFreeSpaceManager mem_free_space;
VecMargaretBufferKindInfo buffer_types;
VkMemoryPropertyFlags mem_properties;
U8 memory_type_id;
VkDevice device;
VkPhysicalDevice physical_device;
};
} MargaretMemAllocator;
MargaretMemAllocator MargaretMemAllocator_new(
VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types,
VkMemoryPropertyFlags mem_properties, U8 memory_type_id
VkDevice device, VkPhysicalDevice physical_device, VkMemoryPropertyFlags mem_properties, U8 memory_type_id
){
MargaretMemAllocator self = {
.buffer_types = VecMargaretBufferKindInfo_new_reserved(buffer_types.len),
.blocks = VecMargaretMemAllocatorOneBlock_new(),
.old_blocks = VecMargaretMemAllocatorOneBlock_new(),
.old_buff_resize_record = VecMargaretOldBufferResizeRecord_new(),
// .old_buff_resize_record = VecMargaretOldBufferResizeRecord_new(),
.mem_free_space = MargaretMemFreeSpaceManager_new(),
.memory_type_id = memory_type_id,
.mem_properties = mem_properties,
@ -612,69 +477,53 @@ MargaretMemAllocator MargaretMemAllocator_new(
.physical_device = physical_device
};
for (size_t i = 0; i < buffer_types.len; i++) {
const MargaretBufferKindDescription* desc = &buffer_types.data[i];
check(U64_is_2pow(desc->inner_alignment));
VecMargaretBufferKindInfo_append(&self.buffer_types, (MargaretBufferKindInfo){
.usage = desc->usage_flags,
.inner_alignment_exp = U64_2pow_log(desc->inner_alignment),
.preserve_at_quiet = desc->preserve_at_quiet,
.total_occupation = 0,
.free_space_inside_buffers = BuffRBTreeByLen_SetMargaretFreeMemSegment_new()
});
}
return self;
}
void MargaretMemAllocator__sink_memory(MargaretMemAllocator* self){
for (size_t i = 0; i < self->buffer_types.len; i++)
BuffRBTreeByLen_SetMargaretFreeMemSegment_sink(&self->buffer_types.buf[i].free_space_inside_buffers);
MargaretMemFreeSpaceManager_sink(&self->mem_free_space);
}
// void MargaretMemAllocator__sink_memory(MargaretMemAllocator* self){
// MargaretMemFreeSpaceManager_sink(&self->mem_free_space);
// }
U64Segment MargaretMemAllocatorOneBlock_get_left_free_space(const MargaretMemAllocatorOneBlock* self, U64 occ_it){
U64 occ_start;
const MargaretMemoryOccupation* occ;
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&self->occupied_memory, occ_it, &occ_start, &occ);
U64Segment MargaretMemAllocatorOneBlock_get_left_free_space(
const MargaretMemAllocatorOneBlock* self, RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it){
U64 occ_start = occ_it->key;
U64 prev_occ_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_prev(&self->occupied_memory, occ_it);
if (prev_occ_it != 0) {
U64 prev_occ_start;
const MargaretMemoryOccupation* prev_occ;
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&self->occupied_memory, prev_occ_it, &prev_occ_start, &prev_occ);
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)};
RBTreeNode_KVPU64ToMargaretMemoryOccupation* prev_occ_it =
RBTree_MapU64ToMargaretMemoryOccupation_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,
.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, U64 occ_it){
U64 occ_start;
const MargaretMemoryOccupation* occ;
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&self->occupied_memory, occ_it, &occ_start, &occ);
U64Segment MargaretMemAllocatorOneBlock_get_right_free_space(
const MargaretMemAllocatorOneBlock* self, RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it){
U64 occ_start = occ_it->key;
U64 occ_taken_size = occ_it->value.taken_size;
U64 next_occ_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_next(&self->occupied_memory, occ_it);
if (next_occ_it != 0) {
U64 next_occ_start;
const MargaretMemoryOccupation* next_occ;
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&self->occupied_memory, next_occ_it, &next_occ_start, &next_occ);
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)};
RBTreeNode_KVPU64ToMargaretMemoryOccupation* next_occ_it =
RBTree_MapU64ToMargaretMemoryOccupation_find_next(&self->occupied_memory, occ_it);
if (next_occ_it != NULL) {
U64 next_occ_start = next_occ_it->key;
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->length - (occ_start + occ->taken_size)};
return (U64Segment){.start = occ_start + occ_taken_size, .len = self->length - (occ_start + occ_taken_size)};
}
/* If mem occupant in question is VkBuffer, it won't delete anything from the set of available free mem segments
* for that buffer kindred. It is your job to remove free buffer subsegments from this set*/
void MargaretMemAllocator__get_rid_of_memory_occupant(
MargaretMemAllocator* self, U32 mem_block_id, U64 occ_it){
MargaretMemAllocator* self, U32 mem_block_id, RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it){
MargaretMemAllocatorOneBlock* block = VecMargaretMemAllocatorOneBlock_mat(&self->blocks, mem_block_id);
U64 occ_start;
const MargaretMemoryOccupation* occ;
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&block->occupied_memory, occ_it, &occ_start, &occ);
const MargaretMemoryOccupation* occ = &occ_it->value;
/* Updating block usage counter */
/* Updating block usage counter TODO: do it everywhere */
block->occupation_counter -= occ->taken_size;
U64Segment left_free_space = MargaretMemAllocatorOneBlock_get_left_free_space(block, occ_it);
@ -686,10 +535,7 @@ void MargaretMemAllocator__get_rid_of_memory_occupant(
vkDestroyImage(self->device, occ->img.image, NULL);
}
/* All these iterators and pointers will get invalidated */
MargaretMemoryOccupation_drop(*occ); // yes, this is illegal, but it works. Don't do it again, please
BuffRBTree_MapU64ToMargaretMemoryOccupation_empty_index_erase(&block->occupied_memory, occ_it);
/* All these iterators and pointers just got invalidated */
RBTree_MapU64ToMargaretMemoryOccupation_erase_by_iter(&block->occupied_memory, occ_it);
MargaretMemFreeSpaceManager_erase(&self->mem_free_space, left_free_space.start, left_free_space.len, mem_block_id);
MargaretMemFreeSpaceManager_erase(&self->mem_free_space, right_free_space.start, right_free_space.len, mem_block_id);
@ -698,107 +544,21 @@ void MargaretMemAllocator__get_rid_of_memory_occupant(
right_free_space.start + right_free_space.len - left_free_space.start, mem_block_id);
}
/* Given a subbuffer inside given buffer, returns segment of free space on the left */
U64Segment MargaretMemoryOccupationBuffer_get_left_free_space(
MargaretMemoryOccupationBuffer* buf, U64 subbuf_it){
U64 subbuf_start;
const MargaretBufferOccupationSubBuffer* subbuf;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, subbuf_it, &subbuf_start, &subbuf);
assert(subbuf_start + subbuf->length <= buf->capacity);
U64 prev_subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find_prev(&buf->subbuffers, subbuf_it);
if (prev_subbuf_it != 0) {
U64 prev_subbuf_start;
const MargaretBufferOccupationSubBuffer* prev_subbuf;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, prev_subbuf_it, &prev_subbuf_start, &prev_subbuf);
assert(prev_subbuf_start + prev_subbuf->length <= subbuf_start);
return (U64Segment){.start = prev_subbuf_start + prev_subbuf->length, .len = subbuf_start - (prev_subbuf_start + prev_subbuf->length)};
}
return (U64Segment){.start = 0, .len = subbuf_start};
}
/* Given a subbuffer inside this buffer, return segment of free space on the right */
U64Segment MargaretMemoryOccupationBuffer_get_right_free_space(
MargaretMemoryOccupationBuffer* buf, U64 subbuf_it){
U64 subbuf_start;
const MargaretBufferOccupationSubBuffer* subbuf;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, subbuf_it, &subbuf_start, &subbuf);
assert(subbuf_start + subbuf->length <= buf->capacity);
U64 next_subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find_next(&buf->subbuffers, subbuf_it);
if (next_subbuf_it != 0) {
U64 next_subbuf_start;
const MargaretBufferOccupationSubBuffer* next_subbuf;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, next_subbuf_it, &next_subbuf_start, &next_subbuf);
assert(subbuf_start + subbuf->length <= next_subbuf_start);
return (U64Segment){.start = subbuf_start + subbuf->length, .len = next_subbuf_start - (subbuf_start + subbuf->length)};
}
return (U64Segment){.start = subbuf_start + subbuf->length, .len = buf->capacity - (subbuf_start + subbuf->length)};
}
/* Don't forget that all the iterators for MMA maps for buffers and sets for free space just got invalidated */
void MargaretMemAllocator__get_rid_of_sub_buffer(MargaretMemAllocator* self, U32 mem_block_id, U64 start){
MargaretMemAllocatorOneBlock* block = VecMargaretMemAllocatorOneBlock_mat(&self->blocks, mem_block_id);
U64 occ_it = BuffRBTree_MapU64ToMargaretMemoryOccupation_find_max_less_or_eq(&block->occupied_memory, 2);
U64 occ_start;
MargaretMemoryOccupation* occ_buf;
BuffRBTree_MapU64ToMargaretMemoryOccupation_mat_iter(&block->occupied_memory, occ_it, &occ_start, &occ_buf);
assert(occ_buf->variant == MargaretMemoryOccupation_Buffer);
MargaretMemoryOccupationBuffer* buf = &occ_buf->buf;
assert(occ_start <= start);
MargaretBufferKindInfo* kindred = VecMargaretBufferKindInfo_mat(&self->buffer_types, buf->kind);
U64 subbuf_it = BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_find(&buf->subbuffers, start - occ_start);
U64 subbuf_start;
const MargaretBufferOccupationSubBuffer* subbuf;
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_at_iter(&buf->subbuffers, subbuf_it, &subbuf_start, &subbuf);
assert(subbuf_start == start - occ_start);
assert(subbuf_start + subbuf->length <= buf->capacity);
assert(start + subbuf->length <= occ_start + buf->capacity);
kindred->total_occupation -= subbuf->length; // todo: give a thought to memory counting
U64Segment left_free_space = MargaretMemoryOccupationBuffer_get_left_free_space(buf, subbuf_it);
U64Segment right_free_space = MargaretMemoryOccupationBuffer_get_right_free_space(buf, subbuf_it);
/* all these iterators and pointers will get invalidated */
/* Because MargaretBufferOccupationSubBuffer is primitive, we don't need to drop it before erasing */
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer_empty_index_erase(&buf->subbuffers, subbuf_it);
/* all these iterators and pointers just got invalidated */
MargaretBufferKindInfo_erase_free_space(kindred, left_free_space.start, left_free_space.len, mem_block_id);
MargaretBufferKindInfo_erase_free_space(kindred, right_free_space.start, right_free_space.len, mem_block_id);
if (buf->subbuffers.el.len == 0) {
/* We don't actually need to add the BIG free memory segment because we are already deleting the whole buffer */
MargaretMemAllocator__get_rid_of_memory_occupant(self, mem_block_id, occ_it);
} else {
U64 LEN = right_free_space.start + right_free_space.len - left_free_space.start;
assert(LEN > 0);
MargaretBufferKindInfo_insert_free_space(kindred, left_free_space.start, LEN, mem_block_id);
}
}
/* This function puts block into invalid state. Which means block should already be in unusable state.
* This structure only wipes out vulkan handlers, destroyes buffers, images, and then destroys memory block
* It won't drop anything, you should do it after you called it.
* It is useful when dropping the whole allocator or when wiping old blocks
*/
void MargaretMemAllocator__clean_handlers_in_block(const MargaretMemAllocator* self, const MargaretMemAllocatorOneBlock* block){
assert(((self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) ==
(block->mapped_memory != NULL));
if (block->mapped_memory)
vkUnmapMemory(self->device, block->mapped_memory);
for (size_t i = 0; i < block->occupied_memory.el.len; i++) {
const MargaretMemoryOccupation* occ = &block->occupied_memory.el.buf[i].value;
if (occ->variant == MargaretMemoryOccupation_Buffer) {
const MargaretMemoryOccupationBuffer* wb = &occ->buf;
vkDestroyBuffer(self->device, wb->buffer, NULL);
} else if (occ->variant == MargaretMemoryOccupation_Image) {
const MargaretMemoryOccupationImage* wi = &occ->img;
vkDestroyImage(self->device, wi->image, NULL);
for (RBTreeNode_KVPU64ToMargaretMemoryOccupation* i =
RBTree_MapU64ToMargaretMemoryOccupation_find_min(&block->occupied_memory); i;
i = RBTree_MapU64ToMargaretMemoryOccupation_find_next(&block->occupied_memory, i))
{
if (i->value.variant == MargaretMemoryOccupation_Buffer) {
vkDestroyBuffer(self->device, i->value.buf.buffer, NULL);
} else {
assert(i->value.variant == MargaretMemoryOccupation_Image);
vkDestroyImage(self->device, i->value.img.image, NULL);
}
}
vkFreeMemory(self->device, block->mem_hand, NULL);
@ -813,14 +573,27 @@ void MargaretMemAllocator_drop(MargaretMemAllocator self){
}
VecMargaretMemAllocatorOneBlock_drop(self.old_blocks);
VecMargaretMemAllocatorOneBlock_drop(self.blocks);
VecMargaretOldBufferResizeRecord_drop(self.old_buff_resize_record);
VecMargaretBufferKindInfo_drop(self.buffer_types);
// VecMargaretOldBufferResizeRecord_drop(self.old_buff_resize_record);
MargaretMemFreeSpaceManager_drop(self.mem_free_space);
}
void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self){
assert(!self->old_blocks.len || !self->old_buff_resize_record.len);
for (size_t blind = 0; blind < self->old_blocks.len; blind++) {
MargaretMemAllocator__clean_handlers_in_block(self, &self->old_blocks.buf[blind]);
}
VecMargaretMemAllocatorOneBlock_sink(&self->old_blocks, 0);
for (U64 ri = 0; ri < self->old_buff_resize_record.len; ri++) {
const MargaretOldBufferResizeRecord* resize = &self->old_buff_resize_record.buf[ri];
if (resize->old_mem_block_id != resize->new_mem_block_id || resize->old_start != resize->new_start) {
MargaretMemAllocator__get_rid_of_sub_buffer(self, resize->old_mem_block_id, resize->old_start);
}
}
VecMargaretOldBufferResizeRecord_sink(&self->old_buff_resize_record, 0);
}
MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request(
MargaretMemAllocator* self, VkCommandBuffer cmd_buff, MargaretMemAllocatorRequest* request
MargaretMemAllocator* self, VkCommandBuffer cmd_buff, MargaretMemAllocatorRequests* requests
){
MargaretMemAllocator_wipe_old(self);
assert(request->expand_alloc_buffer.len == self->buffer_types.len);
@ -1012,21 +785,7 @@ MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request(
return 0;
}
void MargaretMemAllocator_wipe_old(MargaretMemAllocator* self){
assert(!self->old_blocks.len || !self->old_buff_resize_record.len);
for (size_t blind = 0; blind < self->old_blocks.len; blind++) {
MargaretMemAllocator__clean_handlers_in_block(self, &self->old_blocks.buf[blind]);
}
VecMargaretMemAllocatorOneBlock_sink(&self->old_blocks, 0);
for (U64 ri = 0; ri < self->old_buff_resize_record.len; ri++) {
const MargaretOldBufferResizeRecord* resize = &self->old_buff_resize_record.buf[ri];
if (resize->old_mem_block_id != resize->new_mem_block_id || resize->old_start != resize->new_start) {
MargaretMemAllocator__get_rid_of_sub_buffer(self, resize->old_mem_block_id, resize->old_start);
}
}
VecMargaretOldBufferResizeRecord_sink(&self->old_buff_resize_record, 0);
}
// todo: fix skill issues , lol
char* MargaretMemAllocator_get_host_visible_buffer_ptr(
const MargaretMemAllocator* self, const MargaretMemAllocatorSubBufferPosition* pos){
check((self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));