1
0
mirror of https://github.com/Yours3lf/rpi-vk-driver.git synced 2025-02-20 17:54:17 +01:00

rewrote CPA, added test for it

This commit is contained in:
Unknown 2020-03-07 11:13:08 +00:00
parent df62eadb89
commit 1092d59612
5 changed files with 177 additions and 70 deletions

View File

@ -48,59 +48,46 @@ void* consecutivePoolAllocate(ConsecutivePoolAllocator* pa, uint32_t numBlocks)
{
assert(pa->buf);
CPAdebugPrint(pa);
//CPAdebugPrint(pa);
if(!pa->nextFreeBlock)
uint32_t* ptr = pa->nextFreeBlock;
if(!ptr)
{
return 0; //no free blocks
}
void* ret = 0;
for(uint32_t* candidate = pa->nextFreeBlock; candidate; candidate = (uint32_t*)*candidate)
for(; ptr; ptr = *ptr)
{
uint32_t found = 1;
uint32_t* prevBlock = candidate;
uint32_t* blockAfterCandidate = (uint32_t*)*candidate;
//check if there are enough consecutive free blocks
for(uint32_t c = 0; c < numBlocks - 1; ++c)
char* nextBlock = (char*)ptr + pa->blockSize;
uint32_t* nextFree = *ptr;
for(uint32_t c = 1; c != numBlocks; ++c)
{
if(blockAfterCandidate - prevBlock != pa->blockSize)
if(nextBlock == nextFree)
{
//signal if not consecutive (ie. diff is greater than blocksize)
found = 0;
break;
}
prevBlock = blockAfterCandidate;
blockAfterCandidate = (uint32_t*)*blockAfterCandidate;
}
//numblocks consecutive blocks found
if(found)
{
ret = candidate;
if(pa->nextFreeBlock == candidate)
{
//candidate found immediately
pa->nextFreeBlock = blockAfterCandidate;
nextFree = *nextFree;
nextBlock += pa->blockSize;
}
else
{
//somewhere the linked list would point to candidate, we need to correct this
for(uint32_t* nextFreeBlockCandidate = pa->nextFreeBlock; nextFreeBlockCandidate; nextFreeBlockCandidate = (uint32_t*)*nextFreeBlockCandidate)
{
if((uint32_t*)*nextFreeBlockCandidate == candidate)
{
*nextFreeBlockCandidate = (uint32_t)blockAfterCandidate;
break;
}
}
found = 0;
break;
}
}
if(found)
{
//set the next free block to the one that the last block we allocated points to
pa->nextFreeBlock = *(uint32_t*)((char*)ptr + (numBlocks - 1) * pa->blockSize);
break;
}
}
//return a pointer pointing past the linked list ptr
return ret > 0 ? (char*)ret + 4 : ret;
//TODO debug stuff, not for release
memset(ptr, 0, numBlocks * pa->blockSize);
return ptr;
}
//free numBlocks consecutive memory
@ -108,66 +95,114 @@ void consecutivePoolFree(ConsecutivePoolAllocator* pa, void* p, uint32_t numBloc
{
assert(pa->buf);
assert(p);
assert(numBlocks);
p = (char*)p - 4;
//TODO debug stuff, not for release
memset(p, 0, numBlocks * pa->blockSize);
if((void*)pa->nextFreeBlock > p)
//if linked list of free entries is empty
if(!pa->nextFreeBlock)
{
//then restart linked list
pa->nextFreeBlock = p;
char* listPtr = pa->nextFreeBlock;
for(uint32_t c = 0; c < numBlocks - 1; ++c)
{
//set each allocated block to form a linked list
*(uint32_t*)((char*)p + c * pa->blockSize) = (uint32_t)((char*)p + (c + 1) * pa->blockSize);
*(uint32_t*)listPtr = listPtr + pa->blockSize;
listPtr += pa->blockSize;
}
//set last block to point to the next free
*(uint32_t*)((char*)p + (numBlocks - 1) * pa->blockSize) = (uint32_t)pa->nextFreeBlock;
//set next free to the newly freed block
pa->nextFreeBlock = p;
return;
}
//somewhere the linked list may point after the free block (or null), we need to correct this
for(uint32_t* nextFreeBlockCandidate = pa->nextFreeBlock; nextFreeBlockCandidate; nextFreeBlockCandidate = (uint32_t*)*nextFreeBlockCandidate)
//end list
*(uint32_t*)listPtr = 0;
}
else
{
if((void*)*nextFreeBlockCandidate > p || !*nextFreeBlockCandidate)
//if list is not empty, try to form consecutive parts
//search free list to see if the freed element fits anywhere
uint32_t found = 0;
for(uint32_t* listPtr = pa->nextFreeBlock; listPtr; listPtr = *listPtr)
{
//if the freed block fits in the list somewhere
if(((char*)listPtr + pa->blockSize) == p)
{
//add it into the list
uint32_t* tmp = *listPtr;
*listPtr = p;
//reconstruct linked list within the freed element
char* ptr = *listPtr;
for(uint32_t c = 0; c < numBlocks - 1; ++c)
{
*(uint32_t*)ptr = ptr + pa->blockSize;
ptr += pa->blockSize;
}
//set the last element to point to the one after
*(uint32_t*)ptr = tmp;
found = 1;
}
}
if(!found)
{
//if it doesn't fit anywhere, just simply add it to the linked list
uint32_t* tmp = pa->nextFreeBlock;
pa->nextFreeBlock = p;
char* listPtr = pa->nextFreeBlock;
for(uint32_t c = 0; c < numBlocks - 1; ++c)
{
//set each allocated block to form a linked list
*(uint32_t*)((char*)p + c * pa->blockSize) = (uint32_t)((char*)p + (c + 1) * pa->blockSize);
*(uint32_t*)listPtr = listPtr + pa->blockSize;
listPtr += pa->blockSize;
}
//set last block to point to the next free
*(uint32_t*)((char*)p + (numBlocks - 1) * pa->blockSize) = *nextFreeBlockCandidate;
*nextFreeBlockCandidate = (uint32_t)p;
break;
//set the last element to point to the one after
*(uint32_t*)listPtr = tmp;
}
}
}
//if there's a block free after the current block, it just allocates one more block
//else it frees current block and allocates a new one
void* consecutivePoolReAllocate(ConsecutivePoolAllocator* pa, void* currentMem, uint32_t currNumBlocks)
{
fprintf(stderr, "CPA realloc\n");
currentMem = (char*)currentMem - 4;
uint32_t* nextCandidate = (char*)currentMem + pa->blockSize * currNumBlocks;
if(pa->nextFreeBlock == (uint32_t*)((char*)currentMem + currNumBlocks * pa->blockSize))
uint32_t* prevPtr = 0;
for(uint32_t* listPtr = pa->nextFreeBlock; listPtr; listPtr = *listPtr)
{
//we have one more block after current one, so just expand current
pa->nextFreeBlock = (uint32_t*)*pa->nextFreeBlock;
return currentMem;
if(listPtr == nextCandidate)
{
//if the free list contains an element that points right after our currentMem
//we can just use that one
*prevPtr = *listPtr;
//TODO debug stuff, not for release
memset(nextCandidate, 0, pa->blockSize);
return currentMem;
}
prevPtr = listPtr;
}
else
{
void* ret = consecutivePoolAllocate(pa, currNumBlocks + 1);
char* newContents = ret;
char* oldContents = currentMem;
newContents += 4;
oldContents += 4;
memcpy(newContents, oldContents, currNumBlocks * pa->blockSize - 4);
//try to allocate one more block
void* newMem = consecutivePoolAllocate(pa, currNumBlocks + 1);
if(!newMem)
{
return 0;
}
//copy over old content
memcpy(newMem, currentMem, currNumBlocks * pa->blockSize);
//free current element
consecutivePoolFree(pa, currentMem, currNumBlocks);
return newContents;
return newMem;
}
}

View File

@ -52,6 +52,9 @@ VKAPI_ATTR VkResult VKAPI_CALL rpi_vkCreateCommandPool(
int numCommandBufs = 128;
int consecutiveBlockSize = ARM_PAGE_SIZE>>2;
int consecutiveBlockNumber = 64;
//int numCommandBufs = 30;
//int consecutiveBlockSize = getCPABlockSize(256);
//int consecutiveBlockNumber = 30;
int consecutivePoolSize = consecutiveBlockNumber * consecutiveBlockSize;
static int counter = 0;

View File

@ -12,3 +12,4 @@ add_subdirectory(HDR)
add_subdirectory(ETC)
add_subdirectory(query)
add_subdirectory(mipmapping)
add_subdirectory(CPAtest)

View File

@ -0,0 +1,9 @@
file(GLOB testSrc
"*.h"
"*.cpp"
)
add_executable(CPAtest ${testSrc})
target_compile_options(CPAtest PRIVATE -Wall -std=c++11)
target_link_libraries(CPAtest rpi-vk-driver)

59
test/CPAtest/CPAtest.cpp Normal file
View File

@ -0,0 +1,59 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include "driver/CustomAssert.h"
#include "driver/ConsecutivePoolAllocator.h"
#include <vulkan/vulkan.h>
#include "driver/vkExt.h"
void simpleTest()
{
uint32_t blocksize = 16;
uint32_t numblocks = 8;
uint32_t size = numblocks * blocksize;
ConsecutivePoolAllocator cpa = createConsecutivePoolAllocator((char*)malloc(size), blocksize, size);
CPAdebugPrint(&cpa);
void* mem1 = consecutivePoolAllocate(&cpa, 1);
CPAdebugPrint(&cpa);
void* mem2 = consecutivePoolAllocate(&cpa, 2);
CPAdebugPrint(&cpa);
void* mem3 = consecutivePoolAllocate(&cpa, 3);
CPAdebugPrint(&cpa);
void* mem11 = consecutivePoolAllocate(&cpa, 1);
CPAdebugPrint(&cpa);
void* mem111 = consecutivePoolAllocate(&cpa, 1);
CPAdebugPrint(&cpa);
void* mem0 = consecutivePoolAllocate(&cpa, 1);
fprintf(stderr, "\n%p\n", mem0);
consecutivePoolFree(&cpa, mem11, 1);
CPAdebugPrint(&cpa);
consecutivePoolFree(&cpa, mem111, 1);
CPAdebugPrint(&cpa);
consecutivePoolFree(&cpa, mem2, 2);
CPAdebugPrint(&cpa);
consecutivePoolFree(&cpa, mem3, 3);
CPAdebugPrint(&cpa);
consecutivePoolFree(&cpa, mem1, 1);
CPAdebugPrint(&cpa);
}
int main() {
simpleTest();
return 0;
}