diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp index 9e71901ebd..d2fedc76af 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp @@ -389,6 +389,7 @@ private: // Whether `regions` is in ascending address order (true right after AcquireRegistered, whose // regions follow the registry's order), so AddSnapshot can search instead of scanning. bool regionsSorted = false; + bool regionsOverlap = false; std::vector> writes; std::vector> readsOverBase; std::vector>> heapReferences; diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp index b4771f1a6a..d91dc92ba1 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp @@ -2580,6 +2580,11 @@ void GuestBufferMemory::dissolveSpace(bool resolve) { // Both sorted and disjoint (UploadPrepare merged this build's regions; the space's are // registered ranges), so the merge keeps the order Descriptor searches. std::merge(space->base.begin(), space->base.end(), std::make_move_iterator(regions.begin()), std::make_move_iterator(regions.end()), std::back_inserter(merged), [](const Region& left, const Region& right) { return left.begin < right.begin; }); + std::uint64_t reached = 0; + for (const auto& region : merged) { + regionsOverlap = regionsOverlap || region.begin < reached; + reached = std::max(reached, region.end); + } } else { merged.assign(space->base.begin(), space->base.end()); merged.insert(merged.end(), std::make_move_iterator(regions.begin()), std::make_move_iterator(regions.end())); @@ -2597,12 +2602,19 @@ void GuestBufferMemory::dissolveSpace(bool resolve) { } const GuestBufferMemory::Region* GuestBufferMemory::owner(std::uint64_t address, std::uint64_t end) const { - const auto candidate = [address](const std::vector& list) -> const Region* { + const auto candidate = [address, end](const std::vector& list, bool overlapping) -> const Region* { const auto found = std::upper_bound(list.begin(), list.end(), address, [](std::uint64_t value, const Region& region) { return value < region.begin; }); - return found == list.begin() ? nullptr : &*std::prev(found); + if (found == list.begin()) return nullptr; + if (overlapping) { + for (auto it = found; it != list.begin();) { + --it; + if (end <= it->end) return &*it; + } + } + return &*std::prev(found); }; - const auto* own = candidate(regions); - const auto* shared = space != nullptr ? candidate(space->base) : nullptr; + const auto* own = candidate(regions, regionsOverlap); + const auto* shared = space != nullptr ? candidate(space->base, false) : nullptr; const auto holds = [end](const Region* region) { return region != nullptr && end <= region->end; }; if (holds(own) != holds(shared)) return holds(own) ? own : shared; if (own == nullptr || (shared != nullptr && shared->begin > own->begin)) return shared; diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp index e056c5abb4..ab710def2b 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp @@ -581,12 +581,14 @@ void spaceReadsAcrossImportsMergedTests(const Context& context, const BdaTestAcc const std::uint64_t lowerBytes = 512; const std::uint64_t upper = second + 128; const std::uint64_t upperBytes = third + 256 - upper; - for (int build = 0; build < 2; ++build) { + for (int build = 0; build < 3; ++build) { GuestBufferMemory leased(importing); leased.AcquireRegistered(); leased.AddReadable(lower, lowerBytes); leased.AddReadable(upper, upperBytes); - leased.Upload(true); + leased.UploadPrepare(true); + if (build == 2) ClearHostImports(importing.device); + leased.UploadFinish(true); for (const auto& [address, bytes] : {std::pair{lower, lowerBytes}, std::pair{upper, upperBytes}}) { std::uint32_t adjustment = 0; const auto view = leased.Descriptor(address, bytes, adjustment);