diff --git a/GPU/Common/DepthRaster.cpp b/GPU/Common/DepthRaster.cpp index b3f2a56d20..87255f16a3 100644 --- a/GPU/Common/DepthRaster.cpp +++ b/GPU/Common/DepthRaster.cpp @@ -752,6 +752,10 @@ void DepthRasterWorker::Submit() { void DepthRasterWorker::Wait() { Submit(); + WaitForSubmitted(); +} + +void DepthRasterWorker::WaitForSubmitted() { if (!busy_) { return; } diff --git a/GPU/Common/DepthRaster.h b/GPU/Common/DepthRaster.h index 941da558db..d2baa4f1e0 100644 --- a/GPU/Common/DepthRaster.h +++ b/GPU/Common/DepthRaster.h @@ -93,6 +93,8 @@ public: void Submit(); // Submits the current batch and waits until all are rasterized. void Wait(); + // Waits until the batches already submitted are rasterized. + void WaitForSubmitted(); // Waits only if a batch being rasterized may write to [addr, addr + size). void WaitIfWriting(u32 addr, u32 size); diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 1d23403867..828b353ab1 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -1365,6 +1365,12 @@ void DrawEngineCommon::FlushQueuedDepth() { depthWorker_->TakeTimes(&gpuStats.perFrame.msCullDepth, &gpuStats.perFrame.msRasterizeDepth); } +void DrawEngineCommon::WaitForSubmittedDepth() { + if (depthWorker_) { + depthWorker_->WaitForSubmitted(); + } +} + void DrawEngineCommon::WaitForDepthWrites(u32 addr, u32 size) { if (depthWorker_) { depthWorker_->WaitIfWriting(addr, size); diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 9d7947e6de..5d1f98472b 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -164,6 +164,8 @@ public: void FlushQueuedDepth(); // Starts rasterizing the queued depth draws, without waiting. void SubmitQueuedDepth(); + // Waits for the depth draws already submitted, leaving the queued ones queued. + void WaitForSubmittedDepth(); // Waits if depth rasterization in progress may write to these bytes. void WaitForDepthWrites(u32 addr, u32 size); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2072085c53..aaca88a931 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -908,6 +908,18 @@ inline void GPUCommon::UpdateState(GPURunState state) { // This is now called when coreState == CORE_RUNNING_GE, in addition to from the various sceGe commands. DLResult GPUCommon::ProcessDLQueue() { + const DLResult result = RunDLQueue(); + // Games read the depth buffer back on the CPU once a list has ended, without waiting for the GE + // (Syphon Filter's light flares). So the depth rasterizer has to be done by then. Not at a stall, + // though, which some games hit hundreds of times a frame. + if (listEndedSinceDepthWait_) { + listEndedSinceDepthWait_ = false; + drawEngineCommon_->WaitForSubmittedDepth(); + } + return result; +} + +DLResult GPUCommon::RunDLQueue() { if (!resumingFromDebugBreak_) { startingTicks = CoreTiming::GetTicks(currentMIPS); cyclesExecuted = 0; @@ -1213,6 +1225,7 @@ void GPUCommon::Execute_Ret(u32 op, u32 diff) { void GPUCommon::Execute_End(u32 op, u32 diff) { if (flushOnParams_) { drawEngineCommon_->SubmitQueuedDepth(); + listEndedSinceDepthWait_ = true; Flush(); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 04a57ba4e2..e430196495 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -316,6 +316,7 @@ public: void NotifyFlush(); protected: + DLResult RunDLQueue(); // While debugging is active, these may block. void NotifyDisplay(u32 framebuf, u32 stride, int format); @@ -377,6 +378,7 @@ protected: TextureCacheCommon *textureCache_ = nullptr; bool flushOnParams_ = true; + bool listEndedSinceDepthWait_ = false; GraphicsContext *gfxCtx_; Draw::DrawContext *draw_ = nullptr;