From 3132e9630f56432c2e151558ea8e219f17d9a6dc Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Wed, 16 Jun 2021 18:00:51 +0200
Subject: [PATCH] [#72] Added GUIWindow class in gui module using imgui and
 renamed swapchain

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 .gitmodules                                   |   3 +
 config/Sources.cmake                          |   4 +-
 include/vkcv/Core.hpp                         |  13 +-
 include/vkcv/{SwapChain.hpp => Swapchain.hpp} |  63 +++++-----
 include/vkcv/Window.hpp                       |  17 +--
 modules/CMakeLists.txt                        |   1 +
 modules/gui/CMakeLists.txt                    |  34 +++++
 modules/gui/config/ImGui.cmake                |  17 +++
 modules/gui/include/vkcv/gui/GUIWindow.hpp    |  33 +++++
 modules/gui/lib/imgui                         |   1 +
 modules/gui/src/vkcv/gui/GUIWindow.cpp        | 116 ++++++++++++++++++
 projects/cmd_sync_test/src/main.cpp           |   2 +-
 projects/first_mesh/src/main.cpp              |   2 +-
 projects/first_scene/src/main.cpp             |   2 +-
 projects/first_triangle/src/main.cpp          |   2 +-
 src/vkcv/Core.cpp                             |  16 +--
 src/vkcv/{SwapChain.cpp => Swapchain.cpp}     |  64 +++++-----
 src/vkcv/Window.cpp                           |  31 ++---
 18 files changed, 317 insertions(+), 104 deletions(-)
 rename include/vkcv/{SwapChain.hpp => Swapchain.hpp} (83%)
 create mode 100644 modules/gui/CMakeLists.txt
 create mode 100644 modules/gui/config/ImGui.cmake
 create mode 100644 modules/gui/include/vkcv/gui/GUIWindow.hpp
 create mode 160000 modules/gui/lib/imgui
 create mode 100644 modules/gui/src/vkcv/gui/GUIWindow.cpp
 rename src/vkcv/{SwapChain.cpp => Swapchain.cpp} (88%)

diff --git a/.gitmodules b/.gitmodules
index 62938a4b..e0aaf2d1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -19,3 +19,6 @@
 [submodule "modules/shader_compiler/lib/glslang"]
 	path = modules/shader_compiler/lib/glslang
 	url = https://github.com/KhronosGroup/glslang.git
+[submodule "modules/gui/lib/imgui"]
+	path = modules/gui/lib/imgui
+	url = https://github.com/ocornut/imgui.git
diff --git a/config/Sources.cmake b/config/Sources.cmake
index 62cec249..4397e497 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -32,8 +32,8 @@ set(vkcv_sources
 		
 		${vkcv_include}/vkcv/Logger.hpp
 
-		${vkcv_include}/vkcv/SwapChain.hpp
-		${vkcv_source}/vkcv/SwapChain.cpp
+		${vkcv_include}/vkcv/Swapchain.hpp
+		${vkcv_source}/vkcv/Swapchain.cpp
 		
 		${vkcv_include}/vkcv/ShaderStage.hpp
 		
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 4a51b24f..b192dc79 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -8,7 +8,7 @@
 #include <vulkan/vulkan.hpp>
 
 #include "vkcv/Context.hpp"
-#include "vkcv/SwapChain.hpp"
+#include "vkcv/Swapchain.hpp"
 #include "vkcv/Window.hpp"
 #include "vkcv/PassConfig.hpp"
 #include "vkcv/Handles.hpp"
@@ -52,7 +52,7 @@ namespace vkcv
          *
          * @param context encapsulates various Vulkan objects
          */
-        Core(Context &&context, Window &window, const SwapChain& swapChain,  std::vector<vk::ImageView> imageViews,
+        Core(Context &&context, Window &window, const Swapchain& swapChain,  std::vector<vk::ImageView> imageViews,
 			const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
         // explicit destruction of default constructor
         Core() = delete;
@@ -61,7 +61,7 @@ namespace vkcv
 
         Context m_Context;
 
-        SwapChain                       m_swapchain;
+        Swapchain                       m_swapchain;
         std::vector<vk::ImageView>      m_swapchainImageViews;
         std::vector<vk::Image>          m_swapchainImages;
 		std::vector<vk::ImageLayout>    m_swapchainImageLayouts;
@@ -81,7 +81,7 @@ namespace vkcv
 
         std::function<void(int, int)> e_resizeHandle;
 
-        static std::vector<vk::ImageView> createImageViews( Context &context, SwapChain& swapChain);
+        static std::vector<vk::ImageView> createImageViews( Context &context, Swapchain& swapChain);
 
 		void recordSwapchainImageLayoutTransition(vk::CommandBuffer cmdBuffer, vk::ImageLayout newLayout);
 
@@ -123,6 +123,9 @@ 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.
@@ -253,8 +256,6 @@ namespace vkcv
 		*/
 		void endFrame();
 
-		vk::Format getSwapchainImageFormat();
-
 		/**
 		 * Submit a command buffer to any queue of selected type. The recording can be customized by a
 		 * custom record-command-function. If the command submission has finished, an optional finish-function
diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/Swapchain.hpp
similarity index 83%
rename from include/vkcv/SwapChain.hpp
rename to include/vkcv/Swapchain.hpp
index 089205d1..b75fc5a8 100644
--- a/include/vkcv/SwapChain.hpp
+++ b/include/vkcv/Swapchain.hpp
@@ -7,8 +7,9 @@
 
 namespace vkcv
 {
-    class SwapChain final {
+    class Swapchain final {
     private:
+    	friend class Core;
 
         struct Surface
         {
@@ -21,10 +22,10 @@ namespace vkcv
         Surface m_Surface;
 
         vk::SwapchainKHR m_Swapchain;
-        vk::Format m_SwapchainFormat;
-        vk::ColorSpaceKHR m_SwapchainColorSpace;
-        vk::PresentModeKHR m_SwapchainPresentMode;
-		uint32_t m_SwapchainImageCount;
+        vk::Format m_Format;
+        vk::ColorSpaceKHR m_ColorSpace;
+        vk::PresentModeKHR m_PresentMode;
+		uint32_t m_ImageCount;
 	
 		vk::Extent2D m_Extent;
 	
@@ -39,16 +40,36 @@ namespace vkcv
          * @param format
          */
          // TODO:
-        SwapChain(const Surface &surface,
+        Swapchain(const Surface &surface,
                   vk::SwapchainKHR swapchain,
                   vk::Format format,
                   vk::ColorSpaceKHR colorSpace,
                   vk::PresentModeKHR presentMode,
                   uint32_t imageCount,
 				  vk::Extent2D extent) noexcept;
+	
+		/**
+		 * TODO
+		 *
+		 * @return
+		 */
+		bool shouldUpdateSwapchain() const;
+	
+		/**
+		 * TODO
+		 *
+		 * context
+		 * window
+		 */
+		void updateSwapchain(const Context &context, const Window &window);
+	
+		/**
+		 *
+		 */
+		void signalSwapchainRecreation();
 
     public:
-    	SwapChain(const SwapChain& other);
+    	Swapchain(const Swapchain& other);
 
         /**
          * @return The swapchain linked with the #SwapChain class
@@ -69,7 +90,7 @@ namespace vkcv
          * @return gets the chosen swapchain format
          */
         [[nodiscard]]
-        vk::Format getSwapchainFormat() const;
+        vk::Format getFormat() const;
 
         /**
          * creates a swap chain object out of the given window and the given context
@@ -77,37 +98,17 @@ namespace vkcv
          * @param context of the application
          * @return returns an object of swapChain
          */
-        static SwapChain create(const Window &window, const Context &context);
+        static Swapchain create(const Window &window, const Context &context);
 
         /**
          * Destructor of SwapChain
          */
-        virtual ~SwapChain();
+        virtual ~Swapchain();
 
 		/**
 		 * @return number of images in swapchain
 		*/
-		uint32_t getImageCount();
-		
-		/**
-		 * TODO
-		 *
-		 * @return
-		 */
-		bool shouldUpdateSwapchain() const;
-
-		/**
-		 * TODO
-		 *
-		 * context
-		 * window
-		 */
-		void updateSwapchain(const Context &context, const Window &window);
-		
-		/**
-		 *
-		 */
-        void signalSwapchainRecreation();
+		uint32_t getImageCount() const;
 	
         /**
          * TODO
diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp
index f71671c9..5db19bc7 100644
--- a/include/vkcv/Window.hpp
+++ b/include/vkcv/Window.hpp
@@ -13,16 +13,19 @@ struct GLFWwindow;
 
 namespace vkcv {
 
-    class Window final {
-    private:
-        GLFWwindow *m_window;
-
-        /**
+    class Window {
+	protected:
+		GLFWwindow *m_window;
+	
+		/**
          *
          * @param GLFWwindow of the class
          */
-        explicit Window(GLFWwindow *window);
-
+		explicit Window(GLFWwindow *window);
+		
+		static GLFWwindow* createGLFWWindow(const char *windowTitle, int width, int height, bool resizable);
+		
+    private:
         /**
          * mouse callback for moving the mouse on the screen
          * @param[in] window The window that received the event.
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index e8efea49..5edb802b 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -2,5 +2,6 @@
 # Add new modules here:
 add_subdirectory(asset_loader)
 add_subdirectory(camera)
+add_subdirectory(gui)
 add_subdirectory(shader_compiler)
 add_subdirectory(testing)
diff --git a/modules/gui/CMakeLists.txt b/modules/gui/CMakeLists.txt
new file mode 100644
index 00000000..6ddfd536
--- /dev/null
+++ b/modules/gui/CMakeLists.txt
@@ -0,0 +1,34 @@
+cmake_minimum_required(VERSION 3.16)
+project(vkcv_gui)
+
+# setting c++ standard for the module
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+set(vkcv_gui_source ${PROJECT_SOURCE_DIR}/src)
+set(vkcv_gui_include ${PROJECT_SOURCE_DIR}/include)
+
+# Add source and header files to the module
+set(vkcv_gui_sources
+		${vkcv_gui_include}/vkcv/gui/GUIWindow.hpp
+		${vkcv_gui_source}/vkcv/gui/GUIWindow.cpp
+		)
+
+# Setup some path variables to load libraries
+set(vkcv_gui_lib lib)
+set(vkcv_gui_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_gui_lib})
+
+# Check and load IMGUI
+include(config/ImGui.cmake)
+
+# adding source files to the module
+add_library(vkcv_gui STATIC ${vkcv_gui_sources} ${vkcv_imgui_sources})
+
+# link the required libraries to the module
+target_link_libraries(vkcv_gui ${vkcv_gui_libraries} vkcv)
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(vkcv_gui SYSTEM BEFORE PRIVATE ${vkcv_gui_includes} ${vkcv_include})
+
+# add the own include directory for public headers
+target_include_directories(vkcv_gui BEFORE PUBLIC ${vkcv_gui_include} ${vkcv_imgui_includes})
diff --git a/modules/gui/config/ImGui.cmake b/modules/gui/config/ImGui.cmake
new file mode 100644
index 00000000..3f55ad05
--- /dev/null
+++ b/modules/gui/config/ImGui.cmake
@@ -0,0 +1,17 @@
+
+if (EXISTS "${vkcv_gui_lib_path}/imgui")
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_glfw.cpp)
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_vulkan.cpp )
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui.cpp)
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_draw.cpp)
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_demo.cpp)
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_tables.cpp)
+	list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_widgets.cpp)
+	
+	list(APPEND vkcv_imgui_includes ${vkcv_gui_lib}/imgui)
+	list(APPEND vkcv_imgui_includes ${vkcv_gui_lib}/imgui/backend)
+	
+	list(APPEND vkcv_gui_include ${vkcv_gui_lib})
+else()
+	message(WARNING "IMGUI is required..! Update the submodules!")
+endif ()
diff --git a/modules/gui/include/vkcv/gui/GUIWindow.hpp b/modules/gui/include/vkcv/gui/GUIWindow.hpp
new file mode 100644
index 00000000..afc18957
--- /dev/null
+++ b/modules/gui/include/vkcv/gui/GUIWindow.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "imgui/imgui.h"
+#include "imgui/backends/imgui_impl_glfw.h"
+#include "imgui/backends/imgui_impl_vulkan.h"
+
+#include <vkcv/Core.hpp>
+
+namespace vkcv::gui {
+
+	class GUIWindow final : Window {
+	private:
+		Core& m_core;
+		
+		const Context& m_context;
+		const Swapchain& m_swapchain;
+		
+		ImGuiContext* m_gui_context;
+		
+		ImGui_ImplVulkanH_Window m_gui_window;
+		
+		vk::DescriptorPool m_descriptor_pool;
+	
+	public:
+		GUIWindow(GLFWwindow* window, Core& core);
+	
+		virtual ~GUIWindow() override;
+		
+		static GUIWindow create(Core& core, const char *windowTitle, int width = -1, int height = -1, bool resizable = false);
+		
+	};
+
+}
diff --git a/modules/gui/lib/imgui b/modules/gui/lib/imgui
new file mode 160000
index 00000000..d5828cd9
--- /dev/null
+++ b/modules/gui/lib/imgui
@@ -0,0 +1 @@
+Subproject commit d5828cd988db525f27128edeadb1a689cd2d7461
diff --git a/modules/gui/src/vkcv/gui/GUIWindow.cpp b/modules/gui/src/vkcv/gui/GUIWindow.cpp
new file mode 100644
index 00000000..15bc0383
--- /dev/null
+++ b/modules/gui/src/vkcv/gui/GUIWindow.cpp
@@ -0,0 +1,116 @@
+
+#include "vkcv/gui/GUIWindow.hpp"
+
+#include <vkcv/Logger.hpp>
+
+namespace vkcv::gui {
+	
+	static void checkVulkanResult(VkResult resultCode) {
+		if (resultCode == 0)
+			return;
+		
+		const vk::Result result = vk::Result(resultCode);
+		
+		vkcv_log(LogLevel::ERROR, "ImGui has a problem with Vulkan! (%s)", vk::to_string(result).c_str());
+	}
+	
+	GUIWindow::GUIWindow(GLFWwindow* window, Core& core) :
+	Window(window),
+	m_core(core),
+	m_context(core.getContext()),
+	m_swapchain(core.getSwapchain()),
+	m_gui_context(nullptr) {
+		IMGUI_CHECKVERSION();
+		
+		m_gui_context = ImGui::CreateContext();
+		
+		const auto extent = m_swapchain.getExtent();
+		const uint32_t graphicsQueueFamilyIndex = (
+				m_context.getQueueManager().getGraphicsQueues()[0].familyIndex
+		);
+		
+		ImGui_ImplVulkanH_CreateOrResizeWindow(
+				m_context.getInstance(),
+				m_context.getPhysicalDevice(),
+				m_context.getDevice(),
+				&m_gui_window,
+				graphicsQueueFamilyIndex,
+				nullptr,
+				static_cast<int>(extent.width),
+				static_cast<int>(extent.height),
+				m_swapchain.getImageCount()
+		);
+		
+		ImGui_ImplGlfw_InitForVulkan(window, true);
+		
+		vk::DescriptorPoolSize pool_sizes[] = {
+				vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eStorageImage, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eUniformTexelBuffer, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eStorageTexelBuffer, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eUniformBufferDynamic, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eStorageBufferDynamic, 1000),
+				vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, 1000)
+		};
+		
+		const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo (
+				vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
+				static_cast<uint32_t>(1000 * IM_ARRAYSIZE(pool_sizes)),
+				static_cast<uint32_t>(IM_ARRAYSIZE(pool_sizes)),
+				pool_sizes
+		);
+		
+		m_descriptor_pool = m_context.getDevice().createDescriptorPool(descriptorPoolCreateInfo);
+		
+		ImGui_ImplVulkan_InitInfo init_info = {};
+		init_info.Instance = m_context.getInstance();
+		init_info.PhysicalDevice = m_context.getPhysicalDevice();
+		init_info.Device = m_context.getDevice();
+		init_info.QueueFamily = graphicsQueueFamilyIndex;
+		init_info.Queue = m_context.getQueueManager().getGraphicsQueues()[0].handle;
+		init_info.PipelineCache = nullptr;
+		init_info.DescriptorPool = m_descriptor_pool;
+		init_info.Allocator = nullptr;
+		init_info.MinImageCount = m_swapchain.getImageCount();
+		init_info.ImageCount = m_gui_window.ImageCount;
+		init_info.CheckVkResultFn = checkVulkanResult;
+		ImGui_ImplVulkan_Init(&init_info, m_gui_window.RenderPass);
+		
+		const SubmitInfo submitInfo { QueueType::Transfer, {}, {} };
+		
+		core.recordAndSubmitCommands(submitInfo, [](const vk::CommandBuffer& commandBuffer) {
+			ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
+		}, []() {
+			ImGui_ImplVulkan_DestroyFontUploadObjects();
+		});
+	}
+	
+	GUIWindow::~GUIWindow() {
+		m_context.getDevice().waitIdle();
+		
+		ImGui_ImplVulkan_Shutdown();
+		ImGui_ImplGlfw_Shutdown();
+		
+		vkDestroyDescriptorPool(m_context.getDevice(), m_descriptor_pool, nullptr);
+		
+		ImGui_ImplVulkanH_DestroyWindow(
+				m_context.getInstance(),
+				m_context.getDevice(),
+				&m_gui_window,
+				nullptr
+		);
+		
+		if (m_gui_context) {
+			ImGui::DestroyContext(m_gui_context);
+		}
+	}
+	
+	GUIWindow GUIWindow::create(Core &core, const char *windowTitle, int width, int height, bool resizable) {
+		return GUIWindow(Window::createGLFWWindow(windowTitle, width, height, resizable), core);
+	}
+	
+}
diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp
index c33f1adc..7ec54582 100644
--- a/projects/cmd_sync_test/src/main.cpp
+++ b/projects/cmd_sync_test/src/main.cpp
@@ -86,7 +86,7 @@ int main(int argc, const char** argv) {
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
 		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainImageFormat()
+		core.getSwapchain().getFormat()
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment(
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 8ffe5017..6377a672 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -63,7 +63,7 @@ int main(int argc, const char** argv) {
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
 		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainImageFormat()
+		core.getSwapchain().getFormat()
 	);
 	
 	const vkcv::AttachmentDescription depth_attachment(
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 5a59edf7..00a862cf 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -112,7 +112,7 @@ int main(int argc, const char** argv) {
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
 		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainImageFormat()
+		core.getSwapchain().getFormat()
 	);
 
 	const vkcv::AttachmentDescription depth_attachment(
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 1c6f9604..eca7ad77 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -81,7 +81,7 @@ int main(int argc, const char** argv) {
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
 		vkcv::AttachmentOperation::CLEAR,
-		core.getSwapchainImageFormat());
+		core.getSwapchain().getFormat());
 
 	vkcv::PassConfig trianglePassDefinition({ present_color_attachment });
 	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 44e7111e..5fab62f7 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -35,7 +35,7 @@ namespace vkcv
         		deviceExtensions
 		);
 
-        SwapChain swapChain = SwapChain::create(window, context);
+        Swapchain swapChain = Swapchain::create(window, context);
 
         std::vector<vk::ImageView> imageViews;
         imageViews = createImageViews( context, swapChain);
@@ -54,8 +54,12 @@ namespace vkcv
     {
         return m_Context;
     }
+    
+    const Swapchain& Core::getSwapchain() const {
+    	return m_swapchain;
+    }
 
-    Core::Core(Context &&context, Window &window, const SwapChain& swapChain,  std::vector<vk::ImageView> imageViews,
+    Core::Core(Context &&context, Window &window, const Swapchain& swapChain,  std::vector<vk::ImageView> imageViews,
         const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
             m_Context(std::move(context)),
             m_window(window),
@@ -371,10 +375,6 @@ namespace vkcv
 			vkcv_log(LogLevel::ERROR, "Swapchain present failed (%s)", vk::to_string(result).c_str());
 		}
 	}
-
-	vk::Format Core::getSwapchainImageFormat() {
-		return m_swapchain.getSwapchainFormat();
-	}
 	
 	void Core::recordAndSubmitCommands(
 		const SubmitInfo &submitInfo, 
@@ -458,7 +458,7 @@ namespace vkcv
 		return m_DescriptorManager->getDescriptorSet(handle);
 	}
 
-    std::vector<vk::ImageView> Core::createImageViews( Context &context, SwapChain& swapChain){
+    std::vector<vk::ImageView> Core::createImageViews( Context &context, Swapchain& swapChain){
         std::vector<vk::ImageView> imageViews;
         std::vector<vk::Image> swapChainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain());
         imageViews.reserve( swapChainImages.size() );
@@ -477,7 +477,7 @@ namespace vkcv
                     vk::ImageViewCreateFlags(),
                     image,
                     vk::ImageViewType::e2D,
-                    swapChain.getSwapchainFormat(),
+                    swapChain.getFormat(),
                     componentMapping,
                     subResourceRange);
 
diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/Swapchain.cpp
similarity index 88%
rename from src/vkcv/SwapChain.cpp
rename to src/vkcv/Swapchain.cpp
index b787536b..639e949b 100644
--- a/src/vkcv/SwapChain.cpp
+++ b/src/vkcv/Swapchain.cpp
@@ -1,4 +1,4 @@
-#include <vkcv/SwapChain.hpp>
+#include <vkcv/Swapchain.hpp>
 #include <utility>
 
 #define GLFW_INCLUDE_VULKAN
@@ -27,44 +27,44 @@ namespace vkcv
         return vk::SurfaceKHR(surface);
     }
 
-    SwapChain::SwapChain(const Surface &surface,
+    Swapchain::Swapchain(const Surface &surface,
                          vk::SwapchainKHR swapchain,
                          vk::Format format,
                          vk::ColorSpaceKHR colorSpace,
                          vk::PresentModeKHR presentMode,
                          uint32_t imageCount,
 						 vk::Extent2D extent) noexcept :
-    m_Surface(surface),
-    m_Swapchain(swapchain),
-    m_SwapchainFormat(format),
-    m_SwapchainColorSpace(colorSpace),
-    m_SwapchainPresentMode(presentMode),
-    m_SwapchainImageCount(imageCount),
-	m_Extent(extent),
-    m_RecreationRequired(false)
+			m_Surface(surface),
+			m_Swapchain(swapchain),
+			m_Format(format),
+			m_ColorSpace(colorSpace),
+			m_PresentMode(presentMode),
+			m_ImageCount(imageCount),
+			m_Extent(extent),
+			m_RecreationRequired(false)
     {}
     
-    SwapChain::SwapChain(const SwapChain &other) :
+    Swapchain::Swapchain(const Swapchain &other) :
 			m_Surface(other.m_Surface),
 			m_Swapchain(other.m_Swapchain),
-			m_SwapchainFormat(other.m_SwapchainFormat),
-			m_SwapchainColorSpace(other.m_SwapchainColorSpace),
-			m_SwapchainPresentMode(other.m_SwapchainPresentMode),
-			m_SwapchainImageCount(other.m_SwapchainImageCount),
+			m_Format(other.m_Format),
+			m_ColorSpace(other.m_ColorSpace),
+			m_PresentMode(other.m_PresentMode),
+			m_ImageCount(other.m_ImageCount),
 			m_Extent(other.m_Extent),
 			m_RecreationRequired(other.m_RecreationRequired.load())
 	{}
 
-    const vk::SwapchainKHR& SwapChain::getSwapchain() const {
+    const vk::SwapchainKHR& Swapchain::getSwapchain() const {
         return m_Swapchain;
     }
 
-    vk::SurfaceKHR SwapChain::getSurface() const {
+    vk::SurfaceKHR Swapchain::getSurface() const {
         return m_Surface.handle;
     }
 
-    vk::Format SwapChain::getSwapchainFormat() const{
-        return m_SwapchainFormat;
+    vk::Format Swapchain::getFormat() const{
+        return m_Format;
     }
 
     /**
@@ -162,7 +162,7 @@ namespace vkcv
      * @param context that keeps instance, physicalDevice and a device.
      * @return swapchain
      */
-    SwapChain SwapChain::create(const Window &window, const Context &context) {
+    Swapchain Swapchain::create(const Window &window, const Context &context) {
         const vk::Instance& instance = context.getInstance();
         const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
         const vk::Device& device = context.getDevice();
@@ -199,7 +199,7 @@ namespace vkcv
 
         vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo);
 
-        return SwapChain(surface,
+        return Swapchain(surface,
                          swapchain,
                          chosenSurfaceFormat.format,
                          chosenSurfaceFormat.colorSpace,
@@ -208,11 +208,11 @@ namespace vkcv
 						 chosenExtent);
     }
     
-    bool SwapChain::shouldUpdateSwapchain() const {
+    bool Swapchain::shouldUpdateSwapchain() const {
     	return m_RecreationRequired;
     }
     
-    void SwapChain::updateSwapchain(const Context &context, const Window &window) {
+    void Swapchain::updateSwapchain(const Context &context, const Window &window) {
     	if (!m_RecreationRequired.exchange(false))
     		return;
     	
@@ -222,9 +222,9 @@ namespace vkcv
 		vk::SwapchainCreateInfoKHR swapchainCreateInfo(
 				vk::SwapchainCreateFlagsKHR(),
 				m_Surface.handle,
-				m_SwapchainImageCount,
-				m_SwapchainFormat,
-				m_SwapchainColorSpace,
+				m_ImageCount,
+				m_Format,
+				m_ColorSpace,
 				extent2D,
 				1,
 				vk::ImageUsageFlagBits::eColorAttachment,
@@ -233,7 +233,7 @@ namespace vkcv
 				nullptr,
 				vk::SurfaceTransformFlagBitsKHR::eIdentity,
 				vk::CompositeAlphaFlagBitsKHR::eOpaque,
-				m_SwapchainPresentMode,
+				m_PresentMode,
 				true,
 				oldSwapchain
 		);
@@ -244,19 +244,19 @@ namespace vkcv
 		m_Extent = extent2D;
     }
 
-    void SwapChain::signalSwapchainRecreation() {
+    void Swapchain::signalSwapchainRecreation() {
 		m_RecreationRequired = true;
     }
     
-    const vk::Extent2D& SwapChain::getExtent() const {
+    const vk::Extent2D& Swapchain::getExtent() const {
     	return m_Extent;
     }
 
-    SwapChain::~SwapChain() {
+    Swapchain::~Swapchain() {
         // needs to be destroyed by creator
     }
 
-	uint32_t SwapChain::getImageCount() {
-		return m_SwapchainImageCount;
+	uint32_t Swapchain::getImageCount() const {
+		return m_ImageCount;
 	}
 }
diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp
index c21271b7..1d745a4b 100644
--- a/src/vkcv/Window.cpp
+++ b/src/vkcv/Window.cpp
@@ -24,22 +24,25 @@ namespace vkcv {
             glfwTerminate();
         }
     }
+	
+    GLFWwindow* Window::createGLFWWindow(const char *windowTitle, int width, int height, bool resizable) {
+		if(s_WindowCount == 0) {
+			glfwInit();
+		}
+	
+		s_WindowCount++;
+	
+		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);
+		
+		return glfwCreateWindow(width, height, windowTitle, nullptr, nullptr);
+    }
 
     Window Window::create( const char *windowTitle, int width, int height, bool resizable) {
-        if(s_WindowCount == 0) {
-            glfwInit();
-        }
-        s_WindowCount++;
-
-        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;
-        window = glfwCreateWindow(width, height, windowTitle, nullptr, nullptr);
-
-        return Window(window);
+        return Window(createGLFWWindow(windowTitle, width, height, resizable));
     }
 
     void Window::initEvents() {
-- 
GitLab