From 77d15b02a3cb961c579cbaf448bf373633c137f6 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Thu, 4 Aug 2022 23:40:20 +0100 Subject: [PATCH] Ensure backing continuity when recreating GPU dirty buffers Since we don't call `SynchronizeHost` on source buffers which are GPU dirty, their mirrors will be out of date. The backing contents of this source buffer's region in the new buffer will be incorrect. By copying from the backing directly, we can ensure that no writes are lost and that if the newly created buffer needs to turn GPU dirty during recreation no copies need to be done since the backing is as up to date as the mirror at a minimum. --- app/src/main/cpp/skyline/gpu/buffer_manager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/cpp/skyline/gpu/buffer_manager.cpp b/app/src/main/cpp/skyline/gpu/buffer_manager.cpp index fc0bfd74..e3045dbf 100644 --- a/app/src/main/cpp/skyline/gpu/buffer_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/buffer_manager.cpp @@ -118,6 +118,9 @@ namespace skyline::gpu { copyBuffer(*newBuffer->guest, *srcBuffer->guest, newBuffer->mirror.data(), srcBuffer->backing.data()); else newBuffer->MarkGpuDirty(); + + // Since we don't synchost source buffers and the source buffers here are GPU dirty their mirrors will be out of date, meaning the backing contents of this source buffer's region in the new buffer from the initial synchost call will be incorrect. By copying backings directly here we can ensure that no writes are lost and that if the newly created buffer needs to turn GPU dirty during recreation no copies need to be done since the backing is as up to date as the mirror at a minimum. + copyBuffer(*newBuffer->guest, *srcBuffer->guest, newBuffer->backing.data(), srcBuffer->backing.data()); } else if (srcBuffer->AllCpuBackingWritesBlocked()) { if (srcBuffer->dirtyState == Buffer::DirtyState::CpuDirty) Logger::Error("Buffer (0x{}-0x{}) is marked as CPU dirty while CPU backing writes are blocked, this is not valid", srcBuffer->guest->begin().base(), srcBuffer->guest->end().base());