1
0
mirror of https://github.com/Yours3lf/rpi-vk-driver.git synced 2025-02-21 18:54:18 +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); assert(pa->buf);
CPAdebugPrint(pa); //CPAdebugPrint(pa);
if(!pa->nextFreeBlock) uint32_t* ptr = pa->nextFreeBlock;
if(!ptr)
{ {
return 0; //no free blocks return 0; //no free blocks
} }
void* ret = 0; for(; ptr; ptr = *ptr)
for(uint32_t* candidate = pa->nextFreeBlock; candidate; candidate = (uint32_t*)*candidate)
{ {
uint32_t found = 1; uint32_t found = 1;
uint32_t* prevBlock = candidate; char* nextBlock = (char*)ptr + pa->blockSize;
uint32_t* blockAfterCandidate = (uint32_t*)*candidate; uint32_t* nextFree = *ptr;
//check if there are enough consecutive free blocks for(uint32_t c = 1; c != numBlocks; ++c)
for(uint32_t c = 0; c < numBlocks - 1; ++c)
{ {
if(blockAfterCandidate - prevBlock != pa->blockSize) if(nextBlock == nextFree)
{ {
//signal if not consecutive (ie. diff is greater than blocksize) nextFree = *nextFree;
found = 0; nextBlock += pa->blockSize;
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;
} }
else else
{ {
//somewhere the linked list would point to candidate, we need to correct this found = 0;
for(uint32_t* nextFreeBlockCandidate = pa->nextFreeBlock; nextFreeBlockCandidate; nextFreeBlockCandidate = (uint32_t*)*nextFreeBlockCandidate) break;
{
if((uint32_t*)*nextFreeBlockCandidate == candidate)
{
*nextFreeBlockCandidate = (uint32_t)blockAfterCandidate;
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; break;
} }
} }
//return a pointer pointing past the linked list ptr //TODO debug stuff, not for release
return ret > 0 ? (char*)ret + 4 : ret; memset(ptr, 0, numBlocks * pa->blockSize);
return ptr;
} }
//free numBlocks consecutive memory //free numBlocks consecutive memory
@ -108,66 +95,114 @@ void consecutivePoolFree(ConsecutivePoolAllocator* pa, void* p, uint32_t numBloc
{ {
assert(pa->buf); assert(pa->buf);
assert(p); 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) for(uint32_t c = 0; c < numBlocks - 1; ++c)
{ {
//set each allocated block to form a linked list *(uint32_t*)listPtr = listPtr + pa->blockSize;
*(uint32_t*)((char*)p + c * pa->blockSize) = (uint32_t)((char*)p + (c + 1) * 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 //end list
for(uint32_t* nextFreeBlockCandidate = pa->nextFreeBlock; nextFreeBlockCandidate; nextFreeBlockCandidate = (uint32_t*)*nextFreeBlockCandidate) *(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) for(uint32_t c = 0; c < numBlocks - 1; ++c)
{ {
//set each allocated block to form a linked list *(uint32_t*)listPtr = listPtr + pa->blockSize;
*(uint32_t*)((char*)p + c * pa->blockSize) = (uint32_t)((char*)p + (c + 1) * 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; //set the last element to point to the one after
break; *(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) void* consecutivePoolReAllocate(ConsecutivePoolAllocator* pa, void* currentMem, uint32_t currNumBlocks)
{ {
fprintf(stderr, "CPA realloc\n"); 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 if(listPtr == nextCandidate)
pa->nextFreeBlock = (uint32_t*)*pa->nextFreeBlock; {
return currentMem; //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); //try to allocate one more block
char* newContents = ret; void* newMem = consecutivePoolAllocate(pa, currNumBlocks + 1);
char* oldContents = currentMem;
newContents += 4; if(!newMem)
oldContents += 4; {
memcpy(newContents, oldContents, currNumBlocks * pa->blockSize - 4); return 0;
}
//copy over old content
memcpy(newMem, currentMem, currNumBlocks * pa->blockSize);
//free current element
consecutivePoolFree(pa, currentMem, currNumBlocks); 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 numCommandBufs = 128;
int consecutiveBlockSize = ARM_PAGE_SIZE>>2; int consecutiveBlockSize = ARM_PAGE_SIZE>>2;
int consecutiveBlockNumber = 64; int consecutiveBlockNumber = 64;
//int numCommandBufs = 30;
//int consecutiveBlockSize = getCPABlockSize(256);
//int consecutiveBlockNumber = 30;
int consecutivePoolSize = consecutiveBlockNumber * consecutiveBlockSize; int consecutivePoolSize = consecutiveBlockNumber * consecutiveBlockSize;
static int counter = 0; static int counter = 0;

View File

@ -12,3 +12,4 @@ add_subdirectory(HDR)
add_subdirectory(ETC) add_subdirectory(ETC)
add_subdirectory(query) add_subdirectory(query)
add_subdirectory(mipmapping) 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;
}