I just wanted to try out another memory management system for the VRAM (or more generally small amounts of RAM) than the one I used in my valloc library. There I used a double linked list, exactly as the libc malloc routine uses. This solution however has an overhead when only managing small amounts of memory (like the 2MB of VRAM). After playing around with an idea, I coded this version of the memory manager and it turned out up to three times as fast as the previous version.
It uses a fixed block subdivision of the memory area to manage, and allocates block by marking the starting block as allocated and adapting it's size variable according. The old version had to allocate memory management structures for every valloc call plus the linked list approach suffered from inlocality of memory when traversing the list to find a new free/allocated block.
The current implementation uses a fixed amount of MEM_SIZE/BLOCK_SIZE*4 bytes of system ram for the management, that is 16kb for the current implementation with blocks of 512 bytes.
As a result, the code is also much more readable and easier to understand. I hope some can learn something from it.
PRO: - very fast allocation/deallocation of blocks in VRAM (2-3 times as fast as previous valloc implementation)
- less system ram consumption
- more readable code
- can easily be changed to manage any other form of address area
CON: - allocations are aligned on bigger blocks (512 currently), so more memory waste with unaligned allocations
- no vrealloc routine implemented (could be done by doing vfree/valloc + memcpy)
Example code to use with normal GU code:
INITCODE:
gu_frontbuffer = vrelptr(valloc(FRAME_BUFFER_SIZE));
gu_backbuffer = vrelptr(valloc(FRAME_BUFFER_SIZE));
sceGuDrawBuffer(GU_PSM_8888, gu_frontbuffer, FRAME_BUFFER_WIDTH);
sceGuDispBuffer(480, 272, gu_backbuffer, FRAME_BUFFER_WIDTH);
ALLOCATING TEXTURES:
gu_texture = valloc(512*512*4);
// fill texture buffer...
sceGuTexImage(0, 512, 512, 512, gu_texture);
// draw as normal
The same code works for my old valloc library btw. Also you don't need to deallocate the frontbuffer and backbuffer normally, since they should stay static all over your program and allocations are lost when the program exits anyway.
EDIT: Fixed vram.c file to not use undefined u32 type.