mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
render: simplify buffer and memory tracking ownership
This commit is contained in:
@@ -176,13 +176,10 @@ uint8_t *Allocate(PageManager &manager, uint64_t pages) {
|
||||
VirtualAlloc(reinterpret_cast<void *>(base), size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
|
||||
Check(memory == reinterpret_cast<void *>(base), "fixed VirtualAlloc failed");
|
||||
manager.OnGpuMap(base, size);
|
||||
return memory;
|
||||
}
|
||||
|
||||
void Release(PageManager &manager, uint8_t *memory, uint64_t size) {
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
manager.OnGpuUnmap(address, size);
|
||||
void Release(uint8_t *memory) {
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -269,7 +266,7 @@ void TestConcurrentRegionPublication() {
|
||||
second.join();
|
||||
|
||||
tracker.UntrackMemory(address, page_size);
|
||||
Release(page_manager, memory, page_size);
|
||||
Release(memory);
|
||||
Check(cpu_dirty_results.load(std::memory_order_relaxed) == 2,
|
||||
"concurrent region publication lost initial CPU ownership");
|
||||
}
|
||||
@@ -303,7 +300,7 @@ void TestCpuDirtyUpload() {
|
||||
Check(tracker.IsRegionCpuModified(address, page_size) && IsWritable(memory),
|
||||
"explicit CPU dirtiness did not release write protection");
|
||||
tracker.UntrackMemory(address, page_size * 2);
|
||||
Release(page_manager, memory, page_size * 2);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestRangeInvalidation() {
|
||||
@@ -318,7 +315,6 @@ void TestRangeInvalidation() {
|
||||
Check(memory == reinterpret_cast<void *>(base),
|
||||
"range invalidation allocation failed");
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
page_manager.OnGpuMap(address, size);
|
||||
|
||||
tracker.ForEachUploadRange(
|
||||
address, size, true, [](uint64_t, uint64_t) noexcept {},
|
||||
@@ -340,7 +336,7 @@ void TestRangeInvalidation() {
|
||||
Check(flushes == 1,
|
||||
"clean range invalidation unnecessarily requested a GPU flush");
|
||||
tracker.UntrackMemory(address, size);
|
||||
Release(page_manager, memory, size);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestGpuReacquisitionAfterInvalidation() {
|
||||
@@ -387,7 +383,7 @@ void TestGpuReacquisitionAfterInvalidation() {
|
||||
tracker.UnmarkRegionAsGpuModified(address, page_size);
|
||||
tracker.MarkRegionAsCpuModified(address, page_size);
|
||||
tracker.UntrackMemory(address, page_size);
|
||||
Release(page_manager, memory, page_size);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestGpuDirtyBits() {
|
||||
@@ -411,7 +407,7 @@ void TestGpuDirtyBits() {
|
||||
"GPU dirty state did not restore write-only tracking");
|
||||
tracker.MarkRegionAsCpuModified(address, page_size);
|
||||
tracker.UntrackMemory(address, page_size * 2);
|
||||
Release(page_manager, memory, page_size * 2);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestExactDirtyIntervalsSharingTrackerPage() {
|
||||
@@ -456,7 +452,7 @@ void TestExactDirtyIntervalsSharingTrackerPage() {
|
||||
"draining the final exact interval did not release its tracker page");
|
||||
|
||||
tracker.UntrackMemory(address, page_size);
|
||||
Release(page_manager, memory, page_size);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestGpuDownloadProtectionMirrors() {
|
||||
@@ -529,7 +525,7 @@ void TestGpuDownloadProtectionMirrors() {
|
||||
"CPU-dirty transition did not release only its write watcher");
|
||||
|
||||
tracker.UntrackMemory(address, page_size * 4);
|
||||
Release(page_manager, memory, page_size * 4);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestCrossRegionUpload() {
|
||||
@@ -545,7 +541,6 @@ void TestCrossRegionUpload() {
|
||||
Check(memory == reinterpret_cast<void *>(base), "fixed VirtualAlloc failed");
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
const auto boundary = (address + region_size - 1) & ~(region_size - 1);
|
||||
page_manager.OnGpuMap(address, region_size * 2);
|
||||
uint32_t ranges = 0;
|
||||
tracker.ForEachUploadRange(
|
||||
boundary - page_size, page_size * 2, false,
|
||||
@@ -557,7 +552,7 @@ void TestCrossRegionUpload() {
|
||||
"cross-region upload did not clear and protect both regions");
|
||||
tracker.MarkRegionAsCpuModified(boundary - page_size, page_size * 2);
|
||||
tracker.UntrackMemory(address, region_size * 2);
|
||||
Release(page_manager, memory, region_size * 2);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestUploadDoesNotSerializeDisjointRegion() {
|
||||
@@ -607,7 +602,7 @@ void TestUploadDoesNotSerializeDisjointRegion() {
|
||||
tracker.UnmarkRegionAsGpuModified(allocation_base, page_size);
|
||||
tracker.MarkRegionAsCpuModified(allocation_base, page_size);
|
||||
tracker.UntrackMemory(allocation_base, region_size * 2);
|
||||
Release(page_manager, memory, region_size * 2);
|
||||
Release(memory);
|
||||
Check(completed_while_upload_blocked &&
|
||||
query_result.load(std::memory_order_relaxed),
|
||||
"upload callback serialized an unrelated tracker region");
|
||||
@@ -663,7 +658,7 @@ void TestDownloadDoesNotSerializeDisjointRegion() {
|
||||
tracker.MarkRegionAsCpuModified(allocation_base, page_size);
|
||||
tracker.MarkRegionAsCpuModified(second_region, page_size);
|
||||
tracker.UntrackMemory(allocation_base, region_size * 2);
|
||||
Release(page_manager, memory, region_size * 2);
|
||||
Release(memory);
|
||||
Check(completed_while_download_blocked && both_gpu_owned,
|
||||
"download callback serialized an unrelated tracker region");
|
||||
}
|
||||
@@ -726,7 +721,7 @@ void TestGpuUnmarkUsesRegionMask() {
|
||||
"cross-region GPU unmark did not use one update per 4 MiB region");
|
||||
|
||||
tracker.UntrackMemory(allocation_base, region_size * 2);
|
||||
Release(page_manager, memory, region_size * 2);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
void TestFullRegionGpuUnmarkBatching() {
|
||||
@@ -767,7 +762,7 @@ void TestFullRegionGpuUnmarkBatching() {
|
||||
"full-region GPU unmark did not use one exact 4 MiB protection request");
|
||||
|
||||
tracker.UntrackMemory(allocation_base, region_size * 2);
|
||||
Release(page_manager, memory, region_size * 2);
|
||||
Release(memory);
|
||||
}
|
||||
|
||||
[[noreturn]] void RunDeathCase(const char *name) {
|
||||
|
||||
@@ -162,7 +162,6 @@ void TestWatchAndUnwatch() {
|
||||
auto *memory = Allocate(page_size * 2);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
|
||||
manager.OnGpuMap(address, page_size * 2);
|
||||
manager.UpdatePageWatchers<true>(address, page_size);
|
||||
Check(Protection(memory) == PAGE_READONLY && IsWritable(memory + page_size),
|
||||
"write watch installed incorrect protections");
|
||||
@@ -170,7 +169,6 @@ void TestWatchAndUnwatch() {
|
||||
"watch protection bypassed the address-space owner callback");
|
||||
manager.UpdatePageWatchers<false>(address, page_size);
|
||||
Check(IsWritable(memory), "write unwatch did not restore access");
|
||||
manager.OnGpuUnmap(address, page_size * 2);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -180,7 +178,6 @@ void TestSharedWatcherCounts() {
|
||||
auto *memory = Allocate(page_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
|
||||
manager.OnGpuMap(address, page_size);
|
||||
manager.UpdatePageWatchers<true>(address + 8, 32);
|
||||
manager.UpdatePageWatchers<true>(address + 128, 64);
|
||||
manager.UpdatePageWatchers<false>(address + 8, 32);
|
||||
@@ -188,7 +185,6 @@ void TestSharedWatcherCounts() {
|
||||
"first unwatch released a shared watcher");
|
||||
manager.UpdatePageWatchers<false>(address + 128, 64);
|
||||
Check(IsWritable(memory), "last unwatch did not restore access");
|
||||
manager.OnGpuUnmap(address, page_size);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -203,7 +199,6 @@ void TestCrossRegionRange() {
|
||||
boundary + page_size <= base + region_size * 2,
|
||||
"test allocation does not contain a region boundary");
|
||||
|
||||
manager.OnGpuMap(base, region_size * 2);
|
||||
g_protection_calls = 0;
|
||||
g_protection_ranges.clear();
|
||||
manager.UpdatePageWatchers<true>(boundary - page_size, page_size * 2);
|
||||
@@ -228,7 +223,6 @@ void TestCrossRegionRange() {
|
||||
Check(IsWritable(reinterpret_cast<void *>(boundary - page_size)) &&
|
||||
IsWritable(reinterpret_cast<void *>(boundary)),
|
||||
"cross-region unwatch did not restore both pages");
|
||||
manager.OnGpuUnmap(base, region_size * 2);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -240,7 +234,6 @@ void TestBatchedWatcherRanges() {
|
||||
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);
|
||||
@@ -266,7 +259,6 @@ void TestBatchedWatcherRanges() {
|
||||
IsWritable(memory + allocation_size - page_size),
|
||||
"large cross-region unwatch did not restore the full range");
|
||||
|
||||
manager.OnGpuUnmap(address, allocation_size);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -280,7 +272,6 @@ void TestRegionMaskWatcherRanges() {
|
||||
(allocation_base + region_size - 1) & ~(region_size - 1);
|
||||
Check(region_base + region_size <= allocation_base + region_size * 2,
|
||||
"test allocation does not contain a complete tracking region");
|
||||
manager.OnGpuMap(allocation_base, region_size * 2);
|
||||
|
||||
RegionBits full_mask;
|
||||
full_mask.Fill();
|
||||
@@ -364,7 +355,6 @@ void TestRegionMaskWatcherRanges() {
|
||||
g_protection_ranges[0].size == page_size * 3,
|
||||
"sparse read unmask did not bridge a compatible gap");
|
||||
|
||||
manager.OnGpuUnmap(allocation_base, region_size * 2);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -379,7 +369,6 @@ void TestRegionEndpointBatching() {
|
||||
(allocation_base + region_size - 1) & ~(region_size - 1);
|
||||
Check(region_base + region_size <= allocation_base + region_size * 2,
|
||||
"test allocation does not contain a complete tracking region");
|
||||
manager.OnGpuMap(allocation_base, region_size * 2);
|
||||
|
||||
RegionBits endpoints;
|
||||
endpoints.Set(0);
|
||||
@@ -420,7 +409,6 @@ void TestRegionEndpointBatching() {
|
||||
g_protection_ranges[0].size == region_size,
|
||||
"last full-region unwatch did not use one 4 MiB protection call");
|
||||
|
||||
manager.OnGpuUnmap(allocation_base, region_size * 2);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -434,7 +422,6 @@ void TestReadWriteWatcherInteractions() {
|
||||
(allocation_base + region_size - 1) & ~(region_size - 1);
|
||||
Check(region_base + region_size <= allocation_base + region_size * 2,
|
||||
"test allocation does not contain a complete tracking region");
|
||||
manager.OnGpuMap(allocation_base, region_size * 2);
|
||||
|
||||
RegionBits write_mask;
|
||||
write_mask.SetRange(10, 15);
|
||||
@@ -488,7 +475,6 @@ void TestReadWriteWatcherInteractions() {
|
||||
IsWritable(reinterpret_cast<void *>(region_base + page_size * 13)),
|
||||
"read unwatch did not coalesce through compatible writable state");
|
||||
|
||||
manager.OnGpuUnmap(allocation_base, region_size * 2);
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
@@ -503,20 +489,17 @@ void TestReadWriteWatcherInteractions() {
|
||||
auto doomed = std::make_unique<PageManager>();
|
||||
auto *memory = Allocate(page_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
doomed->OnGpuMap(address, page_size);
|
||||
doomed->UpdatePageWatchers<true>(address, page_size);
|
||||
doomed.reset();
|
||||
} else if (std::strcmp(name, "known-write-underflow") == 0) {
|
||||
auto *memory = Allocate(page_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
manager.OnGpuMap(address, page_size);
|
||||
manager.UpdatePageWatchers<true>(address, page_size);
|
||||
manager.UpdatePageWatchers<false>(address, page_size);
|
||||
manager.UpdatePageWatchers<false>(address, page_size);
|
||||
} else if (std::strcmp(name, "read-overflow") == 0) {
|
||||
auto *memory = Allocate(page_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
manager.OnGpuMap(address, page_size);
|
||||
RegionBits mask;
|
||||
const auto region_base = address & ~(TRACKER_REGION_SIZE - 1);
|
||||
const auto page = static_cast<size_t>((address - region_base) / page_size);
|
||||
@@ -526,7 +509,6 @@ void TestReadWriteWatcherInteractions() {
|
||||
} else if (std::strcmp(name, "write-overflow") == 0) {
|
||||
auto *memory = Allocate(page_size);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
manager.OnGpuMap(address, page_size);
|
||||
for (uint32_t count = 0; count < 128; count++) {
|
||||
manager.UpdatePageWatchers<true>(address, page_size);
|
||||
}
|
||||
|
||||
@@ -25536,7 +25536,6 @@ void CheckStorageTextureGpuOwnedRebindState() {
|
||||
"fixed guest-owner allocation failed");
|
||||
PageManager page_manager;
|
||||
MemoryTracker tracker(page_manager);
|
||||
page_manager.OnGpuMap(base, size);
|
||||
tracker.ForEachUploadRange(
|
||||
base, size, true, [](uint64_t, uint64_t) noexcept {}, []() noexcept {});
|
||||
uint64_t readable = 0;
|
||||
@@ -25588,7 +25587,6 @@ void CheckStorageTextureGpuOwnedRebindState() {
|
||||
|
||||
tracker.UnmarkRegionAsGpuModified(base, size);
|
||||
tracker.UntrackMemory(base, size);
|
||||
page_manager.OnGpuUnmap(base, size);
|
||||
Require("StorageTextureGpuOwnedRebind", "free",
|
||||
Libs::LibKernel::Memory::FreeGuestMemory(base, size),
|
||||
"guest-owner free failed");
|
||||
|
||||
Reference in New Issue
Block a user