/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2020 The Khronos Group Inc.
 * Copyright (c) 2020 Valve Corporation
 *
 * 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 VK_AMD_shader_explicit_vertex_parameter tests
 *//*--------------------------------------------------------------------*/

#include "vktDrawExplicitVertexParameterTests.hpp"

#include "vktDrawBaseClass.hpp"
#include "vkQueryUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vktTestGroupUtil.hpp"

#include "vkObjUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkTypeUtil.hpp"

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

#include "tcuTestCase.hpp"
#include "tcuRGBA.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuStringTemplate.hpp"

#include "rrRenderer.hpp"

#include <string>
#include <sstream>

namespace vkt
{
namespace Draw
{
namespace
{
using namespace vk;
using namespace std;

enum Interpolation
{
	SMOOTH = 0,
	NOPERSPECTIVE = 1,
};

enum AuxiliaryQualifier
{
	AUX_NONE = 0,
	AUX_CENTROID = 1,
	AUX_SAMPLE = 2,
};


enum
{
	WIDTH = 16,
	HEIGHT = 16
};

struct PositionValueVertex {
	PositionValueVertex(tcu::Vec4 pos, float val)
	: position(pos)
	, value(val)
	{}
public:
	tcu::Vec4	position;
	float		value;
};

struct DrawParams
{
	Interpolation				interpolation;
	vk::VkSampleCountFlagBits	samples;
	AuxiliaryQualifier			auxiliaryStorage;
};

const char* interpolationToString (Interpolation interpolation)
{
	switch (interpolation)
	{
		case SMOOTH:
			return "smooth";
		case NOPERSPECTIVE:
			return "noperspective";
		default:
			DE_FATAL("Invalid interpolation enum");
	}

	return "";
}

std::string barycentricVariableString (Interpolation interpolation, AuxiliaryQualifier aux)
{
	std::ostringstream name;
	name << "gl_BaryCoord";
	switch (interpolation)
	{
		case SMOOTH:
			name << "Smooth";
			break;
		case NOPERSPECTIVE:
			name << "NoPersp";
			break;
		default:
			DE_FATAL("Invalid interpolation enum");
	}

	switch (aux)
	{
		case AUX_CENTROID:
			name << "Centroid";
			break;
		case AUX_SAMPLE:
			name << "Sample";
			break;
		case AUX_NONE:
			name << "";
			break;
		default:
			DE_FATAL("Invalid auxiliary storage qualifier enum");
	}
	name << "AMD";
	return name.str();
}

const char* auxiliaryQualifierToString (AuxiliaryQualifier aux)
{
	switch (aux)
	{
		case AUX_CENTROID:
			return "centroid";
		case AUX_SAMPLE:
			return "sample";
		case AUX_NONE:
			return "";
		default:
			DE_FATAL("Invalid auxiliary storage qualifier enum");
	}

	return "";
}

std::string getTestName (DrawParams params)
{
	std::ostringstream	name;

	name << interpolationToString(params.interpolation) << "_";

	if (params.auxiliaryStorage != AUX_NONE)
		name << auxiliaryQualifierToString(params.auxiliaryStorage) << "_";

	name << "samples_" << de::toString(params.samples);

	return name.str();
}

class DrawTestInstance : public TestInstance
{
public:
						DrawTestInstance	(Context& context, const DrawParams& data);
						~DrawTestInstance	(void);
	tcu::TestStatus		iterate				(void);
private:
	DrawParams			m_data;
};

DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
	: vkt::TestInstance		(context)
	, m_data				(data)
{
}

DrawTestInstance::~DrawTestInstance (void)
{
}

class DrawTestCase : public TestCase
{
	public:
								DrawTestCase		(tcu::TestContext& context, const char* name, const char* desc, const DrawParams data);
								~DrawTestCase		(void);
	virtual	void				initPrograms		(SourceCollections& programCollection) const;
	virtual TestInstance*		createInstance		(Context& context) const;
	virtual void				checkSupport	(Context& context) const;

private:
	DrawParams					m_data;
};

DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data)
	: vkt::TestCase	(context, name, desc)
	, m_data		(data)
{
}

DrawTestCase::~DrawTestCase	(void)
{
}

void DrawTestCase::checkSupport(Context &context) const
{
	context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");

	if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
		TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
}

void DrawTestCase::initPrograms (SourceCollections& programCollection) const
{
	const deUint32				numValues	= WIDTH * HEIGHT * m_data.samples;

	const tcu::StringTemplate	vertShader	(string(
		"#version 450\n"
		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
		"\n"
		"layout(location = 0) in vec4 in_position;\n"
		"layout(location = 1) in float in_data;\n"
		"layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
		"layout(location = 1) ${auxqualifier} ${qualifier}        out float out_data_${qualifier};\n"
		"\n"
		"out gl_PerVertex {\n"
		"    vec4  gl_Position;\n"
		"    float gl_PointSize;\n"
		"};\n"
		"\n"
		"void main() {\n"
		"    gl_PointSize              = 1.0;\n"
		"    gl_Position               = in_position;\n"
		"    out_data_explicit         = in_data;\n"
		"    out_data_${qualifier}     = in_data;\n"
		"}\n"));

	const tcu::StringTemplate	fragShader	(string(
		"#version 450\n"
		"#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
		"\n"
		"layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
		"layout(location = 1) ${auxqualifier} ${qualifier}        in float in_data_${qualifier};\n"
		"layout(location = 0) out vec4 out_color;\n"
		"layout (binding = 0, std140) writeonly buffer Output {\n"
		"    vec4 values [${numValues}];\n"
		"} sb_out;\n"
		"\n"
		"void main()\n"
		"{\n"
		"    uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + gl_SampleID;\n"
		"    // Barycentric coodinates (I, J, K)\n"
		"    vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
		"\n"
		"    // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
		"    float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
		"    // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
		"    float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
		"    // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
		"    float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
		"    // Match data component with barycentric coordinate\n"
		"    vec3  data  = vec3(data1, data2, data0);\n"
		"\n"
		"    float res      = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
		"    float expected = in_data_${qualifier};\n"
		"\n"
		"    sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
		"\n"
		"    const float threshold = 0.0005f;\n"
		"    if (abs(res - expected) < threshold)\n"
		"        out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
		"    else\n"
		"        out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
		"}\n"));

	map<string, string> attributes;
	attributes["width"]			= de::toString(WIDTH);
	attributes["numValues"]		= de::toString(numValues * m_data.samples);
	attributes["qualifier"]		= interpolationToString(m_data.interpolation);
	attributes["auxqualifier"]	= auxiliaryQualifierToString(m_data.auxiliaryStorage);
	attributes["barycoord"]		= barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
	attributes["samples"]		= de::toString(m_data.samples);

	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
}

TestInstance* DrawTestCase::createInstance (Context& context) const
{
	return new DrawTestInstance(context, m_data);
}

tcu::TestStatus DrawTestInstance::iterate (void)
{
	de::SharedPtr<Image>			colorTargetImage;
	de::SharedPtr<Image>			multisampleTargetImage;
	tcu::TestLog					&log					= m_context.getTestContext().getLog();

	// Run two iterations with shaders that have different interpolation decorations. Images should still match.
	const DeviceInterface&			vk						= m_context.getDeviceInterface();
	const VkDevice					device					= m_context.getDevice();
	const CmdPoolCreateInfo			cmdPoolCreateInfo		(m_context.getUniversalQueueFamilyIndex());
	Move<VkCommandPool>				cmdPool					= createCommandPool(vk, device, &cmdPoolCreateInfo);
	Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const Unique<VkShaderModule>	vs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
	const Unique<VkShaderModule>	fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
	de::SharedPtr<Buffer>			vertexBuffer;
	de::SharedPtr<Buffer>			ssboBuffer;
	Move<VkRenderPass>				renderPass;
	Move<VkImageView>				colorTargetView;
	Move<VkImageView>				multisampleTargetView;
	Move<VkFramebuffer>				framebuffer;
	Move<VkPipeline>				pipeline;
	Move<VkPipelineLayout>			pipelineLayout;
	Move<VkDescriptorPool>			descriptorPool;
	Move<VkDescriptorSet>			descriptorSet;
	Move<VkDescriptorSetLayout>		descriptorSetLayout;

	vk::VkFormat					imageFormat				= VK_FORMAT_R8G8B8A8_UNORM;
	const deUint32					numValues				= WIDTH * HEIGHT * m_data.samples;
	const deBool					useMultisampling		= m_data.samples != VK_SAMPLE_COUNT_1_BIT;

	// Create color buffer images.
	{
		const VkExtent3D			targetImageExtent		= { WIDTH, HEIGHT, 1 };
		const ImageCreateInfo		targetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
															 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
		colorTargetImage									= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());

		if (useMultisampling)
		{
			const ImageCreateInfo		multisampleTargetImageCreateInfo	(VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples,
																			 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
			multisampleTargetImage											= Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
		}
	}

	// Create render pass and frame buffer.
	{
		const ImageViewCreateInfo		colorTargetViewInfo		(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
		colorTargetView	= createImageView(vk, device, &colorTargetViewInfo);

		RenderPassCreateInfo			renderPassCreateInfo;
		renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
																 VK_SAMPLE_COUNT_1_BIT,
																 VK_ATTACHMENT_LOAD_OP_LOAD,
																 VK_ATTACHMENT_STORE_OP_STORE,
																 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
																 VK_ATTACHMENT_STORE_OP_STORE,
																 VK_IMAGE_LAYOUT_UNDEFINED,
																 VK_IMAGE_LAYOUT_GENERAL));

		const VkAttachmentReference		colorAttachmentRef			= { 0u, VK_IMAGE_LAYOUT_GENERAL };
		const VkAttachmentReference		multisampleAttachmentRef	= { 1u, VK_IMAGE_LAYOUT_GENERAL };
		vector<VkImageView>				colorAttachments;
		colorAttachments.push_back(*colorTargetView);

		if (useMultisampling)
		{
			const ImageViewCreateInfo		multisamplingTargetViewInfo		(multisampleTargetImage->object(),
																			 vk::VK_IMAGE_VIEW_TYPE_2D,
																			 imageFormat);


			multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
			colorAttachments.push_back(*multisampleTargetView);

			renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
																	 m_data.samples,
																	 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
																	 vk::VK_ATTACHMENT_STORE_OP_STORE,
																	 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
																	 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
																	 vk::VK_IMAGE_LAYOUT_UNDEFINED,
																	 vk::VK_IMAGE_LAYOUT_GENERAL));
		}

		renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
														   0,
														   0,
														   DE_NULL,
														   1u,
														   useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
														   useMultisampling ? &colorAttachmentRef : DE_NULL,
														   AttachmentReference(),
														   0,
														   DE_NULL));

		renderPass			= createRenderPass(vk, device, &renderPassCreateInfo);

		const FramebufferCreateInfo		framebufferCreateInfo	(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
		framebuffer	= createFramebuffer(vk, device, &framebufferCreateInfo);
	}

	// Create vertex buffer.
	{
		const PositionValueVertex	vertices[]	=
		{
			PositionValueVertex(
				tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f),		// Coord
				float(1.0f)),							// Value

			PositionValueVertex(
				tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f),	// Coord
				float(0.0f)),							// Value
			PositionValueVertex(
				tcu::Vec4( 1.0f,  1.0f, 0.0f, 2.0f),	// Coord
				float(0.5f)),							// Value
			PositionValueVertex(
				tcu::Vec4( 1.0f, -1.0f, 1.0f, 0.5f),	// Coord
				float(1.0f)),							// Value
		};

		const VkDeviceSize			dataSize	= DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
		vertexBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
		deUint8*					ptr			= reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());

		deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
		flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
	}

	// Create SSBO buffer
	{
		const VkDeviceSize		dataSize	= sizeof(tcu::Vec4) * numValues;
		ssboBuffer							= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
		deUint8*				ptr			= reinterpret_cast<deUint8*>(ssboBuffer->getBoundMemory().getHostPtr());

		deMemset(ptr, 0, static_cast<size_t>(dataSize));
		flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(), ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
	}

	// Create Descriptor Set layout
	{
		descriptorSetLayout = DescriptorSetLayoutBuilder()
			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
			.build(vk, device);
	}

	// Create Descriptor Set
	{
		descriptorPool = DescriptorPoolBuilder()
			.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
			.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	    descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);

		const VkDescriptorBufferInfo	bufferInfo =
		{
			ssboBuffer->object(),		// VkBuffer		buffer;
			0u,							// VkDeviceSize	offset;
			VK_WHOLE_SIZE				// VkDeviceSize	range;
		};

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

	// Create pipeline
	{
		const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;

		VkViewport	viewport	= makeViewport(WIDTH, HEIGHT);
		VkRect2D	scissor		= makeRect2D(WIDTH, HEIGHT);

		const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX };

		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
		{
			{ 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
			{ 1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (deUint32)(sizeof(float)* 4) }
		};

		PipelineCreateInfo::VertexInputState vertexInputState	= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);

		pipelineLayout = makePipelineLayout	(vk, device, *descriptorSetLayout);

		PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
		pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
		pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));

		pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
	}

	// Queue draw and read results.
	{
		const VkQueue				queue				= m_context.getUniversalQueue();
		const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
		const tcu::Vec4				clearColor			= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
		const VkRect2D				renderArea			= makeRect2D(WIDTH, HEIGHT);
		const VkDeviceSize			vertexBufferOffset	= 0;
		const VkBuffer				buffer				= vertexBuffer->object();

		vector<VkClearValue>		clearColors;
		clearColors.push_back(makeClearValueColor(clearColor));

		if (useMultisampling)
			clearColors.push_back(makeClearValueColor(clearColor));

		beginCommandBuffer(vk, *cmdBuffer, 0u);
		const VkRenderPassBeginInfo renderPassBeginInfo =
		{
			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
			DE_NULL,									// const void*             pNext;
			*renderPass,								// VkRenderPass            renderPass;
			*framebuffer,								// VkFramebuffer           framebuffer;
			renderArea,									// VkRect2D                renderArea;
			(deUint32)clearColors.size(),				// deUint32                clearValueCount;
			clearColors.data(),							// const VkClearValue*     pClearValues;
		};

		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
		vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
		endRenderPass(vk, *cmdBuffer);
		endCommandBuffer(vk, *cmdBuffer);

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

	qpTestResult res = QP_TEST_RESULT_PASS;

	{
		const Allocation& resultAlloc = ssboBuffer->getBoundMemory();
		invalidateAlloc(vk, device, resultAlloc);

		const tcu::Vec4*	ptr		= reinterpret_cast<tcu::Vec4*>(resultAlloc.getHostPtr());
		for (deUint32 valueNdx = 0u; valueNdx < numValues; valueNdx++)
		{
			if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
			{
				log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got " << ptr[valueNdx].y()
					<< tcu::TestLog::EndMessage;
				res = QP_TEST_RESULT_FAIL;
			}
		}
	}

	return tcu::TestStatus(res, qpGetTestResultName(res));
}

void createTests (tcu::TestCaseGroup* testGroup)
{
	tcu::TestContext&	testCtx		= testGroup->getTestContext();

	const VkSampleCountFlagBits samples[] =
	{
		VK_SAMPLE_COUNT_1_BIT,
		VK_SAMPLE_COUNT_2_BIT,
		VK_SAMPLE_COUNT_4_BIT,
		VK_SAMPLE_COUNT_8_BIT,
		VK_SAMPLE_COUNT_16_BIT,
		VK_SAMPLE_COUNT_32_BIT,
		VK_SAMPLE_COUNT_64_BIT,
	};

	const Interpolation interTypes[] =
	{
		SMOOTH,
		NOPERSPECTIVE
	};

	const AuxiliaryQualifier auxQualifiers[] =
	{
		AUX_NONE,
		AUX_SAMPLE,
		AUX_CENTROID,
	};

	for (deUint32 sampleNdx	= 0;	sampleNdx	< DE_LENGTH_OF_ARRAY(samples);			sampleNdx++)
	for (deUint32 auxNdx	= 0;	auxNdx		< DE_LENGTH_OF_ARRAY(auxQualifiers);	auxNdx++)
    for (deUint32 interNdx	= 0;	interNdx	< DE_LENGTH_OF_ARRAY(interTypes);		interNdx++)
	{
		if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
			continue;

		const DrawParams params =
		{
			interTypes[interNdx],
			samples[sampleNdx],
			auxQualifiers[auxNdx],
		};
		testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), "", params));
	}
}

}	// anonymous

tcu::TestCaseGroup*	createExplicitVertexParameterTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "explicit_vertex_parameter", "Tests for VK_AMD_shader_explicit_vertex_parameter.", createTests);
}

}	// Draw
}	// vkt
