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 429c0bcf729f9afb7dd76cdd58c54931862e1a4a..0dfa7811f0a7cca9107676438c0c66ade4519828 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 PipelineHandle             &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 c0065af5928d9ad2e2c9afd1a1ea44c35d94d799..f4318f42ddd2a14b6f87eefdd46d20df5fc98c44 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 PipelineHandle             &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 17be476ca7af0504a2d4e4f2e2d610ca43f6cee2..9e47c21f668b8d12c62bb44403b1c92b2c189100 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -18,6 +18,8 @@ int main(int argc, const char** argv) {
 		{ 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] : "resources/cube/cube.gltf";
@@ -51,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(
@@ -154,7 +156,7 @@ 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(core.getWindow());
+    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));
@@ -164,11 +166,11 @@ int main(int argc, const char** argv) {
 	while (vkcv::Window::hasOpenWindow()) {
         vkcv::Window::pollEvents();
 		
-		if(core.getWindow().getHeight() == 0 || core.getWindow().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;
 		}
 		
@@ -198,10 +200,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 289d6a05213f064c45b9e578c44c8cc8f1bf883f..efaa7f3ae6d8dc2d297565a23ed1bfbc773c9159 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -19,7 +19,8 @@ int main(int argc, const char** argv) {
 			{vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute},
 			{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }
 	);
-	vkcv::Window window = core.getWindow();
+	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);
@@ -37,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(
@@ -104,7 +105,7 @@ int main(int argc, const char** argv) {
 			continue;
 		
 		uint32_t swapchainWidth, swapchainHeight;
-		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+		if (!core.beginFrame(swapchainWidth, swapchainHeight,windowHandle)) {
 			continue;
 		}
 		
@@ -136,11 +137,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 a95ad05c9d79b3db7a2cb6efa526db876c9ca7a7..5b69539fe95ab22059d4c7fb81a380e7c2836e72 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -18,7 +18,8 @@ int main(int argc, const char** argv) {
 		{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }
 	);
 
-	vkcv::Window& window = core.getWindow();
+	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false);
+	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 };
@@ -30,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);
@@ -97,7 +98,7 @@ int main(int argc, const char** argv) {
         vkcv::Window::pollEvents();
 
 		uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem
-		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+		if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) {
 			continue;
 		}
 		
@@ -120,12 +121,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 bc0e45d7c0017fd642b6ade1af5e93129ea6d474..70a2caec3202f1425a90efbb4d6fcf9024c314a5 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -13,8 +13,8 @@ App::App() :
 		VK_MAKE_VERSION(0, 0, 1),
 		{ vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer },
 		{ VK_KHR_SWAPCHAIN_EXTENSION_NAME })),
-	m_window(m_core.getWindow()),
-	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() {
 
@@ -72,7 +72,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;
@@ -117,7 +117,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) {
@@ -147,11 +147,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);
@@ -212,7 +212,8 @@ void App::run() {
 			m_prePass.pipeline,
 			prepassPushConstants,
 			prepassSceneDrawcalls,
-			prepassRenderTargets);
+			prepassRenderTargets,
+			m_windowHandle);
 
 		// sky prepass
 		glm::mat4 skyPrepassMatrices[2] = {
@@ -227,7 +228,8 @@ void App::run() {
 			m_skyPrePass.pipeline,
 			skyPrepassPushConstants,
 			{ skyDrawcall },
-			prepassRenderTargets);
+			prepassRenderTargets,
+			m_windowHandle);
 
 		// main pass
 		const std::vector<vkcv::ImageHandle> renderTargets   = { 
@@ -253,7 +255,8 @@ void App::run() {
 			m_meshPass.pipeline,
 			meshPushConstants,
 			forwardSceneDrawcalls,
-			renderTargets);
+			renderTargets,
+			m_windowHandle);
 
 		// sky
 		vkcv::PushConstants skyPushConstants(sizeof(glm::mat4));
@@ -265,7 +268,8 @@ void App::run() {
 			m_skyPass.pipeline,
 			skyPushConstants,
 			{ skyDrawcall },
-			renderTargets);
+			renderTargets,
+			m_windowHandle);
 
 		// motion blur
 		vkcv::ImageHandle motionBlurOutput;
@@ -358,6 +362,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 098078631c6061eaa7513a3d0731d3211141d37c..9c2d43bd762ecbaa57a27edd6dd6499edb3593af 100644
--- a/projects/indirect_dispatch/src/App.hpp
+++ b/projects/indirect_dispatch/src/App.hpp
@@ -16,7 +16,7 @@ private:
 	int m_windowHeight;
 
 	vkcv::Core                  m_core;
-	vkcv::Window                m_window;
+	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 7d5c1a12d27d405cb4c189e2f7ab580b1907fbe1..35fa51f318f9000fc41e5fcaa5ae9f5ba7eb81e8 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -95,10 +95,10 @@ int main(int argc, const char** argv) {
 		{ 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::Window &window = core.getWindow();
-
-    vkcv::gui::GUI gui (core, window);
+    vkcv::gui::GUI gui (core, windowHandle);
 
     vkcv::asset::Scene mesh;
     const char* path = argc > 1 ? argv[1] : "resources/Bunny/Bunny.glb";
@@ -163,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,
@@ -309,7 +309,7 @@ int main(int argc, const char** argv) {
 		vkcv::Window::pollEvents();
 
 		uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem
-		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+		if (!core.beginFrame(swapchainWidth, swapchainHeight,windowHandle)) {
 			continue;
 		}
 		
@@ -355,7 +355,8 @@ int main(int argc, const char** argv) {
 				meshShaderPipeline,
 				pushConstantData,
 				{ vkcv::MeshShaderDrawcall({descriptorUsage}, taskCount)},
-				{ renderTargets });
+				{ renderTargets },
+				windowHandle);
 		}
 		else {
 
@@ -367,7 +368,8 @@ int main(int argc, const char** argv) {
 				bunnyPipeline,
 				pushConstantData,
 				{ vkcv::DrawcallInfo(renderMesh, { descriptorUsage }) },
-				{ renderTargets });
+				{ renderTargets },
+				windowHandle);
 		}
 
 		core.prepareSwapchainImageForPresent(cmdStream);
@@ -383,7 +385,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 f6f5c100cb6e6505fe1332663eb0fee8c9eb05a0..4a25588688b8fd0dd45d52ddf76f470f9697e3c2 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -22,7 +22,8 @@ int main(int argc, const char **argv) {
             {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute},
 			{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }
     );
-    vkcv::Window window = core.getWindow();
+	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false);
+    vkcv::Window& window = core.getWindow(windowHandle);
 	vkcv::camera::CameraManager cameraManager(window);
 
     auto particleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3,
@@ -231,7 +232,7 @@ int main(int argc, const char **argv) {
         vkcv::Window::pollEvents();
 
         uint32_t swapchainWidth, swapchainHeight;
-        if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+        if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) {
             continue;
         }
 
@@ -278,7 +279,8 @@ int main(int argc, const char **argv) {
                 particlePipeline,
 				pushConstantsDraw,
                 {drawcalls},
-                { colorBuffer });
+                { colorBuffer },
+                windowHandle);
 
         bloomAndFlares.execWholePipeline(cmdStream, colorBuffer);
 
@@ -306,7 +308,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 32dd5457541f8f09f4d2711ea831e3c78de2303a..ca004ecc929f244327591e46f03dca27e54a2681 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -231,7 +231,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;
@@ -267,7 +268,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 8066d5bdc90a66c0823be4dc23cf6a12729e32c7..2e97c3fcf8fb5228abb20cfa8c58e3710e079fd4 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 f7e03709c6423ef0e3c43251afb28e887b9be61f..505e410156a3ca65d1a3e86bf7dff49bfc630ccc 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -217,7 +217,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 });
 
@@ -275,7 +276,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 };
@@ -319,7 +321,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);
@@ -347,7 +350,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 66c87acb3c13c0d950a28dc33e4084d728da5947..69fef1568675985d67b9d45cb1ff0c686cdb6abb 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 db2d6c2453325a38a7b054a2ff990ed22e0e1e67..e6863d029df367376b15de0a82f6892b10013b49 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -33,8 +33,8 @@ int main(int argc, const char** argv) {
 			{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
 			features
 	);
-
-	vkcv::Window& window = core.getWindow();
+	vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false);
+	vkcv::Window& window = core.getWindow(windowHandle);
 
 	bool     isFullscreen            = false;
 	uint32_t windowedWidthBackup     = windowWidth;
@@ -561,7 +561,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);
@@ -585,7 +585,7 @@ int main(int argc, const char** argv) {
 		vkcv::Window::pollEvents();
 
 		uint32_t swapchainWidth, swapchainHeight;
-		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+		if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) {
 			continue;
 		}
 		
@@ -702,7 +702,8 @@ int main(int argc, const char** argv) {
 			modelMatrices,
 			cameraManager.getActiveCamera(),
 			voxelization.getVoxelOffset(),
-			voxelization.getVoxelExtent());
+			voxelization.getVoxelExtent(),
+			windowHandle);
 
 		// voxelization
 		voxelization.setVoxelExtent(voxelizationExtent);
@@ -710,7 +711,8 @@ int main(int argc, const char** argv) {
 			cmdStream,
 			meshes, 
 			modelMatrices,
-			perMeshDescriptorSets);
+			perMeshDescriptorSets,
+			windowHandle);
 
 		// depth prepass
 		const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP();
@@ -731,7 +733,8 @@ int main(int argc, const char** argv) {
 			prepassPipeline,
 			prepassPushConstants,
 			prepassDrawcalls,
-			prepassRenderTargets);
+			prepassRenderTargets,
+			windowHandle);
 
 		core.recordImageMemoryBarrier(cmdStream, depthBuffer);
 		
@@ -756,10 +759,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));
@@ -772,7 +776,8 @@ int main(int argc, const char** argv) {
 			skyPipe,
 			skySettingsPushConstants,
 			{ vkcv::DrawcallInfo(vkcv::Mesh({}, nullptr, 3), {}) },
-			renderTargets);
+			renderTargets,
+			windowHandle);
 
 		const uint32_t fullscreenLocalGroupSize = 8;
 		
@@ -946,7 +951,7 @@ int main(int argc, const char** argv) {
 
 		gui.endGUI();
 
-		core.endFrame();
+		core.endFrame(windowHandle);
 	}
 	
 	return 0;