40 VmaVulkanFunctions vulkan_functions = {};
41 vulkan_functions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
42 vulkan_functions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
44 VmaAllocatorCreateInfo allocator_info = {};
45 allocator_info.vulkanApiVersion = VK_API_VERSION_1_3;
46 allocator_info.physicalDevice = *context.getPhysicalDevice();
47 allocator_info.device = *context.getDevice();
48 allocator_info.instance = *context.getInstanceRef();
49 allocator_info.pVulkanFunctions = &vulkan_functions;
51 if (vmaCreateAllocator(&allocator_info, &allocator) != VK_SUCCESS) {
52 throw std::runtime_error(
"Failed to create VMA allocator");
55 vk::CommandPoolCreateInfo pool_info(
56 vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
57 context.getQueueFamilyIndex());
58 transfer_pool = vk::raii::CommandPool(context.getDevice(), pool_info);
60 vk::CommandBufferAllocateInfo cmd_info(*transfer_pool,
61 vk::CommandBufferLevel::ePrimary, 1);
62 auto cmd_buffers = vk::raii::CommandBuffers(context.getDevice(), cmd_info);
63 transfer_cmd = std::move(cmd_buffers[0]);
65 vk::FenceCreateInfo fence_info;
66 transfer_fence = vk::raii::Fence(context.getDevice(), fence_info);
76 VkBufferUsageFlags usage) {
77 VkBufferCreateInfo buffer_info = {};
78 buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
79 buffer_info.
size = size;
80 buffer_info.usage = usage;
81 buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
83 VmaAllocationCreateInfo alloc_info = {};
84 alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
86 VkBuffer buffer = VK_NULL_HANDLE;
87 VmaAllocation allocation = VK_NULL_HANDLE;
88 VmaAllocationInfo allocation_info = {};
90 if (vmaCreateBuffer(allocator, &buffer_info, &alloc_info, &buffer,
91 &allocation, &allocation_info) != VK_SUCCESS) {
92 throw std::runtime_error(
"Failed to create GPU buffer");
95 return {buffer, allocation, allocation_info, size};
100 VkBufferCreateInfo buffer_info = {};
101 buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
102 buffer_info.
size = size;
103 buffer_info.usage = for_upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT
104 : VK_BUFFER_USAGE_TRANSFER_DST_BIT;
105 buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
107 VmaAllocationCreateInfo alloc_info = {};
108 alloc_info.usage = VMA_MEMORY_USAGE_AUTO;
109 alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
110 VMA_ALLOCATION_CREATE_MAPPED_BIT;
112 alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT |
113 VMA_ALLOCATION_CREATE_MAPPED_BIT;
116 VkBuffer buffer = VK_NULL_HANDLE;
117 VmaAllocation allocation = VK_NULL_HANDLE;
118 VmaAllocationInfo allocation_info = {};
120 if (vmaCreateBuffer(allocator, &buffer_info, &alloc_info, &buffer,
121 &allocation, &allocation_info) != VK_SUCCESS) {
122 throw std::runtime_error(
"Failed to create staging buffer");
125 return {buffer, allocation, allocation_info, size};
138 VkDeviceSize size, VkDeviceSize offset) {
141 std::memcpy(staging.getMappedData(), data, size);
143 vk::CommandBufferBeginInfo begin_info(
144 vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
145 transfer_cmd.begin(begin_info);
147 vk::BufferCopy copy_region(0, offset, size);
148 transfer_cmd.copyBuffer(staging.buffer, gpu_buffer.
buffer, copy_region);
152 vk::SubmitInfo submit_info;
153 submit_info.setCommandBuffers(*transfer_cmd);
154 context.submit(submit_info, *transfer_fence);
157 context.getDevice().waitForFences(*transfer_fence, VK_TRUE, UINT64_MAX);
158 if (result != vk::Result::eSuccess) {
159 throw std::runtime_error(
"Failed to wait for upload fence");
161 context.getDevice().resetFences(*transfer_fence);
167 VkDeviceSize size, VkDeviceSize offset) {
170 vk::CommandBufferBeginInfo begin_info(
171 vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
172 transfer_cmd.begin(begin_info);
174 vk::BufferCopy copy_region(offset, 0, size);
175 transfer_cmd.copyBuffer(gpu_buffer.
buffer, staging.buffer, copy_region);
179 vk::SubmitInfo submit_info;
180 submit_info.setCommandBuffers(*transfer_cmd);
181 context.submit(submit_info, *transfer_fence);
184 context.getDevice().waitForFences(*transfer_fence, VK_TRUE, UINT64_MAX);
185 if (result != vk::Result::eSuccess) {
186 throw std::runtime_error(
"Failed to wait for download fence");
188 context.getDevice().resetFences(*transfer_fence);
190 std::memcpy(data, staging.getMappedData(), size);
197 vk::CommandBufferBeginInfo begin_info(
198 vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
199 transfer_cmd.begin(begin_info);
201 vk::BufferCopy copy_region(0, 0, size);
202 transfer_cmd.copyBuffer(src.
buffer, dst.
buffer, copy_region);
206 vk::SubmitInfo submit_info;
207 submit_info.setCommandBuffers(*transfer_cmd);
208 context.submit(submit_info, *transfer_fence);
211 context.getDevice().waitForFences(*transfer_fence, VK_TRUE, UINT64_MAX);
212 if (result != vk::Result::eSuccess) {
213 throw std::runtime_error(
"Failed to wait for copy fence");
215 context.getDevice().resetFences(*transfer_fence);