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...
This commit is contained in:
parent
248b81f2ec
commit
2367ce1e9d
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user