diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..add20bf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/imgui"] + path = src/imgui + url = https://github.com/ocornut/imgui.git diff --git a/CMakeLists.txt b/CMakeLists.txt index a468201..892b255 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,6 @@ find_package( glm REQUIRED ) find_package( VulkanMemoryAllocator CONFIG REQUIRED ) find_package( fmt REQUIRED ) # Shader compilers -# Todo - add_executable (glslang::validator IMPORTED) find_program (GLSLANG_VALIDATOR "glslangValidator" HINTS $ENV{VULKAN_SDK}/bin REQUIRED) set_property (TARGET glslang::validator PROPERTY IMPORTED_LOCATION "${GLSLANG_VALIDATOR}") @@ -93,7 +91,7 @@ endfunction() # A function to automate executables aditions function ( addBinary BINARY_NAME ) - cmake_parse_arguments ( BINARY "" "SOURCE" "SHADERS;SLANG_SHADERS;LIBS;TEXTURES;MODELS" ${ARGN} ) + cmake_parse_arguments ( BINARY "IMGUI" "SOURCE" "SHADERS;SLANG_SHADERS;LIBS;TEXTURES;MODELS" ${ARGN} ) if (DEFINED BINARY_SOURCE) add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp ) endif() @@ -118,6 +116,22 @@ function ( addBinary BINARY_NAME ) # Exposes versions BUILD_ID="${ENGINE_VERSION}" ) + if(BINARY_IMGUI) + target_include_directories(${BINARY_NAME} PRIVATE + ${CMAKE_SOURCE_DIR}/src/imgui + ${CMAKE_SOURCE_DIR}/src/imgui/backends + ) + target_sources(${BINARY_NAME} PRIVATE + ${CMAKE_SOURCE_DIR}/src/imgui/imgui.cpp + + ${CMAKE_SOURCE_DIR}/src/imgui/imgui_draw.cpp + ${CMAKE_SOURCE_DIR}/src/imgui/imgui_tables.cpp + ${CMAKE_SOURCE_DIR}/src/imgui/imgui_widgets.cpp + + ${CMAKE_SOURCE_DIR}/src/imgui/backends/imgui_impl_glfw.cpp + ${CMAKE_SOURCE_DIR}/src/imgui/backends/imgui_impl_vulkan.cpp + ) + endif() if(DEFINED BINARY_SHADERS) set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${BINARY_NAME}/shaders) @@ -185,6 +199,7 @@ addBinary ( SHADERS shaders/gradient.comp LIBS glfw fmt vk-bootstrap vulkan + IMGUI ) addBinary ( diff --git a/src/Engine/engine/engine.h b/src/Engine/engine/engine.h index 5855817..1503457 100644 --- a/src/Engine/engine/engine.h +++ b/src/Engine/engine/engine.h @@ -6,7 +6,9 @@ #include "descriptors.h" // Required for public interface custom allocator #include "Common/Types.h" #include +#include #include +#include #include @@ -68,6 +70,11 @@ class Engine { VkPipeline _gradientPipeline; VkPipelineLayout _gradientPipelineLayout; + // Immediate commands + VkFence _immFence; // Immediate mode fence + VkCommandBuffer _immCommandBuffer; + VkCommandPool _immCommandPool; + void init(); @@ -77,15 +84,27 @@ class Engine { void run(); + void immediateSubmit( + std::function < + void( + VkCommandBuffer cmd + ) + > && function + ); + private: + // Init functions void initRender(); void initVulkan(); void initSwapchain(); void initCommands(); void initSyncStructures(); + void initDescriptors(); void initPipelines(); void initBackgroundPipelines(); + void initImgui(); + // Random functions void createSwapchain( uint32_t width, uint32_t height @@ -95,7 +114,7 @@ class Engine { VkCommandBuffer cmd ); - void initDescriptors(); + }; #endif @@ -124,6 +143,11 @@ class Engine { #include "Common/Types.h" #include "Common/Timer.h" +// Imgui +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_vulkan.h" + #include "VkBootstrap.h" #include "vk_mem_alloc.h" @@ -575,6 +599,35 @@ void Engine::initCommands() { ) ); } + // Immediate commands + + VK_CHECK( + vkCreateCommandPool( + _device, + &commandPoolInfo, + nullptr, + &_immCommandPool + ); + ); + + VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::commandBufferAllocateInfo(_immCommandPool, 1); + + VK_CHECK( + vkAllocateCommandBuffers( + _device, + &cmdAllocInfo, + &_immCommandBuffer + ) + ); + + _mainDeletionQueue.pushFunction([this]() { + vkDestroyCommandPool( + _device, + _immCommandPool, + nullptr + ); + }); + #ifdef DEBUG fmt::println("[Engine:Init] Vulkan commands initialized !"); #endif @@ -595,6 +648,25 @@ void Engine::initSyncStructures() { VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._renderSemaphore)); } + // Immediate sync objects + VK_CHECK( + vkCreateFence( + _device, + &fenceCreateInfo, + nullptr, + &_immFence + ); + ); + + _mainDeletionQueue.pushFunction([this]() { + vkDestroyFence( + _device, + _immFence, + nullptr + ); + }); + + #ifdef DEBUG fmt::println("[Engine:Init] Sync structures created !"); #endif @@ -761,6 +833,83 @@ void Engine::initBackgroundPipelines() { #endif } +void Engine::initImgui() { + // Oversized descriptor pool for IMGUI, from the official tutorial + // Ajust for optimization, or needs + + VkDescriptorPoolSize poolSizes[] = { + { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, + { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } + }; + + VkDescriptorPoolCreateInfo poolInfo { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = 1000, + .poolSizeCount = (uint32_t)std::size(poolSizes), + .pPoolSizes = poolSizes + }; + + VkDescriptorPool imguiPool; + VK_CHECK( + vkCreateDescriptorPool( + _device, + &poolInfo, + nullptr, + &imguiPool + ); + ); + + // Init IMGUI + ImGui::CreateContext(); + + ImGui_ImplGlfw_InitForVulkan( + window, + true + ); + + ImGui_ImplVulkan_InitInfo initInfo { + .Instance = _instance, + .PhysicalDevice = _choosenGPU, + .Device = _device, + .Queue = _graphicsQueue, + .DescriptorPool = imguiPool, + .MinImageCount = 3, + .ImageCount = 3, + .PipelineInfoMain = { + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + .PipelineRenderingCreateInfo { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &_swapchainImageFormat + } + }, + .UseDynamicRendering = true + }; + + ImGui_ImplVulkan_Init(&initInfo); + + _mainDeletionQueue.pushFonction([this]() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool( + _device, + imguiPool, + nullptr + ); + }); + +} + + //================================ //=== Render-related Functions === //================================ @@ -862,6 +1011,74 @@ void Engine::drawBackground( } +void Engine::immediateSubmit( + std::function< + void(VkCommandBuffer cmd) + >&& function +) { + + VK_CHECK( + vkResetFences( + _device, + 1, + &_immFence + ); + ); + + VK_CHECK( + vkResetCommandBuffer( + _immCommandBuffer, + 0 + ); + ); + + VkCommandBuffer cmd = _immCommandBuffer; + + VkCommandBufferBeginInfo cmdBeginInfo = vkinit::commandBufferBeginInfo(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + + VK_CHECK( + vkBeginCommandBuffer( + cmd, + &cmdBeginInfo + ); + ); + + function(cmd); + + VK_CHECK( + vkEndCommandBuffer( + cmd + ); + ); + + VkCommandBufferSubmitInfo cmdInfo = vkinit::commandBufferSubmitInfo(cmd); + VkSubmitInfo2 submit = vkinit::submitInfo( + &cmdInfo, + nullptr, + nullptr + ); + + // Blocking operation, waits until graphics operation finish + VK_CHECK( + vkQueueSubmit2( + _graphicsQueue, + 1, + &submit, + _immFence + ); + ); + + VK_CHECK( + vkWaitForFences( + _device, + 1, + &_immFence, + true, + INT64_MAX + ); + ); + +} #endif #endif diff --git a/src/imgui b/src/imgui new file mode 160000 index 0000000..5220a3f --- /dev/null +++ b/src/imgui @@ -0,0 +1 @@ +Subproject commit 5220a3f48d39c000da8b46fb0fccf3dd62695c51