Update Vulkan CTS to version 1.0.2.3

New tests:

 * Add tests for VK_KHR_shared_presentable_image
 * Add tests for VK_KHR_get_surface_capabilities2

Fixes:

 * makeFramebufferWithoutAttachments creates invalid framebuffer
 * Fix typo in dE-IT.build_info.de_endianness_consistent name
 * Fix - uniform buffer incorrectly dereferenced
 * Use vkGetInstanceProcAddr(NULL) to load platform funcs
 * Imgtec Waiver for texture_gather*cube*depth32f*
 * Add VK_KHR_incremental_present to the list of allowed device
extensions
 * Use -std=c++03 with GCC and clang
 * Fix GCC 6.3 warnings in vulkan-cts-1.0.2
 * Improve check_build_sanity.py
 * Relax image verification in anisotropic filtering tests
 * Respect maxColorAttachments in image tests
 * Fix SPIR-V generation in dEQP-VK.spirv_assembly
 * Fix - depth/stencil images mandatory only for VK_IMAGE_TYPE_2D
 * Add missing barrier in ssbo layout tests

Bug: 38260702
Change-Id: I1c00d4b63c339ba69990b64a5bb225c661957e4c
diff --git a/Android.mk b/Android.mk
index 4e7bbcf..e567d55 100644
--- a/Android.mk
+++ b/Android.mk
@@ -911,6 +911,7 @@
 	external/vulkancts/modules/vulkan/vktTestPackageEntry.cpp \
 	external/vulkancts/modules/vulkan/wsi/vktWsiDisplayTimingTests.cpp \
 	external/vulkancts/modules/vulkan/wsi/vktWsiIncrementalPresentTests.cpp \
+	external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.cpp \
 	external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp \
 	external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp \
 	external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index 5e5dec4..d55ef55 100644
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
@@ -134314,7 +134314,9 @@
 dEQP-VK.wsi.android.surface.create_simulate_oom
 dEQP-VK.wsi.android.surface.query_support
 dEQP-VK.wsi.android.surface.query_capabilities
+dEQP-VK.wsi.android.surface.query_capabilities2
 dEQP-VK.wsi.android.surface.query_formats
+dEQP-VK.wsi.android.surface.query_formats2
 dEQP-VK.wsi.android.surface.query_present_modes
 dEQP-VK.wsi.android.surface.destroy_null_handle
 dEQP-VK.wsi.android.surface.initial_size
@@ -134374,6 +134376,12 @@
 dEQP-VK.wsi.android.display_timing.immediate.display_timing
 dEQP-VK.wsi.android.display_timing.mailbox.reference
 dEQP-VK.wsi.android.display_timing.mailbox.display_timing
+dEQP-VK.wsi.android.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_none.continuous
+dEQP-VK.wsi.android.shared_presentable_image.scale_up.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_up.continuous
+dEQP-VK.wsi.android.shared_presentable_image.scale_down.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_down.continuous
 dEQP-VK.synchronization.smoke.fences
 dEQP-VK.synchronization.smoke.semaphores
 dEQP-VK.synchronization.smoke.events
diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
index 10f155e..aad3052 100644
--- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl
@@ -173,6 +173,7 @@
 	VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT									= 1000061000,
 	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR		= 1000080000,
 	VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR									= 1000084000,
+	VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR				= 1000111000,
 	VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR			= 1000085000,
 	VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX							= 1000086000,
 	VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX				= 1000086001,
@@ -181,6 +182,9 @@
 	VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX					= 1000086004,
 	VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX				= 1000086005,
 	VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE								= 1000092000,
+	VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR					= 1000119000,
+	VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR							= 1000119001,
+	VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR									= 1000119002,
 };
 
 enum VkSystemAllocationScope
@@ -455,6 +459,7 @@
 	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL				= 7,
 	VK_IMAGE_LAYOUT_PREINITIALIZED						= 8,
 	VK_IMAGE_LAYOUT_PRESENT_SRC_KHR						= 1000001002,
+	VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR					= 1000111000,
 };
 
 enum VkImageViewType
@@ -750,12 +755,12 @@
 
 enum VkPresentModeKHR
 {
-	VK_PRESENT_MODE_IMMEDIATE_KHR		= 0,
-	VK_PRESENT_MODE_MAILBOX_KHR			= 1,
-	VK_PRESENT_MODE_FIFO_KHR			= 2,
-	VK_PRESENT_MODE_FIFO_RELAXED_KHR	= 3,
-
-	VK_PRESENT_MODE_KHR_LAST
+	VK_PRESENT_MODE_IMMEDIATE_KHR					= 0,
+	VK_PRESENT_MODE_MAILBOX_KHR						= 1,
+	VK_PRESENT_MODE_FIFO_KHR						= 2,
+	VK_PRESENT_MODE_FIFO_RELAXED_KHR				= 3,
+	VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR		= 1000111000,
+	VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR	= 1000111001,
 };
 
 enum VkDebugReportObjectTypeEXT
diff --git a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
index 1976c3b..737ce24 100644
--- a/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
@@ -128,6 +128,7 @@
 virtual VkResult	queuePresentKHR									(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) const;
 virtual VkResult	createSharedSwapchainsKHR						(VkDevice device, deUint32 swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains) const;
 virtual void		trimCommandPoolKHR								(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags) const;
+virtual VkResult	getSwapchainStatusKHR							(VkDevice device, VkSwapchainKHR swapchain) const;
 virtual VkResult	debugMarkerSetObjectTagEXT						(VkDevice device, VkDebugMarkerObjectTagInfoEXT* pTagInfo) const;
 virtual VkResult	debugMarkerSetObjectNameEXT						(VkDevice device, VkDebugMarkerObjectNameInfoEXT* pNameInfo) const;
 virtual void		cmdDebugMarkerBeginEXT							(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT* pMarkerInfo) const;
diff --git a/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl b/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
index a4e8a08..1651e83 100644
--- a/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkConcreteInstanceInterface.inl
@@ -44,6 +44,8 @@
 virtual void				getPhysicalDeviceQueueFamilyProperties2KHR			(VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties) const;
 virtual void				getPhysicalDeviceMemoryProperties2KHR				(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties) const;
 virtual void				getPhysicalDeviceSparseImageFormatProperties2KHR	(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, deUint32* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties) const;
+virtual VkResult			getPhysicalDeviceSurfaceCapabilities2KHR			(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities) const;
+virtual VkResult			getPhysicalDeviceSurfaceFormats2KHR					(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats) const;
 virtual VkResult			createDebugReportCallbackEXT						(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) const;
 virtual void				destroyDebugReportCallbackEXT						(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) const;
 virtual void				debugReportMessageEXT								(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, deUint64 object, deUintptr location, deInt32 messageCode, const char* pLayerPrefix, const char* pMessage) const;
diff --git a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
index adc39d8..bc88896 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
@@ -637,6 +637,11 @@
 	m_vk.trimCommandPoolKHR(device, commandPool, flags);
 }
 
+VkResult DeviceDriver::getSwapchainStatusKHR (VkDevice device, VkSwapchainKHR swapchain) const
+{
+	return m_vk.getSwapchainStatusKHR(device, swapchain);
+}
+
 VkResult DeviceDriver::debugMarkerSetObjectTagEXT (VkDevice device, VkDebugMarkerObjectTagInfoEXT* pTagInfo) const
 {
 	return m_vk.debugMarkerSetObjectTagEXT(device, pTagInfo);
diff --git a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
index 7077438..b929b0f 100644
--- a/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
@@ -128,6 +128,7 @@
 QueuePresentKHRFunc									queuePresentKHR;
 CreateSharedSwapchainsKHRFunc						createSharedSwapchainsKHR;
 TrimCommandPoolKHRFunc								trimCommandPoolKHR;
+GetSwapchainStatusKHRFunc							getSwapchainStatusKHR;
 DebugMarkerSetObjectTagEXTFunc						debugMarkerSetObjectTagEXT;
 DebugMarkerSetObjectNameEXTFunc						debugMarkerSetObjectNameEXT;
 CmdDebugMarkerBeginEXTFunc							cmdDebugMarkerBeginEXT;
diff --git a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
index 1819371..ffc439a 100644
--- a/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
@@ -175,6 +175,9 @@
 typedef VKAPI_ATTR void					(VKAPI_CALL* GetPhysicalDeviceMemoryProperties2KHRFunc)				(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
 typedef VKAPI_ATTR void					(VKAPI_CALL* GetPhysicalDeviceSparseImageFormatProperties2KHRFunc)	(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, deUint32* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
 typedef VKAPI_ATTR void					(VKAPI_CALL* TrimCommandPoolKHRFunc)								(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetPhysicalDeviceSurfaceCapabilities2KHRFunc)			(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetPhysicalDeviceSurfaceFormats2KHRFunc)				(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+typedef VKAPI_ATTR VkResult				(VKAPI_CALL* GetSwapchainStatusKHRFunc)								(VkDevice device, VkSwapchainKHR swapchain);
 typedef VKAPI_ATTR VkResult				(VKAPI_CALL* CreateDebugReportCallbackEXTFunc)						(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
 typedef VKAPI_ATTR void					(VKAPI_CALL* DestroyDebugReportCallbackEXTFunc)						(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
 typedef VKAPI_ATTR void					(VKAPI_CALL* DebugReportMessageEXTFunc)								(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, deUint64 object, deUintptr location, deInt32 messageCode, const char* pLayerPrefix, const char* pMessage);
diff --git a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
index c6755a4..25309f1 100644
--- a/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
@@ -128,6 +128,7 @@
 m_vk.queuePresentKHR									= (QueuePresentKHRFunc)									GET_PROC_ADDR("vkQueuePresentKHR");
 m_vk.createSharedSwapchainsKHR							= (CreateSharedSwapchainsKHRFunc)						GET_PROC_ADDR("vkCreateSharedSwapchainsKHR");
 m_vk.trimCommandPoolKHR									= (TrimCommandPoolKHRFunc)								GET_PROC_ADDR("vkTrimCommandPoolKHR");
+m_vk.getSwapchainStatusKHR								= (GetSwapchainStatusKHRFunc)							GET_PROC_ADDR("vkGetSwapchainStatusKHR");
 m_vk.debugMarkerSetObjectTagEXT							= (DebugMarkerSetObjectTagEXTFunc)						GET_PROC_ADDR("vkDebugMarkerSetObjectTagEXT");
 m_vk.debugMarkerSetObjectNameEXT						= (DebugMarkerSetObjectNameEXTFunc)						GET_PROC_ADDR("vkDebugMarkerSetObjectNameEXT");
 m_vk.cmdDebugMarkerBeginEXT								= (CmdDebugMarkerBeginEXTFunc)							GET_PROC_ADDR("vkCmdDebugMarkerBeginEXT");
diff --git a/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
index 10ab1ae..a7c8d26 100644
--- a/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInitInstanceFunctionPointers.inl
@@ -44,6 +44,8 @@
 m_vk.getPhysicalDeviceQueueFamilyProperties2KHR			= (GetPhysicalDeviceQueueFamilyProperties2KHRFunc)			GET_PROC_ADDR("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
 m_vk.getPhysicalDeviceMemoryProperties2KHR				= (GetPhysicalDeviceMemoryProperties2KHRFunc)				GET_PROC_ADDR("vkGetPhysicalDeviceMemoryProperties2KHR");
 m_vk.getPhysicalDeviceSparseImageFormatProperties2KHR	= (GetPhysicalDeviceSparseImageFormatProperties2KHRFunc)	GET_PROC_ADDR("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+m_vk.getPhysicalDeviceSurfaceCapabilities2KHR			= (GetPhysicalDeviceSurfaceCapabilities2KHRFunc)			GET_PROC_ADDR("vkGetPhysicalDeviceSurfaceCapabilities2KHR");
+m_vk.getPhysicalDeviceSurfaceFormats2KHR				= (GetPhysicalDeviceSurfaceFormats2KHRFunc)					GET_PROC_ADDR("vkGetPhysicalDeviceSurfaceFormats2KHR");
 m_vk.createDebugReportCallbackEXT						= (CreateDebugReportCallbackEXTFunc)						GET_PROC_ADDR("vkCreateDebugReportCallbackEXT");
 m_vk.destroyDebugReportCallbackEXT						= (DestroyDebugReportCallbackEXTFunc)						GET_PROC_ADDR("vkDestroyDebugReportCallbackEXT");
 m_vk.debugReportMessageEXT								= (DebugReportMessageEXTFunc)								GET_PROC_ADDR("vkDebugReportMessageEXT");
diff --git a/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl b/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
index fb3d713..1922903 100644
--- a/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkInstanceDriverImpl.inl
@@ -217,6 +217,16 @@
 	m_vk.getPhysicalDeviceSparseImageFormatProperties2KHR(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
 }
 
+VkResult InstanceDriver::getPhysicalDeviceSurfaceCapabilities2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities) const
+{
+	return m_vk.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
+}
+
+VkResult InstanceDriver::getPhysicalDeviceSurfaceFormats2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats) const
+{
+	return m_vk.getPhysicalDeviceSurfaceFormats2KHR(physicalDevice, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
+}
+
 VkResult InstanceDriver::createDebugReportCallbackEXT (VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) const
 {
 	return m_vk.createDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
diff --git a/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl b/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
index 148b83f..fb44c96 100644
--- a/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
+++ b/external/vulkancts/framework/vulkan/vkInstanceFunctionPointers.inl
@@ -44,6 +44,8 @@
 GetPhysicalDeviceQueueFamilyProperties2KHRFunc			getPhysicalDeviceQueueFamilyProperties2KHR;
 GetPhysicalDeviceMemoryProperties2KHRFunc				getPhysicalDeviceMemoryProperties2KHR;
 GetPhysicalDeviceSparseImageFormatProperties2KHRFunc	getPhysicalDeviceSparseImageFormatProperties2KHR;
+GetPhysicalDeviceSurfaceCapabilities2KHRFunc			getPhysicalDeviceSurfaceCapabilities2KHR;
+GetPhysicalDeviceSurfaceFormats2KHRFunc					getPhysicalDeviceSurfaceFormats2KHR;
 CreateDebugReportCallbackEXTFunc						createDebugReportCallbackEXT;
 DestroyDebugReportCallbackEXTFunc						destroyDebugReportCallbackEXT;
 DebugReportMessageEXTFunc								debugReportMessageEXT;
diff --git a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
index d573957..063bac2 100644
--- a/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
@@ -1195,6 +1195,30 @@
 	DE_UNREF(flags);
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL getPhysicalDeviceSurfaceCapabilities2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
+{
+	DE_UNREF(physicalDevice);
+	DE_UNREF(pSurfaceInfo);
+	DE_UNREF(pSurfaceCapabilities);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL getPhysicalDeviceSurfaceFormats2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats)
+{
+	DE_UNREF(physicalDevice);
+	DE_UNREF(pSurfaceInfo);
+	DE_UNREF(pSurfaceFormatCount);
+	DE_UNREF(pSurfaceFormats);
+	return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL getSwapchainStatusKHR (VkDevice device, VkSwapchainKHR swapchain)
+{
+	DE_UNREF(device);
+	DE_UNREF(swapchain);
+	return VK_SUCCESS;
+}
+
 VKAPI_ATTR void VKAPI_CALL debugReportMessageEXT (VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, deUint64 object, deUintptr location, deInt32 messageCode, const char* pLayerPrefix, const char* pMessage)
 {
 	DE_UNREF(instance);
@@ -1418,6 +1442,8 @@
 	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceQueueFamilyProperties2KHR,		getPhysicalDeviceQueueFamilyProperties2KHR),
 	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceMemoryProperties2KHR,				getPhysicalDeviceMemoryProperties2KHR),
 	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceSparseImageFormatProperties2KHR,	getPhysicalDeviceSparseImageFormatProperties2KHR),
+	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceSurfaceCapabilities2KHR,			getPhysicalDeviceSurfaceCapabilities2KHR),
+	VK_NULL_FUNC_ENTRY(vkGetPhysicalDeviceSurfaceFormats2KHR,				getPhysicalDeviceSurfaceFormats2KHR),
 	VK_NULL_FUNC_ENTRY(vkCreateDebugReportCallbackEXT,						createDebugReportCallbackEXT),
 	VK_NULL_FUNC_ENTRY(vkDestroyDebugReportCallbackEXT,						destroyDebugReportCallbackEXT),
 	VK_NULL_FUNC_ENTRY(vkDebugReportMessageEXT,								debugReportMessageEXT),
@@ -1553,6 +1579,7 @@
 	VK_NULL_FUNC_ENTRY(vkQueuePresentKHR,									queuePresentKHR),
 	VK_NULL_FUNC_ENTRY(vkCreateSharedSwapchainsKHR,							createSharedSwapchainsKHR),
 	VK_NULL_FUNC_ENTRY(vkTrimCommandPoolKHR,								trimCommandPoolKHR),
+	VK_NULL_FUNC_ENTRY(vkGetSwapchainStatusKHR,								getSwapchainStatusKHR),
 	VK_NULL_FUNC_ENTRY(vkDebugMarkerSetObjectTagEXT,						debugMarkerSetObjectTagEXT),
 	VK_NULL_FUNC_ENTRY(vkDebugMarkerSetObjectNameEXT,						debugMarkerSetObjectNameEXT),
 	VK_NULL_FUNC_ENTRY(vkCmdDebugMarkerBeginEXT,							cmdDebugMarkerBeginEXT),
diff --git a/external/vulkancts/framework/vulkan/vkStrUtil.inl b/external/vulkancts/framework/vulkan/vkStrUtil.inl
index 41a4f63..ff6545a 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtil.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtil.inl
@@ -351,6 +351,10 @@
 std::ostream&	operator<<	(std::ostream& s, const VkRectLayerKHR& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPresentRegionKHR& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPresentRegionsKHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkPhysicalDeviceSurfaceInfo2KHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkSurfaceCapabilities2KHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkSurfaceFormat2KHR& value);
+std::ostream&	operator<<	(std::ostream& s, const VkSharedPresentSurfaceCapabilitiesKHR& value);
 std::ostream&	operator<<	(std::ostream& s, const VkDebugReportCallbackCreateInfoEXT& value);
 std::ostream&	operator<<	(std::ostream& s, const VkPipelineRasterizationStateRasterizationOrderAMD& value);
 std::ostream&	operator<<	(std::ostream& s, const VkDebugMarkerObjectNameInfoEXT& value);
diff --git a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
index 05d23ce..36e8648 100644
--- a/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
+++ b/external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
@@ -186,6 +186,7 @@
 		case VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT:									return "VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT";
 		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR:			return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR";
 		case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:										return "VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR";
+		case VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR:					return "VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR";
 		case VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR:				return "VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR";
 		case VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX:							return "VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX";
 		case VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX:				return "VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX";
@@ -194,6 +195,9 @@
 		case VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX:					return "VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX";
 		case VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX:					return "VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX";
 		case VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE:								return "VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE";
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR:						return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR";
+		case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR:								return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR";
+		case VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR:									return "VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR";
 		default:																		return DE_NULL;
 	}
 }
@@ -490,6 +494,7 @@
 		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:				return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL";
 		case VK_IMAGE_LAYOUT_PREINITIALIZED:					return "VK_IMAGE_LAYOUT_PREINITIALIZED";
 		case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:					return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR";
+		case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:				return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
 		default:												return DE_NULL;
 	}
 }
@@ -841,11 +846,13 @@
 {
 	switch (value)
 	{
-		case VK_PRESENT_MODE_IMMEDIATE_KHR:		return "VK_PRESENT_MODE_IMMEDIATE_KHR";
-		case VK_PRESENT_MODE_MAILBOX_KHR:		return "VK_PRESENT_MODE_MAILBOX_KHR";
-		case VK_PRESENT_MODE_FIFO_KHR:			return "VK_PRESENT_MODE_FIFO_KHR";
-		case VK_PRESENT_MODE_FIFO_RELAXED_KHR:	return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
-		default:								return DE_NULL;
+		case VK_PRESENT_MODE_IMMEDIATE_KHR:					return "VK_PRESENT_MODE_IMMEDIATE_KHR";
+		case VK_PRESENT_MODE_MAILBOX_KHR:					return "VK_PRESENT_MODE_MAILBOX_KHR";
+		case VK_PRESENT_MODE_FIFO_KHR:						return "VK_PRESENT_MODE_FIFO_KHR";
+		case VK_PRESENT_MODE_FIFO_RELAXED_KHR:				return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
+		case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR:		return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR";
+		case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR:	return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR";
+		default:											return DE_NULL;
 	}
 }
 
@@ -3508,6 +3515,46 @@
 	return s;
 }
 
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceSurfaceInfo2KHR& value)
+{
+	s << "VkPhysicalDeviceSurfaceInfo2KHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsurface = " << value.surface << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSurfaceCapabilities2KHR& value)
+{
+	s << "VkSurfaceCapabilities2KHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsurfaceCapabilities = " << value.surfaceCapabilities << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSurfaceFormat2KHR& value)
+{
+	s << "VkSurfaceFormat2KHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsurfaceFormat = " << value.surfaceFormat << '\n';
+	s << '}';
+	return s;
+}
+
+std::ostream& operator<< (std::ostream& s, const VkSharedPresentSurfaceCapabilitiesKHR& value)
+{
+	s << "VkSharedPresentSurfaceCapabilitiesKHR = {\n";
+	s << "\tsType = " << value.sType << '\n';
+	s << "\tpNext = " << value.pNext << '\n';
+	s << "\tsharedPresentSupportedUsageFlags = " << getImageUsageFlagsStr(value.sharedPresentSupportedUsageFlags) << '\n';
+	s << '}';
+	return s;
+}
+
 std::ostream& operator<< (std::ostream& s, const VkDebugReportCallbackCreateInfoEXT& value)
 {
 	s << "VkDebugReportCallbackCreateInfoEXT = {\n";
diff --git a/external/vulkancts/framework/vulkan/vkStructTypes.inl b/external/vulkancts/framework/vulkan/vkStructTypes.inl
index 4f57e6d..9f8ede6 100644
--- a/external/vulkancts/framework/vulkan/vkStructTypes.inl
+++ b/external/vulkancts/framework/vulkan/vkStructTypes.inl
@@ -1455,6 +1455,34 @@
 	const VkPresentRegionKHR*	pRegions;
 };
 
+struct VkPhysicalDeviceSurfaceInfo2KHR
+{
+	VkStructureType	sType;
+	const void*		pNext;
+	VkSurfaceKHR	surface;
+};
+
+struct VkSurfaceCapabilities2KHR
+{
+	VkStructureType				sType;
+	void*						pNext;
+	VkSurfaceCapabilitiesKHR	surfaceCapabilities;
+};
+
+struct VkSurfaceFormat2KHR
+{
+	VkStructureType		sType;
+	void*				pNext;
+	VkSurfaceFormatKHR	surfaceFormat;
+};
+
+struct VkSharedPresentSurfaceCapabilitiesKHR
+{
+	VkStructureType		sType;
+	void*				pNext;
+	VkImageUsageFlags	sharedPresentSupportedUsageFlags;
+};
+
 struct VkDebugReportCallbackCreateInfoEXT
 {
 	VkStructureType					sType;
diff --git a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
index 53a1040..51e8653 100644
--- a/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
@@ -128,6 +128,7 @@
 virtual VkResult	queuePresentKHR									(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) const = 0;
 virtual VkResult	createSharedSwapchainsKHR						(VkDevice device, deUint32 swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains) const = 0;
 virtual void		trimCommandPoolKHR								(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags) const = 0;
+virtual VkResult	getSwapchainStatusKHR							(VkDevice device, VkSwapchainKHR swapchain) const = 0;
 virtual VkResult	debugMarkerSetObjectTagEXT						(VkDevice device, VkDebugMarkerObjectTagInfoEXT* pTagInfo) const = 0;
 virtual VkResult	debugMarkerSetObjectNameEXT						(VkDevice device, VkDebugMarkerObjectNameInfoEXT* pNameInfo) const = 0;
 virtual void		cmdDebugMarkerBeginEXT							(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT* pMarkerInfo) const = 0;
diff --git a/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl b/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
index 1793be0..e168a07 100644
--- a/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
+++ b/external/vulkancts/framework/vulkan/vkVirtualInstanceInterface.inl
@@ -44,6 +44,8 @@
 virtual void				getPhysicalDeviceQueueFamilyProperties2KHR			(VkPhysicalDevice physicalDevice, deUint32* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties) const = 0;
 virtual void				getPhysicalDeviceMemoryProperties2KHR				(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties) const = 0;
 virtual void				getPhysicalDeviceSparseImageFormatProperties2KHR	(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, deUint32* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties) const = 0;
+virtual VkResult			getPhysicalDeviceSurfaceCapabilities2KHR			(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities) const = 0;
+virtual VkResult			getPhysicalDeviceSurfaceFormats2KHR					(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats) const = 0;
 virtual VkResult			createDebugReportCallbackEXT						(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) const = 0;
 virtual void				destroyDebugReportCallbackEXT						(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) const = 0;
 virtual void				debugReportMessageEXT								(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, deUint64 object, deUintptr location, deInt32 messageCode, const char* pLayerPrefix, const char* pMessage) const = 0;
diff --git a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
index 05efbad..9fdc29f 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
@@ -656,6 +656,7 @@
 		"VK_KHR_xcb_surface",
 		"VK_KHR_xlib_surface",
 		"VK_KHR_get_physical_device_properties2",
+		"VK_KHR_get_surface_capabilities2",
 	};
 
 	checkKhrExtensions(results, extensions, DE_LENGTH_OF_ARRAY(s_allowedInstanceKhrExtensions), s_allowedInstanceKhrExtensions);
@@ -674,6 +675,7 @@
 		"VK_KHR_push_descriptor",
 		"VK_KHR_descriptor_update_template",
 		"VK_KHR_incremental_present",
+		"VK_KHR_shared_presentable_image",
 	};
 
 	checkKhrExtensions(results, extensions, DE_LENGTH_OF_ARRAY(s_allowedDeviceKhrExtensions), s_allowedDeviceKhrExtensions);
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
index ecfab5a..7e59f2b 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
@@ -441,45 +441,6 @@
 	return createRenderPass(vk, device, &renderPassInfo);
 }
 
-Move<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface&	vk,
-													 const VkDevice			device)
-{
-	const VkAttachmentReference unusedAttachment =
-	{
-		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
-		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
-	};
-
-	const VkSubpassDescription subpassDescription =
-	{
-		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
-		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
-		0u,													// deUint32							inputAttachmentCount;
-		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
-		0u,													// deUint32							colorAttachmentCount;
-		DE_NULL,											// const VkAttachmentReference*		pColorAttachments;
-		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
-		&unusedAttachment,									// const VkAttachmentReference*		pDepthStencilAttachment;
-		0u,													// deUint32							preserveAttachmentCount;
-		DE_NULL												// const deUint32*					pPreserveAttachments;
-	};
-
-	const VkRenderPassCreateInfo renderPassInfo =
-	{
-		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
-		DE_NULL,											// const void*						pNext;
-		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
-		0u,													// deUint32							attachmentCount;
-		DE_NULL,											// const VkAttachmentDescription*	pAttachments;
-		1u,													// deUint32							subpassCount;
-		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
-		0u,													// deUint32							dependencyCount;
-		DE_NULL												// const VkSubpassDependency*		pDependencies;
-	};
-
-	return createRenderPass(vk, device, &renderPassInfo);
-}
-
 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
 									 const VkDevice				device,
 									 const VkRenderPass			renderPass,
@@ -503,25 +464,6 @@
 	return createFramebuffer(vk, device, &framebufferInfo);
 }
 
-Move<VkFramebuffer> makeFramebufferWithoutAttachments (const DeviceInterface&		vk,
-													   const VkDevice				device,
-													   const VkRenderPass			renderPass)
-{
-	const VkFramebufferCreateInfo framebufferInfo = {
-		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
-		DE_NULL,										// const void*                                 pNext;
-		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
-		renderPass,										// VkRenderPass                                renderPass;
-		0u,												// uint32_t                                    attachmentCount;
-		DE_NULL,										// const VkImageView*                          pAttachments;
-		0u,												// uint32_t                                    width;
-		0u,												// uint32_t                                    height;
-		0u,												// uint32_t                                    layers;
-	};
-
-	return createFramebuffer(vk, device, &framebufferInfo);
-}
-
 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
 															 const VkDevice					device,
 															 const VkShaderStageFlagBits	stage,
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
index 79e352d..49feef5 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
@@ -220,9 +220,7 @@
 vk::Move<vk::VkPipelineLayout>	makePipelineLayoutWithoutDescriptors		(const vk::DeviceInterface& vk, const vk::VkDevice device);
 vk::Move<vk::VkPipeline>		makeComputePipeline							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkShaderModule shaderModule, const vk::VkSpecializationInfo* specInfo, PipelineCacheData& pipelineCacheData);
 vk::Move<vk::VkRenderPass>		makeRenderPass								(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkFormat colorFormat);
-vk::Move<vk::VkRenderPass>		makeRenderPassWithoutAttachments			(const vk::DeviceInterface& vk, const vk::VkDevice device);
 vk::Move<vk::VkFramebuffer>		makeFramebuffer								(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass, const vk::VkImageView colorAttachment, const deUint32 width, const deUint32 height, const deUint32 layers);
-vk::Move<vk::VkFramebuffer>		makeFramebufferWithoutAttachments			(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass);
 vk::Move<vk::VkImageView>		makeImageView								(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkImage image, const vk::VkImageViewType viewType, const vk::VkFormat format, const vk::VkImageSubresourceRange subresourceRange);
 vk::Move<vk::VkEvent>			makeEvent									(const vk::DeviceInterface& vk, const vk::VkDevice device);
 vk::VkBufferImageCopy			makeBufferImageCopy							(const vk::VkImageSubresourceLayers subresourceLayers, const vk::VkExtent3D extent);
diff --git a/external/vulkancts/modules/vulkan/tessellation/vktTessellationUtil.cpp b/external/vulkancts/modules/vulkan/tessellation/vktTessellationUtil.cpp
index 58f6c96..c7c8edc 100644
--- a/external/vulkancts/modules/vulkan/tessellation/vktTessellationUtil.cpp
+++ b/external/vulkancts/modules/vulkan/tessellation/vktTessellationUtil.cpp
@@ -482,9 +482,9 @@
 		renderPass,										// VkRenderPass                                renderPass;
 		0u,												// uint32_t                                    attachmentCount;
 		DE_NULL,										// const VkImageView*                          pAttachments;
-		0u,												// uint32_t                                    width;
-		0u,												// uint32_t                                    height;
-		0u,												// uint32_t                                    layers;
+		1u,												// uint32_t                                    width;
+		1u,												// uint32_t                                    height;
+		1u,												// uint32_t                                    layers;
 	};
 
 	return createFramebuffer(vk, device, &framebufferInfo);
diff --git a/external/vulkancts/modules/vulkan/wsi/CMakeLists.txt b/external/vulkancts/modules/vulkan/wsi/CMakeLists.txt
index a565b31..a010a31 100644
--- a/external/vulkancts/modules/vulkan/wsi/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/wsi/CMakeLists.txt
@@ -13,6 +13,8 @@
 	vktWsiIncrementalPresentTests.hpp
 	vktWsiDisplayTimingTests.cpp
 	vktWsiDisplayTimingTests.hpp
+	vktWsiSharedPresentableImageTests.cpp
+	vktWsiSharedPresentableImageTests.hpp
 	)
 
 set(DEQP_VK_WSI_LIBS
diff --git a/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.cpp b/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.cpp
new file mode 100644
index 0000000..d3b4239
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.cpp
@@ -0,0 +1,1367 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for shared presentable image extension
+ *//*--------------------------------------------------------------------*/
+
+#include "vktWsiSharedPresentableImageTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+#include "vkRefUtil.hpp"
+#include "vkWsiPlatform.hpp"
+#include "vkWsiUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkPrograms.hpp"
+
+#include "vkWsiUtil.hpp"
+
+#include "tcuPlatform.hpp"
+#include "tcuResultCollector.hpp"
+
+#include <vector>
+#include <string>
+
+using std::vector;
+using std::string;
+
+using tcu::Maybe;
+using tcu::UVec2;
+using tcu::TestLog;
+
+namespace vkt
+{
+namespace wsi
+{
+namespace
+{
+enum Scaling
+{
+	SCALING_NONE,
+	SCALING_UP,
+	SCALING_DOWN
+};
+
+typedef vector<vk::VkExtensionProperties> Extensions;
+
+void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
+{
+	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
+		 requiredExtName != requiredExtensions.end();
+		 ++requiredExtName)
+	{
+		if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
+			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
+	}
+}
+
+vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface&		vkp,
+												const Extensions&					supportedExtensions,
+												vk::wsi::Type						wsiType)
+{
+	vector<string>	extensions;
+
+	extensions.push_back("VK_KHR_surface");
+	extensions.push_back("VK_KHR_get_surface_capabilities2");
+	// Required for device extension to expose new physical device bits (in this
+	// case, presentation mode enums)
+	extensions.push_back("VK_KHR_get_physical_device_properties2");
+	extensions.push_back(getExtensionName(wsiType));
+
+	checkAllSupported(supportedExtensions, extensions);
+
+	return vk::createDefaultInstance(vkp, vector<string>(), extensions);
+}
+
+vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
+{
+	vk::VkPhysicalDeviceFeatures features;
+	deMemset(&features, 0, sizeof(features));
+	return features;
+}
+
+deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
+{
+	deUint32	numFamilies		= 0;
+
+	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
+
+	return numFamilies;
+}
+
+vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
+{
+	const deUint32		numTotalFamilyIndices	= getNumQueueFamilyIndices(vki, physicalDevice);
+	vector<deUint32>	supportedFamilyIndices;
+
+	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
+	{
+		if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
+			supportedFamilyIndices.push_back(queueFamilyNdx);
+	}
+
+	return supportedFamilyIndices;
+}
+
+deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
+{
+	const vector<deUint32>	supportedFamilyIndices	= getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
+
+	if (supportedFamilyIndices.empty())
+		TCU_THROW(NotSupportedError, "Device doesn't support presentation");
+
+	return supportedFamilyIndices[0];
+}
+
+vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::InstanceInterface&		vki,
+											vk::VkPhysicalDevice				physicalDevice,
+											const Extensions&					supportedExtensions,
+											const deUint32						queueFamilyIndex,
+											bool								requiresSharedPresentableImage,
+											const vk::VkAllocationCallbacks*	pAllocator = DE_NULL)
+{
+	const float							queuePriorities[]	= { 1.0f };
+	const vk::VkDeviceQueueCreateInfo	queueInfos[]		=
+	{
+		{
+			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+			DE_NULL,
+			(vk::VkDeviceQueueCreateFlags)0,
+			queueFamilyIndex,
+			DE_LENGTH_OF_ARRAY(queuePriorities),
+			&queuePriorities[0]
+		}
+	};
+	const vk::VkPhysicalDeviceFeatures	features		= getDeviceNullFeatures();
+	const char* const					extensions[]	=
+	{
+		"VK_KHR_swapchain",
+		"VK_KHR_shared_presentable_image"
+	};
+
+	const vk::VkDeviceCreateInfo		deviceParams	=
+	{
+		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkDeviceCreateFlags)0,
+		DE_LENGTH_OF_ARRAY(queueInfos),
+		&queueInfos[0],
+		0u,
+		DE_NULL,
+		requiresSharedPresentableImage ? 2u : 1u,
+		DE_ARRAY_BEGIN(extensions),
+		&features
+	};
+
+	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
+	{
+		if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
+			TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
+	}
+
+	return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
+}
+
+de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform&	platform,
+											 const Extensions&		supportedExtensions,
+											 vk::wsi::Type			wsiType)
+{
+	try
+	{
+		return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
+	}
+	catch (const tcu::NotSupportedError& e)
+	{
+		if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
+		{
+			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
+			// must support creating native display & window for that WSI type.
+			throw tcu::TestError(e.getMessage());
+		}
+		else
+			throw;
+	}
+}
+
+de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
+{
+	try
+	{
+		return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
+	}
+	catch (const tcu::NotSupportedError& e)
+	{
+		// See createDisplay - assuming that wsi::Display was supported platform port
+		// should also support creating a window.
+		throw tcu::TestError(e.getMessage());
+	}
+}
+
+bool wsiTypeSupportsScaling (vk::wsi::Type wsiType)
+{
+	return vk::wsi::getPlatformProperties(wsiType).swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE;
+}
+
+vk::VkQueue getDeviceQueue (const vk::DeviceInterface& vkd, vk::VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)
+{
+	vk::VkQueue queue = (vk::VkQueue)0;
+	vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
+	return queue;
+}
+
+vk::Move<vk::VkSemaphore> createSemaphore (const vk::DeviceInterface&	vkd,
+										   vk::VkDevice					device)
+{
+	const vk::VkSemaphoreCreateInfo createInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+		DE_NULL,
+		0u
+	};
+	return vk::createSemaphore(vkd, device, &createInfo);
+}
+
+void initSemaphores (const vk::DeviceInterface&		vkd,
+					 vk::VkDevice					device,
+					 std::vector<vk::VkSemaphore>&	semaphores)
+{
+	for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
+		semaphores[ndx] = createSemaphore(vkd, device).disown();
+}
+
+void deinitSemaphores (const vk::DeviceInterface&	vkd,
+					 vk::VkDevice					device,
+					 std::vector<vk::VkSemaphore>&	semaphores)
+{
+	for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
+	{
+		if (semaphores[ndx] != (vk::VkSemaphore)0)
+			vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
+
+		semaphores[ndx] = (vk::VkSemaphore)0;
+	}
+
+	semaphores.clear();
+}
+
+vk::Move<vk::VkFence> createFence (const vk::DeviceInterface&	vkd,
+								   vk::VkDevice					device)
+{
+	const vk::VkFenceCreateInfo createInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+		DE_NULL,
+		0u
+	};
+	return vk::createFence(vkd, device, &createInfo);
+}
+
+void initFences (const vk::DeviceInterface&	vkd,
+				 vk::VkDevice				device,
+				 std::vector<vk::VkFence>&	fences)
+{
+	for (size_t ndx = 0; ndx < fences.size(); ndx++)
+		fences[ndx] = createFence(vkd, device).disown();
+}
+
+void deinitFences (const vk::DeviceInterface&	vkd,
+				   vk::VkDevice					device,
+				   std::vector<vk::VkFence>&	fences)
+{
+	for (size_t ndx = 0; ndx < fences.size(); ndx++)
+	{
+		if (fences[ndx] != (vk::VkFence)0)
+			vkd.destroyFence(device, fences[ndx], DE_NULL);
+
+		fences[ndx] = (vk::VkFence)0;
+	}
+
+	fences.clear();
+}
+
+void cmdRenderFrame (const vk::DeviceInterface&	vkd,
+					 vk::VkCommandBuffer		commandBuffer,
+					 vk::VkPipelineLayout		pipelineLayout,
+					 vk::VkPipeline				pipeline,
+					 size_t						frameNdx,
+					 deUint32					quadCount)
+{
+	const deUint32 frameNdxValue  =	(deUint32)frameNdx;
+
+	vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &frameNdxValue);
+	vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+	vkd.cmdDraw(commandBuffer, quadCount * 6u, 1u, 0u, 0u);
+}
+
+vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&	vkd,
+												   vk::VkDevice					device,
+												   vk::VkCommandPool			commandPool,
+												   vk::VkPipelineLayout			pipelineLayout,
+												   vk::VkRenderPass				renderPass,
+												   vk::VkFramebuffer			framebuffer,
+												   vk::VkPipeline				pipeline,
+												   size_t						frameNdx,
+												   deUint32						quadCount,
+												   deUint32						imageWidth,
+												   deUint32						imageHeight)
+{
+	const vk::VkCommandBufferAllocateInfo allocateInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+		DE_NULL,
+
+		commandPool,
+		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+		1
+	};
+	const vk::VkCommandBufferBeginInfo	beginInfo		=
+	{
+		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+		DE_NULL,
+		0u,
+		DE_NULL
+	};
+
+	vk::Move<vk::VkCommandBuffer>	commandBuffer	(vk::allocateCommandBuffer(vkd, device, &allocateInfo));
+	VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
+
+	{
+		const vk::VkClearValue			clearValue			= vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f);
+		const vk::VkRenderPassBeginInfo	renderPassBeginInfo	=
+		{
+			vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+			DE_NULL,
+
+			renderPass,
+			framebuffer,
+
+			{
+				{ (deInt32)0, (deInt32)0 },
+				{ imageWidth, imageHeight }
+			},
+			1u,
+			&clearValue
+		};
+		vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
+	}
+
+	cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, quadCount);
+
+	vkd.cmdEndRenderPass(*commandBuffer);
+
+	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
+	return commandBuffer;
+}
+
+void deinitCommandBuffers (const vk::DeviceInterface&			vkd,
+						   vk::VkDevice							device,
+						   vk::VkCommandPool					commandPool,
+						   std::vector<vk::VkCommandBuffer>&	commandBuffers)
+{
+	for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
+	{
+		if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
+			vkd.freeCommandBuffers(device, commandPool, 1u,  &commandBuffers[ndx]);
+
+		commandBuffers[ndx] = (vk::VkCommandBuffer)0;
+	}
+
+	commandBuffers.clear();
+}
+
+vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&	vkd,
+											   vk::VkDevice					device,
+											   deUint32						queueFamilyIndex)
+{
+	const vk::VkCommandPoolCreateInfo createInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+		DE_NULL,
+		0u,
+		queueFamilyIndex
+	};
+
+	return vk::createCommandPool(vkd, device, &createInfo);
+}
+
+vk::Move<vk::VkFramebuffer>	createFramebuffer (const vk::DeviceInterface&	vkd,
+											   vk::VkDevice					device,
+											   vk::VkRenderPass				renderPass,
+											   vk::VkImageView				imageView,
+											   deUint32						width,
+											   deUint32						height)
+{
+	const vk::VkFramebufferCreateInfo createInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+		DE_NULL,
+
+		0u,
+		renderPass,
+		1u,
+		&imageView,
+		width,
+		height,
+		1u
+	};
+
+	return vk::createFramebuffer(vkd, device, &createInfo);
+}
+
+vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface&	vkd,
+										   vk::VkDevice					device,
+										   vk::VkImage					image,
+										   vk::VkFormat					format)
+{
+	const vk::VkImageViewCreateInfo	createInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+		DE_NULL,
+
+		0u,
+		image,
+		vk::VK_IMAGE_VIEW_TYPE_2D,
+		format,
+		vk::makeComponentMappingRGBA(),
+		{
+			vk::VK_IMAGE_ASPECT_COLOR_BIT,
+			0u,
+			1u,
+			0u,
+			1u
+		}
+	};
+
+	return vk::createImageView(vkd, device, &createInfo, DE_NULL);
+}
+
+vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface&	vkd,
+											 vk::VkDevice				device,
+											 vk::VkFormat				format)
+{
+	const vk::VkAttachmentDescription	attachments[]			=
+	{
+		{
+			0u,
+			format,
+			vk::VK_SAMPLE_COUNT_1_BIT,
+
+			vk::VK_ATTACHMENT_LOAD_OP_LOAD,
+			vk::VK_ATTACHMENT_STORE_OP_STORE,
+
+			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
+
+			// This differs from the usual layout handling in that the
+			// swapchain image remains in IMAGE_LAYOUT_SHARED_PRESENT_KHR all
+			// the time. We should not ever transition it away (or discard the
+			// contents with a transition from UNDEFINED) as the PE is accessing
+			// the image concurrently with our rendering.
+			vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+			vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
+		}
+	};
+	const vk::VkAttachmentReference		colorAttachmentRefs[]	=
+	{
+		{
+			0u,
+			vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
+		}
+	};
+	const vk::VkSubpassDescription		subpasses[]				=
+	{
+		{
+			0u,
+			vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
+			0u,
+			DE_NULL,
+
+			DE_LENGTH_OF_ARRAY(colorAttachmentRefs),
+			colorAttachmentRefs,
+			DE_NULL,
+
+			DE_NULL,
+			0u,
+			DE_NULL
+		}
+	};
+
+	const vk::VkRenderPassCreateInfo	createInfo				=
+	{
+		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+		DE_NULL,
+		0u,
+
+		DE_LENGTH_OF_ARRAY(attachments),
+		attachments,
+
+		DE_LENGTH_OF_ARRAY(subpasses),
+		subpasses,
+
+		0u,
+		DE_NULL
+	};
+
+	return vk::createRenderPass(vkd, device, &createInfo);
+}
+
+vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface&	vkd,
+										 vk::VkDevice				device,
+										 vk::VkRenderPass			renderPass,
+										 vk::VkPipelineLayout		layout,
+										 vk::VkShaderModule			vertexShaderModule,
+										 vk::VkShaderModule			fragmentShaderModule,
+										 deUint32					width,
+										 deUint32					height)
+{
+	const vk::VkSpecializationInfo				shaderSpecialization	=
+	{
+		0u,
+		DE_NULL,
+		0,
+		DE_NULL
+	};
+	const vk::VkPipelineShaderStageCreateInfo		stages[]			=
+	{
+		{
+			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+			DE_NULL,
+			0u,
+			vk::VK_SHADER_STAGE_VERTEX_BIT,
+			vertexShaderModule,
+			"main",
+			&shaderSpecialization
+		},
+		{
+			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+			DE_NULL,
+			0u,
+			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+			fragmentShaderModule,
+			"main",
+			&shaderSpecialization
+		}
+	};
+	const vk::VkPipelineVertexInputStateCreateInfo	vertexInputState	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+		0u,
+		DE_NULL,
+		0u,
+		DE_NULL
+	};
+	const vk::VkPipelineInputAssemblyStateCreateInfo	inputAssemblyState	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+		VK_FALSE
+	};
+	const vk::VkViewport viewports[] =
+	{
+		{
+			0.0f, 0.0f,
+			(float)width, (float)height,
+			0.0f, 1.0f
+		}
+	};
+	const vk::VkRect2D scissors[] =
+	{
+		{
+			{ 0u, 0u },
+			{ width, height }
+		}
+	};
+	const vk::VkPipelineViewportStateCreateInfo			viewportState		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+
+		DE_LENGTH_OF_ARRAY(viewports),
+		viewports,
+		DE_LENGTH_OF_ARRAY(scissors),
+		scissors
+	};
+	const vk::VkPipelineRasterizationStateCreateInfo	rasterizationState	=
+	{
+		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+		DE_NULL,
+		0u,
+		VK_TRUE,
+		VK_FALSE,
+		vk::VK_POLYGON_MODE_FILL,
+		vk::VK_CULL_MODE_NONE,
+		vk::VK_FRONT_FACE_CLOCKWISE,
+		VK_FALSE,
+		0.0f,
+		0.0f,
+		0.0f,
+		1.0f
+	};
+	const vk::VkSampleMask								sampleMask			= ~0u;
+	const vk::VkPipelineMultisampleStateCreateInfo		multisampleState	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+		vk::VK_SAMPLE_COUNT_1_BIT,
+		VK_FALSE,
+		0.0f,
+		&sampleMask,
+		VK_FALSE,
+		VK_FALSE
+	};
+	const vk::VkPipelineDepthStencilStateCreateInfo	depthStencilState		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+		DE_FALSE,
+		DE_FALSE,
+		vk::VK_COMPARE_OP_ALWAYS,
+		DE_FALSE,
+		DE_FALSE,
+		{
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_COMPARE_OP_ALWAYS,
+			0u,
+			0u,
+			0u,
+		},
+		{
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_STENCIL_OP_KEEP,
+			vk::VK_COMPARE_OP_ALWAYS,
+			0u,
+			0u,
+			0u,
+		},
+		0.0f,
+		1.0f
+	};
+	const vk::VkPipelineColorBlendAttachmentState	attachmentBlendState			=
+	{
+		VK_FALSE,
+		vk::VK_BLEND_FACTOR_ONE,
+		vk::VK_BLEND_FACTOR_ZERO,
+		vk::VK_BLEND_OP_ADD,
+		vk::VK_BLEND_FACTOR_ONE,
+		vk::VK_BLEND_FACTOR_ZERO,
+		vk::VK_BLEND_OP_ADD,
+		(vk::VK_COLOR_COMPONENT_R_BIT|
+		 vk::VK_COLOR_COMPONENT_G_BIT|
+		 vk::VK_COLOR_COMPONENT_B_BIT|
+		 vk::VK_COLOR_COMPONENT_A_BIT),
+	};
+	const vk::VkPipelineColorBlendStateCreateInfo	blendState				=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+		DE_FALSE,
+		vk::VK_LOGIC_OP_COPY,
+		1u,
+		&attachmentBlendState,
+		{ 0.0f, 0.0f, 0.0f, 0.0f }
+	};
+	const vk::VkDynamicState							dynamicStates[]		=
+	{
+		vk::VK_DYNAMIC_STATE_SCISSOR
+	};
+	const vk::VkPipelineDynamicStateCreateInfo			dynamicState		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+		DE_NULL,
+		0u,
+
+		DE_LENGTH_OF_ARRAY(dynamicStates),
+		dynamicStates
+	};
+	const vk::VkGraphicsPipelineCreateInfo				createInfo			=
+	{
+		vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+		DE_NULL,
+		0u,
+
+		DE_LENGTH_OF_ARRAY(stages),
+		stages,
+		&vertexInputState,
+		&inputAssemblyState,
+		DE_NULL,
+		&viewportState,
+		&rasterizationState,
+		&multisampleState,
+		&depthStencilState,
+		&blendState,
+		&dynamicState,
+		layout,
+		renderPass,
+		0u,
+		DE_NULL,
+		0u
+	};
+
+	return vk::createGraphicsPipeline(vkd, device, DE_NULL,  &createInfo);
+}
+
+vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface&	vkd,
+													 vk::VkDevice				device)
+{
+	const vk::VkPushConstantRange			pushConstants[] =
+	{
+		{
+			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+			0u,
+			4u
+		}
+	};
+	const vk::VkPipelineLayoutCreateInfo	createInfo	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+		DE_NULL,
+		0u,
+
+		0u,
+		DE_NULL,
+
+		DE_LENGTH_OF_ARRAY(pushConstants),
+		pushConstants,
+	};
+
+	return vk::createPipelineLayout(vkd, device, &createInfo);
+}
+
+struct TestConfig
+{
+	vk::wsi::Type			wsiType;
+	Scaling					scaling;
+	bool					useSharedPresentableImage;
+	vk::VkPresentModeKHR	presentMode;
+};
+
+class SharedPresentableImageTestInstance : public TestInstance
+{
+public:
+													SharedPresentableImageTestInstance	(Context& context, const TestConfig& testConfig);
+													~SharedPresentableImageTestInstance	(void);
+
+	tcu::TestStatus									iterate								(void);
+
+private:
+	const TestConfig								m_testConfig;
+	const deUint32									m_quadCount;
+	const vk::PlatformInterface&					m_vkp;
+	const Extensions								m_instanceExtensions;
+	const vk::Unique<vk::VkInstance>				m_instance;
+	const vk::InstanceDriver						m_vki;
+	const vk::VkPhysicalDevice						m_physicalDevice;
+	const de::UniquePtr<vk::wsi::Display>			m_nativeDisplay;
+	const de::UniquePtr<vk::wsi::Window>			m_nativeWindow;
+	const vk::Unique<vk::VkSurfaceKHR>				m_surface;
+
+	const deUint32									m_queueFamilyIndex;
+	const Extensions								m_deviceExtensions;
+	const vk::Unique<vk::VkDevice>					m_device;
+	const vk::DeviceDriver							m_vkd;
+	const vk::VkQueue								m_queue;
+
+	const vk::Unique<vk::VkCommandPool>				m_commandPool;
+	const vk::Unique<vk::VkShaderModule>			m_vertexShaderModule;
+	const vk::Unique<vk::VkShaderModule>			m_fragmentShaderModule;
+	const vk::Unique<vk::VkPipelineLayout>			m_pipelineLayout;
+
+	vk::VkImageUsageFlags							m_supportedUsageFlags;
+	const vk::VkSurfaceCapabilitiesKHR				m_surfaceProperties;
+	const vector<vk::VkSurfaceFormatKHR>			m_surfaceFormats;
+	const vector<vk::VkPresentModeKHR>				m_presentModes;
+
+	tcu::ResultCollector							m_resultCollector;
+
+	vk::Move<vk::VkSwapchainKHR>					m_swapchain;
+	vk::VkImage										m_swapchainImage;			  // NOTE: not owning. lifetime managed by swapchain
+	vk::Move<vk::VkImageView>						m_swapchainImageView;
+	vk::Move<vk::VkFramebuffer>						m_framebuffer;
+
+	vk::Move<vk::VkRenderPass>						m_renderPass;
+	vk::Move<vk::VkPipeline>						m_pipeline;
+
+	std::vector<vk::VkCommandBuffer>				m_commandBuffers;
+	std::vector<vk::VkSemaphore>					m_renderSemaphores;
+	std::vector<vk::VkFence>						m_fences;
+
+	std::vector<vk::VkSwapchainCreateInfoKHR>		m_swapchainConfigs;
+	size_t											m_swapchainConfigNdx;
+
+	const size_t									m_frameCount;
+	size_t											m_frameNdx;
+
+	const size_t									m_maxOutOfDateCount;
+	size_t											m_outOfDateCount;
+
+	void											initSwapchainResources		(void);
+	void											deinitSwapchainResources	(void);
+	void											render						(void);
+};
+
+std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR						surface,
+																	deUint32								queueFamilyIndex,
+																	Scaling									scaling,
+																	const vk::VkSurfaceCapabilitiesKHR&		properties,
+																	const vector<vk::VkSurfaceFormatKHR>&	formats,
+																	const vector<vk::VkPresentModeKHR>&		presentModes,
+																	vk::VkPresentModeKHR					presentMode,
+																	vk::VkImageUsageFlags					supportedImageUsage)
+{
+	const deUint32							imageLayers			= 1u;
+	const vk::VkImageUsageFlags				imageUsage			= properties.supportedUsageFlags & supportedImageUsage;
+	const vk::VkBool32						clipped				= VK_FALSE;
+	vector<vk::VkSwapchainCreateInfoKHR>	createInfos;
+
+	const deUint32				imageWidth		= scaling == SCALING_NONE
+												? (properties.currentExtent.width != 0xFFFFFFFFu
+													? properties.currentExtent.width
+													: de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2)))
+												: (scaling == SCALING_UP
+													? de::max(31u, properties.minImageExtent.width)
+													: properties.maxImageExtent.width);
+	const deUint32				imageHeight		= scaling == SCALING_NONE
+												? (properties.currentExtent.height != 0xFFFFFFFFu
+													? properties.currentExtent.height
+													: de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2)))
+												: (scaling == SCALING_UP
+													? de::max(31u, properties.minImageExtent.height)
+													: properties.maxImageExtent.height);
+	const vk::VkExtent2D		imageSize		= { imageWidth, imageHeight };
+
+	{
+		size_t presentModeNdx;
+
+		for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
+		{
+			if (presentModes[presentModeNdx] == presentMode)
+				break;
+		}
+
+		if (presentModeNdx == presentModes.size())
+			TCU_THROW(NotSupportedError, "Present mode not supported");
+	}
+
+	for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
+	{
+		for (vk::VkSurfaceTransformFlagsKHR transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
+		{
+			if ((properties.supportedTransforms & transform) == 0)
+				continue;
+
+			for (vk::VkCompositeAlphaFlagsKHR alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
+			{
+				if ((alpha & properties.supportedCompositeAlpha) == 0)
+					continue;
+
+				const vk::VkSurfaceTransformFlagBitsKHR	preTransform	= (vk::VkSurfaceTransformFlagBitsKHR)transform;
+				const vk::VkCompositeAlphaFlagBitsKHR	compositeAlpha	= (vk::VkCompositeAlphaFlagBitsKHR)alpha;
+				const vk::VkFormat						imageFormat		= formats[formatNdx].format;
+				const vk::VkColorSpaceKHR				imageColorSpace	= formats[formatNdx].colorSpace;
+				const vk::VkSwapchainCreateInfoKHR		createInfo		=
+				{
+					vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+					DE_NULL,
+					0u,
+					surface,
+					1,														// Always 1 image for a shared presentable image swapchain.
+					imageFormat,
+					imageColorSpace,
+					imageSize,
+					imageLayers,
+					imageUsage,
+					vk::VK_SHARING_MODE_EXCLUSIVE,
+					1u,
+					&queueFamilyIndex,
+					preTransform,
+					compositeAlpha,
+					presentMode,
+					clipped,
+					(vk::VkSwapchainKHR)0
+				};
+
+				createInfos.push_back(createInfo);
+			}
+		}
+	}
+
+	return createInfos;
+}
+
+vk::VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const vk::InstanceInterface&	vki,
+																   vk::VkPhysicalDevice			physicalDevice,
+																   vk::VkSurfaceKHR				surface,
+																   vk::VkImageUsageFlags*		usage)
+{
+	const vk::VkPhysicalDeviceSurfaceInfo2KHR	info	=
+	{
+		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+		DE_NULL,
+
+		surface
+	};
+	vk::VkSharedPresentSurfaceCapabilitiesKHR	sharedCapabilities;
+	vk::VkSurfaceCapabilities2KHR				capabilities;
+
+	sharedCapabilities.sType	= vk::VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR;
+	sharedCapabilities.pNext	= DE_NULL;
+
+	capabilities.sType			= vk::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
+	capabilities.pNext			= &sharedCapabilities;
+
+	VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, &info, &capabilities));
+
+	TCU_CHECK(sharedCapabilities.sharedPresentSupportedUsageFlags & vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+	*usage = sharedCapabilities.sharedPresentSupportedUsageFlags;
+
+	return capabilities.surfaceCapabilities;
+}
+
+SharedPresentableImageTestInstance::SharedPresentableImageTestInstance (Context& context, const TestConfig& testConfig)
+	: TestInstance				(context)
+	, m_testConfig				(testConfig)
+	, m_quadCount				(16u)
+	, m_vkp						(context.getPlatformInterface())
+	, m_instanceExtensions		(vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
+	, m_instance				(createInstanceWithWsi(m_vkp, m_instanceExtensions, testConfig.wsiType))
+	, m_vki						(m_vkp, *m_instance)
+	, m_physicalDevice			(vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
+	, m_nativeDisplay			(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
+	, m_nativeWindow			(createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
+	, m_surface					(vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
+
+	, m_queueFamilyIndex		(chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
+	, m_deviceExtensions		(vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
+	, m_device					(createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useSharedPresentableImage))
+	, m_vkd						(m_vki, *m_device)
+	, m_queue					(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
+
+	, m_commandPool				(createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
+	, m_vertexShaderModule		(vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
+	, m_fragmentShaderModule	(vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
+	, m_pipelineLayout			(createPipelineLayout(m_vkd, *m_device))
+
+	, m_supportedUsageFlags		(0u)
+	, m_surfaceProperties		(getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface, &m_supportedUsageFlags))
+	, m_surfaceFormats			(vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
+	, m_presentModes			(vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
+
+	, m_swapchainConfigs		(generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, m_supportedUsageFlags))
+	, m_swapchainConfigNdx		(0u)
+
+	, m_frameCount				(60u * 5u)
+	, m_frameNdx				(0u)
+
+	, m_maxOutOfDateCount		(20u)
+	, m_outOfDateCount			(0u)
+{
+	{
+		const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
+		m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
+		m_context.getTestContext().getLog() << TestLog::Message << "SharedPresentSupportedUsageFlags: " << m_supportedUsageFlags << TestLog::EndMessage;
+
+	}
+}
+
+SharedPresentableImageTestInstance::~SharedPresentableImageTestInstance (void)
+{
+	deinitSwapchainResources();
+}
+
+void SharedPresentableImageTestInstance::initSwapchainResources (void)
+{
+	const size_t		fenceCount	= 6;
+	const deUint32		imageWidth	= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
+	const deUint32		imageHeight	= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
+	const vk::VkFormat	imageFormat	= m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
+
+	m_swapchain				= vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
+	m_swapchainImage		= vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain).front();
+
+	m_renderPass			= createRenderPass(m_vkd, *m_device, imageFormat);
+	m_pipeline				= createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
+
+	m_swapchainImageView	= createImageView(m_vkd, *m_device, m_swapchainImage, imageFormat);
+	m_framebuffer			= createFramebuffer(m_vkd, *m_device, *m_renderPass, *m_swapchainImageView, imageWidth, imageHeight);
+
+	m_renderSemaphores		= std::vector<vk::VkSemaphore>(fenceCount, (vk::VkSemaphore)0);
+	m_fences				= std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
+	m_commandBuffers		= std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
+
+	initSemaphores(m_vkd, *m_device, m_renderSemaphores);
+
+	initFences(m_vkd, *m_device, m_fences);
+
+	// Unlike a traditional swapchain, where we'd acquire a new image from the
+	// PE every frame, a shared image swapchain has a single image that is
+	// acquired upfront. We acquire it here, transition it to the proper layout,
+	// and present it.
+
+	// Acquire the one image
+	const deUint64				foreverNs		= 0xFFFFFFFFFFFFFFFFul;
+	vk::Move<vk::VkSemaphore>	semaphore(createSemaphore(m_vkd, *m_device));
+	deUint32					imageIndex		= 42;	// initialize to junk value
+
+	VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, *semaphore, 0u, &imageIndex));
+	TCU_CHECK(imageIndex == 0);
+
+	// Transition to IMAGE_LAYOUT_SHARED_PRESENT_KHR
+	const vk::VkCommandBufferAllocateInfo allocateInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+		DE_NULL,
+		*m_commandPool,
+		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+		1
+	};
+	const vk::VkCommandBufferBeginInfo	beginInfo		=
+	{
+		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+		DE_NULL,
+		0u,
+		DE_NULL
+	};
+
+	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(vk::allocateCommandBuffer(m_vkd, *m_device, &allocateInfo));
+	VK_CHECK(m_vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
+
+	const vk::VkImageMemoryBarrier barrier = {
+		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+		DE_NULL,
+		0,
+		0,
+		vk::VK_IMAGE_LAYOUT_UNDEFINED,
+		vk::VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+		VK_QUEUE_FAMILY_IGNORED,
+		VK_QUEUE_FAMILY_IGNORED,
+		m_swapchainImage,
+		{
+			vk::VK_IMAGE_ASPECT_COLOR_BIT,
+			0,
+			1,
+			0,
+			1
+		},
+	};
+
+	m_vkd.cmdPipelineBarrier(*commandBuffer,
+							vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+							vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+							0u,
+							0, DE_NULL,
+							0, DE_NULL,
+							1, &barrier);
+
+	VK_CHECK(m_vkd.endCommandBuffer(*commandBuffer));
+
+	const vk::VkSubmitInfo submitInfo =
+	{
+		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+		DE_NULL,
+		1, &*semaphore, DE_NULL,
+		1, &*commandBuffer,
+		0, DE_NULL,
+	};
+
+	VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, (vk::VkFence)0));
+	VK_CHECK(m_vkd.queueWaitIdle(m_queue));
+}
+
+void SharedPresentableImageTestInstance::deinitSwapchainResources (void)
+{
+	VK_CHECK(m_vkd.queueWaitIdle(m_queue));
+
+	deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
+	deinitFences(m_vkd, *m_device, m_fences);
+	deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
+
+	m_framebuffer	= vk::Move<vk::VkFramebuffer>();
+	m_swapchainImageView = vk::Move<vk::VkImageView>();
+	m_swapchainImage = (vk::VkImage)0;
+
+	m_swapchain		= vk::Move<vk::VkSwapchainKHR>();
+	m_renderPass	= vk::Move<vk::VkRenderPass>();
+	m_pipeline		= vk::Move<vk::VkPipeline>();
+}
+
+void SharedPresentableImageTestInstance::render (void)
+{
+	const deUint64		foreverNs		= 0xFFFFFFFFFFFFFFFFul;
+	const vk::VkFence	fence			= m_fences[m_frameNdx % m_fences.size()];
+	const deUint32		width			= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
+	const deUint32		height			= m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
+
+	// Throttle execution
+	if (m_frameNdx >= m_fences.size())
+	{
+		VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
+		VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
+
+		m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
+		m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
+	}
+
+	deUint32			imageIndex = 0;		// There is only one image.
+	const vk::VkSemaphore currentRenderSemaphore = m_renderSemaphores[m_frameNdx % m_renderSemaphores.size()];
+
+	const bool willPresent = m_swapchainConfigs[m_swapchainConfigNdx].presentMode == vk::VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR || !m_frameNdx;
+
+	// Create command buffer
+	m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, *m_framebuffer, *m_pipeline, m_frameNdx, m_quadCount, width, height).disown();
+
+	// Submit command buffer
+	{
+		const vk::VkSubmitInfo			submitInfo		=
+		{
+			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+			DE_NULL,
+			0u,
+			DE_NULL,
+			DE_NULL,
+			1u,
+			&m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
+			willPresent ? 1u : 0u,	  // Only signal the semaphore if we're going to call QueuePresent.
+			&currentRenderSemaphore
+		};
+
+		// With a traditional swapchain, we'd fence on completion of
+		// AcquireNextImage. We never call that for a shared image swapchain, so
+		// fence on completion of the rendering work instead. A real shared
+		// image application would want a more substantial pacing mechanism.
+		VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
+	}
+
+	// DEMAND_REFRESH requires us to call QueuePresent whenever we want to be
+	// assured the PE has picked up a new frame. The PE /may/ also pick up
+	// changes whenever it likes.
+	//
+	// For CONTINUOUS_REFRESH, we need to just call QueuePresent once on the
+	// first frame to kick things off.
+	if (willPresent)
+	{
+
+		// Present frame
+		vk::VkResult result;
+		const vk::VkPresentInfoKHR presentInfo =
+		{
+			vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+			DE_NULL,
+			1u,
+			&currentRenderSemaphore,
+			1u,
+			&*m_swapchain,
+			&imageIndex,
+			&result
+		};
+
+		VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
+		VK_CHECK(result);
+
+	}
+
+	// With either present mode, we can call GetSwapchainStatus at any time
+	// to detect possible OUT_OF_DATE conditions. Let's do that every frame.
+
+	const vk::VkResult swapchainStatus = m_vkd.getSwapchainStatusKHR(*m_device, *m_swapchain);
+	VK_CHECK(swapchainStatus);
+}
+
+tcu::TestStatus SharedPresentableImageTestInstance::iterate (void)
+{
+	// Initialize swapchain specific resources
+	// Render test
+	try
+	{
+		if (m_frameNdx == 0)
+		{
+			if (m_outOfDateCount == 0)
+				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
+
+			initSwapchainResources();
+		}
+
+		render();
+	}
+	catch (const vk::Error& error)
+	{
+		if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
+		{
+			m_swapchainConfigs = generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_supportedUsageFlags);
+
+			if (m_outOfDateCount < m_maxOutOfDateCount)
+			{
+				m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
+				deinitSwapchainResources();
+				m_frameNdx = 0;
+				m_outOfDateCount++;
+
+				return tcu::TestStatus::incomplete();
+			}
+			else
+			{
+				m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
+				m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
+			}
+		}
+		else
+		{
+			m_resultCollector.fail(error.what());
+		}
+
+		deinitSwapchainResources();
+
+		m_swapchainConfigNdx++;
+		m_frameNdx = 0;
+		m_outOfDateCount = 0;
+
+		if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
+			return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
+		else
+			return tcu::TestStatus::incomplete();
+	}
+
+	m_frameNdx++;
+
+	if (m_frameNdx >= m_frameCount)
+	{
+		m_frameNdx = 0;
+		m_outOfDateCount = 0;
+		m_swapchainConfigNdx++;
+
+		deinitSwapchainResources();
+
+		if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
+			return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
+		else
+			return tcu::TestStatus::incomplete();
+	}
+	else
+		return tcu::TestStatus::incomplete();
+}
+
+struct Programs
+{
+	static void init (vk::SourceCollections& dst, TestConfig)
+	{
+		dst.glslSources.add("quad-vert") << glu::VertexSource(
+			"#version 450\n"
+			"out gl_PerVertex {\n"
+			"\tvec4 gl_Position;\n"
+			"};\n"
+			"layout(location = 0) out highp uint quadIndex;\n"
+			"highp float;\n"
+			"void main (void) {\n"
+			"\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
+			"\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
+			"\tquadIndex = gl_VertexIndex / 6;\n"
+			"}\n");
+		dst.glslSources.add("quad-frag") << glu::FragmentSource(
+			"#version 310 es\n"
+			"layout(location = 0) flat in highp uint quadIndex;\n"
+			"layout(location = 0) out highp vec4 o_color;\n"
+			"layout(push_constant) uniform PushConstant {\n"
+			"\thighp uint frameNdx;\n"
+			"} pushConstants;\n"
+			"void main (void)\n"
+			"{\n"
+			"\thighp uint frameNdx = pushConstants.frameNdx;\n"
+			"\thighp uint cellX = bitfieldExtract(uint(gl_FragCoord.x), 7, 10);\n"
+			"\thighp uint cellY = bitfieldExtract(uint(gl_FragCoord.y), 7, 10);\n"
+			"\thighp uint x = quadIndex ^ (frameNdx + (uint(gl_FragCoord.x) >> cellX));\n"
+			"\thighp uint y = quadIndex ^ (frameNdx + (uint(gl_FragCoord.y) >> cellY));\n"
+			"\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
+			"\t             +  64u * bitfieldExtract(y, 1, 1)\n"
+			"\t             +  32u * bitfieldExtract(x, 3, 1);\n"
+			"\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
+			"\t             +  64u * bitfieldExtract(x, 2, 1)\n"
+			"\t             +  32u * bitfieldExtract(y, 3, 1);\n"
+			"\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
+			"\t             +  64u * bitfieldExtract(y, 2, 1)\n"
+			"\t             +  32u * bitfieldExtract(x, 4, 1);\n"
+			"\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
+			"}\n");
+	}
+};
+
+} // anonymous
+
+void createSharedPresentableImageTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
+{
+	const struct
+	{
+		Scaling		scaling;
+		const char*	name;
+	} scaling [] =
+	{
+		{ SCALING_NONE,	"scale_none"	},
+		{ SCALING_UP,	"scale_up"		},
+		{ SCALING_DOWN, "scale_down"	}
+	};
+	const struct
+	{
+		vk::VkPresentModeKHR	mode;
+		const char*				name;
+	} presentModes[] =
+	{
+		{ vk::VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,			"demand"			},
+		{ vk::VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR,		"continuous"		},
+	};
+
+	for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
+	{
+		if (scaling[scalingNdx].scaling == SCALING_NONE || wsiTypeSupportsScaling(wsiType))
+		{
+			de::MovePtr<tcu::TestCaseGroup>	scaleGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
+
+			for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
+			{
+
+				const char* const				name		= presentModes[presentModeNdx].name;
+				TestConfig						config;
+
+				config.wsiType					= wsiType;
+				config.useSharedPresentableImage= true;
+				config.scaling					= scaling[scalingNdx].scaling;
+				config.presentMode				= presentModes[presentModeNdx].mode;
+
+				scaleGroup->addChild(new vkt::InstanceFactory1<SharedPresentableImageTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
+			}
+
+			testGroup->addChild(scaleGroup.release());
+		}
+	}
+}
+
+} // wsi
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.hpp b/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.hpp
new file mode 100644
index 0000000..29a9b84
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/wsi/vktWsiSharedPresentableImageTests.hpp
@@ -0,0 +1,40 @@
+#ifndef _VKTWSISHAREDPRESENTABLEIMAGETESTS_HPP
+#define _VKTWSISHAREDPRESENTABLEIMAGETESTS_HPP
+/*-------------------------------------------------------------------------
+* Vulkan Conformance Tests
+* ------------------------
+*
+* Copyright (c) 2017 Google Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*//*!
+* \file
+* \brief Tests for shared presentable image extension
+*//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+#include "vkDefs.hpp"
+
+namespace vkt
+{
+namespace wsi
+{
+
+void  createSharedPresentableImageTests	(tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType);
+
+} // wsi
+} // vkt
+
+#endif // _VKTWSISHAREDPRESENTABLEIMAGETESTS_HPP
diff --git a/external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp b/external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp
index 2c108e9..87de704 100644
--- a/external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp
+++ b/external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp
@@ -47,6 +47,7 @@
 
 #include "deUniquePtr.hpp"
 #include "deStringUtil.hpp"
+#include "deMemory.h"
 
 namespace vk
 {
@@ -61,6 +62,25 @@
 	return !(a != b);
 }
 
+inline bool operator!= (const VkExtent2D& a, const VkExtent2D& b)
+{
+	return (a.width != b.width) || (a.height != b.height);
+}
+
+inline bool operator!= (const VkSurfaceCapabilitiesKHR& a, const VkSurfaceCapabilitiesKHR& b)
+{
+	return (a.minImageCount				!= b.minImageCount)				||
+		   (a.maxImageCount				!= b.maxImageCount)				||
+		   (a.currentExtent				!= b.currentExtent)				||
+		   (a.minImageExtent			!= b.minImageExtent)			||
+		   (a.maxImageExtent			!= b.maxImageExtent)			||
+		   (a.maxImageArrayLayers		!= b.maxImageArrayLayers)		||
+		   (a.supportedTransforms		!= b.supportedTransforms)		||
+		   (a.currentTransform			!= b.currentTransform)			||
+		   (a.supportedCompositeAlpha	!= b.supportedCompositeAlpha)	||
+		   (a.supportedUsageFlags		!= b.supportedUsageFlags);
+}
+
 } // vk
 
 namespace vkt
@@ -155,9 +175,10 @@
 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&		vkp,
 										const Extensions&				supportedExtensions,
 										Type							wsiType,
+										const vector<string>			extraExtensions,
 										const VkAllocationCallbacks*	pAllocator	= DE_NULL)
 {
-	vector<string>	extensions;
+	vector<string>	extensions	= extraExtensions;
 
 	extensions.push_back("VK_KHR_surface");
 	extensions.push_back(getExtensionName(wsiType));
@@ -179,6 +200,18 @@
 		, instance				(createInstanceWithWsi(context.getPlatformInterface(),
 													   supportedExtensions,
 													   wsiType,
+													   vector<string>(),
+													   pAllocator))
+		, vki					(context.getPlatformInterface(), *instance)
+	{}
+
+	InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
+		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
+																	  DE_NULL))
+		, instance				(createInstanceWithWsi(context.getPlatformInterface(),
+													   supportedExtensions,
+													   wsiType,
+													   extensions,
 													   pAllocator))
 		, vki					(context.getPlatformInterface(), *instance)
 	{}
@@ -464,6 +497,64 @@
 	return tcu::TestStatus(results.getResult(), results.getMessage());
 }
 
+tcu::TestStatus querySurfaceCapabilities2Test (Context& context, Type wsiType)
+{
+	tcu::TestLog&					log						= context.getTestContext().getLog();
+	tcu::ResultCollector			results					(log);
+
+	const InstanceHelper			instHelper				(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
+	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
+	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
+	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
+
+	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
+	{
+		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
+		{
+			const VkSurfaceCapabilitiesKHR	refCapabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
+																								   physicalDevices[deviceNdx],
+																								   *surface);
+			VkSurfaceCapabilities2KHR		extCapabilities;
+
+			deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
+			extCapabilities.sType	= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
+			extCapabilities.pNext	= DE_NULL;
+
+			{
+				const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo	=
+				{
+					VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+					DE_NULL,
+					*surface
+				};
+				VkPhysicalDeviceSurfaceInfo2KHR			infoCopy;
+
+				deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
+
+				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
+
+				results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
+			}
+
+			results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
+						  extCapabilities.pNext == DE_NULL,
+						  "sType/pNext modified");
+
+			if (refCapabilities != extCapabilities.surfaceCapabilities)
+			{
+				log << TestLog::Message
+					<< "Device " << deviceNdx
+					<< ": expected " << refCapabilities
+					<< ", got " << extCapabilities.surfaceCapabilities
+					<< TestLog::EndMessage;
+				results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
+			}
+		}
+	}
+
+	return tcu::TestStatus(results.getResult(), results.getMessage());
+}
+
 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
 {
 	const VkSurfaceFormatKHR*	requiredFormats		= DE_NULL;
@@ -489,6 +580,13 @@
 		if (!de::contains(formats.begin(), formats.end(), requiredFormat))
 			results.fail(de::toString(requiredFormat) + " not supported");
 	}
+
+	// Check that there are no duplicates
+	for (size_t ndx = 1; ndx < formats.size(); ++ndx)
+	{
+		if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
+			results.fail("Found duplicate entry " + de::toString(formats[ndx]));
+	}
 }
 
 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
@@ -520,6 +618,99 @@
 	return tcu::TestStatus(results.getResult(), results.getMessage());
 }
 
+tcu::TestStatus querySurfaceFormats2Test (Context& context, Type wsiType)
+{
+	tcu::TestLog&					log				= context.getTestContext().getLog();
+	tcu::ResultCollector			results			(log);
+
+	const InstanceHelper			instHelper		(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
+	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
+	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
+	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
+
+	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
+	{
+		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
+		{
+			const vector<VkSurfaceFormatKHR>		refFormats	= getPhysicalDeviceSurfaceFormats(instHelper.vki,
+																								  physicalDevices[deviceNdx],
+																								  *surface);
+			const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo	=
+			{
+				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+				DE_NULL,
+				*surface
+			};
+			deUint32								numFormats	= 0;
+
+			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, DE_NULL));
+
+			if ((size_t)numFormats != refFormats.size())
+				results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
+
+			if (numFormats > 0)
+			{
+				vector<VkSurfaceFormat2KHR>	formats	(numFormats);
+
+				for (size_t ndx = 0; ndx < formats.size(); ++ndx)
+				{
+					formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
+					formats[ndx].pNext = DE_NULL;
+				}
+
+				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, &formats[0]));
+
+				if ((size_t)numFormats != formats.size())
+					results.fail("Format count changed between calls");
+
+				{
+					vector<VkSurfaceFormatKHR>	extFormats	(formats.size());
+
+					for (size_t ndx = 0; ndx < formats.size(); ++ndx)
+					{
+						results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
+									  formats[ndx].pNext == DE_NULL,
+									  "sType/pNext modified");
+						extFormats[ndx] = formats[ndx].surfaceFormat;
+					}
+
+					for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
+					{
+						if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
+							results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
+					}
+				}
+
+				// Check VK_INCOMPLETE
+				{
+					vector<VkSurfaceFormat2KHR>	formatsClone	(formats);
+					deUint32					numToSupply		= numFormats/2;
+					VkResult					queryResult;
+
+					ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
+
+					queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
+
+					results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
+					results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
+								  "Driver wrote past last element");
+
+					for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
+					{
+						results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
+									  formatsClone[ndx].pNext == DE_NULL &&
+									  formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
+									  "Returned element " + de::toString(ndx) + " is different");
+					}
+				}
+			}
+		}
+		// else skip query as surface is not supported by the device
+	}
+
+	return tcu::TestStatus(results.getResult(), results.getMessage());
+}
+
 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
 {
 	results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
@@ -688,7 +879,9 @@
 	addFunctionCase(testGroup, "create_simulate_oom",		"Create surface with simulating OOM",	createSurfaceSimulateOOMTest,		wsiType);
 	addFunctionCase(testGroup, "query_support",				"Query surface support",				querySurfaceSupportTest,			wsiType);
 	addFunctionCase(testGroup, "query_capabilities",		"Query surface capabilities",			querySurfaceCapabilitiesTest,		wsiType);
+	addFunctionCase(testGroup, "query_capabilities2",		"Query extended surface capabilities",	querySurfaceCapabilities2Test,		wsiType);
 	addFunctionCase(testGroup, "query_formats",				"Query surface formats",				querySurfaceFormatsTest,			wsiType);
+	addFunctionCase(testGroup, "query_formats2",			"Query extended surface formats",		querySurfaceFormats2Test,			wsiType);
 	addFunctionCase(testGroup, "query_present_modes",		"Query surface present modes",			querySurfacePresentModesTest,		wsiType);
 	addFunctionCase(testGroup, "destroy_null_handle",		"Destroy VK_NULL_HANDLE surface",		destroyNullHandleSurfaceTest,		wsiType);
 
diff --git a/external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp b/external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp
index 678995e..708500a 100644
--- a/external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp
+++ b/external/vulkancts/modules/vulkan/wsi/vktWsiTests.cpp
@@ -29,6 +29,7 @@
 #include "vktWsiSwapchainTests.hpp"
 #include "vktWsiIncrementalPresentTests.hpp"
 #include "vktWsiDisplayTimingTests.hpp"
+#include "vktWsiSharedPresentableImageTests.hpp"
 
 namespace vkt
 {
@@ -44,6 +45,7 @@
 	addTestGroup(testGroup, "swapchain",			"VkSwapchain Tests",			createSwapchainTests,			wsiType);
 	addTestGroup(testGroup, "incremental_present",	"Incremental present tests",	createIncrementalPresentTests,	wsiType);
 	addTestGroup(testGroup, "display_timing",		"Display Timing Tests",			createDisplayTimingTests,		wsiType);
+	addTestGroup(testGroup, "shared_presentable_image",	"VK_KHR_shared_presentable_image tests",	createSharedPresentableImageTests,	wsiType);
 }
 
 void createWsiTests (tcu::TestCaseGroup* apiTests)
diff --git a/external/vulkancts/mustpass/1.0.2/vk-default.txt b/external/vulkancts/mustpass/1.0.2/vk-default.txt
index 953edd4..c5b85b5 100644
--- a/external/vulkancts/mustpass/1.0.2/vk-default.txt
+++ b/external/vulkancts/mustpass/1.0.2/vk-default.txt
@@ -134311,7 +134311,9 @@
 dEQP-VK.wsi.xlib.surface.create_simulate_oom
 dEQP-VK.wsi.xlib.surface.query_support
 dEQP-VK.wsi.xlib.surface.query_capabilities
+dEQP-VK.wsi.xlib.surface.query_capabilities2
 dEQP-VK.wsi.xlib.surface.query_formats
+dEQP-VK.wsi.xlib.surface.query_formats2
 dEQP-VK.wsi.xlib.surface.query_present_modes
 dEQP-VK.wsi.xlib.surface.destroy_null_handle
 dEQP-VK.wsi.xlib.surface.initial_size
@@ -134355,12 +134357,16 @@
 dEQP-VK.wsi.xlib.display_timing.immediate.display_timing
 dEQP-VK.wsi.xlib.display_timing.mailbox.reference
 dEQP-VK.wsi.xlib.display_timing.mailbox.display_timing
+dEQP-VK.wsi.xlib.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.xlib.shared_presentable_image.scale_none.continuous
 dEQP-VK.wsi.xcb.surface.create
 dEQP-VK.wsi.xcb.surface.create_custom_allocator
 dEQP-VK.wsi.xcb.surface.create_simulate_oom
 dEQP-VK.wsi.xcb.surface.query_support
 dEQP-VK.wsi.xcb.surface.query_capabilities
+dEQP-VK.wsi.xcb.surface.query_capabilities2
 dEQP-VK.wsi.xcb.surface.query_formats
+dEQP-VK.wsi.xcb.surface.query_formats2
 dEQP-VK.wsi.xcb.surface.query_present_modes
 dEQP-VK.wsi.xcb.surface.destroy_null_handle
 dEQP-VK.wsi.xcb.surface.initial_size
@@ -134404,12 +134410,16 @@
 dEQP-VK.wsi.xcb.display_timing.immediate.display_timing
 dEQP-VK.wsi.xcb.display_timing.mailbox.reference
 dEQP-VK.wsi.xcb.display_timing.mailbox.display_timing
+dEQP-VK.wsi.xcb.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.xcb.shared_presentable_image.scale_none.continuous
 dEQP-VK.wsi.wayland.surface.create
 dEQP-VK.wsi.wayland.surface.create_custom_allocator
 dEQP-VK.wsi.wayland.surface.create_simulate_oom
 dEQP-VK.wsi.wayland.surface.query_support
 dEQP-VK.wsi.wayland.surface.query_capabilities
+dEQP-VK.wsi.wayland.surface.query_capabilities2
 dEQP-VK.wsi.wayland.surface.query_formats
+dEQP-VK.wsi.wayland.surface.query_formats2
 dEQP-VK.wsi.wayland.surface.query_present_modes
 dEQP-VK.wsi.wayland.surface.destroy_null_handle
 dEQP-VK.wsi.wayland.swapchain.create.min_image_count
@@ -134452,12 +134462,16 @@
 dEQP-VK.wsi.wayland.display_timing.immediate.display_timing
 dEQP-VK.wsi.wayland.display_timing.mailbox.reference
 dEQP-VK.wsi.wayland.display_timing.mailbox.display_timing
+dEQP-VK.wsi.wayland.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.wayland.shared_presentable_image.scale_none.continuous
 dEQP-VK.wsi.mir.surface.create
 dEQP-VK.wsi.mir.surface.create_custom_allocator
 dEQP-VK.wsi.mir.surface.create_simulate_oom
 dEQP-VK.wsi.mir.surface.query_support
 dEQP-VK.wsi.mir.surface.query_capabilities
+dEQP-VK.wsi.mir.surface.query_capabilities2
 dEQP-VK.wsi.mir.surface.query_formats
+dEQP-VK.wsi.mir.surface.query_formats2
 dEQP-VK.wsi.mir.surface.query_present_modes
 dEQP-VK.wsi.mir.surface.destroy_null_handle
 dEQP-VK.wsi.mir.surface.initial_size
@@ -134518,12 +134532,20 @@
 dEQP-VK.wsi.mir.display_timing.immediate.display_timing
 dEQP-VK.wsi.mir.display_timing.mailbox.reference
 dEQP-VK.wsi.mir.display_timing.mailbox.display_timing
+dEQP-VK.wsi.mir.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.mir.shared_presentable_image.scale_none.continuous
+dEQP-VK.wsi.mir.shared_presentable_image.scale_up.demand
+dEQP-VK.wsi.mir.shared_presentable_image.scale_up.continuous
+dEQP-VK.wsi.mir.shared_presentable_image.scale_down.demand
+dEQP-VK.wsi.mir.shared_presentable_image.scale_down.continuous
 dEQP-VK.wsi.android.surface.create
 dEQP-VK.wsi.android.surface.create_custom_allocator
 dEQP-VK.wsi.android.surface.create_simulate_oom
 dEQP-VK.wsi.android.surface.query_support
 dEQP-VK.wsi.android.surface.query_capabilities
+dEQP-VK.wsi.android.surface.query_capabilities2
 dEQP-VK.wsi.android.surface.query_formats
+dEQP-VK.wsi.android.surface.query_formats2
 dEQP-VK.wsi.android.surface.query_present_modes
 dEQP-VK.wsi.android.surface.destroy_null_handle
 dEQP-VK.wsi.android.surface.initial_size
@@ -134583,12 +134605,20 @@
 dEQP-VK.wsi.android.display_timing.immediate.display_timing
 dEQP-VK.wsi.android.display_timing.mailbox.reference
 dEQP-VK.wsi.android.display_timing.mailbox.display_timing
+dEQP-VK.wsi.android.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_none.continuous
+dEQP-VK.wsi.android.shared_presentable_image.scale_up.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_up.continuous
+dEQP-VK.wsi.android.shared_presentable_image.scale_down.demand
+dEQP-VK.wsi.android.shared_presentable_image.scale_down.continuous
 dEQP-VK.wsi.win32.surface.create
 dEQP-VK.wsi.win32.surface.create_custom_allocator
 dEQP-VK.wsi.win32.surface.create_simulate_oom
 dEQP-VK.wsi.win32.surface.query_support
 dEQP-VK.wsi.win32.surface.query_capabilities
+dEQP-VK.wsi.win32.surface.query_capabilities2
 dEQP-VK.wsi.win32.surface.query_formats
+dEQP-VK.wsi.win32.surface.query_formats2
 dEQP-VK.wsi.win32.surface.query_present_modes
 dEQP-VK.wsi.win32.surface.destroy_null_handle
 dEQP-VK.wsi.win32.surface.initial_size
@@ -134632,6 +134662,8 @@
 dEQP-VK.wsi.win32.display_timing.immediate.display_timing
 dEQP-VK.wsi.win32.display_timing.mailbox.reference
 dEQP-VK.wsi.win32.display_timing.mailbox.display_timing
+dEQP-VK.wsi.win32.shared_presentable_image.scale_none.demand
+dEQP-VK.wsi.win32.shared_presentable_image.scale_none.continuous
 dEQP-VK.synchronization.smoke.fences
 dEQP-VK.synchronization.smoke.semaphores
 dEQP-VK.synchronization.smoke.events
diff --git a/external/vulkancts/scripts/gen_framework.py b/external/vulkancts/scripts/gen_framework.py
index 67ca195..6e21052 100644
--- a/external/vulkancts/scripts/gen_framework.py
+++ b/external/vulkancts/scripts/gen_framework.py
@@ -114,7 +114,11 @@
 	"vkDebugReportMessageEXT",
 
 	# VK_NV_external_memory_capabilities
-	"vkGetPhysicalDeviceExternalImageFormatPropertiesNV"
+	"vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
+
+	# VK_KHR_get_surface_capabilities2
+	"vkGetPhysicalDeviceSurfaceCapabilities2KHR",
+	"vkGetPhysicalDeviceSurfaceFormats2KHR",
 ]
 
 DEFINITIONS			= [
diff --git a/external/vulkancts/scripts/src/vulkan.h.in b/external/vulkancts/scripts/src/vulkan.h.in
index 3a4b80e..aac2a32 100644
--- a/external/vulkancts/scripts/src/vulkan.h.in
+++ b/external/vulkancts/scripts/src/vulkan.h.in
@@ -238,6 +238,7 @@
     VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+    VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
     VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
     VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
@@ -246,6 +247,9 @@
     VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
     VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
     VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
+    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
+    VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
     VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
     VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
     VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@@ -533,6 +537,7 @@
     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
     VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
+    VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
     VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
     VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED,
     VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1),
@@ -3250,6 +3255,8 @@
     VK_PRESENT_MODE_MAILBOX_KHR = 1,
     VK_PRESENT_MODE_FIFO_KHR = 2,
     VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
+    VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000,
+    VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001,
     VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR,
     VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
     VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1),
@@ -3921,6 +3928,62 @@
     const VkPresentRegionKHR*    pRegions;
 } VkPresentRegionsKHR;
 
+#define VK_KHR_get_surface_capabilities2 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSurfaceKHR       surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
+typedef struct VkSurfaceCapabilities2KHR {
+    VkStructureType             sType;
+    void*                       pNext;
+    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
+
+typedef struct VkSurfaceFormat2KHR {
+    VkStructureType       sType;
+    void*                 pNext;
+    VkSurfaceFormatKHR    surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    uint32_t*                                   pSurfaceFormatCount,
+    VkSurfaceFormat2KHR*                        pSurfaceFormats);
+#endif
+
+#define VK_KHR_shared_presentable_image 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
+    VkStructureType      sType;
+    void*                pNext;
+    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
+} VkSharedPresentSurfaceCapabilitiesKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain);
+#endif
+
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
diff --git a/modules/internal/ditBuildInfoTests.cpp b/modules/internal/ditBuildInfoTests.cpp
index 8b5ba65..056da8e 100644
--- a/modules/internal/ditBuildInfoTests.cpp
+++ b/modules/internal/ditBuildInfoTests.cpp
@@ -193,7 +193,7 @@
 	addChild(new BuildEnumCase				(m_testCtx, "de_compiler",				"DE_COMPILER",		DE_COMPILER,							getCompilerName));
 	addChild(new BuildInfoStringCase		(m_testCtx, "de_ptr_size",				"DE_PTR_SIZE",		de::toString(DE_PTR_SIZE).c_str()));
 	addChild(new BuildEnumCase				(m_testCtx, "de_endianness",			"DE_ENDIANNESS",	DE_ENDIANNESS,							getEndiannessName));
-	addChild(new EndiannessConsistencyCase	(m_testCtx, "de_endianness_consitent",	"DE_ENDIANNESS"));
+	addChild(new EndiannessConsistencyCase	(m_testCtx, "de_endianness_consistent", "DE_ENDIANNESS"));
 }
 
 } // dit