From 028a341cc8f5715f764291c8c24c118c0a7cf260 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Sep 2022 16:28:15 -0700 Subject: [PATCH] softgpu: Explicitly flush on sync and output. We could in theory skip flush on FinishDeferred, and allow some CPU/GPU overlap. If we did, we'd still want to flush at these times. --- GPU/Software/SoftGpu.cpp | 13 +++++++++++++ GPU/Software/SoftGpu.h | 2 ++ GPU/Software/TransformUnit.cpp | 8 ++++++++ GPU/Software/TransformUnit.h | 1 + 4 files changed, 24 insertions(+) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 9de5fe5cbd..48c5258cd5 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -639,6 +639,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { } void SoftGPU::CopyDisplayToOutput(bool reallyDirty) { + drawEngine_->transformUnit.Flush("output"); // The display always shows 480x272. CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT); MarkDirty(displayFramebuf_, displayStride_, 272, displayFormat_, SoftGPUVRAMDirty::CLEAR); @@ -1138,6 +1139,18 @@ void SoftGPU::FinishDeferred() { drawEngine_->transformUnit.Flush("finish"); } +int SoftGPU::ListSync(int listid, int mode) { + // Take this as a cue that we need to finish drawing. + drawEngine_->transformUnit.Flush("listsync"); + return GPUCommon::ListSync(listid, mode); +} + +u32 SoftGPU::DrawSync(int mode) { + // Take this as a cue that we need to finish drawing. + drawEngine_->transformUnit.Flush("drawsync"); + return GPUCommon::DrawSync(mode); +} + void SoftGPU::GetStats(char *buffer, size_t bufsize) { drawEngine_->transformUnit.GetStats(buffer, bufsize); } diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 11d5dd16f3..54880bd477 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -131,6 +131,8 @@ public: void InitClear() override {} void ExecuteOp(u32 op, u32 diff) override; void FinishDeferred() override; + int ListSync(int listid, int mode) override; + u32 DrawSync(int mode) override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 0cb91dd280..dfc8c6a58e 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -484,6 +484,7 @@ void TransformUnit::SubmitPrimitive(const void* vertices, const void* indices, G // then resolve the indices. This lets us avoid transforming shared vertices twice. binner_->UpdateState(vreader.isThrough()); + hasDraws_ = true; static TransformState transformState; if (binner_->HasDirty(SoftDirty::LIGHT_ALL | SoftDirty::TRANSFORM_ALL)) { @@ -826,8 +827,12 @@ void TransformUnit::SendTriangle(CullType cullType, const VertexData *verts, int } void TransformUnit::Flush(const char *reason) { + if (!hasDraws_) + return; + binner_->Flush(reason); GPUDebug::NotifyDraw(); + hasDraws_ = false; } void TransformUnit::GetStats(char *buffer, size_t bufsize) { @@ -836,6 +841,9 @@ void TransformUnit::GetStats(char *buffer, size_t bufsize) { } void TransformUnit::FlushIfOverlap(const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h) { + if (!hasDraws_) + return; + if (binner_->HasPendingWrite(addr, stride, w, h)) Flush(reason); if (modifying && binner_->HasPendingRead(addr, stride, w, h)) diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index fd6e047350..2b35501b44 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -149,6 +149,7 @@ private: // This is the index of the next vert in data (or higher, may need modulus.) int data_index_ = 0; GEPrimitiveType prev_prim_ = GE_PRIM_POINTS; + bool hasDraws_ = false; }; class SoftwareDrawEngine : public DrawEngineCommon {