lightrec: Detect and speed up GPU status polling
authorPaul Cercueil <paul@crapouillou.net>
Sat, 19 Apr 2025 13:27:02 +0000 (15:27 +0200)
committernotaz <notasas@gmail.com>
Tue, 22 Apr 2025 22:07:18 +0000 (01:07 +0300)
If the GPUSTATUS_POLLING_THRESHOLD macro is set to a value > 0, the
Lightrec glue code will attempt to detect polling of the GPU status
register, with a polling interval in PSX cycles up to the threshold
configured.

This is still quite experimental, hence the reason why it's disabled by
default. However, this gives a huge speed boost (35% and above) when
running on Dreamcast, tested with a threshold value of 350, on games
that don't use the PSX CPU much and spend a lot of time waiting for
VSYNC.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
libpcsxcore/lightrec/plugin.c

index f05012d..3e11265 100644 (file)
 #  endif
 #endif
 
+#ifndef GPUSTATUS_POLLING_THRESHOLD
+#  define GPUSTATUS_POLLING_THRESHOLD 0
+#endif
+
 psxRegisters psxRegs;
 Rcnt rcnts[4];
 
@@ -234,12 +238,30 @@ static u16 hw_read_half(struct lightrec_state *state,
 static u32 hw_read_word(struct lightrec_state *state,
                        u32 op, void *host, u32 mem)
 {
-       u32 val;
+       static u32 old_cycle, oldold_cycle, old_gpusr;
+       u32 val, diff;
 
        lightrec_tansition_to_pcsx(state);
 
        val = psxHwRead32(mem);
 
+       if (GPUSTATUS_POLLING_THRESHOLD > 0 && mem == 0x1f801814) {
+               diff = psxRegs.cycle - old_cycle;
+
+               if (diff > 0
+                   && diff < GPUSTATUS_POLLING_THRESHOLD
+                   && diff == old_cycle - oldold_cycle) {
+                       while (psxRegs.next_interupt > psxRegs.cycle && val == old_gpusr) {
+                               psxRegs.cycle += diff;
+                               val = psxHwRead32(mem);
+                       }
+               }
+
+               oldold_cycle = old_cycle;
+               old_cycle = psxRegs.cycle;
+               old_gpusr = val;
+       }
+
        lightrec_tansition_from_pcsx(state);
 
        return val;