fix(agc-driver): delay storage writeback until queue activity settles

This commit is contained in:
MarcZX100 2026-10-12 09:48:03 +00:00
parent 1acfa7f788
commit afbc3c8eb5
1 changed files with 25 additions and 1 deletions

View File

@ -7,10 +7,17 @@
#include "prx/libSceAgcDriver/Execution/include/WorkerSampler.hpp"
#include "prx/libSceAgcDriver/Execution/include/PerformanceTimer.hpp"
#include <algorithm>
#include <chrono>
#include <cstdlib>
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<FrameTiming>(++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();