+void dither::internal::vulkan_copy_buffer_pieces(
+ VkDevice device, VkCommandPool command_pool, VkQueue queue,
+ VkBuffer src_buf, VkBuffer dst_buf,
+ const std::vector<std::tuple<VkDeviceSize, VkDeviceSize>> &pieces) {
+ VkCommandBufferAllocateInfo alloc_info{};
+ alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ alloc_info.commandPool = command_pool;
+ alloc_info.commandBufferCount = 1;
+
+ VkCommandBuffer command_buf;
+ vkAllocateCommandBuffers(device, &alloc_info, &command_buf);
+
+ VkCommandBufferBeginInfo begin_info{};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+ vkBeginCommandBuffer(command_buf, &begin_info);
+
+ std::vector<VkBufferCopy> regions;
+ for (auto tuple : pieces) {
+ VkBufferCopy copy_region{};
+ copy_region.size = std::get<0>(tuple);
+ copy_region.srcOffset = std::get<1>(tuple);
+ copy_region.dstOffset = std::get<1>(tuple);
+ regions.push_back(copy_region);
+ }
+ vkCmdCopyBuffer(command_buf, src_buf, dst_buf, regions.size(),
+ regions.data());
+
+ vkEndCommandBuffer(command_buf);
+
+ VkSubmitInfo submit_info{};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &command_buf;
+
+ vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
+ vkQueueWaitIdle(queue);
+
+ vkFreeCommandBuffers(device, command_pool, 1, &command_buf);
+}
+