MTVU: Purge pxThread

This commit is contained in:
Connor McLaughlin 2022-05-05 07:55:16 +10:00 committed by refractionpcsx2
parent 0ae17ddb1a
commit 599626b709
5 changed files with 68 additions and 45 deletions

View File

@ -18,8 +18,9 @@
#include "MTVU.h" #include "MTVU.h"
#include "newVif.h" #include "newVif.h"
#include "Gif_Unit.h" #include "Gif_Unit.h"
#include <thread>
VU_Thread vu1Thread(CpuVU1, VU1); VU_Thread vu1Thread;
#define MTVU_ALWAYS_KICK 0 #define MTVU_ALWAYS_KICK 0
#define MTVU_SYNC_MODE 0 #define MTVU_SYNC_MODE 0
@ -86,21 +87,35 @@ void SaveStateBase::mtvuFreeze()
Freeze(vu1Thread.vuCycleIdx); Freeze(vu1Thread.vuCycleIdx);
} }
VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) VU_Thread::VU_Thread()
: vuCPU(_vuCPU)
, vuRegs(_vuRegs)
{ {
m_name = L"MTVU";
Reset(); Reset();
} }
VU_Thread::~VU_Thread() VU_Thread::~VU_Thread()
{ {
try Close();
{ }
pxThread::Cancel();
} void VU_Thread::Open()
DESTRUCTOR_CATCHALL {
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() void VU_Thread::Reset()
@ -117,20 +132,17 @@ void VU_Thread::Reset()
vu1Thread.mtvuInterrupts = 0; vu1Thread.mtvuInterrupts = 0;
} }
void VU_Thread::ExecuteTaskInThread()
{
PCSX2_PAGEFAULT_PROTECT
{
ExecuteRingBuffer();
}
PCSX2_PAGEFAULT_EXCEPT;
}
void VU_Thread::ExecuteRingBuffer() void VU_Thread::ExecuteRingBuffer()
{ {
m_thread_handle = Threading::ThreadHandle::GetForCallingThread();
Threading::SetNameOfCurrentThread("MTVU");
for (;;) for (;;)
{ {
semaEvent.WaitForWork(); semaEvent.WaitForWork();
if (m_shutdown_flag.load(std::memory_order_acquire))
break;
while (m_ato_read_pos.load(std::memory_order_relaxed) != GetWritePos()) while (m_ato_read_pos.load(std::memory_order_relaxed) != GetWritePos())
{ {
u32 tag = Read(); u32 tag = Read();
@ -138,18 +150,18 @@ void VU_Thread::ExecuteRingBuffer()
{ {
case MTVU_VU_EXECUTE: case MTVU_VU_EXECUTE:
{ {
vuRegs.cycle = 0; VU1.cycle = 0;
s32 addr = Read(); s32 addr = Read();
vifRegs.top = Read(); vifRegs.top = Read();
vifRegs.itop = Read(); vifRegs.itop = Read();
vuFBRST = Read(); vuFBRST = Read();
if (addr != -1) if (addr != -1)
vuRegs.VI[REG_TPC].UL = addr & 0x7FF; VU1.VI[REG_TPC].UL = addr & 0x7FF;
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3); CpuVU1->SetStartPC(VU1.VI[REG_TPC].UL << 3);
vuCPU->Execute(vu1RunCycles); CpuVU1->Execute(vu1RunCycles);
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU(); gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
semaXGkick.Post(); // Tell MTGS a path1 packet is complete 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; vuCycleIdx = (vuCycleIdx + 1) & 3;
break; break;
} }
@ -157,22 +169,22 @@ void VU_Thread::ExecuteRingBuffer()
{ {
u32 vu_micro_addr = Read(); u32 vu_micro_addr = Read();
u32 size = Read(); u32 size = Read();
vuCPU->Clear(vu_micro_addr, size); CpuVU1->Clear(vu_micro_addr, size);
Read(&vuRegs.Micro[vu_micro_addr], size); Read(&VU1.Micro[vu_micro_addr], size);
break; break;
} }
case MTVU_VU_WRITE_DATA: case MTVU_VU_WRITE_DATA:
{ {
u32 vu_data_addr = Read(); u32 vu_data_addr = Read();
u32 size = Read(); u32 size = Read();
Read(&vuRegs.Mem[vu_data_addr], size); Read(&VU1.Mem[vu_data_addr], size);
break; break;
} }
case MTVU_VU_WRITE_VIREGS: case MTVU_VU_WRITE_VIREGS:
Read(&vuRegs.VI, size_u32(32)); Read(&VU1.VI, size_u32(32));
break; break;
case MTVU_VU_WRITE_VFREGS: case MTVU_VU_WRITE_VFREGS:
Read(&vuRegs.VF, size_u32(4*32)); Read(&VU1.VF, size_u32(4*32));
break; break;
case MTVU_VIF_WRITE_COL: case MTVU_VIF_WRITE_COL:
Read(&vif.MaskCol, sizeof(vif.MaskCol)); Read(&vif.MaskCol, sizeof(vif.MaskCol));
@ -199,6 +211,9 @@ void VU_Thread::ExecuteRingBuffer()
CommitReadPos(); CommitReadPos();
} }
} }
m_thread_handle = {};
semaEvent.Kill();
} }

View File

@ -14,11 +14,13 @@
*/ */
#pragma once #pragma once
#include "System/SysThreads.h" #include "common/Threading.h"
#include "Vif.h" #include "Vif.h"
#include "Vif_Dma.h" #include "Vif_Dma.h"
#include "VUmicro.h" #include "VUmicro.h"
#include <thread>
#define MTVU_LOG(...) do{} while(0) #define MTVU_LOG(...) do{} while(0)
//#define MTVU_LOG DevCon.WriteLn //#define MTVU_LOG DevCon.WriteLn
@ -26,7 +28,7 @@
// - This class should only be accessed from the EE thread... // - This class should only be accessed from the EE thread...
// - buffer_size must be power of 2 // - buffer_size must be power of 2
// - ring-buffer has no complete pending packets when read_pos==write_pos // - 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); static const s32 buffer_size = (_1mb * 16) / sizeof(s32);
u32 buffer[buffer_size]; 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) 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) 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) int m_write_pos; // temporary write pos (local to the EE thread)
WorkSema semaEvent; Threading::WorkSema semaEvent;
BaseVUmicroCPU*& vuCPU; std::atomic_bool m_shutdown_flag{false};
VURegs& vuRegs;
std::thread m_thread;
Threading::ThreadHandle m_thread_handle;
public: public:
alignas(16) vifStruct vif; alignas(16) vifStruct vif;
alignas(16) VIFregisters vifRegs; alignas(16) VIFregisters vifRegs;
Semaphore semaXGkick; Threading::Semaphore semaXGkick;
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
u32 vuCycleIdx; // Used for VU cycle stealing hack u32 vuCycleIdx; // Used for VU cycle stealing hack
u32 vuFBRST; u32 vuFBRST;
@ -59,8 +63,16 @@ public:
std::atomic<u64> gsLabel; // Used for GS Label command std::atomic<u64> gsLabel; // Used for GS Label command
std::atomic<u64> gsSignal; // Used for GS Signal command std::atomic<u64> gsSignal; // Used for GS Signal command
VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs); VU_Thread();
virtual ~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(); void Reset();
@ -93,9 +105,6 @@ public:
void WriteRow(vifStruct& _vif); void WriteRow(vifStruct& _vif);
protected:
void ExecuteTaskInThread();
private: private:
void ExecuteRingBuffer(); void ExecuteRingBuffer();

View File

@ -119,7 +119,7 @@ void PerformanceMetrics::Reset()
s_last_cpu_time = s_cpu_thread_handle.GetCPUTime(); s_last_cpu_time = s_cpu_thread_handle.GetCPUTime();
s_last_gs_time = GetMTGS().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(); s_last_ticks = GetCPUTicks();
for (GSSWThreadStats& stat : s_gs_sw_threads) 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 cpu_time = s_cpu_thread_handle.GetCPUTime();
const u64 gs_time = GetMTGS().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 cpu_delta = cpu_time - s_last_cpu_time;
const u64 gs_delta = gs_time - s_last_gs_time; const u64 gs_delta = gs_time - s_last_gs_time;

View File

@ -368,8 +368,7 @@ void SysCoreThread::OnCleanupInThread()
m_resetVirtualMachine = true; m_resetVirtualMachine = true;
R3000A::ioman::reset(); R3000A::ioman::reset();
// FIXME: temporary workaround for deadlock on exit, which actually should be a crash vu1Thread.Close();
vu1Thread.WaitVU();
USBclose(); USBclose();
SPU2close(); SPU2close();
PADclose(); PADclose();

View File

@ -371,7 +371,7 @@ void recMicroVU1::Reserve()
if (m_Reserved.exchange(1) == 0) if (m_Reserved.exchange(1) == 0)
{ {
mVUinit(microVU1, 1); mVUinit(microVU1, 1);
vu1Thread.Start(); vu1Thread.Open();
} }
} }