mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
Merge pull request #8896 from teepean/perf/recent-host-imports
perf(agc): find a host import among the last ones found first
This commit is contained in:
3 files changed
+55
No files matched your search
@@ -297,6 +297,10 @@ struct HostImports {
|
||||
std::uint8_t reportNoted = 0;
|
||||
std::map<std::uint64_t, std::uint64_t> spaceUses;
|
||||
std::uint64_t budgetRefusals = 0;
|
||||
std::array<const HostImport*, 4> recentImports{};
|
||||
std::uint64_t recentEpoch = std::numeric_limits<std::uint64_t>::max();
|
||||
std::size_t recentSize = 0;
|
||||
std::size_t recentNext = 0;
|
||||
};
|
||||
|
||||
HostImports& Imports() {
|
||||
@@ -304,6 +308,31 @@ HostImports& Imports() {
|
||||
return imports;
|
||||
}
|
||||
|
||||
bool recentImportsEnabled() {
|
||||
static const bool enabled = std::getenv("APS5_NO_RECENT_IMPORTS") == nullptr;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
const HostImport* recentImport(HostImports& state, std::uint64_t begin, std::uint64_t end) {
|
||||
if (state.recentEpoch != state.epoch || state.recentSize != state.imports.size()) return nullptr;
|
||||
for (const auto* entry : state.recentImports) {
|
||||
if (entry != nullptr && begin >= entry->base && end <= entry->base + entry->bytes) {
|
||||
entry->lastUse = ++state.useCounter;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void rememberImport(HostImports& state, const HostImport* entry) {
|
||||
if (state.recentEpoch != state.epoch || state.recentSize != state.imports.size()) {
|
||||
state.recentImports = {};
|
||||
state.recentEpoch = state.epoch;
|
||||
state.recentSize = state.imports.size();
|
||||
}
|
||||
state.recentImports[state.recentNext++ % state.recentImports.size()] = entry;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void waitSettleBatch(const ImportSettle& settle, VkDevice device, const SettleBatch& batch) {
|
||||
if (batch.busy && settle.waitForFences != nullptr) Check(settle.waitForFences(device, 1, &batch.fence, VK_TRUE, 60'000'000'000ull), "vkWaitForFences (settle batch)");
|
||||
@@ -4023,8 +4052,15 @@ const HostImport* HostImportFor(const Context& context, std::uint64_t address, s
|
||||
#endif
|
||||
// A hit is only valid while the registry has not changed since the imports were reconciled.
|
||||
if (!importsStale(context, state)) {
|
||||
if (recentImportsEnabled()) {
|
||||
if (const auto* entry = recentImport(state, address, address + bytes)) {
|
||||
entry->lastUse = ++state.useCounter;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
if (const auto* entry = findImport(state, address, address + bytes)) {
|
||||
entry->lastUse = ++state.useCounter;
|
||||
if (recentImportsEnabled()) rememberImport(state, entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +360,23 @@ void BusyRetireOutlivesALaterBatch() {
|
||||
Expect(!Live(retired), "the dropped import outlived every batch of its hold");
|
||||
}
|
||||
|
||||
void RecentImportFollowsReplacement() {
|
||||
Heap heap;
|
||||
ActiveRecorder active;
|
||||
const auto context = mockContext();
|
||||
std::lock_guard gpu(AgcDriver::GuestMemory::GpuMutex());
|
||||
const auto* first = HostImportFor(context, heap.Address(), 4096);
|
||||
Expect(first != nullptr, "the first range was not imported");
|
||||
if (first == nullptr) return;
|
||||
Expect(HostImportFor(context, heap.Address(), 4096) == first, "a repeated lookup did not find the same import");
|
||||
const auto retired = first->buffer;
|
||||
heap.Grow();
|
||||
const auto* grown = HostImportFor(context, heap.Address(RangeBytes), 4096);
|
||||
Expect(grown != nullptr && grown->buffer != retired, "the grown run was not imported as a new import");
|
||||
if (grown == nullptr) return;
|
||||
Expect(HostImportFor(context, heap.Address(), 4096) == grown, "a lookup after the replacement served the retired import instead of the one that replaced it");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
@@ -374,6 +391,7 @@ int main() {
|
||||
IdleRetireOutlivesTheHold();
|
||||
BusyRetireOutlivesALaterBatch();
|
||||
AgcDriver::Tests::RunHostImportFailureTests(mockContext(), false);
|
||||
RecentImportFollowsReplacement();
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "%s\n", error.what());
|
||||
return 1;
|
||||
|
||||
@@ -305,6 +305,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti
|
||||
| `APS5_NO_PROC_TABLE` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp` | | resolves the device's Vulkan entry points per call instead of filling the function table once |
|
||||
| `APS5_NO_QUEUED_DRAW_READ_ORDER` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp` | | stops queued draws and DMA copies from holding back write-backs over the guest memory they read at commit |
|
||||
| `APS5_NO_QUEUED_LABELS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Synchronization/DeferredLabels.cpp` | | disables the queued-label table |
|
||||
| `APS5_NO_RECENT_IMPORTS` | presence | `core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp` | | looks every host import up in the import map instead of first checking the last four found while the map is unchanged |
|
||||
| `APS5_NO_RECORDED_CLEAR` | presence | `core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp` | | waits for a storage image's fast clear in a batch of its own instead of recording it |
|
||||
| `APS5_NO_RECORDER_SYNC_DRAWS` | presence | `core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp` | | gives the draws the recorder waits for their own batch instead of recording them with the wait |
|
||||
| `APS5_NO_RECORD_COPIED_DRAWS` | presence | `core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp` | | waits for copied-write draws at once instead of listing their write-back for later |
|
||||
|
||||
Reference in new issue
Block a user