From 94f5cf88d2383e6c6239ec96fc93799f0bb6a134 Mon Sep 17 00:00:00 2001 From: Ilya Shurupov <163508118+elushaX@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:32:43 +0300 Subject: [PATCH] imgui vk dirty --- CMakeLists.txt | 1 + src/DebugGUI/CMakeLists.txt | 26 +++++ src/DebugGUI/exapmle/main.cpp | 86 ++++++++++++++ src/DebugGUI/private/DebugGUI.cpp | 123 +++++++++++++++++++++ src/DebugGUI/public/DebugGUI.hpp | 32 ++++++ src/VulkanGraphics/public/VulkanWindow.hpp | 2 +- 6 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 src/DebugGUI/CMakeLists.txt create mode 100644 src/DebugGUI/exapmle/main.cpp create mode 100644 src/DebugGUI/private/DebugGUI.cpp create mode 100644 src/DebugGUI/public/DebugGUI.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e453ee9..a38eeea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,4 +7,5 @@ add_subdirectory(extern/Modules) add_subdirectory(extern/Utils) add_subdirectory(src/VulkanGraphics) +add_subdirectory(src/DebugGUI) add_subdirectory(src/App) diff --git a/src/DebugGUI/CMakeLists.txt b/src/DebugGUI/CMakeLists.txt new file mode 100644 index 0000000..3ae729c --- /dev/null +++ b/src/DebugGUI/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.30) + +project(IMGUI) +set(IMDIR ../../extern/imgui/) + +add_library(IMGUI + ${IMDIR}imgui.cpp + ${IMDIR}imgui_demo.cpp + ${IMDIR}imgui_tables.cpp + ${IMDIR}imgui_widgets.cpp + ${IMDIR}imgui_draw.cpp + ${IMDIR}backends/imgui_impl_vulkan.cpp + ${IMDIR}backends/imgui_impl_glfw.cpp +) + +target_include_directories(IMGUI PUBLIC ../../extern/imgui/) + +project(DebugGUI) + +file(GLOB SOURCES "./private/*.cpp") +add_library(${PROJECT_NAME} ${SOURCES}) +target_include_directories(${PROJECT_NAME} PUBLIC public) +target_link_libraries(${PROJECT_NAME} PUBLIC VulkanGraphics IMGUI) + +add_executable(${PROJECT_NAME}Example exapmle/main.cpp) +target_link_libraries(${PROJECT_NAME}Example PRIVATE ${PROJECT_NAME}) \ No newline at end of file diff --git a/src/DebugGUI/exapmle/main.cpp b/src/DebugGUI/exapmle/main.cpp new file mode 100644 index 0000000..00066be --- /dev/null +++ b/src/DebugGUI/exapmle/main.cpp @@ -0,0 +1,86 @@ +#include "DebugGUI.hpp" + + +VkRenderPass createRenderPass(VkDevice device, VkFormat format, VkImageLayout finalImageLayout) { + VkRenderPass renderPass = VK_NULL_HANDLE; + + VkAttachmentDescription colorAttachment{ + .format = format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = finalImageLayout, + }; + + VkAttachmentReference colorAttachmentReference{ + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; + + VkSubpassDescription subpassDescription{ + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = 1, + .pColorAttachments = &colorAttachmentReference, + }; + + VkSubpassDependency dependency{ + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + }; + + VkRenderPassCreateInfo renderPassCreateInfo{ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &colorAttachment, + .subpassCount = 1, + .pSubpasses = &subpassDescription, + .dependencyCount = 1, + .pDependencies = &dependency + }; + + vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &renderPass); + + return renderPass; +} + +int main() { + VulkanWindow app; + ImGuiVk imgui; + + auto renderInfo = app.getRenderInfo(); + VkRenderPass renderPass = createRenderPass(renderInfo.device, renderInfo.format, renderInfo.finalImageLayout); + + app.setRenderPass(renderPass); + + imgui.create(&app); + imgui.setRenderPass(renderPass); + + while (!glfwWindowShouldClose(app.getWindow())) { + app.pollEvents(); + + auto drawData = app.startDrawFrame(); + + imgui.beginFrame(); + ImGuiVk::demo(); + imgui.endFrame(); + + imgui.cmdRender(drawData.commandBuffer, drawData.frameBuffer, drawData.extent2D); + + // renderer.fillRenderCommands(drawData.commandBuffer, drawData.frameBuffer, drawData.extent2D); + // renderer.updateUniformBuffer({drawData.extent2D.width, drawData.extent2D.height}); + + app.endDrawFrame(drawData); + } + + app.waitDevice(); + + vkDestroyRenderPass(app.getDevice(), renderPass, nullptr); + imgui.destroy(app.getDevice()); +} \ No newline at end of file diff --git a/src/DebugGUI/private/DebugGUI.cpp b/src/DebugGUI/private/DebugGUI.cpp new file mode 100644 index 0000000..bbdfbe5 --- /dev/null +++ b/src/DebugGUI/private/DebugGUI.cpp @@ -0,0 +1,123 @@ +#include "DebugGUI.hpp" + +#include "backends/imgui_impl_glfw.h" +#include "backends/imgui_impl_vulkan.h" + +/* + get render pass from renderer + create frame buffer +*/ + +void ImGuiVk::create(VulkanWindow* vkWindow) { + mVkWindow = vkWindow; +} + +void ImGuiVk::setRenderPass(VkRenderPass renderPass) { + mRenderPass = renderPass; + + mContext = ImGui::CreateContext(); + + // Setup Platform/Renderer backends + ImGui_ImplGlfw_InitForVulkan(mVkWindow->getWindow(), true); + + VkDescriptorPoolSize poolSize{ + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + }; + + VkDescriptorPoolCreateInfo createInfo{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = 1, + .poolSizeCount = 1, + .pPoolSizes = &poolSize, + }; + + if (vkCreateDescriptorPool(mVkWindow->mDevice, &createInfo, nullptr, &mDescriptorPool) != VK_SUCCESS) { + throw std::runtime_error("failed to create descriptor pool"); + } + + ImGui_ImplVulkan_InitInfo init_info = { + .Instance = mVkWindow->mInstance, + .PhysicalDevice = mVkWindow->mPhysicalDevice, + .Device = mVkWindow->mDevice, + .QueueFamily = (uint32_t) mVkWindow->mGraphicsQueueFamilyIndex, + .Queue = mVkWindow->mGraphicsQueue, + .DescriptorPool = mDescriptorPool, + .RenderPass = mRenderPass, + .MinImageCount = 2, + .ImageCount = 2, + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + }; + + ImGui_ImplVulkan_Init(&init_info); +} + +void ImGuiVk::beginFrame() { + ImGui::SetCurrentContext(mContext); + + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); +} + +void ImGuiVk::endFrame() { + ImGui::SetCurrentContext(mContext); + + ImGui::Render(); + mDrawData = ImGui::GetDrawData(); +} + +void ImGuiVk::demo() { + ImGui::ShowDemoWindow(nullptr); +} + +void ImGuiVk::destroy(VkDevice device) { + ImGui::SetCurrentContext(mContext); + + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + + vkDestroyDescriptorPool(device, mDescriptorPool, nullptr); +} + +ImGuiVk::~ImGuiVk() { + ImGui::SetCurrentContext(mContext); + + ImGui::DestroyContext(); +} + +void ImGuiVk::cmdRender(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend) { + VkCommandBufferBeginInfo commandBufferBeginInfo{ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + + if (vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo) != VK_SUCCESS) { + throw std::runtime_error("failed to begin command buffer ="); + } + + VkClearValue clearColor{.color = {.float32 = {0.f, 0.f, 0.f, 1.f}}}; + + VkRenderPassBeginInfo renderPassBeginInfo{ + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = mRenderPass, + .framebuffer = framebuffer, + .renderArea = { + .offset = {0, 0}, + .extent = extend, + }, + .clearValueCount = 1, + .pClearValues = &clearColor, + }; + + vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + // Record dear imgui primitives into command buffer + ImGui_ImplVulkan_RenderDrawData(mDrawData, commandBuffer); + + vkCmdEndRenderPass(commandBuffer); + + if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { + throw std::runtime_error("failed to end command buffer"); + } +} diff --git a/src/DebugGUI/public/DebugGUI.hpp b/src/DebugGUI/public/DebugGUI.hpp new file mode 100644 index 0000000..d006c61 --- /dev/null +++ b/src/DebugGUI/public/DebugGUI.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "VulkanWindow.hpp" + +#include "imgui.h" + +class ImGuiVk { +public: + ImGuiVk() = default; + + void create(VulkanWindow* vkWindow); + void setRenderPass(VkRenderPass renderPass); + + void beginFrame(); + void endFrame(); + + static void demo(); + + void destroy(VkDevice device); + + ~ImGuiVk(); + + void cmdRender(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend); + +private: + ImGuiContext* mContext = nullptr; + VulkanWindow* mVkWindow = nullptr; + + ImDrawData* mDrawData = nullptr; + VkRenderPass mRenderPass = VK_NULL_HANDLE; + VkDescriptorPool mDescriptorPool = VK_NULL_HANDLE; +}; \ No newline at end of file diff --git a/src/VulkanGraphics/public/VulkanWindow.hpp b/src/VulkanGraphics/public/VulkanWindow.hpp index e8e8895..855ca6c 100644 --- a/src/VulkanGraphics/public/VulkanWindow.hpp +++ b/src/VulkanGraphics/public/VulkanWindow.hpp @@ -58,7 +58,7 @@ private: void destroyCommandPool(); -private: +public: GLFWwindow *mWindow = nullptr; bool mWindowSizeDirtyFlag = true;