From 107bd90827efebbaadbcd2eb0730a141031101db Mon Sep 17 00:00:00 2001 From: Unknown <0.tamas.marton@gmail.com> Date: Fri, 11 May 2018 20:59:22 +0100 Subject: [PATCH] added linear allocator, command pool and buffer allocation done --- driver/LinearAllocator.h | 54 ++++++++++++++++++++ driver/PoolAllocator.h | 1 + driver/driver.c | 104 ++++++++++++++++++++++++++++++++++----- 3 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 driver/LinearAllocator.h diff --git a/driver/LinearAllocator.h b/driver/LinearAllocator.h new file mode 100644 index 0000000..691a607 --- /dev/null +++ b/driver/LinearAllocator.h @@ -0,0 +1,54 @@ +#pragma once + +#include "CustomAssert.h" + +#include + +typedef struct LinearAllocator +{ + char* buf; //preallocated buffer + unsigned offset; + unsigned size; +} LinearAllocator; + +LinearAllocator createLinearAllocator(char* b, unsigned s) +{ + assert(b); + assert(s > 0); + + LinearAllocator la = + { + .buf = b, + .offset = 0, + .size = s + }; +} + +void destroyLinearAllocator(LinearAllocator* la) +{ + la->buf = 0; + la->offset = 0; + la->size = 0; +} + +void* linearAllocte(LinearAllocator* la, unsigned s) +{ + assert(la->buf); + assert(la->size > 0); + + if(la->offset + s >= la->size) + { + return 0; //no space left + } + + char* p = la->buf + la->offset + s; + la->offset += s; + + return p; +} + +void linearFree(LinearAllocator* la, void* p) +{ + assert(0); //this shouldn't really happen, just destroy/reset the whole allocator +} + diff --git a/driver/PoolAllocator.h b/driver/PoolAllocator.h index a901e14..9bc28d3 100644 --- a/driver/PoolAllocator.h +++ b/driver/PoolAllocator.h @@ -17,6 +17,7 @@ PoolAllocator createPoolAllocator(char* b, unsigned bs, unsigned s) assert(b); //only allocated memory assert(bs >= sizeof(void*)); //we need to be able to store assert(s%bs==0); //we want a size that is the exact multiple of block size + assert(s > bs); //at least 1 element PoolAllocator pa = { diff --git a/driver/driver.c b/driver/driver.c index 89ea1df..289bccf 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -18,7 +18,11 @@ #include "modeset.h" +#include "AlignedAllocator.h" #include "PoolAllocator.h" +#include "LinearAllocator.h" + +#include "drm/vc4_drm.h" #ifndef min #define min(a, b) (a < b ? a : b) @@ -72,9 +76,16 @@ typedef struct VkQueue_T typedef struct VkCommandBuffer_T { - int dummy; + drm_vc4_submit_cl cls[100]; //each cl is a draw call } _commandBuffer; +typedef struct VkCommandPool_T +{ + int usePoolAllocator; + PoolAllocator pa; + LinearAllocator la; +} _commandPool; + VkQueueFamilyProperties _queueFamilyProperties[] = { { @@ -566,7 +577,35 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( //TODO: allocator is ignored for now assert(pAllocator == 0); - *pCommandPool = 0; //TODO implement pool memory allocator + //VK_COMMAND_POOL_CREATE_TRANSIENT_BIT + //specifies that command buffers allocated from the pool will be short-lived, meaning that they will be reset or freed in a relatively short timeframe. + //This flag may be used by the implementation to control memory allocation behavior within the pool. + //--> definitely use pool allocator + + //VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + //allows any command buffer allocated from a pool to be individually reset to the initial state; either by calling vkResetCommandBuffer, or via the implicit reset when calling vkBeginCommandBuffer. + //If this flag is not set on a pool, then vkResetCommandBuffer must not be called for any command buffer allocated from that pool. + + //TODO pool family ignored for now + + _commandPool* cp = malloc(sizeof(_commandPool)); + + //initial number of command buffers to hold + int numCommandBufs = 100; + + if(pCreateInfo->flags & VK_COMMAND_POOL_CREATE_TRANSIENT_BIT) + { + //use pool allocator + cp->usePoolAllocator = 1; + cp->pa = createPoolAllocator(malloc(numCommandBufs * sizeof(_commandBuffer)), sizeof(_commandBuffer), numCommandBufs * sizeof(_commandBuffer)); + } + else + { + cp->usePoolAllocator = 0; + cp->la = createLinearAllocator(malloc(numCommandBufs * sizeof(_commandBuffer)), numCommandBufs * sizeof(_commandBuffer)); + } + + *pCommandPool = (VkCommandPool)cp; return VK_SUCCESS; } @@ -587,21 +626,52 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( VkResult res = VK_SUCCESS; - for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) + _commandPool* cp = *(_commandPool*)pAllocateInfo->commandPool; + + if(cp->usePoolAllocator) { - pCommandBuffers[c] = malloc(sizeof(_commandBuffer)); - if(!pCommandBuffers[c]) + for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) { - res = VK_ERROR_OUT_OF_HOST_MEMORY; //TODO or VK_ERROR_OUT_OF_DEVICE_MEMORY? + pCommandBuffers[c] = poolAllocte(&cp->pa); + + if(!pCommandBuffers[c]) + { + res = VK_ERROR_OUT_OF_HOST_MEMORY; //TODO or VK_ERROR_OUT_OF_DEVICE_MEMORY? + break; + } + } + } + else + { + for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) + { + pCommandBuffers[c] = linearAllocte(&cp->la, sizeof(_commandBuffer)); + + if(!pCommandBuffers[c]) + { + res = VK_ERROR_OUT_OF_HOST_MEMORY; //TODO or VK_ERROR_OUT_OF_DEVICE_MEMORY? + break; + } } } if(res != VK_SUCCESS) { - for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) + if(cp->usePoolAllocator) { - free(pCommandBuffers[c]); - pCommandBuffers[c] = 0; + for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) + { + poolFree(&cp->pa, pCommandBuffers[c]); + pCommandBuffers[c] = 0; + } + } + else + { + for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) + { + //we don't really free linear memory, just reset the whole command pool + pCommandBuffers[c] = 0; + } } } @@ -823,12 +893,24 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( const VkAllocationCallbacks* pAllocator) { assert(device); - //assert(commandPool); //TODO + assert(commandPool); //TODO: allocator is ignored for now assert(pAllocator == 0); - //TODO + _commandPool* cp = *(_commandPool*)commandPool; + + if(cp->usePoolAllocator) + { + free(cp->pa.buf); + destroyPoolAllocator(cp->pa); + } + else + { + free(cp->continuousMem); + } + + free(cp); } /*