Add swapchain tests for the VK_KHR_protected_memory extension

New tests:
* dEQP-VK.protected_memory.interaction.wsi.*

Components: Vulkan
VK-GL-CTS issue: 118

Change-Id: Ife48da5098299fd9d747a7b74208136c7f3413e0
(cherry picked from commit 9991ff0e4baea2316a93ec07e06f44ff279d2774)
diff --git a/AndroidGen.mk b/AndroidGen.mk
index 862beff..93738d6 100644
--- a/AndroidGen.mk
+++ b/AndroidGen.mk
@@ -170,6 +170,7 @@
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemBlitImageTests.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemBufferValidator.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemClearColorImageTests.cpp \
+	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemCopyBufferToImageTests.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemCopyImageTests.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemCopyImageToBufferTests.cpp \
@@ -179,6 +180,7 @@
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemStorageBufferTests.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp \
 	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp \
+	external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp \
 	external/vulkancts/modules/vulkan/query_pool/vktQueryPoolOcclusionTests.cpp \
 	external/vulkancts/modules/vulkan/query_pool/vktQueryPoolStatisticsTests.cpp \
 	external/vulkancts/modules/vulkan/query_pool/vktQueryPoolTests.cpp \
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index 8274f9c..5efc639 100755
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
@@ -273790,3 +273790,69 @@
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_8
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_9
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_10
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.render.basic
diff --git a/external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt b/external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt
index c312b9d..d2103f6 100644
--- a/external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt
@@ -2,6 +2,7 @@
 
 set(DEQP_VK_PROTECTED_MEMORY_SRCS
 	vktProtectedMemContext.hpp
+	vktProtectedMemContext.cpp
 	vktProtectedMemUtils.cpp
 	vktProtectedMemUtils.hpp
 	vktProtectedMemTests.cpp
@@ -30,6 +31,8 @@
 	vktProtectedMemStorageBufferTests.hpp
 	vktProtectedMemShaderImageAccessTests.cpp
 	vktProtectedMemShaderImageAccessTests.hpp
+	vktProtectedMemWsiSwapchainTests.cpp
+	vktProtectedMemWsiSwapchainTests.hpp
 	vktProtectedMemTests.cpp
 	vktProtectedMemTests.hpp
 	)
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.cpp
new file mode 100644
index 0000000..e20e619
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.cpp
@@ -0,0 +1,68 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 Protected Memory
+ *//*--------------------------------------------------------------------*/
+#include "vktProtectedMemContext.hpp"
+
+namespace vkt
+{
+namespace ProtectedMem
+{
+
+ProtectedContext::ProtectedContext	(Context&						ctx,
+									 const std::vector<std::string>	instanceExtensions,
+									 const std::vector<std::string>	deviceExtensions)
+	: m_context				(ctx)
+	, m_interface			(m_context.getPlatformInterface())
+	, m_instance			(makeProtectedMemInstance(m_interface, m_context, instanceExtensions))
+	, m_vki					(m_interface, *m_instance)
+	, m_phyDevice			(vk::chooseDevice(m_vki, *m_instance, m_context.getTestContext().getCommandLine()))
+	, m_queueFamilyIndex	(chooseProtectedMemQueueFamilyIndex(m_vki, m_phyDevice))
+	, m_device				(makeProtectedMemDevice(m_vki, m_phyDevice, m_queueFamilyIndex, ctx.getUsedApiVersion(), deviceExtensions))
+	, m_allocator			(createAllocator())
+	, m_deviceDriver		(m_vki, *m_device)
+	, m_queue				(getProtectedQueue(m_deviceDriver, *m_device, m_queueFamilyIndex, 0))
+{
+}
+
+ProtectedContext::ProtectedContext	(Context&						ctx,
+									 vk::wsi::Type					wsiType,
+									 vk::wsi::Display&				display,
+									 vk::wsi::Window&				window,
+									 const std::vector<std::string>	instanceExtensions,
+									 const std::vector<std::string>	deviceExtensions)
+	: m_context				(ctx)
+	, m_interface			(m_context.getPlatformInterface())
+	, m_instance			(makeProtectedMemInstance(m_interface, m_context, instanceExtensions))
+	, m_vki					(m_interface, *m_instance)
+	, m_phyDevice			(vk::chooseDevice(m_vki, *m_instance, m_context.getTestContext().getCommandLine()))
+	, m_surface				(vk::wsi::createSurface(m_vki, *m_instance, wsiType, display, window))
+	, m_queueFamilyIndex	(chooseProtectedMemQueueFamilyIndex(m_vki, m_phyDevice, *m_surface))
+	, m_device				(makeProtectedMemDevice(m_vki, m_phyDevice, m_queueFamilyIndex, ctx.getUsedApiVersion(), deviceExtensions))
+	, m_allocator			(createAllocator())
+	, m_deviceDriver		(m_vki, *m_device)
+	, m_queue				(getProtectedQueue(m_deviceDriver, *m_device, m_queueFamilyIndex, 0))
+{
+}
+
+} // ProtectedMem
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.hpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.hpp
index c4e4c5e..3f2384f 100644
--- a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.hpp
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemContext.hpp
@@ -31,31 +31,31 @@
 #include "vktProtectedMemUtils.hpp"
 #include "tcuCommandLine.hpp"
 #include "vkMemUtil.hpp"
+#include "vkWsiUtil.hpp"
 
 namespace vkt
 {
 namespace ProtectedMem
 {
 
-
 class ProtectedContext
 {
 public:
-		ProtectedContext	(Context& ctx)
-			: m_context				(ctx)
-			, m_interface			(m_context.getPlatformInterface())
-			, m_instance			(makeProtectedMemInstance(m_interface, m_context))
-			, m_vki					(m_interface, *m_instance)
-			, m_phyDevice			(vk::chooseDevice(m_vki, *m_instance, m_context.getTestContext().getCommandLine()))
-			, m_queueFamilyIndex	(chooseProtectedMemQueueFamilyIndex(m_vki, m_phyDevice))
-			, m_device				(makeProtectedMemDevice(m_vki, m_phyDevice, m_queueFamilyIndex, ctx.getUsedApiVersion()))
-			, m_allocator			(createAllocator())
-			, m_deviceDriver		(m_vki, *m_device)
-			, m_queue				(getProtectedQueue(m_deviceDriver, *m_device, m_queueFamilyIndex, 0))
-		{}
+		ProtectedContext	(Context&						ctx,
+							 const std::vector<std::string>	instanceExtensions = std::vector<std::string>(),
+							 const std::vector<std::string>	deviceExtensions = std::vector<std::string>());
+
+		ProtectedContext	(Context&						ctx,
+							 vk::wsi::Type					wsiType,
+							 vk::wsi::Display&				display,
+							 vk::wsi::Window&				window,
+							 const std::vector<std::string>	instanceExtensions = std::vector<std::string>(),
+							 const std::vector<std::string>	deviceExtensions = std::vector<std::string>());
 
 	const vk::DeviceInterface&					getDeviceInterface	(void) const	{ return m_deviceDriver;					}
 	vk::VkDevice								getDevice			(void) const	{ return *m_device;							}
+	const vk::DeviceDriver&						getDeviceDriver		(void) const	{ return m_deviceDriver;					}
+	vk::VkPhysicalDevice						getPhysicalDevice	(void) const	{ return m_phyDevice;						}
 	vk::VkQueue									getQueue			(void) const	{ return m_queue;							}
 	deUint32									getQueueFamilyIndex	(void) const	{ return m_queueFamilyIndex;				}
 
@@ -63,6 +63,11 @@
 	vk::BinaryCollection&						getBinaryCollection	(void) const	{ return m_context.getBinaryCollection();	}
 	vk::Allocator&								getDefaultAllocator	(void) const	{ return *m_allocator;	}
 
+	const vk::InstanceDriver&					getInstanceDriver	(void) const	{ return m_vki;								}
+	vk::VkInstance								getInstance			(void) const	{ return *m_instance;						}
+	const vk::VkSurfaceKHR						getSurface			(void) const	{ return *m_surface;						}
+
+
 private:
 	vk::Allocator* createAllocator (void)
 	{
@@ -73,16 +78,17 @@
 		return new vk::SimpleAllocator(getDeviceInterface(), getDevice(), memoryProperties);
 	}
 
-	Context&						m_context;
-	const vk::PlatformInterface&	m_interface;
-	vk::Move<vk::VkInstance>		m_instance;
-	vk::InstanceDriver				m_vki;
-	vk::VkPhysicalDevice			m_phyDevice;
-	deUint32						m_queueFamilyIndex;
-	vk::Move<vk::VkDevice>			m_device;
+	Context&							m_context;
+	const vk::PlatformInterface&		m_interface;
+	vk::Move<vk::VkInstance>			m_instance;
+	vk::InstanceDriver					m_vki;
+	vk::VkPhysicalDevice				m_phyDevice;
+	const vk::Move<vk::VkSurfaceKHR>	m_surface;
+	deUint32							m_queueFamilyIndex;
+	vk::Move<vk::VkDevice>				m_device;
 	const de::UniquePtr<vk::Allocator>	m_allocator;
-	vk::DeviceDriver				m_deviceDriver;
-	vk::VkQueue						m_queue;
+	vk::DeviceDriver					m_deviceDriver;
+	vk::VkQueue							m_queue;
 };
 
 class ProtectedTestInstance : public TestInstance
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp
index f46c57f..aa7d575 100644
--- a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp
@@ -37,6 +37,7 @@
 #include "vktProtectedMemCopyBufferToImageTests.hpp"
 #include "vktProtectedMemStorageBufferTests.hpp"
 #include "vktProtectedMemShaderImageAccessTests.hpp"
+#include "vktProtectedMemWsiSwapchainTests.hpp"
 
 namespace vkt
 {
@@ -85,6 +86,12 @@
 		protectedTests->addChild(ssboTestGroup.release());
 	}
 
+	{
+		de::MovePtr<tcu::TestCaseGroup> interactionTestGroup (new tcu::TestCaseGroup(testCtx, "interaction", "Various tests which interacts with other extensions"));
+		interactionTestGroup->addChild(createSwapchainTests(testCtx));
+		protectedTests->addChild(interactionTestGroup.release());
+	}
+
 	return protectedTests.release();
 
 }
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp
index 7cae2fe..2ded874 100644
--- a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp
@@ -24,6 +24,8 @@
 
 #include "vktProtectedMemUtils.hpp"
 
+#include <deString.h>
+
 #include "vkDeviceUtil.hpp"
 #include "vkQueryUtil.hpp"
 #include "vkTypeUtil.hpp"
@@ -32,6 +34,7 @@
 
 #include "vkPlatform.hpp"
 #include "vktProtectedMemContext.hpp"
+#include "vkWsiUtil.hpp"
 
 namespace vkt
 {
@@ -75,11 +78,11 @@
 }
 
 
-vk::Move<vk::VkInstance> makeProtectedMemInstance (const vk::PlatformInterface& vkp, const vkt::Context& context)
+vk::Move<vk::VkInstance> makeProtectedMemInstance (const vk::PlatformInterface& vkp, const vkt::Context& context, const std::vector<std::string>& extraExtensions)
 {
 	const Extensions			supportedExtensions(vk::enumerateInstanceExtensionProperties(vkp, DE_NULL));
 	std::vector<std::string>	enabledLayers;
-	std::vector<std::string>	requiredExtensions;
+	std::vector<std::string>	requiredExtensions = extraExtensions;
 	const bool					isValidationEnabled	= context.getTestContext().getCommandLine().isValidationEnabled();
 
 	if (isValidationEnabled)
@@ -107,7 +110,8 @@
 }
 
 deUint32 chooseProtectedMemQueueFamilyIndex	(const vk::InstanceDriver&	vkd,
-											 vk::VkPhysicalDevice		physicalDevice)
+											 vk::VkPhysicalDevice		physicalDevice,
+											 vk::VkSurfaceKHR			surface)
 {
 	std::vector<vk::VkQueueFamilyProperties>	properties;
 	deUint32									numFamilies		= 0;
@@ -126,6 +130,10 @@
 	{
 		vk::VkQueueFlags	flags = properties[idx].queueFlags;
 
+		if (surface != DE_NULL
+			&& vk::wsi::getPhysicalDeviceSurfaceSupport(vkd, physicalDevice, (deUint32)idx, surface) == VK_FALSE)
+			continue; // Skip the queue family index if it does not support the surface
+
 		if ((flags & requiredFlags) == requiredFlags)
 			return (deUint32)idx;
 	}
@@ -133,29 +141,33 @@
 	TCU_THROW(NotSupportedError, "No matching universal protected queue found");
 }
 
-vk::Move<vk::VkDevice> makeProtectedMemDevice	(const vk::InstanceDriver&		vkd,
-												 vk::VkPhysicalDevice			physicalDevice,
-												 const deUint32					queueFamilyIndex,
-												 const deUint32					apiVersion)
+vk::Move<vk::VkDevice> makeProtectedMemDevice	(const vk::InstanceDriver&			vkd,
+												 vk::VkPhysicalDevice				physicalDevice,
+												 const deUint32						queueFamilyIndex,
+												 const deUint32						apiVersion,
+												 const std::vector<std::string>&	extraExtensions)
 {
 	const Extensions					supportedExtensions	(vk::enumerateDeviceExtensionProperties(vkd, physicalDevice, DE_NULL));
-	std::vector<const char*>			requiredExtensions;
-	deUint32							extensionsCount		= 1;
-	const char* const					extensions[]		=
-	{
-		"VK_KHR_protected_memory"
-	};
+	std::vector<std::string>			requiredExtensions;
+	std::vector<std::string>			extensions			= extraExtensions;
+	extensions.push_back("VK_KHR_protected_memory");
 
 	// Check if the physical device supports the protected memory extension name
-	for (deUint32 ndx = 0; ndx < extensionsCount; ++ndx)
+	for (deUint32 ndx = 0; ndx < extensions.size(); ++ndx)
 	{
 		if (!isDeviceExtensionSupported(apiVersion, supportedExtensions, vk::RequiredExtension(extensions[ndx])))
-			TCU_THROW(NotSupportedError, (std::string(extensions[ndx]) + " is not supported").c_str());
+			TCU_THROW(NotSupportedError, (extensions[ndx] + " is not supported").c_str());
 
 		if (!isCoreDeviceExtension(apiVersion, extensions[ndx]))
 			requiredExtensions.push_back(extensions[ndx]);
 	}
 
+	std::vector<const char*>			enabledExts			(requiredExtensions.size());
+	for (size_t idx = 0; idx < requiredExtensions.size(); ++idx)
+	{
+		enabledExts[idx] = requiredExtensions[idx].c_str();
+	}
+
 	// Check if the protected memory can be enabled on the physical device.
 	vk::VkPhysicalDeviceProtectedMemoryFeatures	protectedFeature =
 	{
@@ -201,7 +213,7 @@
 		0u,																// enabledLayerCount
 		DE_NULL,														// pEnabledLayerNames
 		(deUint32)requiredExtensions.size(),							// enabledExtensionCount
-		requiredExtensions.empty() ? DE_NULL : &requiredExtensions[0],	// pEnabledExtensionNames
+		requiredExtensions.empty() ? DE_NULL : &enabledExts[0],			// pEnabledExtensionNames
 		DE_NULL															// pEnabledFeatures
 	};
 
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.hpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.hpp
index 3de495f..57d135f 100644
--- a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.hpp
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.hpp
@@ -51,14 +51,17 @@
 typedef std::vector<vk::VkVertexInputAttributeDescription>	VertexAttribs;
 
 vk::Move<vk::VkInstance>			makeProtectedMemInstance			(const vk::PlatformInterface&		vkp,
-																		 const vkt::Context&				context);
+																		 const vkt::Context&				context,
+																		 const std::vector<std::string>&	extraExtensions = std::vector<std::string>());
 deUint32							chooseProtectedMemQueueFamilyIndex	(const vk::InstanceDriver&			vkd,
-																		 vk::VkPhysicalDevice				physicalDevice);
+																		 vk::VkPhysicalDevice				physicalDevice,
+																		 vk::VkSurfaceKHR					surface = DE_NULL);
 
 vk::Move<vk::VkDevice>				makeProtectedMemDevice				(const vk::InstanceDriver&			vkd,
 																		 vk::VkPhysicalDevice				physicalDevice,
 																		 const deUint32						queueFamilyIndex,
-																		 const deUint32						apiVersion);
+																		 const deUint32						apiVersion,
+																		 const std::vector<std::string>&	extraExtensions = std::vector<std::string>());
 vk::VkQueue							getProtectedQueue					(const vk::DeviceInterface&			vk,
 																		 vk::VkDevice						device,
 																		 const deUint32						queueFamilyIndex,
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp
new file mode 100644
index 0000000..b9f6157
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.cpp
@@ -0,0 +1,1203 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 Protected memory interaction with VkSwapchain Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktProtectedMemWsiSwapchainTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkWsiPlatform.hpp"
+#include "vkWsiUtil.hpp"
+#include "vkAllocationCallbackUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuFormatUtil.hpp"
+#include "tcuPlatform.hpp"
+#include "tcuResultCollector.hpp"
+
+#include "deUniquePtr.hpp"
+#include "deStringUtil.hpp"
+#include "deArrayUtil.hpp"
+#include "deSharedPtr.hpp"
+
+#include <limits>
+
+#include "vktProtectedMemContext.hpp"
+#include "vktProtectedMemUtils.hpp"
+
+namespace vkt
+{
+namespace ProtectedMem
+{
+
+namespace
+{
+
+typedef std::vector<vk::VkExtensionProperties> Extensions;
+
+void checkAllSupported (const Extensions& supportedExtensions, const std::vector<std::string>& requiredExtensions)
+{
+	for (std::vector<std::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());
+	}
+}
+
+std::vector<std::string> getRequiredWsiExtensions (const Extensions&	supportedExtensions,
+												   vk::wsi::Type		wsiType)
+{
+	std::vector<std::string>	extensions;
+
+	extensions.push_back("VK_KHR_surface");
+	extensions.push_back(getExtensionName(wsiType));
+
+	// VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
+	// the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
+	// but using them without enabling the extension is not allowed. Thus we have
+	// two options:
+	//
+	// 1) Filter out non-core formats to stay within valid usage.
+	//
+	// 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
+	//
+	// We opt for (2) as it provides basic coverage for the extension as a bonus.
+	if (isExtensionSupported(supportedExtensions, vk::RequiredExtension("VK_EXT_swapchain_colorspace")))
+		extensions.push_back("VK_EXT_swapchain_colorspace");
+
+	checkAllSupported(supportedExtensions, extensions);
+
+	return extensions;
+}
+
+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 tcu::Maybe<tcu::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());
+	}
+}
+
+struct NativeObjects
+{
+	const de::UniquePtr<vk::wsi::Display>	display;
+	const de::UniquePtr<vk::wsi::Window>	window;
+
+	NativeObjects (Context&							context,
+				   const Extensions&				supportedExtensions,
+				   vk::wsi::Type					wsiType,
+				   const tcu::Maybe<tcu::UVec2>&	initialWindowSize = tcu::nothing<tcu::UVec2>())
+		: display				(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
+		, window				(createWindow(*display, initialWindowSize))
+	{}
+};
+
+enum TestDimension
+{
+	TEST_DIMENSION_MIN_IMAGE_COUNT = 0,	//!< Test all supported image counts
+	TEST_DIMENSION_IMAGE_FORMAT,		//!< Test all supported formats
+	TEST_DIMENSION_IMAGE_EXTENT,		//!< Test various (supported) extents
+	TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
+	TEST_DIMENSION_IMAGE_USAGE,
+	TEST_DIMENSION_IMAGE_SHARING_MODE,
+	TEST_DIMENSION_PRE_TRANSFORM,
+	TEST_DIMENSION_COMPOSITE_ALPHA,
+	TEST_DIMENSION_PRESENT_MODE,
+	TEST_DIMENSION_CLIPPED,
+
+	TEST_DIMENSION_LAST
+};
+
+const char* getTestDimensionName (TestDimension dimension)
+{
+	static const char* const s_names[] =
+	{
+		"min_image_count",
+		"image_format",
+		"image_extent",
+		"image_array_layers",
+		"image_usage",
+		"image_sharing_mode",
+		"pre_transform",
+		"composite_alpha",
+		"present_mode",
+		"clipped"
+	};
+	return de::getSizedArrayElement<TEST_DIMENSION_LAST>(s_names, dimension);
+}
+
+struct TestParameters
+{
+	vk::wsi::Type	wsiType;
+	TestDimension	dimension;
+
+	TestParameters (vk::wsi::Type wsiType_, TestDimension dimension_)
+		: wsiType	(wsiType_)
+		, dimension	(dimension_)
+	{}
+
+	TestParameters (void)
+		: wsiType	(vk::wsi::TYPE_LAST)
+		, dimension	(TEST_DIMENSION_LAST)
+	{}
+};
+
+std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (vk::wsi::Type								wsiType,
+																		   TestDimension								dimension,
+																		   const vk::VkSurfaceCapabilitiesKHR&			capabilities,
+																		   const std::vector<vk::VkSurfaceFormatKHR>&	formats,
+																		   const std::vector<vk::VkPresentModeKHR>&		presentModes)
+{
+	std::vector<vk::VkSwapchainCreateInfoKHR>	cases;
+	const vk::wsi::PlatformProperties&			platformProperties	= getPlatformProperties(wsiType);
+	const vk::VkSurfaceTransformFlagBitsKHR		defaultTransform	= (capabilities.supportedTransforms & vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+																		? vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
+	const vk::VkSwapchainCreateInfoKHR			baseParameters		=
+	{
+		vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+		DE_NULL,
+		vk::VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR,
+		(vk::VkSurfaceKHR)0,
+		capabilities.minImageCount,
+		formats[0].format,
+		formats[0].colorSpace,
+		(platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE
+			? capabilities.minImageExtent : capabilities.currentExtent),
+		1u,									// imageArrayLayers
+		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+		vk::VK_SHARING_MODE_EXCLUSIVE,
+		0u,
+		(const deUint32*)DE_NULL,
+		defaultTransform,
+		vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+		vk::VK_PRESENT_MODE_FIFO_KHR,
+		VK_FALSE,							// clipped
+		(vk::VkSwapchainKHR)0				// oldSwapchain
+	};
+
+	switch (dimension)
+	{
+		case TEST_DIMENSION_MIN_IMAGE_COUNT:
+		{
+			const deUint32	maxImageCountToTest	= de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u);
+
+			for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount)
+			{
+				cases.push_back(baseParameters);
+				cases.back().minImageCount = imageCount;
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_IMAGE_FORMAT:
+		{
+			for (std::vector<vk::VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
+			{
+				cases.push_back(baseParameters);
+				cases.back().imageFormat		= curFmt->format;
+				cases.back().imageColorSpace	= curFmt->colorSpace;
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_IMAGE_EXTENT:
+		{
+			static const vk::VkExtent2D	s_testSizes[]	=
+			{
+				{ 1, 1 },
+				{ 16, 32 },
+				{ 32, 16 },
+				{ 632, 231 },
+				{ 117, 998 },
+			};
+
+			if (platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE ||
+				platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
+			{
+				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_testSizes); ++ndx)
+				{
+					cases.push_back(baseParameters);
+					cases.back().imageExtent.width	= de::clamp(s_testSizes[ndx].width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
+					cases.back().imageExtent.height	= de::clamp(s_testSizes[ndx].height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
+				}
+			}
+
+			if (platformProperties.swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE)
+			{
+				cases.push_back(baseParameters);
+				cases.back().imageExtent = capabilities.currentExtent;
+			}
+
+			if (platformProperties.swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
+			{
+				cases.push_back(baseParameters);
+				cases.back().imageExtent = capabilities.minImageExtent;
+
+				cases.push_back(baseParameters);
+				cases.back().imageExtent = capabilities.maxImageExtent;
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_IMAGE_ARRAY_LAYERS:
+		{
+			const deUint32	maxLayers	= de::min(capabilities.maxImageArrayLayers, 16u);
+
+			for (deUint32 numLayers = 1; numLayers <= maxLayers; ++numLayers)
+			{
+				cases.push_back(baseParameters);
+				cases.back().imageArrayLayers = numLayers;
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_IMAGE_USAGE:
+		{
+			for (deUint32 flags = 1u; flags <= capabilities.supportedUsageFlags; ++flags)
+			{
+				if ((flags & ~capabilities.supportedUsageFlags) == 0)
+				{
+					cases.push_back(baseParameters);
+					cases.back().imageUsage = flags;
+				}
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_IMAGE_SHARING_MODE:
+		{
+			cases.push_back(baseParameters);
+			cases.back().imageSharingMode = vk::VK_SHARING_MODE_EXCLUSIVE;
+
+			cases.push_back(baseParameters);
+			cases.back().imageSharingMode = vk::VK_SHARING_MODE_CONCURRENT;
+
+			break;
+		}
+
+		case TEST_DIMENSION_PRE_TRANSFORM:
+		{
+			for (deUint32 transform = 1u;
+				 transform <= capabilities.supportedTransforms;
+				 transform = transform<<1u)
+			{
+				if ((transform & capabilities.supportedTransforms) != 0)
+				{
+					cases.push_back(baseParameters);
+					cases.back().preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
+				}
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_COMPOSITE_ALPHA:
+		{
+			for (deUint32 alphaMode = 1u;
+				 alphaMode <= capabilities.supportedCompositeAlpha;
+				 alphaMode = alphaMode<<1u)
+			{
+				if ((alphaMode & capabilities.supportedCompositeAlpha) != 0)
+				{
+					cases.push_back(baseParameters);
+					cases.back().compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alphaMode;
+				}
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_PRESENT_MODE:
+		{
+			for (std::vector<vk::VkPresentModeKHR>::const_iterator curMode = presentModes.begin(); curMode != presentModes.end(); ++curMode)
+			{
+				cases.push_back(baseParameters);
+				cases.back().presentMode = *curMode;
+			}
+
+			break;
+		}
+
+		case TEST_DIMENSION_CLIPPED:
+		{
+			cases.push_back(baseParameters);
+			cases.back().clipped = VK_FALSE;
+
+			cases.push_back(baseParameters);
+			cases.back().clipped = VK_TRUE;
+
+			break;
+		}
+
+		default:
+			DE_FATAL("Impossible");
+	}
+
+	DE_ASSERT(!cases.empty());
+	return cases;
+}
+
+std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (vk::wsi::Type					wsiType,
+																		   TestDimension					dimension,
+																		   const vk::InstanceInterface&		vki,
+																		   vk::VkPhysicalDevice				physicalDevice,
+																		   vk::VkSurfaceKHR					surface)
+{
+	const vk::VkSurfaceCapabilitiesKHR			capabilities	= vk::wsi::getPhysicalDeviceSurfaceCapabilities(vki,
+																											   physicalDevice,
+																											   surface);
+	const std::vector<vk::VkSurfaceFormatKHR>	formats			= vk::wsi::getPhysicalDeviceSurfaceFormats(vki,
+																										   physicalDevice,
+																										   surface);
+	const std::vector<vk::VkPresentModeKHR>		presentModes	= vk::wsi::getPhysicalDeviceSurfacePresentModes(vki,
+																											    physicalDevice,
+																											    surface);
+
+	return generateSwapchainParameterCases(wsiType, dimension, capabilities, formats, presentModes);
+}
+
+tcu::TestStatus createSwapchainTest (Context& baseCtx, TestParameters params)
+{
+	std::vector<vk::VkExtensionProperties>			supportedExtensions (enumerateInstanceExtensionProperties(baseCtx.getPlatformInterface(), DE_NULL));
+	std::vector<std::string>						instExts	= getRequiredWsiExtensions(supportedExtensions, params.wsiType);
+	std::vector<std::string>						devExts;
+	devExts.push_back("VK_KHR_swapchain");
+
+	const NativeObjects								native		(baseCtx, supportedExtensions, params.wsiType);
+	ProtectedContext								context		(baseCtx, params.wsiType, *native.display, *native.window, instExts, devExts);
+	vk::VkSurfaceKHR								surface		= context.getSurface();
+	const std::vector<vk::VkSwapchainCreateInfoKHR>	cases		(generateSwapchainParameterCases(params.wsiType,
+																						 params.dimension,
+																						 context.getInstanceDriver(),
+																						 context.getPhysicalDevice(),
+																						 surface));
+	deUint32										queueIdx	= context.getQueueFamilyIndex();
+	for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+	{
+		vk::VkSwapchainCreateInfoKHR	curParams	= cases[caseNdx];
+
+		curParams.surface				= surface;
+		curParams.queueFamilyIndexCount	= 1u;
+		curParams.pQueueFamilyIndices	= &queueIdx;
+
+		context.getTestContext().getLog()
+			<< tcu::TestLog::Message << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": " << curParams << tcu::TestLog::EndMessage;
+
+		{
+			const vk::Unique<vk::VkSwapchainKHR>	swapchain	(createSwapchainKHR(context.getDeviceDriver(), context.getDevice(), &curParams));
+		}
+	}
+
+	return tcu::TestStatus::pass("Creating swapchain succeeded");
+}
+
+struct GroupParameters
+{
+	typedef FunctionInstance1<TestParameters>::Function	Function;
+
+	vk::wsi::Type	wsiType;
+	Function		function;
+
+	GroupParameters (vk::wsi::Type wsiType_, Function function_)
+		: wsiType	(wsiType_)
+		, function	(function_)
+	{}
+
+	GroupParameters (void)
+		: wsiType	(vk::wsi::TYPE_LAST)
+		, function	((Function)DE_NULL)
+	{}
+};
+
+void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters params)
+{
+	for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
+	{
+		const TestDimension		testDimension	= (TestDimension)dimensionNdx;
+
+		addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension));
+	}
+}
+
+vk::VkSwapchainCreateInfoKHR getBasicSwapchainParameters (vk::wsi::Type					wsiType,
+														  const vk::InstanceInterface&	vki,
+														  vk::VkPhysicalDevice			physicalDevice,
+														  vk::VkSurfaceKHR				surface,
+														  const tcu::UVec2&				desiredSize,
+														  deUint32						desiredImageCount)
+{
+	const vk::VkSurfaceCapabilitiesKHR			capabilities		= vk::wsi::getPhysicalDeviceSurfaceCapabilities(vki,
+																												    physicalDevice,
+																												    surface);
+	const std::vector<vk::VkSurfaceFormatKHR>	formats				= vk::wsi::getPhysicalDeviceSurfaceFormats(vki,
+																											   physicalDevice,
+																											   surface);
+	const vk::wsi::PlatformProperties&			platformProperties	= vk::wsi::getPlatformProperties(wsiType);
+	const vk::VkSurfaceTransformFlagBitsKHR		transform			= (capabilities.supportedTransforms & vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+																		? vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
+	const vk::VkSwapchainCreateInfoKHR			parameters			=
+	{
+		vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+		DE_NULL,
+		vk::VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR,
+		surface,
+		de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
+		formats[0].format,
+		formats[0].colorSpace,
+		(platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
+			? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
+		1u,									// imageArrayLayers
+		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+		vk::VK_SHARING_MODE_EXCLUSIVE,
+		0u,
+		(const deUint32*)DE_NULL,
+		transform,
+		vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+		vk::VK_PRESENT_MODE_FIFO_KHR,
+		VK_FALSE,							// clipped
+		(vk::VkSwapchainKHR)0				// oldSwapchain
+	};
+
+	return parameters;
+}
+
+typedef de::SharedPtr<vk::Unique<vk::VkImageView> >		ImageViewSp;
+typedef de::SharedPtr<vk::Unique<vk::VkFramebuffer> >	FramebufferSp;
+
+class TriangleRenderer
+{
+public:
+												TriangleRenderer	(ProtectedContext&				context,
+																	 const vk::BinaryCollection&	binaryRegistry,
+																	 const std::vector<vk::VkImage>	swapchainImages,
+																	 const vk::VkFormat				framebufferFormat,
+																	 const tcu::UVec2&				renderSize);
+												~TriangleRenderer	(void);
+
+	void										recordFrame			(vk::VkCommandBuffer			cmdBuffer,
+																	 deUint32						imageNdx,
+																	 deUint32						frameNdx) const;
+
+	static void									getPrograms			(vk::SourceCollections&			dst);
+
+private:
+	static vk::Move<vk::VkRenderPass>			createRenderPass	(const vk::DeviceInterface&		vkd,
+																	 const vk::VkDevice				device,
+																	 const vk::VkFormat				colorAttachmentFormat);
+	static vk::Move<vk::VkPipelineLayout>		createPipelineLayout(const vk::DeviceInterface&		vkd,
+																	 vk::VkDevice					device);
+	static vk::Move<vk::VkPipeline>				createPipeline		(const vk::DeviceInterface&		vkd,
+																	 const vk::VkDevice				device,
+																	 const vk::VkRenderPass			renderPass,
+																	 const vk::VkPipelineLayout		pipelineLayout,
+																	 const vk::BinaryCollection&	binaryCollection,
+																	 const tcu::UVec2&				renderSize);
+
+	const vk::DeviceInterface&					m_vkd;
+
+	const std::vector<vk::VkImage>				m_swapchainImages;
+	const tcu::UVec2							m_renderSize;
+
+	const vk::Unique<vk::VkRenderPass>			m_renderPass;
+	const vk::Unique<vk::VkPipelineLayout>		m_pipelineLayout;
+	const vk::Unique<vk::VkPipeline>			m_pipeline;
+
+	const de::UniquePtr<vk::BufferWithMemory>	m_vertexBuffer;
+
+	std::vector<ImageViewSp>					m_attachmentViews;
+	std::vector<FramebufferSp>					m_framebuffers;
+};
+
+vk::Move<vk::VkRenderPass> TriangleRenderer::createRenderPass (const vk::DeviceInterface&	vkd,
+															   const vk::VkDevice			device,
+															   const vk::VkFormat			colorAttachmentFormat)
+{
+	const vk::VkAttachmentDescription	colorAttDesc		=
+	{
+		(vk::VkAttachmentDescriptionFlags)0,
+		colorAttachmentFormat,
+		vk::VK_SAMPLE_COUNT_1_BIT,
+		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
+		vk::VK_ATTACHMENT_STORE_OP_STORE,
+		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
+		vk::VK_IMAGE_LAYOUT_UNDEFINED,
+		vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+	};
+	const vk::VkAttachmentReference		colorAttRef			=
+	{
+		0u,
+		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+	};
+	const vk::VkSubpassDescription		subpassDesc			=
+	{
+		(vk::VkSubpassDescriptionFlags)0u,
+		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
+		0u,							// inputAttachmentCount
+		DE_NULL,					// pInputAttachments
+		1u,							// colorAttachmentCount
+		&colorAttRef,				// pColorAttachments
+		DE_NULL,					// pResolveAttachments
+		DE_NULL,					// depthStencilAttachment
+		0u,							// preserveAttachmentCount
+		DE_NULL,					// pPreserveAttachments
+	};
+	const vk::VkSubpassDependency		dependencies[]		=
+	{
+		{
+			VK_SUBPASS_EXTERNAL,	// srcSubpass
+			0u,						// dstSubpass
+			vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+			vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+			vk::VK_ACCESS_MEMORY_READ_BIT,
+			(vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
+			 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
+			vk::VK_DEPENDENCY_BY_REGION_BIT
+		},
+		{
+			0u,						// srcSubpass
+			VK_SUBPASS_EXTERNAL,	// dstSubpass
+			vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+			vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+			(vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
+			 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
+			vk::VK_ACCESS_MEMORY_READ_BIT,
+			vk::VK_DEPENDENCY_BY_REGION_BIT
+		},
+	};
+	const vk::VkRenderPassCreateInfo	renderPassParams	=
+	{
+		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+		DE_NULL,
+		(vk::VkRenderPassCreateFlags)0,
+		1u,
+		&colorAttDesc,
+		1u,
+		&subpassDesc,
+		DE_LENGTH_OF_ARRAY(dependencies),
+		dependencies,
+	};
+
+	return vk::createRenderPass(vkd, device, &renderPassParams);
+}
+
+vk::Move<vk::VkPipelineLayout> TriangleRenderer::createPipelineLayout (const vk::DeviceInterface&	vkd,
+																	   const vk::VkDevice			device)
+{
+	const vk::VkPushConstantRange					pushConstantRange		=
+	{
+		vk::VK_SHADER_STAGE_VERTEX_BIT,
+		0u,											// offset
+		(deUint32)sizeof(deUint32),					// size
+	};
+	const vk::VkPipelineLayoutCreateInfo			pipelineLayoutParams	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineLayoutCreateFlags)0,
+		0u,											// setLayoutCount
+		DE_NULL,									// pSetLayouts
+		1u,
+		&pushConstantRange,
+	};
+
+	return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
+}
+
+vk::Move<vk::VkPipeline> TriangleRenderer::createPipeline (const vk::DeviceInterface&	vkd,
+														   const vk::VkDevice			device,
+														   const vk::VkRenderPass		renderPass,
+														   const vk::VkPipelineLayout	pipelineLayout,
+														   const vk::BinaryCollection&	binaryCollection,
+														   const tcu::UVec2&			renderSize)
+{
+	// \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
+	//		 and can be deleted immediately following that call.
+	const vk::Unique<vk::VkShaderModule>				vertShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
+	const vk::Unique<vk::VkShaderModule>				fragShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
+
+	const vk::VkPipelineShaderStageCreateInfo			shaderStageParams[]		=
+	{
+		{
+			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+			DE_NULL,
+			(vk::VkPipelineShaderStageCreateFlags)0,
+			vk::VK_SHADER_STAGE_VERTEX_BIT,
+			*vertShaderModule,
+			"main",
+			DE_NULL
+		},
+		{
+			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+			DE_NULL,
+			(vk::VkPipelineShaderStageCreateFlags)0,
+			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
+			*fragShaderModule,
+			"main",
+			DE_NULL
+		}
+	};
+	const vk::VkPipelineDepthStencilStateCreateInfo		depthStencilParams		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineDepthStencilStateCreateFlags)0,
+		DE_FALSE,									// depthTestEnable
+		DE_FALSE,									// depthWriteEnable
+		vk::VK_COMPARE_OP_ALWAYS,					// depthCompareOp
+		DE_FALSE,									// depthBoundsTestEnable
+		DE_FALSE,									// stencilTestEnable
+		{
+			vk::VK_STENCIL_OP_KEEP,						// failOp
+			vk::VK_STENCIL_OP_KEEP,						// passOp
+			vk::VK_STENCIL_OP_KEEP,						// depthFailOp
+			vk::VK_COMPARE_OP_ALWAYS,					// compareOp
+			0u,											// compareMask
+			0u,											// writeMask
+			0u,											// reference
+		},											// front
+		{
+			vk::VK_STENCIL_OP_KEEP,						// failOp
+			vk::VK_STENCIL_OP_KEEP,						// passOp
+			vk::VK_STENCIL_OP_KEEP,						// depthFailOp
+			vk::VK_COMPARE_OP_ALWAYS,					// compareOp
+			0u,											// compareMask
+			0u,											// writeMask
+			0u,											// reference
+		},											// back
+		-1.0f,										// minDepthBounds
+		+1.0f,										// maxDepthBounds
+	};
+	const vk::VkViewport								viewport0				=
+	{
+		0.0f,										// x
+		0.0f,										// y
+		(float)renderSize.x(),						// width
+		(float)renderSize.y(),						// height
+		0.0f,										// minDepth
+		1.0f,										// maxDepth
+	};
+	const vk::VkRect2D									scissor0				=
+	{
+		{ 0u, 0u, },								// offset
+		{ renderSize.x(), renderSize.y() },			// extent
+	};
+	const vk::VkPipelineViewportStateCreateInfo			viewportParams			=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineViewportStateCreateFlags)0,
+		1u,
+		&viewport0,
+		1u,
+		&scissor0
+	};
+	const vk::VkPipelineMultisampleStateCreateInfo		multisampleParams		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineMultisampleStateCreateFlags)0,
+		vk::VK_SAMPLE_COUNT_1_BIT,					// rasterizationSamples
+		VK_FALSE,									// sampleShadingEnable
+		0.0f,										// minSampleShading
+		(const vk::VkSampleMask*)DE_NULL,			// sampleMask
+		VK_FALSE,									// alphaToCoverageEnable
+		VK_FALSE,									// alphaToOneEnable
+	};
+	const vk::VkPipelineRasterizationStateCreateInfo	rasterParams			=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineRasterizationStateCreateFlags)0,
+		VK_FALSE,										// depthClampEnable
+		VK_FALSE,										// rasterizerDiscardEnable
+		vk::VK_POLYGON_MODE_FILL,						// polygonMode
+		vk::VK_CULL_MODE_NONE,							// cullMode
+		vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,			// frontFace
+		VK_FALSE,										// depthBiasEnable
+		0.0f,											// depthBiasConstantFactor
+		0.0f,											// depthBiasClamp
+		0.0f,											// depthBiasSlopeFactor
+		1.0f,											// lineWidth
+	};
+	const vk::VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams		=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineInputAssemblyStateCreateFlags)0,
+		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+		DE_FALSE,									// primitiveRestartEnable
+	};
+	const vk::VkVertexInputBindingDescription			vertexBinding0			=
+	{
+		0u,											// binding
+		(deUint32)sizeof(tcu::Vec4),				// stride
+		vk::VK_VERTEX_INPUT_RATE_VERTEX,			// inputRate
+	};
+	const vk::VkVertexInputAttributeDescription			vertexAttrib0			=
+	{
+		0u,											// location
+		0u,											// binding
+		vk::VK_FORMAT_R32G32B32A32_SFLOAT,			// format
+		0u,											// offset
+	};
+	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineVertexInputStateCreateFlags)0,
+		1u,
+		&vertexBinding0,
+		1u,
+		&vertexAttrib0,
+	};
+	const vk::VkPipelineColorBlendAttachmentState		attBlendParams0			=
+	{
+		VK_FALSE,									// blendEnable
+		vk::VK_BLEND_FACTOR_ONE,					// srcColorBlendFactor
+		vk::VK_BLEND_FACTOR_ZERO,					// dstColorBlendFactor
+		vk::VK_BLEND_OP_ADD,						// colorBlendOp
+		vk::VK_BLEND_FACTOR_ONE,					// srcAlphaBlendFactor
+		vk::VK_BLEND_FACTOR_ZERO,					// dstAlphaBlendFactor
+		vk::VK_BLEND_OP_ADD,						// alphaBlendOp
+		(vk::VK_COLOR_COMPONENT_R_BIT|
+		 vk::VK_COLOR_COMPONENT_G_BIT|
+		 vk::VK_COLOR_COMPONENT_B_BIT|
+		 vk::VK_COLOR_COMPONENT_A_BIT),				// colorWriteMask
+	};
+	const vk::VkPipelineColorBlendStateCreateInfo		blendParams				=
+	{
+		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineColorBlendStateCreateFlags)0,
+		VK_FALSE,									// logicOpEnable
+		vk::VK_LOGIC_OP_COPY,
+		1u,
+		&attBlendParams0,
+		{ 0.0f, 0.0f, 0.0f, 0.0f },					// blendConstants[4]
+	};
+	const vk::VkGraphicsPipelineCreateInfo				pipelineParams			=
+	{
+		vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+		DE_NULL,
+		(vk::VkPipelineCreateFlags)0,
+		(deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams),
+		shaderStageParams,
+		&vertexInputStateParams,
+		&inputAssemblyParams,
+		(const vk::VkPipelineTessellationStateCreateInfo*)DE_NULL,
+		&viewportParams,
+		&rasterParams,
+		&multisampleParams,
+		&depthStencilParams,
+		&blendParams,
+		(const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL,
+		pipelineLayout,
+		renderPass,
+		0u,											// subpass
+		DE_NULL,									// basePipelineHandle
+		0u,											// basePipelineIndex
+	};
+
+	return vk::createGraphicsPipeline(vkd, device, (vk::VkPipelineCache)0, &pipelineParams);
+}
+
+TriangleRenderer::TriangleRenderer (ProtectedContext&				context,
+									const vk::BinaryCollection&		binaryRegistry,
+									const std::vector<vk::VkImage>	swapchainImages,
+									const vk::VkFormat				framebufferFormat,
+									const tcu::UVec2&				renderSize)
+	: m_vkd					(context.getDeviceInterface())
+	, m_swapchainImages		(swapchainImages)
+	, m_renderSize			(renderSize)
+	, m_renderPass			(createRenderPass(m_vkd, context.getDevice(), framebufferFormat))
+	, m_pipelineLayout		(createPipelineLayout(m_vkd, context.getDevice()))
+	, m_pipeline			(createPipeline(m_vkd, context.getDevice(), *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
+	, m_vertexBuffer		(makeBuffer(context,
+									PROTECTION_DISABLED,
+									context.getQueueFamilyIndex(),
+									(deUint32)(sizeof(float)*4*3),
+									vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+									vk::MemoryRequirement::HostVisible))
+{
+	m_attachmentViews.resize(swapchainImages.size());
+	m_framebuffers.resize(swapchainImages.size());
+
+	for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
+	{
+		m_attachmentViews[imageNdx]	= ImageViewSp(new vk::Unique<vk::VkImageView>(createImageView(context, swapchainImages[imageNdx], framebufferFormat)));
+		m_framebuffers[imageNdx]	= FramebufferSp(new vk::Unique<vk::VkFramebuffer>(createFramebuffer(context,
+																										renderSize.x(),
+																										renderSize.y(),
+																										*m_renderPass,
+																										**m_attachmentViews[imageNdx])));
+	}
+
+	// Upload vertex data
+	{
+		const tcu::Vec4				vertices[]	=
+		{
+			tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
+			tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
+			tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
+		};
+		DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
+
+		deMemcpy(m_vertexBuffer->getAllocation().getHostPtr(), &vertices[0], sizeof(vertices));
+		vk::flushMappedMemoryRange(m_vkd, context.getDevice(), m_vertexBuffer->getAllocation().getMemory(), m_vertexBuffer->getAllocation().getOffset(), sizeof(vertices));
+	}
+}
+
+TriangleRenderer::~TriangleRenderer (void)
+{
+}
+
+void TriangleRenderer::recordFrame (vk::VkCommandBuffer	cmdBuffer,
+									deUint32			imageNdx,
+									deUint32			frameNdx) const
+{
+	const vk::VkFramebuffer	curFramebuffer	= **m_framebuffers[imageNdx];
+
+	beginCommandBuffer(m_vkd, cmdBuffer);
+
+	{
+		const vk::VkClearValue			clearValue		= vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
+		const vk::VkRenderPassBeginInfo	passBeginParams	=
+		{
+			vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+			DE_NULL,
+			*m_renderPass,
+			curFramebuffer,
+			{
+				{ 0, 0 },
+				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
+			},													// renderArea
+			1u,													// clearValueCount
+			&clearValue,										// pClearValues
+		};
+		m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, vk::VK_SUBPASS_CONTENTS_INLINE);
+	}
+
+	m_vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
+
+	{
+		const vk::VkDeviceSize bindingOffset = 0;
+		m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer->get(), &bindingOffset);
+	}
+
+	m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
+	m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
+	m_vkd.cmdEndRenderPass(cmdBuffer);
+
+	VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer));
+}
+
+void TriangleRenderer::getPrograms (vk::SourceCollections& dst)
+{
+	dst.glslSources.add("tri-vert") << glu::VertexSource(
+		"#version 310 es\n"
+		"layout(location = 0) in highp vec4 a_position;\n"
+		"layout(push_constant) uniform FrameData\n"
+		"{\n"
+		"    highp uint frameNdx;\n"
+		"} frameData;\n"
+		"void main (void)\n"
+		"{\n"
+		"    highp float angle = float(frameData.frameNdx) / 100.0;\n"
+		"    highp float c     = cos(angle);\n"
+		"    highp float s     = sin(angle);\n"
+		"    highp mat4  t     = mat4( c, -s,  0,  0,\n"
+		"                              s,  c,  0,  0,\n"
+		"                              0,  0,  1,  0,\n"
+		"                              0,  0,  0,  1);\n"
+		"    gl_Position = t * a_position;\n"
+		"}\n");
+	dst.glslSources.add("tri-frag") << glu::FragmentSource(
+		"#version 310 es\n"
+		"layout(location = 0) out lowp vec4 o_color;\n"
+		"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
+}
+
+typedef de::SharedPtr<vk::Unique<vk::VkCommandBuffer> >	CommandBufferSp;
+typedef de::SharedPtr<vk::Unique<vk::VkFence> >			FenceSp;
+typedef de::SharedPtr<vk::Unique<vk::VkSemaphore> >		SemaphoreSp;
+
+std::vector<FenceSp> createFences (const vk::DeviceInterface&	vkd,
+								   const vk::VkDevice			device,
+								   size_t						numFences)
+{
+	std::vector<FenceSp> fences(numFences);
+
+	for (size_t ndx = 0; ndx < numFences; ++ndx)
+		fences[ndx] = FenceSp(new vk::Unique<vk::VkFence>(createFence(vkd, device)));
+
+	return fences;
+}
+
+std::vector<SemaphoreSp> createSemaphores (const vk::DeviceInterface&	vkd,
+										   const vk::VkDevice			device,
+										   size_t						numSemaphores)
+{
+	std::vector<SemaphoreSp> semaphores(numSemaphores);
+
+	for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
+		semaphores[ndx] = SemaphoreSp(new vk::Unique<vk::VkSemaphore>(createSemaphore(vkd, device)));
+
+	return semaphores;
+}
+
+std::vector<CommandBufferSp> allocateCommandBuffers (const vk::DeviceInterface&		vkd,
+													 const vk::VkDevice				device,
+													 const vk::VkCommandPool		commandPool,
+													 const vk::VkCommandBufferLevel	level,
+													 const size_t					numCommandBuffers)
+{
+	std::vector<CommandBufferSp>			buffers		(numCommandBuffers);
+
+	for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
+		buffers[ndx] = CommandBufferSp(new vk::Unique<vk::VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
+
+	return buffers;
+}
+
+tcu::TestStatus basicRenderTest (Context& baseCtx, vk::wsi::Type wsiType)
+{
+	std::vector<vk::VkExtensionProperties>	supportedExtensions			(enumerateInstanceExtensionProperties(baseCtx.getPlatformInterface(), DE_NULL));
+	std::vector<std::string>				instExts					= getRequiredWsiExtensions(supportedExtensions, wsiType);
+	std::vector<std::string>				devExts;
+	devExts.push_back("VK_KHR_swapchain");
+
+	const tcu::UVec2						desiredSize					(256, 256);
+	const NativeObjects						native						(baseCtx,  supportedExtensions, wsiType, tcu::just(desiredSize));
+	ProtectedContext						context						(baseCtx, wsiType, *native.display, *native.window, instExts, devExts);
+	vk::VkSurfaceKHR						surface						= context.getSurface();
+	const vk::DeviceInterface&				vkd							= context.getDeviceInterface();
+	const vk::VkDevice						device						= context.getDevice();
+	const vk::VkSwapchainCreateInfoKHR		swapchainInfo				= getBasicSwapchainParameters(wsiType,
+																								  context.getInstanceDriver(),
+																								  context.getPhysicalDevice(),
+																								  surface,
+																								  desiredSize,
+																								  2);
+	const vk::Unique<vk::VkSwapchainKHR>	swapchain					(createSwapchainKHR(vkd, device, &swapchainInfo));
+	const std::vector<vk::VkImage>			swapchainImages				= vk::wsi::getSwapchainImages(vkd, device, *swapchain);
+
+	const TriangleRenderer					renderer					(context,
+																		 context.getBinaryCollection(),
+																		 swapchainImages,
+																		 swapchainInfo.imageFormat,
+																		 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
+
+	const vk::Unique<vk::VkCommandPool>		commandPool					(makeCommandPool(vkd, device, PROTECTION_ENABLED,
+																					 context.getQueueFamilyIndex()));
+
+	const size_t							maxQueuedFrames				= swapchainImages.size()*2;
+
+	// We need to keep hold of fences from vkAcquireNextImageKHR to actually
+	// limit number of frames we allow to be queued.
+	const std::vector<FenceSp>				imageReadyFences			(createFences(vkd, device, maxQueuedFrames));
+
+	// We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
+	// the semaphore in same time as the fence we use to meter rendering.
+	const std::vector<SemaphoreSp>			imageReadySemaphores		(createSemaphores(vkd, device, maxQueuedFrames+1));
+
+	// For rest we simply need maxQueuedFrames as we will wait for image
+	// from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
+	// previous uses must have completed.
+	const std::vector<SemaphoreSp>			renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames));
+	const std::vector<CommandBufferSp>		commandBuffers				(allocateCommandBuffers(vkd,
+																								device,
+																								*commandPool,
+																								vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+																								maxQueuedFrames));
+
+	try
+	{
+		const deUint32	numFramesToRender	= 60*10;
+
+		for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
+		{
+			const vk::VkFence		imageReadyFence		= **imageReadyFences[frameNdx%imageReadyFences.size()];
+			const vk::VkSemaphore	imageReadySemaphore	= **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
+			deUint32				imageNdx			= ~0u;
+
+			if (frameNdx >= maxQueuedFrames)
+				VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
+
+			VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
+
+			{
+				const vk::VkResult	acquireResult	= vkd.acquireNextImageKHR(device,
+																			  *swapchain,
+																			  std::numeric_limits<deUint64>::max(),
+																			  imageReadySemaphore,
+																			  imageReadyFence,
+																			  &imageNdx);
+
+				if (acquireResult == vk::VK_SUBOPTIMAL_KHR)
+					context.getTestContext().getLog() << tcu::TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << tcu::TestLog::EndMessage;
+				else
+					VK_CHECK(acquireResult);
+			}
+
+			TCU_CHECK((size_t)imageNdx < swapchainImages.size());
+
+			{
+				const vk::VkSemaphore			renderingCompleteSemaphore	= **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
+				const vk::VkCommandBuffer		commandBuffer				= **commandBuffers[frameNdx%commandBuffers.size()];
+				const vk::VkPipelineStageFlags	waitDstStage				= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+				vk::VkSubmitInfo				submitInfo					=
+				{
+					vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
+					DE_NULL,
+					1u,
+					&imageReadySemaphore,
+					&waitDstStage,
+					1u,
+					&commandBuffer,
+					1u,
+					&renderingCompleteSemaphore
+				};
+
+				const vk::VkProtectedSubmitInfoKHR  protectedInfo   =
+				{
+					vk::VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO_KHR,	// sType
+					DE_NULL,											// pNext
+					VK_TRUE,											// protectedSubmit
+				};
+				submitInfo.pNext = &protectedInfo;
+
+				const vk::VkPresentInfoKHR		presentInfo					=
+				{
+					vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+					DE_NULL,
+					1u,
+					&renderingCompleteSemaphore,
+					1u,
+					&*swapchain,
+					&imageNdx,
+					(vk::VkResult*)DE_NULL
+				};
+
+				renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
+				VK_CHECK(vkd.queueSubmit(context.getQueue(), 1u, &submitInfo, (vk::VkFence)0));
+				VK_CHECK(vkd.queuePresentKHR(context.getQueue(), &presentInfo));
+			}
+		}
+
+		VK_CHECK(vkd.deviceWaitIdle(device));
+	}
+	catch (...)
+	{
+		// Make sure device is idle before destroying resources
+		vkd.deviceWaitIdle(device);
+		throw;
+	}
+
+	return tcu::TestStatus::pass("Rendering tests succeeded");
+}
+
+void getBasicRenderPrograms (vk::SourceCollections& dst, vk::wsi::Type)
+{
+	TriangleRenderer::getPrograms(dst);
+}
+
+void populateRenderGroup (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
+{
+	addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest, wsiType);
+}
+
+void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
+{
+	addTestGroup(testGroup, "create",			"Create VkSwapchain with various parameters",					populateSwapchainGroup,		GroupParameters(wsiType, createSwapchainTest));
+	addTestGroup(testGroup, "render",			"Rendering Tests",												populateRenderGroup,		wsiType);
+}
+
+void createTypeSpecificTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
+{
+	addTestGroup(testGroup, "swapchain", "VkSwapchain Tests", createSwapchainTests, wsiType);
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createSwapchainTests (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> wsiTestGroup (new tcu::TestCaseGroup(testCtx, "wsi", "WSI Tests"));
+
+	for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
+	{
+		const vk::wsi::Type	wsiType		= (vk::wsi::Type)typeNdx;
+
+		addTestGroup(&*wsiTestGroup, getName(wsiType), "", createTypeSpecificTests, wsiType);
+	}
+
+	return wsiTestGroup.release();
+}
+
+} // wsi
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.hpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.hpp
new file mode 100644
index 0000000..c89094f
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemWsiSwapchainTests.hpp
@@ -0,0 +1,41 @@
+#ifndef _VKTPROTECTEDMEMWSISWAPCHAINTESTS_HPP
+#define _VKTPROTECTEDMEMWSISWAPCHAINTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 Protected memory interaction with VkSwapchain Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+#include "vkDefs.hpp"
+
+namespace vkt
+{
+namespace ProtectedMem
+{
+
+tcu::TestCaseGroup* createSwapchainTests (tcu::TestContext& testCtx);
+
+} // wsi
+} // vkt
+
+#endif // _VKTPROTECTEDMEMWSISWAPCHAINTESTS_HPP
diff --git a/external/vulkancts/mustpass/1.1.0/vk-default.txt b/external/vulkancts/mustpass/1.1.0/vk-default.txt
index 13bd952..e6c6d20 100755
--- a/external/vulkancts/mustpass/1.1.0/vk-default.txt
+++ b/external/vulkancts/mustpass/1.1.0/vk-default.txt
@@ -274072,3 +274072,69 @@
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_8
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_9
 dEQP-VK.protected_memory.ssbo.ssbo_atomic.compute.compswap.random.atomic_compswap_10
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.xlib.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.xcb.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.wayland.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.mir.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.android.swapchain.render.basic
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.min_image_count
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_format
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_extent
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_array_layers
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_usage
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.image_sharing_mode
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.pre_transform
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.composite_alpha
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.present_mode
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.create.clipped
+dEQP-VK.protected_memory.interaction.wsi.win32.swapchain.render.basic