Introduce triple buffer and remove RDP freeze

This commit is contained in:
Ryan Dwyer
2023-05-02 22:50:56 +10:00
parent fcc63f7638
commit 7ef3e9d009
8 changed files with 117 additions and 98 deletions
+2
View File
@@ -100,6 +100,8 @@ typedef struct {
u32 alt;
OSMesgQueue *audmq;
OSMesgQueue *gfxmq;
void *scheduledFB;
void *queuedFB;
} OSSched;
void osCreateScheduler(OSSched *s, OSThread *thread, u8 mode, u32 numFields);
+1 -1
View File
@@ -15,7 +15,7 @@ glabel func0f165360
lui $a3, %hi(g_Vars)
addiu $a3, $a3, %lo(g_Vars)
lw $a3, 0x284($a3)
lw $a3, 0x1740($a3)
lw $a3, 0x1750($a3)
lui $t0, %hi(var800a4cf0)
addiu $t0, $t0, %lo(var800a4cf0)
lui $at, %hi(var7f1b76d0)
+1 -1
View File
@@ -62,7 +62,7 @@ s32 g_MenuScissorX1;
s32 g_MenuScissorX2;
s32 g_MenuScissorY1;
s32 g_MenuScissorY2;
Vp var800a2048[4][2];
Vp var800a2048[4][3];
struct menudialogdef g_PakCannotReadGameBoyMenuDialog;
struct menudialogdef g_PakDamagedMenuDialog;
+1 -1
View File
@@ -371,7 +371,7 @@ void playermgrAllocatePlayer(s32 index)
g_Vars.players[index]->floorflags = 0;
for (i = 0; i < 2; i++) {
for (i = 0; i < 3; i++) {
g_Vars.players[index]->viewport[i].vp.vscale[0] = 640;
g_Vars.players[index]->viewport[i].vp.vscale[1] = (PAL ? 544 : 480);
g_Vars.players[index]->viewport[i].vp.vscale[2] = 511;
+1 -1
View File
@@ -2515,7 +2515,7 @@ struct player {
/*0x0494*/ union modelrwdata *bondheadsave[30];
/*0x050c*/ u32 unk050c;
/*0x0510*/ Mtxf bondheadmatrices[4];
/*0x0610*/ Vp viewport[2];
/*0x0610*/ Vp viewport[3];
/*0x0630*/ s16 viewwidth; // 320 lo-res, 640 hi-res
/*0x0632*/ s16 viewheight; // 220 regardless of res
/*0x0634*/ s16 viewleft; // 0
+1 -1
View File
@@ -785,7 +785,7 @@ glabel model00018680
lwc1 $f0, 0x38($t0)
lw $t2, 0x284($t2)
neg.s $f0, $f0
lwc1 $f1, 0x1774($t2)
lwc1 $f1, 0x1784($t2)
mul.s $f0, $f0, $f1
lui $t0, %hi(g_ModelDistanceScale)
addiu $t0, $t0, %lo(g_ModelDistanceScale)
+84 -74
View File
@@ -77,7 +77,7 @@ static void __scTryDispatch(OSSched *sc)
OSScTask *t = sc->nextAudTask;
sc->nextAudTask = NULL;
__scExec(sc, t);
} else if (sc->curRDPTask == NULL) {
} else if (sc->curRDPTask == NULL && sc->queuedFB == NULL) {
OSScTask *t = sc->nextGfxTask;
if (t) {
@@ -89,56 +89,68 @@ static void __scTryDispatch(OSSched *sc)
}
}
static void __scSwap(OSSched *sc, void *framebuffer)
{
if (g_SchedIsFirstTask) {
osViBlack(false);
g_SchedIsFirstTask = false;
}
var8005ce74 = (var8005ce74 + 1) % 2;
if (g_SchedViModesPending[1 - var8005ce74]) {
if (var8008dd60[1 - var8005ce74]->comRegs.width != var8008dcc0[1 - var8005ce74].comRegs.width
|| var8008dd60[1 - var8005ce74]->comRegs.xScale != var8008dcc0[1 - var8005ce74].comRegs.xScale
|| var8008dd60[1 - var8005ce74]->fldRegs[0].yScale != var8008dcc0[1 - var8005ce74].fldRegs[0].yScale
|| var8008dd60[1 - var8005ce74]->fldRegs[1].yScale != var8008dcc0[1 - var8005ce74].fldRegs[1].yScale
|| var8008dd60[1 - var8005ce74]->fldRegs[0].origin != var8008dcc0[1 - var8005ce74].fldRegs[0].origin
|| var8008dd60[1 - var8005ce74]->fldRegs[1].origin != var8008dcc0[1 - var8005ce74].fldRegs[1].origin) {
s32 mask = osSetIntMask(0x80401);
*var8008dd60[1 - var8005ce74] = var8008dcc0[1 - var8005ce74];
osSetIntMask(mask);
osViSetMode(var8008dd60[1 - var8005ce74]);
osViBlack(g_ViUnblackTimer);
osViSetXScale(g_ViXScalesBySlot[1 - var8005ce74]);
osViSetYScale(g_ViYScalesBySlot[1 - var8005ce74]);
#ifdef ANTIALIAS
osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_ON);
#else
osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_OFF);
#endif
}
g_SchedViModesPending[1 - var8005ce74] = false;
}
if (g_ViUnblackTimer != 0 && g_ViUnblackTimer < 3) {
g_ViUnblackTimer--;
}
osViSwapBuffer(framebuffer);
}
static void __scTaskComplete(OSSched *sc, OSScTask *t)
{
if (t->list.t.type == M_AUDTASK) {
profileHandleRspEvent(RSPEVENT_AUD_FINISH);
osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK);
} else {
profileHandleRspEvent(RSPEVENT_GFX_FINISH);
if (g_SchedIsFirstTask) {
osViBlack(false);
g_SchedIsFirstTask = false;
if (sc->scheduledFB == NULL) {
sc->scheduledFB = t->framebuffer;
__scSwap(sc, t->framebuffer);
} else {
sc->queuedFB = t->framebuffer;
}
var8005ce74 = (var8005ce74 + 1) % 2;
if (g_SchedViModesPending[1 - var8005ce74]) {
if (var8008dd60[1 - var8005ce74]->comRegs.width != var8008dcc0[1 - var8005ce74].comRegs.width
|| var8008dd60[1 - var8005ce74]->comRegs.xScale != var8008dcc0[1 - var8005ce74].comRegs.xScale
|| var8008dd60[1 - var8005ce74]->fldRegs[0].yScale != var8008dcc0[1 - var8005ce74].fldRegs[0].yScale
|| var8008dd60[1 - var8005ce74]->fldRegs[1].yScale != var8008dcc0[1 - var8005ce74].fldRegs[1].yScale
|| var8008dd60[1 - var8005ce74]->fldRegs[0].origin != var8008dcc0[1 - var8005ce74].fldRegs[0].origin
|| var8008dd60[1 - var8005ce74]->fldRegs[1].origin != var8008dcc0[1 - var8005ce74].fldRegs[1].origin) {
s32 mask = osSetIntMask(0x80401);
*var8008dd60[1 - var8005ce74] = var8008dcc0[1 - var8005ce74];
osSetIntMask(mask);
osViSetMode(var8008dd60[1 - var8005ce74]);
osViBlack(g_ViUnblackTimer);
osViSetXScale(g_ViXScalesBySlot[1 - var8005ce74]);
osViSetYScale(g_ViYScalesBySlot[1 - var8005ce74]);
#ifdef ANTIALIAS
osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_ON);
#else
osViSetSpecialFeatures(OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_OFF);
#endif
}
g_SchedViModesPending[1 - var8005ce74] = false;
}
if (g_ViUnblackTimer != 0 && g_ViUnblackTimer < 3) {
g_ViUnblackTimer--;
}
osViSwapBuffer(t->framebuffer);
osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK);
osSendMesg(sc->gfxmq, (OSMesg) &sc->retraceMsg, OS_MESG_BLOCK);
}
osSendMesg(t->msgQ, t->msg, OS_MESG_BLOCK);
}
//-----------------------------------------------------------------------------\
@@ -147,23 +159,35 @@ static void __scTaskComplete(OSSched *sc, OSScTask *t)
static void __scHandleRetrace(OSSched *sc)
{
if (osViGetCurrentFramebuffer() == osViGetNextFramebuffer()) {
osDpSetStatus(DPC_CLR_FREEZE);
if (sc->scheduledFB && osViGetCurrentFramebuffer() == sc->scheduledFB) {
if (sc->queuedFB) {
sc->scheduledFB = sc->queuedFB;
sc->queuedFB = NULL;
__scSwap(sc, sc->scheduledFB);
__scTryDispatch(sc);
} else {
sc->scheduledFB = NULL;
}
}
sc->alt ^= 1;
#if PAL
if (!g_Resetting && sc->alt) {
/**
* On every second retrace, we set a ~6ms timer to prompt the audio thread
* to start making another frame. When the audio task is ready, we try to
* give it to the RSP after the next gfx task finishes rather than yield the
* gfx task. But if we're at the second retrace and the previous gfx task is
* still not done then we must yield it.
*/
if (sc->alt && !g_Resetting) {
osStopTimer(&g_SchedRspTimer);
osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg);
if (sc->nextAudTask && sc->curRSPTask->list.t.type == M_GFXTASK) {
osSpTaskYield();
sc->curRSPTask->state |= OS_SC_YIELD;
}
}
#else
if (!g_Resetting && sc->alt) {
osStopTimer(&g_SchedRspTimer);
osSetTimer(&g_SchedRspTimer, 280000, 0, amgrGetFrameMesgQueue(), &g_SchedRspMsg);
}
#endif
if (!g_Resetting) {
vi00009ed4();
@@ -204,8 +228,6 @@ static void __scHandleRDP(OSSched *sc)
{
OSScTask *t;
osDpSetStatus(DPC_SET_FREEZE);
schedUpdatePendingArtifacts();
if (var8005dd18 == 0) {
@@ -229,8 +251,6 @@ static void __scHandleRDP(OSSched *sc)
}
__scTryDispatch(sc);
osSendMesg(sc->gfxmq, (OSMesg) &sc->retraceMsg, OS_MESG_NOBLOCK);
}
static void __scMain(void *arg)
@@ -258,11 +278,6 @@ void schedSubmitAudTask(OSSched *sc, OSScTask *t)
if (sc->curRSPTask == NULL) {
__scExec(sc, t);
} else {
if (sc->curRSPTask->list.t.type == M_GFXTASK) {
osSpTaskYield();
sc->curRSPTask->state |= OS_SC_YIELD;
}
t->state = OS_SC_NEEDS_RSP;
sc->nextAudTask = t;
}
@@ -277,22 +292,15 @@ void schedSubmitGfxTask(OSSched *sc, OSScTask *t)
t->state = OS_SC_NEEDS_RSP | OS_SC_NEEDS_RDP;
//if (sc->curRSPTask == NULL && sc->curRDPTask == NULL) {
// __scExec(sc, t);
//} else {
// if (sc->nextGfxTask == NULL) {
// sc->nextGfxTask = t;
// } else {
// sc->nextGfxTask2 = t;
// }
//}
if (sc->nextGfxTask == NULL) {
sc->nextGfxTask = t;
if (sc->curRSPTask == NULL && sc->curRDPTask == NULL && sc->queuedFB == NULL) {
__scExec(sc, t);
} else {
sc->nextGfxTask2 = t;
if (sc->nextGfxTask == NULL) {
sc->nextGfxTask = t;
} else {
sc->nextGfxTask2 = t;
}
}
__scTryDispatch(sc);
osSetThreadPri(0, prevpri);
}
@@ -325,6 +333,8 @@ void osCreateScheduler(OSSched *sc, OSThread *thread, u8 mode, u32 numFields)
sc->retraceMsg.type = OS_SC_RETRACE_MSG;
sc->prenmiMsg.type = OS_SC_PRE_NMI_MSG;
sc->thread = thread;
sc->scheduledFB = NULL;
sc->queuedFB = NULL;
resetThreadCreate();
+26 -19
View File
@@ -26,7 +26,7 @@ Mtx *var80092870;
u16 g_ViPerspScale;
u8 g_ViFrontIndex;
u8 g_ViBackIndex;
u16 *g_FrameBuffers[2];
u16 *g_FrameBuffers[3];
struct rend_vidat g_ViDataArray[] = {
{
@@ -53,6 +53,18 @@ struct rend_vidat g_ViDataArray[] = {
0, 0, // viewleft and viewtop
true, // usezbuf
0,
}, {
0, 0, 0, 0,
320, 220, // x and y
60, // fovy
1.4545454978943f, // aspect
30, // znear
10000, // zfar
320, 220, // bufx and bufy
320, 220, // viewx and viewy
0, 0, // viewleft and viewtop
true, // usezbuf
0,
},
};
@@ -60,7 +72,6 @@ s32 var8005d588 = 0;
s32 var8005d58c = 0;
struct rend_vidat *g_ViFrontData = &g_ViDataArray[0];
struct rend_vidat *g_ViBackData = &g_ViDataArray[0];
bool g_ViIs16Bit = true;
bool g_ViReconfigured = false;
s32 g_ViSlot = 0;
@@ -87,7 +98,7 @@ void viConfigureForCopyright(u16 *texturedata)
{
s32 i;
for (i = 0; i < 2; i++) {
for (i = 0; i < 3; i++) {
g_FrameBuffers[i] = texturedata;
g_ViDataArray[i].x = 576;
@@ -115,7 +126,7 @@ void viConfigureForLegal(void)
{
s32 i;
for (i = 0; i < 2; i++) {
for (i = 0; i < 3; i++) {
g_ViDataArray[i].x = 320;
g_ViDataArray[i].bufx = 320;
g_ViDataArray[i].viewx = 320;
@@ -155,6 +166,7 @@ void viReset(s32 stagenum)
u8 *ptr;
u8 *fb0;
u8 *fb1;
u8 *fb2;
if (stagenum == STAGE_TITLE) {
viSetMode(VIMODE_HI);
@@ -164,22 +176,25 @@ void viReset(s32 stagenum)
fbsize = 320 * 220 * 2;
}
ptr = mempAlloc(fbsize * 2 + 0x40, MEMPOOL_STAGE);
ptr = mempAlloc(fbsize * 3 + 0x40, MEMPOOL_STAGE);
ptr = (u8 *)(((u32)ptr + 0x3f) & 0xffffffc0);
g_FrameBuffers[0] = (u16 *) ptr;
g_FrameBuffers[1] = (u16 *) (fbsize + ptr);
g_FrameBuffers[1] = (u16 *) (ptr + fbsize);
g_FrameBuffers[2] = (u16 *) (ptr + fbsize * 2);
g_ViFrontData->fb = g_FrameBuffers[g_ViFrontIndex];
g_ViBackData->fb = g_FrameBuffers[g_ViBackIndex];
fb0 = (u8 *) g_FrameBuffers[0];
fb1 = (u8 *) g_FrameBuffers[1];
fb2 = (u8 *) g_FrameBuffers[2];
for (i = 0; i < fbsize; i++) {
fb0[i] = 0;
fb1[i] = 0;
fb2[i] = 0;
}
g_ViReconfigured = true;
@@ -360,12 +375,12 @@ void viUpdateMode(void)
// 908
g_ViSlot = (g_ViSlot + 1) % 2;
g_RdpCurTask->framebuffer = g_ViIs16Bit ? g_ViBackData->fb : g_FrameBuffers[0];
g_RdpCurTask->framebuffer = g_ViBackData->fb;
prevdata = g_ViBackData;
g_ViFrontIndex = (g_ViFrontIndex + 1) % 2;
g_ViBackIndex = (g_ViBackIndex + 1) % 2;
g_ViFrontIndex = (g_ViFrontIndex + 1) % 3;
g_ViBackIndex = (g_ViBackIndex + 1) % 3;
g_ViFrontData = g_ViDataArray + g_ViFrontIndex;
g_ViBackData = g_ViDataArray + g_ViBackIndex;
@@ -544,11 +559,7 @@ Gfx *vi0000b1d0(Gfx *gdl)
{
gdl = vi0000b1a8(gdl);
if (g_ViIs16Bit) {
gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_ViBackData->fb));
} else {
gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_32b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_FrameBuffers[0]));
}
gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, g_ViBackData->bufx, OS_K0_TO_PHYSICAL(g_ViBackData->fb));
return gdl;
}
@@ -784,11 +795,7 @@ void viGetZRange(struct zrange *zrange)
Gfx *viSetFillColour(Gfx *gdl, s32 r, s32 g, s32 b)
{
if (g_ViIs16Bit) {
gDPSetFillColor(gdl++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1));
} else {
gDPSetFillColor(gdl++, r << 24 | g << 16 | b << 8 | 0xff);
}
gDPSetFillColor(gdl++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1));
return gdl;
}