diff --git a/pcsx2-qt/Settings/SystemSettingsWidget.cpp b/pcsx2-qt/Settings/SystemSettingsWidget.cpp index 5fa97237c3..2c2ce7609b 100644 --- a/pcsx2-qt/Settings/SystemSettingsWidget.cpp +++ b/pcsx2-qt/Settings/SystemSettingsWidget.cpp @@ -89,7 +89,7 @@ SystemSettingsWidget::SystemSettingsWidget(SettingsDialog* dialog, QWidget* pare "Safe for most games, but a few are incompatible and may hang.")); dialog->registerWidgetHelp(m_ui.instantVU1, tr("Instant VU1"), tr("Checked"), - tr("Runs VU1 instantly (when MTVU is disabled). Provides a modest speed improvement. " + tr("Runs VU1 instantly. Provides a modest speed improvement in most games. " "Safe for most games, but a few games may exhibit graphical errors.")); dialog->registerWidgetHelp(m_ui.fastCDVD, tr("Enable Fast CDVD"), tr("Unchecked"), @@ -103,7 +103,7 @@ SystemSettingsWidget::~SystemSettingsWidget() = default; void SystemSettingsWidget::updateVU1InstantState() { - m_ui.instantVU1->setEnabled(!m_dialog->getEffectiveBoolValue("EmuCore/Speedhacks", "vuThread", false)); + //m_ui.instantVU1->setEnabled(!m_dialog->getEffectiveBoolValue("EmuCore/Speedhacks", "vuThread", false)); } int SystemSettingsWidget::getGlobalClampingModeIndex(bool vu) const diff --git a/pcsx2/MTVU.cpp b/pcsx2/MTVU.cpp index f1c9c323fc..a058f95502 100644 --- a/pcsx2/MTVU.cpp +++ b/pcsx2/MTVU.cpp @@ -416,7 +416,8 @@ void VU_Thread::Get_MTVUChanges() { mtvuInterrupts.fetch_and(~InterruptFlagVUEBit, std::memory_order_relaxed); - VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; + if(!INSTANT_VU1) + VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; //DevCon.Warning("E-Bit registered %x", VU0.VI[REG_VPU_STAT].UL); } if (interrupts & InterruptFlagVUTBit) @@ -458,10 +459,17 @@ void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop, u32 fbrst) CommitWritePos(); gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0); KickStart(); - u32 cycles = std::min(Get_vuCycles(), 3000u); - cpuRegs.cycle += cycles * EmuConfig.Speedhacks.EECycleSkip; - VU0.cycle += cycles * EmuConfig.Speedhacks.EECycleSkip; + u32 cycles = std::max(Get_vuCycles(), 4u); + u32 skip_cycles = std::min(cycles, 3000u); + cpuRegs.cycle += skip_cycles * EmuConfig.Speedhacks.EECycleSkip; + VU0.cycle += skip_cycles * EmuConfig.Speedhacks.EECycleSkip; Get_MTVUChanges(); + + if (!INSTANT_VU1) + { + VU0.VI[REG_VPU_STAT].UL |= 0x100; + CPU_INT(VU_MTVU_BUSY, cycles); + } } void VU_Thread::VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size) diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 57d2e3133c..7a6692fff3 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -246,6 +246,13 @@ __fi void cpuSetNextEventDelta( s32 delta ) cpuSetNextEvent( cpuRegs.cycle, delta ); } +__fi int cpuGetCycles(int interrupt) +{ + int cycles = (cpuRegs.sCycle[interrupt] + cpuRegs.eCycle[interrupt]) - cpuRegs.cycle; + + return std::max(1, cycles); +} + // tests the cpu cycle against the given start and delta values. // Returns true if the delta time has passed. __fi int cpuTestCycle( u32 startCycle, s32 delta ) @@ -292,7 +299,7 @@ static __fi void _cpuTestInterrupts() } /* These are 'pcsx2 interrupts', they handle asynchronous stuff that depends on the cycle timings */ - + TESTINT(VU_MTVU_BUSY, MTVUInterrupt); TESTINT(DMAC_VIF1, vif1Interrupt); TESTINT(DMAC_GIF, gifInterrupt); TESTINT(DMAC_SIF0, EEsif0Interrupt); diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index e5d480bca0..4de17e5f97 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -415,7 +415,8 @@ enum EE_EventType DMAC_GIF_UNIT, VIF_VU0_FINISH, VIF_VU1_FINISH, - IPU_PROCESS + IPU_PROCESS, + VU_MTVU_BUSY }; extern void CPU_INT( EE_EventType n, s32 ecycle ); @@ -435,6 +436,7 @@ extern void cpuSetNextEvent( u32 startCycle, s32 delta ); extern void cpuSetNextEventDelta( s32 delta ); extern int cpuTestCycle( u32 startCycle, s32 delta ); extern void cpuSetEvent(); +extern int cpuGetCycles(int interrupt); extern void _cpuEventTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900: diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index 3f28d04395..5f429fab20 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -70,7 +70,6 @@ void vu1ExecMicro(u32 addr) // VU0.VI[REG_VPU_STAT].UL |= 0x0100; // } // Update 25/06/2022: Disabled this for now, let games YOLO it, if it breaks MTVU, disable MTVU (it doesn't work properly anyway) - Refraction - vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop, VU0.VI[REG_FBRST].UL); return; } @@ -90,3 +89,8 @@ void vu1ExecMicro(u32 addr) else CpuVU1->Execute(vu1RunCycles); } + +void MTVUInterrupt() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xFF00; +} diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index 27b3cab850..572ce77850 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -256,6 +256,7 @@ extern void vu1ResetRegs(); extern void vu1ExecMicro(u32 addr); extern void vu1Exec(VURegs* VU); extern void iDumpVU1Registers(); +extern void MTVUInterrupt(); #ifdef VUM_LOG diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 91ba82fcf2..ef98d45e00 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -238,7 +238,10 @@ __fi void vif1VUFinish() u32 _cycles = VU1.cycle; //DevCon.Warning("Finishing VU1"); vu1Finish(false); - CPU_INT(VIF_VU1_FINISH, VU1.cycle - _cycles); + if (THREAD_VU1 && !INSTANT_VU1 && (VU0.VI[REG_VPU_STAT].UL & 0x100)) + CPU_INT(VIF_VU1_FINISH, cpuGetCycles(VU_MTVU_BUSY)); + else + CPU_INT(VIF_VU1_FINISH, VU1.cycle - _cycles); return; } diff --git a/pcsx2/gui/Panels/SpeedhacksPanel.cpp b/pcsx2/gui/Panels/SpeedhacksPanel.cpp index ef07938e32..4b0298fcda 100644 --- a/pcsx2/gui/Panels/SpeedhacksPanel.cpp +++ b/pcsx2/gui/Panels/SpeedhacksPanel.cpp @@ -167,7 +167,7 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) m_check_vuThread = new pxCheckBox( vuHacksPanel, _("MTVU (Multi-Threaded microVU1)"), _("Good Speedup and High Compatibility; may cause hanging... [Recommended on 3+ cores]") ); - m_check_vu1Instant = new pxCheckBox(vuHacksPanel, _("Instant VU1 (without MTVU only)"), + m_check_vu1Instant = new pxCheckBox(vuHacksPanel, _("Instant VU1"), _("Good Speedup and High Compatibility; may cause some graphical errors")); m_check_vuFlagHack->SetToolTip( pxEt( L"Updates Status Flags only on blocks which will read them, instead of all the time. This is safe most of the time." @@ -176,7 +176,7 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) m_check_vuThread->SetToolTip( pxEt( L"Runs VU1 on its own thread (microVU1-only). Generally a speedup on CPUs with 3 or more cores. This is safe for most games, but a few games are incompatible and may hang. In the case of GS limited games, it may be a slowdown (especially on dual core CPUs)." ) ); - m_check_vu1Instant->SetToolTip(pxEt(L"Runs VU1 instantly (when MTVU is disabled). Provides a modest speed improvement. This is safe for most games, but a few games may exhibit graphical errors." + m_check_vu1Instant->SetToolTip(pxEt(L"Runs VU1 instantly. Provides a modest speed improvement in most games. This is safe for most games, but a few games may exhibit graphical errors." )); // ------------------------------------------------------------------------ @@ -270,7 +270,7 @@ void Panels::SpeedHacksPanel::EnableStuff( AppConfig* configToUse ) // Disables the Instant VU1 checkbox when MTVU is checked in the GUI as reflected in the code. // Makes Instant VU1 toggleable when MTVU is unchecked in the GUI. // Some may think that having MTVU + Instant VU1 checked, can have bad side-effects when it doesn't. - m_check_vu1Instant->Enable(hacksEnabled && !m_check_vuThread->GetValue()); + //m_check_vu1Instant->Enable(hacksEnabled && !m_check_vuThread->GetValue()); // Layout necessary to ensure changed slider text gets re-aligned properly // and to properly gray/ungray pxStaticText stuff (I suspect it causes a