mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
perf(agc): bind the address space's BDA table for writes inside writable imports
A build mapping only the cached address space but writing through V#s got a table keyed by its writes: a new key for nearly every set of written addresses, so each such build merged the space's imported ranges, stored them, then hashed and compared them in BdaResources. AddressRanges splits only ranges without write permission around the written intervals. When no written interval overlaps such a range of the space, its result is the space's own ranges, so the build binds the space's table by the space serial, as a build without writes does. A write overlapping a range without write permission keeps the per-writes table. Test: builds with one and two writes inside a writable import bind the serial and the ranges of the build without writes, equal to AddressRanges(), and keep the read-only import without write permission. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5030fbb5cb
commit
d95634b706
2 files changed
+63
No files matched your search
@@ -3451,6 +3451,15 @@ std::optional<GuestBufferMemory::CachedTable> GuestBufferMemory::CachedAddressTa
|
||||
Require(uploaded && !committed, "guest GPU address ranges are not available");
|
||||
if (writes.empty()) return CachedTable{space->serial, &space->ranges};
|
||||
if (writeTableRanges != nullptr) return CachedTable{writeTableSerial, writeTableRanges.get()};
|
||||
const auto& spaceRanges = space->ranges;
|
||||
const bool inWritable = std::all_of(writes.begin(), writes.end(), [&](const auto& written) {
|
||||
auto at = std::partition_point(spaceRanges.begin(), spaceRanges.end(), [&](const auto& range) { return range.end <= written.first; });
|
||||
for (; at != spaceRanges.end() && at->begin < written.second; ++at) {
|
||||
if ((at->permissions & ShaderRecompiler::BdaAbi::Write) == 0u) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (inWritable) return CachedTable{space->serial, &space->ranges};
|
||||
std::lock_guard lock(space->tableMutex);
|
||||
const auto found = space->writeTables.find(writes);
|
||||
if (found != space->writeTables.end()) {
|
||||
|
||||
@@ -119,6 +119,59 @@ void importSpanTests(const Context& context) {
|
||||
::operator delete(block, std::align_val_t{piece});
|
||||
}
|
||||
|
||||
void spaceWritableWritesTests(const Context& context) {
|
||||
if (!AddressSpaceCounters().enabled) return;
|
||||
constexpr std::size_t piece = 65536;
|
||||
auto* writable = static_cast<std::uint8_t*>(::operator new(piece, std::align_val_t{piece}));
|
||||
auto* readOnly = static_cast<std::uint8_t*>(::operator new(piece, std::align_val_t{piece}));
|
||||
std::memset(writable, 0x11, piece);
|
||||
std::memset(readOnly, 0x22, piece);
|
||||
auto importing = context;
|
||||
importing.hostImportAlignment = piece;
|
||||
const auto change = [&](std::uint8_t* range, bool add, bool canWrite) {
|
||||
auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix();
|
||||
if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, range, piece, true, canWrite, true);
|
||||
else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, range);
|
||||
GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation);
|
||||
};
|
||||
change(writable, true, true);
|
||||
change(readOnly, true, false);
|
||||
const auto same = [](const std::vector<ShaderRecompiler::BdaAbi::Range>& left, const std::vector<ShaderRecompiler::BdaAbi::Range>& right) {
|
||||
return left.size() == right.size() && (left.empty() || std::memcmp(left.data(), right.data(), left.size() * sizeof(left.front())) == 0);
|
||||
};
|
||||
struct Built {
|
||||
std::uint64_t serial;
|
||||
std::vector<ShaderRecompiler::BdaAbi::Range> ranges;
|
||||
};
|
||||
const auto build = [&](std::initializer_list<std::pair<std::size_t, std::size_t>> written, const char* step) {
|
||||
GuestBufferMemory leased(importing);
|
||||
leased.AcquireRegistered();
|
||||
for (const auto& [offset, bytes] : written) leased.AddWritable(reinterpret_cast<std::uintptr_t>(writable) + offset, bytes);
|
||||
leased.Upload(true);
|
||||
const auto cached = leased.CachedAddressTable();
|
||||
Require(cached.has_value() && cached->ranges != nullptr, std::string("a build of the space alone has no cached table: ") + step);
|
||||
Built result{cached->serial, leased.AddressRanges()};
|
||||
Require(same(*cached->ranges, result.ranges), std::string("the cached table differs from AddressRanges(): ") + step);
|
||||
leased.WriteBack();
|
||||
return result;
|
||||
};
|
||||
const auto plain = build({}, "no writes");
|
||||
const auto once = build({{256, 512}}, "one write in a writable import");
|
||||
const auto twice = build({{4096, 64}, {8192, 128}}, "two writes in a writable import");
|
||||
Require(once.serial == plain.serial && twice.serial == plain.serial, "writes in a writable import did not bind the space's table");
|
||||
Require(same(once.ranges, plain.ranges) && same(twice.ranges, plain.ranges), "writes in a writable import changed the BDA table");
|
||||
const auto writableBegin = reinterpret_cast<std::uint64_t>(writable);
|
||||
const auto readOnlyBegin = reinterpret_cast<std::uint64_t>(readOnly);
|
||||
for (const auto& range : once.ranges) {
|
||||
if (range.begin == writableBegin) Require((range.permissions & ShaderRecompiler::BdaAbi::Write) != 0u, "the writable import lost its write permission");
|
||||
if (range.begin == readOnlyBegin) Require((range.permissions & ShaderRecompiler::BdaAbi::Write) == 0u, "the read-only import gained write permission");
|
||||
}
|
||||
change(writable, false, true);
|
||||
change(readOnly, false, false);
|
||||
::operator delete(writable, std::align_val_t{piece});
|
||||
::operator delete(readOnly, std::align_val_t{piece});
|
||||
}
|
||||
|
||||
void failedImportRemapTests(const Context& context, const BdaTestAccess& access) {
|
||||
constexpr std::size_t piece = 65536;
|
||||
auto* block = static_cast<std::byte*>(::operator new(4 * piece, std::align_val_t{piece}));
|
||||
@@ -1239,6 +1292,7 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) {
|
||||
importSpanTests(context);
|
||||
failedImportRemapTests(context, access);
|
||||
spaceImportRunTests(context);
|
||||
spaceWritableWritesTests(context);
|
||||
importWindowTests(context);
|
||||
heapMirrorTests(context, access);
|
||||
importedHeapMirrorTests(context, access);
|
||||
|
||||
Reference in new issue
Block a user