1 #include <msp/core/algorithm.h>
5 #include "synchronizer.h"
13 Synchronizer::Synchronizer(Device &d):
17 void Synchronizer::access(VkBuffer buffer, size_t offset, size_t size)
19 auto i = find_member(buffer_accesses, buffer, &BufferAccess::buffer);
20 if(i==buffer_accesses.end())
22 i = buffer_accesses.emplace(buffer_accesses.end());
29 size_t begin = min(offset, i->offset);
30 size_t end = max(offset+size, i->offset+i->size);
35 i->pending_write = true;
38 void Synchronizer::reset()
40 for(BufferAccess &b: buffer_accesses)
41 b.pending_write = false;
44 void Synchronizer::barrier(VkCommandBuffer command_buffer)
46 const VulkanFunctions &vk = device.get_functions();
48 if(buffer_accesses.empty())
51 VkPipelineStageFlags src_stage = 0;
52 VkPipelineStageFlags dst_stage = 0;
54 static constexpr VkPipelineStageFlags buffer_read_stages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT|
55 VK_PIPELINE_STAGE_VERTEX_SHADER_BIT|VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
56 static constexpr VkPipelineStageFlags buffer_write_stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
58 vector<VkBufferMemoryBarrier> buffer_barriers;
59 buffer_barriers.reserve(buffer_accesses.size());
60 for(BufferAccess &b: buffer_accesses)
62 buffer_barriers.emplace_back(VkBufferMemoryBarrier{ });
63 VkBufferMemoryBarrier &barrier = buffer_barriers.back();
65 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
66 barrier.srcAccessMask = (b.was_written ? VK_ACCESS_MEMORY_WRITE_BIT : 0);
67 barrier.dstAccessMask = (b.pending_write ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_MEMORY_READ_BIT);
68 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
69 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
70 barrier.buffer = handle_cast<::VkBuffer>(b.buffer);
71 barrier.offset = b.offset;
72 barrier.size = b.size;
74 src_stage |= (b.was_written ? buffer_write_stages : buffer_read_stages);
75 dst_stage |= (b.pending_write ? buffer_write_stages : buffer_read_stages);
79 src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
81 dst_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
83 vk.CmdPipelineBarrier(command_buffer, src_stage, dst_stage, 0, 0, 0,
84 buffer_barriers.size(), buffer_barriers.data(), 0, 0);
86 for(auto i=buffer_accesses.begin(); i!=buffer_accesses.end(); )
89 i = buffer_accesses.erase(i);
92 i->was_written = i->pending_write;