Merge pull request #7214 from stenzek/cp-access-sync

Fifo: Run/sync with the GPU on command processor register access
This commit is contained in:
JMC47 2021-04-18 11:17:25 -04:00 committed by GitHub
commit 821e51cda4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 20 deletions

View File

@ -234,6 +234,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead<u16>([](u32) { mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead<u16>([](u32) {
Fifo::SyncGPUForRegisterAccess();
SetCpStatusRegister(); SetCpStatusRegister();
return m_CPStatusReg.Hex; return m_CPStatusReg.Hex;
}), }),
@ -271,18 +272,21 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance),
WMASK_LO_ALIGN_32BIT)); WMASK_LO_ALIGN_32BIT));
mmio->Register(base | FIFO_RW_DISTANCE_HI, mmio->Register(base | FIFO_RW_DISTANCE_HI,
IsOnThread() ? IsOnThread() ? MMIO::ComplexRead<u16>([](u32) {
MMIO::ComplexRead<u16>([](u32) { Fifo::SyncGPUForRegisterAccess();
if (fifo.CPWritePointer >= fifo.SafeCPReadPointer) if (fifo.CPWritePointer >= fifo.SafeCPReadPointer)
return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer); return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer);
else else
return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer -
fifo.CPBase + 32); fifo.CPBase + 32);
}) : }) :
MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.CPReadWriteDistance)), MMIO::ComplexRead<u16>([](u32) {
Fifo::SyncGPUForRegisterAccess();
return ReadHigh(fifo.CPReadWriteDistance);
}),
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) { MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) {
Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT);
Fifo::SyncGPU(Fifo::SyncGPUReason::Other);
Fifo::RunGpu(); Fifo::RunGpu();
})); }));
mmio->Register( mmio->Register(
@ -290,16 +294,24 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
IsOnThread() ? MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : IsOnThread() ? MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) :
MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer)), MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer)),
MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT));
mmio->Register( mmio->Register(base | FIFO_READ_POINTER_HI,
base | FIFO_READ_POINTER_HI, IsOnThread() ? MMIO::ComplexRead<u16>([](u32) {
IsOnThread() ? MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.SafeCPReadPointer)) : Fifo::SyncGPUForRegisterAccess();
MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.CPReadPointer)), return ReadHigh(fifo.SafeCPReadPointer);
IsOnThread() ? }) :
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) { MMIO::ComplexRead<u16>([](u32) {
WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); Fifo::SyncGPUForRegisterAccess();
fifo.SafeCPReadPointer = fifo.CPReadPointer; return ReadHigh(fifo.CPReadPointer);
}) : }),
MMIO::DirectWrite<u16>(MMIO::Utils::HighPart(&fifo.CPReadPointer), WMASK_HI_RESTRICT)); IsOnThread() ? MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) {
Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT);
fifo.SafeCPReadPointer = fifo.CPReadPointer;
}) :
MMIO::ComplexWrite<u16>([WMASK_HI_RESTRICT](u32, u16 val) {
Fifo::SyncGPUForRegisterAccess();
WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT);
}));
} }
void GatherPipeBursted() void GatherPipeBursted()

View File

@ -580,6 +580,16 @@ static void SyncGPUCallback(u64 ticks, s64 cyclesLate)
CoreTiming::ScheduleEvent(next, s_event_sync_gpu, next); CoreTiming::ScheduleEvent(next, s_event_sync_gpu, next);
} }
void SyncGPUForRegisterAccess()
{
SyncGPU(SyncGPUReason::Other);
if (!SConfig::GetInstance().bCPUThread || s_use_deterministic_gpu_thread)
RunGpuOnCpu(GPU_TIME_SLOT_SIZE);
else if (SConfig::GetInstance().bSyncGPU)
WaitForGpuThread(GPU_TIME_SLOT_SIZE);
}
// Initialize GPU - CPU thread syncing, this gives us a deterministic way to start the GPU thread. // Initialize GPU - CPU thread syncing, this gives us a deterministic way to start the GPU thread.
void Prepare() void Prepare()
{ {

View File

@ -33,6 +33,10 @@ enum class SyncGPUReason
// In deterministic GPU thread mode this waits for the GPU to be done with pending work. // In deterministic GPU thread mode this waits for the GPU to be done with pending work.
void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr = true); void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr = true);
// In single core mode, this runs the GPU for a single slice.
// In dual core mode, this synchronizes with the GPU thread.
void SyncGPUForRegisterAccess();
void PushFifoAuxBuffer(const void* ptr, size_t size); void PushFifoAuxBuffer(const void* ptr, size_t size);
void* PopFifoAuxBuffer(size_t size); void* PopFifoAuxBuffer(size_t size);