diff --git a/app/src/main/cpp/skyline/gpu/buffer.cpp b/app/src/main/cpp/skyline/gpu/buffer.cpp index 5db282d6..693fe230 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.cpp +++ b/app/src/main/cpp/skyline/gpu/buffer.cpp @@ -223,7 +223,7 @@ namespace skyline::gpu { std::memcpy(data.data(), mirror.data() + offset, data.size()); } - void Buffer::Write(bool isFirstUsage, const std::function &flushHostCallback, const std::function &gpuCopyCallback, span data, vk::DeviceSize offset) { + bool Buffer::Write(bool isFirstUsage, const std::function &flushHostCallback, span data, vk::DeviceSize offset, const std::function &gpuCopyCallback) { AdvanceSequence(); // We are modifying GPU backing contents so advance to the next sequence everHadInlineUpdate = true; @@ -238,12 +238,19 @@ namespace skyline::gpu { 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 (!SequencedCpuBackingWritesBlocked() && PollFence()) + 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()); - else + } else { // If this buffer is host immutable, perform a GPU-side inline update for the buffer contents since we can't directly modify the backing - gpuCopyCallback(); + // If no copy callback is supplied, return true to indicate that the caller should repeat the write with an appropriate callback + if (gpuCopyCallback) + gpuCopyCallback(); + else + return true; + } + + return false; } BufferView Buffer::GetView(vk::DeviceSize offset, vk::DeviceSize size) { diff --git a/app/src/main/cpp/skyline/gpu/buffer.h b/app/src/main/cpp/skyline/gpu/buffer.h index f8742882..00074463 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.h +++ b/app/src/main/cpp/skyline/gpu/buffer.h @@ -245,9 +245,10 @@ namespace skyline::gpu { * @brief Writes data at the specified offset in the buffer, falling back to GPU side copies if the buffer is host immutable * @param isFirstUsage If this is the first usage of this resource in the context as returned from LockWithTag(...) * @param flushHostCallback Callback to flush and execute all pending GPU work to allow for synchronisation of GPU dirty buffers - * @param gpuCopyCallback Callback to perform a GPU-side copy for this Write + * @param gpuCopyCallback Optional callback to perform a GPU-side copy for this Write if necessary, if such a copy is needed and this is not supplied `true` will be returned to indicate that the write needs to be repeated with the callback present + * @return Whether the write needs to be repeated with `gpuCopyCallback` provided, always false if `gpuCopyCallback` is provided */ - void Write(bool isFirstUsage, const std::function &flushHostCallback, const std::function &gpuCopyCallback, span data, vk::DeviceSize offset); + bool Write(bool isFirstUsage, const std::function &flushHostCallback, span data, vk::DeviceSize offset, const std::function &gpuCopyCallback = {}); /** * @return A view into this buffer with the supplied attributes