diff --git a/app/src/main/cpp/skyline/gpu/buffer.cpp b/app/src/main/cpp/skyline/gpu/buffer.cpp index 84668b0e..d017a886 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.cpp +++ b/app/src/main/cpp/skyline/gpu/buffer.cpp @@ -145,10 +145,10 @@ namespace skyline::gpu { std::memcpy(data.data(), backing.data() + offset, data.size()); } - void Buffer::Write(span data, vk::DeviceSize offset) { + void Buffer::Write(span data, vk::DeviceSize offset, bool skipCleanHostWrite) { if (dirtyState == DirtyState::CpuDirty || dirtyState == DirtyState::Clean) std::memcpy(mirror.data() + offset, data.data(), data.size()); - if (dirtyState == DirtyState::GpuDirty || dirtyState == DirtyState::Clean) + if ((!skipCleanHostWrite && dirtyState == DirtyState::Clean) || dirtyState == DirtyState::GpuDirty) std::memcpy(backing.data() + offset, data.data(), data.size()); } @@ -234,7 +234,7 @@ namespace skyline::gpu { bufferDelegate->buffer->Read(data, offset + bufferDelegate->view->offset); } - void BufferView::Write(span data, vk::DeviceSize offset) const { - bufferDelegate->buffer->Write(data, offset + bufferDelegate->view->offset); + void BufferView::Write(span data, vk::DeviceSize offset, bool skipCleanHostWrite) const { + bufferDelegate->buffer->Write(data, offset + bufferDelegate->view->offset, skipCleanHostWrite); } } diff --git a/app/src/main/cpp/skyline/gpu/buffer.h b/app/src/main/cpp/skyline/gpu/buffer.h index b9a7b9d4..c1ba6632 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.h +++ b/app/src/main/cpp/skyline/gpu/buffer.h @@ -171,8 +171,9 @@ namespace skyline::gpu { /** * @brief Writes data at the specified offset in the buffer + * @param skipCleanHostWrite Skip writing to the host buffer if it's clean, assumes the buffer data will be synchronised externally */ - void Write(span data, vk::DeviceSize offset); + void Write(span data, vk::DeviceSize offset, bool skipCleanHostWrite = false); /** * @return A cached or newly created view into this buffer with the supplied attributes @@ -250,7 +251,8 @@ namespace skyline::gpu { /** * @brief Writes data at the specified offset in the view * @note The view **must** be locked prior to calling this + * @param skipCleanHostWrite Skip writing to the host buffer if it's clean, assumes the buffer data will be synchronised externally */ - void Write(span data, vk::DeviceSize offset) const; + void Write(span data, vk::DeviceSize offset, bool skipCleanHostWrite = false) const; }; } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 7bf62e13..e3043a12 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -629,7 +629,7 @@ namespace skyline::gpu::interconnect { template void Write(T &object, size_t offset) { std::scoped_lock lock{view}; - view.Write(span(object).template cast(), offset); + view.Write(span(object).template cast(), offset, true); } }; ConstantBuffer constantBufferSelector; //!< The constant buffer selector is used to bind a constant buffer to a stage or update data in it @@ -698,6 +698,11 @@ namespace skyline::gpu::interconnect { if (!view) { auto mappings{channelCtx.asCtx->gmmu.TranslateRange(constantBufferSelector.iova, constantBufferSelector.size)}; view = gpu.buffer.FindOrCreate(mappings.front(), executor.cycle); + { + std::scoped_lock lock{*view}; + view->bufferDelegate->buffer->SynchronizeHost(false); + } + constantBufferCache.Insert(constantBufferSelector.size, constantBufferSelector.iova, *view); } @@ -708,6 +713,11 @@ namespace skyline::gpu::interconnect { void ConstantBufferUpdate(u32 data, u32 offset) { auto constantBuffer{GetConstantBufferSelector().value()}; constantBuffer.Write(data, offset); + + executor.AddNonGraphicsPass([view = constantBuffer.view, data, offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &) { + std::scoped_lock lock{view}; + commandBuffer.updateBuffer(view.bufferDelegate->buffer->GetBacking(), offset, vk::ArrayProxy(1, &data)); + }); } /* Shader Program */