diff --git a/app/src/main/cpp/skyline/gpu/buffer.cpp b/app/src/main/cpp/skyline/gpu/buffer.cpp index 693fe230..b7b3c477 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.cpp +++ b/app/src/main/cpp/skyline/gpu/buffer.cpp @@ -231,13 +231,19 @@ namespace skyline::gpu { std::scoped_lock lock{stateMutex}; // Syncs in both directions to ensure correct ordering of writes - if (dirtyState == DirtyState::CpuDirty) - SynchronizeHost(); - else if (dirtyState == DirtyState::GpuDirty) + if (dirtyState == DirtyState::GpuDirty) SynchronizeGuestImmediate(isFirstUsage, flushHostCallback); + if (dirtyState == DirtyState::CpuDirty && SequencedCpuBackingWritesBlocked()) + // If the buffer is used in sequence directly on the GPU, SynchronizeHost before modifying the mirror contents to ensure proper sequencing. This write will then be sequenced on the GPU instead (the buffer will be kept clean for the rest of the execution due to gpuCopyCallback blocking all writes) + SynchronizeHost(); + std::memcpy(mirror.data() + offset, data.data(), data.size()); // Always copy to mirror since any CPU side reads will need the up-to-date contents + if (dirtyState == DirtyState::CpuDirty && !SequencedCpuBackingWritesBlocked()) + // Skip updating backing if the changes are gonna be updated later by SynchroniseHost in executor anyway + return false; + if (!SequencedCpuBackingWritesBlocked() && PollFence()) { // We can write directly to the backing as long as this resource isn't being actively used by a past workload (in the current context or another) std::memcpy(backing.data() + offset, data.data(), data.size()); @@ -269,8 +275,6 @@ namespace skyline::gpu { // Bail out if buffer cannot be synced, we don't know the contents ahead of time so the sequence is indeterminate return {}; - SynchronizeHost(); // Ensure that the returned mirror is fully up-to-date by performing a CPU -> GPU sync - return {sequenceNumber, mirror}; }