]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/buffer_backend.cpp
Make Buffer::AsyncTransfer default-constructible and move-assignable
[libs/gl.git] / source / backends / vulkan / buffer_backend.cpp
1 #include "buffer.h"
2 #include "buffer_backend.h"
3 #include "device.h"
4 #include "vulkan.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 VulkanBuffer::VulkanBuffer():
12         device(Device::get_current())
13 { }
14
15 VulkanBuffer::VulkanBuffer(VulkanBuffer &&other):
16         device(other.device),
17         handle(other.handle),
18         memory_id(other.memory_id),
19         mapped_address(other.mapped_address),
20         debug_name(move(other.debug_name))
21 {
22         other.handle = 0;
23         other.memory_id = 0;
24         other.mapped_address = 0;
25 }
26
27 VulkanBuffer::~VulkanBuffer()
28 {
29         if(handle)
30                 device.get_destroy_queue().destroy(handle, memory_id);
31 }
32
33 void VulkanBuffer::allocate()
34 {
35         const Buffer &self = *static_cast<const Buffer *>(this);
36         const VulkanFunctions &vk = device.get_functions();
37
38         VkBufferCreateInfo buffer_info = { };
39         buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
40         buffer_info.size = self.get_total_size();
41         buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT|VK_BUFFER_USAGE_TRANSFER_DST_BIT|VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT|
42                 VK_BUFFER_USAGE_INDEX_BUFFER_BIT|VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
43         buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
44
45         vk.CreateBuffer(buffer_info, handle);
46
47         memory_id = device.get_allocator().allocate(handle, (self.usage==STREAMING ? STREAMING_MEMORY : DEVICE_MEMORY));
48
49         if(!debug_name.empty())
50                 set_vulkan_object_name();
51 }
52
53 void VulkanBuffer::sub_data(size_t off, size_t sz, const void *d)
54 {
55         Buffer::AsyncTransfer transfer(*static_cast<Buffer *>(this), off, sz);
56         const char *src = static_cast<const char *>(d);
57         copy(src, src+sz, static_cast<char *>(transfer.get_address()));
58 }
59
60 unsigned VulkanBuffer::get_multiplicity() const
61 {
62         BufferUsage usage = static_cast<const Buffer *>(this)->usage;
63         return (usage==STREAMING ? device.get_n_frames_in_flight() : 1);
64 }
65
66 bool VulkanBuffer::can_map() const
67 {
68         return static_cast<const Buffer *>(this)->usage==STREAMING;
69 }
70
71 void *VulkanBuffer::map()
72 {
73         size_t size = static_cast<const Buffer *>(this)->size;
74         mapped_address = device.get_allocator().map(memory_id, 0, size);
75         return mapped_address;
76 }
77
78 bool VulkanBuffer::unmap()
79 {
80         device.get_allocator().unmap(mapped_address);
81         mapped_address = 0;
82         return true;
83 }
84
85 void VulkanBuffer::set_debug_name(const string &name)
86 {
87 #ifdef DEBUG
88         debug_name = name;
89         if(handle)
90                 set_vulkan_object_name();
91 #else
92         (void)name;
93 #endif
94 }
95
96 void VulkanBuffer::set_vulkan_object_name() const
97 {
98 #ifdef DEBUG
99         const VulkanFunctions &vk = device.get_functions();
100
101         VkDebugUtilsObjectNameInfoEXT name_info = { };
102         name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
103         name_info.objectType = VK_OBJECT_TYPE_BUFFER;
104         name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
105         name_info.pObjectName = debug_name.c_str();
106         vk.SetDebugUtilsObjectName(name_info);
107 #endif
108 }
109
110
111 void Buffer::AsyncTransfer::allocate()
112 {
113         if(buffer->can_map())
114                 dest_addr = static_cast<char *>(buffer->map())+offset;
115         else
116         {
117                 Buffer &buf = *buffer;
118                 size_t off = offset;
119                 size_t sz = size;
120
121                 dest_addr = buf.device.get_transfer_queue().prepare_transfer(buffer, false, size,
122                         [&buf, off, sz](){
123                                 buf.device.get_synchronizer().write_buffer(buf.handle, off, sz);
124                         },
125                         [&buf, off, sz](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
126                                 const VulkanFunctions &vk = buf.device.get_functions();
127
128                                 VkBufferCopy region = { };
129                                 region.srcOffset = src_off;
130                                 region.dstOffset = off;
131                                 region.size = sz;
132                                 vk.CmdCopyBuffer(cmd_buf, staging_buf, buf.handle, 1, &region);
133                         });
134         }
135 }
136
137 void Buffer::AsyncTransfer::finalize()
138 {
139         if(buffer->can_map())
140         {
141                 buffer->unmap();
142                 buffer->device.get_synchronizer().write_buffer(buffer->handle, offset, size, true);
143         }
144         else
145                 buffer->device.get_transfer_queue().finalize_transfer(dest_addr);
146 }
147
148 } // namespace GL
149 } // namespace Msp