Fixed issue with latency patch not always starting with the correct behavior

This commit is contained in:
Mr-Wiseguy 2024-03-30 22:44:08 -04:00
parent 1651298a2c
commit 31d2424774
3 changed files with 40 additions and 52 deletions

View File

@ -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);
}
} }

View File

@ -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;

View File

@ -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);