]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/transferqueue.cpp
Use another callback for pre-transfer synchronization
[libs/gl.git] / source / backends / vulkan / transferqueue.cpp
1 #include <msp/core/algorithm.h>
2 #include "device.h"
3 #include "transferqueue.h"
4 #include "vulkan.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 TransferQueue::TransferQueue(Device &d):
12         device(d)
13 { }
14
15 TransferQueue::PendingTransfer &TransferQueue::prepare_transfer(size_t size)
16 {
17         auto i = find_if(buffers, [size](const StagingBuffer &b){ return b.used+size<=b.size; });
18         if(i==buffers.end())
19         {
20                 buffers.emplace_back(device, max(default_buffer_size, size));
21                 i = prev(buffers.end());
22         }
23
24         PendingTransfer transfer;
25         transfer.buffer_index = distance(buffers.begin(), i);
26         transfer.offset = i->used;
27         transfer.size = size;
28         transfers.push_back(transfer);
29
30         i->used += size;
31
32         return transfers.back();
33 }
34
35 void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer)
36 {
37         if(transfers.empty())
38                 return;
39
40         for(const PendingTransfer &t: transfers)
41                 t.synchronize();
42
43         device.get_synchronizer().barrier(command_buffer);
44
45         for(const PendingTransfer &t: transfers)
46         {
47                 VkBuffer buffer = buffers[t.buffer_index].buffer;
48                 t.transfer(command_buffer, buffer, t.offset);
49         }
50
51         transfers.clear();
52 }
53
54
55 TransferQueue::StagingBuffer::StagingBuffer(Device &d, size_t s):
56         device(d),
57         size(s)
58 {
59         const VulkanFunctions &vk = device.get_functions();
60
61         VkBufferCreateInfo buffer_info = { };
62         buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
63         buffer_info.size = size;
64         buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
65         buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
66
67         vk.CreateBuffer(buffer_info, buffer);
68
69         MemoryAllocator &allocator = device.get_allocator();
70         memory_id = allocator.allocate(buffer, STAGING_MEMORY);
71         mapped_address = allocator.map(memory_id, 0, size);
72 }
73
74 TransferQueue::StagingBuffer::StagingBuffer(StagingBuffer &&other):
75         device(other.device),
76         buffer(other.buffer),
77         memory_id(other.memory_id),
78         size(other.size),
79         used(other.used),
80         mapped_address(other.mapped_address)
81 {
82         other.buffer = 0;
83         other.memory_id = 0;
84         other.mapped_address = 0;
85 }
86
87 TransferQueue::StagingBuffer::~StagingBuffer()
88 {
89         const VulkanFunctions &vk = device.get_functions();
90         MemoryAllocator &allocator = device.get_allocator();
91
92         if(mapped_address)
93         {
94                 allocator.unmap(mapped_address);
95                 allocator.release(memory_id);
96         }
97         if(buffer)
98                 vk.DestroyBuffer(buffer);
99 }
100
101 } // namespace GL
102 } // namespace Msp