VU: Run sync ahead on small blocks

This commit is contained in:
refractionpcsx2 2022-02-27 17:20:40 +00:00
parent eabda670ac
commit 6dc5087cbd
6 changed files with 36 additions and 13 deletions

View File

@ -20,6 +20,19 @@
#include "GS.h" #include "GS.h"
#include "Gif_Unit.h" #include "Gif_Unit.h"
__inline u32 CalculateMinRunCycles(u32 cycles, bool requiresAccurateCycles)
{
// If we're running an interlocked COP2 operation
// run for an exact amount of cycles
if(requiresAccurateCycles)
return cycles;
// Allow a minimum of 16 cycles to avoid running small blocks
// Running a block of like 3 cycles is highly inefficient
// so while sync isn't tight, it's okay to run ahead a little bit.
return std::max(16U, cycles);
}
// Executes a Block based on EE delta time // Executes a Block based on EE delta time
void BaseVUmicroCPU::ExecuteBlock(bool startUp) void BaseVUmicroCPU::ExecuteBlock(bool startUp)
{ {
@ -57,12 +70,12 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
if (EmuConfig.Gamefixes.VUKickstartHack) if (EmuConfig.Gamefixes.VUKickstartHack)
{ {
if (delta > 0) // When kickstarting we just need 1 cycle for run ahead if (delta > 0) // When kickstarting we just need 1 cycle for run ahead
Execute(delta); Execute(CalculateMinRunCycles(delta, false));
} }
else else
{ {
if (delta >= nextblockcycles && delta > 0) // When running behind, make sure we have enough cycles passed for the block to run if (delta >= nextblockcycles && delta > 0) // When running behind, make sure we have enough cycles passed for the block to run
Execute(delta); Execute(CalculateMinRunCycles(delta, false));
} }
} }
} }
@ -71,7 +84,7 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
// EE data to VU0's registers. We want to run VU0 Micro right after this // EE data to VU0's registers. We want to run VU0 Micro right after this
// to ensure that the register is used at the correct time. // to ensure that the register is used at the correct time.
// This fixes spinning/hanging in some games like Ratchet and Clank's Intro. // This fixes spinning/hanging in some games like Ratchet and Clank's Intro.
void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu) void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu, bool interlocked)
{ {
const u32& stat = VU0.VI[REG_VPU_STAT].UL; const u32& stat = VU0.VI[REG_VPU_STAT].UL;
const int test = 1; const int test = 1;
@ -83,7 +96,7 @@ void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu)
if (delta > 0) if (delta > 0)
{ {
cpu->Execute(delta); // Execute the time since the last call cpu->Execute(CalculateMinRunCycles(delta, interlocked)); // Execute the time since the last call
} }
} }
} }

View File

@ -147,7 +147,7 @@ public:
// Executes a Block based on EE delta time (see VUmicro.cpp) // Executes a Block based on EE delta time (see VUmicro.cpp)
virtual void ExecuteBlock(bool startUp=0); virtual void ExecuteBlock(bool startUp=0);
static void __fastcall ExecuteBlockJIT(BaseVUmicroCPU* cpu); static void __fastcall ExecuteBlockJIT(BaseVUmicroCPU* cpu, bool interlocked);
// VU1 sometimes needs to break execution on XGkick Path1 transfers if // VU1 sometimes needs to break execution on XGkick Path1 transfers if
// there is another gif path 2/3 transfer already taking place. // there is another gif path 2/3 transfer already taking place.

View File

@ -27,6 +27,7 @@ extern u32 pc; // recompiler pc
extern int g_branch; // set for branch extern int g_branch; // set for branch
extern u32 target; // branch target extern u32 target; // branch target
extern u32 s_nBlockCycles; // cycles of current block recompiling extern u32 s_nBlockCycles; // cycles of current block recompiling
extern bool s_nBlockInterlocked; // Current block has VU0 interlocking
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //

View File

@ -61,7 +61,7 @@ alignas(16) static u32 hwLUT[_64kb];
static __fi u32 HWADDR(u32 mem) { return hwLUT[mem >> 16] + mem; } static __fi u32 HWADDR(u32 mem) { return hwLUT[mem >> 16] + mem; }
u32 s_nBlockCycles = 0; // cycles of current block recompiling u32 s_nBlockCycles = 0; // cycles of current block recompiling
bool s_nBlockInterlocked = false; // Block is VU0 interlocked
u32 pc; // recompiler pc u32 pc; // recompiler pc
int g_branch; // set for branch int g_branch; // set for branch
@ -1927,6 +1927,7 @@ static void __fastcall recRecompile(const u32 startpc)
// reset recomp state variables // reset recomp state variables
s_nBlockCycles = 0; s_nBlockCycles = 0;
s_nBlockInterlocked = false;
pc = startpc; pc = startpc;
g_cpuHasConstReg = g_cpuFlushedConstReg = 1; g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
pxAssert(g_cpuConstRegs[0].UD[0] == 0); pxAssert(g_cpuConstRegs[0].UD[0] == 0);

View File

@ -963,7 +963,8 @@ void recLQC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();
@ -1012,7 +1013,8 @@ void recSQC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();

View File

@ -327,6 +327,7 @@ void COP2_Interlock(bool mBitSync)
if (cpuRegs.code & 1) if (cpuRegs.code & 1)
{ {
s_nBlockInterlocked = true;
_freeX86reg(eax); _freeX86reg(eax);
xMOV(eax, ptr32[&cpuRegs.cycle]); xMOV(eax, ptr32[&cpuRegs.cycle]);
xADD(eax, scaleblockcycles_clear()); xADD(eax, scaleblockcycles_clear());
@ -342,7 +343,8 @@ void COP2_Interlock(bool mBitSync)
xCMP(eax, 0); xCMP(eax, 0);
xForwardJL32 skip; xForwardJL32 skip;
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
skip.SetTarget(); skip.SetTarget();
xFastCall((void*)_vu0WaitMicro); xFastCall((void*)_vu0WaitMicro);
@ -387,7 +389,8 @@ static void recCFC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();
@ -449,7 +452,8 @@ static void recCTC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();
@ -551,7 +555,8 @@ static void recQMFC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();
@ -591,7 +596,8 @@ static void recQMTC2()
xForwardJL32 skip; xForwardJL32 skip;
_cop2BackupRegs(); _cop2BackupRegs();
xLoadFarAddr(arg1reg, CpuVU0); xLoadFarAddr(arg1reg, CpuVU0);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); xMOV(arg2reg, s_nBlockInterlocked);
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
_cop2RestoreRegs(); _cop2RestoreRegs();
skip.SetTarget(); skip.SetTarget();
skipvuidle.SetTarget(); skipvuidle.SetTarget();