From 1aa684175962d83a5674def986378c33c19e49f9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 24 Sep 2022 19:26:52 -0700 Subject: [PATCH 1/2] softgpu: Increase queued prims. We made them smaller, so we can queue more of them in the same space. Helps a little bit. --- GPU/Software/BinManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h index 15c09bccf7d1..d651dfe577bc 100644 --- a/GPU/Software/BinManager.h +++ b/GPU/Software/BinManager.h @@ -228,8 +228,8 @@ class BinManager { static constexpr int QUEUED_STATES = 4096; // These are 1KB each, so half an MB. static constexpr int QUEUED_CLUTS = 512; - // About 320 KB, but we have usually 16 or less of them, so 5 MB - 20 MB. - static constexpr int QUEUED_PRIMS = 1024; + // About 360 KB, but we have usually 16 or less of them, so 5 MB - 22 MB. + static constexpr int QUEUED_PRIMS = 2048; typedef BinQueue BinStateQueue; typedef BinQueue BinClutQueue; From 24560eef5cad36241ef019db10094ee3ba04a831 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 24 Sep 2022 19:57:45 -0700 Subject: [PATCH 2/2] softgpu: Avoid waiting for a thread to drain. If we can, we want to keep the thread queues healthy, but not full. Reduce the amount we push on a typical drain to avoid the Wait(). --- GPU/Software/BinManager.cpp | 20 ++++++++++++++------ GPU/Software/BinManager.h | 6 +++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp index 8ad233b61cbe..d36c8137b3d2 100644 --- a/GPU/Software/BinManager.cpp +++ b/GPU/Software/BinManager.cpp @@ -406,7 +406,7 @@ void BinManager::AddPoint(const VertexData &v0) { Expand(range); } -void BinManager::Drain() { +void BinManager::Drain(bool flushing) { PROFILE_THIS_SCOPE("bin_drain"); // If the waitable has fully drained, we can update our binning decisions. @@ -446,6 +446,7 @@ void BinManager::Drain() { queue_.SkipNext(); } } else { + int max = flushing ? QUEUED_PRIMS : QUEUED_PRIMS / 2; while (!queue_.Empty()) { const BinItem &item = queue_.PeekNext(); for (int i = 0; i < (int)taskRanges_.size(); ++i) { @@ -453,17 +454,24 @@ void BinManager::Drain() { if (range.Invalid()) continue; - // This shouldn't often happen, but if it does, wait for space. - if (taskQueues_[i].Full()) - waitable_->Wait(); + if (taskQueues_[i].NearFull()) { + // This shouldn't often happen, but if it does, wait for space. + if (taskQueues_[i].Full()) + waitable_->Wait(); + // If we're not flushing and not near full, let's just continue later. + // Near full means we'd drain on next prim, so better to finish it now. + else if (!flushing && !queue_.NearFull()) + max = 0; + } BinItem &taskItem = taskQueues_[i].PeekPush(); taskItem = item; taskItem.range = range; taskQueues_[i].PushPeeked(); - } queue_.SkipNext(); + if (--max <= 0) + break; } int threads = 0; @@ -491,7 +499,7 @@ void BinManager::Flush(const char *reason) { double st; if (coreCollectDebugStats) st = time_now_d(); - Drain(); + Drain(true); waitable_->Wait(); taskRanges_.clear(); tasksSplit_ = false; diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h index d651dfe577bc..d874f0d3c8d3 100644 --- a/GPU/Software/BinManager.h +++ b/GPU/Software/BinManager.h @@ -132,6 +132,10 @@ struct BinQueue { return size_ == N - 1; } + bool NearFull() const { + return size_ >= N - 2; + } + bool Empty() const { return size_ == 0; } @@ -195,7 +199,7 @@ class BinManager { void AddLine(const VertexData &v0, const VertexData &v1); void AddPoint(const VertexData &v0); - void Drain(); + void Drain(bool flushing = false); void Flush(const char *reason); bool HasPendingWrite(uint32_t start, uint32_t stride, uint32_t w, uint32_t h); // Assumes you've also checked for a write (writes are partial so are automatically reads.)