diff options
Diffstat (limited to 'Rend/rend_vk_arena.c')
| -rw-r--r-- | Rend/rend_vk_arena.c | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/Rend/rend_vk_arena.c b/Rend/rend_vk_arena.c deleted file mode 100644 index b936be4..0000000 --- a/Rend/rend_vk_arena.c +++ /dev/null @@ -1,264 +0,0 @@ -#pragma once -#include "rend_internal.h" -#include "rend_vk_internal.h" -#include <vulkan/vulkan_core.h> - -/* arenas need to be subdivided into blocks - * just like pools because we must respect page size */ -typedef struct RendVkPage { - RendMemory memory; - size_t head; - int reserved; -} RendVkPage; - -typedef struct RendVkPagedArena { - RendVkPage *page_darr; - uint32_t capacity; - uint32_t elements; -} RendVkPagedArena; - -struct RendVkArenaAllocator { - VkAllocationCallbacks *allocator; - size_t *heap_idx_alloc_sizes; // allocation size per type of memory available on the gpu - RendVkPagedArena *mem_arenas; // memory arena per type of memory available on the gpu - VkDevice logical_device; // virtual device - VkPhysicalDevice physical_device; // physical device we are allocating memory from - VkDeviceSize gpu_alignment; // allocations must respect the physical limitations of the gpu - VkDeviceSize block_min_size; // minimum size per block of memory - uint64_t total_allocations; - uint32_t heap_index_count; - VkPhysicalDeviceMemoryProperties properties; // useful for getting properties per heap index -}; - -static RendVkArenaAllocator -rend_vk_arena_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator) -{ - RendVkArenaAllocator arena = { - .allocator = allocator, - .heap_idx_alloc_sizes = NULL, - .logical_device = logical_device, - .physical_device = physical_device, - .gpu_alignment = 0, - .block_min_size = 0, - .total_allocations = 0, - .heap_index_count = 0, - .mem_arenas = 0, - }; - - VkPhysicalDeviceMemoryProperties mem_properties; - vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties); - arena.properties = mem_properties; - - uint32_t count = mem_properties.memoryTypeCount; - arena.heap_index_count = count; - - arena.heap_idx_alloc_sizes = rmalloc(count * sizeof *arena.heap_idx_alloc_sizes); - memset(arena.heap_idx_alloc_sizes, 0, count * sizeof *arena.heap_idx_alloc_sizes); - - arena.mem_arenas = rmalloc(count * sizeof *arena.mem_arenas); - for (uint32_t u = 0; u < count; ++u) { - arena.mem_arenas[u].capacity = 2; - arena.mem_arenas[u].elements = 0; - arena.mem_arenas[u].page_darr = rmalloc(2 * sizeof *arena.mem_arenas[u].page_darr); - memset(arena.mem_arenas[u].page_darr, 0, 2 * sizeof *arena.mem_arenas[u].page_darr); - } - - VkDeviceSize alignment = device_limits.bufferImageGranularity; - if (device_limits.nonCoherentAtomSize > alignment) { - alignment = device_limits.nonCoherentAtomSize; - } - - arena.gpu_alignment = alignment; - arena.block_min_size = arena.gpu_alignment * 10; - - return arena; -} - -static uint32_t -rend_vk_arena_add_page(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index, bool fit_to_alloc) -{ - VkDeviceSize new_arena_size = fit_to_alloc ? size : (size * 2); - new_arena_size = (new_arena_size < arena->block_min_size) ? arena->block_min_size : new_arena_size; - - VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags; - - RendVkPage page = (RendVkPage) {0}; - page.head = 0; - - VkMemoryAllocateFlagsInfo flags_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, - .pNext = NULL, - .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, - .deviceMask = 0 - }; - - VkMemoryAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = new_arena_size, - .pNext = &flags_info, - .memoryTypeIndex = heap_index - }; - - page.memory = (RendMemory) {0}; - page.memory.offset = 0; - page.memory.size = new_arena_size; - - VkResult res = vkAllocateMemory(arena->logical_device, &alloc_info, arena->allocator, (VkDeviceMemory*) &page.memory.device_memory); - if (res != VK_SUCCESS) { - return UINT32_MAX; - } - - if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - vkMapMemory( - arena->logical_device, - (VkDeviceMemory) page.memory.device_memory, - 0, // Offset inside VkDeviceMemory!!!1 - new_arena_size, // MUST match alloc_info.allocationSize and NOT raw size!!! - 0, - &page.memory.host_mapped_memory - ); - } - - RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index]; - - if (mem_arena->elements + 1 >= mem_arena->capacity) { - uint32_t new_capacity = mem_arena->capacity * 2; - void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr); - if (!new_darr) { - vkFreeMemory(arena->logical_device, (VkDeviceMemory) page.memory.device_memory, arena->allocator); - return UINT32_MAX; - } - mem_arena->page_darr = new_darr; - mem_arena->capacity = new_capacity; - } - - uint32_t page_index = mem_arena->elements; - mem_arena->page_darr[mem_arena->elements++] = page; - - arena->total_allocations++; - - return page_index; -} - -static RendMemory -rend_vk_arena_alloc(RendVkArenaAllocator *arena, VkDeviceSize size, uint32_t heap_index) -{ - assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?"); - RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index]; - - VkMemoryPropertyFlags properties = arena->properties.memoryTypes[heap_index].propertyFlags; - - /* align to allocation to fit page size */ - VkDeviceSize align = arena->gpu_alignment; - VkDeviceSize aligned_size = (size + align - 1) & ~(align - 1); - - /* check if fits in previous blocks */ - int whole_page = !(properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - uint32_t page_idx = UINT32_MAX; - for (uint32_t u = 0; u < mem_arena->elements; ++u) { - RendVkPage page = mem_arena->page_darr[u]; - int valid = (whole_page) ? (page.head == 0) : 1; - if ((page.head + aligned_size <= page.memory.size) && valid) { - page_idx = u; - break; - } - } - - /* page not found, add new page */ - if (page_idx == UINT32_MAX) { - page_idx = rend_vk_arena_add_page(arena, aligned_size, heap_index, whole_page); - if (page_idx == UINT32_MAX) { - REND__CRASH("[REND_VK] Arena page allocation failed!"); - } - } - - mem_arena->page_darr[page_idx].reserved = whole_page; - - RendMemory memory = { - .device_memory = mem_arena->page_darr[page_idx].memory.device_memory, - .size = aligned_size, - .offset = mem_arena->page_darr[page_idx].head, - .host_mapped_memory = 0, - .heap_index = heap_index, - .id = page_idx, - }; - - if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - memory.host_mapped_memory = mem_arena->page_darr[page_idx].memory.host_mapped_memory + memory.offset; - } - - /* move head */ - arena->heap_idx_alloc_sizes[heap_index] += aligned_size; - mem_arena->page_darr[page_idx].head += aligned_size; - return memory; -} - - -static void -rend_vk_arena_clear(RendVkArenaAllocator *arena, uint32_t heap_index) -{ - assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?"); - RendVkPagedArena mem_arena = arena->mem_arenas[heap_index]; - if (mem_arena.page_darr) { - for (uint32_t u = 0; u < mem_arena.elements; ++u) { - mem_arena.page_darr[u].head = 0; - mem_arena.page_darr[u].reserved = 0; - } - } -} - -static void -rend_vk_arena_clear_all(RendVkArenaAllocator *arena) -{ - for (uint32_t u = 0; u < arena->properties.memoryTypeCount; ++u) { - rend_vk_arena_clear(arena, u); - } -} - -static void -rend_vk_arena_shrink(RendVkArenaAllocator *arena, uint32_t heap_index) -{ - assert(heap_index < 32 && "Unusual heap index. Did you pass the memory type instead?"); - RendVkPagedArena *mem_arena = &arena->mem_arenas[heap_index]; - if (mem_arena->capacity > 4) { - uint32_t new_capacity = mem_arena->capacity / 2; - void *new_darr = rrealloc(mem_arena->page_darr, new_capacity * sizeof *mem_arena->page_darr); - if (!new_darr) return; - mem_arena->page_darr = new_darr; - mem_arena->capacity = new_capacity; - } -} - -static void -rend_vk_arena_destroy(RendVkArenaAllocator *arena) -{ - if (arena->mem_arenas) { - for (size_t u = 0; u < arena->heap_index_count; ++u) { - RendVkPagedArena *mem_arena = &arena->mem_arenas[u]; - for (uint32_t p = 0; p < mem_arena->elements; ++p) { - - RendMemory memory = mem_arena->page_darr[p].memory ; - if (memory.offset == 0) { - if (memory.host_mapped_memory) { - vkUnmapMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory); - } - vkFreeMemory(arena->logical_device, (VkDeviceMemory) memory.device_memory, arena->allocator); - } else { - PWARN("[REND_VK] Attempted to free memory with an offset!"); - } - - } - if (mem_arena->page_darr) { - rfree(mem_arena->page_darr); - mem_arena->page_darr = 0; - } - } - rfree(arena->mem_arenas); - arena->mem_arenas = 0; - } - if (arena->heap_idx_alloc_sizes) { - rfree(arena->heap_idx_alloc_sizes); - arena->heap_idx_alloc_sizes = 0; - } - memset(arena, 0, sizeof *arena); -} |
