/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Copyright (c) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Shader builtin variable tests.
 *//*--------------------------------------------------------------------*/

#include "vktShaderRenderBuiltinVarTests.hpp"

#include "tcuFloat.hpp"
#include "deUniquePtr.hpp"
#include "vkDefs.hpp"
#include "vktShaderRender.hpp"
#include "gluShaderUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuTestLog.hpp"
#include "vktDrawUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkCmdUtil.hpp"

#include "deMath.h"
#include "deRandom.hpp"

#include <map>

using namespace std;
using namespace tcu;
using namespace vk;
using namespace de;

namespace vkt
{
using namespace drawutil;

namespace sr
{

namespace
{

enum
{
	FRONTFACE_RENDERWIDTH			= 16,
	FRONTFACE_RENDERHEIGHT			= 16
};

class FrontFacingVertexShader : public rr::VertexShader
{
public:
	FrontFacingVertexShader (void)
		: rr::VertexShader(1, 0)
	{
		m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
	}

	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
																	 packets[packetNdx]->instanceNdx,
																	 packets[packetNdx]->vertexNdx);
		}
	}
};

class FrontFacingFragmentShader : public rr::FragmentShader
{
public:
	FrontFacingFragmentShader (void)
		: rr::FragmentShader(0, 1)
	{
		m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
	}

	void shadeFragments (rr::FragmentPacket* , const int numPackets, const rr::FragmentShadingContext& context) const
	{
		tcu::Vec4 color;
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
			{
				if (context.visibleFace == rr::FACETYPE_FRONT)
					color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
				else
					color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
			}
		}
	}
};

class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
{
public:
					BuiltinGlFrontFacingCaseInstance	(Context& context, VkPrimitiveTopology topology);

	TestStatus		iterate								(void);
private:
	const VkPrimitiveTopology							m_topology;
};

BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context, VkPrimitiveTopology topology)
	: ShaderRenderCaseInstance	(context)
	, m_topology				(topology)
{
}


TestStatus BuiltinGlFrontFacingCaseInstance::iterate (void)
{
	TestLog&							log				= m_context.getTestContext().getLog();
	std::vector<Vec4>					vertices;
	std::vector<VulkanShader>			shaders;
	std::shared_ptr<rr::VertexShader>	vertexShader	= std::make_shared<FrontFacingVertexShader>();
	std::shared_ptr<rr::FragmentShader>	fragmentShader	= std::make_shared<FrontFacingFragmentShader>();
	std::string							testDesc;

	vertices.push_back(Vec4( -0.75f,	-0.75f,	0.0f,	1.0f));
	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));
	vertices.push_back(Vec4( -0.37f,	0.75f,	0.0f,	1.0f));
	vertices.push_back(Vec4(  0.37f,	0.75f,	0.0f,	1.0f));
	vertices.push_back(Vec4(  0.75f,	-0.75f,	0.0f,	1.0f));
	vertices.push_back(Vec4(  0.0f,		-0.75f,	0.0f,	1.0f));

	shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert")));
	shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag")));

	testDesc = "gl_FrontFacing " + getPrimitiveTopologyShortName(m_topology) + " ";

	FrameBufferState			frameBufferState	(FRONTFACE_RENDERWIDTH, FRONTFACE_RENDERHEIGHT);
	PipelineState				pipelineState		(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
	DrawCallData				drawCallData		(m_topology, vertices);
	VulkanProgram				vulkanProgram		(shaders);
	VulkanDrawContext			dc					(m_context, frameBufferState);
	dc.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
	dc.draw();

	ReferenceDrawContext		refDrawContext(frameBufferState);
	refDrawContext.registerDrawObject(pipelineState, vertexShader, fragmentShader, drawCallData);
	refDrawContext.draw();

	log << TestLog::Image( "reference",
							"reference",
							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
									refDrawContext.getColorPixels().getFormat()),
									refDrawContext.getColorPixels().getWidth(),
									refDrawContext.getColorPixels().getHeight(),
									1,
									refDrawContext.getColorPixels().getDataPtr()));

	log << TestLog::Image(	"result",
							"result",
							tcu::ConstPixelBufferAccess(tcu::TextureFormat(
									dc.getColorPixels().getFormat()),
									dc.getColorPixels().getWidth(),
									dc.getColorPixels().getHeight(),
									1,
									dc.getColorPixels().getDataPtr()));

	if (tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
												  "ComparisonResult",
												  "Image comparison result",
												  refDrawContext.getColorPixels(),
												  dc.getColorPixels(),
												  UVec4(0u),
												  IVec3(1,1,0),
												  false,
												  tcu::COMPARE_LOG_RESULT))
	{
		testDesc += "passed";
		return tcu::TestStatus::pass(testDesc.c_str());
	}
	else
	{
		testDesc += "failed";
		return tcu::TestStatus::fail(testDesc.c_str());
	}
}

class BuiltinGlFrontFacingCase : public TestCase
{
public:
								BuiltinGlFrontFacingCase	(TestContext& testCtx, VkPrimitiveTopology topology, const char* name, const char* description);
	virtual						~BuiltinGlFrontFacingCase	(void);

	void						initPrograms				(SourceCollections& dst) const;
	TestInstance*				createInstance				(Context& context) const;

private:
								BuiltinGlFrontFacingCase	(const BuiltinGlFrontFacingCase&);	// not allowed!
	BuiltinGlFrontFacingCase&	operator=					(const BuiltinGlFrontFacingCase&);	// not allowed!

	const VkPrimitiveTopology	m_topology;
};

BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, VkPrimitiveTopology topology, const char* name, const char* description)
	: TestCase					(testCtx, name, description)
	, m_topology				(topology)
{
}

BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
{
}

void BuiltinGlFrontFacingCase::initPrograms (SourceCollections& programCollection) const
{
	{
		std::ostringstream vertexSource;
		vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
			<< "\n"
			<< "layout(location = 0) in highp vec4 position;\n"
			<< "void main()\n"
			<< "{\n"
			<< "gl_Position = position;\n"
			<< "gl_PointSize = 1.0;\n"
			<< "}\n";
		programCollection.glslSources.add("vert") << glu::VertexSource(vertexSource.str());
	}

	{
		std::ostringstream fragmentSource;
		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
			<< "\n"
			<< "layout(location = 0) out mediump vec4 color;\n"
			<< "void main()\n"
			<< "{\n"
			<< "if (gl_FrontFacing)\n"
			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
			<< "else\n"
			<< "	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
			<< "}\n";
		programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str());
	}
}

TestInstance* BuiltinGlFrontFacingCase::createInstance (Context& context) const
{
	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");

		if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
			throw tcu::NotSupportedError("sampleRateShading 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");

		if (m_largeDepthEnable && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
			throw tcu::NotSupportedError("large_depth test variants require the VK_EXT_depth_range_unrestricted extension");

		if (m_context.getDeviceFeatures().depthClamp == VK_FALSE && m_depthClampEnable)
			throw tcu::NotSupportedError("Depthclamp is not supported.");
	}
	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<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);
	}

	// Initialize 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
				}
			},
		};

		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
				}
			},
		};

		beginCommandBuffer(vk, *transferCmdBuffer);
		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);

		vk.cmdClearColorImage(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color, 1u, &colorClearRange);

		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);

		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
	}


	// Perform Draw
	{
		std::vector<Vec4>				vertices;
		std::vector<VulkanShader>		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(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVert")));
		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFrag")));

		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
		DrawCallData				drawCallData(m_topology, vertices);
		VulkanProgram				vulkanProgram(shaders);

		frameBufferState.depthFormat		= m_format;
		frameBufferState.numSamples			= m_samples;
		frameBufferState.depthImageView		= *depthImageView;
		pipelineState.depthClampEnable		= m_depthClampEnable;
		pipelineState.compareOp				= rr::TESTFUNC_ALWAYS;
		pipelineState.depthTestEnable		= true;
		pipelineState.depthWriteEnable		= true;
		pipelineState.sampleShadingEnable	= true;
		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
		vulkanProgram.descriptorSet			= *descriptorSet;

		VulkanDrawContext			vulkanDrawContext(m_context, frameBufferState);
		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
		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()));
	}

	// 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

				}
			}
		};

		beginCommandBuffer(vk, *transferCmdBuffer);
		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_HOST_BIT,
				(VkDependencyFlags)0,
				0, (const VkMemoryBarrier*)DE_NULL,
				0, (const VkBufferMemoryBarrier*)DE_NULL,
				DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
	}

	// Resolve Depth Buffer
	{
		std::vector<Vec4>				vertices;
		std::vector<VulkanShader>		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(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVertPass2")));
		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFragPass2")));

		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
		DrawCallData				drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
		VulkanProgram				vulkanProgram(shaders);

		frameBufferState.numSamples				= m_samples;
		pipelineState.sampleShadingEnable		= true;
		vulkanProgram.descriptorSetLayout		= *descriptorSetLayout;
		vulkanProgram.descriptorSet				= *descriptorSet;

		VulkanDrawContext		vulkanDrawContext(m_context, frameBufferState);
		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
		vulkanDrawContext.draw();
	}

	// Transfer marker buffer
	{
		beginCommandBuffer(vk, *transferCmdBuffer);
		copyImageToBuffer(vk, *transferCmdBuffer, *markerImage, *markerBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
	}

	// Verify depth buffer
	{
		bool status;

		beginCommandBuffer(vk, *transferCmdBuffer, 0u);
		copyImageToBuffer(vk, *transferCmdBuffer, *depthResolveImage, *validationBuffer, tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());

		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;

			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 BuiltinFragCoordMsaaCaseInstance : public TestInstance
{
public:
	enum
	{
		RENDERWIDTH		= 16,
		RENDERHEIGHT	= 16
	};
				BuiltinFragCoordMsaaCaseInstance	(Context& context, VkSampleCountFlagBits sampleCount);
	TestStatus	iterate								(void);
private:
	bool		validateSampleLocations				(const ConstPixelBufferAccess& sampleLocationBuffer) const;

	const tcu::UVec2				m_renderSize;
	const VkSampleCountFlagBits		m_sampleCount;
};

BuiltinFragCoordMsaaCaseInstance::BuiltinFragCoordMsaaCaseInstance (Context& context, VkSampleCountFlagBits sampleCount)
	: TestInstance		(context)
	, m_renderSize		(RENDERWIDTH, RENDERHEIGHT)
	, m_sampleCount		(sampleCount)
{
	const InstanceInterface&	vki					= m_context.getInstanceInterface();
	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();

	if (!context.getDeviceFeatures().sampleRateShading)
		TCU_THROW(NotSupportedError, "sampleRateShading not supported");

	try
	{
		VkImageFormatProperties		imageFormatProperties;
		VkFormatProperties			formatProperties;

		if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
			throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");

		if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
			throw tcu::NotSupportedError("sampleRateShading not supported");

		imageFormatProperties = getPhysicalDeviceImageFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_TYPE_2D,
				VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, (VkImageCreateFlags)0);

		if ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
			throw tcu::NotSupportedError("Image format and sample count not supported");

		formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT);

		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
			throw tcu::NotSupportedError("Output 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 BuiltinFragCoordMsaaCaseInstance::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();
	Move<VkImage>					outputImage;
	Move<VkImageView>				outputImageView;
	MovePtr<Allocation>				outputImageAllocation;
	Move<VkDescriptorSetLayout>		descriptorSetLayout;
	Move<VkDescriptorPool>			descriptorPool;
	Move<VkDescriptorSet>			descriptorSet;
	Move<VkBuffer>					sampleLocationBuffer;
	MovePtr<Allocation>				sampleLocationBufferAllocation;
	Move<VkCommandPool>				cmdPool;
	Move<VkCommandBuffer>			transferCmdBuffer;

	// Coordinate result image
	{
		const VkImageCreateInfo outputImageCreateInfo =
		{
			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_R32G32B32A32_SFLOAT,							// VkFormat					format
			makeExtent3D(m_sampleCount * m_renderSize.x(), m_renderSize.y(), 1u),	// VkExtent3D				extent3d
			1u,														// uint32_t					mipLevels
			1u,														// uint32_t					arrayLayers
			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples
			VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling
			VK_IMAGE_USAGE_STORAGE_BIT |							// VkImageUsageFlags		usage
			VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
			VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode
			0u,														// uint32_t					queueFamilyIndexCount
			DE_NULL,												// const uint32_t*			pQueueFamilyIndices
			VK_IMAGE_LAYOUT_UNDEFINED								// VkImageLayout			initialLayout
		};

		outputImage = createImage(vk, device, &outputImageCreateInfo, DE_NULL);
		outputImageAllocation = allocator.allocate(getImageMemoryRequirements(vk, device, *outputImage), MemoryRequirement::Any);
		vk.bindImageMemory(device, *outputImage, outputImageAllocation->getMemory(), outputImageAllocation->getOffset());

		VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
		const VkImageViewCreateInfo outputImageViewCreateInfo =
		{
			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,				// VkStructureType			sType
			DE_NULL,												// const void*				pNext
			(VkImageViewCreateFlags)0,								// VkImageViewCreateFlags	flags
			*outputImage,											// VkImage					image
			VK_IMAGE_VIEW_TYPE_2D,									// VkImageViewType			viewType
			VK_FORMAT_R32G32B32A32_SFLOAT,							// VkFormat					format,
			makeComponentMappingRGBA(),								// VkComponentMapping		components
			imageSubresourceRange									// VkImageSubresourceRange	imageSubresourceRange
		};

		outputImageView = createImageView(vk, device, &outputImageViewCreateInfo);
	}

	// Validation buffer
	{
		VkDeviceSize  pixelSize = getPixelSize(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT));
		const VkBufferCreateInfo sampleLocationBufferCreateInfo =
		{
			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,				// VkStructureType		sType
			DE_NULL,											// const void*			pNext
			(VkBufferCreateFlags)0,								// VkBufferCreateFlags	flags
			m_sampleCount * m_renderSize.x() * m_renderSize.y() * pixelSize,	// VkDeviceSize			size
			VK_BUFFER_USAGE_TRANSFER_DST_BIT,					// VkBufferUsageFlags	usage
			VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode		mode
			0u,													// uint32_t				queueFamilyIndexCount
			DE_NULL												// const uint32_t*		pQueueFamilyIndices
		};

		sampleLocationBuffer = createBuffer(vk, device, &sampleLocationBufferCreateInfo, DE_NULL);
		sampleLocationBufferAllocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *sampleLocationBuffer), MemoryRequirement::HostVisible);
		vk.bindBufferMemory(device, *sampleLocationBuffer, sampleLocationBufferAllocation->getMemory(), sampleLocationBufferAllocation->getOffset());
	}

	// Descriptors
	{
		DescriptorSetLayoutBuilder		layoutBuilder;
		layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
		descriptorSetLayout = layoutBuilder.build(vk, device);
		descriptorPool = DescriptorPoolBuilder()
			.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
		};

		descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);

		const VkDescriptorImageInfo imageInfo =
		{
			(VkSampler)DE_NULL,
			*outputImageView,
			VK_IMAGE_LAYOUT_GENERAL
		};

		DescriptorSetUpdateBuilder()
			.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
			.update(vk, device);
	}

	// 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);
	}

	// Transition the output image to LAYOUT_GENERAL
	{
		const VkImageMemoryBarrier barrier =
		{
			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType		sType
			DE_NULL,									// const void*			pNext
			0u,											// VkAccessFlags		srcAccessMask
			VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags		dstAccessMask
			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout		oldLayout
			VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout		newLayout
			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				srcQueueFamilyIndex
			VK_QUEUE_FAMILY_IGNORED,					// uint32_t				dstQueueFamilyIndex
			*outputImage,								// 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
			}
		};

		beginCommandBuffer(vk, *transferCmdBuffer);
		vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
				(VkDependencyFlags)0,
				0, (const VkMemoryBarrier*)DE_NULL,
				0, (const VkBufferMemoryBarrier*)DE_NULL,
				1, &barrier);

		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
	}

	// Perform draw
	{
		std::vector<Vec4>				vertices;
		std::vector<VulkanShader>		shaders;

		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(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragCoordMsaaVert")));
		shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragCoordMsaaFrag")));

		FrameBufferState			frameBufferState(m_renderSize.x(), m_renderSize.y());
		PipelineState				pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
		DrawCallData				drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
		VulkanProgram				vulkanProgram(shaders);

		frameBufferState.numSamples				= m_sampleCount;
		pipelineState.sampleShadingEnable		= true;
		vulkanProgram.descriptorSetLayout	= *descriptorSetLayout;
		vulkanProgram.descriptorSet			= *descriptorSet;

		VulkanDrawContext			vulkanDrawContext(m_context, frameBufferState);
		vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
		vulkanDrawContext.draw();

		log << TestLog::Image(	"result",
								"result",
								tcu::ConstPixelBufferAccess(tcu::TextureFormat(
										vulkanDrawContext.getColorPixels().getFormat()),
										vulkanDrawContext.getColorPixels().getWidth(),
										vulkanDrawContext.getColorPixels().getHeight(),
										1,
										vulkanDrawContext.getColorPixels().getDataPtr()));
	}

	// Transfer location image to buffer
	{
		beginCommandBuffer(vk, *transferCmdBuffer);
		copyImageToBuffer(vk, *transferCmdBuffer, *outputImage, *sampleLocationBuffer, tcu::IVec2(m_renderSize.x() * m_sampleCount, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
		endCommandBuffer(vk, *transferCmdBuffer);

		submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());

		invalidateAlloc(vk, device, *sampleLocationBufferAllocation);
	}

	// Validate result
	{
		bool status;

		ConstPixelBufferAccess sampleLocationPixelBuffer(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_sampleCount * m_renderSize.x(),
				m_renderSize.y(), 1u, sampleLocationBufferAllocation->getHostPtr());

		status = validateSampleLocations(sampleLocationPixelBuffer);
		if (status)
			return TestStatus::pass("FragCoordMsaa passed");
		else
			return TestStatus::fail("FragCoordMsaa failed");
	}
}

static bool pixelOffsetCompare (const Vec2& a, const Vec2& b)
{
	return a.x() < b.x();
}

bool BuiltinFragCoordMsaaCaseInstance::validateSampleLocations (const ConstPixelBufferAccess& sampleLocationBuffer) const
{
	const InstanceInterface&	vki					= m_context.getInstanceInterface();
	TestLog&					log					= m_context.getTestContext().getLog();
	const VkPhysicalDevice		physicalDevice		= m_context.getPhysicalDevice();
	deUint32					logSampleCount		= deLog2Floor32(m_sampleCount);
	VkPhysicalDeviceProperties	physicalDeviceProperties;

	static const Vec2 sampleCount1Bit[] =
	{
		Vec2(0.5f, 0.5f)
	};

	static const Vec2 sampleCount2Bit[] =
	{
		Vec2(0.25f, 0.25f), Vec2(0.75f, 0.75f)
	};

	static const Vec2 sampleCount4Bit[] =
	{
		Vec2(0.375f, 0.125f), Vec2(0.875f, 0.375f), Vec2(0.125f, 0.625f), Vec2(0.625f, 0.875f)
	};

	static const Vec2 sampleCount8Bit[] =
	{
		Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f,0.5625f), Vec2(0.3125f, 0.1875f),
		Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f), Vec2(0.6875f,0.9375f), Vec2(0.9375f, 0.0625f)
	};

	static const Vec2 sampleCount16Bit[] =
	{
		Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f,0.6250f), Vec2(0.7500f, 0.4375f),
		Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f,0.6875f), Vec2(0.6875f, 0.1875f),
		Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f,0.1250f), Vec2(0.1250f, 0.7500f),
		Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f,0.9375f), Vec2(0.0625f, 0.0000f)
	};

	static const Vec2* standardSampleLocationTable[] =
	{
		sampleCount1Bit,
		sampleCount2Bit,
		sampleCount4Bit,
		sampleCount8Bit,
		sampleCount16Bit
	};

	vki.getPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);

	for (deInt32 rowNdx = 0; rowNdx < (deInt32)m_renderSize.y(); rowNdx++)
	{
		for (deInt32 colNdx = 0; colNdx < (deInt32)m_renderSize.x(); colNdx++)
		{
			std::vector<Vec2> locations;

			for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
			{
				const UVec2 pixelAddress	= UVec2(sampleNdx + m_sampleCount * colNdx, rowNdx);
				const Vec4  pixelData		= sampleLocationBuffer.getPixel(pixelAddress.x(), pixelAddress.y());

				locations.push_back(Vec2(pixelData.x(), pixelData.y()));
			}

			std::sort(locations.begin(), locations.end(), pixelOffsetCompare);
			for (std::vector<Vec2>::const_iterator sampleIt = locations.begin(); sampleIt != locations.end(); sampleIt++)
			{
				IVec2	sampleFloor(deFloorFloatToInt32((*sampleIt).x()), deFloorFloatToInt32((*sampleIt).y()));
				IVec2	sampleCeil(deCeilFloatToInt32((*sampleIt).x()), deCeilFloatToInt32((*sampleIt).y()));

				if ( (sampleFloor.x() < colNdx) || (sampleCeil.x() > colNdx + 1) || (sampleFloor.y() < rowNdx) || (sampleCeil.y() > rowNdx + 1) )
				{
					log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): " << *sampleIt << TestLog::EndMessage;
					return false;
				}
			}

			std::vector<Vec2>::iterator last = std::unique(locations.begin(), locations.end());
			if (last != locations.end())
			{
				log << TestLog::Message << "Fail: Sample locations contains non-unique entry" << TestLog::EndMessage;
				return false;
			}

			// Check standard sample locations
			if (logSampleCount < DE_LENGTH_OF_ARRAY(standardSampleLocationTable))
			{
				if (physicalDeviceProperties.limits.standardSampleLocations)
				{
					for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)m_sampleCount; sampleNdx++)
					{
						if (!de::contains(locations.begin(), locations.end(), standardSampleLocationTable[logSampleCount][sampleNdx] + Vec2(float(colNdx), float(rowNdx))))
						{
							log << TestLog::Message << "Didn't match sample locations " << standardSampleLocationTable[logSampleCount][sampleNdx] << TestLog::EndMessage;
							return false;
						}
					}
				}
			}
		}
	}

	return true;
}

class BuiltinFragCoordMsaaTestCase : public TestCase
{
public:
					BuiltinFragCoordMsaaTestCase	(TestContext& testCtx, const char* name, const char* description, VkSampleCountFlagBits sampleCount);
	virtual			~BuiltinFragCoordMsaaTestCase	(void);
	void			initPrograms					(SourceCollections& sourceCollections) const;
	TestInstance*	createInstance					(Context& context) const;
private:
	const VkSampleCountFlagBits			m_sampleCount;
};

BuiltinFragCoordMsaaTestCase::BuiltinFragCoordMsaaTestCase (TestContext& testCtx, const char* name, const char* description, VkSampleCountFlagBits sampleCount)
	: TestCase			(testCtx, name, description)
	, m_sampleCount		(sampleCount)
{
}

BuiltinFragCoordMsaaTestCase::~BuiltinFragCoordMsaaTestCase (void)
{
}

void BuiltinFragCoordMsaaTestCase::initPrograms (SourceCollections& programCollection) const
{
	{
		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("FragCoordMsaaVert") << glu::VertexSource(vertexSource.str());
	}

	{
		std::ostringstream fragmentSource;
		fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) out mediump vec4 color;\n"
			<< "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
			<< "void main()\n"
			<< "{\n"
			<< "	const int sampleNdx = int(gl_SampleID);\n"
			<< "	ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_sampleCount << ", int(gl_FragCoord.y));\n"
			<< "	imageStore(storageImage, imageCoord, vec4(gl_FragCoord.xy,vec2(0)));\n"
			<< "	color = vec4(1.0, 0.0, 0.0, 1.0);\n"
			<< "}\n";
		programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(fragmentSource.str());
	}
}

TestInstance* BuiltinFragCoordMsaaTestCase::createInstance (Context& context) const
{
	return new BuiltinFragCoordMsaaCaseInstance(context, m_sampleCount);
}

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"
				<< "	gl_PointSize = 1.0;\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"
				<< "	gl_PointSize = 1.0;\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:
					BuiltinGlFragCoordXYZCaseInstance	(Context& context);

	TestStatus		iterate								(void);
	virtual void	setupDefaultInputs					(void);
};

BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
	: ShaderRenderCaseInstance	(context)
{
	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
}

TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate (void)
{
	const UVec2		viewportSize	= getViewportSize();
	const int		width			= viewportSize.x();
	const int		height			= viewportSize.y();
	const tcu::Vec3	scale			(1.0f / float(width), 1.0f / float(height), 1.0f);
	const float		precision		= 0.00001f;
	const deUint16	indices[6]		=
	{
		2, 1, 3,
		0, 1, 2,
	};

	setup();
	addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);

	render(4, 2, indices);

	// Reference image
	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			const float	xf			= (float(x) + .5f) / float(width);
			const float	yf			= (float(height - y - 1) + .5f) / float(height);
			const float	z			= (xf + yf) / 2.0f;
			const Vec3	fragCoord	(float(x) + .5f, float(y) + .5f, z);
			const Vec3	scaledFC	= fragCoord*scale;
			const Vec4	color		(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);

			if (de::abs(color.x() - resultColor.x()) > precision ||
				de::abs(color.y() - resultColor.y()) > precision ||
				de::abs(color.z() - resultColor.z()) > precision)
			return TestStatus::fail("Image mismatch");
		}
	}

	return TestStatus::pass("Result image matches reference");
}

void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs (void)
{
	const float		vertices[]		=
	{
		-1.0f,  1.0f,  0.0f, 1.0f,
		-1.0f, -1.0f,  0.5f, 1.0f,
		 1.0f,  1.0f,  0.5f, 1.0f,
		 1.0f, -1.0f,  1.0f, 1.0f,
	};

	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
}

class BuiltinGlFragCoordXYZCase : public TestCase
{
public:
								BuiltinGlFragCoordXYZCase	(TestContext& testCtx, const string& name, const string& description);
	virtual						~BuiltinGlFragCoordXYZCase	(void);

	void						initPrograms				(SourceCollections& dst) const;
	TestInstance*				createInstance				(Context& context) const;

private:
								BuiltinGlFragCoordXYZCase	(const BuiltinGlFragCoordXYZCase&);	// not allowed!
	BuiltinGlFragCoordXYZCase&	operator=					(const BuiltinGlFragCoordXYZCase&);	// not allowed!
};

BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name, const string& description)
	: TestCase(testCtx, name, description)
{
}

BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
{
}

void BuiltinGlFragCoordXYZCase::initPrograms (SourceCollections& dst) const
{
	dst.glslSources.add("vert") << glu::VertexSource(
		"#version 310 es\n"
		"layout(location = 0) in highp vec4 a_position;\n"
		"void main (void)\n"
		"{\n"
		"       gl_Position = a_position;\n"
		"}\n");

	dst.glslSources.add("frag") << glu::FragmentSource(
		"#version 310 es\n"
		"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
		"layout(location = 0) out highp vec4 o_color;\n"
		"void main (void)\n"
		"{\n"
		"       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
		"}\n");
}

TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
{
	return new BuiltinGlFragCoordXYZCaseInstance(context);
}

inline float projectedTriInterpolate (const Vec3& s, const Vec3& w, float nx, float ny)
{
	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
}

class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
{
public:
					BuiltinGlFragCoordWCaseInstance	(Context& context);

	TestStatus		iterate							(void);
	virtual void	setupDefaultInputs				(void);

private:

	const Vec4		m_w;

};

BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
	: ShaderRenderCaseInstance	(context)
	, m_w						(1.7f, 2.0f, 1.2f, 1.0f)
{
	m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
}

TestStatus BuiltinGlFragCoordWCaseInstance::iterate (void)
{
	const UVec2		viewportSize	= getViewportSize();
	const int		width			= viewportSize.x();
	const int		height			= viewportSize.y();
	const float		precision		= 0.00001f;
	const deUint16	indices[6]		=
	{
		2, 1, 3,
		0, 1, 2,
	};

	setup();
	render(4, 2, indices);

	// Reference image
	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			const float	xf			= (float(x) + .5f) / float(width);
			const float	yf			= (float(height - y - 1) +.5f) / float(height);
			const float	oow			= ((xf + yf) < 1.0f)
										? projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf)
										: projectedTriInterpolate(Vec3(m_w[3], m_w[2], m_w[1]), Vec3(m_w[3], m_w[2], m_w[1]), 1.0f - xf, 1.0f - yf);
			const Vec4	color		(0.0f, oow - 1.0f, 0.0f, 1.0f);
			const Vec4	resultColor	= getResultImage().getAccess().getPixel(x, y);

			if (de::abs(color.x() - resultColor.x()) > precision ||
				de::abs(color.y() - resultColor.y()) > precision ||
				de::abs(color.z() - resultColor.z()) > precision)
			return TestStatus::fail("Image mismatch");
		}
	}

	return TestStatus::pass("Result image matches reference");
}

void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs (void)
{
	const float vertices[] =
	{
		-m_w[0],  m_w[0], 0.0f, m_w[0],
		-m_w[1], -m_w[1], 0.0f, m_w[1],
		 m_w[2],  m_w[2], 0.0f, m_w[2],
		 m_w[3], -m_w[3], 0.0f, m_w[3]
	};

	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
}

class BuiltinGlFragCoordWCase : public TestCase
{
public:
								BuiltinGlFragCoordWCase		(TestContext& testCtx, const string& name, const string& description);
	virtual						~BuiltinGlFragCoordWCase	(void);

	void						initPrograms				(SourceCollections& dst) const;
	TestInstance*				createInstance				(Context& context) const;

private:
								BuiltinGlFragCoordWCase		(const BuiltinGlFragCoordWCase&);	// not allowed!
	BuiltinGlFragCoordWCase&	operator=					(const BuiltinGlFragCoordWCase&);	// not allowed!
};

BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name, const string& description)
	: TestCase(testCtx, name, description)
{
}

BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
{
}

void BuiltinGlFragCoordWCase::initPrograms (SourceCollections& dst) const
{
	dst.glslSources.add("vert") << glu::VertexSource(
		"#version 310 es\n"
		"layout(location = 0) in highp vec4 a_position;\n"
		"void main (void)\n"
		"{\n"
		"       gl_Position = a_position;\n"
		"}\n");

	dst.glslSources.add("frag") << glu::FragmentSource(
		"#version 310 es\n"
		"layout(location = 0) out highp vec4 o_color;\n"
		"void main (void)\n"
		"{\n"
		"       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
		"}\n");
}

TestInstance* BuiltinGlFragCoordWCase::createInstance (Context& context) const
{
	return new BuiltinGlFragCoordWCaseInstance(context);
}

enum
{
	POINTCOORD_VARIANT_DEFAULT,
	POINTCOORD_VARIANT_UNIFORM_VERTEX,
	POINTCOORD_VARIANT_UNIFORM_FRAGMENT
};


class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
{
public:
					BuiltinGlPointCoordCaseInstance	(Context& context, int testVariant);

	TestStatus		iterate								(void);
	virtual void	setupDefaultInputs					(void);
private:
	int				variant;
};

BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context, int testVariant)
	: ShaderRenderCaseInstance	(context),
	  variant(testVariant)
{
}

TestStatus BuiltinGlPointCoordCaseInstance::iterate (void)
{
	const UVec2				viewportSize	= getViewportSize();
	const int				width			= viewportSize.x();
	const int				height			= viewportSize.y();
	const float				threshold		= 0.02f;
	const int				numPoints		= 16;
	vector<Vec3>			coords			(numPoints);
	de::Random				rnd				(0x145fa);
	Surface					resImage		(width, height);
	Surface					refImage		(width, height);
	bool					compareOk		= false;
	const tcu::Vec3			scale(1.0f / float(width), 1.0f / float(height), 1.0f);

	// Compute coordinates.
	{
		const VkPhysicalDeviceLimits&	limits					= m_context.getDeviceProperties().limits;
		const float						minPointSize			= limits.pointSizeRange[0];
		const float						maxPointSize			= limits.pointSizeRange[1];
		const int						pointSizeDeltaMultiples	= de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));

		TCU_CHECK(minPointSize <= maxPointSize);

		for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
		{
			coord->x() = rnd.getFloat(-0.9f, 0.9f);
			coord->y() = rnd.getFloat(-0.9f, 0.9f);
			coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) * limits.pointSizeGranularity);
		}
	}

	setup();

	if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX || variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
		addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);

	addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
	render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
	copy(resImage.getAccess(), getResultImage().getAccess());

	// Draw reference
	clear(refImage.getAccess(), m_clearColor);

	for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
	{
		float x = pointIter->x();
		float y = pointIter->y();
		if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX)
		{
			x *= scale.m_data[0];
			y *= scale.m_data[1];
		}
		const float	centerX	= float(width) *(x*0.5f + 0.5f);
		const float	centerY	= float(height)*(y*0.5f + 0.5f);
		const float	size	= pointIter->z();
		const int	x0		= deRoundFloatToInt32(centerX - size*0.5f);
		const int	y0		= deRoundFloatToInt32(centerY - size*0.5f);
		const int	x1		= deRoundFloatToInt32(centerX + size*0.5f);
		const int	y1		= deRoundFloatToInt32(centerY + size*0.5f);
		const int	w		= x1-x0;
		const int	h		= y1-y0;

		for (int yo = 0; yo < h; yo++)
		{
			for (int xo = 0; xo < w; xo++)
			{
				const int		dx		= x0+xo;
				const int		dy		= y0+yo;
				const float		fragX	= float(dx) + 0.5f;
				const float		fragY	= float(dy) + 0.5f;
				const float		s		= 0.5f + (fragX - centerX) / size;
				const float		t		= 0.5f + (fragY - centerY) / size;
				Vec4			color	(s, t, 0.0f, 1.0f);

				if (variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
				{
					color.m_data[0] *= scale.m_data[0];
					color.m_data[1] *= scale.m_data[1];
					color.m_data[2] *= scale.m_data[2];
				}

				if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
					refImage.setPixel(dx, dy, RGBA(color));
			}
		}
	}

	compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);

	if (compareOk)
		return TestStatus::pass("Result image matches reference");
	else
		return TestStatus::fail("Image mismatch");
}

void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
{
}

class BuiltinGlPointCoordCase : public TestCase
{
public:
								BuiltinGlPointCoordCase	(TestContext& testCtx, const string& name, const string& description, int testVariant);
	virtual						~BuiltinGlPointCoordCase	(void);

	void						initPrograms				(SourceCollections& dst) const;
	TestInstance*				createInstance				(Context& context) const;

private:
	int							variant;
								BuiltinGlPointCoordCase	(const BuiltinGlPointCoordCase&);	// not allowed!
	BuiltinGlPointCoordCase&	operator=					(const BuiltinGlPointCoordCase&);	// not allowed!
};

BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description, int testVariant)
	: TestCase(testCtx, name, description),
	  variant(testVariant)
{
}

BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
{
}

void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
{
	switch (variant)
	{
	case POINTCOORD_VARIANT_UNIFORM_FRAGMENT:
		dst.glslSources.add("vert") << glu::VertexSource(
			"#version 310 es\n"
			"layout(location = 0) in highp vec3 a_position;\n"
			"void main (void)\n"
			"{\n"
			"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
			"    gl_PointSize = a_position.z;\n"
			"}\n");

		dst.glslSources.add("frag") << glu::FragmentSource(
			"#version 310 es\n"
			"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
			"layout(location = 0) out lowp vec4 o_color;\n"
			"void main (void)\n"
			"{\n"
			"    o_color = vec4(gl_PointCoord, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
			"}\n");
		break;
	case POINTCOORD_VARIANT_UNIFORM_VERTEX:
		dst.glslSources.add("vert") << glu::VertexSource(
			"#version 310 es\n"
			"layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
			"layout(location = 0) in highp vec3 a_position;\n"
			"void main (void)\n"
			"{\n"
			"    gl_Position = vec4(a_position.xy, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
			"    gl_PointSize = a_position.z;\n"
			"}\n");

		dst.glslSources.add("frag") << glu::FragmentSource(
			"#version 310 es\n"
			"layout(location = 0) out lowp vec4 o_color;\n"
			"void main (void)\n"
			"{\n"
			"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
			"}\n");
		break;
	default: // POINTCOORD_VARIANT_DEFAULT
		dst.glslSources.add("vert") << glu::VertexSource(
			"#version 310 es\n"
			"layout(location = 0) in highp vec3 a_position;\n"
			"void main (void)\n"
			"{\n"
			"    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
			"    gl_PointSize = a_position.z;\n"
			"}\n");

		dst.glslSources.add("frag") << glu::FragmentSource(
			"#version 310 es\n"
			"layout(location = 0) out lowp vec4 o_color;\n"
			"void main (void)\n"
			"{\n"
			"    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
			"}\n");
	}
}

TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
{
	return new BuiltinGlPointCoordCaseInstance(context, variant);
}

enum ShaderInputTypeBits
{
	SHADER_INPUT_BUILTIN_BIT	= 0x01,
	SHADER_INPUT_VARYING_BIT	= 0x02,
	SHADER_INPUT_CONSTANT_BIT	= 0x04
};

typedef deUint16 ShaderInputTypes;

string shaderInputTypeToString (ShaderInputTypes type)
{
	string typeString = "input";

	if (type == 0)
		return "input_none";

	if (type & SHADER_INPUT_BUILTIN_BIT)
		typeString += "_builtin";

	if (type & SHADER_INPUT_VARYING_BIT)
		typeString += "_varying";

	if (type & SHADER_INPUT_CONSTANT_BIT)
		typeString += "_constant";

	return typeString;
}

class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
{
public:
							BuiltinInputVariationsCaseInstance	(Context& context, const ShaderInputTypes shaderInputTypes);

	TestStatus				iterate								(void);
	virtual void			setupDefaultInputs					(void);
	virtual void			updatePushConstants					(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);

private:
	const ShaderInputTypes	m_shaderInputTypes;
	const Vec4				m_constantColor;
};

BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
	: ShaderRenderCaseInstance	(context)
	, m_shaderInputTypes		(shaderInputTypes)
	, m_constantColor			(0.1f, 0.05f, 0.2f, 0.0f)
{
}

TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
{
	const UVec2					viewportSize	= getViewportSize();
	const int					width			= viewportSize.x();
	const int					height			= viewportSize.y();
	const tcu::RGBA				threshold		(2, 2, 2, 2);
	Surface						resImage		(width, height);
	Surface						refImage		(width, height);
	bool						compareOk		= false;
	const VkPushConstantRange	pcRanges		=
	{
		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
		0u,								// deUint32				offset;
		sizeof(Vec4)					// deUint32				size;
	};
	const deUint16				indices[12]		=
	{
		0, 4, 1,
		0, 5, 4,
		1, 2, 3,
		1, 3, 4
	};

	setup();

	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
		setPushConstantRanges(1, &pcRanges);

	render(6, 4, indices);
	copy(resImage.getAccess(), getResultImage().getAccess());

	// Reference image
	for (int y = 0; y < refImage.getHeight(); y++)
	{
		for (int x = 0; x < refImage.getWidth(); x++)
		{
			Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);

			if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
				!(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
			{
				if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
				{
					const float xf = (float(x)+.5f) / float(refImage.getWidth());
					color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
				}
				else
					color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
			}

			if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
				color += m_constantColor;

			refImage.setPixel(x, y, RGBA(color));
		}
	}

	compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);

	if (compareOk)
		return TestStatus::pass("Result image matches reference");
	else
		return TestStatus::fail("Image mismatch");
}

void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
{
	const float vertices[] =
	{
		-1.0f, -1.0f, 0.0f, 1.0f,
		 0.0f, -1.0f, 0.0f, 1.0f,
		 1.0f, -1.0f, 0.0f, 1.0f,
		 1.0f,  1.0f, 0.0f, 1.0f,
		 0.0f,  1.0f, 0.0f, 1.0f,
		-1.0f,  1.0f, 0.0f, 1.0f
	};

	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);

	if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
	{
		const float colors[] =
		{
			 0.6f,  0.0f, 0.0f, 1.0f,
			 0.3f,  0.3f, 0.0f, 1.0f,
			 0.0f,  0.6f, 0.0f, 1.0f,
			 0.0f,  0.6f, 0.0f, 1.0f,
			 0.3f,  0.3f, 0.0f, 1.0f,
			 0.6f,  0.0f, 0.0f, 1.0f
		};
		addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
	}
}

void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
{
	if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
	{
		const DeviceInterface& vk = m_context.getDeviceInterface();
		vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
	}
}

class BuiltinInputVariationsCase : public TestCase
{
public:
								BuiltinInputVariationsCase	(TestContext& testCtx, const string& name, const string& description, const ShaderInputTypes shaderInputTypes);
	virtual						~BuiltinInputVariationsCase	(void);

	void						initPrograms				(SourceCollections& dst) const;
	TestInstance*				createInstance				(Context& context) const;

private:
								BuiltinInputVariationsCase	(const BuiltinInputVariationsCase&);	// not allowed!
	BuiltinInputVariationsCase&	operator=					(const BuiltinInputVariationsCase&);	// not allowed!
	const ShaderInputTypes		m_shaderInputTypes;
};

BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, const string& description, ShaderInputTypes shaderInputTypes)
	: TestCase				(testCtx, name, description)
	, m_shaderInputTypes	(shaderInputTypes)
{
}

BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
{
}

void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
{
	map<string, string>			vertexParams;
	map<string, string>			fragmentParams;
	const tcu::StringTemplate	vertexCodeTemplate		(
		"#version 450\n"
		"layout(location = 0) in highp vec4 a_position;\n"
		"out gl_PerVertex {\n"
		"	vec4 gl_Position;\n"
		"};\n"
		"${VARYING_DECL}"
		"void main (void)\n"
		"{\n"
		"    gl_Position = a_position;\n"
		"    ${VARYING_USAGE}"
		"}\n");

	const tcu::StringTemplate	fragmentCodeTemplate	(
		"#version 450\n"
		"${VARYING_DECL}"
		"${CONSTANT_DECL}"
		"layout(location = 0) out highp vec4 o_color;\n"
		"void main (void)\n"
		"{\n"
		"    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
		"    ${BUILTIN_USAGE}"
		"    ${VARYING_USAGE}"
		"    ${CONSTANT_USAGE}"
		"}\n");

	vertexParams["VARYING_DECL"]		=
		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 1) in highp vec4 a_color;\n"
														  "layout(location = 0) out highp vec4 v_color;\n"
														: "";

	vertexParams["VARYING_USAGE"]		=
		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "v_color = a_color;\n"
														: "";

	fragmentParams["VARYING_DECL"]		=
		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "layout(location = 0) in highp vec4 a_color;\n"
														: "";

	fragmentParams["CONSTANT_DECL"]		=
		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "layout(push_constant) uniform PCBlock {\n"
														  "  vec4 color;\n"
														  "} pc;\n"
														: "";

	fragmentParams["BUILTIN_USAGE"]		=
		m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT	? "if (gl_FrontFacing)\n"
														: "";

	fragmentParams["VARYING_USAGE"]		=
		m_shaderInputTypes & SHADER_INPUT_VARYING_BIT	? "o_color += vec4(a_color.xyz, 0.0);\n"
														: "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";


	fragmentParams["CONSTANT_USAGE"]	=
		m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT	? "o_color += pc.color;\n"
														: "";

	dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
	dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
}

TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
{
	return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
}

} // anonymous

TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
{
	de::MovePtr<TestCaseGroup> builtinGroup			(new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
	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."));
	de::MovePtr<TestCaseGroup> fragCoordMsaaGroup	(new TestCaseGroup(testCtx, "fragcoord_msaa", "Test interation between gl_FragCoord and msaa"));

	simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
	simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", "PointCoord test", POINTCOORD_VARIANT_DEFAULT));
	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_frag", "PointCoord test with fragment uniform", POINTCOORD_VARIANT_UNIFORM_FRAGMENT));
	simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_vert", "PointCoord test with vertex uniform", POINTCOORD_VARIANT_UNIFORM_VERTEX));

	// FragCoord_msaa
	{
		static const struct FragCoordMsaaCaseList
		{
			const char*				name;
			const char*				description;
			VkSampleCountFlagBits	sampleCount;
		} fragCoordMsaaCaseList[] =
		{
			{ "1_bit",	"Test FragCoord locations with 2 samples", VK_SAMPLE_COUNT_1_BIT },
			{ "2_bit",	"Test FragCoord locations with 2 samples", VK_SAMPLE_COUNT_2_BIT },
			{ "4_bit",	"Test FragCoord locations with 4 samples", VK_SAMPLE_COUNT_4_BIT },
			{ "8_bit",	"Test FragCoord locations with 8 samples", VK_SAMPLE_COUNT_8_BIT },
			{ "16_bit",	"Test FragCoord locations with 16 samples", VK_SAMPLE_COUNT_16_BIT },
			{ "32_bit", "Test FragCoord locations with 32 samples", VK_SAMPLE_COUNT_32_BIT },
			{ "64_bit", "Test FragCoord locaitons with 64 samples", VK_SAMPLE_COUNT_64_BIT }
		};

		for (deUint32 caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
			fragCoordMsaaGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, fragCoordMsaaCaseList[caseNdx].name, fragCoordMsaaCaseList[caseNdx].description, fragCoordMsaaCaseList[caseNdx].sampleCount));
	}

	// gl_FrontFacing tests
	{
		static const struct PrimitiveTable
		{
			const char*				name;
			const char*				desc;
			VkPrimitiveTopology		primitive;
		} frontfacingCases[] =
		{
			{ "point_list",		"Test that points are frontfacing",							VK_PRIMITIVE_TOPOLOGY_POINT_LIST },
			{ "line_list",		"Test that lines are frontfacing",							VK_PRIMITIVE_TOPOLOGY_LINE_LIST },
			{ "triangle_list",	"Test that triangles can be frontfacing or backfacing",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST },
			{ "triangle_strip",	"Test that traiangle strips can be front or back facing",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP },
			{ "triangle_fan",	"Test that triangle fans can be front or back facing",		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
		};

		for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(frontfacingCases); ndx++)
			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(fragCoordMsaaGroup.release());
	builtinGroup->addChild(simpleGroup.release());

	for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
	{
		inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), "Input variation test", shaderType));
	}

	builtinGroup->addChild(inputVariationsGroup.release());
	return builtinGroup.release();
}

} // sr
} // vkt
