Refactor linear heap code (formerly known as GSP heap)
This commit is contained in:
parent
16544492a2
commit
125398a52f
@ -161,12 +161,12 @@ int main()
|
|||||||
GPU_Init(NULL);
|
GPU_Init(NULL);
|
||||||
|
|
||||||
u32 gpuCmdSize=0x40000;
|
u32 gpuCmdSize=0x40000;
|
||||||
u32* gpuCmd=(u32*)gfxAllocLinear(gpuCmdSize*4);
|
u32* gpuCmd=(u32*)linearAlloc(gpuCmdSize*4);
|
||||||
|
|
||||||
GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize);
|
GPU_Reset(gxCmdBuf, gpuCmd, gpuCmdSize);
|
||||||
|
|
||||||
vertArray=(float*)gfxAllocLinear(0x100000);
|
vertArray=(float*)linearAlloc(0x100000);
|
||||||
texData=(u32*)gfxAllocLinear(0x100000);
|
texData=(u32*)linearAlloc(0x100000);
|
||||||
|
|
||||||
memcpy(texData, test_png_bin, test_png_bin_size);
|
memcpy(texData, test_png_bin, test_png_bin_size);
|
||||||
memcpy(vertArray, mdlData, sizeof(mdlData));
|
memcpy(vertArray, mdlData, sizeof(mdlData));
|
||||||
|
@ -8,6 +8,7 @@ extern "C" {
|
|||||||
#include <3ds/types.h>
|
#include <3ds/types.h>
|
||||||
#include <3ds/svc.h>
|
#include <3ds/svc.h>
|
||||||
#include <3ds/srv.h>
|
#include <3ds/srv.h>
|
||||||
|
#include <3ds/linear.h>
|
||||||
#include <3ds/os.h>
|
#include <3ds/os.h>
|
||||||
#include <3ds/gfx.h>
|
#include <3ds/gfx.h>
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ void gfxSwapBuffersGpu();
|
|||||||
|
|
||||||
//helper stuff
|
//helper stuff
|
||||||
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
|
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
|
||||||
void* gfxAllocLinear(size_t size);
|
|
||||||
|
|
||||||
//global variables
|
//global variables
|
||||||
extern u8* gfxTopLeftFramebuffers[2];
|
extern u8* gfxTopLeftFramebuffers[2];
|
||||||
|
6
libctru/include/3ds/linear.h
Normal file
6
libctru/include/3ds/linear.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Functions for allocating/deallocating memory from linear heap
|
||||||
|
void* linearAlloc(size_t size);
|
||||||
|
void* linearRealloc(void* mem, size_t size);
|
||||||
|
void linearFree(void* mem);
|
@ -17,25 +17,7 @@ bool enable3d;
|
|||||||
|
|
||||||
Handle gspEvent, gspSharedMemHandle;
|
Handle gspEvent, gspSharedMemHandle;
|
||||||
|
|
||||||
u8* gspHeap;
|
|
||||||
u32* gxCmdBuf;
|
u32* gxCmdBuf;
|
||||||
extern u32 __gsp_heap_size;
|
|
||||||
|
|
||||||
// TODO: this function is not thread-safe and you cannot 'free' this memory.
|
|
||||||
void* gfxAllocLinear(size_t size)
|
|
||||||
{
|
|
||||||
static size_t currentOffset = 0;
|
|
||||||
size_t free = __gsp_heap_size - currentOffset;
|
|
||||||
|
|
||||||
if(free >= size)
|
|
||||||
{
|
|
||||||
currentOffset += size;
|
|
||||||
return (void*) &gspHeap[currentOffset - size];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void gfxSet3D(bool enable)
|
void gfxSet3D(bool enable)
|
||||||
{
|
{
|
||||||
@ -90,9 +72,6 @@ void gfxInit()
|
|||||||
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID);
|
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &gfxThreadID);
|
||||||
svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000);
|
svcMapMemoryBlock(gspSharedMemHandle, (u32)gfxSharedMemory, 0x3, 0x10000000);
|
||||||
|
|
||||||
//map GSP heap
|
|
||||||
svcControlMemory((u32*)&gspHeap, 0x0, 0x0, __gsp_heap_size, 0x10003, 0x3);
|
|
||||||
|
|
||||||
// default gspHeap configuration :
|
// default gspHeap configuration :
|
||||||
// topleft1 0x00000000-0x00046500
|
// topleft1 0x00000000-0x00046500
|
||||||
// topleft2 0x00046500-0x0008CA00
|
// topleft2 0x00046500-0x0008CA00
|
||||||
@ -102,12 +81,12 @@ void gfxInit()
|
|||||||
// topright1 0x000FD200-0x00143700
|
// topright1 0x000FD200-0x00143700
|
||||||
// topright2 0x00143700-0x00189C00
|
// topright2 0x00143700-0x00189C00
|
||||||
|
|
||||||
gfxTopLeftFramebuffers[0]=gfxAllocLinear(0x46500);
|
gfxTopLeftFramebuffers[0]=linearAlloc(0x46500);
|
||||||
gfxTopLeftFramebuffers[1]=gfxAllocLinear(0x46500);
|
gfxTopLeftFramebuffers[1]=linearAlloc(0x46500);
|
||||||
gfxBottomFramebuffers[0]=gfxAllocLinear(0x38400);
|
gfxBottomFramebuffers[0]=linearAlloc(0x38400);
|
||||||
gfxBottomFramebuffers[1]=gfxAllocLinear(0x38400);
|
gfxBottomFramebuffers[1]=linearAlloc(0x38400);
|
||||||
gfxTopRightFramebuffers[0]=gfxAllocLinear(0x46500);
|
gfxTopRightFramebuffers[0]=linearAlloc(0x46500);
|
||||||
gfxTopRightFramebuffers[1]=gfxAllocLinear(0x46500);
|
gfxTopRightFramebuffers[1]=linearAlloc(0x46500);
|
||||||
enable3d=false;
|
enable3d=false;
|
||||||
|
|
||||||
//initialize framebuffer info structures
|
//initialize framebuffer info structures
|
||||||
@ -129,8 +108,13 @@ void gfxExit()
|
|||||||
// Exit event handler
|
// Exit event handler
|
||||||
gspExitEventHandler();
|
gspExitEventHandler();
|
||||||
|
|
||||||
//free GSP heap
|
// Free framebuffers (let's pretend linearFree is actually implemented...)
|
||||||
svcControlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, __gsp_heap_size, MEMOP_FREE, 0x0);
|
linearFree(gfxTopRightFramebuffers[1]);
|
||||||
|
linearFree(gfxTopRightFramebuffers[0]);
|
||||||
|
linearFree(gfxBottomFramebuffers[1]);
|
||||||
|
linearFree(gfxBottomFramebuffers[0]);
|
||||||
|
linearFree(gfxTopLeftFramebuffers[1]);
|
||||||
|
linearFree(gfxTopLeftFramebuffers[0]);
|
||||||
|
|
||||||
//unmap GSP shared mem
|
//unmap GSP shared mem
|
||||||
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
|
svcUnmapMemoryBlock(gspSharedMemHandle, 0x10002000);
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
int __system_argc;
|
int __system_argc;
|
||||||
char** __system_argv;
|
char** __system_argv;
|
||||||
void (*__system_retAddr)(void);
|
void (*__system_retAddr)(void);
|
||||||
|
u32 __linear_heap;
|
||||||
|
|
||||||
// Data from _prm structure
|
// Data from _prm structure
|
||||||
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
|
extern void* __service_ptr; // used to detect if we're run from a homebrew launcher
|
||||||
extern u32 __heap_size;
|
extern u32 __heap_size, __linear_heap_size;
|
||||||
extern const char* __system_arglist;
|
extern const char* __system_arglist;
|
||||||
|
|
||||||
// newlib definitions we need
|
// newlib definitions we need
|
||||||
@ -27,7 +28,10 @@ void __attribute__((noreturn)) __ctru_exit(int rc)
|
|||||||
|
|
||||||
// TODO: APT exit goes here
|
// TODO: APT exit goes here
|
||||||
|
|
||||||
// Unmap the heap
|
// Unmap the linear heap
|
||||||
|
svcControlMemory(&__linear_heap, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0);
|
||||||
|
|
||||||
|
// Unmap the application heap
|
||||||
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
|
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0);
|
||||||
|
|
||||||
// Jump to the loader if it provided a callback
|
// Jump to the loader if it provided a callback
|
||||||
@ -48,6 +52,9 @@ void initSystem(void (*retAddr)(void))
|
|||||||
heapBase = 0x08000000;
|
heapBase = 0x08000000;
|
||||||
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
|
svcControlMemory(&heapBase, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3);
|
||||||
|
|
||||||
|
// Allocate the linear heap
|
||||||
|
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3);
|
||||||
|
|
||||||
// Set up newlib heap
|
// Set up newlib heap
|
||||||
fake_heap_start = (char*)heapBase;
|
fake_heap_start = (char*)heapBase;
|
||||||
fake_heap_end = fake_heap_start + __heap_size;
|
fake_heap_end = fake_heap_start + __heap_size;
|
||||||
|
32
libctru/source/linear.c
Normal file
32
libctru/source/linear.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <3ds.h>
|
||||||
|
|
||||||
|
extern u32 __linear_heap, __linear_heap_size;
|
||||||
|
|
||||||
|
// TODO: this allocator sucks! It is not thread-safe and you cannot 'free' this memory.
|
||||||
|
void* linearAlloc(size_t size)
|
||||||
|
{
|
||||||
|
static size_t currentOffset = 0;
|
||||||
|
size_t free = __linear_heap_size - currentOffset;
|
||||||
|
|
||||||
|
// Enforce 8-byte alignment
|
||||||
|
size = (size + 7) &~ 7;
|
||||||
|
|
||||||
|
void* mem = NULL;
|
||||||
|
if (free >= size)
|
||||||
|
{
|
||||||
|
mem = (void*)(__linear_heap + currentOffset);
|
||||||
|
currentOffset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* linearRealloc(void* mem, size_t size)
|
||||||
|
{
|
||||||
|
return NULL; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void linearFree(void* mem)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
@ -358,7 +358,7 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle*
|
|||||||
svcClearEvent(gspEvent);
|
svcClearEvent(gspEvent);
|
||||||
|
|
||||||
u32 cmdBufHeader;
|
u32 cmdBufHeader;
|
||||||
__asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
|
__asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
|
||||||
|
|
||||||
u8 commandIndex=cmdBufHeader&0xFF;
|
u8 commandIndex=cmdBufHeader&0xFF;
|
||||||
u8 totalCommands=(cmdBufHeader>>8)&0xFF;
|
u8 totalCommands=(cmdBufHeader>>8)&0xFF;
|
||||||
@ -370,17 +370,17 @@ Result GSPGPU_SubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8], Handle*
|
|||||||
memcpy(dst, gxCommand, 0x20);
|
memcpy(dst, gxCommand, 0x20);
|
||||||
|
|
||||||
u32 mcrVal=0x0;
|
u32 mcrVal=0x0;
|
||||||
__asm__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register
|
__asm__ __volatile__ ("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (mcrVal)); //Data Synchronization Barrier Register
|
||||||
totalCommands++;
|
totalCommands++;
|
||||||
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8);
|
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|(((u32)totalCommands)<<8);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
u32 strexResult;
|
u32 strexResult;
|
||||||
__asm__ ("strex %[result], %[val], [%[adr]]" : [result] "=&r" (strexResult) : [adr] "r" (sharedGspCmdBuf), [val] "r" (cmdBufHeader));
|
__asm__ __volatile__ ("strex %[result], %[val], [%[adr]]" : [result] "=&r" (strexResult) : [adr] "r" (sharedGspCmdBuf), [val] "r" (cmdBufHeader));
|
||||||
if(!strexResult)break;
|
if(!strexResult)break;
|
||||||
|
|
||||||
__asm__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
|
__asm__ __volatile__ ("ldrex %[result], [%[adr]]" : [result] "=r" (cmdBufHeader) : [adr] "r" (sharedGspCmdBuf));
|
||||||
totalCommands=((cmdBufHeader&0xFF00)>>8)+1;
|
totalCommands=((cmdBufHeader&0xFF00)>>8)+1;
|
||||||
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00);
|
cmdBufHeader=((cmdBufHeader)&0xFFFF00FF)|((totalCommands<<8)&0xFF00);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user