diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 4694860787..0ad2bf2cea 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -234,6 +234,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) } mmio->Register(base | STATUS_REGISTER, MMIO::ComplexRead([](u32) { + Fifo::SyncGPUForRegisterAccess(); SetCpStatusRegister(); return m_CPStatusReg.Hex; }), @@ -271,18 +272,21 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), WMASK_LO_ALIGN_32BIT)); mmio->Register(base | FIFO_RW_DISTANCE_HI, - IsOnThread() ? - MMIO::ComplexRead([](u32) { - if (fifo.CPWritePointer >= fifo.SafeCPReadPointer) - return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer); - else - return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - - fifo.CPBase + 32); - }) : - MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.CPReadWriteDistance)), + IsOnThread() ? MMIO::ComplexRead([](u32) { + Fifo::SyncGPUForRegisterAccess(); + if (fifo.CPWritePointer >= fifo.SafeCPReadPointer) + return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer); + else + return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - + fifo.CPBase + 32); + }) : + MMIO::ComplexRead([](u32) { + Fifo::SyncGPUForRegisterAccess(); + return ReadHigh(fifo.CPReadWriteDistance); + }), MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); WriteHigh(fifo.CPReadWriteDistance, val & WMASK_HI_RESTRICT); - Fifo::SyncGPU(Fifo::SyncGPUReason::Other); Fifo::RunGpu(); })); mmio->Register( @@ -290,16 +294,24 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) IsOnThread() ? MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer)) : MMIO::DirectRead(MMIO::Utils::LowPart(&fifo.CPReadPointer)), MMIO::DirectWrite(MMIO::Utils::LowPart(&fifo.CPReadPointer), WMASK_LO_ALIGN_32BIT)); - mmio->Register( - base | FIFO_READ_POINTER_HI, - IsOnThread() ? MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.SafeCPReadPointer)) : - MMIO::DirectRead(MMIO::Utils::HighPart(&fifo.CPReadPointer)), - IsOnThread() ? - MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { - WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); - fifo.SafeCPReadPointer = fifo.CPReadPointer; - }) : - MMIO::DirectWrite(MMIO::Utils::HighPart(&fifo.CPReadPointer), WMASK_HI_RESTRICT)); + mmio->Register(base | FIFO_READ_POINTER_HI, + IsOnThread() ? MMIO::ComplexRead([](u32) { + Fifo::SyncGPUForRegisterAccess(); + return ReadHigh(fifo.SafeCPReadPointer); + }) : + MMIO::ComplexRead([](u32) { + Fifo::SyncGPUForRegisterAccess(); + return ReadHigh(fifo.CPReadPointer); + }), + IsOnThread() ? MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + fifo.SafeCPReadPointer = fifo.CPReadPointer; + }) : + MMIO::ComplexWrite([WMASK_HI_RESTRICT](u32, u16 val) { + Fifo::SyncGPUForRegisterAccess(); + WriteHigh(fifo.CPReadPointer, val & WMASK_HI_RESTRICT); + })); } void GatherPipeBursted() diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 57dcb07c85..5aede12b96 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -580,6 +580,16 @@ static void SyncGPUCallback(u64 ticks, s64 cyclesLate) 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. void Prepare() { diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index dfdf43a157..9b454a6849 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -33,6 +33,10 @@ enum class SyncGPUReason // 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); +// 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* PopFifoAuxBuffer(size_t size);