|
|
|
|
@ -174,6 +174,95 @@
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
@ -192,15 +281,25 @@ 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;
|
|
|
|
|
@ -210,15 +309,38 @@ typedef struct {
|
|
|
|
|
VkImageUsageFlags usage_flags;
|
|
|
|
|
bool preserve_at_quiet;
|
|
|
|
|
VkImage image;
|
|
|
|
|
MargaretMemAllocatorOccupantPosition* ans;
|
|
|
|
|
MargaretMemAllocatorImagePosition* ans;
|
|
|
|
|
} MargaretMemoryOccupationImage;
|
|
|
|
|
|
|
|
|
|
/* primitive */
|
|
|
|
|
|
|
|
|
|
/* Stored in MargaretMemoryOccupation::buf */
|
|
|
|
|
typedef struct {
|
|
|
|
|
VkBufferUsageFlags usage_flags;
|
|
|
|
|
bool preserve_at_quiet;
|
|
|
|
|
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;
|
|
|
|
|
VkBuffer buffer;
|
|
|
|
|
U64 capacity; /* Needed only for debugging purposes */
|
|
|
|
|
U64 capacity;
|
|
|
|
|
BuffRBTree_MapU64ToMargaretBufferOccupationSubBuffer subbuffers;
|
|
|
|
|
} MargaretMemoryOccupationBuffer;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
@ -228,7 +350,6 @@ typedef enum {
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
U64 taken_size;
|
|
|
|
|
MargaretMemAllocatorOccupantPosition* ans;
|
|
|
|
|
MargaretMemoryOccupation_variant variant;
|
|
|
|
|
union {
|
|
|
|
|
MargaretMemoryOccupationImage img;
|
|
|
|
|
@ -236,11 +357,29 @@ typedef struct {
|
|
|
|
|
};
|
|
|
|
|
} MargaretMemoryOccupation;
|
|
|
|
|
|
|
|
|
|
#include "../../../gen/l1_5/eve/margaret/RBTree_MapU64ToMargaretMemoryOccupation.h"
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
|
/* Not primitive */
|
|
|
|
|
typedef struct {
|
|
|
|
|
RBTree_MapU64ToMargaretMemoryOccupation occupied_memory;
|
|
|
|
|
BuffRBTree_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;
|
|
|
|
|
@ -248,58 +387,14 @@ typedef struct {
|
|
|
|
|
void* mapped_memory;
|
|
|
|
|
} MargaretMemAllocatorOneBlock;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MargaretMemAllocatorOneBlock_drop(MargaretMemAllocatorOneBlock self){
|
|
|
|
|
RBTree_MapU64ToMargaretMemoryOccupation_drop(self.occupied_memory);
|
|
|
|
|
BuffRBTree_MapU64ToMargaretMemoryOccupation_drop(self.occupied_memory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "../../../gen/l1/eve/margaret/VecMargaretMemAllocatorOneBlock.h"
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/* Used to enumerate both free memory segments in VkDeviceMemory
|
|
|
|
|
* and free memory in buffers of some kind */
|
|
|
|
|
typedef struct {
|
|
|
|
|
U64 start;
|
|
|
|
|
U64 len;
|
|
|
|
|
@ -334,35 +429,37 @@ bool MargaretFreeMemSegment_less_resp_align(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "../../../gen/l1/eve/margaret/VecMargaretFreeMemSegment.h"
|
|
|
|
|
#include "../../../gen/l1/eve/margaret/OptionMargaretFreeMemSegment.h"
|
|
|
|
|
#include "../../../gen/l1_5/eve/margaret/BufRBTreeByLen_SetMargaretFreeMemSegment.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"
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
|
#include "../../../gen/l1/VecAndSpan_U8.h"
|
|
|
|
|
|
|
|
|
|
@ -384,14 +481,14 @@ MargaretMemFreeSpaceManager MargaretMemFreeSpaceManager_new(){
|
|
|
|
|
|
|
|
|
|
void MargaretMemFreeSpaceManager_drop(MargaretMemFreeSpaceManager self){
|
|
|
|
|
for (U8 alignment_exp = 0; alignment_exp < MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP; alignment_exp++)
|
|
|
|
|
OptionBufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_drop(self.free_space_in_memory[alignment_exp]);
|
|
|
|
|
OptionBuffRBTreeByLenRespAlign_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)
|
|
|
|
|
BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_sink(&self->free_space_in_memory[ae].some);
|
|
|
|
|
BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_sink(&self->free_space_in_memory[ae].some);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MargaretMemFreeSpaceManager_erase(MargaretMemFreeSpaceManager* man, U64 start, U64 len, U32 dev_mem_block){
|
|
|
|
|
@ -402,7 +499,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 = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_erase(&
|
|
|
|
|
bool eret = BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_erase(&
|
|
|
|
|
man->free_space_in_memory[alignment].some, &(MargaretFreeMemSegment){start, len, dev_mem_block});
|
|
|
|
|
assert(eret);
|
|
|
|
|
}
|
|
|
|
|
@ -415,7 +512,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 = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&
|
|
|
|
|
bool iret = BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&
|
|
|
|
|
man->free_space_in_memory[alignment].some, (MargaretFreeMemSegment){start, len, dev_mem_block});
|
|
|
|
|
assert(iret);
|
|
|
|
|
}
|
|
|
|
|
@ -426,25 +523,57 @@ 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);
|
|
|
|
|
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));
|
|
|
|
|
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));
|
|
|
|
|
for (size_t i = 0; i < have->el.len; i++) {
|
|
|
|
|
BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_insert(&man->free_space_in_memory[alignment_exp].some,
|
|
|
|
|
// MargaretFreeMemSegment
|
|
|
|
|
BuffRBTreeByLenRespAlign_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 = BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_find_min_grtr_or_eq(&man->free_space_in_memory[alignment_exp].some,
|
|
|
|
|
U64 sit = BuffRBTreeByLenRespAlign_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(*BufRBTreeByLenRespAlign_SetMargaretFreeMemSegment_at_iter(
|
|
|
|
|
return Some_MargaretFreeMemSegment(*BuffRBTreeByLenRespAlign_SetMargaretFreeMemSegment_at_iter(
|
|
|
|
|
&man->free_space_in_memory[alignment_exp].some, sit));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* VkDevice and VkPhysicalDevice stay remembered here. Don't forget that, please */
|
|
|
|
|
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 {
|
|
|
|
|
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
|
|
|
|
|
@ -454,22 +583,28 @@ typedef struct {
|
|
|
|
|
* 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, VkMemoryPropertyFlags mem_properties, U8 memory_type_id
|
|
|
|
|
VkDevice device, VkPhysicalDevice physical_device, SpanMargaretBufferKindDescription buffer_types,
|
|
|
|
|
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,
|
|
|
|
|
@ -477,53 +612,69 @@ 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){
|
|
|
|
|
// MargaretMemFreeSpaceManager_sink(&self->mem_free_space);
|
|
|
|
|
// }
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U64Segment MargaretMemAllocatorOneBlock_get_left_free_space(
|
|
|
|
|
const MargaretMemAllocatorOneBlock* self, RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it){
|
|
|
|
|
U64 occ_start = occ_it->key;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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)};
|
|
|
|
|
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)};
|
|
|
|
|
}
|
|
|
|
|
return (U64Segment){.start = 0, .len = occ_start};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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)};
|
|
|
|
|
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)};
|
|
|
|
|
}
|
|
|
|
|
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, RBTreeNode_KVPU64ToMargaretMemoryOccupation* occ_it){
|
|
|
|
|
MargaretMemAllocator* self, U32 mem_block_id, U64 occ_it){
|
|
|
|
|
MargaretMemAllocatorOneBlock* block = VecMargaretMemAllocatorOneBlock_mat(&self->blocks, mem_block_id);
|
|
|
|
|
|
|
|
|
|
const MargaretMemoryOccupation* occ = &occ_it->value;
|
|
|
|
|
U64 occ_start;
|
|
|
|
|
const MargaretMemoryOccupation* occ;
|
|
|
|
|
BuffRBTree_MapU64ToMargaretMemoryOccupation_at_iter(&block->occupied_memory, occ_it, &occ_start, &occ);
|
|
|
|
|
|
|
|
|
|
/* Updating block usage counter TODO: do it everywhere */
|
|
|
|
|
/* Updating block usage counter */
|
|
|
|
|
block->occupation_counter -= occ->taken_size;
|
|
|
|
|
|
|
|
|
|
U64Segment left_free_space = MargaretMemAllocatorOneBlock_get_left_free_space(block, occ_it);
|
|
|
|
|
@ -535,7 +686,10 @@ void MargaretMemAllocator__get_rid_of_memory_occupant(
|
|
|
|
|
vkDestroyImage(self->device, occ->img.image, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RBTree_MapU64ToMargaretMemoryOccupation_erase_by_iter(&block->occupied_memory, occ_it);
|
|
|
|
|
/* 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 */
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
@ -544,21 +698,107 @@ 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 (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);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vkFreeMemory(self->device, block->mem_hand, NULL);
|
|
|
|
|
@ -573,27 +813,14 @@ void MargaretMemAllocator_drop(MargaretMemAllocator self){
|
|
|
|
|
}
|
|
|
|
|
VecMargaretMemAllocatorOneBlock_drop(self.old_blocks);
|
|
|
|
|
VecMargaretMemAllocatorOneBlock_drop(self.blocks);
|
|
|
|
|
// VecMargaretOldBufferResizeRecord_drop(self.old_buff_resize_record);
|
|
|
|
|
VecMargaretOldBufferResizeRecord_drop(self.old_buff_resize_record);
|
|
|
|
|
VecMargaretBufferKindInfo_drop(self.buffer_types);
|
|
|
|
|
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, MargaretMemAllocatorRequests* requests
|
|
|
|
|
MargaretMemAllocator* self, VkCommandBuffer cmd_buff, MargaretMemAllocatorRequest* request
|
|
|
|
|
){
|
|
|
|
|
MargaretMemAllocator_wipe_old(self);
|
|
|
|
|
assert(request->expand_alloc_buffer.len == self->buffer_types.len);
|
|
|
|
|
@ -785,7 +1012,21 @@ MargaretMemAllocatorDemands MargaretMemAllocator_carry_out_request(
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// todo: fix skill issues , lol
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* MargaretMemAllocator_get_host_visible_buffer_ptr(
|
|
|
|
|
const MargaretMemAllocator* self, const MargaretMemAllocatorSubBufferPosition* pos){
|
|
|
|
|
check((self->mem_properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
|
|
|
|
|
|