1
0
mirror of https://github.com/Yours3lf/rpi-vk-driver.git synced 2025-01-19 11:52:16 +01:00

added linear allocator, command pool and buffer allocation done

This commit is contained in:
Unknown 2018-05-11 20:59:22 +01:00
parent 0f8f62e4da
commit 107bd90827
3 changed files with 148 additions and 11 deletions

54
driver/LinearAllocator.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
#include "CustomAssert.h"
#include <stdint.h>
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
}

View File

@ -17,6 +17,7 @@ PoolAllocator createPoolAllocator(char* b, unsigned bs, unsigned s)
assert(b); //only allocated memory assert(b); //only allocated memory
assert(bs >= sizeof(void*)); //we need to be able to store 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==0); //we want a size that is the exact multiple of block size
assert(s > bs); //at least 1 element
PoolAllocator pa = PoolAllocator pa =
{ {

View File

@ -18,7 +18,11 @@
#include "modeset.h" #include "modeset.h"
#include "AlignedAllocator.h"
#include "PoolAllocator.h" #include "PoolAllocator.h"
#include "LinearAllocator.h"
#include "drm/vc4_drm.h"
#ifndef min #ifndef min
#define min(a, b) (a < b ? a : b) #define min(a, b) (a < b ? a : b)
@ -72,9 +76,16 @@ typedef struct VkQueue_T
typedef struct VkCommandBuffer_T typedef struct VkCommandBuffer_T
{ {
int dummy; drm_vc4_submit_cl cls[100]; //each cl is a draw call
} _commandBuffer; } _commandBuffer;
typedef struct VkCommandPool_T
{
int usePoolAllocator;
PoolAllocator pa;
LinearAllocator la;
} _commandPool;
VkQueueFamilyProperties _queueFamilyProperties[] = VkQueueFamilyProperties _queueFamilyProperties[] =
{ {
{ {
@ -566,7 +577,35 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(
//TODO: allocator is ignored for now //TODO: allocator is ignored for now
assert(pAllocator == 0); 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; return VK_SUCCESS;
} }
@ -587,23 +626,54 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(
VkResult res = VK_SUCCESS; VkResult res = VK_SUCCESS;
_commandPool* cp = *(_commandPool*)pAllocateInfo->commandPool;
if(cp->usePoolAllocator)
{
for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c)
{ {
pCommandBuffers[c] = malloc(sizeof(_commandBuffer)); pCommandBuffers[c] = poolAllocte(&cp->pa);
if(!pCommandBuffers[c]) if(!pCommandBuffers[c])
{ {
res = VK_ERROR_OUT_OF_HOST_MEMORY; //TODO or VK_ERROR_OUT_OF_DEVICE_MEMORY? 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) if(res != VK_SUCCESS)
{
if(cp->usePoolAllocator)
{ {
for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c) for(int c = 0; c < pAllocateInfo->commandBufferCount; ++c)
{ {
free(pCommandBuffers[c]); poolFree(&cp->pa, pCommandBuffers[c]);
pCommandBuffers[c] = 0; 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;
}
}
}
return res; return res;
} }
@ -823,12 +893,24 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(
const VkAllocationCallbacks* pAllocator) const VkAllocationCallbacks* pAllocator)
{ {
assert(device); assert(device);
//assert(commandPool); //TODO assert(commandPool);
//TODO: allocator is ignored for now //TODO: allocator is ignored for now
assert(pAllocator == 0); assert(pAllocator == 0);
//TODO _commandPool* cp = *(_commandPool*)commandPool;
if(cp->usePoolAllocator)
{
free(cp->pa.buf);
destroyPoolAllocator(cp->pa);
}
else
{
free(cp->continuousMem);
}
free(cp);
} }
/* /*