mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 08:13:05 +00:00
graphics: copy sparse buffer uploads through resident mappings
This commit is contained in:
1 parent
9a3aca963a
commit
40692dfb64
6 files changed
+172
-42
No files matched your search
@@ -5344,6 +5344,47 @@ public:
|
||||
ReadBuffer(name, readback, 8) == std::vector<u32>{0x00020001u, 0x00020001u, 0u, 0u,
|
||||
0x00020101u, 0xabcdef01u, 0x00020103u, 0x00040101u},
|
||||
"upload lost sparse holes, boundary bytes, compute access, or in-flight lifetime");
|
||||
// Cached uploads must read reserved holes without faulting back into the tracker,
|
||||
// while retaining the private-memory sources accepted by ordinary buffer reads.
|
||||
const auto private_base = LibKernel::Memory::AllocateRuntimeMemory(
|
||||
0, page, Common::VirtualMemory::Mode::ReadWrite, "private_buffer_upload");
|
||||
Require(name, "private source allocation", private_base != 0, "private allocation failed");
|
||||
auto *private_words = reinterpret_cast<u32 *>(private_base);
|
||||
private_words[0] = 0x55667788u;
|
||||
private_words[page / sizeof(u32) - 1u] = 0x99aabbccu;
|
||||
context.MapMemory(private_base, page);
|
||||
context.MapMemory(base + page, 2u * page);
|
||||
const auto sparse_buffer = cache.ObtainBuffer(base, 2u * page, false);
|
||||
const auto private_buffer = cache.ObtainBuffer(private_base, page, false);
|
||||
const auto sparse_stream = cache.ObtainBuffer(base + 2u * page, sizeof(u32), false);
|
||||
Require(name, "sparse stream source",
|
||||
sparse_stream.first == &cache.GetUtilityBuffer(MemoryUsage::Stream),
|
||||
"small sparse read did not exercise the stream path");
|
||||
const std::array<vk::BufferCopy, 2> sparse_copies{{
|
||||
{sparse_buffer.second, 0, sizeof(u32)},
|
||||
{sparse_buffer.second + page, sizeof(u32), sizeof(u32)}}};
|
||||
const std::array<vk::BufferCopy, 2> private_copies{{
|
||||
{private_buffer.second, 2u * sizeof(u32), sizeof(u32)},
|
||||
{private_buffer.second + page - sizeof(u32), 3u * sizeof(u32), sizeof(u32)}}};
|
||||
scheduler.Current().Handle().copyBuffer(sparse_buffer.first->Handle(), readback.buffer,
|
||||
sparse_copies.size(), sparse_copies.data());
|
||||
scheduler.Current().Handle().copyBuffer(private_buffer.first->Handle(), readback.buffer,
|
||||
private_copies.size(), private_copies.data());
|
||||
const vk::BufferCopy stream_copy{sparse_stream.second, 4u * sizeof(u32), sizeof(u32)};
|
||||
scheduler.Current().Handle().copyBuffer(sparse_stream.first->Handle(), readback.buffer,
|
||||
1, &stream_copy);
|
||||
scheduler.Current().Handle().pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::PipelineStageFlagBits::eHost, {}, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||
scheduler.Finish();
|
||||
Require(name, "cached sparse and private upload",
|
||||
ReadBuffer(name, readback, 5) == std::vector<u32>{0x00020001u, 0u, 0x55667788u, 0x99aabbccu, 0u} &&
|
||||
!cache.IsRegionGpuModified(base, 2u * page) &&
|
||||
!cache.IsRegionGpuModified(private_base, page),
|
||||
"cached upload lost sparse/private data or changed read-only GPU ownership");
|
||||
context.UnmapMemory(private_base, page);
|
||||
context.UnmapMemory(base + page, 2u * page);
|
||||
Require(name, "private source release", LibKernel::Memory::FreeGuestMemory(private_base, page),
|
||||
"private allocation release failed");
|
||||
DestroyBuffer(&readback);
|
||||
for (const auto offset : mapped_offsets) context.UnmapMemory(base + offset, page);
|
||||
scheduler.Finish();
|
||||
|
||||
@@ -619,7 +619,8 @@ void TestConcurrentBackingReads() {
|
||||
constexpr uint64_t original = 0x123456789abcdef0ull;
|
||||
for (const auto& readers: {std::pair {&TryReadBacking, &TryReadBacking},
|
||||
std::pair {&TryReadBacking, &TryReadSparseBacking},
|
||||
std::pair {&TryReadSparseBacking, &TryReadSparseBacking}}) {
|
||||
std::pair {&TryReadSparseBacking, &TryReadSparseBacking},
|
||||
std::pair {&CopySparseMemory, &CopySparseMemory}}) {
|
||||
const auto base = MapNamedFlexible(test, SceKernelPageSize, SceKernelProtCpuRw,
|
||||
"concurrent_backing_reads");
|
||||
std::memcpy(reinterpret_cast<void*>(base), &original, sizeof(original));
|
||||
@@ -654,7 +655,7 @@ void TestBackingReadExcludesWritesAndUnmap() {
|
||||
const char* test = "BackingReadExcludesWritesAndUnmap";
|
||||
constexpr uint64_t original = 0x123456789abcdef0ull;
|
||||
constexpr uint64_t replacement = 0xfedcba9876543210ull;
|
||||
for (const auto read: {TryReadBacking, TryReadSparseBacking}) {
|
||||
for (const auto read: {TryReadBacking, TryReadSparseBacking, CopySparseMemory}) {
|
||||
for (const bool unmap: {false, true}) {
|
||||
const auto base = MapNamedFlexible(test, SceKernelPageSize, SceKernelProtCpuRw,
|
||||
"backing_read_exclusion");
|
||||
@@ -1152,6 +1153,54 @@ void TestRuntimeMemoryOwnerLifecycle() {
|
||||
std::printf("[host] %-48s ok\n", test);
|
||||
}
|
||||
|
||||
void TestCopySparseMemoryMappings() {
|
||||
using namespace Libs::LibKernel::Memory;
|
||||
const char* test = "CopySparseMemoryMappings";
|
||||
constexpr uint64_t size = SceKernelPageSize * 5;
|
||||
const auto base = AllocateRuntimeMemory(0, size, Common::VirtualMemory::Mode::ReadWrite,
|
||||
"sparse_copy_private");
|
||||
Check(test, base != 0, "private allocation failed");
|
||||
for (const auto page : {0u, 2u, 4u}) {
|
||||
Check(test, FreeGuestMemory(base + page * SceKernelPageSize, SceKernelPageSize),
|
||||
"private page release failed");
|
||||
}
|
||||
void* shared = reinterpret_cast<void*>(base);
|
||||
CheckOk(test, KernelMapNamedFlexibleMemory(&shared, SceKernelPageSize, SceKernelProtCpuRw,
|
||||
SceKernelMapFixed, "sparse_copy_shared"),
|
||||
"map shared first page");
|
||||
constexpr std::array<uint8_t, 5> values {0x3c, 0xa7, 0, 0x5d, 0};
|
||||
for (const auto page : {0u, 1u, 3u}) {
|
||||
std::memset(reinterpret_cast<void*>(base + page * SceKernelPageSize), values[page],
|
||||
SceKernelPageSize);
|
||||
}
|
||||
CheckOk(test, KernelMprotect(shared, SceKernelPageSize, 0), "protect shared first page");
|
||||
constexpr uint64_t prefix = 29, suffix = 17, copied = size - prefix - suffix;
|
||||
std::vector<uint8_t> bytes(copied + 2, 0x55);
|
||||
Check(test, !TryReadSparseBacking(base + prefix, bytes.data() + 1, copied) &&
|
||||
std::all_of(bytes.begin(), bytes.end(), [](uint8_t value) { return value == 0x55; }),
|
||||
"strict backing read accepted private memory or changed its destination");
|
||||
Check(test, CopySparseMemory(base + prefix, bytes.data() + 1, copied),
|
||||
"sparse copy rejected mixed shared, private and unbacked pages");
|
||||
Check(test, bytes.front() == 0x55 && bytes.back() == 0x55,
|
||||
"sparse copy overwrote destination canaries");
|
||||
for (uint64_t i = 0; i < copied; ++i) {
|
||||
Check(test, bytes[i + 1] == values[(prefix + i) / SceKernelPageSize],
|
||||
"sparse copy misplaced mapped data or an unbacked gap");
|
||||
}
|
||||
uint64_t canary = UINT64_MAX;
|
||||
Check(test, !CopySparseMemory(0x10000, &canary, sizeof(canary)) &&
|
||||
!CopySparseMemory(UINT64_MAX - 3, &canary, sizeof(canary)) &&
|
||||
!CopySparseMemory(base, &canary, 0) &&
|
||||
!CopySparseMemory(base, nullptr, sizeof(canary)) && canary == UINT64_MAX,
|
||||
"invalid sparse copy accepted its range or changed its destination");
|
||||
CheckOk(test, KernelMunmap(base, SceKernelPageSize), "unmap shared first page");
|
||||
for (const auto page : {1u, 3u}) {
|
||||
Check(test, FreeGuestMemory(base + page * SceKernelPageSize, SceKernelPageSize),
|
||||
"private page cleanup failed");
|
||||
}
|
||||
std::printf("[host] %-48s ok\n", test);
|
||||
}
|
||||
|
||||
void TestFlexibleMapQueryAndWholeMunmap() {
|
||||
const char* test = "FlexibleMapQueryAndWholeMunmap";
|
||||
const auto baseline = AvailableFlexibleMemory(test);
|
||||
@@ -4420,6 +4469,7 @@ int main(int argc, char** argv) {
|
||||
RunTest(TestConcurrentBackingReads);
|
||||
RunTest(TestBackingReadExcludesWritesAndUnmap);
|
||||
RunTest(TestSparseBackingReadPreservesResidency);
|
||||
RunTest(TestCopySparseMemoryMappings);
|
||||
RunTest(TestSparseReadDuringDirectCommit);
|
||||
RunTest(TestDirectMapQueryOffsetAndPartialMunmap);
|
||||
RunTest(TestFlexibleMemoryUsesSharedBacking);
|
||||
@@ -4473,6 +4523,7 @@ int main(int argc, char** argv) {
|
||||
RunTest(TestProsperoArgumentAndInfoSizeContracts);
|
||||
RunTest(TestGuestAddressSpaceOwnsReservationsBeforeBacking);
|
||||
RunTest(TestSparseBackingReadPreservesResidency);
|
||||
RunTest(TestCopySparseMemoryMappings);
|
||||
RunTest(TestSparseReadDuringDirectCommit);
|
||||
RunTest(TestConcurrentBackingReads);
|
||||
RunTest(TestBackingReadExcludesWritesAndUnmap);
|
||||
|
||||
Reference in new issue
Block a user