Assignable VRAM bank allocations

This change integrates being able to allocate to a specific VRAM bank
into the existing implementation.
This commit is contained in:
DiscostewSM 2017-02-06 11:52:57 -08:00
parent e06c8e542f
commit eb9a98bcf9
2 changed files with 109 additions and 17 deletions

View File

@ -4,6 +4,21 @@
*/ */
#pragma once #pragma once
typedef enum
{
VRAM_A = 0x00;
VRAM_B = 0x01;
VRAM_AB = 0x02;
} VRAM_ALLOCATOR;
/**
* @brief Allocates a 0x80-byte aligned buffer to a specific VRAM bank.
* @param bank The bank to which the buffer will reside.
* @param size Size of the buffer to allocate.
* @return The allocated buffer.
*/
void* vramBankAlloc(VRAM_ALLOCATOR bank, size_t size);
/** /**
* @brief Allocates a 0x80-byte aligned buffer. * @brief Allocates a 0x80-byte aligned buffer.
* @param size Size of the buffer to allocate. * @param size Size of the buffer to allocate.
@ -11,6 +26,15 @@
*/ */
void* vramAlloc(size_t size); void* vramAlloc(size_t size);
/**
* @brief Allocates a buffer aligned to the given size in a specific bank.
* @param bank The bank to which the buffer will reside
* @param size Size of the buffer to allocate.
* @param alignment Alignment to use.
* @return The allocated buffer.
*/
void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment);
/** /**
* @brief Allocates a buffer aligned to the given size. * @brief Allocates a buffer aligned to the given size.
* @param size Size of the buffer to allocate. * @param size Size of the buffer to allocate.
@ -35,7 +59,13 @@ void* vramRealloc(void* mem, size_t size);
void vramFree(void* mem); void vramFree(void* mem);
/** /**
* @brief Gets the current VRAM free space. * @brief Gets the current VRAM bank free space.
* @return The current VRAM free space. * @return The current VRAM bank free space.
*/ */
u32 vramSpaceFree(void); u32 vramBankSpaceFree(VRAM_ALLOCATOR bank);
/**
* @brief Gets the current overall VRAM free space.
* @return The current overall VRAM free space.
*/
u32 vramSpaceFree(void);

View File

@ -8,21 +8,28 @@ extern "C"
#include "mem_pool.h" #include "mem_pool.h"
#include "addrmap.h" #include "addrmap.h"
static MemPool sVramPool; static MemPool sVramPoolA;
static MemPool sVramPoolB;
static bool vramInit() static bool vramInit()
{ {
auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000); auto blkA = MemBlock::Create((u8*)0x1F000000, 0x00300000);
if (blk) if (blkA)
{ {
sVramPool.AddBlock(blk); auto blkB = MemBlock::Create((u8*)0x1F300000, 0x00300000);
rbtree_init(&sAddrMap, addrMapNodeComparator); if(blkB)
return true; {
sVramPoolA.AddBlock(blkA);
sVramPoolB.Addblock(blkB);
rbtree_init(&sAddrMap, addrMapNodeComparator);
return true;
}
free(blkA);
} }
return false; return false;
} }
void* vramMemAlign(size_t size, size_t alignment) void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment)
{ {
// Enforce minimum alignment // Enforce minimum alignment
if (alignment < 16) if (alignment < 16)
@ -39,27 +46,65 @@ void* vramMemAlign(size_t size, size_t alignment)
return nullptr; return nullptr;
// Initialize the pool if it is not ready // Initialize the pool if it is not ready
if (!sVramPool.Ready() && !vramInit()) if (!sVramPoolA.Ready() && !sVramPoolB.Ready() && !vramInit())
return nullptr; return nullptr;
// Allocate the chunk // Allocate the chunk
MemChunk chunk; MemChunk chunk;
if (!sVramPool.Allocate(chunk, size, shift)) int bankSet;
return nullptr; if(bank != VRAM_B)
{
// Attempt Bank A (for both cases)
if(!sVramPoolA.Allocate(chunk, size, shift))
{
if(bank == VRAM_A)
return nullptr;
else
{
// Attempt Bank B
if(!sVramPoolB.Allocate(chunk, size, shift))
return nullptr;
bankSet = 1;
}
}
else
bankset = 0;
}
else
{
// Attempt Bank B only
if(!sVramPoolB.Allocate(chunk, size, shift))
return nullptr;
bankSet = 1;
}
auto node = newNode(chunk); auto node = newNode(chunk);
if (!node) if (!node)
{ {
sVramPool.Deallocate(chunk); if(bankSet)
sVramPoolB.Deallocate(chunk);
else
sVramPoolA.Deallocate(chunk);
return nullptr; return nullptr;
} }
if (rbtree_insert(&sAddrMap, &node->node)); if (rbtree_insert(&sAddrMap, &node->node));
return chunk.addr; return chunk.addr;
} }
void* vramMemAlign(size_t size, size_t alignment)
{
return vramBankMemAlign(VRMA_AB, size, alignment);
}
void* vramBankAlloc(VRAM_ALLOCATOR bank, size_t size)
{
return vramBankMemAlign(bank, size, 0x80);
}
void* vramAlloc(size_t size) void* vramAlloc(size_t size)
{ {
return vramMemAlign(size, 0x80); return vramBankMemAlign(VRAM_AB, size, 0x80);
} }
void* vramRealloc(void* mem, size_t size) void* vramRealloc(void* mem, size_t size)
@ -74,13 +119,30 @@ void vramFree(void* mem)
if (!node) return; if (!node) return;
// Free the chunk // Free the chunk
sVramPool.Deallocate(node->chunk); if((u32)mem < 0x1F300000)
sVramPoolA.Deallocate(node->chunk);
else
sVramPoolB.Deallocate(node->chunk);
// Free the node // Free the node
delNode(node); delNode(node);
} }
u32 vramBankSpaceFree(VRAM_ALLOCATOR bank);
{
if(bank != VRAM_B)
{
u32 space = sVramPoolA.GetFreeSpace();
if(bank == VRAM_A)
return space;
else
return space + sVramPoolB.GetFreeSpace();
}
else
return sVramPoolB.GetFreeSpace();
}
u32 vramSpaceFree() u32 vramSpaceFree()
{ {
return sVramPool.GetFreeSpace(); return sVramPoolA.GetFreeSpace() + sVramPoolB.GetFreeSpace();
} }