diff options
Diffstat (limited to 'unused code/rend_vk_pool.c')
| -rw-r--r-- | unused code/rend_vk_pool.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/unused code/rend_vk_pool.c b/unused code/rend_vk_pool.c new file mode 100644 index 0000000..e527354 --- /dev/null +++ b/unused code/rend_vk_pool.c @@ -0,0 +1,221 @@ +#pragma once +#include "rend_internal.h" +#include "rend_vk_internal.h" +#include <vulkan/vulkan_core.h> + +/* NOTE(vasco): + * Check out https://kylehalladay.com/blog/tutorial/2017/12/13/Custom-Allocators-Vulkan.html + * for a basic grasp on what it entails to actually write a memory allocator for vulkan. + * + * This allocator isnt anything particularly amazing but it works so I'm keeping this code. + * Based on the framework presented here we could implement other more efficient allocators. + * Which is what I did for the arena allocator. + */ + +#if 0 +typedef struct RendVkAddress { + VkDeviceMemory handle; + uint32_t type; + uint32_t id; + VkDeviceSize size; + VkDeviceSize offset; +} RendVkAddress; + +typedef struct RendVkPoolLayout { + uint64_t offset, size; +} RendVkPoolLayout; + +typedef struct RendVKPoolBlock { + RendVkAddress address; + RendVkPoolLayout *layout_darr; + uint8_t reserved; +} RendVKPoolBlock; + +typedef struct RendVkPoolMemory { + RendVKPoolBlock *block_darr; +} RendVkPoolMemory; + +struct RendVkPoolAllocator { + VkAllocationCallbacks *allocator; + size_t *mem_type_alloc_sizes; // allocation size per type of memory available on the gpu + RendVkPoolMemory *mem_pools; // memory pools per type of memory available on the gpu + VkDevice logical_device; // virtual device + VkPhysicalDevice physical_device; // physical device we are allocating memory from + VkDeviceSize page_size; // 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 memory_type_count; +}; + +static RendVkPoolAllocator +rend_vk_pool_create(VkDevice logical_device, VkPhysicalDevice physical_device, VkPhysicalDeviceLimits device_limits, VkAllocationCallbacks *allocator) +{ + RendVkPoolAllocator pool = { + .allocator = allocator, + .mem_type_alloc_sizes = NULL, + .mem_pools = NULL, + .logical_device = logical_device, + .physical_device = physical_device, + .page_size = 0, + .block_min_size = 0, + .total_allocations = 0, + .memory_type_count = 0, + }; + + VkPhysicalDeviceMemoryProperties mem_properties; + vkGetPhysicalDeviceMemoryProperties(physical_device, &mem_properties); + + pool.mem_type_alloc_sizes = malloc(mem_properties.memoryTypeCount * sizeof *pool.mem_type_alloc_sizes); + memset(pool.mem_type_alloc_sizes, 0, mem_properties.memoryTypeCount * sizeof *pool.mem_type_alloc_sizes); + + pool.mem_pools = malloc(mem_properties.memoryTypeCount * sizeof *pool.mem_pools); + memset(pool.mem_pools, 0, mem_properties.memoryTypeCount * sizeof *pool.mem_pools); + + pool.memory_type_count = mem_properties.memoryTypeCount; + pool.page_size = device_limits.bufferImageGranularity; + pool.block_min_size = pool.page_size * 10; + + return pool; +} + +static uint32_t +rend_vk_pool_add_block(RendVkPoolAllocator *pool, VkDeviceSize size, uint32_t memory_type, VkMemoryPropertyFlags properties, bool fit_to_alloc) +{ + VkDeviceSize new_pool_size = size * 2; + new_pool_size = (new_pool_size < pool->block_min_size) ? pool->block_min_size : new_pool_size; + + VkMemoryAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = new_pool_size, + .memoryTypeIndex = rend_vk_memory_find_index(pool->physical_device, memory_type, properties) + }; + + RendVKPoolBlock block = {0}; + VkResult res = vkAllocateMemory(pool->logical_device, &alloc_info, pool->allocator, &block.address.handle); + block.address.type = memory_type; + block.address.size = new_pool_size; + + RendVkPoolMemory *mem_pool = &pool->mem_pools[memory_type]; + p_darray_push(mem_pool->block_darr, block); + + RendVkPoolLayout layout = { + .offset = 0, + .size = new_pool_size + }; + p_darray_push(mem_pool->block_darr[pool_size - 1].layout_darr, layout); + + pool->total_allocations++; + + size_t pool_size = p_darray_len(mem_pool->block_darr); + return pool_size - 1; +} + +static RendVkMemory +rend_vk_pool_alloc(RendVkPoolAllocator *pool, VkDeviceSize size, uint32_t usage, uint32_t memory_type, VkMemoryPropertyFlags properties) +{ + RendVkPoolMemory *mem_pool = &pool->mem_pools[memory_type]; + + VkDeviceSize requested_alloc_size = ((size / pool->page_size) + 1) * pool->page_size; + pool->mem_type_alloc_sizes[memory_type] += requested_alloc_size; + + /* find free chunk for allocation + * TODO: free list? + */ + int whole_page = usage != VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + uint64_t block_idx = UINT64_MAX; + uint64_t span_idx = UINT64_MAX; + for (uint32_t i = 0; i < p_darray_len(mem_pool->block_darr); ++i) { + for (uint32_t j = 0; j < p_darray_len(mem_pool->block_darr[i].layout_darr); ++j) { + int valid = (whole_page) ? mem_pool->block_darr[i].layout_darr[j].offset == 0 : 1; + if (mem_pool->block_darr[i].layout_darr[j].size >= size && valid) { + block_idx = i; + span_idx = j; + } + } + } + + if (block_idx == UINT64_MAX || span_idx == UINT64_MAX) { + block_idx = rend_vk_pool_add_block(pool, size, memory_type, properites, whole_page); + span_idx = 0; + } + + mem_pool->block_darr[block_idx].reserved = whole_page; + + RendVkMemory memory = { + .device_memory = mem_pool->block_darr[block_idx].address.handle, + .size = size, + .offset = mem_pool->block_darr[block_idx].layout_darr[span_idx].offset, + .type = memory_type, + + .logical_device = pool->logical_device, + .allocator = pool->allocator, + .host_mapped_memory = 0, + .physical_device = pool->physical_device, + .properties = properties, + + .id = block_idx, + }; + + /* mark chunck */ + mem_pool->block_darr[block_idx].layout_darr[span_idx].offset += size; + mem_pool->block_darr[block_idx].layout_darr[span_idx].size -= size; + return memory; +} + + +static void +rend_vk_pool_free(RendVkPoolAllocator *pool, RendVkMemory *memory) +{ + VkDeviceSize requested = ((memory->size / pool->page_size) + 1) * pool->page_size; + + RendVkPoolMemory *mem_pool = &pool->mem_pools[memory->type]; + + pool->blocks_[allocation.id].pageReserved = false; + + mem_pool->block_darr[block_idx].layout_darr[span_idx].offset += size; + mem_pool->block_darr[block_idx].layout_darr[span_idx].size -= size; + + OffsetSize span = {allocation.offset, requestedAllocSize }; + bool found = false; + + uint32_t numLayoutMems = pool.blocks[allocation.id].layout.size(); + for (uint32_t j = 0; j < numLayoutMems; ++j) + { + if (pool.blocks[allocation.id].layout[j].offset == requestedAllocSize +allocation.offset) + { + pool.blocks[allocation.id].layout[j].offset = allocation.offset; + pool.blocks[allocation.id].layout[j].size += requestedAllocSize; + found = true; + break; + } + } + + if (!found) + { + state.memPools[allocation.type].blocks[allocation.id].layout.push_back(span); + state.memTypeAllocSizes[allocation.type] -= requestedAllocSize; + } +} + +static void +rend_vk_pool_destroy(RendVkPoolAllocator *pool) +{ + if (pool->mem_pools) { + for (size_t u = 0; u < pool->memory_type_count; ++u) { + RendVkPoolMemory mem_pool = pool->mem_pools[u]; + for (size_t b = 0; b < p_darray_len(mem_pool.block_darr); ++b) { + RendVKPoolBlock block = mem_pool.block_darr[b]; + p_darray_destroy(block.layout_darr); + } + p_darray_destroy(mem_pool.block_darr); + } + free(pool->mem_pools); + pool->mem_pools = 0; + } + if (pool->mem_type_alloc_sizes) { + free(pool->mem_type_alloc_sizes); + pool->mem_type_alloc_sizes = 0; + } + memset(pool, 0, sizeof *pool); +} +#endif |
