mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 05:46:56 +01:00
Optimize texture cache tracking (#123)
Optimize texture cache page tracking
This commit is contained in:
@@ -577,6 +577,75 @@ void TestCrossRegionRange() {
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
void TestBatchedWatcherRanges() {
|
||||
FaultContext context;
|
||||
PageManager manager(InvalidateFault, &context);
|
||||
context.manager = &manager;
|
||||
const auto page_size = manager.GetPageSize();
|
||||
constexpr uint64_t region_size = 4ull * 1024ull * 1024ull;
|
||||
constexpr uint64_t allocation_size = region_size * 3;
|
||||
auto *memory = Allocate(allocation_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
|
||||
manager.OnGpuMap(address, allocation_size);
|
||||
|
||||
manager.UpdatePageWatchers(true, address + page_size, page_size);
|
||||
manager.UpdatePageWatchers(true, address + page_size * 3, page_size);
|
||||
manager.UpdatePageWatchers(true, address, page_size * 5);
|
||||
for (uint64_t page = 0; page < 5; page++) {
|
||||
Check(Protection(memory + page * page_size) == PAGE_READONLY,
|
||||
"fragmented watch did not coalesce to read-only");
|
||||
}
|
||||
manager.UpdatePageWatchers(false, address, page_size * 5);
|
||||
Check(IsWritable(memory) &&
|
||||
Protection(memory + page_size) == PAGE_READONLY &&
|
||||
IsWritable(memory + page_size * 2) &&
|
||||
Protection(memory + page_size * 3) == PAGE_READONLY &&
|
||||
IsWritable(memory + page_size * 4),
|
||||
"fragmented unwatch lost overlapping watcher counts");
|
||||
manager.UpdatePageWatchers(false, address + page_size, page_size);
|
||||
manager.UpdatePageWatchers(false, address + page_size * 3, page_size);
|
||||
|
||||
manager.UpdatePageWatchers(true, address, allocation_size);
|
||||
Check(!IsWritable(memory) &&
|
||||
!IsWritable(memory + region_size) &&
|
||||
!IsWritable(memory + region_size * 2) &&
|
||||
!IsWritable(memory + allocation_size - page_size),
|
||||
"large cross-region watch did not protect the full range");
|
||||
manager.UpdatePageWatchers(false, address, allocation_size);
|
||||
Check(IsWritable(memory) &&
|
||||
IsWritable(memory + region_size) &&
|
||||
IsWritable(memory + region_size * 2) &&
|
||||
IsWritable(memory + allocation_size - page_size),
|
||||
"large cross-region unwatch did not restore the full range");
|
||||
|
||||
manager.UpdatePageWatchers(true, address, page_size * 5);
|
||||
manager.UpdatePageWatchers(true, address + page_size, page_size * 3,
|
||||
Libs::Graphics::PageWatchMode::ReadWrite);
|
||||
Check(Protection(memory) == PAGE_READONLY &&
|
||||
Protection(memory + page_size) == PAGE_NOACCESS &&
|
||||
Protection(memory + page_size * 2) == PAGE_NOACCESS &&
|
||||
Protection(memory + page_size * 3) == PAGE_NOACCESS &&
|
||||
Protection(memory + page_size * 4) == PAGE_READONLY,
|
||||
"mixed watcher modes installed incorrect protections");
|
||||
manager.UpdatePageWatchers(false, address, page_size * 5);
|
||||
Check(IsWritable(memory) &&
|
||||
Protection(memory + page_size) == PAGE_NOACCESS &&
|
||||
Protection(memory + page_size * 2) == PAGE_NOACCESS &&
|
||||
Protection(memory + page_size * 3) == PAGE_NOACCESS &&
|
||||
IsWritable(memory + page_size * 4),
|
||||
"write unwatch incorrectly released read/write watchers");
|
||||
manager.UpdatePageWatchers(false, address + page_size, page_size * 3,
|
||||
Libs::Graphics::PageWatchMode::ReadWrite);
|
||||
Check(IsWritable(memory + page_size) &&
|
||||
IsWritable(memory + page_size * 2) &&
|
||||
IsWritable(memory + page_size * 3),
|
||||
"read/write unwatch did not restore writable protection");
|
||||
|
||||
manager.OnGpuUnmap(address, allocation_size);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
[[noreturn]] void RunDeathCase(const char *name) {
|
||||
FaultContext context;
|
||||
auto manager = std::make_unique<PageManager>(InvalidateFault, &context);
|
||||
@@ -795,6 +864,7 @@ int main(int argc, char **argv) {
|
||||
TestNativeAccessViolation();
|
||||
TestInvalidLateWriteTokenIsConsumed();
|
||||
TestCrossRegionRange();
|
||||
TestBatchedWatcherRanges();
|
||||
TestConcurrentFault();
|
||||
TestExternalDirtyTransferDuringResolution();
|
||||
TestMappingDoesNotRequireCpuWriteAccess();
|
||||
|
||||
@@ -3195,6 +3195,10 @@ public:
|
||||
const auto fault_b_image = texture_cache.FindImage(fault_b_desc);
|
||||
texture_cache.MarkGpuWritten(fault_a_image);
|
||||
texture_cache.MarkGpuWritten(fault_b_image);
|
||||
Require(name, "per-image watcher installation",
|
||||
texture_cache.GetImage(fault_a_image).IsTracked() &&
|
||||
texture_cache.GetImage(fault_b_image).IsTracked(),
|
||||
"same-page images did not install independent write watchers");
|
||||
constexpr uint64_t padding_fault_offset = 0x8080;
|
||||
uint32_t write_only_read_a = 0;
|
||||
uint32_t write_only_read_b = 0;
|
||||
@@ -3212,13 +3216,24 @@ public:
|
||||
resources.HandleFault(PageFaultAccess::Write,
|
||||
base + padding_fault_offset) &&
|
||||
texture_cache.GetImage(fault_a_image).IsGpuModified() &&
|
||||
texture_cache.GetImage(fault_b_image).IsGpuModified(),
|
||||
texture_cache.GetImage(fault_b_image).IsGpuModified() &&
|
||||
!texture_cache.GetImage(fault_a_image).IsTracked() &&
|
||||
!texture_cache.GetImage(fault_b_image).IsTracked() &&
|
||||
texture_cache.GetImage(fault_a_image).IsMaybeCpuDirty() &&
|
||||
texture_cache.GetImage(fault_b_image).IsMaybeCpuDirty(),
|
||||
"a byte-disjoint CPU write discarded authoritative images");
|
||||
const auto retracked_a = texture_cache.FindImage(fault_a_desc);
|
||||
const auto retracked_b = texture_cache.FindImage(fault_b_desc);
|
||||
Require(name, "same-page image re-track",
|
||||
texture_cache.FindImage(fault_a_desc) == fault_a_image &&
|
||||
texture_cache.FindImage(fault_b_desc) == fault_b_image &&
|
||||
retracked_a == fault_a_image && retracked_b == fault_b_image &&
|
||||
texture_cache.GetImage(fault_a_image).IsTracked() &&
|
||||
texture_cache.GetImage(fault_b_image).IsTracked() &&
|
||||
!texture_cache.GetImage(fault_a_image).IsCpuDirty() &&
|
||||
!texture_cache.GetImage(fault_b_image).IsCpuDirty() &&
|
||||
texture_cache.SynchronizeImageToBuffer(base + 0x8000,
|
||||
sizeof(fault_a)) &&
|
||||
texture_cache.GetImage(fault_a_image).IsTracked() &&
|
||||
texture_cache.GetImage(fault_b_image).IsTracked() &&
|
||||
!texture_cache.GetImage(fault_a_image).IsGpuModified() &&
|
||||
texture_cache.GetImage(fault_b_image).IsGpuModified(),
|
||||
"retiring one same-page image lost the surviving owner");
|
||||
|
||||
Reference in New Issue
Block a user