Implement VK_KHR_surface/swapchain_maintenance1

Tests: dEQP-VK.wsi.*.maintenance1.*
Bug: angleproject:7878
Change-Id: Ibb2829ded96c2f104c7382bf9bbd543654eb9863
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/70229
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Shahbaz Youssefi <syoussefi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Presubmit-Ready: Shahbaz Youssefi <syoussefi@google.com>
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index c471770..5e930c8 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -31,6 +31,7 @@
  Logan (Tzu-hsiang) Chien <loganchien@google.com>

  Stephen White <senorblanco@google.com>

  Raymond Chiu <chiur@google.com>

+ Shahbaz Youssefi <syoussefi@google.com>

 

 TransGaming Inc.

  Nicolas Capens

diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index 0a88948..6f6f276 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -552,6 +552,12 @@
 	        MAKE_VULKAN_DEVICE_ENTRY(vkGetDeviceGroupPresentCapabilitiesKHR),
 	        MAKE_VULKAN_DEVICE_ENTRY(vkGetDeviceGroupSurfacePresentModesKHR),
 	    } },
+	// VK_EXT_swapchain_maintenance1
+	{
+	    VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME,
+	    {
+	        MAKE_VULKAN_DEVICE_ENTRY(vkReleaseSwapchainImagesEXT),
+	    } },
 #endif
 
 #if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index a7b0b78..049ec97 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -395,6 +395,12 @@
 }
 
 template<typename T>
+static void getPhysicalDeviceSwapchainMaintenance1FeaturesKHR(T *features)
+{
+	features->swapchainMaintenance1 = VK_TRUE;
+}
+
+template<typename T>
 static void getPhysicalDeviceVulkan12Features(T *features)
 {
 	features->samplerMirrorClampToEdge = VK_TRUE;
@@ -634,6 +640,9 @@
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT:
 			getPhysicalDeviceGraphicsPipelineLibraryFeatures(reinterpret_cast<struct VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT *>(curExtension));
 			break;
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT:
+			getPhysicalDeviceSwapchainMaintenance1FeaturesKHR(reinterpret_cast<struct VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT *>(curExtension));
+			break;
 		case VK_STRUCTURE_TYPE_MAX_ENUM:  // TODO(b/176893525): This may not be legal. dEQP tests that this value is ignored.
 			break;
 		default:
@@ -1656,6 +1665,13 @@
 	return CheckFeature(requested, supported, graphicsPipelineLibrary);
 }
 
+bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT *requested) const
+{
+	auto supported = getSupportedFeatures(requested);
+
+	return CheckFeature(requested, supported, swapchainMaintenance1);
+}
+
 bool PhysicalDevice::hasExtendedFeatures(const VkPhysicalDeviceDescriptorIndexingFeatures *requested) const
 {
 	auto supported = getSupportedFeatures(requested);
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp
index 6bf6411..11e3d47 100644
--- a/src/Vulkan/VkPhysicalDevice.hpp
+++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -61,6 +61,7 @@
 	bool hasExtendedFeatures(const VkPhysicalDeviceBufferDeviceAddressFeatures *requested) const;
 	bool hasExtendedFeatures(const VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT *requested) const;
 	bool hasExtendedFeatures(const VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR *requested) const;
+	bool hasExtendedFeatures(const VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT *requested) const;
 
 	const VkPhysicalDeviceProperties &getProperties() const;
 	void getProperties(VkPhysicalDeviceIDProperties *properties) const;
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp
index c48fb49..c8fd79c 100644
--- a/src/Vulkan/VkQueue.cpp
+++ b/src/Vulkan/VkQueue.cpp
@@ -203,6 +203,8 @@
 		semaphore->wait();
 	}
 
+	const auto *presentFences = vk::GetExtendedStruct<VkSwapchainPresentFenceInfoEXT>(presentInfo->pNext, VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT);
+
 	VkResult commandResult = VK_SUCCESS;
 
 	for(uint32_t i = 0; i < presentInfo->swapchainCount; i++)
@@ -224,6 +226,12 @@
 				commandResult = perSwapchainResult;
 			}
 		}
+
+		// The wait semaphores and the swapchain are no longer accessed
+		if(presentFences)
+		{
+			vk::Cast(presentFences->pFences[i])->complete();
+		}
 	}
 
 	return commandResult;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index f8106f8..3a3c0ea 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -286,6 +286,7 @@
 	{ { VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_SPEC_VERSION } },
 #ifndef __ANDROID__
 	{ { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION } },
+	{ { VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION } },
 	{ { VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION } },
 #endif
 #ifdef VK_USE_PLATFORM_XCB_KHR
@@ -413,6 +414,9 @@
 	{ { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION } },
 	{ { VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME, VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION } },
 	{ { VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME, VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION } },
+#ifndef __ANDROID__
+	{ { VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION } },
+#endif
 	{ { VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME, VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION } },
 	{ { VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION } },
 	{ { VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION } },
@@ -1112,6 +1116,7 @@
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES:
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT:
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT:
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT:
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT:
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT:
 			break;
@@ -4652,6 +4657,14 @@
 	return vk::Cast(pAcquireInfo->swapchain)->getNextImage(pAcquireInfo->timeout, vk::DynamicCast<vk::BinarySemaphore>(pAcquireInfo->semaphore), vk::Cast(pAcquireInfo->fence), pImageIndex);
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo)
+{
+	TRACE("(VkDevice device = %p, const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo = %p",
+	      device, pReleaseInfo);
+
+	return vk::Cast(pReleaseInfo->swapchain)->releaseImages(pReleaseInfo->imageIndexCount, pReleaseInfo->pImageIndices);
+}
+
 VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities)
 {
 	TRACE("(VkDevice device = %p, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities = %p)",
diff --git a/src/Vulkan/vk_swiftshader.def b/src/Vulkan/vk_swiftshader.def
index 640a9f5..27354ef 100644
--- a/src/Vulkan/vk_swiftshader.def
+++ b/src/Vulkan/vk_swiftshader.def
@@ -151,6 +151,9 @@
 	vkGetPhysicalDeviceSurfaceCapabilities2KHR

 	vkGetPhysicalDeviceSurfaceFormats2KHR

 

+	; VK_EXT_swapchain_maintenance1

+	vkReleaseSwapchainImagesEXT

+

 	; VK_KHR_surface

 	vkGetPhysicalDeviceSurfacePresentModesKHR

 	vkCreateSwapchainKHR

diff --git a/src/Vulkan/vk_swiftshader.lds b/src/Vulkan/vk_swiftshader.lds
index 8652471..873e9cd 100644
--- a/src/Vulkan/vk_swiftshader.lds
+++ b/src/Vulkan/vk_swiftshader.lds
@@ -151,6 +151,9 @@
 	vkGetPhysicalDeviceSurfaceCapabilities2KHR;
 	vkGetPhysicalDeviceSurfaceFormats2KHR;
 
+	# VK_EXT_swapchain_maintenance1
+	vkReleaseSwapchainImagesEXT;
+
 	# VK_KHR_surface
 	vkGetPhysicalDeviceSurfacePresentModesKHR;
 	vkCreateSwapchainKHR;
diff --git a/src/WSI/DirectFBSurfaceEXT.cpp b/src/WSI/DirectFBSurfaceEXT.cpp
index c66d736..3f661a5 100644
--- a/src/WSI/DirectFBSurfaceEXT.cpp
+++ b/src/WSI/DirectFBSurfaceEXT.cpp
@@ -36,8 +36,6 @@
 
 VkResult DirectFBSurfaceEXT::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
 {
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
-
 	int width, height;
 	surface->GetSize(surface, &width, &height);
 	VkExtent2D extent = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
@@ -45,6 +43,8 @@
 	pSurfaceCapabilities->currentExtent = extent;
 	pSurfaceCapabilities->minImageExtent = extent;
 	pSurfaceCapabilities->maxImageExtent = extent;
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	return VK_SUCCESS;
 }
 
diff --git a/src/WSI/DisplaySurfaceKHR.cpp b/src/WSI/DisplaySurfaceKHR.cpp
index 8d05bc1..71d7f21 100644
--- a/src/WSI/DisplaySurfaceKHR.cpp
+++ b/src/WSI/DisplaySurfaceKHR.cpp
@@ -276,13 +276,13 @@
 
 VkResult DisplaySurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
 {
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
-
 	VkExtent2D extent = { width, height };
 
 	pSurfaceCapabilities->currentExtent = extent;
 	pSurfaceCapabilities->minImageExtent = extent;
 	pSurfaceCapabilities->maxImageExtent = extent;
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	return VK_SUCCESS;
 }
 
diff --git a/src/WSI/HeadlessSurfaceKHR.cpp b/src/WSI/HeadlessSurfaceKHR.cpp
index 9de6c96..a3d46ea 100644
--- a/src/WSI/HeadlessSurfaceKHR.cpp
+++ b/src/WSI/HeadlessSurfaceKHR.cpp
@@ -31,10 +31,11 @@
 
 VkResult HeadlessSurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
 {
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	pSurfaceCapabilities->currentExtent = { 1280, 720 };
 	pSurfaceCapabilities->minImageExtent = { 0, 0 };
 	pSurfaceCapabilities->maxImageExtent = { 3840, 2160 };
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	return VK_SUCCESS;
 }
 
diff --git a/src/WSI/MetalSurface.mm b/src/WSI/MetalSurface.mm
index 5d65f9b..83d3bf7 100644
--- a/src/WSI/MetalSurface.mm
+++ b/src/WSI/MetalSurface.mm
@@ -149,9 +149,6 @@
                                               void *pSurfaceCapabilitiesPNext) const
     API_AVAILABLE(macosx(10.11))
 {
-    setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities,
-                                 pSurfaceCapabilitiesPNext);
-
     // The value of drawableSize in CAMetalLayer is set the first time a drawable is queried but after that it is the
     // (Metal) application's responsibility to resize the drawable when the window is resized. The best time for Swiftshader
     // to resize the drawable is when querying the capabilities of the swapchain as that's done when the Vulkan application
@@ -160,7 +157,10 @@
     pSurfaceCapabilities->currentExtent = extent;
     pSurfaceCapabilities->minImageExtent = extent;
     pSurfaceCapabilities->maxImageExtent = extent;
-	return VK_SUCCESS;
+
+    setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities,
+                                 pSurfaceCapabilitiesPNext);
+    return VK_SUCCESS;
 }
 
 VkResult MetalSurface::present(PresentImage* image) API_AVAILABLE(macosx(10.11))
diff --git a/src/WSI/VkSurfaceKHR.cpp b/src/WSI/VkSurfaceKHR.cpp
index 07fcdb6..05989df 100644
--- a/src/WSI/VkSurfaceKHR.cpp
+++ b/src/WSI/VkSurfaceKHR.cpp
@@ -15,6 +15,7 @@
 #include "VkSurfaceKHR.hpp"
 
 #include "Vulkan/VkDestroy.hpp"
+#include "Vulkan/VkStringify.hpp"
 
 #include <algorithm>
 
@@ -199,6 +200,48 @@
 	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
 	    VK_IMAGE_USAGE_SAMPLED_BIT |
 	    VK_IMAGE_USAGE_STORAGE_BIT;
+
+	auto *extInfo = reinterpret_cast<VkBaseOutStructure *>(pSurfaceCapabilitiesPNext);
+	while(extInfo)
+	{
+		switch(extInfo->sType)
+		{
+		case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT:
+			{
+				// Supported scaling is per present mode, but currently that's identical for all present modes.
+				ASSERT(vk::GetExtendedStruct<VkSurfacePresentModeEXT>(pSurfaceInfoPNext, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT) != nullptr);
+				VkSurfacePresentScalingCapabilitiesEXT *presentScalingCapabilities = reinterpret_cast<VkSurfacePresentScalingCapabilitiesEXT *>(extInfo);
+				presentScalingCapabilities->supportedPresentScaling = 0;
+				presentScalingCapabilities->supportedPresentGravityX = 0;
+				presentScalingCapabilities->supportedPresentGravityY = 0;
+				presentScalingCapabilities->minScaledImageExtent = pSurfaceCapabilities->minImageExtent;
+				presentScalingCapabilities->maxScaledImageExtent = pSurfaceCapabilities->maxImageExtent;
+				break;
+			}
+		case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT:
+			{
+				VkSurfacePresentModeCompatibilityEXT *presentModeCompatibility = reinterpret_cast<VkSurfacePresentModeCompatibilityEXT *>(extInfo);
+				const auto *presentMode = vk::GetExtendedStruct<VkSurfacePresentModeEXT>(pSurfaceInfoPNext, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT);
+				ASSERT(presentMode != nullptr);
+
+				// No support for switching between present modes; i.e. each mode is only compatible with itself.
+				if(presentModeCompatibility->pPresentModes == nullptr)
+				{
+					presentModeCompatibility->presentModeCount = 1;
+				}
+				else if(presentModeCompatibility->presentModeCount >= 1)
+				{
+					presentModeCompatibility->pPresentModes[0] = presentMode->presentMode;
+					presentModeCompatibility->presentModeCount = 1;
+				}
+				break;
+			}
+		default:
+			UNSUPPORTED("pSurfaceCapabilities->pNext sType = %s", vk::Stringify(extInfo->sType).c_str());
+			break;
+		}
+		extInfo = extInfo->pNext;
+	}
 }
 
 }  // namespace vk
diff --git a/src/WSI/VkSwapchainKHR.cpp b/src/WSI/VkSwapchainKHR.cpp
index 803b5c8..8096902 100644
--- a/src/WSI/VkSwapchainKHR.cpp
+++ b/src/WSI/VkSwapchainKHR.cpp
@@ -219,6 +219,23 @@
 	auto &image = images[index];
 	image.setStatus(PRESENTING);
 	VkResult result = surface->present(&image);
+
+	releaseImage(index);
+	return result;
+}
+
+VkResult SwapchainKHR::releaseImages(uint32_t imageIndexCount, const uint32_t *pImageIndices)
+{
+	for(uint32_t i = 0; i < imageIndexCount; ++i)
+	{
+		releaseImage(pImageIndices[i]);
+	}
+	return VK_SUCCESS;
+}
+
+void SwapchainKHR::releaseImage(uint32_t index)
+{
+	auto &image = images[index];
 	image.setStatus(AVAILABLE);
 
 	if(retired)
@@ -227,8 +244,5 @@
 		image.release();
 		surface->releaseImageMemory(&image);
 	}
-
-	return result;
 }
-
-}  // namespace vk
\ No newline at end of file
+}  // namespace vk
diff --git a/src/WSI/VkSwapchainKHR.hpp b/src/WSI/VkSwapchainKHR.hpp
index 1c4a61e..dce79d8 100644
--- a/src/WSI/VkSwapchainKHR.hpp
+++ b/src/WSI/VkSwapchainKHR.hpp
@@ -47,7 +47,11 @@
 	VkResult present(uint32_t index);
 	const PresentImage &getImage(uint32_t imageIndex) { return images[imageIndex]; }
 
+	VkResult releaseImages(uint32_t imageIndexCount, const uint32_t *pImageIndices);
+
 private:
+	void releaseImage(uint32_t index);
+
 	SurfaceKHR *surface = nullptr;
 	PresentImage *images = nullptr;
 	uint32_t imageCount = 0;
diff --git a/src/WSI/WaylandSurfaceKHR.cpp b/src/WSI/WaylandSurfaceKHR.cpp
index ff3a373..5a7e7c0 100644
--- a/src/WSI/WaylandSurfaceKHR.cpp
+++ b/src/WSI/WaylandSurfaceKHR.cpp
@@ -64,11 +64,11 @@
 
 VkResult WaylandSurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
 {
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
-
 	pSurfaceCapabilities->currentExtent = { 0xFFFFFFFF, 0xFFFFFFFF };
 	pSurfaceCapabilities->minImageExtent = { 1, 1 };
 	pSurfaceCapabilities->maxImageExtent = { 0xFFFFFFFF, 0xFFFFFFFF };
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	return VK_SUCCESS;
 }
 
diff --git a/src/WSI/Win32SurfaceKHR.cpp b/src/WSI/Win32SurfaceKHR.cpp
index 2a1c79a..f4537c8 100644
--- a/src/WSI/Win32SurfaceKHR.cpp
+++ b/src/WSI/Win32SurfaceKHR.cpp
@@ -57,14 +57,14 @@
 
 VkResult Win32SurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
 {
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
-
 	VkExtent2D extent;
 	VkResult result = getWindowSize(hwnd, extent);
 	pSurfaceCapabilities->currentExtent = extent;
 	pSurfaceCapabilities->minImageExtent = extent;
 	pSurfaceCapabilities->maxImageExtent = extent;
-	return result;
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
+	return VK_SUCCESS;
 }
 
 void Win32SurfaceKHR::attachImage(PresentImage *image)
diff --git a/src/WSI/XcbSurfaceKHR.cpp b/src/WSI/XcbSurfaceKHR.cpp
index 6c2c9dc..c5a3d54 100644
--- a/src/WSI/XcbSurfaceKHR.cpp
+++ b/src/WSI/XcbSurfaceKHR.cpp
@@ -94,8 +94,6 @@
 		return VK_ERROR_SURFACE_LOST_KHR;
 	}
 
-	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
-
 	VkExtent2D extent;
 	int depth;
 	if(!getWindowSizeAndDepth(connection, window, &extent, &depth))
@@ -107,6 +105,8 @@
 	pSurfaceCapabilities->currentExtent = extent;
 	pSurfaceCapabilities->minImageExtent = extent;
 	pSurfaceCapabilities->maxImageExtent = extent;
+
+	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
 	return VK_SUCCESS;
 }