Fixed issue with latency patch not always starting with the correct behavior
This commit is contained in:
parent
1651298a2c
commit
31d2424774
|
@ -2,7 +2,12 @@
|
||||||
#include "sys_cfb.h"
|
#include "sys_cfb.h"
|
||||||
#include "buffers.h"
|
#include "buffers.h"
|
||||||
#include "fault.h"
|
#include "fault.h"
|
||||||
|
#include "audiomgr.h"
|
||||||
#include "z64speed_meter.h"
|
#include "z64speed_meter.h"
|
||||||
|
#include "z64vimode.h"
|
||||||
|
#include "z64viscvg.h"
|
||||||
|
#include "z64vismono.h"
|
||||||
|
#include "z64viszbuf.h"
|
||||||
|
|
||||||
void recomp_set_current_frame_poll_id();
|
void recomp_set_current_frame_poll_id();
|
||||||
void PadMgr_HandleRetrace(void);
|
void PadMgr_HandleRetrace(void);
|
||||||
|
@ -34,6 +39,7 @@ void PadMgr_GetInput2(Input* inputs, s32 gameRequest) {
|
||||||
extern CfbInfo sGraphCfbInfos[3];
|
extern CfbInfo sGraphCfbInfos[3];
|
||||||
u32 recomp_time_us();
|
u32 recomp_time_us();
|
||||||
void recomp_measure_latency();
|
void recomp_measure_latency();
|
||||||
|
void* osViGetCurrentFramebuffer_recomp();
|
||||||
|
|
||||||
OSMesgQueue *rdp_queue_ptr = NULL;
|
OSMesgQueue *rdp_queue_ptr = NULL;
|
||||||
|
|
||||||
|
@ -51,13 +57,10 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||||
static IrqMgrClient irq_client = {0};
|
static IrqMgrClient irq_client = {0};
|
||||||
static OSMesgQueue vi_queue = {0};
|
static OSMesgQueue vi_queue = {0};
|
||||||
static OSMesg vi_buf[8] = {0};
|
static OSMesg vi_buf[8] = {0};
|
||||||
static OSMesgQueue rdp_queue = {0};
|
|
||||||
static OSMesg rdp_mesg = NULL;
|
|
||||||
static bool created = false;
|
static bool created = false;
|
||||||
if (!created) {
|
if (!created) {
|
||||||
created = true;
|
created = true;
|
||||||
osCreateMesgQueue(&vi_queue, vi_buf, ARRAY_COUNT(vi_buf));
|
osCreateMesgQueue(&vi_queue, vi_buf, ARRAY_COUNT(vi_buf));
|
||||||
osCreateMesgQueue(&rdp_queue, &rdp_mesg, 1);
|
|
||||||
extern IrqMgr gIrqMgr;
|
extern IrqMgr gIrqMgr;
|
||||||
IrqMgr_AddClient(&gIrqMgr, &irq_client, &vi_queue);
|
IrqMgr_AddClient(&gIrqMgr, &irq_client, &vi_queue);
|
||||||
}
|
}
|
||||||
|
@ -65,9 +68,7 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||||
// @recomp Disable the wait here so that it can be moved after task submission for minimizing latency.
|
// @recomp Disable the wait here so that it can be moved after task submission for minimizing latency.
|
||||||
// retry:
|
// retry:
|
||||||
// osSetTimer(&timer, OS_USEC_TO_CYCLES(3 * 1000 * 1000), 0, &gfxCtx->queue, (OSMesg)666);
|
// osSetTimer(&timer, OS_USEC_TO_CYCLES(3 * 1000 * 1000), 0, &gfxCtx->queue, (OSMesg)666);
|
||||||
u32 count_before = recomp_time_us();
|
// osRecvMesg(&gfxCtx->queue, &msg, OS_MESG_BLOCK);
|
||||||
osRecvMesg(&gfxCtx->queue, &msg, OS_MESG_BLOCK);
|
|
||||||
u32 count_after = recomp_time_us();
|
|
||||||
// osStopTimer(&timer);
|
// osStopTimer(&timer);
|
||||||
|
|
||||||
// if (msg == (OSMesg)666) {
|
// if (msg == (OSMesg)666) {
|
||||||
|
@ -143,66 +144,51 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||||
osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK);
|
osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @recomp Set up the dedicated RDP complete message queue pointer for the scheduler.
|
|
||||||
rdp_queue_ptr = &rdp_queue;
|
|
||||||
|
|
||||||
gfxCtx->schedMsgQ = &gSchedContext.cmdQ;
|
gfxCtx->schedMsgQ = &gSchedContext.cmdQ;
|
||||||
recomp_measure_latency();
|
|
||||||
osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK);
|
osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK);
|
||||||
Sched_SendEntryMsg(&gSchedContext);
|
Sched_SendEntryMsg(&gSchedContext);
|
||||||
|
|
||||||
// @recomp Wait for the RDP complete message to mitigate waiting between creating the next task and submitting it.
|
// @recomp Immediately wait on the task to complete to minimize latency for the next one.
|
||||||
osRecvMesg(&rdp_queue, NULL, OS_MESG_BLOCK);
|
osRecvMesg(&gfxCtx->queue, &msg, OS_MESG_BLOCK);
|
||||||
rdp_queue_ptr = NULL;
|
|
||||||
|
|
||||||
// @recomp Manually wait the required number of VI periods after submitting the task
|
// @recomp Wait on the VI framebuffer to change if this task has a framebuffer swap.
|
||||||
// so that the next frame doesn't need to wait before submitting its task.
|
if (scTask->flags & OS_SC_SWAPBUFFER) {
|
||||||
u32 vi_count_before = recomp_time_us();
|
while (osViGetCurrentFramebuffer_recomp() != cfb->fb1) {
|
||||||
for (int i = 0; i < cfb->updateRate; i++) {
|
osRecvMesg(&vi_queue, NULL, OS_MESG_BLOCK);
|
||||||
|
}
|
||||||
|
// Wait one extra VI afterwards.
|
||||||
osRecvMesg(&vi_queue, NULL, OS_MESG_BLOCK);
|
osRecvMesg(&vi_queue, NULL, OS_MESG_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @recomp Flush any excess VI messages that came in.
|
// @recomp Flush any extra messages from the VI queue.
|
||||||
while (osRecvMesg(&vi_queue, NULL, OS_MESG_NOBLOCK) == 0) {
|
while (osRecvMesg(&vi_queue, NULL, OS_MESG_NOBLOCK) == 0) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
u32 vi_count_after = recomp_time_us();
|
|
||||||
|
|
||||||
// recomp_printf("recv wait added %d us\nVI wait: %d us\n", count_after - count_before, vi_count_after - vi_count_before);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern OSTime sRDPStartTime;
|
extern SpeedMeter sGameSpeedMeter;
|
||||||
|
extern VisCvg sGameVisCvg;
|
||||||
|
extern VisZbuf sGameVisZbuf;
|
||||||
|
extern VisMono sGameVisMono;
|
||||||
|
extern ViMode sGameViMode;
|
||||||
|
|
||||||
// @recomp Patched to send a message to the dedicated RDP complete message queue.
|
void GameState_Destroy(GameState* gameState) {
|
||||||
void Sched_HandleRDPDone(SchedContext* sched) {
|
AudioMgr_StopAllSfxExceptSystem();
|
||||||
OSScTask* curRDP;
|
Audio_Update();
|
||||||
OSScTask* nextRSP = NULL;
|
|
||||||
OSScTask* nextRDP = NULL;
|
|
||||||
s32 state;
|
|
||||||
|
|
||||||
if (sched->curRDPTask == NULL) {
|
// @recomp The wait for the gfx task was moved to directly after submission, so it's not needed here.
|
||||||
osSyncPrintf("__scHandleRDP:sc->curRDPTask == NULL\n");
|
// osRecvMesg(&gameState->gfxCtx->queue, NULL, OS_MESG_BLOCK);
|
||||||
return;
|
|
||||||
|
if (gameState->destroy != NULL) {
|
||||||
|
gameState->destroy(gameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log run time
|
Rumble_Destroy();
|
||||||
gRDPTimeAcc = osGetTime() - sRDPStartTime;
|
SpeedMeter_Destroy(&sGameSpeedMeter);
|
||||||
|
VisCvg_Destroy(&sGameVisCvg);
|
||||||
// Mark task done
|
VisZbuf_Destroy(&sGameVisZbuf);
|
||||||
curRDP = sched->curRDPTask;
|
VisMono_Destroy(&sGameVisMono);
|
||||||
sched->curRDPTask = NULL;
|
ViMode_Destroy(&sGameViMode);
|
||||||
curRDP->state &= ~OS_SC_DP;
|
THA_Destroy(&gameState->tha);
|
||||||
|
GameAlloc_Cleanup(&gameState->alloc);
|
||||||
// @recomp Send a message to the dedicated RDP complete message queue if it's currently set up.
|
|
||||||
if (rdp_queue_ptr) {
|
|
||||||
osSendMesg(rdp_queue_ptr, NULL, OS_MESG_BLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sched_NotifyDone(sched, curRDP);
|
|
||||||
|
|
||||||
// Schedule and run next task
|
|
||||||
state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL);
|
|
||||||
if (Sched_Schedule(sched, &nextRSP, &nextRDP, state) != state) {
|
|
||||||
Sched_RunTask(sched, nextRSP, nextRDP);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,3 +25,4 @@ osCreateMesgQueue_recomp = 0x8F000048;
|
||||||
recomp_set_current_frame_poll_id = 0x8F00004C;
|
recomp_set_current_frame_poll_id = 0x8F00004C;
|
||||||
recomp_time_us = 0x8F000050;
|
recomp_time_us = 0x8F000050;
|
||||||
recomp_measure_latency = 0x8F000054;
|
recomp_measure_latency = 0x8F000054;
|
||||||
|
osViGetCurrentFramebuffer_recomp = 0x8F000058;
|
||||||
|
|
|
@ -320,6 +320,7 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern
|
||||||
// is finished as well, so sending this early shouldn't be an issue in most cases.
|
// is finished as well, so sending this early shouldn't be an issue in most cases.
|
||||||
// If this causes issues then the logic can be replaced with responding to yield requests.
|
// If this causes issues then the logic can be replaced with responding to yield requests.
|
||||||
sp_complete();
|
sp_complete();
|
||||||
|
ultramodern::measure_input_latency();
|
||||||
|
|
||||||
auto rt64_start = std::chrono::system_clock::now();
|
auto rt64_start = std::chrono::system_clock::now();
|
||||||
RT64SendDL(rdram, &task_action->task);
|
RT64SendDL(rdram, &task_action->task);
|
||||||
|
|
Loading…
Reference in New Issue