3DS: Improve graphics pipeline, framelimiting

This commit is contained in:
Vicki Pfau 2017-09-02 15:05:14 -07:00
parent 41f27bf617
commit 10b14f90d1
3 changed files with 64 additions and 46 deletions

View File

@ -26,23 +26,21 @@ struct ctrUIVertex {
float rotate[2];
};
#define MAX_NUM_QUADS 256
#define BUFFER_PARTITIONS 4
#define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * BUFFER_PARTITIONS * sizeof(struct ctrUIVertex)
#define MAX_NUM_QUADS 4096
#define VERTEX_BUFFER_SIZE MAX_NUM_QUADS * sizeof(struct ctrUIVertex)
static struct ctrUIVertex* ctrVertexBuffer = NULL;
static int ctrNumVerts = 0;
static int ctrVertStart = 0;
static int ctrVertPartition = 0;
static C3D_Tex* activeTexture = NULL;
static const C3D_Tex* activeTexture = NULL;
static shaderProgram_s uiProgram;
static DVLB_s* uiShader = NULL;
static int GSH_FVEC_projectionMtx;
static int GSH_FVEC_textureMtx;
bool ctrInitGpu() {
bool ctrInitGpu(void) {
// Load vertex shader binary
uiShader = DVLB_ParseFile((u32*) uishader, uishader_size);
if (uiShader == NULL) {
@ -85,7 +83,7 @@ bool ctrInitGpu() {
return true;
}
void ctrDeinitGpu() {
void ctrDeinitGpu(void) {
if (ctrVertexBuffer) {
linearFree(ctrVertexBuffer);
ctrVertexBuffer = NULL;
@ -110,10 +108,23 @@ void ctrSetViewportSize(s16 w, s16 h, bool tilt) {
C3D_FVUnifMtx4x4(GPU_GEOMETRY_SHADER, GSH_FVEC_projectionMtx, &projectionMtx);
}
void ctrActivateTexture(C3D_Tex* texture) {
void ctrFlushBatch(void) {
int thisBatch = ctrNumVerts - ctrVertStart;
if (!thisBatch) {
return;
}
if (thisBatch < 0) {
svcBreak(USERBREAK_PANIC);
}
C3D_DrawArrays(GPU_GEOMETRY_PRIM, ctrVertStart, thisBatch);
ctrVertStart = ctrNumVerts;
}
void ctrActivateTexture(const C3D_Tex* texture) {
if (texture == activeTexture) {
return;
}
if (activeTexture) {
ctrFlushBatch();
}
@ -174,16 +185,11 @@ void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s
return;
}
if (ctrNumVerts + ctrVertStart == MAX_NUM_QUADS) {
ctrFlushBatch();
++ctrVertPartition;
if (ctrVertPartition == BUFFER_PARTITIONS) {
svcBreak(USERBREAK_PANIC);
}
ctrVertStart = ctrVertPartition * MAX_NUM_QUADS;
if (ctrNumVerts == MAX_NUM_QUADS) {
abort();
}
struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrVertStart + ctrNumVerts];
struct ctrUIVertex* vtx = &ctrVertexBuffer[ctrNumVerts];
vtx->x = x;
vtx->y = y;
vtx->w = w;
@ -203,24 +209,17 @@ void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) {
ctrAddRectEx(color, x, y, w, h, u, v, w, h, 0);
}
void ctrFlushBatch(void) {
if (ctrNumVerts == 0) {
return;
}
void ctrStartFrame(void) {
ctrNumVerts = 0;
ctrVertStart = 0;
activeTexture = NULL;
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 4, 0x3210);
GSPGPU_FlushDataCache(&ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex) * ctrNumVerts);
C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumVerts);
ctrVertStart += ctrNumVerts;
ctrNumVerts = 0;
BufInfo_Add(bufInfo, ctrVertexBuffer, sizeof(struct ctrUIVertex), 4, 0x3210);
}
void ctrFinalize(void) {
void ctrEndFrame(void) {
ctrFlushBatch();
ctrVertStart = 0;
ctrVertPartition = 0;
GSPGPU_FlushDataCache(ctrVertexBuffer, sizeof(struct ctrUIVertex) * ctrNumVerts);
}

View File

@ -16,12 +16,13 @@ void ctrDeinitGpu(void);
void ctrSetViewportSize(s16 w, s16 h, bool tilt);
void ctrActivateTexture(C3D_Tex* texture);
void ctrActivateTexture(const C3D_Tex* texture);
void ctrTextureMultiply(void);
void ctrTextureBias(u32 color);
void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh, float rotate);
void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h);
void ctrFlushBatch(void);
void ctrFinalize(void);
void ctrStartFrame(void);
void ctrEndFrame(void);
#endif

View File

@ -92,11 +92,12 @@ static C3D_Tex outputTexture;
static ndspWaveBuf dspBuffer[DSP_BUFFERS];
static int bufferId = 0;
static bool frameLimiter = true;
static unsigned frameCounter;
static u64 tickCounter;
static C3D_RenderTarget* topScreen[2];
static C3D_RenderTarget* bottomScreen[2];
static int doubleBuffer = 0;
static bool frameStarted = false;
static C3D_RenderTarget* upscaleBuffer;
static C3D_Tex upscaleBufferTex;
@ -226,22 +227,38 @@ static void _csndPlaySound(u32 flags, u32 sampleRate, float vol, void* left, voi
static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* right);
static void _drawStart(void) {
C3D_FrameBegin(frameLimiter ? 0 : C3D_FRAME_NONBLOCK);
}
static void _frameStart(void) {
if (frameStarted) {
return;
}
frameStarted = true;
u8 flags = 0;
if (!frameLimiter) {
if (tickCounter + 4481000 > svcGetSystemTick()) {
flags = C3D_FRAME_NONBLOCK;
} else {
tickCounter = svcGetSystemTick();
}
}
C3D_FrameBegin(flags);
// Mark both buffers used to make sure they get cleared
C3D_FrameDrawOn(topScreen[doubleBuffer]);
C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
ctrStartFrame();
}
static void _drawEnd(void) {
ctrFinalize();
if (!frameStarted) {
return;
}
ctrEndFrame();
C3D_RenderTargetSetOutput(topScreen[doubleBuffer], GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8));
C3D_RenderTargetSetOutput(bottomScreen[doubleBuffer], GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8));
C3D_FrameEnd(GX_CMDLIST_FLUSH);
if (frameLimiter) {
while (frameCounter == C3D_FrameCounter(0)) {
gspWaitForAnyEvent();
}
}
frameStarted = false;
doubleBuffer ^= 1;
C3D_FrameBufClear(&bottomScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
C3D_FrameBufClear(&topScreen[doubleBuffer]->frameBuf, C3D_CLEAR_COLOR, 0, 0);
@ -263,6 +280,7 @@ static int _batteryState(void) {
}
static void _guiPrepare(void) {
_frameStart();
C3D_FrameDrawOn(bottomScreen[doubleBuffer]);
ctrSetViewportSize(320, 240, true);
}
@ -442,12 +460,8 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
}
}
static void _storeCounter(struct mGUIRunner* runner) {
UNUSED(runner);
frameCounter = C3D_FrameCounter(0);
}
static void _drawTex(struct mCore* core, bool faded) {
_frameStart();
unsigned screen_w, screen_h;
switch (screenMode) {
case SM_PA_BOTTOM:
@ -657,7 +671,11 @@ static void _incrementScreenMode(struct mGUIRunner* runner) {
static void _setFrameLimiter(struct mGUIRunner* runner, bool limit) {
UNUSED(runner);
if (frameLimiter == limit) {
return;
}
frameLimiter = limit;
tickCounter = svcGetSystemTick();
}
static uint32_t _pollInput(const struct mInputMap* map) {
@ -995,7 +1013,7 @@ int main() {
.teardown = 0,
.gameLoaded = _gameLoaded,
.gameUnloaded = _gameUnloaded,
.prepareForFrame = _storeCounter,
.prepareForFrame = 0,
.drawFrame = _drawFrame,
.drawScreenshot = _drawScreenshot,
.paused = _gameUnloaded,