Merge in changes from Khronos repository
diff --git a/Android.mk b/Android.mk
index a769d34..0183bb0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -734,10 +734,12 @@
 		liblog \
 		libm \
 		libc \
-		libpng \
 		libz \
 		libdl
 
+LOCAL_STATIC_LIBRARIES := \
+		libpng_ndk \
+
 LOCAL_CFLAGS += \
 	$(deqp_compile_flags) \
 	-Wno-error=date-time
diff --git a/execserver/xsPosixTestProcess.cpp b/execserver/xsPosixTestProcess.cpp
index 5c9dcb6..9f4d21d 100644
--- a/execserver/xsPosixTestProcess.cpp
+++ b/execserver/xsPosixTestProcess.cpp
@@ -200,7 +200,7 @@
 	}
 
 	// Construct command line.
-	string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).normalize().getPath();
+	string cmdLine = de::FilePath(name).isAbsolutePath() ? name : de::FilePath::join(workingDir, name).getPath();
 	cmdLine += string(" --deqp-log-filename=") + logFilePath.getBaseName();
 
 	if (hasCaseList)
diff --git a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
index a9363e4..f618893 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
@@ -275,7 +275,7 @@
 				deUint32 limitToCheck = featureLimitTable[ndx].uintVal;
 				if (featureLimitTable[ndx].unsuppTableNdx != -1)
 				{
-					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)))
+					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)) == VK_FALSE)
 						limitToCheck = unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].uintVal;
 				}
 
@@ -308,7 +308,7 @@
 				float limitToCheck = featureLimitTable[ndx].floatVal;
 				if (featureLimitTable[ndx].unsuppTableNdx != -1)
 				{
-					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)))
+					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)) == VK_FALSE)
 						limitToCheck = unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].floatVal;
 				}
 
@@ -340,7 +340,7 @@
 				deInt32 limitToCheck = featureLimitTable[ndx].intVal;
 				if (featureLimitTable[ndx].unsuppTableNdx != -1)
 				{
-					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)))
+					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)) == VK_FALSE)
 						limitToCheck = unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].intVal;
 				}
 				if (featureLimitTable[ndx].type == LIMIT_TYPE_MIN)
@@ -371,7 +371,7 @@
 				deUint64 limitToCheck = featureLimitTable[ndx].deviceSizeVal;
 				if (featureLimitTable[ndx].unsuppTableNdx != -1)
 				{
-					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)))
+					if (*((VkBool32*)((char*)features+unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].featureOffset)) == VK_FALSE)
 						limitToCheck = unsupportedFeatureTable[featureLimitTable[ndx].unsuppTableNdx].deviceSizeVal;
 				}
 
diff --git a/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp
index 2a3089f..3f610f1 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiObjectManagementTests.cpp
@@ -293,7 +293,10 @@
 {
 	typedef VkInstance Type;
 
-	enum { MAX_CONCURRENT = 32 };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return 32;
+	}
 
 	struct Parameters
 	{
@@ -337,7 +340,10 @@
 {
 	typedef VkDevice Type;
 
-	enum { MAX_CONCURRENT = 32 };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return 32;
+	}
 
 	struct Parameters
 	{
@@ -428,7 +434,10 @@
 {
 	typedef VkDeviceMemory Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context& context)
+	{
+		return context.getDeviceProperties().limits.maxMemoryAllocationCount;
+	}
 
 	struct Parameters
 	{
@@ -481,7 +490,10 @@
 {
 	typedef VkBuffer Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -522,7 +534,10 @@
 {
 	typedef VkBufferView Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -576,7 +591,10 @@
 {
 	typedef VkImage Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -648,7 +666,10 @@
 {
 	typedef VkImageView Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -706,7 +727,10 @@
 {
 	typedef VkSemaphore Type;
 
-	enum { MAX_CONCURRENT = 100 };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return 100;
+	}
 
 	struct Parameters
 	{
@@ -739,7 +763,10 @@
 {
 	typedef VkFence Type;
 
-	enum { MAX_CONCURRENT = 100 };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return 100;
+	}
 
 	struct Parameters
 	{
@@ -772,7 +799,10 @@
 {
 	typedef VkEvent Type;
 
-	enum { MAX_CONCURRENT = 100 };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return 100;
+	}
 
 	struct Parameters
 	{
@@ -805,7 +835,10 @@
 {
 	typedef VkQueryPool Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -847,7 +880,10 @@
 {
 	typedef VkShaderModule Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -928,7 +964,10 @@
 {
 	typedef VkPipelineCache Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -959,7 +998,10 @@
 {
 	typedef VkSampler Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context& context)
+	{
+		return context.getDeviceProperties().limits.maxSamplerAllocationCount;
+	}
 
 	struct Parameters
 	{
@@ -1036,7 +1078,10 @@
 {
 	typedef VkDescriptorSetLayout Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1141,7 +1186,10 @@
 {
 	typedef VkPipelineLayout Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1204,7 +1252,10 @@
 {
 	typedef VkRenderPass Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	// \todo [2015-09-17 pyry] More interesting configurations
 	struct Parameters
@@ -1292,7 +1343,10 @@
 {
 	typedef VkPipeline Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	// \todo [2015-09-17 pyry] More interesting configurations
 	struct Parameters
@@ -1506,7 +1560,10 @@
 {
 	typedef VkPipeline Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	// \todo [2015-09-17 pyry] More interesting configurations
 	struct Parameters
@@ -1573,7 +1630,10 @@
 {
 	typedef VkDescriptorPool Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1625,7 +1685,10 @@
 {
 	typedef VkDescriptorSet Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1691,7 +1754,10 @@
 {
 	typedef VkFramebuffer Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1758,7 +1824,10 @@
 {
 	typedef VkCommandPool Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1792,7 +1861,10 @@
 {
 	typedef VkCommandBuffer Type;
 
-	enum { MAX_CONCURRENT = DEFAULT_MAX_CONCURRENT_OBJECTS };
+	static deUint32 getMaxConcurrent (Context&)
+	{
+		return DEFAULT_MAX_CONCURRENT_OBJECTS;
+	}
 
 	struct Parameters
 	{
@@ -1886,7 +1958,7 @@
 	typedef Unique<typename Object::Type>	UniqueObject;
 	typedef SharedPtr<UniqueObject>			ObjectPtr;
 
-	const deUint32						numObjects	= Object::MAX_CONCURRENT;
+	const deUint32						numObjects	= Object::getMaxConcurrent(context);
 	const Environment					env			(context, numObjects);
 	const typename Object::Resources	res			(env, params);
 	vector<ObjectPtr>					objects		(numObjects);
diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp b/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
index 76f03e1..4ac9b4a 100644
--- a/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
+++ b/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
@@ -92,6 +92,7 @@
 enum
 {
 	ALL_PIPELINE_STAGES = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
+						| vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
 						| vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
 						| vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
 						| vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
@@ -215,6 +216,7 @@
 enum PipelineStage
 {
 	PIPELINESTAGE_TOP_OF_PIPE_BIT = 0,
+	PIPELINESTAGE_BOTTOM_OF_PIPE_BIT,
 	PIPELINESTAGE_DRAW_INDIRECT_BIT,
 	PIPELINESTAGE_VERTEX_INPUT_BIT,
 	PIPELINESTAGE_VERTEX_SHADER_BIT,
@@ -237,6 +239,7 @@
 	switch (flags)
 	{
 		case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:						return PIPELINESTAGE_TOP_OF_PIPE_BIT;
+		case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT:					return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
 		case vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:					return PIPELINESTAGE_DRAW_INDIRECT_BIT;
 		case vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT:					return PIPELINESTAGE_VERTEX_INPUT_BIT;
 		case vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT:					return PIPELINESTAGE_VERTEX_SHADER_BIT;
@@ -2084,6 +2087,7 @@
 						~ImageTransition	(void) {}
 	const char*			getName				(void) const { return "ImageTransition"; }
 
+	void				prepare				(PrepareContext& context);
 	void				logSubmit			(TestLog& log, size_t commandIndex) const;
 	void				submit				(SubmitContext& context);
 };
@@ -2093,6 +2097,11 @@
 	log << TestLog::Message << commandIndex << ":" << getName() << " Use pipeline barrier to trasition to VK_IMAGE_LAYOUT_GENERAL." << TestLog::EndMessage;
 }
 
+void ImageTransition::prepare (PrepareContext& context)
+{
+	context.setImageLayout(vk::VK_IMAGE_LAYOUT_GENERAL);
+}
+
 void ImageTransition::submit (SubmitContext& context)
 {
 	const vk::DeviceInterface&		vkd			= context.getContext().getDeviceInterface();
@@ -5379,6 +5388,7 @@
 					&& usage & USAGE_HOST_WRITE
 					&& state.memoryDefined
 					&& state.hostInvalidated
+					&& state.queueIdle
 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)
 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
 				{
@@ -5388,6 +5398,7 @@
 				if (usage & USAGE_HOST_READ
 					&& state.memoryDefined
 					&& state.hostInvalidated
+					&& state.queueIdle
 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
 				{
 					ops.push_back(OP_MAP_READ);
@@ -5395,6 +5406,7 @@
 
 				if (usage & USAGE_HOST_WRITE
 					&& state.hostInvalidated
+					&& state.queueIdle
 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT))
 				{
 					ops.push_back(OP_MAP_WRITE);
diff --git a/external/vulkancts/modules/vulkan/vktRenderPassTests.cpp b/external/vulkancts/modules/vulkan/vktRenderPassTests.cpp
index 1a82a12..3fde02e 100644
--- a/external/vulkancts/modules/vulkan/vktRenderPassTests.cpp
+++ b/external/vulkancts/modules/vulkan/vktRenderPassTests.cpp
@@ -2805,6 +2805,7 @@
 
 				if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
 				{
+					const Vec4	minDiff		= Vec4(1.0f) / (IVec4(1) << tcu::getTextureFormatMantissaBitDepth(format)).cast<float>();
 					const Vec4	minUvs		= computeUvs(posA, posB, IVec2(x-1, y-1));
 					const Vec4	maxUvs		= computeUvs(posA, posB, IVec2(x+1, y+1));
 					const bool	softCheck	= std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
@@ -2812,10 +2813,22 @@
 
 					const Vec4	resColor	(result.getPixel(x, y));
 
-					const Vec4	minRefColor	= srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
-													 : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs) - threshold;
-					const Vec4	maxRefColor	= srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
-													 : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs) + threshold;
+					Vec4	minRefColor	= srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
+											 : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs) - threshold;
+					Vec4	maxRefColor	= srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
+											 : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs) + threshold;
+
+					// Take into account rounding and quantization
+					if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
+					{
+						minRefColor = tcu::min(minRefColor * (Vec4(1.0f) - minDiff), minRefColor * (Vec4(1.0f) + minDiff));
+						maxRefColor = tcu::max(maxRefColor * (Vec4(1.0f) - minDiff), maxRefColor * (Vec4(1.0f) + minDiff));
+					}
+					else
+					{
+						minRefColor = minRefColor - minDiff;
+						maxRefColor = maxRefColor + minDiff;
+					}
 
 					DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
 					DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
@@ -3703,6 +3716,18 @@
 	checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments());
 
 	{
+		const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
+
+		log << TestLog::Message << "Max color attachments: " << properties.limits.maxColorAttachments << TestLog::EndMessage;
+
+		for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
+		{
+			 if (renderPassInfo.getSubpasses()[subpassNdx].getColorAttachments().size() > (size_t)properties.limits.maxColorAttachments)
+				 TCU_THROW(NotSupportedError, "Subpass uses more than maxColorAttachments.");
+		}
+	}
+
+	{
 		const VkDevice								device								= context.getDevice();
 		const DeviceInterface&						vk									= context.getDeviceInterface();
 		const VkQueue								queue								= context.getUniversalQueue();
@@ -3830,7 +3855,7 @@
 
 de::MovePtr<tcu::TestCaseGroup> createAttachmentTestCaseGroup (tcu::TestContext& testCtx)
 {
-	const deUint32 attachmentCounts[] = { 1, 3, 8 };
+	const deUint32 attachmentCounts[] = { 1, 3, 4, 8 };
 	const VkAttachmentLoadOp loadOps[] =
 	{
 		VK_ATTACHMENT_LOAD_OP_LOAD,