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:
parent
df62eadb89
commit
1092d59612
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
9
test/CPAtest/CMakeLists.txt
Normal file
9
test/CPAtest/CMakeLists.txt
Normal 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
59
test/CPAtest/CPAtest.cpp
Normal 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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user