From 83adc44c2be185153523653b5853fe2434279ea7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 16 Jan 2022 20:19:51 -0800 Subject: [PATCH 1/2] softgpu: Heuristic to avoid over-draining. Some games (i.e. VC3) benefit from an early drain, since they get more done while processing more verts. Others finish the draw quickly, and then cause significant overhead in queueing new threads. This attempts to balance the two, and improves Call of Duty and Blade Dancer. --- GPU/Software/BinManager.cpp | 26 ++++++++++++++++++++------ GPU/Software/BinManager.h | 3 +++ GPU/Software/TransformUnit.cpp | 1 - 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp index faa1f648c0..093d0acf93 100644 --- a/GPU/Software/BinManager.cpp +++ b/GPU/Software/BinManager.cpp @@ -183,6 +183,11 @@ void BinManager::UpdateState() { queueOffsetX_ = gstate.getOffsetX16(); queueOffsetY_ = gstate.getOffsetY16(); } + + if (lastFlipstats_ != gpuStats.numFlips) { + lastFlipstats_ = gpuStats.numFlips; + ResetStats(); + } } void BinManager::UpdateClut(const void *src) { @@ -320,15 +325,22 @@ void BinManager::Drain() { queue_.SkipNext(); } + int threads = 0; for (int i = 0; i < (int)taskRanges_.size(); ++i) { - if (taskQueues_[i].Empty() || taskStatus_[i]) + if (taskQueues_[i].Empty()) + continue; + threads++; + if (taskStatus_[i]) continue; waitable_->Fill(); taskStatus_[i] = true; DrawBinItemsTask *task = new DrawBinItemsTask(waitable_, taskQueues_[i], taskStatus_[i], states_); g_threadManager.EnqueueTaskOnThread(i, task, true); + enqueues_++; } + + mostThreads_ = std::max(mostThreads_, threads); } } @@ -392,13 +404,13 @@ void BinManager::GetStats(char *buffer, size_t bufsize) { "Slowest individual flush: %s (%0.4f)\n" "Slowest frame flush: %s (%0.4f)\n" "Slowest recent flush: %s (%0.4f)\n" - "Total flush time: %0.4f (%05.2f%%, last 2: %05.2f%%)\n", + "Total flush time: %0.4f (%05.2f%%, last 2: %05.2f%%)\n" + "Thread enqueues: %d, count %d", slowestFlushReason_, slowestFlushTime_, slowestTotalReason, slowestTotalTime, slowestRecentReason, slowestRecentTime, - allTotal, allTotal * (6000.0 / 1.001), recentTotal * (3000.0 / 1.001)); - - constexpr int foo = sizeof(BinItem); + allTotal, allTotal * (6000.0 / 1.001), recentTotal * (3000.0 / 1.001), + enqueues_, mostThreads_); } void BinManager::ResetStats() { @@ -406,6 +418,8 @@ void BinManager::ResetStats() { flushReasonTimes_.clear(); slowestFlushReason_ = nullptr; slowestFlushTime_ = 0.0; + enqueues_ = 0; + mostThreads_ = 0; } inline BinCoords BinCoords::Intersect(const BinCoords &range) const { @@ -454,7 +468,7 @@ void BinManager::Expand(const BinCoords &range) { queueRange_.x2 = std::max(queueRange_.x2, range.x2); queueRange_.y2 = std::max(queueRange_.y2, range.y2); - if (maxTasks_ == 1 || queueRange_.y2 - queueRange_.y1 >= 224 * 16) { + if (maxTasks_ == 1 || (queueRange_.y2 - queueRange_.y1 >= 224 * 16 && enqueues_ < 36 * maxTasks_)) { Drain(); } } diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h index 883997ad10..9a7e387400 100644 --- a/GPU/Software/BinManager.h +++ b/GPU/Software/BinManager.h @@ -211,6 +211,9 @@ private: std::unordered_map lastFlushReasonTimes_; const char *slowestFlushReason_ = nullptr; double slowestFlushTime_ = 0.0; + int lastFlipstats_ = 0; + int enqueues_ = 0; + int mostThreads_ = 0; BinCoords Scissor(BinCoords range); BinCoords Range(const VertexData &v0, const VertexData &v1, const VertexData &v2); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 068fb29b0a..eee3b316a4 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -620,7 +620,6 @@ void TransformUnit::Flush(const char *reason) { void TransformUnit::GetStats(char *buffer, size_t bufsize) { // TODO: More stats? binner_->GetStats(buffer, bufsize); - binner_->ResetStats(); } void TransformUnit::FlushIfOverlap(const char *reason, uint32_t addr, uint32_t sz) { From 423ec7625876164d8c8de8270488f201e0355125 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 16 Jan 2022 12:21:38 -0800 Subject: [PATCH 2/2] softgpu: Correct texsize flush annotation. --- GPU/Software/SoftGpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index f1c1d7409c..162068bc85 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -689,7 +689,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXSIZE5: case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: - drawEngine_->transformUnit.FlushIfOverlap("texbufw", gstate.getTextureAddress(cmd - GE_CMD_TEXSIZE0), 4 * gstate.getTextureWidth(cmd - GE_CMD_TEXSIZE0) * gstate.getTextureHeight(cmd - GE_CMD_TEXSIZE0)); + drawEngine_->transformUnit.FlushIfOverlap("texsize", gstate.getTextureAddress(cmd - GE_CMD_TEXSIZE0), 4 * gstate.getTextureWidth(cmd - GE_CMD_TEXSIZE0) * gstate.getTextureHeight(cmd - GE_CMD_TEXSIZE0)); break; case GE_CMD_ZBUFPTR: