diff --git a/Common/Thread/ParallelLoop.cpp b/Common/Thread/ParallelLoop.cpp index 0212a84b8a..2f00664618 100644 --- a/Common/Thread/ParallelLoop.cpp +++ b/Common/Thread/ParallelLoop.cpp @@ -9,6 +9,10 @@ public: LoopRangeTask(WaitableCounter *counter, const std::function &loop, int lower, int upper) : counter_(counter), loop_(loop), lower_(lower), upper_(upper) {} + TaskType Type() const override { + return TaskType::CPU_COMPUTE; + } + void Run() override { loop_(lower_, upper_); counter_->Count(); @@ -34,7 +38,7 @@ WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std:: } else if (range <= minSize) { // Single background task. WaitableCounter *waitableCounter = new WaitableCounter(1); - threadMan->EnqueueTaskOnThread(0, new LoopRangeTask(waitableCounter, loop, lower, upper), TaskType::CPU_COMPUTE); + threadMan->EnqueueTaskOnThread(0, new LoopRangeTask(waitableCounter, loop, lower, upper)); return waitableCounter; } else { // Split the range between threads. Allow for some fractional bits. @@ -61,7 +65,7 @@ WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std:: // Let's do the stragglers on the current thread. break; } - threadMan->EnqueueTaskOnThread(i, new LoopRangeTask(waitableCounter, loop, start, end), TaskType::CPU_COMPUTE); + threadMan->EnqueueTaskOnThread(i, new LoopRangeTask(waitableCounter, loop, start, end)); counter += delta; if ((counter >> fractionalBits) >= upper) { break; diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index f69bb791e9..cd057631ef 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -9,13 +9,17 @@ template class PromiseTask : public Task { public: - PromiseTask(std::function fun, Mailbox *tx) : fun_(fun), tx_(tx) { + PromiseTask(std::function fun, Mailbox *tx, TaskType t) : fun_(fun), tx_(tx), type_(t) { tx_->AddRef(); } ~PromiseTask() { tx_->Release(); } + TaskType Type() const override { + return type_; + } + void Run() override { T value = fun_(); tx_->Send(value); @@ -23,6 +27,7 @@ public: std::function fun_; Mailbox *tx_; + TaskType type_; }; // Represents pending or actual data. @@ -38,8 +43,8 @@ public: Promise *promise = new Promise(); promise->rx_ = mailbox; - PromiseTask *task = new PromiseTask(fun, mailbox); - threadman->EnqueueTask(task, taskType); + PromiseTask *task = new PromiseTask(fun, mailbox, taskType); + threadman->EnqueueTask(task); return promise; } diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index 5cdd23d64e..1a48645357 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -172,12 +172,12 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) { } } -void ThreadManager::EnqueueTask(Task *task, TaskType taskType) { +void ThreadManager::EnqueueTask(Task *task) { _assert_msg_(IsInitialized(), "ThreadManager not initialized"); int maxThread; int threadOffset = 0; - if (taskType == TaskType::CPU_COMPUTE) { + if (task->Type() == TaskType::CPU_COMPUTE) { // only the threads reserved for heavy compute. maxThread = numComputeThreads_; threadOffset = 0; @@ -219,7 +219,7 @@ void ThreadManager::EnqueueTask(Task *task, TaskType taskType) { chosenThread->cond.notify_one(); } -void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task, TaskType taskType) { +void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) { _assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized"); ThreadContext *thread = global_->threads_[threadNum]; diff --git a/Common/Thread/ThreadManager.h b/Common/Thread/ThreadManager.h index a56184c44f..f6ddd842b2 100644 --- a/Common/Thread/ThreadManager.h +++ b/Common/Thread/ThreadManager.h @@ -14,6 +14,7 @@ enum class TaskType { class Task { public: virtual ~Task() {} + virtual TaskType Type() const = 0; virtual void Run() = 0; virtual bool Cancellable() { return false; } virtual void Cancel() {} @@ -44,8 +45,8 @@ public: // It gets even trickier when you think about mobile chips with BIG/LITTLE, but we'll // just ignore it and let the OS handle it. void Init(int numCores, int numLogicalCoresPerCpu); - void EnqueueTask(Task *task, TaskType taskType); - void EnqueueTaskOnThread(int threadNum, Task *task, TaskType taskType); + void EnqueueTask(Task *task); + void EnqueueTaskOnThread(int threadNum, Task *task); void Teardown(); bool IsInitialized() const; diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 3d40e302d0..f4a2e72828 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -785,6 +785,10 @@ public: ReplacedTextureTask(ReplacedTexture &tex, LimitedWaitable *w) : tex_(tex), waitable_(w) { } + TaskType Type() const override { + return TaskType::IO_BLOCKING; + } + void Run() override { tex_.Prepare(); waitable_->Notify(); @@ -815,7 +819,7 @@ bool ReplacedTexture::IsReady(double budget) { if (g_Config.bReplaceTexturesAllowLate) { threadWaitable_ = new LimitedWaitable(); - g_threadManager.EnqueueTask(new ReplacedTextureTask(*this, threadWaitable_), TaskType::IO_BLOCKING); + g_threadManager.EnqueueTask(new ReplacedTextureTask(*this, threadWaitable_)); if (threadWaitable_->WaitFor(budget)) { threadWaitable_->WaitAndRelease(); diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index e3bbfb34d0..83743e4090 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -340,6 +340,10 @@ public: info_->readyEvent.Notify(); } + TaskType Type() const override { + return TaskType::IO_BLOCKING; + } + void Run() override { // An early-return will result in the destructor running, where we can set // flags like working and pending. @@ -738,7 +742,7 @@ std::shared_ptr GameInfoCache::GetInfo(Draw::DrawContext *draw, const } GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info); - g_threadManager.EnqueueTask(item, TaskType::IO_BLOCKING); + g_threadManager.EnqueueTask(item); // Don't re-insert if we already have it. if (info_.find(pathStr) == info_.end())