From 81ef1ff485ae13902e26be6357dc827d80fd6c40 Mon Sep 17 00:00:00 2001 From: eljackjoestar-cmd Date: Thu, 15 Oct 2026 16:49:08 +0400 Subject: [PATCH] fix(agc): limit copied-writer waits to copied ranges --- .../Graphics/src/ShaderResources.cpp | 2 +- .../prx/libSceAgcDriver/tests/Recorder.cpp | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp index 15a0f3c2d2e..a05901b397f 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp @@ -2786,7 +2786,7 @@ bool CompletePendingCpuWrites(const Context& context, std::uint64_t address, std if ((context.copiedWriters == nullptr || context.copiedWriters->empty()) && drawWriters->empty() && !labels) return false; if (!recorder->PendingWriteOverlaps(address, bytes)) return false; const auto overlaps = [&](const auto& writers) { - return std::any_of(writers.begin(), writers.end(), [&](const auto& writer) { return writer->WritesOverlap(address, bytes); }); + return std::any_of(writers.begin(), writers.end(), [&](const auto& writer) { return writer->CopiedWritesOverlap(address, bytes); }); }; if ((context.copiedWriters != nullptr && overlaps(*context.copiedWriters)) || overlaps(*drawWriters) || (labels && recorder->PendingLabelIn(address, bytes))) { Recorder::CountSync(4); diff --git a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp index 040c2dd1954..4dd269c6c15 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp @@ -499,6 +499,39 @@ void copiedDirectOrderingTests(const Device& device, Recorder& recorder) { update(direct, 2); recorder.Sync(); Require(*block == 45, "direct consumers lost GPU-ordered updates"); + { + std::array unregistered{}; + struct Finish { + Recorder& recorder; + ~Finish() { recorder.Sync(); } + } finish{recorder}; + const auto copiedAddress = reinterpret_cast(unregistered.data()); + auto mixedProgram = program; + auto& mixedBinding = mixedProgram.bindings[0]; + mixedBinding.count = 2; + mixedBinding.guestDescriptor.insert(mixedBinding.guestDescriptor.end(), {static_cast(copiedAddress), static_cast(copiedAddress >> 32u) & 0xffffu, 1024, 0x31000000u}); + mixedBinding.bufferWritten = {true, true}; + const CompiledShader mixedCompute{ShaderRecompiler::ShaderStage::Compute, &mixedProgram, 0}; + for (const bool draw : {false, true}) { + auto mixed = std::make_shared(context, mixedCompute); + Require(mixed->HasCopiedWrites() && mixed->WritesOverlap(address, 4) && !mixed->CopiedWritesOverlap(address, 4) && mixed->CopiedWritesOverlap(copiedAddress, 4), "the mixed producer did not retain direct and CPU-copied writes"); + auto& pending = draw ? *DrawCopiedWriters() : writers; + static_cast(recorder.Commands()); + recorder.Keep(mixed); + mixed->MarkGpuWrites(recorder); + pending.push_back(mixed); + auto completed = std::make_shared(0); + recorder.OnComplete([mixed, &pending, completed] { + mixed->WriteBackBuffers(); + std::erase(pending, mixed); + ++*completed; + }); + Require(!CompletePendingCpuWrites(context, address, 4), "a direct write in a mixed producer caused a CPU write-back wait"); + Require(*completed == 0 && !pending.empty(), "a disjoint copied write-back was completed while binding a direct buffer"); + Require(CompletePendingCpuWrites(context, copiedAddress, 4), "a CPU-copied write in a mixed producer was not completed"); + Require(*completed == 1 && pending.empty(), "the required CPU write-back did not release the mixed producer"); + } + } { TextureDetiler detiler(context); auto imageContext = context;