#include #include #include #include #include #include #include namespace { constexpr auto NO_TIMEOUT = std::numeric_limits::max(); } void VulkanImmediateExecutor::init( VkDevice deviceHandle, std::uint32_t graphicsQueueFamily, VkQueue graphicsQueueHandle) { if (initialized) { throw std::logic_error("VulkanImmediateExecutor::init called twice"); } this->device = deviceHandle; this->graphicsQueue = graphicsQueueHandle; try { const auto poolCreateInfo = vkinit:: commandPoolCreateInfo(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, graphicsQueueFamily); VK_CHECK(vkCreateCommandPool(deviceHandle, &poolCreateInfo, nullptr, &immCommandPool)); const auto cmdAllocInfo = vkinit::commandBufferAllocateInfo(immCommandPool, 1); VK_CHECK(vkAllocateCommandBuffers(deviceHandle, &cmdAllocInfo, &immCommandBuffer)); constexpr auto fenceCreateInfo = VkFenceCreateInfo{ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .flags = VK_FENCE_CREATE_SIGNALED_BIT, }; VK_CHECK(vkCreateFence(deviceHandle, &fenceCreateInfo, nullptr, &immFence)); vkutil::addDebugLabel(deviceHandle, immCommandPool, "immediate command pool"); vkutil::addDebugLabel(deviceHandle, immCommandBuffer, "immediate command buffer"); vkutil::addDebugLabel(deviceHandle, immFence, "immediate fence"); initialized = true; } catch (...) { cleanup(deviceHandle); throw; } } void VulkanImmediateExecutor::cleanup(VkDevice deviceHandle) { if (deviceHandle == VK_NULL_HANDLE && device != VK_NULL_HANDLE) { deviceHandle = device; } if (deviceHandle == VK_NULL_HANDLE) { return; } if (immCommandPool != VK_NULL_HANDLE) { vkDestroyCommandPool(deviceHandle, immCommandPool, nullptr); } if (immFence != VK_NULL_HANDLE) { vkDestroyFence(deviceHandle, immFence, nullptr); } immCommandPool = VK_NULL_HANDLE; immCommandBuffer = VK_NULL_HANDLE; immFence = VK_NULL_HANDLE; this->device = VK_NULL_HANDLE; graphicsQueue = VK_NULL_HANDLE; initialized = false; } void VulkanImmediateExecutor::immediateSubmit( std::function&& function) const { assert(initialized); VK_CHECK(vkResetFences(device, 1, &immFence)); VK_CHECK(vkResetCommandBuffer(immCommandBuffer, 0)); auto cmd = immCommandBuffer; const auto cmdBeginInfo = VkCommandBufferBeginInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); function(cmd); VK_CHECK(vkEndCommandBuffer(cmd)); const auto cmdinfo = vkinit::commandBufferSubmitInfo(cmd); const auto submit = vkinit::submitInfo(&cmdinfo, nullptr, nullptr); VK_CHECK(vkQueueSubmit2(graphicsQueue, 1, &submit, immFence)); VK_CHECK(vkWaitForFences(device, 1, &immFence, true, NO_TIMEOUT)); }