]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/buffer_backend.cpp
Initial implementation of Vulkan backend
[libs/gl.git] / source / backends / vulkan / buffer_backend.cpp
diff --git a/source/backends/vulkan/buffer_backend.cpp b/source/backends/vulkan/buffer_backend.cpp
new file mode 100644 (file)
index 0000000..4207e87
--- /dev/null
@@ -0,0 +1,127 @@
+#include "buffer.h"
+#include "buffer_backend.h"
+#include "device.h"
+#include "vulkan.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+VulkanBuffer::VulkanBuffer():
+       device(Device::get_current())
+{ }
+
+VulkanBuffer::VulkanBuffer(VulkanBuffer &&other):
+       device(other.device),
+       handle(other.handle),
+       memory_id(other.memory_id),
+       mapped_address(other.mapped_address),
+       debug_name(move(other.debug_name))
+{
+       other.handle = 0;
+       other.memory_id = 0;
+       other.mapped_address = 0;
+}
+
+VulkanBuffer::~VulkanBuffer()
+{
+       if(handle)
+               device.get_destroy_queue().destroy(handle, memory_id);
+}
+
+void VulkanBuffer::allocate()
+{
+       const Buffer &self = *static_cast<const Buffer *>(this);
+       const VulkanFunctions &vk = device.get_functions();
+
+       VkBufferCreateInfo buffer_info = { };
+       buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+       buffer_info.size = self.size;
+       buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT|VK_BUFFER_USAGE_TRANSFER_DST_BIT|VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT|
+               VK_BUFFER_USAGE_INDEX_BUFFER_BIT|VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+       buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+       vk.CreateBuffer(buffer_info, handle);
+
+       memory_id = device.get_allocator().allocate(handle, (self.usage==STREAMING ? STREAMING_MEMORY : DEVICE_MEMORY));
+
+       if(!debug_name.empty())
+               set_vulkan_object_name();
+}
+
+void VulkanBuffer::sub_data(size_t off, size_t sz, const void *d)
+{
+       void *staging = device.get_transfer_queue().prepare_transfer(sz, [this, off, sz](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){
+               const VulkanFunctions &vk = device.get_functions();
+
+               VkBufferCopy region = { };
+               region.srcOffset = src_off;
+               region.dstOffset = off;
+               region.size = sz;
+               vk.CmdCopyBuffer(cmd_buf, staging_buf, handle, 1, &region);
+
+               VkBufferMemoryBarrier barrier = { };
+               barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+               barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
+               barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+               barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+               barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+               barrier.buffer = handle_cast<::VkBuffer>(handle);
+               barrier.offset = off;
+               barrier.size = sz;
+
+               vk.CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                       0, 0, 0, 1, &barrier, 0, 0);
+       });
+
+       const char *src = static_cast<const char *>(d);
+       copy(src, src+sz, static_cast<char *>(staging));
+}
+
+bool VulkanBuffer::can_map() const
+{
+       return static_cast<const Buffer *>(this)->usage==STREAMING;
+}
+
+void *VulkanBuffer::map()
+{
+       size_t size = static_cast<const Buffer *>(this)->size;
+       mapped_address = device.get_allocator().map(memory_id, 0, size);
+       return mapped_address;
+}
+
+bool VulkanBuffer::unmap()
+{
+       device.get_allocator().unmap(mapped_address);
+       mapped_address = 0;
+       return true;
+}
+
+void VulkanBuffer::set_debug_name(const string &name)
+{
+#ifdef DEBUG
+       debug_name = name;
+       if(handle)
+               set_vulkan_object_name();
+#else
+       (void)name;
+#endif
+}
+
+void VulkanBuffer::set_vulkan_object_name() const
+{
+#ifdef DEBUG
+       const VulkanFunctions &vk = device.get_functions();
+
+       VkDebugUtilsObjectNameInfoEXT name_info = { };
+       name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+       name_info.objectType = VK_OBJECT_TYPE_BUFFER;
+       name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
+       name_info.pObjectName = debug_name.c_str();
+       vk.SetDebugUtilsObjectName(name_info);
+#endif
+}
+
+} // namespace GL
+} // namespace Msp