From 47e53672199e566ef00636e1c7199495b3bee47a Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Fri, 18 Oct 2024 21:13:55 +0200 Subject: [PATCH] add imgui as submodule, different double buffering for computing --- .gitmodules | 4 +++ CMakeLists.txt | 8 ++++- imgui.ini | 27 ++++++++++++++++ include/application.hpp | 1 + include/vulkan/descriptor_pool.hpp | 2 +- include/vulkan/instance.hpp | 7 +++++ lib/imgui | 1 + shaders/shader.frag | 4 +-- src/application.cpp | 49 ++++++++++++++++++++---------- src/vulkan/instance.cpp | 47 ++++++++++++++++++++++++++++ 10 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 .gitmodules create mode 100644 imgui.ini create mode 160000 lib/imgui diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5d94ea8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "lib/imgui"] + path = lib/imgui + url = https://github.com/ocornut/imgui.git + branch = docking diff --git a/CMakeLists.txt b/CMakeLists.txt index d94ff89..a35caca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,15 @@ cmake_minimum_required(VERSION 3.22) project(VulkanSimulation) +include(CMakePrintHelpers) + set(CMAKE_CXX_STANDARD 20) file(GLOB_RECURSE SRC_FILES src/**.cpp) -add_executable(VulkanSimulation ${SRC_FILES}) +file(GLOB IMGUI_FILES lib/imgui/*.cpp lib/imgui/*.h lib/imgui/backends/imgui_impl_glfw* lib/imgui/backends/imgui_impl_vulkan*) +cmake_print_variables(IMGUI_FILES) + +add_executable(VulkanSimulation ${SRC_FILES} ${IMGUI_FILES}) find_package(Vulkan REQUIRED) find_package(OpenMP REQUIRED) @@ -21,6 +26,7 @@ target_compile_options(assimp PRIVATE -Wno-unknown-pragmas) target_link_libraries(VulkanSimulation glm glfw Vulkan::Vulkan GPUOpen::VulkanMemoryAllocator assimp tet OpenMP::OpenMP_CXX) target_include_directories(VulkanSimulation PRIVATE include lib) +target_include_directories(VulkanSimulation PRIVATE include lib/imgui) target_compile_definitions(VulkanSimulation PRIVATE GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE diff --git a/imgui.ini b/imgui.ini new file mode 100644 index 0000000..e1d13d7 --- /dev/null +++ b/imgui.ini @@ -0,0 +1,27 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Dear ImGui Demo] +Pos=1568,0 +Size=351,1004 +Collapsed=0 + +[Window][Dear ImGui Metrics/Debugger] +Pos=91,122 +Size=775,375 +Collapsed=0 + +[Window][Dear ImGui Debug Log] +Pos=428,238 +Size=380,328 +Collapsed=0 + +[Window][Dear ImGui Style Editor] +Pos=153,27 +Size=353,999 +Collapsed=0 + +[Docking][Data] + diff --git a/include/application.hpp b/include/application.hpp index debe8e7..7a00855 100644 --- a/include/application.hpp +++ b/include/application.hpp @@ -42,6 +42,7 @@ public: void mainLoop(); ~Application(); private: + void initIMGUI(); void createSyncObjects(); unique_ptr imageAvailable; diff --git a/include/vulkan/descriptor_pool.hpp b/include/vulkan/descriptor_pool.hpp index 22d3c52..fe159ff 100644 --- a/include/vulkan/descriptor_pool.hpp +++ b/include/vulkan/descriptor_pool.hpp @@ -22,8 +22,8 @@ public: void bindImage(const Image& image, VkDescriptorType type, DescriptorSet set, uint32_t binding); std::map sets; std::map layouts; -private: VkDescriptorPool handle = VK_NULL_HANDLE; +private: void createLayout(DescriptorSet set, const std::vector &bindings); }; \ No newline at end of file diff --git a/include/vulkan/instance.hpp b/include/vulkan/instance.hpp index 038f09c..c67c09b 100644 --- a/include/vulkan/instance.hpp +++ b/include/vulkan/instance.hpp @@ -7,10 +7,14 @@ #include #include #include "vk_mem_alloc.h" +#include "imgui.h" +#include "imgui/backends/imgui_impl_vulkan.h" +#include "imgui/backends/imgui_impl_glfw.h" using std::optional, std::vector; class CommandPool; +class Swapchain; void printVmaStats(); @@ -57,12 +61,15 @@ public: static VkPhysicalDevice GetPhysicalDevice(); static VmaAllocator GetAllocator(); static VkSurfaceKHR GetSurface(); + void initImGui(const Swapchain& swapchain); private: VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE; VmaAllocator allocator = VK_NULL_HANDLE; + VkDescriptorPool imGuiDescriptorPool = VK_NULL_HANDLE; + VkInstance handle = VK_NULL_HANDLE; void initWindow(); diff --git a/lib/imgui b/lib/imgui new file mode 160000 index 0000000..4e2126e --- /dev/null +++ b/lib/imgui @@ -0,0 +1 @@ +Subproject commit 4e2126ee44c066c642d89d25320fd32e449e5a9a diff --git a/shaders/shader.frag b/shaders/shader.frag index 83be0f0..4fa1d02 100644 --- a/shaders/shader.frag +++ b/shaders/shader.frag @@ -10,7 +10,7 @@ layout (set = 0, binding = 2) uniform sampler2D texSampler; void main() { // outColor = vec4((normal + vec3(1, 1, 1)) / 2, 1.0); - vec3 L = vec3(1, 1, 1); + vec3 L = vec3(1, 5, 1); L = normalize(L); vec3 N = normal; @@ -21,7 +21,7 @@ void main() { float lambertian = max(dot(L, N), 0); vec3 diffuse = lambertian * albedo; - vec3 ambient = vec3(1, 1, 1) * 0.01; + vec3 ambient = albedo * 0.1; vec3 C = ambient + diffuse; diff --git a/src/application.cpp b/src/application.cpp index a9c50e3..a70adbe 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -15,6 +15,14 @@ #include "timer.hpp" #include "grabber.hpp" #include "stb_image.h" +#include +#include +#include "imgui.h" +#include "imgui/backends/imgui_impl_vulkan.h" +#include "imgui/backends/imgui_impl_glfw.h" + +using namespace std::chrono; + struct SizesUniformData { uint32_t vertexCount; @@ -51,6 +59,7 @@ struct PBDPushData { Application::Application() { createSyncObjects(); swapchain = make_unique(); + Instance::instance->initImGui(*swapchain); descriptorPool = make_unique(); graphicsPipeline = unique_ptr(new GraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", swapchain->renderPass, @@ -129,14 +138,11 @@ Application::Application() { printVmaStats(); } -#include -#include - -using namespace std::chrono; - void Application::mainLoop() { vkDeviceWaitIdle(Instance::GetDevice()); std::future compute = std::async(std::launch::async, [this](){ + setbuf(stdout, NULL); + descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0); while (!glfwWindowShouldClose(Instance::instance->window)){ auto t1 = system_clock::now(); update(); @@ -145,12 +151,26 @@ void Application::mainLoop() { auto measuredUpdateDuration = duration(t2 - t1); auto requestedUpdateDuration = duration(simulationPropertiesBuffer->access().dt); std::this_thread::sleep_for(requestedUpdateDuration - measuredUpdateDuration); + + auto totalUpdateDuration = std::max(requestedUpdateDuration, measuredUpdateDuration); + printf("\r%f", totalUpdateDuration.count()); } }); + bool show_demo_window = true; + auto t1 = system_clock::now(); while (!glfwWindowShouldClose(Instance::instance->window)){ glfwPollEvents(); + + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + ImGui::ShowDemoWindow(&show_demo_window); + + ImGui::Render(); + auto t2 = system_clock::now(); float seconds = duration(t2 - t1).count(); t1 = system_clock::now(); @@ -176,18 +196,18 @@ void Application::createSyncObjects() { void Application::createMeshBuffers() { Mesh sphere("models/icosphere.ply"); - Mesh bunny("models/bunny_high.ply"); + Mesh bunny("models/bunny_medium.ply"); - auto body = std::make_unique(&sphere, 1.f / 100); + auto body = std::make_unique(&sphere, 1.f / 60); - for (size_t i = 0; i < 0; i++){ + for (size_t i = 0; i < 5; i++){ auto copy = std::make_unique(*body.get()); copy->applyVertexOffset({i * 2, 0, 0}); softBodies.push_back(std::move(copy)); } body = std::make_unique(&bunny, 1.f / 10); - for (size_t i = 0; i < 2; i++){ + for (size_t i = 0; i < 5; i++){ auto copy = std::make_unique(*body.get()); copy->applyVertexOffset({i * 2, 0, 2}); softBodies.push_back(std::move(copy)); @@ -423,6 +443,8 @@ void Application::drawFrame(float dt) { recordDrawCommands(cmdBuffer); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmdBuffer); + vkCmdEndRenderPass(cmdBuffer); vkEndCommandBuffer(cmdBuffer); } @@ -485,11 +507,12 @@ void Application::update() { vkResetFences(Instance::GetDevice(), 1, &computeFence->handle); currentDrawVertexBuffer = 1 - currentDrawVertexBuffer; - descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0); vkWaitForFences(Instance::GetDevice(), 1, &transferFence->handle, VK_TRUE, UINT64_MAX); vkResetFences(Instance::GetDevice(), 1, &transferFence->handle); + currentDrawVertexBuffer = 1 - currentDrawVertexBuffer; + VkCommandBufferBeginInfo beginInfo {}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = 0; @@ -687,9 +710,3 @@ void Application::recordNormalCommands(VkCommandBuffer cmdBuffer) { barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr); } - - - - - - diff --git a/src/vulkan/instance.cpp b/src/vulkan/instance.cpp index 47b4f13..cb59be0 100644 --- a/src/vulkan/instance.cpp +++ b/src/vulkan/instance.cpp @@ -70,6 +70,7 @@ void Instance::initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); window = glfwCreateWindow(800, 600, "Vulkan Simulation", nullptr, nullptr); glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) { instance->windowResized = true; @@ -283,6 +284,12 @@ VkSurfaceKHR Instance::GetSurface() { Instance::~Instance() { delete renderingCommandPool; delete computeCommandPool; + + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + vkDestroyDescriptorPool(Instance::GetDevice(), imGuiDescriptorPool, nullptr); + vmaDestroyAllocator(allocator); vkDestroyDevice(device, nullptr); vkDestroySurfaceKHR(handle, surface, nullptr); @@ -291,3 +298,43 @@ Instance::~Instance() { glfwDestroyWindow(window); glfwTerminate(); } + +void Instance::initImGui(const Swapchain& swapchain) { + ImGui::CreateContext(); + ImGui::StyleColorsDark(); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + + ImGui_ImplGlfw_InitForVulkan(window, true); + + VkDescriptorPoolSize pool_sizes[] = { + { + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 + } + }; + VkDescriptorPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + pool_info.maxSets = 1; + pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); + pool_info.pPoolSizes = pool_sizes; + vkCreateDescriptorPool(Instance::GetDevice(), &pool_info, nullptr, &imGuiDescriptorPool); + + ImGui_ImplVulkan_InitInfo initInfo {}; + initInfo.Instance = handle; + initInfo.PhysicalDevice = physicalDevice; + initInfo.Device = device; + initInfo.QueueFamily = renderingCommandPool->queueFamilyIndex; + initInfo.Queue = graphicsAndPresentQueue; + initInfo.PipelineCache = VK_NULL_HANDLE; + initInfo.DescriptorPool = imGuiDescriptorPool; + initInfo.RenderPass = swapchain.renderPass; + initInfo.Subpass = 0; + initInfo.MinImageCount = swapchain.frameBuffers.size(); + initInfo.ImageCount = swapchain.frameBuffers.size(); + initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + initInfo.Allocator = VK_NULL_HANDLE; + initInfo.CheckVkResultFn = VK_NULL_HANDLE; + + ImGui_ImplVulkan_Init(&initInfo); +}