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