From 363315f7beebcb376a332ae31020942471d78e7b Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Wed, 13 Jul 2022 02:02:20 +0200
Subject: [PATCH] Removed immediate command buffer submission and replaced with
 command streams

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Core.hpp             | 18 +--------
 modules/gui/src/vkcv/gui/GUI.cpp  | 13 ++++---
 src/vkcv/BufferManager.cpp        | 18 +++++----
 src/vkcv/CommandStreamManager.cpp |  2 +
 src/vkcv/Core.cpp                 | 65 +++++++------------------------
 src/vkcv/ImageManager.cpp         | 19 +++++----
 6 files changed, 47 insertions(+), 88 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index aaac77de..2ab87859 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -657,20 +657,6 @@ namespace vkcv
 		 */
 		void endFrame( const WindowHandle& windowHandle );
 
-		/**
-		 * Submit a command buffer to any queue of selected type. The recording can be customized by a
-		 * custom record-command-function. If the command submission has finished, an optional finish-function
-		 * will be called.
-		 *
-		 * @param submitInfo Submit information
-		 * @param record Record-command-function
-		 * @param finish Finish-command-function or nullptr
-		 */
-		void recordAndSubmitCommandsImmediate(
-			const SubmitInfo            &submitInfo, 
-			const RecordCommandFunction &record, 
-			const FinishCommandFunction &finish);
-
 		/**
 		 * @brief Create a new command stream
 		 * 
@@ -687,7 +673,7 @@ namespace vkcv
 		 * @param finish Finish function, called after execution of commands is finished
 		 */
 		void recordCommandsToStream(
-			const CommandStreamHandle   cmdStreamHandle,
+			const CommandStreamHandle   &stream,
 			const RecordCommandFunction &record,
 			const FinishCommandFunction &finish);
 
@@ -697,7 +683,7 @@ namespace vkcv
 		 * @param[in] handle Command stream to submit
 		 * @param[in] signalRendering Flag to specify if the command stream finishes rendering
 		 */
-		void submitCommandStream(const CommandStreamHandle& handle,
+		void submitCommandStream(const CommandStreamHandle& stream,
 								 bool signalRendering = true);
 
 		/**
diff --git a/modules/gui/src/vkcv/gui/GUI.cpp b/modules/gui/src/vkcv/gui/GUI.cpp
index 5ac03ce5..15a1b049 100644
--- a/modules/gui/src/vkcv/gui/GUI.cpp
+++ b/modules/gui/src/vkcv/gui/GUI.cpp
@@ -145,14 +145,15 @@ namespace vkcv::gui {
 		
 		ImGui_ImplVulkan_Init(&init_info, static_cast<VkRenderPass>(m_render_pass));
 		
-		const SubmitInfo submitInfo { QueueType::Graphics, {}, {} };
+		auto stream = m_core.createCommandStream(QueueType::Graphics);
 		
-		m_core.recordAndSubmitCommandsImmediate(submitInfo, [](const vk::CommandBuffer& commandBuffer) {
+		m_core.recordCommandsToStream(stream, [](const vk::CommandBuffer& commandBuffer) {
 			ImGui_ImplVulkan_CreateFontsTexture(static_cast<VkCommandBuffer>(commandBuffer));
 		}, []() {
 			ImGui_ImplVulkan_DestroyFontUploadObjects();
 		});
 		
+		m_core.submitCommandStream(stream, false);
 		m_context.getDevice().waitIdle();
 	}
 	
@@ -217,11 +218,9 @@ namespace vkcv::gui {
 		);
 		
 		const vk::Framebuffer framebuffer = m_context.getDevice().createFramebuffer(framebufferCreateInfo);
+		auto stream = m_core.createCommandStream(QueueType::Graphics);
 		
-		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Graphics;
-		
-		m_core.recordAndSubmitCommandsImmediate(submitInfo, [&](const vk::CommandBuffer& commandBuffer) {
+		m_core.recordCommandsToStream(stream, [&](const vk::CommandBuffer& commandBuffer) {
 
 			assert(initialImageLayout == vk::ImageLayout::eColorAttachmentOptimal);
 			m_core.prepareImageForAttachmentManually(commandBuffer, vkcv::ImageHandle::createSwapchainImageHandle());
@@ -252,6 +251,8 @@ namespace vkcv::gui {
 		}, [&]() {
 			m_context.getDevice().destroyFramebuffer(framebuffer);
 		});
+		
+		m_core.submitCommandStream(stream, false);
 	}
 	
 }
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index 22ef2890..da2a370f 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -188,11 +188,10 @@ namespace vkcv {
 		memcpy(mapped, reinterpret_cast<const char*>(info.data) + info.stagingPosition, mapped_size);
 		allocator.unmapMemory(info.stagingAllocation);
 		
-		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Transfer;
+		auto stream = core.createCommandStream(QueueType::Transfer);
 		
-		core.recordAndSubmitCommandsImmediate(
-				submitInfo,
+		core.recordCommandsToStream(
+				stream,
 				[&info, &mapped_size](const vk::CommandBuffer& commandBuffer) {
 					const vk::BufferCopy region (
 							0,
@@ -213,6 +212,8 @@ namespace vkcv {
 					}
 				}
 		);
+		
+		core.submitCommandStream(stream, false);
 	}
 	
 	/**
@@ -245,11 +246,10 @@ namespace vkcv {
 		const size_t remaining = info.size - info.stagingPosition;
 		const size_t mapped_size = std::min(remaining, info.stagingLimit);
 		
-		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Transfer;
+		auto stream = core.createCommandStream(QueueType::Transfer);
 		
-		core.recordAndSubmitCommandsImmediate(
-				submitInfo,
+		core.recordCommandsToStream(
+				stream,
 				[&info, &mapped_size](const vk::CommandBuffer& commandBuffer) {
 					const vk::BufferCopy region (
 							info.offset + info.stagingPosition,
@@ -276,6 +276,8 @@ namespace vkcv {
 					}
 				}
 		);
+		
+		core.submitCommandStream(stream, false);
 	}
 	
 	vk::Buffer BufferManager::getBuffer(const BufferHandle& handle) const {
diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp
index ced6c86c..9f85eea3 100644
--- a/src/vkcv/CommandStreamManager.cpp
+++ b/src/vkcv/CommandStreamManager.cpp
@@ -69,9 +69,11 @@ namespace vkcv {
 		stream.cmdBuffer.end();
 
 		const auto device = getCore().getContext().getDevice();
+		
 		const vk::Fence waitFence = createFence(device);
 		submitCommandBufferToQueue(stream.queue, stream.cmdBuffer, waitFence, waitSemaphores, signalSemaphores);
 		waitForFence(device, waitFence);
+		
 		device.destroyFence(waitFence);
 		stream.queue = nullptr;
 
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index edccae45..761dd66d 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -889,35 +889,6 @@ namespace vkcv
 			m_SwapchainManager->signalRecreation(swapchainHandle);
 		}
 	}
-	
-	void Core::recordAndSubmitCommandsImmediate(
-		const SubmitInfo &submitInfo, 
-		const RecordCommandFunction &record, 
-		const FinishCommandFunction &finish)
-	{
-		const vk::Device& device = m_Context.getDevice();
-
-		const vkcv::Queue		queue		= getQueueForSubmit(submitInfo.queueType, m_Context.getQueueManager());
-		const vk::CommandPool	cmdPool		= chooseCmdPool(queue, m_CommandResources);
-		const vk::CommandBuffer	cmdBuffer	= allocateCommandBuffer(device, cmdPool);
-
-		beginCommandBuffer(cmdBuffer, vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
-		record(cmdBuffer);
-		cmdBuffer.end();
-		
-		vk::Fence waitFence = createFence(device);
-
-		submitCommandBufferToQueue(queue.handle, cmdBuffer, waitFence, submitInfo.waitSemaphores, submitInfo.signalSemaphores);
-		waitForFence(device, waitFence);
-		
-		device.destroyFence(waitFence);
-		
-		device.freeCommandBuffers(cmdPool, cmdBuffer);
-		
-		if (finish) {
-			finish();
-		}
-	}
 
 	CommandStreamHandle Core::createCommandStream(QueueType queueType) {
 		const vkcv::Queue       queue   = getQueueForSubmit(queueType, m_Context.getQueueManager());
@@ -926,21 +897,19 @@ namespace vkcv
 		return m_CommandStreamManager->createCommandStream(queue.handle, cmdPool);
 	}
 
-    void Core::recordCommandsToStream(
-		const CommandStreamHandle   cmdStreamHandle,
-		const RecordCommandFunction &record, 
-		const FinishCommandFunction &finish) {
-
+    void Core::recordCommandsToStream(const CommandStreamHandle &stream,
+									  const RecordCommandFunction &record,
+									  const FinishCommandFunction &finish) {
 		if (record) {
-			m_CommandStreamManager->recordCommandsToStream(cmdStreamHandle, record);
+			m_CommandStreamManager->recordCommandsToStream(stream, record);
 		}
 		
 		if (finish) {
-			m_CommandStreamManager->addFinishCallbackToStream(cmdStreamHandle, finish);
+			m_CommandStreamManager->addFinishCallbackToStream(stream, finish);
 		}
 	}
 
-	void Core::submitCommandStream(const CommandStreamHandle& handle,
+	void Core::submitCommandStream(const CommandStreamHandle& stream,
 								   bool signalRendering) {
 		std::vector<vk::Semaphore> waitSemaphores;
 		
@@ -950,7 +919,7 @@ namespace vkcv
 			signalSemaphores.push_back(m_SyncResources.renderFinished);
 		}
 		
-		m_CommandStreamManager->submitCommandStreamSynchronous(handle, waitSemaphores, signalSemaphores);
+		m_CommandStreamManager->submitCommandStreamSynchronous(stream, waitSemaphores, signalSemaphores);
 	}
 
 	SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter,
@@ -959,17 +928,14 @@ namespace vkcv
 		return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias, borderColor);
 	}
 
-	Image Core::createImage(
-		vk::Format      format,
-		uint32_t        width,
-		uint32_t        height,
-		uint32_t        depth,
-		bool            createMipChain,
-		bool            supportStorage,
-		bool            supportColorAttachment,
-		Multisampling   multisampling)
-	{
-
+	Image Core::createImage(vk::Format      format,
+							uint32_t        width,
+							uint32_t        height,
+							uint32_t        depth,
+							bool            createMipChain,
+							bool            supportStorage,
+							bool            supportColorAttachment,
+							Multisampling   multisampling) {
 		uint32_t mipCount = 1;
 		if (createMipChain) {
 			mipCount = 1 + (uint32_t)std::floor(std::log2(std::max(width, std::max(height, depth))));
@@ -995,7 +961,6 @@ namespace vkcv
 									uint32_t windowWidth,
 									uint32_t windowHeight,
 									bool resizeable) {
-
 		WindowHandle windowHandle = m_WindowManager->createWindow(*m_SwapchainManager ,applicationName, windowWidth, windowHeight, resizeable);
 		SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchain();
 		setSwapchainImages( swapchainHandle );
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index e28cfce8..83246db6 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -439,11 +439,11 @@ namespace vkcv {
 		auto& image = (*this)[handle];
 		const auto transitionBarrier = createImageLayoutTransitionBarrier(image, 0, 0, newLayout);
 		
-		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Graphics;
+		auto& core = getCore();
+		auto stream = core.createCommandStream(QueueType::Graphics);
 		
-		getCore().recordAndSubmitCommandsImmediate(
-			submitInfo,
+		core.recordCommandsToStream(
+			stream,
 			[transitionBarrier](const vk::CommandBuffer& commandBuffer) {
 			// TODO: precise PipelineStageFlagBits, will require a lot of context
 			commandBuffer.pipelineBarrier(
@@ -458,6 +458,7 @@ namespace vkcv {
 			nullptr
 		);
 		
+		core.submitCommandStream(stream, false);
 		image.m_layout = newLayout;
 	}
 
@@ -549,11 +550,11 @@ namespace vkcv {
 		
 		vk::Buffer stagingBuffer = getBufferManager().getBuffer(bufferHandle);
 		
-		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Transfer;
+		auto& core = getCore();
+		auto stream = core.createCommandStream(QueueType::Transfer);
 		
-		getCore().recordAndSubmitCommandsImmediate(
-				submitInfo,
+		core.recordCommandsToStream(
+				stream,
 				[&image, &stagingBuffer](const vk::CommandBuffer& commandBuffer) {
 					vk::ImageAspectFlags aspectFlags;
 					
@@ -592,6 +593,8 @@ namespace vkcv {
 					);
 				}
 		);
+		
+		core.submitCommandStream(stream, false);
 	}
 
 	void ImageManager::recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream,
-- 
GitLab