diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp
index c195c9acd1..2463d5bed8 100644
--- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp
+++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp
@@ -430,7 +430,9 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan)
 	vk::set_current_thread_ctx(m_thread_context);
 	vk::set_current_renderer(m_swap_chain->get_device());
 
-	m_swap_chain->init_swapchain(m_frame->client_width(), m_frame->client_height());
+	m_client_width = m_frame->client_width();
+	m_client_height = m_frame->client_height();
+	m_swap_chain->init_swapchain(m_client_width, m_client_height);
 
 	//create command buffer...
 	m_command_buffer_pool.create((*m_device));
@@ -1135,13 +1137,9 @@ void VKGSRender::prepare_rtts()
 		return;
 
 	m_rtts_dirty = false;
-	bool reconfigure_render_pass = true;
 
 	if (m_surface.format != surface_format)
-	{
 		m_surface.unpack(surface_format);
-		reconfigure_render_pass = true;
-	}
 
 	u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
 	u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
@@ -1202,18 +1200,27 @@ void VKGSRender::prepare_rtts()
 
 void VKGSRender::flip(int buffer)
 {
-	//LOG_NOTICE(Log::RSX, "flip(%d)", buffer);
-	u32 buffer_width = gcm_buffers[buffer].width;
-	u32 buffer_height = gcm_buffers[buffer].height;
-	u32 buffer_pitch = gcm_buffers[buffer].pitch;
+	bool resize_screen = false;
 
-	rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
+	if (m_client_height != m_frame->client_height() ||
+		m_client_width != m_frame->client_width())
+	{
+		if (!!m_frame->client_height() && !!m_frame->client_width())
+			resize_screen = true;
+	}
 
-	areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });
-
-	coordi aspect_ratio;
-	if (1) //enable aspect ratio
+	if (!resize_screen)
 	{
+		u32 buffer_width = gcm_buffers[buffer].width;
+		u32 buffer_height = gcm_buffers[buffer].height;
+		u32 buffer_pitch = gcm_buffers[buffer].pitch;
+
+		rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
+
+		areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });
+
+		coordi aspect_ratio;
+
 		sizei csize = { m_frame->client_width(), m_frame->client_height() };
 		sizei new_size = csize;
 
@@ -1233,53 +1240,112 @@ void VKGSRender::flip(int buffer)
 		}
 
 		aspect_ratio.size = new_size;
+
+		VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
+
+		//Prepare surface for new frame
+		CHECK_RESULT(vkAcquireNextImageKHR((*m_device), (*m_swap_chain), 0, m_present_semaphore, VK_NULL_HANDLE, &m_current_present_image));
+
+		//Blit contents to screen..
+		VkImage image_to_flip = nullptr;
+
+		if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
+			image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0])->value;
+		else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
+			image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1])->value;
+
+		VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_present_image);
+		if (image_to_flip)
+		{
+			vk::copy_scaled_image(m_command_buffer, image_to_flip, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+				buffer_width, buffer_height, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT);
+		}
+		else
+		{
+			//No draw call was issued!
+			VkImageSubresourceRange range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
+			VkClearColorValue clear_black = { 0 };
+			vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, range);
+			vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range);
+			vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range);
+		}
+
+		close_and_submit_command_buffer({ m_present_semaphore }, m_submit_fence);
+		CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
+
+		VkPresentInfoKHR present = {};
+		present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+		present.pNext = nullptr;
+		present.swapchainCount = 1;
+		present.pSwapchains = &swap_chain;
+		present.pImageIndices = &m_current_present_image;
+		CHECK_RESULT(m_swap_chain->queuePresentKHR(m_swap_chain->get_present_queue(), &present));
 	}
 	else
 	{
-		aspect_ratio.size = { m_frame->client_width(), m_frame->client_height() };
+		/**
+		* Since we are about to destroy the old swapchain and its images, we just discard the commandbuffer.
+		* Waiting for the commands to process does not work reliably as the fence can be signaled before swap images are released
+		* and there are no explicit methods to ensure that the presentation engine is not using the images at all.
+		*/
+
+		CHECK_RESULT(vkEndCommandBuffer(m_command_buffer));
+
+		//Will have to block until rendering is completed
+		VkFence resize_fence = VK_NULL_HANDLE;
+		VkFenceCreateInfo infos = {};
+		infos.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+
+		vkQueueWaitIdle(m_swap_chain->get_present_queue());
+		vkDeviceWaitIdle(*m_device);
+
+		vkCreateFence((*m_device), &infos, nullptr, &resize_fence);
+
+		//Wait for all grpahics tasks to complete
+		VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
+		VkSubmitInfo submit_infos = {};
+		submit_infos.commandBufferCount = 0;
+		submit_infos.pCommandBuffers = nullptr;
+		submit_infos.pWaitDstStageMask = &pipe_stage_flags;
+		submit_infos.pWaitSemaphores = nullptr;
+		submit_infos.waitSemaphoreCount = 0;
+		submit_infos.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+		CHECK_RESULT(vkQueueSubmit(m_swap_chain->get_present_queue(), 1, &submit_infos, resize_fence));
+
+		vkWaitForFences((*m_device), 1, &resize_fence, VK_TRUE, UINT64_MAX);
+		vkResetFences((*m_device), 1, &resize_fence);
+
+		vkDeviceWaitIdle(*m_device);
+
+		//Rebuild swapchain. Old swapchain destruction is handled by the init_swapchain call
+		m_client_width = m_frame->client_width();
+		m_client_height = m_frame->client_height();
+		m_swap_chain->init_swapchain(m_client_width, m_client_height);
+
+		//Prepare new swapchain images for use
+		CHECK_RESULT(vkResetCommandPool(*m_device, m_command_buffer_pool, 0));
+		open_command_buffer();
+
+		for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i)
+		{
+			vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
+				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
+				vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
+
+			VkClearColorValue clear_color{};
+			auto range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
+			vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
+			vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(i),
+				VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+				vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT));
+		}
+
+		//Flush the command buffer
+		close_and_submit_command_buffer({}, resize_fence);
+		CHECK_RESULT(vkWaitForFences((*m_device), 1, &resize_fence, VK_TRUE, UINT64_MAX));
+		vkDestroyFence((*m_device), resize_fence, nullptr);
 	}
 
-	VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
-
-	//Prepare surface for new frame
-	CHECK_RESULT(vkAcquireNextImageKHR((*m_device), (*m_swap_chain), 0, m_present_semaphore, VK_NULL_HANDLE, &m_current_present_image));
-
-
-	//Blit contents to screen..
-	VkImage image_to_flip = nullptr;
-
-	if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
-		image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0])->value;
-	else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
-		image_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1])->value;
-
-	VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_present_image);
-	if (image_to_flip)
-	{
-		vk::copy_scaled_image(m_command_buffer, image_to_flip, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
-			buffer_width, buffer_height, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT);
-	}
-	else
-	{
-		//No draw call was issued!
-		VkImageSubresourceRange range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT);
-		VkClearColorValue clear_black = { 0 };
-		vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, range);
-		vkCmdClearColorImage(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range);
-		vk::change_image_layout(m_command_buffer, m_swap_chain->get_swap_chain_image(m_current_present_image), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range);
-	}
-
-	close_and_submit_command_buffer({ m_present_semaphore }, m_submit_fence);
-	CHECK_RESULT(vkWaitForFences((*m_device), 1, &m_submit_fence, VK_TRUE, ~0ULL));
-
-	VkPresentInfoKHR present = {};
-	present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
-	present.pNext = nullptr;
-	present.swapchainCount = 1;
-	present.pSwapchains = &swap_chain;
-	present.pImageIndices = &m_current_present_image;
-	CHECK_RESULT(m_swap_chain->queuePresentKHR(m_swap_chain->get_present_queue(), &present));
-
 	m_uniform_buffer_ring_info.m_get_pos = m_uniform_buffer_ring_info.get_current_put_pos_minus_one();
 	m_index_buffer_ring_info.m_get_pos = m_index_buffer_ring_info.get_current_put_pos_minus_one();
 	m_attrib_ring_info.m_get_pos = m_attrib_ring_info.get_current_put_pos_minus_one();
diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h
index 3788265446..4b7e1b12c8 100644
--- a/rpcs3/Emu/RSX/VK/VKGSRender.h
+++ b/rpcs3/Emu/RSX/VK/VKGSRender.h
@@ -69,6 +69,9 @@ private:
 	std::vector<std::unique_ptr<vk::framebuffer> > m_framebuffer_to_clean;
 	std::vector<std::unique_ptr<vk::sampler> > m_sampler_to_clean;
 
+	u32 m_client_width = 0;
+	u32 m_client_height = 0;
+
 	u32 m_draw_calls = 0;
 	u32 m_used_descriptors = 0;
 	u8 m_draw_buffers_count = 0;