diff --git a/config/Sources.cmake b/config/Sources.cmake index b51b37b5eb734021663184c813cdb350018999d9..606dc4c97d62ed284d5967707e07237ebd2f7580 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -85,6 +85,12 @@ set(vkcv_sources ${vkcv_source}/vkcv/SamplerManager.hpp ${vkcv_source}/vkcv/SamplerManager.cpp + + ${vkcv_source}/vkcv/WindowManager.hpp + ${vkcv_source}/vkcv/WindowManager.cpp + + ${vkcv_source}/vkcv/SwapchainManager.hpp + ${vkcv_source}/vkcv/SwapchainManager.cpp ${vkcv_include}/vkcv/DescriptorWrites.hpp diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index b82d2edad914a632c5e2ea1be2d08f56b3a912e4..d6e47d26e5c26dab7929ac5905938c2ac0c80125 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -25,6 +25,9 @@ #include "Event.hpp" #include "DrawcallRecording.hpp" #include "CommandRecordingFunctionTypes.hpp" +#include "../../src/vkcv/WindowManager.hpp" +#include "../../src/vkcv/SwapchainManager.hpp" + namespace vkcv { @@ -38,6 +41,8 @@ namespace vkcv class SamplerManager; class ImageManager; class CommandStreamManager; + class WindowManager; + class SwapchainManager; struct SubmitInfo { QueueType queueType; @@ -54,18 +59,14 @@ namespace vkcv * * @param context encapsulates various Vulkan objects */ - Core(Context &&context, Window &window, const Swapchain& swapChain, std::vector<vk::ImageView> imageViews, - const CommandResources& commandResources, const SyncResources& syncResources) noexcept; + Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept; // explicit destruction of default constructor Core() = delete; - Result acquireSwapchainImage(); + Result acquireSwapchainImage(const SwapchainHandle &swapchainHandle); Context m_Context; - Swapchain m_swapchain; - Window& m_window; - std::unique_ptr<PassManager> m_PassManager; std::unique_ptr<GraphicsPipelineManager> m_PipelineManager; std::unique_ptr<ComputePipelineManager> m_ComputePipelineManager; @@ -74,12 +75,18 @@ namespace vkcv std::unique_ptr<SamplerManager> m_SamplerManager; std::unique_ptr<ImageManager> m_ImageManager; std::unique_ptr<CommandStreamManager> m_CommandStreamManager; + std::unique_ptr<WindowManager> m_WindowManager; + std::unique_ptr<SwapchainManager> m_SwapchainManager; CommandResources m_CommandResources; SyncResources m_SyncResources; uint32_t m_currentSwapchainImageIndex; - event_handle<int,int> e_resizeHandle; + /** + * sets up swapchain images + * @param swapchainHandles of swapchain + */ + void setSwapchainImages(SwapchainHandle handle); public: /** @@ -119,9 +126,6 @@ namespace vkcv [[nodiscard]] const Context &getContext() const; - - [[nodiscard]] - const Swapchain& getSwapchain() const; /** * Creates a #Core with given @p applicationName and @p applicationVersion for your application. @@ -138,8 +142,7 @@ namespace vkcv * @param[in] deviceExtensions (optional) Requested device extensions * @return New instance of #Context */ - static Core create(Window &window, - const char *applicationName, + static Core create(const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags = {}, const Features& features = {}, @@ -224,12 +227,73 @@ namespace vkcv bool supportColorAttachment = false, Multisampling multisampling = Multisampling::None); + /** + * creates a new window and returns it's handle + * @param applicationName window name + * @param windowWidth + * @param windowHeight + * @param resizeable resizeability bool + * @return windowHandle + */ + [[nodiscard]] + WindowHandle createWindow( + const char *applicationName, + uint32_t windowWidth, + uint32_t windowHeight, + bool resizeable); + + /** + * getter for window reference + * @param handle of the window + * @return the window + */ + [[nodiscard]] + Window& getWindow(const WindowHandle& handle ); + + /** + * gets the swapchain of the current focused window + * @return swapchain + */ + [[nodiscard]] + Swapchain& getSwapchainOfCurrentWindow(); + + /** + * returns the swapchain reference + * @param handle of the swapchain + * @return swapchain + */ + [[nodiscard]] + Swapchain& getSwapchain(const SwapchainHandle& handle); + + /** + * gets the swapchain handle from the window + * @param handle of the window + * @return the swapchain from getSwapchain( SwapchainHandle ) + */ + [[nodiscard]] + Swapchain& getSwapchain(const WindowHandle& handle); + + /** + * returns the image width + * @param image handle + * @return imageWidth + */ [[nodiscard]] uint32_t getImageWidth(const ImageHandle& image); - + + /** + * returns the image height + * @param image handle + * @return imageHeight + */ [[nodiscard]] uint32_t getImageHeight(const ImageHandle& image); - + + /** + * returns the image format of the image + * @param image handle + * @return imageFormat + */ [[nodiscard]] vk::Format getImageFormat(const ImageHandle& image); @@ -256,7 +320,7 @@ namespace vkcv /** * @brief start recording command buffers and increment frame index */ - bool beginFrame(uint32_t& width, uint32_t& height); + bool beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle); void recordDrawcallsToCmdStream( const CommandStreamHandle& cmdStreamHandle, @@ -264,7 +328,8 @@ namespace vkcv const GraphicsPipelineHandle &pipelineHandle, const PushConstants &pushConstants, const std::vector<DrawcallInfo> &drawcalls, - const std::vector<ImageHandle> &renderTargets); + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle); void recordMeshShaderDrawcalls( const CommandStreamHandle& cmdStreamHandle, @@ -272,7 +337,8 @@ namespace vkcv const GraphicsPipelineHandle &pipelineHandle, const PushConstants& pushConstantData, const std::vector<MeshShaderDrawcall>& drawcalls, - const std::vector<ImageHandle>& renderTargets); + const std::vector<ImageHandle>& renderTargets, + const WindowHandle& windowHandle); void recordComputeDispatchToCmdStream( CommandStreamHandle cmdStream, @@ -298,7 +364,7 @@ namespace vkcv /** * @brief end recording and present image */ - void endFrame(); + void endFrame( const WindowHandle& windowHandle ); /** * Submit a command buffer to any queue of selected type. The recording can be customized by a diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index 4a1df5852adc0fc8fe924041cb7879ec0e376001..1e6091c97dbe8dfc31013b653f175acede76070b 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -115,6 +115,18 @@ namespace vkcv }; + class WindowHandle : public Handle { + friend class WindowManager; + private: + using Handle::Handle; + }; + + class SwapchainHandle : public Handle { + friend class SwapchainManager; + private: + using Handle::Handle; + }; + class CommandStreamHandle : public Handle { friend class CommandStreamManager; private: diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp index 0919d20d8e07fee67ceb2f393c29b4a53c51b857..9d219c9d7a308cac29bec1580bd8894a70f68fb3 100644 --- a/include/vkcv/QueueManager.hpp +++ b/include/vkcv/QueueManager.hpp @@ -39,6 +39,14 @@ namespace vkcv { std::vector<std::pair<int, int>> &queuePairsCompute, std::vector<std::pair<int, int>> &queuePairsTransfer); + /** + * checks for surface support in the queues + * @param physicalDevice to get the Queues + * @param surface that needs to checked + * @return + */ + static uint32_t checkSurfaceSupport(const vk::PhysicalDevice &physicalDevice, vk::SurfaceKHR &surface); + private: std::vector<Queue> m_graphicsQueues; std::vector<Queue> m_computeQueues; diff --git a/include/vkcv/Swapchain.hpp b/include/vkcv/Swapchain.hpp index 5e9bc7d0593a3b2e1f1f8e7b5ef7ea69e9711fb5..c7741c652926fad5d581ecf7465ed74af9e2db37 100644 --- a/include/vkcv/Swapchain.hpp +++ b/include/vkcv/Swapchain.hpp @@ -13,6 +13,8 @@ namespace vkcv class Swapchain final { private: friend class Core; + friend class Window; + friend class SwapchainManager; struct Surface { @@ -20,6 +22,7 @@ namespace vkcv std::vector<vk::SurfaceFormatKHR> formats; vk::SurfaceCapabilitiesKHR capabilities; std::vector<vk::PresentModeKHR> presentModes; + uint32_t presentQueueIndex; }; Surface m_Surface; @@ -34,15 +37,18 @@ namespace vkcv std::atomic<bool> m_RecreationRequired; - /** - * Constructor of a SwapChain object - * glfw is not initialized in this class because ist must be sure that there exists a context first - * glfw is already initialized by the window class - * @param surface used by the swapchain - * @param swapchain to show images in the window - * @param format - */ - // TODO: + /** + * Constructor of a SwapChain object + * glfw is not initialized in this class because ist must be sure that there exists a context first + * glfw is already initialized by the window class + * @param surface used by the swapchain + * @param swapchain to show images in the window + * @param format of the swapchain + * @param colorSpace of the swapchain + * @param presentMode of the swapchain + * @param imageCount of the swapchain + * @param extent of the swapchain + */ Swapchain(const Surface &surface, vk::SwapchainKHR swapchain, vk::Format format, @@ -52,22 +58,20 @@ namespace vkcv vk::Extent2D extent) noexcept; /** - * TODO - * - * @return + * checks if the update flag is true + * @return if an update is needed */ bool shouldUpdateSwapchain() const; /** - * TODO - * + * recreates the swapchain * context * window */ void updateSwapchain(const Context &context, const Window &window); /** - * + * signal that the swapchain needs to be recreated */ void signalSwapchainRecreation(); @@ -114,13 +118,17 @@ namespace vkcv uint32_t getImageCount() const; /** - * TODO - * - * @return + * @return the 2d extent of the swapchain */ [[nodiscard]] const vk::Extent2D& getExtent() const; - - }; + + /** + * @return the familyQueueIndex for the surface + */ + [[nodiscard]] + const uint32_t& getPresentQueueIndex() const; + + }; } diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index f3b3a8fe88ae6e8791d7d92361ad5b6bf2447dcb..cef735632689cdd119b694674e9ac7af67471a3c 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -1,107 +1,90 @@ #pragma once -/** - * @authors Sebastian Gaida - * @file src/vkcv/Window.hpp - * @brief Window class to handle a basic rendering surface and input - */ #define NOMINMAX #include <algorithm> +#include <string> #include "Event.hpp" +#include "Handles.hpp" struct GLFWwindow; namespace vkcv { class Window { - protected: - GLFWwindow *m_window; - - /** - * - * @param GLFWwindow of the class - */ - explicit Window(GLFWwindow *window); + friend class WindowManager; + friend class SwapchainManager; - private: - /** - * mouse callback for moving the mouse on the screen - * @param[in] window The window that received the event. - * @param[in] xpos The new cursor x-coordinate, relative to the left edge of the content area. - * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the content area. - */ - static void onMouseMoveEvent(GLFWwindow *window, double x, double y); - - /** - * mouseButton callback for mouse buttons - * @param[in] button The [mouse button](@ref buttons) that was pressed or released. - * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were held down. - */ - static void onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods); - - /** - * @brief A callback function for handling mouse scrolling events. - * @param[in] callbackWindow The window that received the event. - * @param[in] xoffset The extent of horizontal scrolling. - * @param[in] yoffset The extent of vertical scrolling. - */ - static void onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset); - - /** - * resize callback for the resize option of the window - * @param[in] window The window that was resized. - * @param[in] width The new width, in screen coordinates, of the window. - * @param[in] height The new height, in screen coordinates, of the window. - */ - static void onResize(GLFWwindow *callbackWindow, int width, int height); - - /** - * key callback for the pressed key - * @param[in] window The window that received the event. - * @param[in] key The [keyboard key](@ref keys) that was pressed or released. - * @param[in] scancode The system-specific scancode of the key. - * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were held down. - */ - static void onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods); - - /** - * char callback for any typed character - * @param[in] window The window that received the event - * @param[in] c The character that got typed - */ - static void onCharEvent(GLFWwindow *callbackWindow, unsigned int c); - - /** - * @brief A callback function for gamepad input events. - * @param gamepadIndex The gamepad index. - */ - static void onGamepadEvent(int gamepadIndex); + private: + std::string m_title; + bool m_resizable; + bool m_shouldClose; + GLFWwindow *m_window; + SwapchainHandle m_swapchainHandle; + event_handle<int, int> m_resizeHandle; public: - /** - * creates a GLFWwindow with the parameters in the function - * @param[in] windowTitle of the window - * @param[in] width of the window (optional) - * @param[in] height of the window (optional) + /** + * creates an uninitialized #Window + */ + Window(); + + /** + * creates a #Window with the parameters + * + * @param[in] title title of the window + * @param[in] width width of the window (optional) + * @param[in] height height of the window (optional) * @param[in] resizable resize ability of the window (optional) - * @return Window class */ - static Window create( const char *windowTitle, int width = -1, int height = -1, bool resizable = false); + explicit Window(const char* title, int width = -1, int height = -1, bool resizable = false); + + /** + * Copy-constructor of #Window + * + * @param other Other instance of #Window + */ + Window(const Window& other) = delete; + + /** + * Copy-operator of #Window + * + * @param other Other instance of #Window + * @return Reference to itself + */ + Window &operator=(const Window &other) = delete; + /** * checks if the window is still open, or the close event was called * This function should be changed/removed later on * @return bool if the window is still open */ [[nodiscard]] - bool isWindowOpen() const; + bool isOpen() const; + + /** + * gets the currently focused window and returns it + * only accessible to WindowManager + * @return + */ + static Window& getFocusedWindow(); + + /** + * checks if any GLFWWindows are open + * @return bool if a window is open + */ + static bool hasOpenWindow(); /** * polls all events on the GLFWwindow */ static void pollEvents(); + + /** + * + * @return + */ + static const std::vector<std::string>& getExtensions(); /** * basic events of the window @@ -120,26 +103,16 @@ namespace vkcv { */ [[nodiscard]] GLFWwindow *getWindow() const; - - /** - * Copy-operator of #Window is deleted! - * - * @param other Other instance of #Window - * @return Reference to itself - */ - Window &operator=(const Window &other) = delete; - + /** - * Move-operator of #Window uses default behavior! - * - * @param other Other instance of #Window - * @return Reference to itself + * gets the window title + * @return string with window title */ - Window &operator=(Window &&other) = default; + [[nodiscard]] + const std::string& getTitle() const; /** * gets the window width - * @param window glfwWindow * @return int with window width */ [[nodiscard]] @@ -147,23 +120,40 @@ namespace vkcv { /** * gets the window height - * @param window glfwWindow * @return int with window height */ [[nodiscard]] int getHeight() const; + + /** + * is the window resizable + * @return bool with window resizable + */ + [[nodiscard]] + bool isResizable() const; /** * Destructor of #Window, terminates GLFW */ virtual ~Window(); - + + /** + * destroys the window + */ + //void destroyWindow(); + /** * gets the windows framebuffer size * @param width * @param height */ void getFramebufferSize(int& width, int& height) const; + + /** + * gets the SwapchainHandle corresponding to the swapchain of the window + * @return + */ + SwapchainHandle getSwapchainHandle() const; }; } diff --git a/modules/gui/include/vkcv/gui/GUI.hpp b/modules/gui/include/vkcv/gui/GUI.hpp index d1a9986c5f69bfd9d4392bd5ae50f0b1f8b60642..8826cdbac057e39f2655844bfe9a252da43a4596 100644 --- a/modules/gui/include/vkcv/gui/GUI.hpp +++ b/modules/gui/include/vkcv/gui/GUI.hpp @@ -11,7 +11,7 @@ namespace vkcv::gui { class GUI final { private: - Window& m_window; + WindowHandle m_windowHandle; Core& m_core; const Context& m_context; @@ -33,7 +33,7 @@ namespace vkcv::gui { * @param core Valid #Core instance of the framework * @param window Valid #Window instance of the framework */ - GUI(Core& core, Window& window); + GUI(Core& core, WindowHandle& windowHandle); GUI(const GUI& other) = delete; GUI(GUI&& other) = delete; diff --git a/modules/gui/src/vkcv/gui/GUI.cpp b/modules/gui/src/vkcv/gui/GUI.cpp index 38bb6894fb2b40c6ab10445f19431f87f7370afc..22c40d2937c69525c04ffd79f26107f829e42f4d 100644 --- a/modules/gui/src/vkcv/gui/GUI.cpp +++ b/modules/gui/src/vkcv/gui/GUI.cpp @@ -15,31 +15,33 @@ namespace vkcv::gui { vkcv_log(LogLevel::ERROR, "ImGui has a problem with Vulkan! (%s)", vk::to_string(result).c_str()); } - GUI::GUI(Core& core, Window& window) : - m_window(window), + GUI::GUI(Core& core, WindowHandle& windowHandle) : + m_windowHandle(windowHandle), m_core(core), m_context(m_core.getContext()), m_gui_context(nullptr) { IMGUI_CHECKVERSION(); m_gui_context = ImGui::CreateContext(); + + Window& window = m_core.getWindow(windowHandle); + + ImGui_ImplGlfw_InitForVulkan(window.getWindow(), false); - ImGui_ImplGlfw_InitForVulkan(m_window.getWindow(), false); - - f_mouseButton = m_window.e_mouseButton.add([&](int button, int action, int mods) { - ImGui_ImplGlfw_MouseButtonCallback(m_window.getWindow(), button, action, mods); + f_mouseButton = window.e_mouseButton.add([&](int button, int action, int mods) { + ImGui_ImplGlfw_MouseButtonCallback(window.getWindow(), button, action, mods); }); - f_mouseScroll = m_window.e_mouseScroll.add([&](double xoffset, double yoffset) { - ImGui_ImplGlfw_ScrollCallback(m_window.getWindow(), xoffset, yoffset); + f_mouseScroll = window.e_mouseScroll.add([&](double xoffset, double yoffset) { + ImGui_ImplGlfw_ScrollCallback(window.getWindow(), xoffset, yoffset); }); - f_key = m_window.e_key.add([&](int key, int scancode, int action, int mods) { - ImGui_ImplGlfw_KeyCallback(m_window.getWindow(), key, scancode, action, mods); + f_key = window.e_key.add([&](int key, int scancode, int action, int mods) { + ImGui_ImplGlfw_KeyCallback(window.getWindow(), key, scancode, action, mods); }); - f_char = m_window.e_char.add([&](unsigned int c) { - ImGui_ImplGlfw_CharCallback(m_window.getWindow(), c); + f_char = window.e_char.add([&](unsigned int c) { + ImGui_ImplGlfw_CharCallback(window.getWindow(), c); }); vk::DescriptorPoolSize pool_sizes[] = { @@ -66,7 +68,7 @@ namespace vkcv::gui { m_descriptor_pool = m_context.getDevice().createDescriptorPool(descriptorPoolCreateInfo); const vk::PhysicalDevice& physicalDevice = m_context.getPhysicalDevice(); - const Swapchain& swapchain = m_core.getSwapchain(); + const Swapchain& swapchain = m_core.getSwapchain(m_windowHandle); const uint32_t graphicsQueueFamilyIndex = ( m_context.getQueueManager().getGraphicsQueues()[0].familyIndex @@ -152,18 +154,19 @@ namespace vkcv::gui { GUI::~GUI() { m_context.getDevice().waitIdle(); - + Window& window = m_core.getWindow(m_windowHandle); + ImGui_ImplVulkan_Shutdown(); m_context.getDevice().destroyRenderPass(m_render_pass); m_context.getDevice().destroyDescriptorPool(m_descriptor_pool); ImGui_ImplGlfw_Shutdown(); - - m_window.e_mouseButton.remove(f_mouseButton); - m_window.e_mouseScroll.remove(f_mouseScroll); - m_window.e_key.remove(f_key); - m_window.e_char.remove(f_char); + + window.e_mouseButton.remove(f_mouseButton); + window.e_mouseScroll.remove(f_mouseScroll); + window.e_key.remove(f_key); + window.e_char.remove(f_char); if (m_gui_context) { ImGui::DestroyContext(m_gui_context); @@ -171,7 +174,7 @@ namespace vkcv::gui { } void GUI::beginGUI() { - const Swapchain& swapchain = m_core.getSwapchain(); + const Swapchain& swapchain = m_core.getSwapchain(m_windowHandle); const auto extent = swapchain.getExtent(); if ((extent.width > 0) && (extent.height > 0)) { @@ -194,7 +197,7 @@ namespace vkcv::gui { return; } - const Swapchain& swapchain = m_core.getSwapchain(); + const Swapchain& swapchain = m_core.getSwapchain(m_windowHandle); const auto extent = swapchain.getExtent(); const vk::ImageView swapchainImageView = m_core.getSwapchainImageView(); diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp index b0afec4819105e4a27f7e6a635cb9ca70b0db2c5..095c5e278e9e3f76544e884bdb87cea10770307a 100644 --- a/modules/scene/include/vkcv/scene/Scene.hpp +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -61,7 +61,8 @@ namespace vkcv::scene { const GraphicsPipelineHandle &pipeline, size_t pushConstantsSizePerDrawcall, const RecordMeshDrawcallFunction &record, - const std::vector<ImageHandle> &renderTargets); + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle); static Scene create(Core& core); diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index 0cb4efd2c50e6d013f817949241476e848b4a151..cd02004f56ea3dfddcd20618b7859a0699d92d71 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -115,7 +115,8 @@ namespace vkcv::scene { const GraphicsPipelineHandle &pipeline, size_t pushConstantsSizePerDrawcall, const RecordMeshDrawcallFunction &record, - const std::vector<ImageHandle> &renderTargets) { + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle) { m_core->recordBeginDebugLabel(cmdStream, "vkcv::scene::Scene", { 0.0f, 1.0f, 0.0f, 1.0f }); @@ -139,7 +140,8 @@ namespace vkcv::scene { pipeline, pushConstants, drawcalls, - renderTargets + renderTargets, + windowHandle ); m_core->recordEndDebugLabel(cmdStream); diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index c1bce3dbd6315cd7014f4dcfb1df821f871c58f3..5ef277dfedbfa823a2b6fa55c5a6303117ddaa52 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -1,6 +1,5 @@ #include <iostream> #include <vkcv/Core.hpp> -#include <GLFW/glfw3.h> #include <vkcv/camera/CameraManager.hpp> #include <chrono> #include <vkcv/asset/asset_loader.hpp> @@ -9,21 +8,18 @@ int main(int argc, const char** argv) { const char* applicationName = "First Mesh"; - vkcv::Window window = vkcv::Window::create( - applicationName, - 800, - 600, - true - ); - + uint32_t windowWidth = 800; + uint32_t windowHeight = 600; + vkcv::Core core = vkcv::Core::create( - window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, { VK_KHR_SWAPCHAIN_EXTENSION_NAME } ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false); + vkcv::asset::Scene mesh; const char* path = argc > 1 ? argv[1] : "assets/cube/cube.gltf"; @@ -57,7 +53,7 @@ int main(int argc, const char** argv) { const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat() + core.getSwapchain(windowHandle).getFormat() ); const vkcv::AttachmentDescription depth_attachment( @@ -158,7 +154,7 @@ int main(int argc, const char** argv) { core.writeDescriptorSet(descriptorSet, setWrites); - auto swapchainExtent = core.getSwapchain().getExtent(); + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); vkcv::ImageHandle depthBuffer = core.createImage( vk::Format::eD32Sfloat, @@ -174,21 +170,21 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1); - vkcv::camera::CameraManager cameraManager(window); + vkcv::camera::CameraManager cameraManager(core.getWindow(windowHandle)); uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -3)); auto start = std::chrono::system_clock::now(); - while (window.isWindowOpen()) { + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); - if(window.getHeight() == 0 || window.getWidth() == 0) + if(core.getWindow(windowHandle).getHeight() == 0 || core.getWindow(windowHandle).getWidth() == 0) continue; uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) { continue; } @@ -218,10 +214,11 @@ int main(int argc, const char** argv) { firstMeshPipeline, pushConstants, { drawcall }, - renderTargets); + renderTargets, + windowHandle); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); - core.endFrame(); + core.endFrame(windowHandle); } return 0; diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index c7d4fcac5aa1748b9407b003eba3f35f418169f3..4891fecbf8e0fc5dee3f9930b477aa03115916d2 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -10,14 +10,19 @@ int main(int argc, const char** argv) { const char* applicationName = "First Scene"; - vkcv::Window window = vkcv::Window::create( - applicationName, - 800, - 600, - true - ); + uint32_t windowWidth = 800; + uint32_t windowHeight = 600; + vkcv::Core core = vkcv::Core::create( + applicationName, + VK_MAKE_VERSION(0, 0, 1), + {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, + { VK_KHR_SWAPCHAIN_EXTENSION_NAME } + ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false); + vkcv::Window& window = core.getWindow(windowHandle); vkcv::camera::CameraManager cameraManager(window); + uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); @@ -25,15 +30,7 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex0).setNearFar(0.1f, 30.0f); cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); - - vkcv::Core core = vkcv::Core::create( - window, - applicationName, - VK_MAKE_VERSION(0, 0, 1), - { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, - { VK_KHR_SWAPCHAIN_EXTENSION_NAME } - ); - + vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( argc > 1 ? argv[1] : "assets/Sponza/Sponza.gltf" )); @@ -41,7 +38,7 @@ int main(int argc, const char** argv) { const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat() + core.getSwapchain(windowHandle).getFormat() ); const vkcv::AttachmentDescription depth_attachment( @@ -96,7 +93,7 @@ int main(int argc, const char** argv) { return EXIT_FAILURE; } - auto swapchainExtent = core.getSwapchain().getExtent(); + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); vkcv::ImageHandle depthBuffer = core.createImage( vk::Format::eD32Sfloat, @@ -107,14 +104,14 @@ int main(int argc, const char** argv) { const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); auto start = std::chrono::system_clock::now(); - while (window.isWindowOpen()) { + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) continue; uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight,windowHandle)) { continue; } @@ -146,11 +143,12 @@ int main(int argc, const char** argv) { scenePipeline, sizeof(glm::mat4), recordMesh, - renderTargets); + renderTargets, + windowHandle); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); - core.endFrame(); + core.endFrame(windowHandle); } return 0; diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index b083af4a9f4578ea62888d3be9139928204d67ac..1725b5c84dea931fe785880e3cd423cbb5f04a46 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -7,22 +7,20 @@ int main(int argc, const char** argv) { const char* applicationName = "First Triangle"; - - vkcv::Window window = vkcv::Window::create( - applicationName, - 800, - 600, - false - ); + + const int windowWidth = 800; + const int windowHeight = 600; vkcv::Core core = vkcv::Core::create( - window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, { VK_KHR_SWAPCHAIN_EXTENSION_NAME } ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); + vkcv::Window& window = core.getWindow(windowHandle); + auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL); uint16_t indices[3] = { 0, 1, 2 }; triangleIndexBuffer.fill(&indices[0], sizeof(indices)); @@ -33,7 +31,7 @@ int main(int argc, const char** argv) { const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat()); + core.getSwapchain(windowHandle).getFormat()); vkcv::PassConfig trianglePassDefinition({ present_color_attachment }); vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition); @@ -59,7 +57,7 @@ int main(int argc, const char** argv) { triangleShaderProgram.addShader(shaderStage, path); }); - const auto swapchainExtent = core.getSwapchain().getExtent(); + const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); const vkcv::GraphicsPipelineConfig trianglePipelineDefinition { triangleShaderProgram, @@ -97,12 +95,12 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setPosition(glm::vec3(0.0f, 0.0f, 0.0f)); cameraManager.getCamera(camIndex1).setCenter(glm::vec3(0.0f, 0.0f, -1.0f)); - while (window.isWindowOpen()) + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) { continue; } @@ -125,12 +123,13 @@ int main(int argc, const char** argv) { trianglePipeline, pushConstants, { drawcall }, - { swapchainInput }); + { swapchainInput }, + windowHandle); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); - core.endFrame(); + core.endFrame(windowHandle); } return 0; } diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index ac7ddf52a4ef60254ac5c265be178ab927abe934..d4afc61c7421bd45c773bbdbc3da796b868869d2 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -23,18 +23,13 @@ App::App() : m_applicationName("Indirect Dispatch"), m_windowWidth(AppConfig::defaultWindowWidth), m_windowHeight(AppConfig::defaultWindowHeight), - m_window(vkcv::Window::create( - m_applicationName, - m_windowWidth, - m_windowHeight, - true)), m_core(vkcv::Core::create( - m_window, m_applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, { VK_KHR_SWAPCHAIN_EXTENSION_NAME })), - m_cameraManager(m_window){} + m_windowHandle(m_core.createWindow(m_applicationName, m_windowWidth, m_windowHeight, false)), + m_cameraManager(m_core.getWindow(m_windowHandle)){} bool App::initialize() { @@ -92,7 +87,7 @@ void App::run() { const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); const vkcv::DrawcallInfo skyDrawcall(m_cubeMesh.mesh, {}, 1); - vkcv::gui::GUI gui(m_core, m_window); + vkcv::gui::GUI gui(m_core, m_windowHandle); eMotionVectorVisualisationMode motionVectorVisualisationMode = eMotionVectorVisualisationMode::None; eMotionBlurMode motionBlurMode = eMotionBlurMode::Default; @@ -137,7 +132,7 @@ void App::run() { bool spaceWasPressed = false; - m_window.e_key.add([&](int key, int scancode, int action, int mods) { + m_core.getWindow(m_windowHandle).e_key.add([&](int key, int scancode, int action, int mods) { if (key == GLFW_KEY_SPACE) { if (action == GLFW_PRESS) { if (!spaceWasPressed) { @@ -153,7 +148,7 @@ void App::run() { auto frameEndTime = std::chrono::system_clock::now(); - while (m_window.isWindowOpen()) { + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); @@ -167,11 +162,11 @@ void App::run() { } } - if (m_window.getHeight() == 0 || m_window.getWidth() == 0) + if (m_core.getWindow(m_windowHandle).getHeight() == 0 || m_core.getWindow(m_windowHandle).getWidth() == 0) continue; uint32_t swapchainWidth, swapchainHeight; - if (!m_core.beginFrame(swapchainWidth, swapchainHeight)) + if (!m_core.beginFrame(swapchainWidth, swapchainHeight,m_windowHandle)) continue; const bool hasResolutionChanged = (swapchainWidth != m_windowWidth) || (swapchainHeight != m_windowHeight); @@ -232,7 +227,8 @@ void App::run() { m_prePass.pipeline, prepassPushConstants, prepassSceneDrawcalls, - prepassRenderTargets); + prepassRenderTargets, + m_windowHandle); // sky prepass glm::mat4 skyPrepassMatrices[2] = { @@ -247,7 +243,8 @@ void App::run() { m_skyPrePass.pipeline, skyPrepassPushConstants, { skyDrawcall }, - prepassRenderTargets); + prepassRenderTargets, + m_windowHandle); // main pass const std::vector<vkcv::ImageHandle> renderTargets = { @@ -273,7 +270,8 @@ void App::run() { m_meshPass.pipeline, meshPushConstants, forwardSceneDrawcalls, - renderTargets); + renderTargets, + m_windowHandle); // sky vkcv::PushConstants skyPushConstants(sizeof(glm::mat4)); @@ -285,7 +283,8 @@ void App::run() { m_skyPass.pipeline, skyPushConstants, { skyDrawcall }, - renderTargets); + renderTargets, + m_windowHandle); // motion blur vkcv::ImageHandle motionBlurOutput; @@ -378,6 +377,6 @@ void App::run() { ImGui::End(); gui.endGUI(); - m_core.endFrame(); + m_core.endFrame(m_windowHandle); } } \ No newline at end of file diff --git a/projects/indirect_dispatch/src/App.hpp b/projects/indirect_dispatch/src/App.hpp index 4ce66e9b28d44024cee0d07f6f765d396b873bd7..a35c2342c4c90e39b089a7c33a73c3aa7ce8a83f 100644 --- a/projects/indirect_dispatch/src/App.hpp +++ b/projects/indirect_dispatch/src/App.hpp @@ -15,8 +15,8 @@ private: uint32_t m_windowWidth; uint32_t m_windowHeight; - vkcv::Window m_window; vkcv::Core m_core; + vkcv::WindowHandle m_windowHandle; vkcv::camera::CameraManager m_cameraManager; MotionBlur m_motionBlur; diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 6c3bc2f40090c87ae967499e4ff53bf0af81b9ff..0ee16b99822e0c8fbeaf58af57f02255493b0fb5 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -78,12 +78,8 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) { int main(int argc, const char** argv) { const char* applicationName = "Mesh shader"; - vkcv::Window window = vkcv::Window::create( - applicationName, - 1280, - 720, - false - ); + const int windowWidth = 1280; + const int windowHeight = 720; vkcv::Features features; features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); @@ -94,14 +90,15 @@ int main(int argc, const char** argv) { }); vkcv::Core core = vkcv::Core::create( - window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, features ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false); + vkcv::Window &window = core.getWindow(windowHandle); - vkcv::gui::GUI gui (core, window); + vkcv::gui::GUI gui (core, windowHandle); vkcv::asset::Scene mesh; const char* path = argc > 1 ? argv[1] : "assets/Bunny/Bunny.glb"; @@ -166,7 +163,7 @@ int main(int argc, const char** argv) { const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, - core.getSwapchain().getFormat()); + core.getSwapchain(windowHandle).getFormat()); const vkcv::AttachmentDescription depth_attachment( vkcv::AttachmentOperation::STORE, @@ -206,7 +203,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetLayoutHandle vertexShaderDescriptorSetLayout = core.createDescriptorSetLayout(bunnyShaderProgram.getReflectedDescriptors().at(0)); vkcv::DescriptorSetHandle vertexShaderDescriptorSet = core.createDescriptorSet(vertexShaderDescriptorSetLayout); - auto swapchainExtent = core.getSwapchain().getExtent(); + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); const vkcv::GraphicsPipelineConfig bunnyPipelineDefinition { bunnyShaderProgram, @@ -315,12 +312,12 @@ int main(int argc, const char** argv) { bool useMeshShader = true; bool updateFrustumPlanes = true; - while (window.isWindowOpen()) + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight,windowHandle)) { continue; } @@ -366,7 +363,8 @@ int main(int argc, const char** argv) { meshShaderPipeline, pushConstantData, { vkcv::MeshShaderDrawcall({descriptorUsage}, taskCount)}, - { renderTargets }); + { renderTargets }, + windowHandle); } else { @@ -378,7 +376,8 @@ int main(int argc, const char** argv) { bunnyPipeline, pushConstantData, { vkcv::DrawcallInfo(renderMesh, { descriptorUsage }) }, - { renderTargets }); + { renderTargets }, + windowHandle); } core.prepareSwapchainImageForPresent(cmdStream); @@ -394,7 +393,7 @@ int main(int argc, const char** argv) { gui.endGUI(); - core.endFrame(); + core.endFrame(windowHandle); } return 0; } diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index ff249e4e8efe2ca60c7773d32a66a05d12f06c3a..ddbe6195e66e78504d4bccb32b3b09ff680ab414 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -6,29 +6,25 @@ #include "ParticleSystem.hpp" #include <random> #include <glm/gtc/matrix_access.hpp> -#include <time.h> +#include <ctime> #include <vkcv/shader/GLSLCompiler.hpp> #include "BloomAndFlares.hpp" int main(int argc, const char **argv) { const char *applicationName = "Particlesystem"; - vkcv::Window window = vkcv::Window::create( - applicationName, - 800, - 600, - true - ); - - vkcv::camera::CameraManager cameraManager(window); + uint32_t windowWidth = 800; + uint32_t windowHeight = 600; vkcv::Core core = vkcv::Core::create( - window, applicationName, VK_MAKE_VERSION(0, 0, 1), {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, { VK_KHR_SWAPCHAIN_EXTENSION_NAME } ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); + vkcv::Window& window = core.getWindow(windowHandle); + vkcv::camera::CameraManager cameraManager(window); auto particleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL); @@ -186,7 +182,7 @@ int main(int argc, const char **argv) { auto pos = glm::vec2(0.f); auto spawnPosition = glm::vec3(0.f); - window.e_mouseMove.add([&](double offsetX, double offsetY) { + window.e_mouseMove.add([&](double offsetX, double offsetY) { pos = glm::vec2(static_cast<float>(offsetX), static_cast<float>(offsetY)); pos.x = (-2 * pos.x + static_cast<float>(window.getWidth())) / static_cast<float>(window.getWidth()); pos.y = (-2 * pos.y + static_cast<float>(window.getHeight())) / static_cast<float>(window.getHeight()); @@ -213,7 +209,7 @@ int main(int argc, const char **argv) { cameraManager.getCamera(camIndex1).setPosition(glm::vec3(0.0f, 0.0f, -2.0f)); cameraManager.getCamera(camIndex1).setCenter(glm::vec3(0.0f, 0.0f, 0.0f)); - auto swapchainExtent = core.getSwapchain().getExtent(); + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); vkcv::ImageHandle colorBuffer = core.createImage( colorFormat, @@ -223,7 +219,7 @@ int main(int argc, const char **argv) { ).getHandle(); BloomAndFlares bloomAndFlares(&core, colorFormat, swapchainExtent.width, swapchainExtent.height); window.e_resize.add([&](int width, int height) { - swapchainExtent = core.getSwapchain().getExtent(); + swapchainExtent = core.getSwapchain(windowHandle).getExtent(); colorBuffer = core.createImage( colorFormat, swapchainExtent.width, @@ -246,11 +242,11 @@ int main(int argc, const char **argv) { std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; - while (window.isWindowOpen()) { + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) { continue; } @@ -297,7 +293,8 @@ int main(int argc, const char **argv) { particlePipeline, pushConstantsDraw, {drawcalls}, - { colorBuffer }); + { colorBuffer }, + windowHandle); bloomAndFlares.execWholePipeline(cmdStream, colorBuffer); @@ -325,7 +322,7 @@ int main(int argc, const char **argv) { core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); - core.endFrame(); + core.endFrame(windowHandle); } return 0; diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index 55fb781c52049fd18722f263033d78f7e0e9bebd..d8041c1e9935d148ded8fb1ca8f0e4d8b79fce71 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -235,7 +235,8 @@ void ShadowMapping::recordShadowMapRendering( const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, const glm::vec3& voxelVolumeOffset, - float voxelVolumeExtent) { + float voxelVolumeExtent, + const vkcv::WindowHandle& windowHandle) { LightInfo lightInfo; lightInfo.sunColor = lightColor; @@ -271,7 +272,8 @@ void ShadowMapping::recordShadowMapRendering( m_shadowMapPipe, shadowPushConstants, drawcalls, - { m_shadowMapDepth.getHandle() }); + { m_shadowMapDepth.getHandle() }, + windowHandle); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapDepth.getHandle()); // depth to moments diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 3a577a75c6a374fb41bf02056efe64eef331fcdc..7de83b800ce073f5541a889b87a7f0cd763ffa69 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -27,7 +27,8 @@ public: const std::vector<glm::mat4>& modelMatrices, const vkcv::camera::Camera& camera, const glm::vec3& voxelVolumeOffset, - float voxelVolumeExtent); + float voxelVolumeExtent, + const vkcv::WindowHandle& windowHandle); vkcv::ImageHandle getShadowMap(); vkcv::SamplerHandle getShadowSampler(); diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index 668dc8596951356e97535f09d9a74d8d15ae2003..3cbff0df84757fb370a0372ddd45a9df401d4b60 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -218,7 +218,8 @@ void Voxelization::voxelizeMeshes( vkcv::CommandStreamHandle cmdStream, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, - const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets) { + const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets, + const vkcv::WindowHandle& windowHandle) { m_voxelInfoBuffer.fill({ m_voxelInfo }); @@ -276,7 +277,8 @@ void Voxelization::voxelizeMeshes( m_voxelizationPipe, voxelizationPushConstants, drawcalls, - { m_dummyRenderTarget.getHandle() }); + { m_dummyRenderTarget.getHandle() }, + windowHandle); // buffer to image const uint32_t bufferToImageGroupSize[3] = { 4, 4, 4 }; @@ -320,7 +322,8 @@ void Voxelization::renderVoxelVisualisation( vkcv::CommandStreamHandle cmdStream, const glm::mat4& viewProjectin, const std::vector<vkcv::ImageHandle>& renderTargets, - uint32_t mipLevel) { + uint32_t mipLevel, + const vkcv::WindowHandle& windowHandle) { vkcv::PushConstants voxelVisualisationPushConstants (sizeof(glm::mat4)); voxelVisualisationPushConstants.appendDrawcall(viewProjectin); @@ -348,7 +351,8 @@ void Voxelization::renderVoxelVisualisation( m_visualisationPipe, voxelVisualisationPushConstants, { drawcall }, - renderTargets); + renderTargets, + windowHandle); } void Voxelization::updateVoxelOffset(const vkcv::camera::Camera& camera) { diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index c099581a527045a7cb51e4de144f3c181fee53b1..d5f41123b527f2919dec678d0337ee25ea6fa2c6 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -23,13 +23,15 @@ public: vkcv::CommandStreamHandle cmdStream, const std::vector<vkcv::Mesh>& meshes, const std::vector<glm::mat4>& modelMatrices, - const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets); + const std::vector<vkcv::DescriptorSetHandle>& perMeshDescriptorSets, + const vkcv::WindowHandle& windowHandle); void renderVoxelVisualisation( vkcv::CommandStreamHandle cmdStream, const glm::mat4& viewProjectin, const std::vector<vkcv::ImageHandle>& renderTargets, - uint32_t mipLevel); + uint32_t mipLevel, + const vkcv::WindowHandle& windowHandle); void updateVoxelOffset(const vkcv::camera::Camera& camera); void setVoxelExtent(float extent); diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 795acb1795e7d9242fe9e9c4969a8833cb8c1175..a7798813a52429d31f207ae24af6a3effb90c17c 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -17,13 +17,23 @@ int main(int argc, const char** argv) { const vkcv::Multisampling msaa = vkcv::Multisampling::MSAA4X; const bool usingMsaa = msaa != vkcv::Multisampling::None; - - vkcv::Window window = vkcv::Window::create( - applicationName, - 1280, - 720, - true + + vkcv::Features features; + features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + features.requireExtension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); + features.requireExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME); + + const uint32_t windowWidth = 1280; + const uint32_t windowHeight = 720; + + vkcv::Core core = vkcv::Core::create( + applicationName, + VK_MAKE_VERSION(0, 0, 1), + { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, + features ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); + vkcv::Window& window = core.getWindow(windowHandle); bool isFullscreen = false; uint32_t windowedWidthBackup = window.getWidth(); @@ -76,19 +86,6 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex).setFov(glm::radians(37.8)); // fov of a 35mm lens cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f); - - vkcv::Features features; - features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); - features.requireExtension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); - features.requireExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME); - - vkcv::Core core = vkcv::Core::create( - window, - applicationName, - VK_MAKE_VERSION(0, 0, 1), - { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, - features - ); vkcv::asset::Scene mesh; @@ -301,7 +298,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetLayoutHandle prepassDescriptorSetLayout = core.createDescriptorSetLayout({}); vkcv::DescriptorSetHandle prepassDescriptorSet = core.createDescriptorSet(prepassDescriptorSetLayout); - auto swapchainExtent = core.getSwapchain().getExtent(); + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); vkcv::GraphicsPipelineConfig prepassPipelineConfig{ depthPrepassShader, @@ -602,7 +599,7 @@ int main(int argc, const char** argv) { bool bilinearUpscaling = false; - vkcv::gui::GUI gui(core, window); + vkcv::gui::GUI gui(core, windowHandle); glm::vec2 lightAnglesDegree = glm::vec2(90.f, 0.f); glm::vec3 lightColor = glm::vec3(1); @@ -622,11 +619,11 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); const auto appStartTime = start; - while (window.isWindowOpen()) { + while (vkcv::Window::hasOpenWindow()) { vkcv::Window::pollEvents(); uint32_t swapchainWidth, swapchainHeight; - if (!core.beginFrame(swapchainWidth, swapchainHeight)) { + if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) { continue; } @@ -743,7 +740,8 @@ int main(int argc, const char** argv) { modelMatrices, cameraManager.getActiveCamera(), voxelization.getVoxelOffset(), - voxelization.getVoxelExtent()); + voxelization.getVoxelExtent(), + windowHandle); // voxelization voxelization.setVoxelExtent(voxelizationExtent); @@ -751,7 +749,8 @@ int main(int argc, const char** argv) { cmdStream, meshes, modelMatrices, - perMeshDescriptorSets); + perMeshDescriptorSets, + windowHandle); // depth prepass const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP(); @@ -772,7 +771,8 @@ int main(int argc, const char** argv) { prepassPipeline, prepassPushConstants, prepassDrawcalls, - prepassRenderTargets); + prepassRenderTargets, + windowHandle); core.recordImageMemoryBarrier(cmdStream, depthBuffer); @@ -797,10 +797,11 @@ int main(int argc, const char** argv) { forwardPipeline, pushConstants, drawcalls, - renderTargets); + renderTargets, + windowHandle); if (renderVoxelVis) { - voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip); + voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip, windowHandle); } vkcv::PushConstants skySettingsPushConstants (sizeof(skySettings)); @@ -813,7 +814,8 @@ int main(int argc, const char** argv) { skyPipe, skySettingsPushConstants, { vkcv::DrawcallInfo(vkcv::Mesh({}, nullptr, 3), {}) }, - renderTargets); + renderTargets, + windowHandle); const uint32_t fullscreenLocalGroupSize = 8; @@ -988,7 +990,7 @@ int main(int argc, const char** argv) { gui.endGUI(); - core.endFrame(); + core.endFrame(windowHandle); } return 0; diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index 512d05e9b1337dcd7d6c5d8162d6155f7a4dd97e..01f6039eba5646bc99780415b7c41f0a02d65fe6 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -1,7 +1,6 @@ -#include <GLFW/glfw3.h> - #include "vkcv/Context.hpp" +#include "vkcv/Window.hpp" namespace vkcv { @@ -177,13 +176,11 @@ namespace vkcv return true; } - std::vector<const char*> getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - + std::vector<std::string> getRequiredExtensions() { + std::vector<std::string> extensions = Window::getExtensions(); + #ifndef NDEBUG - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + extensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); #endif return extensions; @@ -227,7 +224,13 @@ namespace vkcv } // for GLFW: get all required extensions - std::vector<const char*> requiredExtensions = getRequiredExtensions(); + auto requiredStrings = getRequiredExtensions(); + std::vector<const char*> requiredExtensions; + + for (const auto& extension : requiredStrings) { + requiredExtensions.push_back(extension.c_str()); + } + requiredExtensions.insert(requiredExtensions.end(), instanceExtensions.begin(), instanceExtensions.end()); if (!checkSupport(supportedExtensions, requiredExtensions)) { diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index e55fb9cb53a001f71e756e0f2d04195e9e237f6d..21435c818451d1bea796b862cbb57ebeea8f0abd 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -14,6 +14,7 @@ #include "SamplerManager.hpp" #include "ImageManager.hpp" #include "DescriptorManager.hpp" +#include "WindowManager.hpp" #include "ImageLayoutTransitions.hpp" #include "vkcv/CommandStreamManager.hpp" #include <cmath> @@ -21,38 +22,7 @@ namespace vkcv { - - static std::vector<vk::ImageView> createSwapchainImageViews( Context &context, const std::vector<vk::Image>& images, - vk::Format format){ - std::vector<vk::ImageView> imageViews; - imageViews.reserve( images.size() ); - //here can be swizzled with vk::ComponentSwizzle if needed - vk::ComponentMapping componentMapping( - vk::ComponentSwizzle::eR, - vk::ComponentSwizzle::eG, - vk::ComponentSwizzle::eB, - vk::ComponentSwizzle::eA ); - - vk::ImageSubresourceRange subResourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ); - - for ( auto image : images ) - { - vk::ImageViewCreateInfo imageViewCreateInfo( - vk::ImageViewCreateFlags(), - image, - vk::ImageViewType::e2D, - format, - componentMapping, - subResourceRange); - - imageViews.push_back(context.getDevice().createImageView(imageViewCreateInfo)); - } - - return imageViews; - } - - Core Core::create(Window &window, - const char *applicationName, + Core Core::create(const char *applicationName, uint32_t applicationVersion, const std::vector<vk::QueueFlagBits>& queueFlags, const Features& features, @@ -65,34 +35,22 @@ namespace vkcv instanceExtensions ); - Swapchain swapChain = Swapchain::create(window, context); - - const auto swapchainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain()); - const auto swapchainImageViews = createSwapchainImageViews( context, swapchainImages, swapChain.getFormat()); - const auto& queueManager = context.getQueueManager(); const std::unordered_set<int> queueFamilySet = generateQueueFamilyIndexSet(queueManager); const auto commandResources = createCommandResources(context.getDevice(), queueFamilySet); const auto defaultSyncResources = createSyncResources(context.getDevice()); - return Core(std::move(context) , window, swapChain, swapchainImageViews, commandResources, defaultSyncResources); + return Core(std::move(context) , commandResources, defaultSyncResources); } const Context &Core::getContext() const { return m_Context; } - - const Swapchain& Core::getSwapchain() const { - return m_swapchain; - } - Core::Core(Context &&context, Window &window, const Swapchain& swapChain, std::vector<vk::ImageView> swapchainImageViews, - const CommandResources& commandResources, const SyncResources& syncResources) noexcept : + Core::Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept : m_Context(std::move(context)), - m_swapchain(swapChain), - m_window(window), m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, m_PipelineManager{std::make_unique<GraphicsPipelineManager>(m_Context.m_Device)}, m_ComputePipelineManager{std::make_unique<ComputePipelineManager>(m_Context.m_Device)}, @@ -101,39 +59,23 @@ namespace vkcv m_SamplerManager(std::unique_ptr<SamplerManager>(new SamplerManager(m_Context.m_Device))), m_ImageManager{std::unique_ptr<ImageManager>(new ImageManager(*m_BufferManager))}, m_CommandStreamManager{std::unique_ptr<CommandStreamManager>(new CommandStreamManager)}, + m_WindowManager(std::make_unique<WindowManager>()), + m_SwapchainManager(std::make_unique<SwapchainManager>()), m_CommandResources(commandResources), m_SyncResources(syncResources) { m_BufferManager->m_core = this; m_BufferManager->init(); m_CommandStreamManager->init(this); - + m_SwapchainManager->m_context = &m_Context; m_ImageManager->m_core = this; - - e_resizeHandle = m_window.e_resize.add( [&](int width, int height) { - m_swapchain.signalSwapchainRecreation(); - }); - - const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); - m_ImageManager->setSwapchainImages( - swapchainImages, - swapchainImageViews, - swapChain.getExtent().width, - swapChain.getExtent().height, - swapChain.getFormat() - ); } Core::~Core() noexcept { - m_window.e_resize.remove(e_resizeHandle); - m_Context.getDevice().waitIdle(); destroyCommandResources(m_Context.getDevice(), m_CommandResources); destroySyncResources(m_Context.getDevice(), m_SyncResources); - - m_Context.m_Device.destroySwapchainKHR(m_swapchain.getSwapchain()); - m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface()); } GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) @@ -151,13 +93,13 @@ namespace vkcv return m_PassManager->createPass(config); } - Result Core::acquireSwapchainImage() { + Result Core::acquireSwapchainImage(const SwapchainHandle &swapchainHandle) { uint32_t imageIndex; vk::Result result; try { result = m_Context.getDevice().acquireNextImageKHR( - m_swapchain.getSwapchain(), + m_SwapchainManager->getSwapchain(swapchainHandle).getSwapchain(), std::numeric_limits<uint64_t>::max(), m_SyncResources.swapchainImageAcquired, nullptr, @@ -176,37 +118,29 @@ namespace vkcv } else if (result == vk::Result::eSuboptimalKHR) { vkcv_log(LogLevel::WARNING, "Acquired image is suboptimal"); - m_swapchain.signalSwapchainRecreation(); + m_SwapchainManager->getSwapchain(swapchainHandle).signalSwapchainRecreation(); } m_currentSwapchainImageIndex = imageIndex; return Result::SUCCESS; } - bool Core::beginFrame(uint32_t& width, uint32_t& height) { - if (m_swapchain.shouldUpdateSwapchain()) { + bool Core::beginFrame(uint32_t& width, uint32_t& height, const WindowHandle &windowHandle) { + const SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchainHandle(); + + if (m_SwapchainManager->getSwapchain(swapchainHandle).shouldUpdateSwapchain()) { m_Context.getDevice().waitIdle(); - m_swapchain.updateSwapchain(m_Context, m_window); + m_SwapchainManager->getSwapchain(swapchainHandle).updateSwapchain(m_Context, m_WindowManager->getWindow(windowHandle)); - if (!m_swapchain.getSwapchain()) { + if (!m_SwapchainManager->getSwapchain(swapchainHandle).getSwapchain()) { return false; } - - const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); - const auto swapchainViews = createSwapchainImageViews(m_Context, swapchainImages, m_swapchain.getFormat()); - - const auto& extent = m_swapchain.getExtent(); - m_ImageManager->setSwapchainImages( - swapchainImages, - swapchainViews, - extent.width, extent.height, - m_swapchain.getFormat() - ); + setSwapchainImages(swapchainHandle); } - const auto& extent = m_swapchain.getExtent(); + const auto& extent = m_SwapchainManager->getSwapchain(swapchainHandle).getExtent(); width = extent.width; height = extent.height; @@ -215,7 +149,7 @@ namespace vkcv return false; } - if (acquireSwapchainImage() != Result::SUCCESS) { + if (acquireSwapchainImage( swapchainHandle ) != Result::SUCCESS) { vkcv_log(LogLevel::ERROR, "Acquire failed"); m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max(); @@ -334,13 +268,16 @@ namespace vkcv const GraphicsPipelineHandle &pipelineHandle, const PushConstants &pushConstantData, const std::vector<DrawcallInfo> &drawcalls, - const std::vector<ImageHandle> &renderTargets) { + const std::vector<ImageHandle> &renderTargets, + const WindowHandle &windowHandle) { + + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchainHandle(); if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - const std::array<uint32_t, 2> widthHeight = getWidthHeightFromRenderTargets(renderTargets, m_swapchain, *m_ImageManager); + const std::array<uint32_t, 2> widthHeight = getWidthHeightFromRenderTargets(renderTargets, m_SwapchainManager->getSwapchain(swapchainHandle), *m_ImageManager); const auto width = widthHeight[0]; const auto height = widthHeight[1]; @@ -354,7 +291,7 @@ namespace vkcv vk::CommandBuffer cmdBuffer = m_CommandStreamManager->getStreamCommandBuffer(cmdStreamHandle); transitionRendertargetsToAttachmentLayout(renderTargets, *m_ImageManager, cmdBuffer); - const vk::Framebuffer framebuffer = createFramebuffer(renderTargets, *m_ImageManager, m_swapchain, renderpass, m_Context.m_Device); + const vk::Framebuffer framebuffer = createFramebuffer(renderTargets, *m_ImageManager, m_SwapchainManager->getSwapchain(swapchainHandle), renderpass, m_Context.m_Device); if (!framebuffer) { vkcv_log(LogLevel::ERROR, "Failed to create temporary framebuffer"); @@ -399,13 +336,16 @@ namespace vkcv const GraphicsPipelineHandle &pipelineHandle, const PushConstants& pushConstantData, const std::vector<MeshShaderDrawcall>& drawcalls, - const std::vector<ImageHandle>& renderTargets) { + const std::vector<ImageHandle>& renderTargets, + const WindowHandle& windowHandle) { + + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchainHandle(); if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - const std::array<uint32_t, 2> widthHeight = getWidthHeightFromRenderTargets(renderTargets, m_swapchain, *m_ImageManager); + const std::array<uint32_t, 2> widthHeight = getWidthHeightFromRenderTargets(renderTargets, m_SwapchainManager->getSwapchain(swapchainHandle), *m_ImageManager); const auto width = widthHeight[0]; const auto height = widthHeight[1]; @@ -419,7 +359,7 @@ namespace vkcv vk::CommandBuffer cmdBuffer = m_CommandStreamManager->getStreamCommandBuffer(cmdStreamHandle); transitionRendertargetsToAttachmentLayout(renderTargets, *m_ImageManager, cmdBuffer); - const vk::Framebuffer framebuffer = createFramebuffer(renderTargets, *m_ImageManager, m_swapchain, renderpass, m_Context.m_Device); + const vk::Framebuffer framebuffer = createFramebuffer(renderTargets, *m_ImageManager, m_SwapchainManager->getSwapchain(swapchainHandle), renderpass, m_Context.m_Device); if (!framebuffer) { vkcv_log(LogLevel::ERROR, "Failed to create temporary framebuffer"); @@ -579,20 +519,20 @@ namespace vkcv recordCommandsToStream(cmdStream, submitFunction, nullptr); } - void Core::endFrame() { + void Core::endFrame(const WindowHandle& windowHandle) { + + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchainHandle(); + if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } - - const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); - - const auto& queueManager = m_Context.getQueueManager(); + std::array<vk::Semaphore, 2> waitSemaphores{ m_SyncResources.renderFinished, m_SyncResources.swapchainImageAcquired }; - const vk::SwapchainKHR& swapchain = m_swapchain.getSwapchain(); + const vk::SwapchainKHR& swapchain = m_SwapchainManager->getSwapchain(swapchainHandle).getSwapchain(); const vk::PresentInfoKHR presentInfo( waitSemaphores, swapchain, @@ -602,7 +542,7 @@ namespace vkcv vk::Result result; try { - result = queueManager.getPresentQueue().handle.presentKHR(presentInfo); + result = m_Context.getDevice().getQueue(m_SwapchainManager->getSwapchain(swapchainHandle).getPresentQueueIndex(),0).presentKHR(presentInfo); } catch (const vk::OutOfDateKHRError& e) { result = vk::Result::eErrorOutOfDateKHR; } catch (const vk::DeviceLostError& e) { @@ -615,7 +555,7 @@ namespace vkcv } else if (result == vk::Result::eSuboptimalKHR) { vkcv_log(LogLevel::WARNING, "Swapchain presentation is suboptimal"); - m_swapchain.signalSwapchainRecreation(); + m_SwapchainManager->signalRecreation(swapchainHandle); } } @@ -707,6 +647,22 @@ namespace vkcv multisampling); } + WindowHandle Core::createWindow( + const char *applicationName, + uint32_t windowWidth, + uint32_t windowHeight, + bool resizeable) { + + WindowHandle windowHandle = m_WindowManager->createWindow(*m_SwapchainManager ,applicationName, windowWidth, windowHeight, resizeable); + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchainHandle(); + setSwapchainImages( swapchainHandle ); + return windowHandle; + } + + Window& Core::getWindow(const WindowHandle& handle) { + return m_WindowManager->getWindow(handle); + } + uint32_t Core::getImageWidth(const ImageHandle& image) { return m_ImageManager->getImageWidth(image); @@ -721,6 +677,19 @@ namespace vkcv return m_ImageManager->getImageFormat(image); } + Swapchain& Core::getSwapchainOfCurrentWindow() { + return m_SwapchainManager->getSwapchain(Window::getFocusedWindow().getSwapchainHandle()); + } + + Swapchain& Core::getSwapchain(const SwapchainHandle& handle) { + return m_SwapchainManager->getSwapchain(handle); + } + + Swapchain& Core::getSwapchain(const WindowHandle& handle) { + SwapchainHandle swapchainHandle = m_WindowManager->getWindow(handle).getSwapchainHandle(); + return getSwapchain(swapchainHandle); + } + DescriptorSetLayoutHandle Core::createDescriptorSetLayout(const DescriptorBindings &bindingsMap) { return m_DescriptorManager->createDescriptorSetLayout(bindingsMap); @@ -870,6 +839,20 @@ namespace vkcv ); }, nullptr); } + + void Core::setSwapchainImages( SwapchainHandle handle ) { + Swapchain swapchain = m_SwapchainManager->getSwapchain(handle); + const auto swapchainImages = m_SwapchainManager->getSwapchainImages(handle); + const auto swapchainImageViews = m_SwapchainManager->createSwapchainImageViews(handle); + + m_ImageManager->setSwapchainImages( + swapchainImages, + swapchainImageViews, + swapchain.getExtent().width, + swapchain.getExtent().height, + swapchain.getFormat() + ); + } static void setDebugObjectLabel(const vk::Device& device, const vk::ObjectType& type, uint64_t handle, const std::string& label) { @@ -1023,5 +1006,4 @@ namespace vkcv label ); } - } diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index 4b3af103e6b78a0a05f12ee9c743d9ca63450d44..ff134041bdc6279d312df668cab448a50750f1c3 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -5,6 +5,7 @@ #include "vkcv/QueueManager.hpp" #include "vkcv/Logger.hpp" +#include "vkcv/Swapchain.hpp" namespace vkcv { @@ -85,7 +86,7 @@ namespace vkcv { found = false; for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][0] > 0) { - queuePairsGraphics.push_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0])); + queuePairsGraphics.emplace_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0])); queueFamilyStatus[i][0]--; queueFamilyStatus[i][1]--; queueFamilyStatus[i][2]--; @@ -95,7 +96,7 @@ namespace vkcv { if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][0] > 0) { - queuePairsGraphics.push_back(std::pair(i, 0)); + queuePairsGraphics.emplace_back(std::pair(i, 0)); found = true; } } @@ -107,7 +108,7 @@ namespace vkcv { found = false; for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][1] > 0) { - queuePairsCompute.push_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1])); + queuePairsCompute.emplace_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1])); queueFamilyStatus[i][0]--; queueFamilyStatus[i][1]--; queueFamilyStatus[i][2]--; @@ -117,7 +118,7 @@ namespace vkcv { if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][1] > 0) { - queuePairsCompute.push_back(std::pair(i, 0)); + queuePairsCompute.emplace_back(std::pair(i, 0)); found = true; } } @@ -129,7 +130,7 @@ namespace vkcv { found = false; for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (queueFamilyStatus[i][2] > 0) { - queuePairsTransfer.push_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2])); + queuePairsTransfer.emplace_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2])); queueFamilyStatus[i][0]--; queueFamilyStatus[i][1]--; queueFamilyStatus[i][2]--; @@ -139,7 +140,7 @@ namespace vkcv { if (!found) { for (size_t i = 0; i < queueFamilyStatus.size() && !found; i++) { if (initialQueueFamilyStatus[i][2] > 0) { - queuePairsTransfer.push_back(std::pair(i, 0)); + queuePairsTransfer.emplace_back(std::pair(i, 0)); found = true; } } @@ -194,13 +195,33 @@ namespace vkcv { std::vector<std::pair<int, int>> &queuePairsTransfer) { std::vector<Queue> graphicsQueues = getQueues(device, queuePairsGraphics); - std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute ); + std::vector<Queue> computeQueues = getQueues(device, queuePairsCompute); std::vector<Queue> transferQueues = getQueues(device, queuePairsTransfer); return QueueManager( std::move(graphicsQueues), std::move(computeQueues), std::move(transferQueues), 0); } - QueueManager::QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, std::vector<Queue>&& transferQueues, size_t presentIndex) + uint32_t QueueManager::checkSurfaceSupport( + const vk::PhysicalDevice &physicalDevice, + vk::SurfaceKHR &surface + ) { + std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); + + for(uint32_t i = 0; i < qFamilyProperties.size(); i++) { + vk::Bool32 presentSupport; + + if ((vk::Result::eSuccess == physicalDevice.getSurfaceSupportKHR(i, surface, &presentSupport)) && + (presentSupport == VK_TRUE)) { + return i; + } + } + + vkcv_log(LogLevel::WARNING, "No supported present queue"); + return 0; + } + + QueueManager::QueueManager(std::vector<Queue>&& graphicsQueues, std::vector<Queue>&& computeQueues, + std::vector<Queue>&& transferQueues, size_t presentIndex) : m_graphicsQueues(graphicsQueues), m_computeQueues(computeQueues), m_transferQueues(transferQueues), m_presentIndex(presentIndex) {} diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp index 3174807c7fd6073be58d2dbaf3c1ceb2639d1add..483732927bc2cc507f0868226b65bf4d49e27048 100644 --- a/src/vkcv/Swapchain.cpp +++ b/src/vkcv/Swapchain.cpp @@ -163,10 +163,11 @@ namespace vkcv const vk::Device& device = context.getDevice(); Surface surface; - surface.handle = createSurface(window.getWindow(), instance, physicalDevice); - surface.formats = physicalDevice.getSurfaceFormatsKHR(surface.handle); - surface.capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle); - surface.presentModes = physicalDevice.getSurfacePresentModesKHR(surface.handle); + surface.handle = createSurface(window.getWindow(), instance, physicalDevice); + surface.formats = physicalDevice.getSurfaceFormatsKHR(surface.handle); + surface.capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle); + surface.presentModes = physicalDevice.getSurfacePresentModesKHR(surface.handle); + surface.presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surface.handle); vk::Extent2D chosenExtent = chooseExtent(physicalDevice, surface.handle, window); vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, surface.handle); @@ -264,4 +265,8 @@ namespace vkcv uint32_t Swapchain::getImageCount() const { return m_ImageCount; } + + const uint32_t &Swapchain::getPresentQueueIndex() const { + return m_Surface.presentQueueIndex; + } } diff --git a/src/vkcv/SwapchainManager.cpp b/src/vkcv/SwapchainManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0caea9fd0fe47b4f51a53adac9134fb7f81a205a --- /dev/null +++ b/src/vkcv/SwapchainManager.cpp @@ -0,0 +1,85 @@ +#include "SwapchainManager.hpp" + +namespace vkcv { + + SwapchainManager::SwapchainManager() noexcept { + } + + SwapchainManager::~SwapchainManager() noexcept { + for (uint64_t id = 0; id < m_swapchains.size(); id++) { + destroySwapchainById(id); + } + m_swapchains.clear(); + } + + SwapchainHandle SwapchainManager::createSwapchain(Window &window) { + const uint64_t id = m_swapchains.size(); + + Swapchain swapchain = Swapchain::create(window, *m_context); + + m_swapchains.push_back(swapchain); + SwapchainHandle swapchainHandle = SwapchainHandle(id, [&](uint64_t id) { destroySwapchainById(id); }); + window.m_swapchainHandle = swapchainHandle; + return swapchainHandle; + } + + Swapchain& SwapchainManager::getSwapchain(const SwapchainHandle& handle) { + return m_swapchains[handle.getId()]; + } + + void SwapchainManager::destroySwapchainById(uint64_t id) { + + if (id >= m_swapchains.size()) { + vkcv_log(LogLevel::ERROR, "Invalid id"); + return; + } + Swapchain &swapchain = m_swapchains[id]; + + if (swapchain.m_Swapchain) { + m_context->getDevice().destroySwapchainKHR(swapchain.m_Swapchain); + swapchain.m_Swapchain = nullptr; + } + + if (swapchain.m_Surface.handle) { + m_context->getInstance().destroySurfaceKHR(swapchain.m_Surface.handle); + swapchain.m_Surface.handle = nullptr; + } + } + + void SwapchainManager::signalRecreation(const SwapchainHandle& handle) { + m_swapchains[handle.getId()].signalSwapchainRecreation(); + } + + std::vector<vk::Image> SwapchainManager::getSwapchainImages(const SwapchainHandle& handle) { + return m_context->getDevice().getSwapchainImagesKHR(m_swapchains[handle.getId()].getSwapchain()); + } + + std::vector<vk::ImageView> SwapchainManager::createSwapchainImageViews(SwapchainHandle& handle) { + std::vector<vk::Image> images = getSwapchainImages(handle); + Swapchain &swapchain = m_swapchains[handle.getId()]; + + std::vector<vk::ImageView> imageViews; + imageViews.reserve(images.size()); + //here can be swizzled with vk::ComponentSwizzle if needed + vk::ComponentMapping componentMapping( + vk::ComponentSwizzle::eR, + vk::ComponentSwizzle::eG, + vk::ComponentSwizzle::eB, + vk::ComponentSwizzle::eA); + + vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); + + for (auto image : images) { + vk::ImageViewCreateInfo imageViewCreateInfo( + vk::ImageViewCreateFlags(), + image, + vk::ImageViewType::e2D, + swapchain.getFormat(), + componentMapping, + subResourceRange); + + imageViews.push_back(m_context->getDevice().createImageView(imageViewCreateInfo)); + } + return imageViews; + } +} \ No newline at end of file diff --git a/src/vkcv/SwapchainManager.hpp b/src/vkcv/SwapchainManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..58478ef09af1734bef7df217550d43af74fd8424 --- /dev/null +++ b/src/vkcv/SwapchainManager.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include <vector> +#include <GLFW/glfw3.h> + +#include "WindowManager.hpp" +#include "vkcv/Swapchain.hpp" +#include "vkcv/Handles.hpp" + +namespace vkcv { + class Core; + + class SwapchainManager { + friend class Core; + + friend class WindowManager; + + private: + std::vector<Swapchain> m_swapchains; + + Context *m_context; + + void destroySwapchainById(uint64_t id); + + public: + SwapchainManager() noexcept; + + ~SwapchainManager() noexcept; + + SwapchainManager(SwapchainManager &&other) = delete; + + SwapchainManager(const SwapchainManager &other) = delete; + + SwapchainManager &operator=(SwapchainManager &&other) = delete; + + SwapchainManager &operator=(const SwapchainManager &other) = delete; + + /** + * creates a swapchain and returns the handle + * @param window of the to creatable window + * @return the swapchainHandle of the created swapchain + */ + SwapchainHandle createSwapchain(Window &window); + + /** + * @param handle of the swapchain to get + * @return the reference of the swapchain + */ + [[nodiscard]] + Swapchain &getSwapchain(const SwapchainHandle& handle); + + /** + * sets the recreation flag fot the swapchain + * @param handle of the swapchain that should be recreated + */ + void signalRecreation(const SwapchainHandle& handle); + + /** + * gets the swapchain images + * @param handle of the swapchain + * @return a vector of the swapchain images + */ + std::vector<vk::Image> getSwapchainImages(const SwapchainHandle& handle); + + /** + * creates the swapchain imageViews for the swapchain + * @param handle of the swapchain which ImageViews should be created + * @return a ov ImageViews of the swapchain + */ + std::vector<vk::ImageView> createSwapchainImageViews(SwapchainHandle& handle); + }; +} \ No newline at end of file diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index 072efcd00eb6520fa4f20379721b559668339f6e..2b49ea32b21dc5d2497f6844c17baf8c3454640e 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -1,8 +1,3 @@ -/** - * @authors Sebastian Gaida - * @file src/vkcv/Window.cpp - * @brief Window class to handle a basic rendering surface and input - */ #include <thread> #include <vector> @@ -11,11 +6,117 @@ #include "vkcv/Window.hpp" namespace vkcv { + + void Window_onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + if (window != nullptr) { + window->e_mouseButton(button, action, mods); + } + } + + void Window_onMouseMoveEvent(GLFWwindow *callbackWindow, double x, double y) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + if (window != nullptr) { + window->e_mouseMove(x, y); + } + } + + void Window_onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + if (window != nullptr) { + window->e_mouseScroll(xoffset, yoffset); + } + } + + void Window_onResize(GLFWwindow *callbackWindow, int width, int height) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + if (window != nullptr) { + window->e_resize(width, height); + } + } + + void Window_onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + if (window != nullptr) { + window->e_key(key, scancode, action, mods); + } + } + + void Window_onCharEvent(GLFWwindow *callbackWindow, unsigned int c) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); + + if (window != nullptr) { + window->e_char(c); + } + } + static std::vector<GLFWwindow*> s_Windows; - Window::Window(GLFWwindow *window) : - m_window(window), + void Window_onGamepadEvent(int gamepadIndex) { + Window::getFocusedWindow().e_gamepad(gamepadIndex); + } + + static GLFWwindow* createGLFWWindow(const char *windowTitle, int width, int height, bool resizable) { + if(s_Windows.empty()) { + glfwInit(); + } + + width = std::max(width, 1); + height = std::max(height, 1); + + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE); + + GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); + + if (window) { + s_Windows.push_back(window); + } + + return window; + } + + static void bindGLFWWindow(GLFWwindow *windowHandle, Window* window) { + if (!windowHandle) { + return; + } + + glfwSetWindowUserPointer(windowHandle, window); + + // combine Callbacks with Events + glfwSetMouseButtonCallback(windowHandle, Window_onMouseButtonEvent); + glfwSetCursorPosCallback(windowHandle, Window_onMouseMoveEvent); + glfwSetWindowSizeCallback(windowHandle, Window_onResize); + glfwSetKeyCallback(windowHandle, Window_onKeyEvent); + glfwSetScrollCallback(windowHandle, Window_onMouseScrollEvent); + glfwSetCharCallback(windowHandle, Window_onCharEvent); + } + + Window::Window() : + m_title(), + m_resizable(false), + m_shouldClose(false), + m_window(nullptr), + e_mouseButton(true), + e_mouseMove(true), + e_mouseScroll(true), + e_resize(true), + e_key(true), + e_char(true), + e_gamepad(true) + {} + + Window::Window(const char* title, int width, int height, bool resizable) : + m_title(title), + m_resizable(resizable), + m_shouldClose(false), + m_window(createGLFWWindow(title, width, height, resizable)), e_mouseButton(true), e_mouseMove(true), e_mouseScroll(true), @@ -24,15 +125,7 @@ namespace vkcv { e_char(true), e_gamepad(true) { - glfwSetWindowUserPointer(m_window, this); - - // combine Callbacks with Events - glfwSetMouseButtonCallback(m_window, Window::onMouseButtonEvent); - glfwSetCursorPosCallback(m_window, Window::onMouseMoveEvent); - glfwSetWindowSizeCallback(m_window, Window::onResize); - glfwSetKeyCallback(m_window, Window::onKeyEvent); - glfwSetScrollCallback(m_window, Window::onMouseScrollEvent); - glfwSetCharCallback(m_window, Window::onCharEvent); + bindGLFWWindow(m_window, this); } Window::~Window() { @@ -43,31 +136,28 @@ namespace vkcv { Window::e_key.unlock(); Window::e_char.unlock(); Window::e_gamepad.unlock(); - - s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); - glfwDestroyWindow(m_window); + Window::e_resize.remove(m_resizeHandle); + if (m_window) { + s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); + glfwDestroyWindow(m_window); + } if(s_Windows.empty()) { glfwTerminate(); } } - Window Window::create( const char *windowTitle, int width, int height, bool resizable) { - if(s_Windows.empty()) { - glfwInit(); + bool Window::hasOpenWindow() { + for (auto glfwWindow : s_Windows) { + auto window = static_cast<Window *>(glfwGetWindowUserPointer(glfwWindow)); + + if (window->isOpen()) { + return true; + } } - - width = std::max(width, 1); - height = std::max(height, 1); - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE); - GLFWwindow *window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr); - - s_Windows.push_back(window); - - return Window(window); - } + + return false; + } void Window::pollEvents() { @@ -92,7 +182,7 @@ namespace vkcv { for (int gamepadIndex = GLFW_JOYSTICK_1; gamepadIndex <= GLFW_JOYSTICK_LAST; gamepadIndex++) { if (glfwJoystickPresent(gamepadIndex)) { - onGamepadEvent(gamepadIndex); + Window_onGamepadEvent(gamepadIndex); } } @@ -106,96 +196,101 @@ namespace vkcv { window->e_key.lock(); window->e_char.lock(); window->e_gamepad.lock(); + + window->m_shouldClose |= glfwWindowShouldClose(glfwWindow); } } + + const std::vector<std::string>& Window::getExtensions() { + static std::vector<std::string> extensions; + + if (extensions.empty()) { + if(s_Windows.empty()) { + glfwInit(); + } + + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + for (uint32_t i = 0; i < glfwExtensionCount; i++) { + extensions.emplace_back(glfwExtensions[i]); + } + + if (s_Windows.empty()) { + glfwTerminate(); + } + } + + return extensions; + } - void Window::onMouseButtonEvent(GLFWwindow *callbackWindow, int button, int action, int mods) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_mouseButton(button, action, mods); - } + bool Window::isOpen() const { + if (!m_window) { + return false; + } + + return !m_shouldClose; } - - void Window::onMouseMoveEvent(GLFWwindow *callbackWindow, double x, double y) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_mouseMove(x, y); - } + + const std::string& Window::getTitle() const { + return m_title; } - void Window::onMouseScrollEvent(GLFWwindow *callbackWindow, double xoffset, double yoffset) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_mouseScroll(xoffset, yoffset); + int Window::getWidth() const { + int width = 0; + + if (m_window) { + glfwGetWindowSize(m_window, &width, nullptr); } + + return std::max(width, 1); } - void Window::onResize(GLFWwindow *callbackWindow, int width, int height) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_resize(width, height); + int Window::getHeight() const { + int height = 0; + + if (m_window) { + glfwGetWindowSize(m_window, nullptr, &height); } + + return std::max(height, 1); } + + bool Window::isResizable() const { + return m_resizable; + } - void Window::onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_key(key, scancode, action, mods); - } + GLFWwindow* Window::getWindow() const { + return m_window; } - void Window::onCharEvent(GLFWwindow *callbackWindow, unsigned int c) { - auto window = static_cast<Window *>(glfwGetWindowUserPointer(callbackWindow)); - - if (window != nullptr) { - window->e_char(c); + void Window::getFramebufferSize(int &width, int &height) const { + if (m_window) { + glfwGetFramebufferSize(m_window, &width, &height); + } else { + width = 0; + height = 0; } } - void Window::onGamepadEvent(int gamepadIndex) { - size_t activeWindowIndex = std::find_if( - s_Windows.begin(), - s_Windows.end(), - [](GLFWwindow* window){return glfwGetWindowAttrib(window, GLFW_FOCUSED);} - ) - s_Windows.begin(); - - // fixes index getting out of bounds (e.g. if there is no focused window) - activeWindowIndex *= (activeWindowIndex < s_Windows.size()); - - auto window = static_cast<Window *>(glfwGetWindowUserPointer(s_Windows[activeWindowIndex])); + Window& Window::getFocusedWindow() { + static Window defaultWindow; - if (window != nullptr) { - window->e_gamepad(gamepadIndex); - } - } - - bool Window::isWindowOpen() const { - return !glfwWindowShouldClose(m_window); - } + auto activeWindowIterator = std::find_if( + s_Windows.begin(), + s_Windows.end(), + [](GLFWwindow *window) { return glfwGetWindowAttrib(window, GLFW_FOCUSED); } + ); - int Window::getWidth() const { - int width; - glfwGetWindowSize(m_window, &width, nullptr); - return width; - } - - int Window::getHeight() const { - int height; - glfwGetWindowSize(m_window, nullptr, &height); - return height; - } + if( activeWindowIterator == s_Windows.end() ) + { + return defaultWindow; + } + Window& window = *static_cast<Window *>(glfwGetWindowUserPointer(*activeWindowIterator)); + return window; + } - GLFWwindow *Window::getWindow() const { - return m_window; - } - - void Window::getFramebufferSize(int &width, int &height) const { - glfwGetFramebufferSize(m_window, &width, &height); - } - + SwapchainHandle Window::getSwapchainHandle() const { + return m_swapchainHandle; + } } diff --git a/src/vkcv/WindowManager.cpp b/src/vkcv/WindowManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3179b219e9e93905d7202cf8e11dbbf0e019020f --- /dev/null +++ b/src/vkcv/WindowManager.cpp @@ -0,0 +1,56 @@ +#include "WindowManager.hpp" + +namespace vkcv { + + WindowManager::WindowManager() noexcept { + } + + WindowManager::~WindowManager() noexcept { + for (uint64_t id = 0; id < m_windows.size(); id++) { + destroyWindowById(id); + } + + m_windows.clear(); + } + + WindowHandle WindowManager::createWindow( + SwapchainManager &swapchainManager, + const char *applicationName, + uint32_t windowWidth, + uint32_t windowHeight, + bool resizeable) { + const uint64_t id = m_windows.size(); + + auto window = new Window(applicationName, windowWidth, windowHeight, resizeable); + + SwapchainHandle swapchainHandle = swapchainManager.createSwapchain(*window); + + if (resizeable) { + const event_handle<int, int> &resizeHandle = window->e_resize.add([&,handle=swapchainHandle](int width, int height) { + // copy handle because it would run out of scope and be invalid + swapchainManager.signalRecreation(handle); + }); + window->m_resizeHandle = resizeHandle; + } + + m_windows.push_back(window); + return WindowHandle(id, [&](uint64_t id) { destroyWindowById(id); }); + } + + Window &WindowManager::getWindow(const WindowHandle handle) const { + return *m_windows[handle.getId()]; + } + + void WindowManager::destroyWindowById(uint64_t id) { + + if (id >= m_windows.size()) { + vkcv_log(LogLevel::ERROR, "Invalid id"); + return; + } + + if (m_windows[id] != nullptr) { + delete m_windows[id]; + m_windows[id] = nullptr; + } + } +} \ No newline at end of file diff --git a/src/vkcv/WindowManager.hpp b/src/vkcv/WindowManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..66186c494c38a5af46ffe34cc31b2e86bbbc95db --- /dev/null +++ b/src/vkcv/WindowManager.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include <memory> +#include <vector> +#include <GLFW/glfw3.h> + +#include "vkcv/Window.hpp" +#include "vkcv/Handles.hpp" +#include "SwapchainManager.hpp" + +namespace vkcv { + class Context; + + class SwapchainManager; + + class WindowManager { + friend class Core; + + private: + std::vector<Window*> m_windows; + + void destroyWindowById(uint64_t id); + + public: + WindowManager() noexcept; + + ~WindowManager() noexcept; + + WindowManager(WindowManager &&other) = delete; + + WindowManager(const WindowManager &other) = delete; + + WindowManager &operator=(WindowManager &&other) = delete; + + WindowManager &operator=(const WindowManager &other) = delete; + + /** + * creates a window and returns it's handle + * @param swapchainManager for swapchain creation + * @param applicationName name of the window + * @param windowWidth + * @param windowHeight + * @param resizeable if the window is resizable + * @return window handle + */ + WindowHandle createWindow(SwapchainManager &swapchainManager, const char *applicationName, uint32_t windowWidth, + uint32_t windowHeight, + bool resizeable); + + /** + * @param handle of the window to get + * @return the reference of the window + */ + [[nodiscard]] + Window &getWindow(const WindowHandle handle) const; + + }; +} \ No newline at end of file