Add test for FragDepth shader built-in

Components: Vulkan

VK-GL-CTS issue: 93

Test: fragdepth, frontface, clipping
Change-Id: I531e39a58dd6b577108bff14b2206d7bf9d9cd4f
(cherry picked from commit 3aeb0c565fe64441466247fe381fc815209d46e4)
diff --git a/android/cts/master/src/vk-excluded-tests.txt b/android/cts/master/src/vk-excluded-tests.txt
index 6c97232..6ce5b49 100644
--- a/android/cts/master/src/vk-excluded-tests.txt
+++ b/android/cts/master/src/vk-excluded-tests.txt
@@ -325,3 +325,6 @@
 dEQP-VK.pipeline.render_to_image.*.small.r32_uint_d32_sfloat_s8_uint
 dEQP-VK.pipeline.render_to_image.*.small.r16g16_sint_d32_sfloat_s8_uint
 dEQP-VK.pipeline.render_to_image.*.small.r32g32b32a32_sfloat_d32_sfloat_s8_uint
+
+#VK-GL-CTS 655
+dEQP-VK.glsl.builtin_var.fragdepth.*
diff --git a/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp
index bc69299..bad106d 100644
--- a/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp
+++ b/external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp
@@ -25,6 +25,8 @@
 
 #include "vktShaderRenderBuiltinVarTests.hpp"
 
+#include "tcuFloat.hpp"
+#include "deUniquePtr.hpp"
 #include "vkDefs.hpp"
 #include "vktShaderRender.hpp"
 #include "gluShaderUtil.hpp"
@@ -32,6 +34,9 @@
 #include "tcuStringTemplate.hpp"
 #include "tcuTextureUtil.hpp"
 #include "vktDrawUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkMemUtil.hpp"
 #include "tcuTestLog.hpp"
 
 #include "deMath.h"
@@ -42,6 +47,7 @@
 using namespace std;
 using namespace tcu;
 using namespace vk;
+using namespace de;
 
 namespace vkt
 {
@@ -253,6 +259,1139 @@
 	return new BuiltinGlFrontFacingCaseInstance(context, m_topology);
 }
 
+class BuiltinFragDepthCaseInstance : public TestInstance
+{
+public:
+	enum
+	{
+		RENDERWIDTH		= 16,
+		RENDERHEIGHT	= 16
+	};
+					BuiltinFragDepthCaseInstance		(Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples);
+	TestStatus		iterate								(void);
+
+	bool			validateDepthBuffer					(const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const;
+private:
+	const VkPrimitiveTopology		m_topology;
+	const VkFormat					m_format;
+	const bool						m_largeDepthEnable;
+	const float						m_defaultDepthValue;
+	const bool						m_depthClampEnable;
+	const VkSampleCountFlagBits		m_samples;
+	const tcu::UVec2				m_renderSize;
+	const float						m_largeDepthBase;
+};
+
+BuiltinFragDepthCaseInstance::BuiltinFragDepthCaseInstance (Context& context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples)
+	: TestInstance			(context)
+	, m_topology			(topology)
+	, m_format				(format)
+	, m_largeDepthEnable	(largeDepthEnable)
+	, m_defaultDepthValue	(defaultDepth)
+	, m_depthClampEnable	(depthClampEnable)
+	, m_samples				(samples)
+	, m_renderSize			(RENDERWIDTH, RENDERHEIGHT)
+	, m_largeDepthBase		(20.0f)
+{
+	const InstanceInterface&	vki					= m_context.getInstanceInterface();
+	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
+
+	try
+	{
+		VkImageFormatProperties		imageFormatProperties;
+		VkFormatProperties			formatProperties;
+
+		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
+			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
+
+		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, VK_IMAGE_TYPE_2D,
+				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, (VkImageCreateFlags)0);
+
+		if ((imageFormatProperties.sampleCounts & m_samples) == 0)
+			throw tcu::NotSupportedError("Image format and sample count not supported");
+
+		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R8G8B8A8_UINT);
+
+		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
+			throw tcu::NotSupportedError("MarkerImage format not supported as storage image");
+	}
+	catch (const vk::Error& e)
+	{
+		if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
+			throw tcu::NotSupportedError("Image format not supported");
+		else
+			throw;
+
+	}
+}
+
+TestStatus BuiltinFragDepthCaseInstance::iterate (void)
+{
+	const VkDevice					device				= m_context.getDevice();
+	const DeviceInterface&			vk					= m_context.getDeviceInterface();
+	const VkQueue					queue				= m_context.getUniversalQueue();
+	Allocator&						allocator			= m_context.getDefaultAllocator();
+	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
+	TestLog&						log					= m_context.getTestContext().getLog();
+	const deUint32					scale				= 4;										// To account for std140 stride
+	const VkDeviceSize				pixelCount			= m_renderSize.x() * m_renderSize.y();
+	std::string						testDesc;
+	Move<VkImage>					depthResolveImage;
+	Move<VkImageView>				depthResolveImageView;
+	MovePtr<Allocation>				depthResolveAllocation;
+	Move<VkImage>					depthImage;
+	Move<VkImageView>				depthImageView;
+	MovePtr<Allocation>				depthImageAllocation;
+	Move<VkBuffer>					controlBuffer;
+	MovePtr<Allocation>				controlBufferAllocation;
+	Move<VkImage>					markerImage;
+	Move<VkImageView>				markerImageView;
+	MovePtr<Allocation>				markerImageAllocation;
+	Move<VkBuffer>					markerBuffer;
+	MovePtr<Allocation>				markerBufferAllocation;
+	Move<VkBuffer>					validationBuffer;
+	MovePtr<Allocation>				validationAlloc;
+	MovePtr<Allocation>				depthInitAllocation;
+	Move<VkCommandPool>				cmdPool;
+	Move<VkCommandBuffer>			transferCmdBuffer;
+	Move<VkFence>					fence;
+	Move<VkSampler>					depthSampler;
+
+	// Create Buffer/Image for validation
+	{
+		VkFormat	resolvedBufferFormat = VK_FORMAT_R32_SFLOAT;
+		const VkBufferCreateInfo validationBufferCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,										// VkStructureType		sType
+			DE_NULL,																	// const void*			pNext
+			(VkBufferCreateFlags)0,														// VkBufferCreateFlags	flags
+			m_samples * pixelCount * getPixelSize(mapVkFormat(resolvedBufferFormat)),	// VkDeviceSize			size
+			VK_BUFFER_USAGE_TRANSFER_DST_BIT,											// VkBufferUsageFlags	usage
+			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode
+			0u,																			// uint32_t				queueFamilyIndexCount,
+			DE_NULL																		// const uint32_t*		pQueueFamilyIndices
+		};
+
+		validationBuffer = createBuffer(vk, device, &validationBufferCreateInfo);
+		validationAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *validationBuffer), MemoryRequirement::HostVisible);
+		VK_CHECK(vk.bindBufferMemory(device, *validationBuffer, validationAlloc->getMemory(), validationAlloc->getOffset()));
+
+		const VkImageCreateInfo depthResolveImageCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								// VkStructureType			sType
+			DE_NULL,															// const void*				pNext
+			(VkImageCreateFlags)0,												// VkImageCreateFlags		flags
+			VK_IMAGE_TYPE_2D,													// VkIMageType				imageType
+			resolvedBufferFormat,												// VkFormat					format
+			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
+			1u,																	// uint32_t					mipLevels
+			1u,																	// uint32_t					arrayLayers
+			VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagsBits	samples
+			VK_IMAGE_TILING_OPTIMAL,											// VkImageTiling			tiling
+			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |									// VkImageUsageFlags		usage
+			VK_IMAGE_USAGE_STORAGE_BIT |
+			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+			VK_SHARING_MODE_EXCLUSIVE,											// VkSharingMode			sharingMode
+			0u,																	// uint32_t					queueFamilyIndexCount
+			DE_NULL,															// const uint32_t			pQueueFamilyIndices
+			VK_IMAGE_LAYOUT_UNDEFINED											// VkImageLayout			initialLayout
+		};
+
+		depthResolveImage = createImage(vk, device, &depthResolveImageCreateInfo, DE_NULL);
+		depthResolveAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthResolveImage), MemoryRequirement::Any);
+		VK_CHECK(vk.bindImageMemory(device, *depthResolveImage, depthResolveAllocation->getMemory(), depthResolveAllocation->getOffset()));
+
+		const VkImageViewCreateInfo depthResolveImageViewCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,								// VkStructureType			sType
+			DE_NULL,																// const void*				pNext
+			(VkImageViewCreateFlags)0,												// VkImageViewCreateFlags	flags
+			*depthResolveImage,														// VkImage					image
+			VK_IMAGE_VIEW_TYPE_2D,													// VkImageViewType			type
+			resolvedBufferFormat,													// VkFormat					format
+			makeComponentMappingRGBA(),												// VkComponentMapping		componentMapping
+			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)	// VkImageSUbresourceRange	subresourceRange
+		};
+
+		depthResolveImageView = createImageView(vk, device, &depthResolveImageViewCreateInfo, DE_NULL);
+	}
+
+	// Marker Buffer
+	{
+		const VkDeviceSize	size			= m_samples * m_renderSize.x() * m_renderSize.y() * getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT));
+
+		const VkBufferCreateInfo markerBufferCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,			// VkStructureType			sType
+			DE_NULL,										// const void*				pNext
+			(VkBufferCreateFlags)0,							// VkBufferCreateFlags		flags
+			size,											// VkDeviceSize				size
+			VK_BUFFER_USAGE_TRANSFER_DST_BIT,				// VkBufferUsageFlags		usage
+			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
+			0u,												// uint32_t					queueFamilyIndexCount
+			DE_NULL											// const uint32_t*			pQueueFamilyIndices
+		};
+
+		markerBuffer = createBuffer(vk, device, &markerBufferCreateInfo, DE_NULL);
+		markerBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *markerBuffer), MemoryRequirement::HostVisible);
+		VK_CHECK(vk.bindBufferMemory(device, *markerBuffer, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset()));
+
+		const VkImageCreateInfo markerImageCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType
+			DE_NULL,														// const void*				pNext
+			(VkImageCreateFlags)0,											// VkImageCreateFlags		flags
+			VK_IMAGE_TYPE_2D,												// VkImageType				imageType
+			VK_FORMAT_R8G8B8A8_UINT,										// VkFormat					format
+			makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1),// VkExtent3D				extent
+			1u,																// uint32_t					mipLevels
+			1u,																// uint32_t					arrayLayers
+			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagsBit	smaples
+			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling
+			VK_IMAGE_USAGE_STORAGE_BIT |									// VkImageUsageFlags		usage
+			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharing
+			0u,																// uint32_t					queueFamilyIndexCount
+			DE_NULL,														// const uint32_t*			pQueueFamilyIndices
+			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout
+		};
+
+		markerImage = createImage(vk, device, &markerImageCreateInfo, DE_NULL);
+		markerImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *markerImage), MemoryRequirement::Any);
+		VK_CHECK(vk.bindImageMemory(device, *markerImage, markerImageAllocation->getMemory(), markerImageAllocation->getOffset()));
+
+		const VkImageViewCreateInfo markerViewCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
+			DE_NULL,												// const void*				pNext
+			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
+			*markerImage,											// VkImage					image
+			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
+			VK_FORMAT_R8G8B8A8_UINT,								// VkFormat					format
+			makeComponentMappingRGBA(),								// VkComponentMapping		components
+			makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)
+		};
+
+		markerImageView = createImageView(vk, device, &markerViewCreateInfo, DE_NULL);
+	}
+
+	// Control Buffer
+	{
+		const VkBufferCreateInfo controlBufferCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType		sType
+			DE_NULL,												// const void*			pNext
+			(VkBufferCreateFlags)0,									// VkBufferCreateFlags	flags
+			pixelCount * sizeof(float)* scale,						// VkDeviceSize			size
+			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,						// VkBufferUsageFlags	usage
+			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode		sharingMode
+			0u,														// deUint32				queueFamilyIndexCount
+
+			DE_NULL													// pQueueFamilyIndices
+		};
+
+		controlBuffer = createBuffer(vk, device, &controlBufferCreateInfo, DE_NULL);
+		controlBufferAllocation = allocator.allocate( getBufferMemoryRequirements(vk, device, *controlBuffer), MemoryRequirement::HostVisible);
+		VK_CHECK(vk.bindBufferMemory(device, *controlBuffer, controlBufferAllocation->getMemory(), controlBufferAllocation->getOffset()));
+
+		{
+			float* bufferData = (float*)(controlBufferAllocation->getHostPtr());
+			float sign = m_depthClampEnable ? -1.0f : 1.0f;
+			for (deUint32 ndx = 0; ndx < m_renderSize.x() * m_renderSize.y(); ndx++)
+			{
+				bufferData[ndx * scale] = (float)ndx / 256.0f * sign;
+				if (m_largeDepthEnable)
+					bufferData[ndx * scale] += m_largeDepthBase;
+			}
+
+			const VkMappedMemoryRange range =
+			{
+				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+				DE_NULL,
+				controlBufferAllocation->getMemory(),
+				0u,
+				VK_WHOLE_SIZE
+			};
+
+			VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &range));
+		}
+	}
+
+	// Depth Buffer
+	{
+		VkImageSubresourceRange depthSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
+		const VkImageCreateInfo depthImageCreateInfo	=
+		{
+			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType
+			DE_NULL,												// const void*				pNext
+			(VkImageCreateFlags)0,									// VkImageCreateFlags		flags
+			VK_IMAGE_TYPE_2D,										// VkImageType				imageType
+			m_format,												// VkFormat					format
+			makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent
+			1u,														// uint32_t					mipLevels
+			1u,														// uint32_t					arrayLayers
+			m_samples,												// VkSampleCountFlagsBits	samples
+			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
+			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+			VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+			VK_IMAGE_USAGE_SAMPLED_BIT      |
+			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,			// VkImageUsageFlags		usage
+			VK_SHARING_MODE_EXCLUSIVE,								// VkShaderingMode			sharingMode
+			0u,														// uint32_t					queueFamilyIndexCount
+			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
+			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
+		};
+
+		depthImage = createImage(vk, device, &depthImageCreateInfo, DE_NULL);
+		depthImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *depthImage), MemoryRequirement::Any);
+		VK_CHECK(vk.bindImageMemory(device, *depthImage, depthImageAllocation->getMemory(), depthImageAllocation->getOffset()));
+
+		const VkImageViewCreateInfo imageViewParams =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
+			DE_NULL,										// const void*				pNext;
+			(VkImageViewCreateFlags)0,						// VkImageViewCreateFlags	flags;
+			*depthImage,									// VkImage					image;
+			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
+			m_format,										// VkFormat					format;
+			makeComponentMappingRGBA(),						// VkComponentMapping		components;
+			depthSubresourceRange,							// VkImageSubresourceRange	subresourceRange;
+		};
+		depthImageView = createImageView(vk, device, &imageViewParams);
+
+		const VkSamplerCreateInfo depthSamplerCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,			// VkStructureType			sType
+			DE_NULL,										// const void*				pNext
+			(VkSamplerCreateFlags)0,						// VkSamplerCreateFlags		flags
+			VK_FILTER_NEAREST,								// VkFilter					minFilter
+			VK_FILTER_NEAREST,								// VkFilter					magFilter
+			VK_SAMPLER_MIPMAP_MODE_NEAREST,					// VkSamplerMipMapMode		mipMapMode
+			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeU
+			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressModeV
+			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			// VkSamplerAddressMode		addressmodeW
+			0.0f,											// float					mipLodBias
+			VK_FALSE,										// VkBool32					anisotropyEnable
+			0.0f,											// float					maxAnisotropy
+			VK_FALSE,										// VkBool32					compareEnable
+			VK_COMPARE_OP_NEVER,							// VkCompareOp				compareOp
+			0.0f,											// float					minLod
+			0.0f,											// float					maxLod
+			VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,		// VkBorderColor			borderColor
+			VK_FALSE										// VkBool32					unnormalizedCoordinates
+		};
+
+		depthSampler = createSampler(vk, device, &depthSamplerCreateInfo, DE_NULL);
+	}
+
+	// Command Pool
+	{
+		const VkCommandPoolCreateInfo cmdPoolCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType
+			DE_NULL,											// const void*				pNext
+			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags
+			queueFamilyIndex									// uint32_t					queueFamilyIndex
+		};
+
+		cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
+	}
+
+	// Command buffer for data transfers
+	{
+		const VkCommandBufferAllocateInfo cmdBufferAllocInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType		sType,
+			DE_NULL,										// const void*			pNext
+			*cmdPool,										// VkCommandPool		commandPool
+			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel	level
+			1u												// uint32_t				bufferCount
+		};
+
+		transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
+	}
+
+	// Fence for data transfer
+	{
+		const VkFenceCreateInfo fenceCreateInfo =
+		{
+			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType
+			DE_NULL,								// const void*			pNext
+			(VkFenceCreateFlags)0					// VkFenceCreateFlags	flags
+		};
+
+		fence = createFence(vk, device, &fenceCreateInfo);
+	}
+
+	// Initialize Depth Buffer and Marker Buffer
+	{
+		VkImageAspectFlags	depthImageAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
+		if (hasStencilComponent(mapVkFormat(m_format).order))
+			depthImageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
+
+		const VkImageMemoryBarrier imageBarrier[] =
+		{
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
+				DE_NULL,										// const void*			pNext
+				0,												// VkAccessMask			srcAccessMask
+				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessMask			dstAccessMask
+				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		newLayout
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
+				*markerImage,									// VkImage				image
+				{
+					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
+					0u,										// uint32_t				baseMipLevel
+					1u,										// uint32_t				mipLevels
+					0u,										// uint32_t				baseArray
+					1u										// uint32_t				arraySize
+				}
+			},
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
+				DE_NULL,										// const void*			pNext
+				0,												// VkAccessMask			srcAccessMask
+				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessMask			dstAccessMask
+				VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		newLayout
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
+				*depthImage,									// VkImage				image
+				{
+					depthImageAspectFlags,					// VkImageAspectFlags	aspectMask
+					0u,										// uint32_t				baseMipLevel
+					1u,										// uint32_t				mipLevels
+					0u,										// uint32_t				baseArray
+					1u										// uint32_t				arraySize
+				}
+			}
+		};
+
+		const VkImageMemoryBarrier imagePostBarrier[] =
+		{
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
+				DE_NULL,										// const void*			pNext
+				VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlagBits		srcAccessMask
+				VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlagBits		dstAccessMask
+				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		newLayout
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
+				VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
+				*markerImage,									// VkImage				image
+				{
+					VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
+					0u,										// uint32_t				baseMipLevel
+					1u,										// uint32_t				mipLevels
+					0u,										// uint32_t				baseArray
+					1u										// uint32_t				arraySize
+				}
+			},
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
+				DE_NULL,											// cont void*			pNext
+				VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlagBits		srcAccessMask
+				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlagBits		dstAccessMask
+				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout		newLayout
+				VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
+				VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
+				*depthImage,										// VkImage				image
+				{
+					depthImageAspectFlags,						// VkImageAspectFlags	aspectMask
+					0u,											// uint32_t				baseMipLevel
+					1u,											// uint32_t				mipLevels
+					0u,											// uint32_t				baseArray
+					1u											// uint32_t				arraySize
+				}
+
+			}
+		};
+
+		const VkCommandBufferBeginInfo	cmdBufferBeginInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType
+			DE_NULL,										// const void*						pNext
+			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags
+			(const VkCommandBufferInheritanceInfo*)DE_NULL	// VkCommandBufferInheritanceInfo	pInheritanceInfo
+		};
+
+		VK_CHECK(vk.beginCommandBuffer(*transferCmdBuffer, &cmdBufferBeginInfo));
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				0, (const VkBufferMemoryBarrier*)DE_NULL,
+				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
+
+		const VkClearValue				colorClearValue	= makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+		const VkImageSubresourceRange	colorClearRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+		const VkClearValue				depthClearValue	= makeClearValueDepthStencil(m_defaultDepthValue, 0);
+		const VkImageSubresourceRange	depthClearRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
+
+		vk.cmdClearColorImage(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color, 1u, &colorClearRange);
+		vk.cmdClearDepthStencilImage(*transferCmdBuffer, *depthImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthClearValue.depthStencil, 1u, &depthClearRange);
+
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				0, (const VkBufferMemoryBarrier*)DE_NULL,
+				DE_LENGTH_OF_ARRAY(imagePostBarrier), imagePostBarrier);
+
+		VK_CHECK(vk.endCommandBuffer(*transferCmdBuffer));
+
+		const VkSubmitInfo submitInfo =
+		{
+			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType			sType
+			DE_NULL,								// const void*				pNext
+			0u,										// uint32_t					waitSemaphoreCount
+			DE_NULL,								// const VkSemaphore*		pWaitSemaphores
+			(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*	pWaitDstStageMask
+			1u,										// uint32_t					commandBufferCount
+			&transferCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers
+			0u,										// uint32_t					signalSemaphoreCount
+			DE_NULL									// const VkSemaphore*		pSignalSemaphores
+		};
+
+		VK_CHECK(vk.resetFences(device, 1, &fence.get()));
+		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+		VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull)));
+	}
+
+
+	// Perform Draw
+	{
+		std::vector<Vec4>				vertices;
+		std::vector<Shader>				shaders;
+		Move<VkDescriptorSetLayout>		descriptorSetLayout;
+		Move<VkDescriptorPool>			descriptorPool;
+		Move<VkDescriptorSet>			descriptorSet;
+
+		// Descriptors
+		{
+			DescriptorSetLayoutBuilder	layoutBuilder;
+			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
+			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
+			descriptorSetLayout = layoutBuilder.build(vk, device);
+			descriptorPool = DescriptorPoolBuilder()
+					.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
+					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
+					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
+			{
+				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+				DE_NULL,
+				*descriptorPool,
+				1u,
+				&descriptorSetLayout.get()
+			};
+
+			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
+
+			const VkDescriptorBufferInfo bufferInfo =
+			{
+				*controlBuffer,
+				0u,
+				VK_WHOLE_SIZE
+			};
+
+			const VkDescriptorImageInfo imageInfo =
+			{
+				(VkSampler)DE_NULL,
+				*markerImageView,
+				VK_IMAGE_LAYOUT_GENERAL
+			};
+
+			DescriptorSetUpdateBuilder()
+				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo)
+				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
+				.update(vk, device);
+		}
+
+		vertices.push_back(Vec4( -0.70f,	0.5f,	0.0f,	1.0f));
+		vertices.push_back(Vec4(  0.45f,	-0.75f,	0.0f,	1.0f));
+		vertices.push_back(Vec4(  0.78f,	0.0f,	0.0f,	1.0f));
+		vertices.push_back(Vec4( -0.1f,		0.6f,	0.0f,	1.0f));
+
+		shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVert")));
+		shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFrag")));
+
+		DrawState				drawState(m_topology, m_renderSize.x(), m_renderSize.y());
+		DrawCallData			drawCallData(vertices);
+		VulkanProgram			vulkanProgram(shaders);
+
+		drawState.depthClampEnable			= m_depthClampEnable;
+		drawState.depthFormat				= m_format;
+		drawState.numSamples				= m_samples;
+		drawState.compareOp					= rr::TESTFUNC_ALWAYS;
+		drawState.depthTestEnable			= true;
+		drawState.depthWriteEnable			= true;
+		drawState.sampleShadingEnable		= true;
+		vulkanProgram.depthImageView		= depthImageView;
+		vulkanProgram.descriptorSetLayout	= descriptorSetLayout;
+		vulkanProgram.descriptorSet			= descriptorSet;
+
+		VulkanDrawContext		vulkanDrawContext(m_context, drawState, drawCallData, vulkanProgram);
+		vulkanDrawContext.draw();
+
+		log << TestLog::Image(	"resultColor",
+								"Result Color Buffer",
+								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
+										vulkanDrawContext.getColorPixels().getFormat()),
+										vulkanDrawContext.getColorPixels().getWidth(),
+										vulkanDrawContext.getColorPixels().getHeight(),
+										1,
+										vulkanDrawContext.getColorPixels().getDataPtr()));
+
+		depthImageView = vulkanProgram.depthImageView;
+	}
+
+	// Barrier to transition between first and second pass
+	{
+		VkImageAspectFlags	depthImageAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
+		if (hasStencilComponent(mapVkFormat(m_format).order))
+			depthImageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
+
+		const VkImageMemoryBarrier imageBarrier[] =
+		{
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
+				DE_NULL,													// const void*			pNext
+				VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,				// VkAccessFlags		srcAccessMask
+				VK_ACCESS_SHADER_READ_BIT,									// VkAccessFlags		dstAccessMask
+				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,			// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
+				0u,															// deUint32				srcQueueFamilyIndex
+				0u,															// deUint32				dstQueueFamilyIndex
+				*depthImage,												// VkImage				image
+				{
+					depthImageAspectFlags,							// VkImageAspectFlags		aspectMask
+					0u,												// deUint32					baseMipLevel
+					1u,												// deUint32					levelCount
+					0u,												// deUint32					baseArrayLayer
+					1u												// deUint32					layerCount
+				}
+			},
+			{
+				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType		sType
+				DE_NULL,													// const void*			pNext
+				0u,															// VkAccessFlags		srcAccessMask
+				VK_ACCESS_HOST_READ_BIT,									// VkAccessFlags		dstAccessMask
+				VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout		oldLayout
+				VK_IMAGE_LAYOUT_GENERAL,									// VkImageLayout		newLayout
+				0u,															// deUint32				srcQueueFamilyIndex
+				0u,															// deUint32				dstQueueFamilyIndex
+				*depthResolveImage,											// VkImage				image
+				{
+					VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags		aspectMask
+					0u,												// deUint32					baseMipLevel
+					1u,												// deUint32					levelCount
+					0u,												// deUint32					baseArrayLayer
+					1u,												// deUint32					layerCount
+
+				}
+			}
+		};
+
+		const VkCommandBufferBeginInfo	cmdBufferBeginInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType
+			DE_NULL,										// const void*						pNext
+			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags
+			(const VkCommandBufferInheritanceInfo*)DE_NULL	// VkCommandBufferInheritanceInfo	pInheritanceInfo
+		};
+
+		VK_CHECK(vk.beginCommandBuffer(*transferCmdBuffer, &cmdBufferBeginInfo));
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				0, (const VkBufferMemoryBarrier*)DE_NULL,
+				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
+		VK_CHECK(vk.endCommandBuffer(*transferCmdBuffer));
+
+		const VkSubmitInfo submitInfo =
+		{
+			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType			sType
+			DE_NULL,								// const void*				pNext
+			0u,										// uint32_t					waitSemaphoreCount
+			DE_NULL,								// const VkSemaphore*		pWaitSemaphores
+			(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*	pWaitDstStageMask
+			1u,										// uint32_t					commandBufferCount
+			&transferCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers
+			0u,										// uint32_t					signalSemaphoreCount
+			DE_NULL									// const VkSemaphore*		pSignalSemaphores
+		};
+
+		VK_CHECK(vk.resetFences(device, 1, &fence.get()));
+		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+		VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull)));
+	}
+
+	// Resolve Depth Buffer
+	{
+		std::vector<Vec4>				vertices;
+		std::vector<Shader>				shaders;
+		Move<VkDescriptorSetLayout>		descriptorSetLayout;
+		Move<VkDescriptorPool>			descriptorPool;
+		Move<VkDescriptorSet>			descriptorSet;
+
+		// Descriptors
+		{
+			DescriptorSetLayoutBuilder	layoutBuilder;
+			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+			layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
+			descriptorSetLayout = layoutBuilder.build(vk, device);
+			descriptorPool = DescriptorPoolBuilder()
+					.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+					.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
+					.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+			const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
+			{
+				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+				DE_NULL,
+				*descriptorPool,
+				1u,
+				&descriptorSetLayout.get()
+			};
+
+			descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
+
+			const VkDescriptorImageInfo depthImageInfo =
+			{
+				*depthSampler,
+				*depthImageView,
+				VK_IMAGE_LAYOUT_GENERAL
+			};
+
+			const VkDescriptorImageInfo imageInfo =
+			{
+				(VkSampler)DE_NULL,
+				*depthResolveImageView,
+				VK_IMAGE_LAYOUT_GENERAL
+			};
+
+			DescriptorSetUpdateBuilder()
+				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo)
+				.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
+				.update(vk, device);
+		}
+
+		vertices.push_back(Vec4( -1.0f,	-1.0f,	0.0f,	1.0f));
+		vertices.push_back(Vec4( -1.0f,	 1.0f,	0.0f,	1.0f));
+		vertices.push_back(Vec4(  1.0f,	-1.0f,	0.0f,	1.0f));
+		vertices.push_back(Vec4(  1.0f,	 1.0f,	0.0f,	1.0f));
+
+		shaders.push_back(Shader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVertPass2")));
+		shaders.push_back(Shader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFragPass2")));
+
+		DrawState				drawState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, m_renderSize.x(), m_renderSize.y());
+		DrawCallData			drawCallData(vertices);
+		VulkanProgram			vulkanProgram(shaders);
+
+		drawState.numSamples				= m_samples;
+		drawState.sampleShadingEnable		= true;
+		vulkanProgram.descriptorSetLayout	= descriptorSetLayout;
+		vulkanProgram.descriptorSet			= descriptorSet;
+
+		VulkanDrawContext		vulkanDrawContext(m_context, drawState, drawCallData, vulkanProgram);
+		vulkanDrawContext.draw();
+	}
+
+	// Transfer marker buffer
+	{
+		const UVec2 copySize		= UVec2(m_renderSize.x() * m_samples, m_renderSize.y());
+		const VkImageMemoryBarrier imageBarrier =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType		sType
+			DE_NULL,										// const void*			pNext
+			VK_ACCESS_SHADER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
+			VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessMask			dstAccessMask
+			VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout		oldLayout
+			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout		newLayout
+			VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
+			VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
+			*markerImage,									// VkImage				image
+			{
+				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
+				0u,										// uint32_t				baseMipLevel
+				1u,										// uint32_t				mipLevels
+				0u,										// uint32_t				baseArray
+				1u										// uint32_t				arraySize
+			}
+		};
+
+		const VkBufferMemoryBarrier bufferBarrier =
+		{
+			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType		sType
+			DE_NULL,										// const void*			pNext
+			VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags		srcAccessMask
+			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags		dstAccessMask
+			VK_QUEUE_FAMILY_IGNORED,						// uint32_t				srcQueueFamilyIndex
+			VK_QUEUE_FAMILY_IGNORED,						// uint32_t				dstQueueFamilyIndex
+			*markerBuffer,									// VkBufer				buffer
+			0u,												// VkDeviceSize			offset
+			VK_WHOLE_SIZE									// VkDeviceSize			size
+		};
+
+		const VkBufferImageCopy bufferImageCopy =
+		{
+			0u,									// VkDeviceSize		bufferOffset
+			copySize.x(),						// uint32_t			bufferRowLength
+			copySize.y(),						// uint32_t			bufferImageHeight
+			{
+				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspect
+				0u,							// uint32_t				mipLevel
+				0u,							// uint32_t				baseArrayLayer
+				1u							// uint32_t				layerCount
+			},
+			{ 0, 0, 0 },						// VkOffset3D		imageOffset
+			{
+				copySize.x(),				// uint32_t				width
+				copySize.y(),				// uint32_t				height,
+				1u							// uint32_t				depth
+			}
+		};
+
+		const VkCommandBufferBeginInfo	cmdBufferBeginInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType
+			DE_NULL,										// const void*						pNext
+			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags
+			(const VkCommandBufferInheritanceInfo*)DE_NULL	// VkCommandBufferInheritanceInfo	pInheritanceInfo
+		};
+
+		VK_CHECK(vk.beginCommandBuffer(*transferCmdBuffer, &cmdBufferBeginInfo));
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				0, (const VkBufferMemoryBarrier*)DE_NULL,
+				1, &imageBarrier);
+		vk.cmdCopyImageToBuffer(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *markerBuffer, 1u, &bufferImageCopy);
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				1, &bufferBarrier,
+				0, (const VkImageMemoryBarrier*)DE_NULL);
+		VK_CHECK(vk.endCommandBuffer(*transferCmdBuffer));
+
+		const VkSubmitInfo submitInfo =
+		{
+			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType			sType
+			DE_NULL,								// const void*				pNext
+			0u,										// uint32_t					waitSemaphoreCount
+			DE_NULL,								// const VkSemaphore*		pWaitSemaphores
+			(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*	pWaitDstStageMask
+			1u,										// uint32_t					commandBufferCount
+			&transferCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers
+			0u,										// uint32_t					signalSemaphoreCount
+			DE_NULL									// const VkSemaphore*		pSignalSemaphores
+		};
+
+		VK_CHECK(vk.resetFences(device, 1, &fence.get()));
+		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+		VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull)));
+	}
+
+	// Verify depth buffer
+	{
+		bool status;
+
+		const VkBufferMemoryBarrier bufferBarrier =
+		{
+			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,			// VkStructureType		sType
+			DE_NULL,											// const void*			pNext
+			VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags		srcAccessMask
+			VK_ACCESS_HOST_READ_BIT,							// VkAccessFlags		dstAccessMask
+			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
+			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
+			*validationBuffer,									// VkBuffer				buffer
+			0u,													// VkDeviceSize			offset
+			VK_WHOLE_SIZE										// VkDeviceSize			size
+		};
+
+		const VkImageMemoryBarrier imageBarrier =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType		sType
+			DE_NULL,											// const void*			pNext
+			VK_ACCESS_SHADER_WRITE_BIT,							// VkAccessFlags		srcAccessMask
+			VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags		dstAccessMask
+			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout		oldLayout
+			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				// VkImageLayout		newLayout
+			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				srcQueueFamilyIndex
+			VK_QUEUE_FAMILY_IGNORED,							// uint32_t				dstQueueFamilyIndex
+			*depthResolveImage,									// VkImage				image
+			{
+				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask
+				0u,										// uint32_t				baseMipLevel
+				1u,										// uint32_t				mipLevels,
+				0u,										// uint32_t				baseArray
+				1u,										// uint32_t				arraySize
+			}
+		};
+
+		const VkBufferImageCopy bufferImageCopy =
+		{
+			0u,													// VkDeviceSize			bufferOffset
+			m_samples * m_renderSize.x(),						// uint32_t				bufferRowLength
+			m_renderSize.y(),									// uint32_t				bufferImageHeight
+			{
+				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspect
+				0u,										// uint32_t				mipLevel
+				0u,										// uint32_t				baseArrayLayer
+				1u										// uint32_t				layerCount
+			},
+			{ 0, 0, 0 },										// VkOffset3D			imageOffset
+			{
+				m_samples * m_renderSize.x(),			// uint32_t				width
+				m_renderSize.y(),						// uint32_t				height
+				1u										// uint32_t				depth
+			}
+		};
+
+		const VkCommandBufferBeginInfo	cmdBufferBeginInfo =
+		{
+			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType
+			DE_NULL,										// const void*						pNext
+			VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags
+			(const VkCommandBufferInheritanceInfo*)DE_NULL	// VkCommandBufferInheritanceInfo	pInheritanceInfo
+		};
+
+		VK_CHECK(vk.beginCommandBuffer(*transferCmdBuffer, &cmdBufferBeginInfo));
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				0, (const VkBufferMemoryBarrier*)DE_NULL,
+				1, &imageBarrier);
+		vk.cmdCopyImageToBuffer(*transferCmdBuffer, *depthResolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *validationBuffer, 1u, &bufferImageCopy);
+		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
+				(VkDependencyFlags)0,
+				0, (const VkMemoryBarrier*)DE_NULL,
+				1, &bufferBarrier,
+				0, (const VkImageMemoryBarrier*)DE_NULL);
+		VK_CHECK(vk.endCommandBuffer(*transferCmdBuffer));
+
+		const VkSubmitInfo submitInfo =
+		{
+			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType			sType
+			DE_NULL,								// const void*				pNext
+			0u,										// uint32_t					waitSemaphoreCount
+			DE_NULL,								// const VkSemaphore*		pWaitSemaphores
+			(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*	pWaitDstStageMask
+			1u,										// uint32_t					commandBufferCount
+			&transferCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers
+			0u,										// uint32_t					signalSemaphoreCount
+			DE_NULL									// const VkSemaphore*		pSignalSemaphores
+		};
+
+		VK_CHECK(vk.resetFences(device, 1, &fence.get()));
+		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
+		VK_CHECK(vk.waitForFences(device, 1, &fence.get(), true, ~(0ull)));
+
+		invalidateMappedMemoryRange(vk, device, validationAlloc->getMemory(), validationAlloc->getOffset(), VK_WHOLE_SIZE);
+		invalidateMappedMemoryRange(vk, device, markerBufferAllocation->getMemory(), markerBufferAllocation->getOffset(), VK_WHOLE_SIZE);
+
+		tcu::ConstPixelBufferAccess resultPixelBuffer(mapVkFormat(VK_FORMAT_R32_SFLOAT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, validationAlloc->getHostPtr());
+		tcu::ConstPixelBufferAccess markerPixelBuffer(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), m_renderSize.x() * m_samples, m_renderSize.y(), 1u, markerBufferAllocation->getHostPtr());
+		status = validateDepthBuffer(resultPixelBuffer, markerPixelBuffer, 0.001f);
+		testDesc = "gl_FragDepth " + getPrimitiveTopologyShortName(m_topology) + " ";
+		if (status)
+		{
+			testDesc += "passed";
+			return tcu::TestStatus::pass(testDesc.c_str());
+		}
+		else
+		{
+			log << TestLog::Image("resultDepth", "Result Depth Buffer", resultPixelBuffer);
+			testDesc += "failed";
+			return tcu::TestStatus::fail(testDesc.c_str());
+		}
+	}
+}
+
+bool BuiltinFragDepthCaseInstance::validateDepthBuffer (const tcu::ConstPixelBufferAccess& validationBuffer, const tcu::ConstPixelBufferAccess& markerBuffer, const float tolerance) const
+{
+	TestLog& log = m_context.getTestContext().getLog();
+
+	for (deUint32 rowNdx = 0; rowNdx < m_renderSize.y(); rowNdx++)
+	{
+		for (deUint32 colNdx = 0; colNdx < m_renderSize.x(); colNdx++)
+		{
+			const float multiplier		= m_depthClampEnable ? 0.0f : 1.0f;
+			float expectedValue	= (float)(rowNdx * m_renderSize.x() + colNdx)/256.0f * multiplier;
+
+			if (m_largeDepthEnable)
+				expectedValue += m_largeDepthBase;
+
+			if (expectedValue > 1.0f)
+				expectedValue = 1.0f;
+
+			if (expectedValue < 0.0f)
+				expectedValue = 0.0f;
+
+			for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_samples; sampleNdx++)
+			{
+				const float	actualValue		= validationBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
+				const float	markerValue		= markerBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
+
+				if (markerValue != 0)
+				{
+					if (de::abs(expectedValue - actualValue) > tolerance)
+					{
+						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
+						return false;
+					}
+				}
+				else
+				{
+					if (de::abs(actualValue - m_defaultDepthValue) > tolerance)
+					{
+						log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
+						return false;
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+class BuiltinFragDepthCase : public TestCase
+{
+public:
+					BuiltinFragDepthCase		(TestContext& testCtx, const char* name, const char* description, VkPrimitiveTopology topology,  VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits samples);
+	virtual			~BuiltinFragDepthCase		(void);
+
+	void			initPrograms				(SourceCollections& dst) const;
+	TestInstance*	createInstance				(Context& context) const;
+
+private:
+	const VkPrimitiveTopology		m_topology;
+	const VkFormat					m_format;
+	const bool						m_largeDepthEnable;
+	const float						m_defaultDepth;
+	const bool						m_depthClampEnable;
+	const VkSampleCountFlagBits		m_samples;
+};
+
+BuiltinFragDepthCase::BuiltinFragDepthCase (TestContext& testCtx, const char* name, const char* description, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits  samples)
+	: TestCase				(testCtx, name, description)
+	, m_topology			(topology)
+	, m_format				(format)
+	, m_largeDepthEnable	(largeDepthEnable)
+	, m_defaultDepth		(0.0f)
+	, m_depthClampEnable	(depthClampEnable)
+	, m_samples				(samples)
+{
+}
+
+BuiltinFragDepthCase::~BuiltinFragDepthCase(void)
+{
+}
+
+void BuiltinFragDepthCase::initPrograms (SourceCollections& programCollection) const
+{
+	// Vertex
+	{
+		// Pass 1
+		{
+			std::ostringstream vertexSource;
+			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+				<< "\n"
+				<<  "layout (location = 0) in vec4 position;\n"
+				<< "void main()\n"
+				<< "{\n"
+				<< "	gl_Position = position;\n"
+				<< "}\n";
+			programCollection.glslSources.add("FragDepthVert") << glu::VertexSource(vertexSource.str());
+		}
+
+		// Pass 2
+		{
+			std::ostringstream vertexSource;
+			vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+				<< "\n"
+				<<  "layout (location = 0) in vec4 position;\n"
+				<<  "layout (location = 1) out vec2 texCoord;\n"
+				<< "void main()\n"
+				<< "{\n"
+				<< "	gl_Position = position;\n"
+				<< "	texCoord = position.xy/2 + vec2(0.5);\n"
+				<< "}\n";
+			programCollection.glslSources.add("FragDepthVertPass2") << glu::VertexSource(vertexSource.str());
+		}
+	}
+
+	// Fragment
+	{
+		// Pass 1
+		{
+			std::ostringstream	fragmentSource;
+			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+				<< "\n"
+				<< "layout(location = 0) out mediump vec4 color;\n"
+				<< "layout (std140, set = 0, binding = 0) uniform control_buffer_t\n"
+				<< "{\n"
+				<< "	float data[256];\n"
+				<< "} control_buffer;\n"
+				<< "layout (set = 0, binding = 1, rgba8ui) writeonly uniform uimage2D storageImage;\n"
+				<< "float controlDepthValue;\n"
+				<< "void recheck(float controlDepthValue)\n"
+				<< "{\n"
+				<< "	if (gl_FragDepth != controlDepthValue)\n"
+				<< "		gl_FragDepth = 1.0;\n"
+				<< "}\n"
+				<< "void main()\n"
+				<< "{\n"
+				<< "	const int numSamples = " << m_samples << ";\n"
+				<< "	if (int(gl_FragCoord.x) == " << BuiltinFragDepthCaseInstance::RENDERWIDTH/4 << ")\n"
+				<< "		discard;\n"
+				<< "	highp int index =int(gl_FragCoord.y) * " << BuiltinFragDepthCaseInstance::RENDERHEIGHT << " + int(gl_FragCoord.x);\n"
+				<< "	controlDepthValue = control_buffer.data[index];\n"
+				<< "	gl_FragDepth = controlDepthValue;\n"
+				<< "	const int sampleNdx = int(gl_SampleID);\n"
+				<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_samples << ", int(gl_FragCoord.y));\n"
+				<< "	imageStore(storageImage, imageCoord, uvec4(1));\n"
+				<< "	recheck(controlDepthValue);\n"
+				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+				<< "}\n";
+			programCollection.glslSources.add("FragDepthFrag") << glu::FragmentSource(fragmentSource.str());
+		}
+
+		// Pass 2
+		{
+			const char* multisampleDecoration = m_samples != VK_SAMPLE_COUNT_1_BIT ? "MS" : "";
+			std::ostringstream fragmentSource;
+			fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+				<< "\n"
+				<< "layout (location = 0) out mediump vec4 color;\n"
+				<< "layout (location = 1) in vec2 texCoord;\n"
+				<< "layout (binding = 0, set = 0) uniform sampler2D" << multisampleDecoration << " u_depthTex;\n"
+				<< "layout (binding = 1, set = 0, r32f) writeonly uniform image2D u_outImage;\n"
+				<< "void main (void)\n"
+				<< "{\n"
+				<< "	const int numSamples = " << m_samples << ";\n"
+				<< "	const int sampleNdx = int(gl_SampleID);\n"
+				<< "	ivec2 renderSize = ivec2(" << BuiltinFragDepthCaseInstance::RENDERWIDTH << "," << BuiltinFragDepthCaseInstance::RENDERHEIGHT << ");\n"
+				<< "	ivec2 imageCoord = ivec2(int(texCoord.x * renderSize.x), int(texCoord.y * renderSize.y));\n"
+				<< "	vec4 depthVal = texelFetch(u_depthTex, imageCoord, sampleNdx);\n"
+				<< "	imageStore(u_outImage, ivec2(sampleNdx + int(texCoord.x * renderSize.x) * numSamples, int(texCoord.y * renderSize.y)), depthVal);\n"
+				<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+				<< "}\n";
+			programCollection.glslSources.add("FragDepthFragPass2") << glu::FragmentSource(fragmentSource.str());
+		}
+	}
+}
+
+TestInstance* BuiltinFragDepthCase::createInstance (Context& context) const
+{
+	return new BuiltinFragDepthCaseInstance(context, m_topology, m_format, m_largeDepthEnable, m_defaultDepth, m_depthClampEnable, m_samples);
+}
+
 class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
 {
 public:
@@ -900,6 +2039,7 @@
 	de::MovePtr<TestCaseGroup> simpleGroup			(new TestCaseGroup(testCtx, "simple", "Simple cases."));
 	de::MovePtr<TestCaseGroup> inputVariationsGroup	(new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
 	de::MovePtr<TestCaseGroup> frontFacingGroup		(new TestCaseGroup(testCtx, "frontfacing", "Test gl_Frontfacing keyword."));
+	de::MovePtr<TestCaseGroup> fragDepthGroup		(new TestCaseGroup(testCtx, "fragdepth", "Test gl_FragDepth keyword."));
 
 	simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
 	simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
@@ -925,7 +2065,57 @@
 			frontFacingGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, frontfacingCases[ndx].primitive, frontfacingCases[ndx].name, frontfacingCases[ndx].desc));
 	}
 
+	// gl_FragDepth
+	{
+		static const struct PrimitiveTopologyTable
+		{
+			std::string			name;
+			std::string			desc;
+			VkPrimitiveTopology	prim;
+		} primitiveTopologyTable[] =
+		{
+			{ "point_list",		"test that points respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
+			{ "line_list",		"test taht lines respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
+			{ "triangle_list",	"test that triangles respect gl_fragdepth", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
+		};
+
+		static const struct TestCaseTable
+		{
+			VkFormat				format;
+			std::string				name;
+			bool					largeDepthEnable;
+			bool					depthClampEnable;
+			VkSampleCountFlagBits	samples;
+		} testCaseTable[] =
+		{
+			{ VK_FORMAT_D16_UNORM,				"d16_unorm_no_depth_clamp",				false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_X8_D24_UNORM_PACK32,	"x8_d24_unorm_pack32_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_no_depth_clamp",			false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D16_UNORM_S8_UINT,		"d16_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D24_UNORM_S8_UINT,		"d24_unorm_s8_uint_no_depth_clamp",		false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint_no_depth_clamp",	false,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_large_depth",				true,	false,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat",							false,	true,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT_S8_UINT,		"d32_sfloat_s8_uint",					false,	true,	VK_SAMPLE_COUNT_1_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_2",				false,	false,	VK_SAMPLE_COUNT_2_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_4",				false,	false,	VK_SAMPLE_COUNT_4_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_8",				false,	false,	VK_SAMPLE_COUNT_8_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_16",			false,	false,	VK_SAMPLE_COUNT_16_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_32",			false,	false,	VK_SAMPLE_COUNT_32_BIT },
+			{ VK_FORMAT_D32_SFLOAT,				"d32_sfloat_multisample_64",			false,	false,	VK_SAMPLE_COUNT_64_BIT },
+		};
+
+		for (deUint32 primNdx = 0;  primNdx < DE_LENGTH_OF_ARRAY(primitiveTopologyTable); primNdx++)
+		{
+			for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCaseTable); caseNdx++)
+				fragDepthGroup->addChild(new BuiltinFragDepthCase(testCtx, (primitiveTopologyTable[primNdx].name+"_" + testCaseTable[caseNdx].name).c_str(), primitiveTopologyTable[primNdx].desc.c_str(),
+							primitiveTopologyTable[primNdx].prim, testCaseTable[caseNdx].format, testCaseTable[caseNdx].largeDepthEnable, testCaseTable[caseNdx].depthClampEnable, testCaseTable[caseNdx].samples));
+
+		}
+	}
+
 	builtinGroup->addChild(frontFacingGroup.release());
+	builtinGroup->addChild(fragDepthGroup.release());
 	builtinGroup->addChild(simpleGroup.release());
 
 	for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
diff --git a/external/vulkancts/modules/vulkan/vktDrawUtil.cpp b/external/vulkancts/modules/vulkan/vktDrawUtil.cpp
index 7eb0a21..1642299 100644
--- a/external/vulkancts/modules/vulkan/vktDrawUtil.cpp
+++ b/external/vulkancts/modules/vulkan/vktDrawUtil.cpp
@@ -28,9 +28,11 @@
 #include "vkImageWithMemory.hpp"
 #include "vkTypeUtil.hpp"
 #include "rrRenderer.hpp"
+#include "rrRenderState.hpp"
 #include "rrPrimitiveTypes.hpp"
 #include "tcuTextureUtil.hpp"
 #include "deArrayUtil.hpp"
+#include "vkBuilderUtil.hpp"
 #include "tcuTestLog.hpp"
 
 namespace vkt
@@ -42,6 +44,24 @@
 using namespace tcu;
 using namespace vk;
 
+static VkCompareOp mapCompareOp (rr::TestFunc compareFunc)
+{
+	switch (compareFunc)
+	{
+		case rr::TESTFUNC_NEVER:				return VK_COMPARE_OP_NEVER;
+		case rr::TESTFUNC_LESS:					return VK_COMPARE_OP_LESS;
+		case rr::TESTFUNC_EQUAL:				return VK_COMPARE_OP_EQUAL;
+		case rr::TESTFUNC_LEQUAL:				return VK_COMPARE_OP_LESS_OR_EQUAL;
+		case rr::TESTFUNC_GREATER:				return VK_COMPARE_OP_GREATER;
+		case rr::TESTFUNC_NOTEQUAL:				return VK_COMPARE_OP_NOT_EQUAL;
+		case rr::TESTFUNC_GEQUAL:				return VK_COMPARE_OP_GREATER_OR_EQUAL;
+		case rr::TESTFUNC_ALWAYS:				return VK_COMPARE_OP_ALWAYS;
+		default:
+			DE_ASSERT(false);
+	}
+	return VK_COMPARE_OP_LAST;
+}
+
 rr::PrimitiveType mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology& primitiveTopology)
 {
 	static const rr::PrimitiveType primitiveTypeTable[] =
@@ -289,9 +309,14 @@
 	, colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
 	, renderSize			(tcu::UVec2(renderWidth_, renderHeight_))
 	, depthClampEnable		(false)
+	, depthTestEnable		(false)
+	, depthWriteEnable		(false)
+	, compareOp				(rr::TESTFUNC_LESS)
 	, blendEnable			(false)
 	, lineWidth				(1.0)
 	, numPatchControlPoints	(0)
+	, numSamples			(VK_SAMPLE_COUNT_1_BIT)
+	, sampleShadingEnable	(false)
 {
 	DE_ASSERT(renderSize.x() != 0 && renderSize.y() != 0);
 }
@@ -339,7 +364,7 @@
 VulkanDrawContext::VulkanDrawContext (  Context&				context,
 										const DrawState&		drawState,
 										const DrawCallData&		drawCallData,
-										const VulkanProgram&	vulkanProgram)
+										VulkanProgram&	vulkanProgram)
 	: DrawContext						(drawState, drawCallData)
 	, m_context							(context)
 	, m_program							(vulkanProgram)
@@ -348,6 +373,7 @@
 	const VkDevice			device					= m_context.getDevice();
 	Allocator&				allocator				= m_context.getDefaultAllocator();
 	VkImageSubresourceRange	colorSubresourceRange;
+	Move<VkSampler>			sampler;
 
 	// Command buffer
 	{
@@ -369,11 +395,11 @@
 			makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u),	// VkExtent3D				extent;
 			1u,																			// uint32_t					mipLevels;
 			1u,																			// uint32_t					arrayLayers;
-			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
+			(VkSampleCountFlagBits)m_drawState.numSamples,								// VkSampleCountFlagBits	samples;
 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
 			usage,																		// VkImageUsageFlags		usage;
 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
-			VK_QUEUE_FAMILY_IGNORED,													// uint32_t					queueFamilyIndexCount;
+			0u,																			// uint32_t					queueFamilyIndexCount;
 			DE_NULL,																	// const uint32_t*			pQueueFamilyIndices;
 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
 		};
@@ -405,38 +431,65 @@
 		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
 	}
 
-	// Pipeline layout
+	// bind descriptor sets
 	{
-		m_pipelineLayout = makePipelineLayoutWithoutDescriptors(vk, device);
+		if (!vulkanProgram.descriptorSetLayout)
+			m_pipelineLayout = makePipelineLayoutWithoutDescriptors(vk, device);
+		else
+			m_pipelineLayout = makePipelineLayout(vk, device, vulkanProgram.descriptorSetLayout.get());
 	}
 
 	// Renderpass
 	{
-		const VkAttachmentDescription colorAttachmentDescription =
+		std::vector<VkAttachmentDescription> attachmentDescriptions;
+		const VkAttachmentDescription attachDescriptors[] =
 		{
-			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
-			m_drawState.colorFormat,							// VkFormat							format;
-			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
-			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
-			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
-			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
-			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
-			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
-			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
+			{
+				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
+				m_drawState.colorFormat,							// VkFormat							format;
+				(VkSampleCountFlagBits)m_drawState.numSamples,		// VkSampleCountFlagBits			samples;
+				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
+				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
+				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
+				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
+				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
+				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
+			},
+			{
+				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags
+				m_drawState.depthFormat,							// VkFormat							format
+				(VkSampleCountFlagBits)m_drawState.numSamples,		// VkSampleCountFlagBits			samples
+				VK_ATTACHMENT_LOAD_OP_LOAD,							// VkAttachmentLoadOp				loadOp
+				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp
+				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp
+				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp
+				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout
+				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout
+
+			}
 		};
 
-		const VkAttachmentReference colorAttachmentReference =
+		const VkAttachmentReference attachmentReferences[] =
 		{
-			0u,													// deUint32			attachment;
-			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
+			{
+				0u,													// uint32_t			attachment
+				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout
+			},
+			{
+				1u,													// uint32_t			attachment
+				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout
+			},
+			{
+				VK_ATTACHMENT_UNUSED,								// deUint32         attachment;
+				VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout    layout;
+			}
 		};
 
-		const VkAttachmentReference depthAttachmentReference =
-		{
-			VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
-			VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
-		};
+		attachmentDescriptions.push_back(attachDescriptors[0]);
+		if (vulkanProgram.depthImageView)
+			attachmentDescriptions.push_back(attachDescriptors[1]);
 
+		deUint32 depthReferenceNdx = vulkanProgram.depthImageView ? 1 : 2;
 		const VkSubpassDescription subpassDescription =
 		{
 			(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
@@ -444,9 +497,9 @@
 			0u,													// deUint32							inputAttachmentCount;
 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
 			1u,													// deUint32							colorAttachmentCount;
-			&colorAttachmentReference,							// const VkAttachmentReference*		pColorAttachments;
+			&attachmentReferences[0],							// const VkAttachmentReference*		pColorAttachments;
 			DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
-			&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
+			&attachmentReferences[depthReferenceNdx],			// const VkAttachmentReference*		pDepthStencilAttachment;
 			0u,													// deUint32							preserveAttachmentCount;
 			DE_NULL												// const deUint32*					pPreserveAttachments;
 		};
@@ -456,8 +509,8 @@
 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
 			DE_NULL,											// const void*						pNext;
 			(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
-			1u,													// deUint32							attachmentCount;
-			&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
+			(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount;
+			&attachmentDescriptions[0],							// const VkAttachmentDescription*	pAttachments;
 			1u,													// deUint32							subpassCount;
 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
 			0u,													// deUint32							dependencyCount;
@@ -469,18 +522,20 @@
 
 	// Framebuffer
 	{
-		const VkImageView attachmentBindInfos[] =
-		{
-			m_colorImageView.get()
-		};
+		std::vector<VkImageView>	attachmentBindInfos;
+		deUint32					numAttachments;
+		attachmentBindInfos.push_back(*m_colorImageView);
+		if (vulkanProgram.depthImageView)
+			attachmentBindInfos.push_back(*vulkanProgram.depthImageView);
 
+		numAttachments = (deUint32)(attachmentBindInfos.size());
 		const VkFramebufferCreateInfo framebufferInfo = {
 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType						sType;
 			DE_NULL,										// const void*							pNext;
 			(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags				flags;
 			*m_renderPass,									// VkRenderPass							renderPass;
-			DE_LENGTH_OF_ARRAY(attachmentBindInfos),		// uint32_t								attachmentCount;
-			attachmentBindInfos,							// const VkImageView*					pAttachments;
+			numAttachments,									// uint32_t								attachmentCount;
+			&attachmentBindInfos[0],						// const VkImageView*					pAttachments;
 			m_drawState.renderSize.x(),						// uint32_t								width;
 			m_drawState.renderSize.y(),						// uint32_t								height;
 			1u,												// uint32_t								layers;
@@ -581,9 +636,9 @@
 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
 			DE_NULL,													// const void*								pNext;
 			(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
-			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
-			VK_FALSE,													// VkBool32									sampleShadingEnable;
-			0.0f,														// float									minSampleShading;
+			(VkSampleCountFlagBits)m_drawState.numSamples,				// VkSampleCountFlagBits					rasterizationSamples;
+			m_drawState.sampleShadingEnable ? VK_TRUE : VK_FALSE,		// VkBool32									sampleShadingEnable;
+			m_drawState.sampleShadingEnable ? 1.0f : 0.0f,				// float									minSampleShading;
 			DE_NULL,													// const VkSampleMask*						pSampleMask;
 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
 			VK_FALSE													// VkBool32									alphaToOneEnable;
@@ -603,10 +658,10 @@
 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
 			DE_NULL,													// const void*								pNext;
 			(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
-			VK_FALSE,													// VkBool32									depthTestEnable;
-			VK_FALSE,													// VkBool32									depthWriteEnable;
-			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
-			VK_FALSE,													// VkBool32									depthBoundsTestEnable;
+			m_drawState.depthTestEnable,								// VkBool32									depthTestEnable;
+			m_drawState.depthWriteEnable,								// VkBool32									depthWriteEnable;
+			mapCompareOp(m_drawState.compareOp),						// VkCompareOp								depthCompareOp;
+			VK_TRUE,													// VkBool32									depthBoundsTestEnable;
 			VK_FALSE,													// VkBool32									stencilTestEnable;
 			stencilOpState,												// VkStencilOpState							front;
 			stencilOpState,												// VkStencilOpState							back;
@@ -700,10 +755,13 @@
 		const VkDeviceSize zeroOffset = 0ull;
 
 		beginCommandBuffer(vk, *m_cmdBuffer);
+		if (vulkanProgram.descriptorSet)
+			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*vulkanProgram.descriptorSet, 0u, DE_NULL);
 
 		// Begin render pass
 		{
-			const VkClearValue	clearValue = makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+			const VkClearValue	clearValue	= makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
 			const VkRect2D		renderArea =
 			{
 				makeOffset2D(0, 0),
@@ -740,10 +798,67 @@
 				0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
 		}
 
+		// Resolve multisample image
 		{
+			if (m_drawState.numSamples != VK_SAMPLE_COUNT_1_BIT)
+			{
+				const VkImageResolve imageResolve =
+				{
+					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
+					{ 0, 0, 0},
+					makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
+					{ 0, 0, 0},
+					makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u)
+				};
+
+				const VkImageCreateInfo resolveImageCreateInfo =
+				{
+					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,				// VkStructureType			sType
+					DE_NULL,											// const void*				pNext
+					(VkImageCreateFlags)0,								// VkImageCreateFlags		flags
+					VK_IMAGE_TYPE_2D,									// VkImageType				imageType
+					m_drawState.colorFormat,							// VkFormat					format
+					makeExtent3D(m_drawState.renderSize.x(),			// VkExtent3D				extent;
+							m_drawState.renderSize.y(), 1u),
+					1u,													// uint32_t					mipLevels
+					1u,													// uint32_t					arrayLayers
+					VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits	samples
+					VK_IMAGE_TILING_OPTIMAL,							// VkImaageTiling			tiling
+					VK_IMAGE_USAGE_TRANSFER_DST_BIT |					// VkImageUsageFlags		usage
+					VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+					VK_SHARING_MODE_EXCLUSIVE,							// VkSharingModeExclusive	sharingMode
+					0u,													// uint32_t					queueFamilyIndexCount
+					DE_NULL,											// const uint32_t*			pQueueFamilyIndices
+					VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout			initialLayout
+				};
+
+				m_resolveImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, resolveImageCreateInfo, MemoryRequirement::Any));
+
+				const VkImageMemoryBarrier resolveBarrier = makeImageMemoryBarrier(
+						0u, VK_ACCESS_TRANSFER_READ_BIT,
+						VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+						**m_resolveImage, colorSubresourceRange);
+
+				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
+						0u, DE_NULL, 0u, DE_NULL, 1u, &resolveBarrier);
+
+				vk.cmdResolveImage(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+						**m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &imageResolve);
+
+				const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
+					VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
+					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+					**m_resolveImage, colorSubresourceRange);
+
+				vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
+					0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
+			}
+			else
+				m_resolveImage = m_colorImage;
+
 			const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
 					makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u));
-			vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
+			vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
 		}
 
 		// Barrier: copy to buffer -> host read
diff --git a/external/vulkancts/modules/vulkan/vktDrawUtil.hpp b/external/vulkancts/modules/vulkan/vktDrawUtil.hpp
index d6bd65f..8e64ac0 100644
--- a/external/vulkancts/modules/vulkan/vktDrawUtil.hpp
+++ b/external/vulkancts/modules/vulkan/vktDrawUtil.hpp
@@ -54,13 +54,19 @@
 
 struct DrawState
 {
-	const vk::VkPrimitiveTopology	topology;
-	const vk::VkFormat				colorFormat;
+	vk::VkPrimitiveTopology			topology;
+	vk::VkFormat					colorFormat;
+	vk::VkFormat					depthFormat;
 	tcu::UVec2						renderSize;
 	bool							depthClampEnable;
+	bool							depthTestEnable;
+	bool							depthWriteEnable;
+	rr::TestFunc					compareOp;
 	bool							blendEnable;
 	float							lineWidth;
 	deUint32						numPatchControlPoints;
+	deUint32						numSamples;
+	bool							sampleShadingEnable;
 
 	DrawState (const vk::VkPrimitiveTopology topology_, deUint32 renderWidth_, deUint32 renderHeight_);
 };
@@ -94,8 +100,8 @@
 	virtual void							draw					(void) = 0;
 	virtual tcu::ConstPixelBufferAccess		getColorPixels			(void) const = 0;
 protected:
-		const DrawState						m_drawState;
-		const DrawCallData					m_drawCallData;
+		const DrawState&					m_drawState;
+		const DrawCallData&					m_drawCallData;
 };
 
 class ReferenceDrawContext : public DrawContext
@@ -121,7 +127,10 @@
 
 struct VulkanProgram
 {
-	const std::vector<Shader>&				shaders;
+	const std::vector<Shader>&			shaders;
+	vk::Move<vk::VkImageView>			depthImageView;
+	vk::Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
+	vk::Move<vk::VkDescriptorSet>		descriptorSet;
 
 	VulkanProgram		(const std::vector<Shader>&			shaders_)
 		: shaders		(shaders_)
@@ -135,18 +144,19 @@
 											VulkanDrawContext	(Context&				context,
 																 const DrawState&		drawState,
 																 const DrawCallData&	drawCallData,
-																 const VulkanProgram&	vulkanProgram);
+																 VulkanProgram&			vulkanProgram);
 	virtual									~VulkanDrawContext	(void);
 	virtual void							draw				(void);
 	virtual tcu::ConstPixelBufferAccess		getColorPixels		(void) const;
 private:
-	enum Contants
+	enum VulkanContants
 	{
 		MAX_NUM_SHADER_MODULES					= 5,
 	};
 	Context&									m_context;
-	VulkanProgram								m_program;
+	VulkanProgram&								m_program;
 	de::MovePtr<vk::ImageWithMemory>			m_colorImage;
+	de::MovePtr<vk::ImageWithMemory>			m_resolveImage;
 	de::MovePtr<vk::BufferWithMemory>			m_colorAttachmentBuffer;
 	vk::refdetails::Move<vk::VkImageView>		m_colorImageView;
 	vk::refdetails::Move<vk::VkRenderPass>		m_renderPass;
diff --git a/external/vulkancts/mustpass/1.0.2/src/excluded-tests.txt b/external/vulkancts/mustpass/1.0.2/src/excluded-tests.txt
index 6c97232..6ce5b49 100644
--- a/external/vulkancts/mustpass/1.0.2/src/excluded-tests.txt
+++ b/external/vulkancts/mustpass/1.0.2/src/excluded-tests.txt
@@ -325,3 +325,6 @@
 dEQP-VK.pipeline.render_to_image.*.small.r32_uint_d32_sfloat_s8_uint
 dEQP-VK.pipeline.render_to_image.*.small.r16g16_sint_d32_sfloat_s8_uint
 dEQP-VK.pipeline.render_to_image.*.small.r32g32b32a32_sfloat_d32_sfloat_s8_uint
+
+#VK-GL-CTS 655
+dEQP-VK.glsl.builtin_var.fragdepth.*