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 "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
void BaseVUmicroCPU::ExecuteBlock(bool startUp)
{
@ -57,12 +70,12 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
if (EmuConfig.Gamefixes.VUKickstartHack)
{
if (delta > 0) // When kickstarting we just need 1 cycle for run ahead
Execute(delta);
Execute(CalculateMinRunCycles(delta, false));
}
else
{
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
// to ensure that the register is used at the correct time.
// 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 int test = 1;
@ -83,7 +96,7 @@ void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu)
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)
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
// 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 u32 target; // branch target
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; }
u32 s_nBlockCycles = 0; // cycles of current block recompiling
bool s_nBlockInterlocked = false; // Block is VU0 interlocked
u32 pc; // recompiler pc
int g_branch; // set for branch
@ -1927,6 +1927,7 @@ static void __fastcall recRecompile(const u32 startpc)
// reset recomp state variables
s_nBlockCycles = 0;
s_nBlockInterlocked = false;
pc = startpc;
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
pxAssert(g_cpuConstRegs[0].UD[0] == 0);

View File

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

View File

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