Use proper image tiling in synchronization test support checks

Some test variants use LINEAR instead of OPTIMAL tiling and the proper
tiling mode features need to be checked.

Affected tests:
dEQP-VK.synchronization.*

Components: Vulkan
VK-GL-CTS issue: 3572

Change-Id: I16042ace7fb3a2f93b1503e539a5bbe59e03ae14
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
index 73ddddc..4facf5f 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationCrossInstanceSharingTests.cpp
@@ -794,6 +794,7 @@
 			DE_NULL,
 			(vk::VkExternalMemoryHandleTypeFlags)externalType
 		};
+		const vk::VkImageTiling				tiling					= chooseTiling(externalType);
 		const vk::VkImageCreateInfo			createInfo				=
 		{
 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -806,7 +807,7 @@
 			1u,
 			1u,
 			resourceDesc.imageSamples,
-			chooseTiling(externalType),
+			tiling,
 			readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
 			vk::VK_SHARING_MODE_EXCLUSIVE,
 
@@ -818,7 +819,7 @@
 		vk::Move<vk::VkImage>			image		= vk::createImage(vkd, device, &createInfo);
 		de::MovePtr<vk::Allocation>		allocation	= importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
 
-		return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
+		return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers, tiling));
 	}
 	else
 	{
@@ -1079,6 +1080,7 @@
 
 			vk::Move<vk::VkImage>			image					= createImage(m_vkdA, *m_deviceA, resourceDesc, extent, m_queueFamilyIndicesA,
 																				  *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType);
+			const vk::VkImageTiling			tiling					= chooseTiling(m_memoryHandleType);
 			const vk::VkMemoryRequirements	requirements			= getMemoryRequirements(m_vkdA, *m_deviceA, *image, m_config.dedicated, m_getMemReq2Supported);
 											exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
 			vk::Move<vk::VkDeviceMemory>	memory					= allocateExportableMemory(m_vkdA, *m_deviceA, requirements.size, exportedMemoryTypeIndex, m_memoryHandleType, m_config.dedicated ? *image : (vk::VkImage)0);
@@ -1086,7 +1088,7 @@
 			VK_CHECK(m_vkdA.bindImageMemory(*m_deviceA, *image, *memory, 0u));
 
 			de::MovePtr<vk::Allocation> allocation = de::MovePtr<vk::Allocation>(new SimpleAllocation(m_vkdA, *m_deviceA, memory.disown()));
-			resourceA = de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
+			resourceA = de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers, tiling));
 		}
 		else
 		{
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationInternallySynchronizedObjectsTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationInternallySynchronizedObjectsTests.cpp
index 687ef30..43f51bb 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationInternallySynchronizedObjectsTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationInternallySynchronizedObjectsTests.cpp
@@ -370,7 +370,7 @@
 		const VkExtent3D				colorImageExtent			= makeExtent3D(1u, 1u, 1u);
 		const VkImageSubresourceRange	colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
 		de::MovePtr<Image>				colorAttachmentImage		= de::MovePtr<Image>(new Image(vk, device, *queues.m_allocator,
-																		makeImageCreateInfo(VK_IMAGE_TYPE_2D, colorImageExtent, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
+																		makeImageCreateInfo(VK_IMAGE_TYPE_2D, colorImageExtent, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 																		MemoryRequirement::Any));
 		Move<VkImageView>				colorAttachmentView			= makeImageView(vk, device, **colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange);
 		Move<VkFramebuffer>				framebuffer					= makeFramebuffer(vk, device, renderPass, *colorAttachmentView, colorImageExtent.width, colorImageExtent.height);
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.cpp
index 1825d7f..631fe51 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.cpp
@@ -911,9 +911,11 @@
 		flushAlloc(vk, device, alloc);
 
 		// Staging image
+		const auto& imgResource = m_resource.getImage();
 		m_image = de::MovePtr<Image>(new Image(
 			vk, device, allocator,
-			makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
+			makeImageCreateInfo(imgResource.imageType, imgResource.extent, imgResource.format,
+								(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 			MemoryRequirement::Any));
 	}
 
@@ -1099,11 +1101,13 @@
 	{
 		const InstanceInterface&	vki				= m_context.getInstanceInterface();
 		const VkPhysicalDevice		physDevice		= m_context.getPhysicalDevice();
-		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, m_resource.getImage().format);
+		const auto&					imgResource		= m_resource.getImage();
+		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
+		const auto&					features		= ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
 		const VkFormatFeatureFlags	requiredFlags	= (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
 
 		// SRC and DST blit is required because both images are using the same format.
-		if ((formatProps.optimalTilingFeatures & requiredFlags) != requiredFlags)
+		if ((features & requiredFlags) != requiredFlags)
 			TCU_THROW(NotSupportedError, "Format doesn't support blits");
 	}
 
@@ -1284,11 +1288,13 @@
 
 		const InstanceInterface&	vki				= m_context.getInstanceInterface();
 		const VkPhysicalDevice		physDevice		= m_context.getPhysicalDevice();
-		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, m_inResource.getImage().format);
+		const auto&					imgResource		= m_inResource.getImage();
+		const VkFormatProperties	formatProps		= getPhysicalDeviceFormatProperties(vki, physDevice, imgResource.format);
+		const auto&					features		= ((imgResource.tiling == VK_IMAGE_TILING_LINEAR) ? formatProps.linearTilingFeatures : formatProps.optimalTilingFeatures);
 		const VkFormatFeatureFlags	requiredFlags	= (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT);
 
 		// SRC and DST blit is required because both images are using the same format.
-		if ((formatProps.optimalTilingFeatures & requiredFlags) != requiredFlags)
+		if ((features & requiredFlags) != requiredFlags)
 			TCU_THROW(NotSupportedError, "Format doesn't support blits");
 	}
 
@@ -1515,7 +1521,8 @@
 		m_colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
 		m_colorImageExtent				= makeExtent3D(16u, 16u, 1u);
 		m_colorAttachmentImage			= de::MovePtr<Image>(new Image(vk, device, allocator,
-			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
+			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 			MemoryRequirement::Any));
 
 		// Pipeline
@@ -1834,7 +1841,8 @@
 		requireFeaturesForSSBOAccess(m_context, m_stage);
 
 		// Some storage image formats may not be supported
-		requireStorageImageSupport(vki, physDevice, m_resource.getImage().format);
+		const auto& imgResource = m_resource.getImage();
+		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
 
 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
 			vk, device, allocator, makeBufferCreateInfo(m_hostBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
@@ -1854,7 +1862,8 @@
 		{
 			m_image = de::MovePtr<Image>(new Image(vk, device, allocator,
 				makeImageCreateInfo(m_resource.getImage().imageType, m_resource.getImage().extent, m_resource.getImage().format,
-									VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
+									(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT),
+									VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 				MemoryRequirement::Any));
 
 			if (m_mode == ACCESS_MODE_READ)
@@ -2608,7 +2617,8 @@
 		requireFeaturesForSSBOAccess(m_context, m_stage);
 
 		// Some storage image formats may not be supported
-		requireStorageImageSupport(vki, physDevice, m_inResource.getImage().format);
+		const auto& imgResource = m_inResource.getImage();
+		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
 
 		// Image resources
 		{
@@ -2827,7 +2837,8 @@
 		const VkPhysicalDeviceFeatures	features	= getPhysicalDeviceFeatures(vki, physDevice);
 		Allocator&						allocator	= m_context.getAllocator();
 
-		requireStorageImageSupport(vki, physDevice, m_resource.getImage().format);
+		const auto& imgResource = m_resource.getImage();
+		requireStorageImageSupport(vki, physDevice, imgResource.format, imgResource.tiling);
 		if (!features.shaderStorageImageMultisample)
 			TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
 
@@ -3104,7 +3115,11 @@
 
 		// Copy destination image.
 		m_image = de::MovePtr<Image>(new Image(
-			vk, device, allocator, makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), MemoryRequirement::Any));
+			vk, device, allocator,
+			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format,
+								(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
+								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
+			MemoryRequirement::Any));
 
 		// Image data will be copied here, so it can be read on the host.
 		m_hostBuffer = de::MovePtr<Buffer>(new Buffer(
@@ -3424,7 +3439,10 @@
 
 		// Source data image
 		m_image = de::MovePtr<Image>(new Image(
-			vk, device, allocator, makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), MemoryRequirement::Any));
+			vk, device, allocator,
+			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_imageExtent, format, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
+								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
+			MemoryRequirement::Any));
 	}
 
 	void recordCommands (const VkCommandBuffer cmdBuffer)
@@ -4379,7 +4397,8 @@
 		m_colorImageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
 		m_colorImageExtent				= makeExtent3D(16u, 16u, 1u);
 		m_colorAttachmentImage			= de::MovePtr<Image>(new Image(vk, device, allocator,
-			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
+			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 			MemoryRequirement::Any));
 
 		// Pipeline
@@ -4924,7 +4943,8 @@
 		m_colorImageSubresourceRange		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
 		m_colorImageExtent					= makeExtent3D(16u, 16u, 1u);
 		m_colorAttachmentImage				= de::MovePtr<Image>(new Image(vk, device, allocator,
-			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
+			makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_colorImageExtent, m_colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+								VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
 			MemoryRequirement::Any));
 
 		// Pipeline
@@ -5228,26 +5248,29 @@
 
 	if (m_type == RESOURCE_TYPE_BUFFER || m_type == RESOURCE_TYPE_INDEX_BUFFER || isIndirectBuffer(m_type))
 	{
-		m_bufferData.offset					= 0u;
-		m_bufferData.size					= static_cast<VkDeviceSize>(desc.size.x());
-		VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData.size, usage);
+		m_bufferData = de::MovePtr<BufferResource>(new BufferResource(DE_NULL, 0u, static_cast<VkDeviceSize>(desc.size.x())));
+		VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(m_bufferData->size, usage);
 		bufferCreateInfo.sharingMode		= sharingMode;
 		if (queueFamilyIndex.size() > 0)
 		{
 			bufferCreateInfo.queueFamilyIndexCount	= static_cast<deUint32>(queueFamilyIndex.size());
 			bufferCreateInfo.pQueueFamilyIndices	= &queueFamilyIndex[0];
 		}
-		m_buffer			= de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
-		m_bufferData.handle	= **m_buffer;
+		m_buffer				= de::MovePtr<Buffer>(new Buffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Any));
+		m_bufferData->handle	= **m_buffer;
 	}
 	else if (m_type == RESOURCE_TYPE_IMAGE)
 	{
-		m_imageData.extent				= makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z()));
-		m_imageData.imageType			= desc.imageType;
-		m_imageData.format				= desc.imageFormat;
-		m_imageData.subresourceRange	= makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u);
-		m_imageData.subresourceLayers	= makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u);
-		VkImageCreateInfo imageInfo		= makeImageCreateInfo(m_imageData.imageType, m_imageData.extent, m_imageData.format, usage, desc.imageSamples);
+		m_imageData = de::MovePtr<ImageResource>(new ImageResource(
+			DE_NULL,
+			makeExtent3D(desc.size.x(), std::max(1, desc.size.y()), std::max(1, desc.size.z())),
+			desc.imageType,
+			desc.imageFormat,
+			makeImageSubresourceRange(desc.imageAspect, 0u, 1u, 0u, 1u),
+			makeImageSubresourceLayers(desc.imageAspect, 0u, 0u, 1u),
+			vk::VK_IMAGE_TILING_OPTIMAL
+		));
+		VkImageCreateInfo imageInfo		= makeImageCreateInfo(m_imageData->imageType, m_imageData->extent, m_imageData->format, usage, desc.imageSamples, m_imageData->tiling);
 		imageInfo.sharingMode			= sharingMode;
 		if (queueFamilyIndex.size() > 0)
 		{
@@ -5265,7 +5288,7 @@
 			TCU_THROW(NotSupportedError, "Requested sample count is not supported");
 
 		m_image							= de::MovePtr<Image>(new Image(vk, device, allocator, imageInfo, MemoryRequirement::Any));
-		m_imageData.handle				= **m_image;
+		m_imageData->handle				= **m_image;
 	}
 	else
 		DE_ASSERT(0);
@@ -5276,14 +5299,11 @@
 					de::MovePtr<vk::Allocation>	allocation,
 					vk::VkDeviceSize			offset,
 					vk::VkDeviceSize			size)
-	: m_type	(type)
-	, m_buffer	(new Buffer(buffer, allocation))
+	: m_type		(type)
+	, m_buffer		(new Buffer(buffer, allocation))
+	, m_bufferData	(de::MovePtr<BufferResource>(new BufferResource(m_buffer->get(), offset, size)))
 {
 	DE_ASSERT(type != RESOURCE_TYPE_IMAGE);
-
-	m_bufferData.handle	= m_buffer->get();
-	m_bufferData.offset	= offset;
-	m_bufferData.size	= size;
 }
 
 Resource::Resource (vk::Move<vk::VkImage>			image,
@@ -5292,16 +5312,12 @@
 					vk::VkImageType					imageType,
 					vk::VkFormat					format,
 					vk::VkImageSubresourceRange		subresourceRange,
-					vk::VkImageSubresourceLayers	subresourceLayers)
-	: m_type	(RESOURCE_TYPE_IMAGE)
-	, m_image	(new Image(image, allocation))
+					vk::VkImageSubresourceLayers	subresourceLayers,
+					vk::VkImageTiling				tiling)
+	: m_type		(RESOURCE_TYPE_IMAGE)
+	, m_image		(new Image(image, allocation))
+	, m_imageData	(de::MovePtr<ImageResource>(new ImageResource(m_image->get(), extent, imageType, format, subresourceRange, subresourceLayers, tiling)))
 {
-	m_imageData.handle				= m_image->get();
-	m_imageData.extent				= extent;
-	m_imageData.imageType			= imageType;
-	m_imageData.format				= format;
-	m_imageData.subresourceRange	= subresourceRange;
-	m_imageData.subresourceLayers	= subresourceLayers;
 }
 
 vk::VkDeviceMemory Resource::getMemory (void) const
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.hpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.hpp
index 9077d1d..7862077 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.hpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationOperation.hpp
@@ -206,20 +206,21 @@
 										 vk::VkImageType				imageType,
 										 vk::VkFormat					format,
 										 vk::VkImageSubresourceRange	subresourceRange,
-										 vk::VkImageSubresourceLayers	subresourceLayers);
+										 vk::VkImageSubresourceLayers	subresourceLayers,
+										 vk::VkImageTiling				tiling);
 
 	ResourceType			getType		(void) const { return m_type; }
-	const BufferResource&	getBuffer	(void) const { return m_bufferData; }
-	const ImageResource&	getImage	(void) const { return m_imageData; }
+	const BufferResource&	getBuffer	(void) const { DE_ASSERT(m_bufferData.get()); return *m_bufferData; }
+	const ImageResource&	getImage	(void) const { DE_ASSERT(m_imageData.get()); return *m_imageData; }
 
 	vk::VkDeviceMemory		getMemory	(void) const;
 
 private:
-	const ResourceType		m_type;
-	de::MovePtr<Buffer>		m_buffer;
-	BufferResource			m_bufferData;
-	de::MovePtr<Image>		m_image;
-	ImageResource			m_imageData;
+	const ResourceType			m_type;
+	de::MovePtr<Buffer>			m_buffer;
+	de::MovePtr<BufferResource>	m_bufferData;
+	de::MovePtr<Image>			m_image;
+	de::MovePtr<ImageResource>	m_imageData;
 };
 
 // \note Meaning of image layout is different for read and write types of operations:
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationSignalOrderTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationSignalOrderTests.cpp
index 87c2de1..c9707f3 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationSignalOrderTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationSignalOrderTests.cpp
@@ -389,6 +389,7 @@
 			DE_NULL,
 			(VkExternalMemoryHandleTypeFlags)externalType
 		};
+		const VkImageTiling				tiling					= VK_IMAGE_TILING_OPTIMAL;
 		const VkImageCreateInfo			createInfo				=
 		{
 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -401,7 +402,7 @@
 			1u,
 			1u,
 			resourceDesc.imageSamples,
-			VK_IMAGE_TILING_OPTIMAL,
+			tiling,
 			readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
 			VK_SHARING_MODE_EXCLUSIVE,
 
@@ -413,7 +414,7 @@
 		Move<VkImage>			image		= createImage(vkd, device, &createInfo);
 		MovePtr<Allocation>		allocation	= importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex);
 
-		return MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
+		return MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers, tiling));
 	}
 	else
 	{
@@ -537,7 +538,8 @@
 	Move<VkImage> createImage (const vk::DeviceInterface&	vkd,
 							   vk::VkDevice					device,
 							   const vk::VkExtent3D&		extent,
-							   deUint32						queueFamilyIndex)
+							   deUint32						queueFamilyIndex,
+							   vk::VkImageTiling			tiling)
 	{
 		const VkExternalMemoryImageCreateInfo externalInfo =
 		{
@@ -557,7 +559,7 @@
 			1u,
 			1u,
 			m_resourceDesc.imageSamples,
-			VK_IMAGE_TILING_OPTIMAL,
+			tiling,
 			m_readOpSupport->getInResourceUsageFlags() | m_writeOpSupport->getOutResourceUsageFlags(),
 			VK_SHARING_MODE_EXCLUSIVE,
 
@@ -661,7 +663,8 @@
 					1u
 				};
 
-				Move<VkImage>							image			= createImage(vkA, deviceA, extent, universalQueueFamilyIndex);
+				const vk::VkImageTiling					tiling			= VK_IMAGE_TILING_OPTIMAL;
+				Move<VkImage>							image			= createImage(vkA, deviceA, extent, universalQueueFamilyIndex, tiling);
 				const vk::VkMemoryRequirements			requirements	= getMemoryRequirements(vkA, deviceA, *image);
 														memoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
 				vk::Move<vk::VkDeviceMemory>			memory			= allocateExportableMemory(vkA, deviceA, requirements.size, memoryTypeIndex, m_memoryHandleType, *image);
@@ -669,7 +672,7 @@
 				VK_CHECK(vkA.bindImageMemory(deviceA, *image, *memory, 0u));
 
 				MovePtr<Allocation> allocation(new SimpleAllocation(vkA, deviceA, memory.disown()));
-				iter.resourceA = makeSharedPtr(new Resource(image, allocation, extent, m_resourceDesc.imageType, m_resourceDesc.imageFormat, subresourceRange, subresourceLayers));
+				iter.resourceA = makeSharedPtr(new Resource(image, allocation, extent, m_resourceDesc.imageType, m_resourceDesc.imageFormat, subresourceRange, subresourceLayers, tiling));
 			}
 			else
 			{
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
index 1751dc2..9b6c58d 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.cpp
@@ -91,7 +91,8 @@
 									   const VkExtent3D&			extent,
 									   const VkFormat				format,
 									   const VkImageUsageFlags		usage,
-									   const VkSampleCountFlagBits	samples)
+									   const VkSampleCountFlagBits	samples,
+									   const VkImageTiling			tiling)
 {
 	return
 	{
@@ -104,7 +105,7 @@
 		1u,											// uint32_t                 mipLevels;
 		1u,											// uint32_t                 arrayLayers;
 		samples,									// VkSampleCountFlagBits    samples;
-		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
+		tiling,										// VkImageTiling            tiling;
 		usage,										// VkImageUsageFlags        usage;
 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
 		0u,											// uint32_t                 queueFamilyIndexCount;
@@ -988,10 +989,12 @@
 		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
 }
 
-void requireStorageImageSupport(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat fmt)
+void requireStorageImageSupport(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat fmt, const VkImageTiling tiling)
 {
-	const VkFormatProperties p = getPhysicalDeviceFormatProperties(vki, physDevice, fmt);
-	if ((p.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
+	const VkFormatProperties	p			= getPhysicalDeviceFormatProperties(vki, physDevice, fmt);
+	const auto&					features	= ((tiling == VK_IMAGE_TILING_LINEAR) ? p.linearTilingFeatures : p.optimalTilingFeatures);
+
+	if ((features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
 		throw tcu::NotSupportedError("Storage image format not supported");
 }
 
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
index c937cc7..d782446 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationUtil.hpp
@@ -260,6 +260,10 @@
 
 struct BufferResource
 {
+	BufferResource (vk::VkBuffer handle_, vk::VkDeviceSize offset_, vk::VkDeviceSize size_)
+		: handle(handle_), offset(offset_), size(size_)
+		{}
+
 	vk::VkBuffer					handle;
 	vk::VkDeviceSize				offset;
 	vk::VkDeviceSize				size;
@@ -267,12 +271,30 @@
 
 struct ImageResource
 {
+	ImageResource (
+		vk::VkImage handle_,
+		vk::VkExtent3D extent_,
+		vk::VkImageType imageType_,
+		vk::VkFormat format_,
+		vk::VkImageSubresourceRange subresourceRange_,
+		vk::VkImageSubresourceLayers subresourceLayers_,
+		vk::VkImageTiling tiling_)
+		: handle(handle_)
+		, extent(extent_)
+		, imageType(imageType_)
+		, format(format_)
+		, subresourceRange(subresourceRange_)
+		, subresourceLayers(subresourceLayers_)
+		, tiling(tiling_)
+		{}
+
 	vk::VkImage						handle;
 	vk::VkExtent3D					extent;
 	vk::VkImageType					imageType;
 	vk::VkFormat					format;
 	vk::VkImageSubresourceRange		subresourceRange;
 	vk::VkImageSubresourceLayers	subresourceLayers;
+	vk::VkImageTiling				tiling;
 };
 
 typedef std::shared_ptr<SynchronizationWrapperBase> SynchronizationWrapperPtr;
@@ -289,12 +311,13 @@
 																				 const vk::VkExtent3D&				extent,
 																				 const vk::VkFormat					format,
 																				 const vk::VkImageUsageFlags		usage,
-																				 const vk::VkSampleCountFlagBits	samples = vk::VK_SAMPLE_COUNT_1_BIT);
+																				 const vk::VkSampleCountFlagBits	samples,
+																				 const vk::VkImageTiling			tiling);
 vk::Move<vk::VkCommandBuffer>		makeCommandBuffer							(const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool);
 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);
 void								beginRenderPassWithRasterizationDisabled	(const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer, const vk::VkRenderPass renderPass, const vk::VkFramebuffer framebuffer);
 void								requireFeatures								(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const FeatureFlags flags);
-void								requireStorageImageSupport					(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const vk::VkFormat fmt);
+void								requireStorageImageSupport					(const vk::InstanceInterface& vki, const vk::VkPhysicalDevice physDevice, const vk::VkFormat fmt, const vk::VkImageTiling tiling);
 std::string							getResourceName								(const ResourceDescription& resource);
 bool								isIndirectBuffer							(const ResourceType type);
 vk::VkCommandBufferSubmitInfoKHR	makeCommonCommandBufferSubmitInfo			(const vk::VkCommandBuffer cmdBuf);
diff --git a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationWin32KeyedMutexTests.cpp b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationWin32KeyedMutexTests.cpp
index 5f6805a..b558196 100644
--- a/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationWin32KeyedMutexTests.cpp
+++ b/external/vulkancts/modules/vulkan/synchronization/vktSynchronizationWin32KeyedMutexTests.cpp
@@ -418,6 +418,7 @@
 			DE_NULL,
 			(vk::VkExternalMemoryHandleTypeFlags)externalType
 		};
+		const vk::VkImageTiling								tiling					= VK_IMAGE_TILING_OPTIMAL;
 		const vk::VkImageCreateInfo							createInfo				=
 		{
 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -430,7 +431,7 @@
 			1u,
 			1u,
 			resourceDesc.imageSamples,
-			vk::VK_IMAGE_TILING_OPTIMAL,
+			tiling,
 			readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
 			vk::VK_SHARING_MODE_EXCLUSIVE,
 
@@ -442,7 +443,7 @@
 		vk::Move<vk::VkImage>								image					= vk::createImage(vkd, device, &createInfo);
 		de::MovePtr<vk::Allocation>							allocation				= importAndBindMemory(vkd, device, *image, nativeHandle, externalType);
 
-		return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
+		return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers, tiling));
 	}
 	else
 	{