diff --git a/3rdParty/CMakeLists.txt b/3rdParty/CMakeLists.txt index 55e95f2..a5477a0 100644 --- a/3rdParty/CMakeLists.txt +++ b/3rdParty/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(pugixml) add_subdirectory(stb) add_subdirectory(eigen) add_subdirectory(utfcpp) +add_subdirectory(imgui) add_subdirectory(tracy) if (NOT LINUX) diff --git a/3rdParty/imgui/CMakeLists.txt b/3rdParty/imgui/CMakeLists.txt new file mode 100644 index 0000000..ef08911 --- /dev/null +++ b/3rdParty/imgui/CMakeLists.txt @@ -0,0 +1,58 @@ +include(FetchContent) + +project(imgui_internal VERSION 1.0 LANGUAGES C CXX) + +set(IMGUI_SRC_DIR ${CMAKE_BINARY_DIR}/3rdParty/imgui/imgui-src) + +FetchContent_Populate(imgui + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_SHALLOW TRUE + GIT_TAG origin/docking + SOURCE_DIR ${IMGUI_SRC_DIR} +) + +add_library(imgui_internal STATIC + ${IMGUI_SRC_DIR}/imgui.cpp + ${IMGUI_SRC_DIR}/imgui_draw.cpp + ${IMGUI_SRC_DIR}/imgui_demo.cpp + ${IMGUI_SRC_DIR}/imgui_tables.cpp + ${IMGUI_SRC_DIR}/imgui_widgets.cpp + ${IMGUI_SRC_DIR}/backends/imgui_impl_vulkan.cpp +) + +find_package(glfw3) +if (glfw3_FOUND) + target_sources(imgui_internal PRIVATE ${IMGUI_SRC_DIR}/backends/imgui_impl_glfw.cpp) + target_link_libraries(imgui_internal PUBLIC glfw) +endif () + +if (APPLE) + # Try to find xcframework of MoltenVK + cmake_path(SET MoltenVK_path NORMALIZE "$ENV{VULKAN_SDK}/../MoltenVK/") + cmake_path(SET MoltenVK_XC_path NORMALIZE "$ENV{VULKAN_SDK}/../MoltenVK/MoltenVK.xcframework") + if (EXISTS "${MoltenVK_path}" AND EXISTS "${MoltenVK_XC_path}") + if (EXISTS "${MoltenVK_path}/include") + set(Vulkan_INCLUDE_DIR "${MoltenVK_path}/include") + endif() + + target_link_libraries(imgui_internal PRIVATE "${MoltenVK_XC_path}/ios-arm64/libMoltenVK.a") + message("Found MoltenVK xcframework: ${MoltenVK_XC_path}") + endif() + + if (NOT ${Vulkan_INCLUDE_DIR}) + #find_package(Vulkan REQUIRED COMPONENTS MoltenVK) + #target_link_libraries(imgui_internal PRIVATE Vulkan::MoltenVK) + endif() +else () + find_package(Vulkan REQUIRED) + target_link_libraries(imgui_internal PRIVATE Vulkan::Vulkan) +endif() +target_include_directories(imgui_internal PUBLIC ${Vulkan_INCLUDE_DIR}) + +target_include_directories(imgui_internal + PUBLIC + ${IMGUI_SRC_DIR} + ${IMGUI_SRC_DIR}/backends +) + +set_property(TARGET imgui_internal PROPERTY CXX_STANDARD 17) diff --git a/CMakeLists.txt b/CMakeLists.txt index 665b284..87a9144 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,7 @@ find_package(LibArchive REQUIRED) set(ZLIB_USE_STATIC_LIBS ON) find_package(ZLIB REQUIRED) target_include_directories(openVulkanoCpp PRIVATE ${LibArchive_INCLUDE_DIR}) -target_link_libraries(openVulkanoCpp PRIVATE magic_enum yaml-cpp spdlog glm pugixml ${LibArchive_LIBRARIES} ${ZLIB_LIBRARIES} stb eigen utf8cpp TracyClient) +target_link_libraries(openVulkanoCpp PRIVATE magic_enum yaml-cpp spdlog glm pugixml ${LibArchive_LIBRARIES} ${ZLIB_LIBRARIES} stb eigen utf8cpp imgui_internal TracyClient) add_compile_definitions(GLM_FORCE_INTRINSICS) add_compile_definitions(GLM_FORCE_SILENT_WARNINGS) diff --git a/openVulkanoCpp/Base/UI/IWindow.hpp b/openVulkanoCpp/Base/UI/IWindow.hpp index 0eb288e..fbd77b7 100644 --- a/openVulkanoCpp/Base/UI/IWindow.hpp +++ b/openVulkanoCpp/Base/UI/IWindow.hpp @@ -80,6 +80,7 @@ namespace openVulkanoCpp [[nodiscard]] virtual uint32_t GetWindowId() const = 0; + virtual void* GetNativeWindowHandle() = 0; protected: static uint32_t CreateWindowId() { diff --git a/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp b/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp index 620f34d..89ab79c 100644 --- a/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp +++ b/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp @@ -85,6 +85,8 @@ namespace openVulkanoCpp::GLFW std::vector GetRequiredInstanceExtensions() override; + void* GetNativeWindowHandle() override { return window; } + public: // Window events void OnResize(uint32_t newWidth, uint32_t newHeight); diff --git a/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm b/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm index 61fe611..0404f50 100644 --- a/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm +++ b/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm @@ -58,6 +58,8 @@ public: IOpenGlWindow * GetOpenGlWindow() override { return nullptr; } IVulkanWindow * GetVulkanWindow() override { return this; } + void* GetNativeWindowHandle() override { return caMetalLayer; } + vk::SurfaceKHR CreateSurface(const vk::Instance &instance, const vk::AllocationCallbacks *pAllocator = nullptr) override { VkMetalSurfaceCreateInfoEXT surfaceCreateInfo; diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index 2ee50ef..90697ca 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -32,6 +32,7 @@ namespace openVulkanoCpp::Vulkan waitSemaphores[i].renderReady.resize(2); } resourceManager.Init(&context, context.swapChain.GetImageCount()); + uiRenderer.Init(&context); threadPool.resize(EngineConfiguration::GetEngineConfiguration()->GetNumThreads() - 1); //Setup cmd pools and buffers @@ -116,6 +117,7 @@ namespace openVulkanoCpp::Vulkan CommandHelper* cmdHelper = GetCommandData(commands.size() - 1); cmdHelper->cmdBuffer.executeCommands(submitBuffers[currentImageId].size(), submitBuffers[currentImageId].data()); context.swapChainRenderPass.End(cmdHelper->cmdBuffer); + uiRenderer.DrawUiFrame(cmdHelper->cmdBuffer); cmdHelper->cmdBuffer.end(); std::array stateFlags = { vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput), vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput) }; waitSemaphores[currentImageId].renderReady[0] = resourceManager.EndFrame(); diff --git a/openVulkanoCpp/Vulkan/Renderer.hpp b/openVulkanoCpp/Vulkan/Renderer.hpp index b3c459b..0bbe469 100644 --- a/openVulkanoCpp/Vulkan/Renderer.hpp +++ b/openVulkanoCpp/Vulkan/Renderer.hpp @@ -10,6 +10,7 @@ #include "Base/UI/IWindow.hpp" #include "Base/Logger.hpp" #include "Context.hpp" +#include "UiRenderer.hpp" #include "Resources/ResourceManager.hpp" #include "Data/ReadOnlyAtomicArrayQueue.hpp" #include "CommandHelper.hpp" @@ -35,11 +36,12 @@ namespace openVulkanoCpp::Vulkan std::vector threadPool; std::vector> commands; std::vector> submitBuffers; + UiRenderer uiRenderer; VulkanShader* shader; public: Renderer() = default; - virtual ~Renderer() = default; + ~Renderer() override = default; void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override; diff --git a/openVulkanoCpp/Vulkan/UiRenderer.cpp b/openVulkanoCpp/Vulkan/UiRenderer.cpp new file mode 100644 index 0000000..f075109 --- /dev/null +++ b/openVulkanoCpp/Vulkan/UiRenderer.cpp @@ -0,0 +1,93 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "UiRenderer.hpp" +#include "Context.hpp" +#include "Base/UI/IVulkanWindow.hpp" +#include +#include +#if __has_include("GLFW/glfw3.h") +#include +#define GLFW_AVAILABLE +#endif + +namespace openVulkanoCpp::Vulkan +{ + void UiRenderer::Init(Context* context) + { + device = context->device->device; + uiRenderPass.Init(context->device.get(), &context->swapChain, false, true); + constexpr vk::DescriptorPoolSize sizeInfo[] = { + { vk::DescriptorType::eSampler, 1000 }, + { vk::DescriptorType::eCombinedImageSampler, 1000 }, + { vk::DescriptorType::eSampledImage, 1000 }, + { vk::DescriptorType::eStorageImage, 1000 }, + { vk::DescriptorType::eUniformTexelBuffer, 1000 }, + { vk::DescriptorType::eStorageTexelBuffer, 1000 }, + { vk::DescriptorType::eUniformBuffer, 1000 }, + { vk::DescriptorType::eStorageBuffer, 1000 }, + { vk::DescriptorType::eUniformBufferDynamic, 1000 }, + { vk::DescriptorType::eStorageBufferDynamic, 1000 }, + { vk::DescriptorType::eInputAttachment, 1000 } + }; + vk::DescriptorPoolCreateInfo poolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1000, std::size(sizeInfo), sizeInfo); + + descriptorPool = context->device->device.createDescriptorPool(poolCreateInfo); + + ImGui_ImplVulkan_InitInfo vkInfo{}; + + vkInfo.Instance = context->instance; + vkInfo.PhysicalDevice = context->device->physicalDevice; + vkInfo.Device = context->device->device; + vkInfo.QueueFamily = context->device->queueIndices.GetGraphics(); + vkInfo.Queue = context->device->graphicsQueue; + //vkInfo.PipelineCache = NULL; + vkInfo.DescriptorPool = descriptorPool; + vkInfo.Subpass = 0; + vkInfo.MinImageCount = context->swapChain.GetImageCount(); + vkInfo.ImageCount = context->swapChain.GetImageCount(); + vkInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + vkInfo.UseDynamicRendering = false; + + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + + ImGui_ImplVulkan_Init(&vkInfo, uiRenderPass.renderPass); + //ImGui_ImplVulkan_Init(&vkInfo, context->swapChainRenderPass.renderPass); +#ifdef GLFW_AVAILABLE + ImGui_ImplGlfw_InitForVulkan((GLFWwindow*)context->window->GetNativeWindowHandle(), true); +#endif + } + + void UiRenderer::Close() + { + ImGui_ImplVulkan_Shutdown(); + device.destroy(descriptorPool); + } + + void UiRenderer::BeginUiFrame() const + { + ImGui_ImplVulkan_NewFrame(); +#ifdef GLFW_AVAILABLE + ImGui_ImplGlfw_NewFrame(); +#endif + ImGui::NewFrame(); + } + + void UiRenderer::DrawUiFrame(vk::CommandBuffer& cmdBuffer) + { + BeginUiFrame(); + ImGui::ShowDemoWindow(); + + ImGui::Render(); + uiRenderPass.Begin(cmdBuffer, true); + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmdBuffer); + uiRenderPass.End(cmdBuffer); + } +} diff --git a/openVulkanoCpp/Vulkan/UiRenderer.hpp b/openVulkanoCpp/Vulkan/UiRenderer.hpp new file mode 100644 index 0000000..2c115ea --- /dev/null +++ b/openVulkanoCpp/Vulkan/UiRenderer.hpp @@ -0,0 +1,37 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "RenderPass.hpp" +#include + +namespace openVulkanoCpp::Vulkan +{ + class Context; + + class UiRenderer + { + vk::Device device; + RenderPass uiRenderPass; + vk::DescriptorPool descriptorPool; + + public: + UiRenderer() = default; + + UiRenderer(Context* context) { Init(context); } + + ~UiRenderer() { if (descriptorPool) Close(); } + + void Init(Context* context); + + void BeginUiFrame() const; + + void DrawUiFrame(vk::CommandBuffer& cmdBuffer); + + void Close(); + }; +} \ No newline at end of file