diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/QueueWorker.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/QueueWorker.cpp index d568f7b81..3e7a391ba 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/QueueWorker.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/QueueWorker.cpp @@ -7,10 +7,17 @@ #include "prx/libSceAgcDriver/Execution/include/WorkerSampler.hpp" #include "prx/libSceAgcDriver/Execution/include/PerformanceTimer.hpp" #include +#include #include namespace AgcDriver::DriverDetail { +namespace { + +constexpr auto IdleResultsQuietPeriod = std::chrono::milliseconds(50); + +} + FrameTiming* Driver::frameTiming() { if (!APS5_ENABLE_TIMING_LOG) return nullptr; if (pendingFrameTiming == nullptr) pendingFrameTiming = std::make_shared(++frameSerial, true); @@ -114,6 +121,9 @@ void Driver::run(std::uint32_t id) noexcept { return runningWorkers.load(std::memory_order_acquire) == 0 && std::all_of(workers.begin(), workers.end(), [](const auto& item) { return item.second.pending.empty(); }); }; + const auto idleResultsPending = [&] { + return id == 0 && Graphics::StorageTexture::AnyPending() && allQueuesIdle() && !completionsPending(); + }; const auto poll = [&](const auto& done) { #ifdef _WIN32 lock.unlock(); @@ -128,7 +138,21 @@ void Driver::run(std::uint32_t id) noexcept { while (!ready()) { if (!completionsPending() || (id != 0 && Graphics::Recorder::PendingCompletionLabels() == 0)) { const auto idleEpochAtCheck = idleEpoch.load(std::memory_order_acquire); - const bool storeIdleResults = id == 0 && allQueuesIdle() && !completionsPending(); + const bool storeIdleResults = idleResultsPending(); + if (storeIdleResults) { + queue0Dormant.store(true, std::memory_order_relaxed); + const auto quietUntil = std::chrono::steady_clock::now() + IdleResultsQuietPeriod; + const auto idleEpochAtWait = idleEpoch.load(std::memory_order_acquire); + changed.wait_until(lock, quietUntil, [&] { + return ready() || idleEpoch.load(std::memory_order_acquire) != idleEpochAtWait; + }); + queue0Dormant.store(false, std::memory_order_relaxed); + if (ready()) break; + if (idleEpoch.load(std::memory_order_acquire) != idleEpochAtWait) { + continue; + } + if (!idleResultsPending()) continue; + } lock.unlock(); if (storeIdleResults) { if (const auto localDevice = device.Load()) localDevice->StoreIdleResults();