mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Threading VU1 took a lot of rewrites and new code to make possible (MTGS, microVU, gifUnit...), but we finally got to the point where it was feasible, and now we've done it! (so now everyone can stop complaining that pcsx2 only takes advantages of 2 cores :p). The speedups in the games that benefit from it are great if you have a cpu with 3+ cores (generally a 10~45% speedup), however games that are GS limited can be a slowdown (especially on dual core cpu's). The option can be found in the speedhacks section as "MTVU (Multi-Threaded microVU1)". And when enabled it should should show the VU thread-time percentage on the title bar window (Like we currently do for EE/GS/UI threads). It is listed as a speedhack because in order for threading VU1 to have been a speedup, we need to assume that games will not send gif packets containing Signal/Finish/Label commands from path 1 (vu1's xgkick). The good news is very-few games ever do this, so the compatibility of MTVU is very high (a game that does do this will likely hang). Note: vs2010 builds and Linux builds need to be updated to include "MTVU.h" and "MTVU.cpp". git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4865 96395faa-99c1-11dd-bbfe-3dabce05a288
120 lines
3.7 KiB
C++
120 lines
3.7 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "PrecompiledHeader.h"
|
|
#include "Common.h"
|
|
|
|
#include "GS.h"
|
|
#include "Gif_Unit.h"
|
|
#include "Vif.h"
|
|
#include "Vif_Dma.h"
|
|
#include "IPU/IPU.h"
|
|
#include "IPU/IPU_Fifo.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////// Quick & dirty FIFO :D ////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Notes on FIFO implementation
|
|
//
|
|
// The FIFO consists of four separate pages of HW register memory, each mapped to a
|
|
// PS2 device. They are listed as follows:
|
|
//
|
|
// 0x4000 - 0x5000 : VIF0 (all registers map to 0x4000)
|
|
// 0x5000 - 0x6000 : VIF1 (all registers map to 0x5000)
|
|
// 0x6000 - 0x7000 : GS (all registers map to 0x6000)
|
|
// 0x7000 - 0x8000 : IPU (registers map to 0x7000 and 0x7010, respectively)
|
|
|
|
void __fastcall ReadFIFO_VIF1(mem128_t* out)
|
|
{
|
|
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) )
|
|
DevCon.Warning( "Reading from vif1 fifo when stalled" );
|
|
|
|
ZeroQWC(out); // Clear first in case no data gets written...
|
|
pxAssertRel(vif1Regs.stat.FQC != 0, "FQC = 0 on VIF FIFO READ!");
|
|
if (vif1Regs.stat.FDR) {
|
|
if (vif1Regs.stat.FQC > vif1.GSLastDownloadSize) {
|
|
DevCon.Warning("Warning! GS Download size < FIFO count!");
|
|
}
|
|
if (vif1Regs.stat.FQC > 0) {
|
|
GetMTGS().WaitGS();
|
|
GSreadFIFO((u64*)out);
|
|
vif1.GSLastDownloadSize--;
|
|
GUNIT_LOG("ReadFIFO_VIF1");
|
|
if (vif1.GSLastDownloadSize <= 16)
|
|
gifRegs.stat.OPH = false;
|
|
vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
|
|
}
|
|
}
|
|
|
|
VIF_LOG("ReadFIFO/VIF1 -> %ls", out->ToString().c_str());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// WriteFIFO Pages
|
|
//
|
|
void __fastcall WriteFIFO_VIF0(const mem128_t *value)
|
|
{
|
|
VIF_LOG("WriteFIFO/VIF0 <- %ls", value->ToString().c_str());
|
|
|
|
vif0ch.qwc += 1;
|
|
if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!");
|
|
bool ret = VIF0transfer((u32*)value, 4);
|
|
|
|
if (vif0.cmd)
|
|
{
|
|
if(vif0.done && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
|
|
}
|
|
else
|
|
{
|
|
vif0Regs.stat.VPS = VPS_IDLE;
|
|
}
|
|
|
|
pxAssertDev( ret, "vif stall code not implemented" );
|
|
}
|
|
|
|
void __fastcall WriteFIFO_VIF1(const mem128_t *value)
|
|
{
|
|
VIF_LOG("WriteFIFO/VIF1 <- %ls", value->ToString().c_str());
|
|
|
|
if (vif1Regs.stat.FDR) {
|
|
DevCon.Warning("writing to fifo when fdr is set!");
|
|
}
|
|
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) ) {
|
|
DevCon.Warning("writing to vif1 fifo when stalled");
|
|
}
|
|
if (vif1.irqoffset != 0 && vif1.vifstalled == true) {
|
|
DevCon.Warning("Offset on VIF1 FIFO start!");
|
|
}
|
|
|
|
vif1ch.qwc += 1;
|
|
|
|
bool ret = VIF1transfer((u32*)value, 4);
|
|
|
|
if (vif1.cmd) {
|
|
if (vif1.done && !vif1ch.qwc) vif1Regs.stat.VPS = VPS_WAITING;
|
|
}
|
|
else vif1Regs.stat.VPS = VPS_IDLE;
|
|
|
|
pxAssertDev( ret, "vif stall code not implemented" );
|
|
}
|
|
|
|
void __fastcall WriteFIFO_GIF(const mem128_t *value)
|
|
{
|
|
GUNIT_LOG("WriteFIFO_GIF()");
|
|
gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16);
|
|
}
|