From 6b71e042b41c08fd84d9776e0ee6afb553537488 Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Tue, 25 May 2021 14:03:48 +0200 Subject: [PATCH] [#39]implement submit function --- include/vkcv/CommandResources.hpp | 13 ++-- include/vkcv/Core.hpp | 12 ++++ include/vkcv/SyncResources.hpp | 5 +- projects/first_triangle/src/main.cpp | 24 ------- src/vkcv/CommandResources.cpp | 47 ++++++++++---- src/vkcv/Core.cpp | 94 +++++++++++++++++++++------- src/vkcv/SyncResources.cpp | 12 ++-- 7 files changed, 138 insertions(+), 69 deletions(-) diff --git a/include/vkcv/CommandResources.hpp b/include/vkcv/CommandResources.hpp index 05e84829..197227a1 100644 --- a/include/vkcv/CommandResources.hpp +++ b/include/vkcv/CommandResources.hpp @@ -1,12 +1,17 @@ #pragma once #include <vulkan/vulkan.hpp> +#include <unordered_set> +#include "QueueManager.hpp" namespace vkcv { struct CommandResources { - vk::CommandPool commandPool; - vk::CommandBuffer commandBuffer; + std::vector<vk::CommandPool> cmdPoolPerQueueFamily; }; - CommandResources createDefaultCommandResources(const vk::Device& device, const int graphicFamilyIndex); - void destroyCommandResources(const vk::Device& device, const CommandResources& resources); + std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager& queueManager); + CommandResources createCommandResources(const vk::Device& device, const std::unordered_set<int> &familyIndexSet); + void destroyCommandResources(const vk::Device& device, const CommandResources& resources); + + vk::CommandBuffer allocateCommandBuffer(const vk::Device& device, const vk::CommandPool cmdPool); + vk::CommandPool chooseCmdPool(const Queue &queue, const CommandResources &cmdResources); } \ No newline at end of file diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 065c21d2..0a843c4c 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -24,6 +24,13 @@ namespace vkcv class PassManager; class PipelineManager; + enum class QueueType { Compute, Transfer, Graphics, Present }; + struct SubmitInfo { + QueueType queueType; + std::vector<vk::Semaphore> waitSemaphores; + std::vector<vk::Semaphore> signalSemaphores; + }; + class Core final { private: @@ -172,5 +179,10 @@ namespace vkcv void endFrame(); vk::Format getSwapchainImageFormat(); + + void submitCommands( + const SubmitInfo &submitInfo, + const std::function<void(vk::CommandBuffer cmdBuffer)> recording, + const std::function<void()> finishCallback); }; } diff --git a/include/vkcv/SyncResources.hpp b/include/vkcv/SyncResources.hpp index 44565947..c399631f 100644 --- a/include/vkcv/SyncResources.hpp +++ b/include/vkcv/SyncResources.hpp @@ -8,6 +8,7 @@ namespace vkcv { vk::Fence presentFinished; }; - SyncResources createDefaultSyncResources(const vk::Device& device); - void destroySyncResources(const vk::Device& device, const SyncResources& resources); + SyncResources createDefaultSyncResources(const vk::Device &device); + void destroySyncResources(const vk::Device &device, const SyncResources &resources); + vk::Fence createFence(const vk::Device &device); } \ No newline at end of file diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index d718da09..08097ef0 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -16,30 +16,6 @@ int main(int argc, const char** argv) { false ); - // showing basic usage lambda events of window - window.e_mouseMove.add([&](double x, double y){ - std::cout << "movement: " << x << " , " << y << std::endl; - }); - - window.e_key.add([&](int key, int scancode, int action, int mods){ - switch (key) { - case GLFW_KEY_W: - std::cout << "Move forward" << std::endl; - break; - case GLFW_KEY_A: - std::cout << "Move left" << std::endl; - break; - case GLFW_KEY_S: - std::cout << "Move backward" << std::endl; - break; - case GLFW_KEY_D: - std::cout << "Move right" << std::endl; - break; - default: - std::cout << "this key is not supported yet: " << std::endl; - } - }); - window.initEvents(); vkcv::Core core = vkcv::Core::create( diff --git a/src/vkcv/CommandResources.cpp b/src/vkcv/CommandResources.cpp index 451ec4f2..69028620 100644 --- a/src/vkcv/CommandResources.cpp +++ b/src/vkcv/CommandResources.cpp @@ -1,23 +1,48 @@ #include "vkcv/CommandResources.hpp" namespace vkcv { - CommandResources createDefaultCommandResources(const vk::Device& device, const int graphicFamilyIndex) { + + std::unordered_set<int> generateQueueFamilyIndexSet(const QueueManager &queueManager) { + std::unordered_set<int> indexSet; + for (const auto& queue : queueManager.getGraphicsQueues()) { + indexSet.insert(queue.familyIndex); + } + for (const auto& queue : queueManager.getComputeQueues()) { + indexSet.insert(queue.familyIndex); + } + for (const auto& queue : queueManager.getTransferQueues()) { + indexSet.insert(queue.familyIndex); + } + indexSet.insert(queueManager.getPresentQueue().familyIndex); + return indexSet; + } + + CommandResources createCommandResources(const vk::Device& device, const std::unordered_set<int>& familyIndexSet) { CommandResources resources; - vk::CommandPoolCreateFlags flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer; - vk::CommandPoolCreateInfo poolCreateInfo(flags, graphicFamilyIndex); - resources.commandPool = device.createCommandPool(poolCreateInfo, nullptr, {}); + const size_t queueFamiliesCount = familyIndexSet.size(); + resources.cmdPoolPerQueueFamily.resize(queueFamiliesCount); - const int commandPoolCount = 1; - vk::CommandBufferAllocateInfo allocateInfo(resources.commandPool, vk::CommandBufferLevel::ePrimary, commandPoolCount); - const std::vector<vk::CommandBuffer> createdBuffers = device.allocateCommandBuffers(allocateInfo, {}); - assert(createdBuffers.size() == 1); - resources.commandBuffer = createdBuffers[0]; + const vk::CommandPoolCreateFlags poolFlags = vk::CommandPoolCreateFlagBits::eTransient; + for (const int familyIndex : familyIndexSet) { + const vk::CommandPoolCreateInfo poolCreateInfo(poolFlags, familyIndex); + resources.cmdPoolPerQueueFamily[familyIndex] = device.createCommandPool(poolCreateInfo, nullptr, {}); + } return resources; } void destroyCommandResources(const vk::Device& device, const CommandResources& resources) { - device.freeCommandBuffers(resources.commandPool, resources.commandBuffer, {}); - device.destroyCommandPool(resources.commandPool, {}); + for (const vk::CommandPool &pool : resources.cmdPoolPerQueueFamily) { + device.destroyCommandPool(pool); + } + } + + vk::CommandBuffer allocateCommandBuffer(const vk::Device& device, const vk::CommandPool cmdPool) { + const vk::CommandBufferAllocateInfo info(cmdPool, vk::CommandBufferLevel::ePrimary, 1); + return device.allocateCommandBuffers(info).front(); + } + + vk::CommandPool chooseCmdPool(const Queue& queue, const CommandResources& cmdResources) { + return cmdResources.cmdPoolPerQueueFamily[queue.familyIndex]; } } \ No newline at end of file diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 48871511..7df30529 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -66,15 +66,16 @@ namespace vkcv const auto& queueManager = context.getQueueManager(); - const int graphicQueueFamilyIndex = queueManager.getGraphicsQueues()[0].familyIndex; - const auto defaultCommandResources = createDefaultCommandResources(context.getDevice(), graphicQueueFamilyIndex); - const auto defaultSyncResources = createDefaultSyncResources(context.getDevice()); + const int graphicQueueFamilyIndex = queueManager.getGraphicsQueues()[0].familyIndex; + const std::unordered_set<int> queueFamilySet = generateQueueFamilyIndexSet(queueManager); + const auto commandResources = createCommandResources(context.getDevice(), queueFamilySet); + const auto defaultSyncResources = createDefaultSyncResources(context.getDevice()); window.e_resize.add([&](int width, int height){ recreateSwapchain(width,height); }); - return Core(std::move(context) , window, swapChain, imageViews, defaultCommandResources, defaultSyncResources); + return Core(std::move(context) , window, swapChain, imageViews, commandResources, defaultSyncResources); } const Context &Core::getContext() const @@ -161,9 +162,6 @@ namespace vkcv m_window.pollEvents(); m_Context.getDevice().waitIdle(); // FIMXE: this is a sin against graphics programming, but its getting late - Alex destroyTemporaryFramebuffers(); - const vk::CommandBufferUsageFlags beginFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; - const vk::CommandBufferBeginInfo beginInfos(beginFlags); - m_CommandResources.commandBuffer.begin(beginInfos); } void Core::renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, @@ -171,22 +169,31 @@ namespace vkcv if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - + const vk::RenderPass renderpass = m_PassManager->getVkPass(renderpassHandle); - const std::array<float, 4> clearColor = { 0.f, 0.f, 0.f, 1.f }; - const vk::ClearValue clearValues(clearColor); + const vk::ImageView imageView = m_swapchainImageViews[m_currentSwapchainImageIndex]; + const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle); const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height)); - const vk::ImageView imageView = m_swapchainImageViews[m_currentSwapchainImageIndex]; + const vk::Framebuffer framebuffer = createFramebuffer(m_Context.getDevice(), renderpass, width, height, imageView); m_TemporaryFramebuffers.push_back(framebuffer); - const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, 1, &clearValues); - const vk::SubpassContents subpassContents = {}; - m_CommandResources.commandBuffer.beginRenderPass(beginInfo, subpassContents, {}); - - const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle); - m_CommandResources.commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); - m_CommandResources.commandBuffer.draw(3, 1, 0, 0, {}); - m_CommandResources.commandBuffer.endRenderPass(); + + SubmitInfo submitInfo; + submitInfo.queueType = QueueType::Graphics; + submitInfo.signalSemaphores = { m_SyncResources.renderFinished }; + submitCommands(submitInfo, [renderpass, renderArea, imageView, framebuffer, pipeline](const vk::CommandBuffer cmdBuffer) { + + const std::array<float, 4> clearColor = { 0.f, 0.f, 0.f, 1.f }; + const vk::ClearValue clearValues(clearColor); + + const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, 1, &clearValues); + const vk::SubpassContents subpassContents = {}; + cmdBuffer.beginRenderPass(beginInfo, subpassContents, {}); + + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); + cmdBuffer.draw(3, 1, 0, 0, {}); + cmdBuffer.endRenderPass(); + }, nullptr); } void Core::endFrame() { @@ -196,13 +203,8 @@ namespace vkcv const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); const vk::Image presentImage = swapchainImages[m_currentSwapchainImageIndex]; - - m_CommandResources.commandBuffer.end(); const auto& queueManager = m_Context.getQueueManager(); - - const vk::SubmitInfo submitInfo(0, nullptr, 0, 1, &(m_CommandResources.commandBuffer), 1, &m_SyncResources.renderFinished); - queueManager.getGraphicsQueues()[0].handle.submit(submitInfo); vk::Result presentResult; const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain(); @@ -222,4 +224,48 @@ namespace vkcv /* boilerplate for #34 */ std::cout << "Resized to : " << width << " , " << height << std::endl; } + + void Core::submitCommands( + const SubmitInfo& submitInfo, + const std::function<void(vk::CommandBuffer cmdBuffer)> recording, + const std::function<void()> finishCallback) { + + vkcv::Queue queue; + if (submitInfo.queueType == QueueType::Graphics) { + queue = m_Context.getQueueManager().getGraphicsQueues().front(); + } + else if (submitInfo.queueType == QueueType::Compute) { + queue = m_Context.getQueueManager().getComputeQueues().front(); + } + else if (submitInfo.queueType == QueueType::Transfer) { + queue = m_Context.getQueueManager().getTransferQueues().front(); + } + else if (submitInfo.queueType == QueueType::Present) { + queue = m_Context.getQueueManager().getPresentQueue(); + } + else { + std::cerr << "Unknown queue type" << std::endl; + return; + } + + const vk::CommandPool cmdPool = chooseCmdPool(queue, m_CommandResources); + const vk::CommandBuffer cmdBuffer = allocateCommandBuffer(m_Context.getDevice(), cmdPool); + const vk::CommandBufferBeginInfo beginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + cmdBuffer.begin(beginInfo); + recording(cmdBuffer); + cmdBuffer.end(); + const std::vector<vk::PipelineStageFlags> waitDstStageMasks(submitInfo.waitSemaphores.size(), vk::PipelineStageFlagBits::eAllCommands); + vk::SubmitInfo queueSubmitInfo(submitInfo.waitSemaphores, waitDstStageMasks, cmdBuffer, submitInfo.signalSemaphores); + if (finishCallback) { + vk::Fence waitFence = createFence(m_Context.getDevice()); + queue.handle.submit(queueSubmitInfo, waitFence); + const auto result = m_Context.getDevice().waitForFences(waitFence, true, UINT64_MAX); + assert(result == vk::Result::eSuccess); + m_Context.getDevice().destroyFence(waitFence); + finishCallback(); + } + else { + queue.handle.submit(queueSubmitInfo); + } + } } diff --git a/src/vkcv/SyncResources.cpp b/src/vkcv/SyncResources.cpp index 10d582a2..01833da6 100644 --- a/src/vkcv/SyncResources.cpp +++ b/src/vkcv/SyncResources.cpp @@ -8,10 +8,8 @@ namespace vkcv { const vk::SemaphoreCreateInfo semaphoreInfo(semaphoreFlags); resources.renderFinished = device.createSemaphore(semaphoreInfo, nullptr, {}); - const vk::FenceCreateFlags fenceFlags = vk::FenceCreateFlagBits(); - vk::FenceCreateInfo fenceInfo(fenceFlags); - resources.presentFinished = device.createFence(fenceInfo, nullptr, {}); - resources.swapchainImageAcquired = device.createFence(fenceInfo, nullptr, {}); + resources.presentFinished = createFence(device); + resources.swapchainImageAcquired = createFence(device); return resources; } @@ -21,4 +19,10 @@ namespace vkcv { device.destroyFence(resources.presentFinished); device.destroyFence(resources.swapchainImageAcquired); } + + vk::Fence createFence(const vk::Device& device) { + const vk::FenceCreateFlags fenceFlags = vk::FenceCreateFlagBits(); + vk::FenceCreateInfo fenceInfo(fenceFlags); + return device.createFence(fenceInfo, nullptr, {}); + } } \ No newline at end of file -- GitLab