diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index feeafd9b..63391a18 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -119,19 +119,23 @@ public: return buffer; } - std::optional GetBarrier(vk::AccessFlagBits2 dst_acess_mask, - vk::PipelineStageFlagBits2 dst_stage) { + std::optional GetBarrier( + vk::Flags dst_acess_mask, vk::PipelineStageFlagBits2 dst_stage, + u32 offset = 0) { if (dst_acess_mask == access_mask && stage == dst_stage) { return {}; } + DEBUG_ASSERT(offset < size_bytes); + auto barrier = vk::BufferMemoryBarrier2{ .srcStageMask = stage, .srcAccessMask = access_mask, .dstStageMask = dst_stage, .dstAccessMask = dst_acess_mask, .buffer = buffer.buffer, - .size = size_bytes, + .offset = offset, + .size = size_bytes - offset, }; access_mask = dst_acess_mask; stage = dst_stage; @@ -150,8 +154,10 @@ public: Vulkan::Scheduler* scheduler; MemoryUsage usage; UniqueBuffer buffer; - vk::AccessFlagBits2 access_mask{vk::AccessFlagBits2::eNone}; - vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eNone}; + vk::Flags access_mask{ + vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite | + vk::AccessFlagBits2::eTransferRead | vk::AccessFlagBits2::eTransferWrite}; + vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eAllCommands}; }; class StreamBuffer : public Buffer { diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 322a9dd4..d5ebd85f 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -479,43 +479,36 @@ void BufferCache::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, }; scheduler.EndRendering(); const auto cmdbuf = scheduler.CommandBuffer(); - const std::array pre_barriers = { - vk::BufferMemoryBarrier2{ - .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, - .srcAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, - .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, - .dstAccessMask = vk::AccessFlagBits2::eTransferRead, - .buffer = overlap.Handle(), - .offset = 0, - .size = overlap.SizeBytes(), - }, - }; - const std::array post_barriers = { - vk::BufferMemoryBarrier2{ - .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, - .srcAccessMask = vk::AccessFlagBits2::eTransferRead, - .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, - .dstAccessMask = vk::AccessFlagBits2::eMemoryWrite, - .buffer = overlap.Handle(), - .offset = 0, - .size = overlap.SizeBytes(), - }, - vk::BufferMemoryBarrier2{ - .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, - .srcAccessMask = vk::AccessFlagBits2::eTransferWrite, - .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, - .dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, - .buffer = new_buffer.Handle(), - .offset = dst_base_offset, - .size = overlap.SizeBytes(), - }, - }; + + boost::container::static_vector pre_barriers{}; + if (auto src_barrier = overlap.GetBarrier(vk::AccessFlagBits2::eTransferRead, + vk::PipelineStageFlagBits2::eTransfer)) { + pre_barriers.push_back(*src_barrier); + } + if (auto dst_barrier = + new_buffer.GetBarrier(vk::AccessFlagBits2::eTransferWrite, + vk::PipelineStageFlagBits2::eTransfer, dst_base_offset)) { + pre_barriers.push_back(*dst_barrier); + } cmdbuf.pipelineBarrier2(vk::DependencyInfo{ .dependencyFlags = vk::DependencyFlagBits::eByRegion, - .bufferMemoryBarrierCount = 1, + .bufferMemoryBarrierCount = static_cast(pre_barriers.size()), .pBufferMemoryBarriers = pre_barriers.data(), }); + cmdbuf.copyBuffer(overlap.Handle(), new_buffer.Handle(), copy); + + boost::container::static_vector post_barriers{}; + if (auto src_barrier = + overlap.GetBarrier(vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + vk::PipelineStageFlagBits2::eAllCommands)) { + post_barriers.push_back(*src_barrier); + } + if (auto dst_barrier = new_buffer.GetBarrier( + vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + vk::PipelineStageFlagBits2::eAllCommands, dst_base_offset)) { + post_barriers.push_back(*dst_barrier); + } cmdbuf.pipelineBarrier2(vk::DependencyInfo{ .dependencyFlags = vk::DependencyFlagBits::eByRegion, .bufferMemoryBarrierCount = static_cast(post_barriers.size()), @@ -626,7 +619,8 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, const auto cmdbuf = scheduler.CommandBuffer(); const vk::BufferMemoryBarrier2 pre_barrier = { .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, - .srcAccessMask = vk::AccessFlagBits2::eMemoryRead, + .srcAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite | + vk::AccessFlagBits2::eTransferRead | vk::AccessFlagBits2::eTransferWrite, .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, .dstAccessMask = vk::AccessFlagBits2::eTransferWrite, .buffer = buffer.Handle(),