From 26c6748c1a343206615292e288bbe4010e5b11de Mon Sep 17 00:00:00 2001 From: Top61ly Date: Sun, 25 May 2025 23:00:39 +0800 Subject: [PATCH 1/5] feat: implement ImGui rendering support with Vulkan render pass and framebuffers --- src/Rendering/RenderSystem.cpp | 119 ++++++++++++++++++++++++++++++++- src/Rendering/RenderSystem.h | 10 +++ 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/Rendering/RenderSystem.cpp b/src/Rendering/RenderSystem.cpp index 558e758..157942e 100644 --- a/src/Rendering/RenderSystem.cpp +++ b/src/Rendering/RenderSystem.cpp @@ -477,6 +477,33 @@ void RenderSystem::InitImgui() //this initializes imgui for SDL ImGui_ImplGlfw_InitForVulkan(m_App->GetWindow()->Get(), true); + //this initialize renderPass for ImGui + vk::AttachmentDescription attachmentDesc = {}; + attachmentDesc.format = m_Swapchain.GetFormat().format; + attachmentDesc.samples = vk::SampleCountFlagBits::e1; + attachmentDesc.loadOp = vk::AttachmentLoadOp::eClear; + attachmentDesc.storeOp = vk::AttachmentStoreOp::eStore; + attachmentDesc.stencilLoadOp = vk::AttachmentLoadOp::eDontCare; + attachmentDesc.stencilStoreOp = vk::AttachmentStoreOp::eDontCare; + attachmentDesc.initialLayout = vk::ImageLayout::eUndefined; + attachmentDesc.finalLayout = vk::ImageLayout::ePresentSrcKHR; + + vk::AttachmentReference colorAttachmentRef = {}; + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal; + + vk::SubpassDescription subpassDesc = {}; + subpassDesc.pipelineBindPoint = vk::PipelineBindPoint::eGraphics; + subpassDesc.colorAttachmentCount = 1; + subpassDesc.pColorAttachments = &colorAttachmentRef; + + vk::RenderPassCreateInfo renderPassInfo = {}; + renderPassInfo.attachmentCount = 1; + renderPassInfo.pAttachments = &attachmentDesc; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpassDesc; + m_ImGuiObjects.renderPass = m_Device.Get().createRenderPass(renderPassInfo); + //this initializes imgui for Vulkan ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = *m_Device.GetInstance()->Get(); @@ -487,9 +514,24 @@ void RenderSystem::InitImgui() init_info.MinImageCount = 3; init_info.ImageCount = 3; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - init_info.UseDynamicRendering = true; - init_info.ColorAttachmentFormat = static_cast(m_Swapchain.GetFormat().format); - ImGui_ImplVulkan_Init(&init_info, nullptr); + ImGui_ImplVulkan_Init(&init_info, m_ImGuiObjects.renderPass); + + assert(m_ImGuiObjects.renderPass != VK_NULL_HANDLE); + + vk::FramebufferCreateInfo framebufferInfo = {}; + framebufferInfo.renderPass = m_ImGuiObjects.renderPass; + framebufferInfo.attachmentCount = 1; + framebufferInfo.width = m_Swapchain.GetExtent().width; + framebufferInfo.height = m_Swapchain.GetExtent().height; + framebufferInfo.layers = 1; + + m_ImGuiObjects.framebuffers.resize(m_Swapchain.GetImageCount()); + + for (uint32_t i = 0; i < m_Swapchain.GetImageCount(); i++) + { + framebufferInfo.pAttachments = &(*m_Swapchain.GetImageViews()[i]); + m_ImGuiObjects.framebuffers[i] = m_Device.Get().createFramebuffer(framebufferInfo); + } } void RenderSystem::ShutdownImgui() @@ -499,6 +541,12 @@ void RenderSystem::ShutdownImgui() ImGui::DestroyContext(); m_ImguiDescriptorPool.clear(); + + (*m_Device.Get()).destroyRenderPass(m_ImGuiObjects.renderPass); + for (auto& framebuffer : m_ImGuiObjects.framebuffers) + { + (*m_Device.Get()).destroyFramebuffer(framebuffer); + } } void RenderSystem::RecordDebugMarker(void* pUserContext, const RpsRuntimeOpRecordDebugMarkerArgs* pArgs) @@ -707,6 +755,71 @@ RpsResult RenderSystem::ExecuteRenderGraph( return RPS_OK; } +void RenderSystem::StartImguiDraw() +{ + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); +} + +void RenderSystem::DrawImgui() +{ + +} + +void RenderSystem::EndImguiDraw(RpsRenderGraph renderGraph) +{ + ImGui::Render(); + + RpsRenderGraphBatchLayout batchLayout = {}; + RpsResult result = rpsRenderGraphGetBatchLayout(renderGraph, &batchLayout); + AssertIfRpsFailed(result); + + ActiveCommandList cmdList = BeginCmdList(RPS_QUEUE_GRAPHICS); + + vk::ImageMemoryBarrier graphToGuiBarrier = {}; + // TODO Better solution for srcAccessMask + graphToGuiBarrier.srcAccessMask = {}; + graphToGuiBarrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite; + graphToGuiBarrier.oldLayout = + m_FrameCounter < m_Swapchain.GetImageCount() ? vk::ImageLayout::eUndefined : vk::ImageLayout::eColorAttachmentOptimal; + graphToGuiBarrier.newLayout = vk::ImageLayout::eColorAttachmentOptimal; + graphToGuiBarrier.image = m_Swapchain.GetImages()[m_backBufferIndex]; + graphToGuiBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + graphToGuiBarrier.subresourceRange.layerCount = 1; + graphToGuiBarrier.subresourceRange.levelCount = 1; + + cmdList.cmdBuf.pipelineBarrier( + vk::PipelineStageFlagBits::eBottomOfPipe, + vk::PipelineStageFlagBits::eColorAttachmentOutput, + {}, + 0, + nullptr, + 0, + nullptr, + 1, + &graphToGuiBarrier); + + vk::ClearValue clearColor = {}; + + vk::RenderPassBeginInfo beginInfo = {}; + beginInfo.framebuffer = m_ImGuiObjects.framebuffers[m_backBufferIndex]; + beginInfo.clearValueCount = 1; + beginInfo.pClearValues = &clearColor; + beginInfo.renderPass = m_ImGuiObjects.renderPass; + beginInfo.renderArea = vk::Rect2D{{0, 0}, m_Swapchain.GetExtent()}; + + cmdList.cmdBuf.beginRenderPass(beginInfo, vk::SubpassContents::eInline); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmdList.cmdBuf); + cmdList.cmdBuf.endRenderPass(); + + EndCmdList(cmdList); + + SubmitCmdLists(&cmdList, 1, true); + + RecycleCmdList(cmdList); +} + void RenderSystem::WaitForSwapChainBuffer() { m_swapChainImageSemaphoreIndex = (m_swapChainImageSemaphoreIndex + 1) % m_imageAcquiredSemaphores.size(); diff --git a/src/Rendering/RenderSystem.h b/src/Rendering/RenderSystem.h index 06b5a8a..02971b2 100644 --- a/src/Rendering/RenderSystem.h +++ b/src/Rendering/RenderSystem.h @@ -103,6 +103,16 @@ ENGINE_CLASS(RenderSystem) final : System // Imgui void InitImgui(); void ShutdownImgui(); + + struct ImGuiObjects + { + vk::RenderPass renderPass = {}; + std::vector framebuffers = {}; + } m_ImGuiObjects; + + void StartImguiDraw(); + void DrawImgui(); + void EndImguiDraw(RpsRenderGraph renderGraph); ImGui_ImplVulkanH_Window m_ImguiWindowData; vk::raii::DescriptorPool m_ImguiDescriptorPool; From 0f54f664fd231bdec044a65bd5b92eecd2cc652e Mon Sep 17 00:00:00 2001 From: Top61ly Date: Mon, 26 May 2025 18:10:38 +0800 Subject: [PATCH 2/5] fix: dereference device pointer for ImGui render pass and framebuffer creation --- src/Rendering/RenderSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Rendering/RenderSystem.cpp b/src/Rendering/RenderSystem.cpp index 157942e..d18dcd9 100644 --- a/src/Rendering/RenderSystem.cpp +++ b/src/Rendering/RenderSystem.cpp @@ -502,7 +502,7 @@ void RenderSystem::InitImgui() renderPassInfo.pAttachments = &attachmentDesc; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpassDesc; - m_ImGuiObjects.renderPass = m_Device.Get().createRenderPass(renderPassInfo); + m_ImGuiObjects.renderPass = (*m_Device.Get()).createRenderPass(renderPassInfo); //this initializes imgui for Vulkan ImGui_ImplVulkan_InitInfo init_info = {}; @@ -530,7 +530,7 @@ void RenderSystem::InitImgui() for (uint32_t i = 0; i < m_Swapchain.GetImageCount(); i++) { framebufferInfo.pAttachments = &(*m_Swapchain.GetImageViews()[i]); - m_ImGuiObjects.framebuffers[i] = m_Device.Get().createFramebuffer(framebufferInfo); + m_ImGuiObjects.framebuffers[i] = (*m_Device.Get()).createFramebuffer(framebufferInfo); } } From e2b4346eec3130ba66616037587a91ceacaa1c89 Mon Sep 17 00:00:00 2001 From: Top61ly Date: Mon, 26 May 2025 22:59:20 +0800 Subject: [PATCH 3/5] feat: enhance ImGui integration with updated render graph handling and demo window --- src/Rendering/RenderSystem.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Rendering/RenderSystem.cpp b/src/Rendering/RenderSystem.cpp index d18dcd9..bf8325f 100644 --- a/src/Rendering/RenderSystem.cpp +++ b/src/Rendering/RenderSystem.cpp @@ -621,7 +621,13 @@ void RenderSystem::RunRpsSystem() ResetCommandPools(); - ExecuteRenderGraph(m_FrameCounter, *m_RpsSystem->rpsRDG); + ExecuteRenderGraph(m_FrameCounter, *m_RpsSystem->rpsRDG, true, false); + + StartImguiDraw(); + + DrawImgui(); + + EndImguiDraw(*m_RpsSystem->rpsRDG); vk::PresentInfoKHR presentInfo = {}; presentInfo.swapchainCount = 1; @@ -764,7 +770,8 @@ void RenderSystem::StartImguiDraw() void RenderSystem::DrawImgui() { - + bool show = true; + ImGui::ShowDemoWindow(&show); } void RenderSystem::EndImguiDraw(RpsRenderGraph renderGraph) @@ -782,7 +789,7 @@ void RenderSystem::EndImguiDraw(RpsRenderGraph renderGraph) graphToGuiBarrier.srcAccessMask = {}; graphToGuiBarrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite; graphToGuiBarrier.oldLayout = - m_FrameCounter < m_Swapchain.GetImageCount() ? vk::ImageLayout::eUndefined : vk::ImageLayout::eColorAttachmentOptimal; + m_FrameCounter < m_Swapchain.GetImageCount() ? vk::ImageLayout::eUndefined : vk::ImageLayout::ePresentSrcKHR; graphToGuiBarrier.newLayout = vk::ImageLayout::eColorAttachmentOptimal; graphToGuiBarrier.image = m_Swapchain.GetImages()[m_backBufferIndex]; graphToGuiBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; From 2bb93619c183996502135def4fa57338a1ac61fb Mon Sep 17 00:00:00 2001 From: Top61ly Date: Mon, 26 May 2025 23:10:48 +0800 Subject: [PATCH 4/5] fix: change ImGui attachment load operation from clear to load --- src/Rendering/RenderSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rendering/RenderSystem.cpp b/src/Rendering/RenderSystem.cpp index bf8325f..4bbcbff 100644 --- a/src/Rendering/RenderSystem.cpp +++ b/src/Rendering/RenderSystem.cpp @@ -481,7 +481,7 @@ void RenderSystem::InitImgui() vk::AttachmentDescription attachmentDesc = {}; attachmentDesc.format = m_Swapchain.GetFormat().format; attachmentDesc.samples = vk::SampleCountFlagBits::e1; - attachmentDesc.loadOp = vk::AttachmentLoadOp::eClear; + attachmentDesc.loadOp = vk::AttachmentLoadOp::eLoad; attachmentDesc.storeOp = vk::AttachmentStoreOp::eStore; attachmentDesc.stencilLoadOp = vk::AttachmentLoadOp::eDontCare; attachmentDesc.stencilStoreOp = vk::AttachmentStoreOp::eDontCare; From d85d4f6ebc145198e18b5b5d46700799080084b0 Mon Sep 17 00:00:00 2001 From: Top61ly Date: Tue, 27 May 2025 22:22:06 +0800 Subject: [PATCH 5/5] feat: add ImGui framebuffer creation and destruction methods --- src/Rendering/RenderSystem.cpp | 57 ++++++++++++++++++++++------------ src/Rendering/RenderSystem.h | 3 ++ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/Rendering/RenderSystem.cpp b/src/Rendering/RenderSystem.cpp index 4bbcbff..6acc4ad 100644 --- a/src/Rendering/RenderSystem.cpp +++ b/src/Rendering/RenderSystem.cpp @@ -434,6 +434,10 @@ void RenderSystem::OnResize(Window* window, int width, int height) m_Swapchain.Recreate(3, static_cast(width), static_cast(height)); CreateDepthBuffer(); + + // ImGui recreate + DestroyImGuiFramebuffer(); + CreateImGuiFramebuffer(); } void RenderSystem::DrawRenderer(DrawKey key, vk::CommandBuffer cmd, GraphicsPipelineHandle overridePipeline) @@ -444,6 +448,36 @@ void RenderSystem::DrawRenderer(DrawKey key, vk::CommandBuffer cmd, GraphicsPipe ScheduleDrawStream(*m_RenderContext, m_DrawData[key], cmd); } +void RenderSystem::CreateImGuiFramebuffer() +{ + assert(m_ImGuiObjects.renderPass != VK_NULL_HANDLE); + + vk::FramebufferCreateInfo framebufferInfo = {}; + framebufferInfo.renderPass = m_ImGuiObjects.renderPass; + framebufferInfo.attachmentCount = 1; + framebufferInfo.width = m_Swapchain.GetExtent().width; + framebufferInfo.height = m_Swapchain.GetExtent().height; + framebufferInfo.layers = 1; + + assert(m_ImGuiObjects.framebuffers.empty()); + m_ImGuiObjects.framebuffers.resize(m_Swapchain.GetImageCount()); + + for (uint32_t i = 0; i < m_Swapchain.GetImageCount(); i++) + { + framebufferInfo.pAttachments = &(*m_Swapchain.GetImageViews()[i]); + m_ImGuiObjects.framebuffers[i] = (*m_Device.Get()).createFramebuffer(framebufferInfo); + } +} + +void RenderSystem::DestroyImGuiFramebuffer() +{ + for (auto& framebuffer : m_ImGuiObjects.framebuffers) + { + (*m_Device.Get()).destroyFramebuffer(framebuffer); + } + m_ImGuiObjects.framebuffers.clear(); +} + void RenderSystem::InitImgui() { //1: create descriptor pool for IMGUI @@ -516,22 +550,7 @@ void RenderSystem::InitImgui() init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; ImGui_ImplVulkan_Init(&init_info, m_ImGuiObjects.renderPass); - assert(m_ImGuiObjects.renderPass != VK_NULL_HANDLE); - - vk::FramebufferCreateInfo framebufferInfo = {}; - framebufferInfo.renderPass = m_ImGuiObjects.renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.width = m_Swapchain.GetExtent().width; - framebufferInfo.height = m_Swapchain.GetExtent().height; - framebufferInfo.layers = 1; - - m_ImGuiObjects.framebuffers.resize(m_Swapchain.GetImageCount()); - - for (uint32_t i = 0; i < m_Swapchain.GetImageCount(); i++) - { - framebufferInfo.pAttachments = &(*m_Swapchain.GetImageViews()[i]); - m_ImGuiObjects.framebuffers[i] = (*m_Device.Get()).createFramebuffer(framebufferInfo); - } + CreateImGuiFramebuffer(); } void RenderSystem::ShutdownImgui() @@ -543,10 +562,8 @@ void RenderSystem::ShutdownImgui() m_ImguiDescriptorPool.clear(); (*m_Device.Get()).destroyRenderPass(m_ImGuiObjects.renderPass); - for (auto& framebuffer : m_ImGuiObjects.framebuffers) - { - (*m_Device.Get()).destroyFramebuffer(framebuffer); - } + + DestroyImGuiFramebuffer(); } void RenderSystem::RecordDebugMarker(void* pUserContext, const RpsRuntimeOpRecordDebugMarkerArgs* pArgs) diff --git a/src/Rendering/RenderSystem.h b/src/Rendering/RenderSystem.h index 02971b2..fec547b 100644 --- a/src/Rendering/RenderSystem.h +++ b/src/Rendering/RenderSystem.h @@ -104,6 +104,9 @@ ENGINE_CLASS(RenderSystem) final : System void InitImgui(); void ShutdownImgui(); + void CreateImGuiFramebuffer(); + void DestroyImGuiFramebuffer(); + struct ImGuiObjects { vk::RenderPass renderPass = {};