VulkanBufferCache: Avoid adding barriers between multiple copies.
This commit is contained in:
parent
99547d2656
commit
c5dbd93adb
|
@ -853,12 +853,14 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
|
||||||
}
|
}
|
||||||
if constexpr (USE_MEMORY_MAPS) {
|
if constexpr (USE_MEMORY_MAPS) {
|
||||||
auto download_staging = runtime.DownloadStagingBuffer(total_size_bytes);
|
auto download_staging = runtime.DownloadStagingBuffer(total_size_bytes);
|
||||||
|
runtime.PreCopyBarrier();
|
||||||
for (auto& [copy, buffer_id] : downloads) {
|
for (auto& [copy, buffer_id] : downloads) {
|
||||||
// Have in mind the staging buffer offset for the copy
|
// Have in mind the staging buffer offset for the copy
|
||||||
copy.dst_offset += download_staging.offset;
|
copy.dst_offset += download_staging.offset;
|
||||||
const std::array copies{copy};
|
const std::array copies{copy};
|
||||||
runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies);
|
runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies, false);
|
||||||
}
|
}
|
||||||
|
runtime.PostCopyBarrier();
|
||||||
runtime.Finish();
|
runtime.Finish();
|
||||||
for (const auto& [copy, buffer_id] : downloads) {
|
for (const auto& [copy, buffer_id] : downloads) {
|
||||||
const Buffer& buffer = slot_buffers[buffer_id];
|
const Buffer& buffer = slot_buffers[buffer_id];
|
||||||
|
|
|
@ -146,7 +146,7 @@ void BufferCacheRuntime::Finish() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
||||||
std::span<const VideoCommon::BufferCopy> copies) {
|
std::span<const VideoCommon::BufferCopy> copies, bool barrier) {
|
||||||
static constexpr VkMemoryBarrier READ_BARRIER{
|
static constexpr VkMemoryBarrier READ_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -163,10 +163,42 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
||||||
boost::container::small_vector<VkBufferCopy, 3> vk_copies(copies.size());
|
boost::container::small_vector<VkBufferCopy, 3> vk_copies(copies.size());
|
||||||
std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy);
|
std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy);
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([src_buffer, dst_buffer, vk_copies](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
|
||||||
|
if (barrier) {
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
||||||
|
}
|
||||||
|
cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
|
||||||
|
if (barrier) {
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::PreCopyBarrier() {
|
||||||
|
static constexpr VkMemoryBarrier READ_BARRIER{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
};
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, READ_BARRIER);
|
0, READ_BARRIER);
|
||||||
cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferCacheRuntime::PostCopyBarrier() {
|
||||||
|
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
|
};
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
0, WRITE_BARRIER);
|
0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
|
|
|
@ -69,8 +69,12 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
|
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
|
||||||
|
|
||||||
|
void PreCopyBarrier();
|
||||||
|
|
||||||
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
|
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
|
||||||
std::span<const VideoCommon::BufferCopy> copies);
|
std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
|
||||||
|
|
||||||
|
void PostCopyBarrier();
|
||||||
|
|
||||||
void ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value);
|
void ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value);
|
||||||
|
|
||||||
|
|
Reference in New Issue