mirror of https://github.com/PCSX2/pcsx2.git
MTVU: Purge pxThread
This commit is contained in:
parent
0ae17ddb1a
commit
599626b709
|
@ -18,8 +18,9 @@
|
|||
#include "MTVU.h"
|
||||
#include "newVif.h"
|
||||
#include "Gif_Unit.h"
|
||||
#include <thread>
|
||||
|
||||
VU_Thread vu1Thread(CpuVU1, VU1);
|
||||
VU_Thread vu1Thread;
|
||||
|
||||
#define MTVU_ALWAYS_KICK 0
|
||||
#define MTVU_SYNC_MODE 0
|
||||
|
@ -86,21 +87,35 @@ void SaveStateBase::mtvuFreeze()
|
|||
Freeze(vu1Thread.vuCycleIdx);
|
||||
}
|
||||
|
||||
VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs)
|
||||
: vuCPU(_vuCPU)
|
||||
, vuRegs(_vuRegs)
|
||||
VU_Thread::VU_Thread()
|
||||
{
|
||||
m_name = L"MTVU";
|
||||
Reset();
|
||||
}
|
||||
|
||||
VU_Thread::~VU_Thread()
|
||||
{
|
||||
try
|
||||
{
|
||||
pxThread::Cancel();
|
||||
Close();
|
||||
}
|
||||
DESTRUCTOR_CATCHALL
|
||||
|
||||
void VU_Thread::Open()
|
||||
{
|
||||
if (m_thread.joinable())
|
||||
return;
|
||||
|
||||
Reset();
|
||||
semaEvent.Reset();
|
||||
m_shutdown_flag.store(false, std::memory_order_release);
|
||||
m_thread = std::thread(&VU_Thread::ExecuteRingBuffer, this);
|
||||
}
|
||||
|
||||
void VU_Thread::Close()
|
||||
{
|
||||
if (!m_thread.joinable())
|
||||
return;
|
||||
|
||||
m_shutdown_flag.store(true, std::memory_order_release);
|
||||
semaEvent.NotifyOfWork();
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
void VU_Thread::Reset()
|
||||
|
@ -117,20 +132,17 @@ void VU_Thread::Reset()
|
|||
vu1Thread.mtvuInterrupts = 0;
|
||||
}
|
||||
|
||||
void VU_Thread::ExecuteTaskInThread()
|
||||
{
|
||||
PCSX2_PAGEFAULT_PROTECT
|
||||
{
|
||||
ExecuteRingBuffer();
|
||||
}
|
||||
PCSX2_PAGEFAULT_EXCEPT;
|
||||
}
|
||||
|
||||
void VU_Thread::ExecuteRingBuffer()
|
||||
{
|
||||
m_thread_handle = Threading::ThreadHandle::GetForCallingThread();
|
||||
Threading::SetNameOfCurrentThread("MTVU");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
semaEvent.WaitForWork();
|
||||
if (m_shutdown_flag.load(std::memory_order_acquire))
|
||||
break;
|
||||
|
||||
while (m_ato_read_pos.load(std::memory_order_relaxed) != GetWritePos())
|
||||
{
|
||||
u32 tag = Read();
|
||||
|
@ -138,18 +150,18 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
{
|
||||
case MTVU_VU_EXECUTE:
|
||||
{
|
||||
vuRegs.cycle = 0;
|
||||
VU1.cycle = 0;
|
||||
s32 addr = Read();
|
||||
vifRegs.top = Read();
|
||||
vifRegs.itop = Read();
|
||||
vuFBRST = Read();
|
||||
if (addr != -1)
|
||||
vuRegs.VI[REG_TPC].UL = addr & 0x7FF;
|
||||
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
|
||||
vuCPU->Execute(vu1RunCycles);
|
||||
VU1.VI[REG_TPC].UL = addr & 0x7FF;
|
||||
CpuVU1->SetStartPC(VU1.VI[REG_TPC].UL << 3);
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
|
||||
semaXGkick.Post(); // Tell MTGS a path1 packet is complete
|
||||
vuCycles[vuCycleIdx].store(vuRegs.cycle, std::memory_order_release);
|
||||
vuCycles[vuCycleIdx].store(VU1.cycle, std::memory_order_release);
|
||||
vuCycleIdx = (vuCycleIdx + 1) & 3;
|
||||
break;
|
||||
}
|
||||
|
@ -157,22 +169,22 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
{
|
||||
u32 vu_micro_addr = Read();
|
||||
u32 size = Read();
|
||||
vuCPU->Clear(vu_micro_addr, size);
|
||||
Read(&vuRegs.Micro[vu_micro_addr], size);
|
||||
CpuVU1->Clear(vu_micro_addr, size);
|
||||
Read(&VU1.Micro[vu_micro_addr], size);
|
||||
break;
|
||||
}
|
||||
case MTVU_VU_WRITE_DATA:
|
||||
{
|
||||
u32 vu_data_addr = Read();
|
||||
u32 size = Read();
|
||||
Read(&vuRegs.Mem[vu_data_addr], size);
|
||||
Read(&VU1.Mem[vu_data_addr], size);
|
||||
break;
|
||||
}
|
||||
case MTVU_VU_WRITE_VIREGS:
|
||||
Read(&vuRegs.VI, size_u32(32));
|
||||
Read(&VU1.VI, size_u32(32));
|
||||
break;
|
||||
case MTVU_VU_WRITE_VFREGS:
|
||||
Read(&vuRegs.VF, size_u32(4*32));
|
||||
Read(&VU1.VF, size_u32(4*32));
|
||||
break;
|
||||
case MTVU_VIF_WRITE_COL:
|
||||
Read(&vif.MaskCol, sizeof(vif.MaskCol));
|
||||
|
@ -199,6 +211,9 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
CommitReadPos();
|
||||
}
|
||||
}
|
||||
|
||||
m_thread_handle = {};
|
||||
semaEvent.Kill();
|
||||
}
|
||||
|
||||
|
||||
|
|
31
pcsx2/MTVU.h
31
pcsx2/MTVU.h
|
@ -14,11 +14,13 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "System/SysThreads.h"
|
||||
#include "common/Threading.h"
|
||||
#include "Vif.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#define MTVU_LOG(...) do{} while(0)
|
||||
//#define MTVU_LOG DevCon.WriteLn
|
||||
|
||||
|
@ -26,7 +28,7 @@
|
|||
// - This class should only be accessed from the EE thread...
|
||||
// - buffer_size must be power of 2
|
||||
// - ring-buffer has no complete pending packets when read_pos==write_pos
|
||||
class VU_Thread : public pxThread {
|
||||
class VU_Thread final {
|
||||
static const s32 buffer_size = (_1mb * 16) / sizeof(s32);
|
||||
|
||||
u32 buffer[buffer_size];
|
||||
|
@ -35,14 +37,16 @@ class VU_Thread : public pxThread {
|
|||
alignas(64) std::atomic<int> m_ato_write_pos; // Only modified by EE thread
|
||||
alignas(64) int m_read_pos; // temporary read pos (local to the VU thread)
|
||||
int m_write_pos; // temporary write pos (local to the EE thread)
|
||||
WorkSema semaEvent;
|
||||
BaseVUmicroCPU*& vuCPU;
|
||||
VURegs& vuRegs;
|
||||
Threading::WorkSema semaEvent;
|
||||
std::atomic_bool m_shutdown_flag{false};
|
||||
|
||||
std::thread m_thread;
|
||||
Threading::ThreadHandle m_thread_handle;
|
||||
|
||||
public:
|
||||
alignas(16) vifStruct vif;
|
||||
alignas(16) VIFregisters vifRegs;
|
||||
Semaphore semaXGkick;
|
||||
Threading::Semaphore semaXGkick;
|
||||
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
|
||||
u32 vuCycleIdx; // Used for VU cycle stealing hack
|
||||
u32 vuFBRST;
|
||||
|
@ -59,8 +63,16 @@ public:
|
|||
std::atomic<u64> gsLabel; // Used for GS Label command
|
||||
std::atomic<u64> gsSignal; // Used for GS Signal command
|
||||
|
||||
VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs);
|
||||
virtual ~VU_Thread();
|
||||
VU_Thread();
|
||||
~VU_Thread();
|
||||
|
||||
__fi const Threading::ThreadHandle& GetThreadHandle() const { return m_thread_handle; }
|
||||
|
||||
/// Ensures the VU thread is started.
|
||||
void Open();
|
||||
|
||||
/// Shuts down the VU thread if it is currently running.
|
||||
void Close();
|
||||
|
||||
void Reset();
|
||||
|
||||
|
@ -93,9 +105,6 @@ public:
|
|||
|
||||
void WriteRow(vifStruct& _vif);
|
||||
|
||||
protected:
|
||||
void ExecuteTaskInThread();
|
||||
|
||||
private:
|
||||
void ExecuteRingBuffer();
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ void PerformanceMetrics::Reset()
|
|||
|
||||
s_last_cpu_time = s_cpu_thread_handle.GetCPUTime();
|
||||
s_last_gs_time = GetMTGS().GetCpuTime();
|
||||
s_last_vu_time = THREAD_VU1 ? vu1Thread.GetCpuTime() : 0;
|
||||
s_last_vu_time = THREAD_VU1 ? vu1Thread.GetThreadHandle().GetCPUTime() : 0;
|
||||
s_last_ticks = GetCPUTicks();
|
||||
|
||||
for (GSSWThreadStats& stat : s_gs_sw_threads)
|
||||
|
@ -184,7 +184,7 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit)
|
|||
|
||||
const u64 cpu_time = s_cpu_thread_handle.GetCPUTime();
|
||||
const u64 gs_time = GetMTGS().GetCpuTime();
|
||||
const u64 vu_time = THREAD_VU1 ? vu1Thread.GetCpuTime() : 0;
|
||||
const u64 vu_time = THREAD_VU1 ? vu1Thread.GetThreadHandle().GetCPUTime() : 0;
|
||||
|
||||
const u64 cpu_delta = cpu_time - s_last_cpu_time;
|
||||
const u64 gs_delta = gs_time - s_last_gs_time;
|
||||
|
|
|
@ -368,8 +368,7 @@ void SysCoreThread::OnCleanupInThread()
|
|||
m_resetVirtualMachine = true;
|
||||
|
||||
R3000A::ioman::reset();
|
||||
// FIXME: temporary workaround for deadlock on exit, which actually should be a crash
|
||||
vu1Thread.WaitVU();
|
||||
vu1Thread.Close();
|
||||
USBclose();
|
||||
SPU2close();
|
||||
PADclose();
|
||||
|
|
|
@ -371,7 +371,7 @@ void recMicroVU1::Reserve()
|
|||
if (m_Reserved.exchange(1) == 0)
|
||||
{
|
||||
mVUinit(microVU1, 1);
|
||||
vu1Thread.Start();
|
||||
vu1Thread.Open();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue