Avoid creating vkInstances for not supported cases

Defer vkInstance creation for cross instance tests until not supported
checks complete to shorten the runtime of these 10k total test cases.

Affects: dEQP-VK.synchronization.cross_instance.*

Components: Vulkan

VK-GL-CTS Issue: 885

Change-Id: I481de90d8c0363c23a287aaf457ac101c327c558
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
index b3c8cf9..071ce13 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
@@ -72,6 +72,178 @@
 	const bool											dedicated;
 };
 
+// A helper class to test for extensions upfront and throw not supported to speed up test runtimes compared to failing only
+// after creating unnecessary vkInstances.  A common example of this is win32 platforms taking a long time to run _fd tests.
+class NotSupportedChecker
+{
+public:
+				NotSupportedChecker	(const Context&			 context,
+									 TestConfig				 config,
+									 const OperationSupport& writeOp,
+									 const OperationSupport& readOp)
+	: m_context	(context)
+	{
+		// Check instance support
+		requireInstanceExtension("VK_KHR_get_physical_device_properties2");
+
+		requireInstanceExtension("VK_KHR_external_semaphore_capabilities");
+		requireInstanceExtension("VK_KHR_external_memory_capabilities");
+
+		// Check device support
+		if (config.dedicated)
+			requireDeviceExtension("VK_KHR_dedicated_allocation");
+
+		requireDeviceExtension("VK_KHR_external_semaphore");
+		requireDeviceExtension("VK_KHR_external_memory");
+
+		if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
+			|| config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
+			|| config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
+		{
+			requireDeviceExtension("VK_KHR_external_semaphore_fd");
+			requireDeviceExtension("VK_KHR_external_memory_fd");
+		}
+
+		if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
+			|| config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
+			|| config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
+			|| config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
+		{
+			requireDeviceExtension("VK_KHR_external_semaphore_win32");
+			requireDeviceExtension("VK_KHR_external_memory_win32");
+		}
+
+		TestLog&						log				= context.getTestContext().getLog();
+		const vk::InstanceInterface&	vki				= context.getInstanceInterface();
+		const vk::VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
+
+		// Check resource support
+		if (config.resource.type == RESOURCE_TYPE_IMAGE)
+		{
+			const vk::VkPhysicalDeviceExternalImageFormatInfoKHR	externalInfo		=
+			{
+				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
+				DE_NULL,
+				config.memoryHandleType
+			};
+			const vk::VkPhysicalDeviceImageFormatInfo2KHR	imageFormatInfo		=
+			{
+				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
+				&externalInfo,
+				config.resource.imageFormat,
+				config.resource.imageType,
+				vk::VK_IMAGE_TILING_OPTIMAL,
+				readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
+				0u
+			};
+			vk::VkExternalImageFormatPropertiesKHR			externalProperties	=
+			{
+				vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
+				DE_NULL,
+				{ 0u, 0u, 0u }
+			};
+			vk::VkImageFormatProperties2KHR					formatProperties	=
+			{
+				vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
+				&externalProperties,
+				{
+					{ 0u, 0u, 0u },
+					0u,
+					0u,
+					0u,
+					0u,
+				}
+			};
+
+			{
+				const vk::VkResult res = vki.getPhysicalDeviceImageFormatProperties2KHR(physicalDevice, &imageFormatInfo, &formatProperties);
+
+				if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
+					TCU_THROW(NotSupportedError, "Image format not supported");
+
+				VK_CHECK(res); // Check other errors
+			}
+
+			log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
+
+			if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
+				TCU_THROW(NotSupportedError, "Exporting image resource not supported");
+
+			if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
+				TCU_THROW(NotSupportedError, "Importing image resource not supported");
+
+			if (!config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
+			{
+				TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
+			}
+		}
+		else
+		{
+			const vk::VkPhysicalDeviceExternalBufferInfoKHR	info	=
+			{
+				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
+				DE_NULL,
+
+				0u,
+				readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
+				config.memoryHandleType
+			};
+			vk::VkExternalBufferPropertiesKHR				properties			=
+			{
+				vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
+				DE_NULL,
+				{ 0u, 0u, 0u}
+			};
+			vki.getPhysicalDeviceExternalBufferPropertiesKHR(physicalDevice, &info, &properties);
+
+			log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
+
+			if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
+				|| (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
+				TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
+
+			if (!config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
+			{
+				TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
+			}
+		}
+
+		// Check semaphore support
+		{
+			const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR	info		=
+			{
+				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
+				DE_NULL,
+				config.semaphoreHandleType
+			};
+			vk::VkExternalSemaphorePropertiesKHR				properties;
+
+			vki.getPhysicalDeviceExternalSemaphorePropertiesKHR(physicalDevice, &info, &properties);
+
+			log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
+
+			if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
+				|| (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
+				TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
+		}
+	}
+
+private:
+	void requireDeviceExtension(const char* name) const
+	{
+		if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), name))
+			TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str());
+	}
+
+	void requireInstanceExtension(const char* name) const
+	{
+		if (!de::contains(m_context.getInstanceExtensions().begin(), m_context.getInstanceExtensions().end(), name))
+			TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str());
+	}
+
+	const Context& m_context;
+};
+
 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
 {
 	if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
@@ -813,6 +985,7 @@
 	const TestConfig									m_config;
 	const de::UniquePtr<OperationSupport>				m_supportWriteOp;
 	const de::UniquePtr<OperationSupport>				m_supportReadOp;
+	const NotSupportedChecker							m_notSupportedChecker; // Must declare before VkInstance to effectively reduce runtimes!
 
 	const vk::Unique<vk::VkInstance>					m_instanceA;
 
@@ -850,6 +1023,7 @@
 	, m_config					(config)
 	, m_supportWriteOp			(makeOperationSupport(config.writeOp, config.resource))
 	, m_supportReadOp			(makeOperationSupport(config.readOp, config.resource))
+	, m_notSupportedChecker		(context, m_config, *m_supportWriteOp, *m_supportReadOp)
 
 	, m_instanceA				(createInstance(context.getPlatformInterface()))
 
@@ -877,117 +1051,6 @@
 	, m_queueANdx				(0)
 	, m_queueBNdx				(0)
 {
-	TestLog& log = m_context.getTestContext().getLog();
-
-	// Check resource support
-	if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
-	{
-		const vk::VkPhysicalDeviceExternalImageFormatInfoKHR	externalInfo		=
-		{
-			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
-			DE_NULL,
-			m_memoryHandleType
-		};
-		const vk::VkPhysicalDeviceImageFormatInfo2KHR	imageFormatInfo		=
-		{
-			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
-			&externalInfo,
-			m_config.resource.imageFormat,
-			m_config.resource.imageType,
-			vk::VK_IMAGE_TILING_OPTIMAL,
-			m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
-			0u
-		};
-		vk::VkExternalImageFormatPropertiesKHR			externalProperties	=
-		{
-			vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
-			DE_NULL,
-			{ 0u, 0u, 0u }
-		};
-		vk::VkImageFormatProperties2KHR					formatProperties	=
-		{
-			vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
-			&externalProperties,
-			{
-				{ 0u, 0u, 0u },
-				0u,
-				0u,
-				0u,
-				0u,
-			}
-		};
-
-		{
-			const vk::VkResult res = m_vkiA.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDeviceA, &imageFormatInfo, &formatProperties);
-
-			if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
-				TCU_THROW(NotSupportedError, "Image format not supported");
-
-			VK_CHECK(res); // Check other errors
-		}
-
-		log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
-
-		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
-			TCU_THROW(NotSupportedError, "Exporting image resource not supported");
-
-		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
-			TCU_THROW(NotSupportedError, "Importing image resource not supported");
-
-		if (!m_config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
-		{
-			TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
-		}
-	}
-	else
-	{
-		const vk::VkPhysicalDeviceExternalBufferInfoKHR	info	=
-		{
-			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
-			DE_NULL,
-
-			0u,
-			m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
-			m_memoryHandleType
-		};
-		vk::VkExternalBufferPropertiesKHR				properties			=
-		{
-			vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
-			DE_NULL,
-			{ 0u, 0u, 0u}
-		};
-		m_vkiA.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDeviceA, &info, &properties);
-
-		log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
-
-		if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
-				|| (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
-			TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
-
-		if (!m_config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
-		{
-			TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
-		}
-	}
-
-	// Check semaphore support
-	{
-		const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR	info		=
-		{
-			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
-			DE_NULL,
-			m_semaphoreHandleType
-		};
-		vk::VkExternalSemaphorePropertiesKHR				properties;
-
-		m_vkiA.getPhysicalDeviceExternalSemaphorePropertiesKHR(m_physicalDeviceA, &info, &properties);
-
-		log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
-
-		if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
-				|| (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
-			TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
-	}
 }
 
 tcu::TestStatus SharingTestInstance::iterate (void)