/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 *
 * 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 Simple Draw Tests
 *//*--------------------------------------------------------------------*/

#include "vktBasicDrawTests.hpp"

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

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

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

#include "rrRenderer.hpp"

#include <string>
#include <sstream>

namespace vkt
{
namespace Draw
{
namespace
{
static const deUint32 SEED			= 0xc2a39fu;
static const deUint32 INDEX_LIMIT	= 10000;
// To avoid too big and mostly empty structures
static const deUint32 OFFSET_LIMIT	= 1000;
// Number of primitives to draw
static const deUint32 PRIMITIVE_COUNT[] = {1, 3, 17, 45};

enum DrawCommandType
{
	DRAW_COMMAND_TYPE_DRAW,
	DRAW_COMMAND_TYPE_DRAW_INDEXED,
	DRAW_COMMAND_TYPE_DRAW_INDIRECT,
	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,

	DRAW_COMMAND_TYPE_DRAW_LAST
};

const char* getDrawCommandTypeName (DrawCommandType command)
{
	switch (command)
	{
		case DRAW_COMMAND_TYPE_DRAW:					return "draw";
		case DRAW_COMMAND_TYPE_DRAW_INDEXED:			return "draw_indexed";
		case DRAW_COMMAND_TYPE_DRAW_INDIRECT:			return "draw_indirect";
		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:	return "draw_indexed_indirect";
		default:					DE_ASSERT(false);
	}
	return "";
}

rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
{
	switch (primitiveTopology)
	{
		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:						return rr::PRIMITIVETYPE_POINTS;
		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						return rr::PRIMITIVETYPE_LINES;
		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:						return rr::PRIMITIVETYPE_LINE_STRIP;
		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					return rr::PRIMITIVETYPE_TRIANGLES;
		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:					return rr::PRIMITIVETYPE_TRIANGLE_FAN;
		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:					return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINES_ADJACENCY;
		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
		default:
			DE_ASSERT(false);
	}
	return rr::PRIMITIVETYPE_LAST;
}

struct DrawParamsBase
{
	std::vector<PositionColorVertex>	vertices;
	vk::VkPrimitiveTopology				topology;

	DrawParamsBase ()
	{}

	DrawParamsBase (const vk::VkPrimitiveTopology top)
		: topology	(top)
	{}
};

struct IndexedParamsBase
{
	std::vector<deUint32>	indexes;
	const vk::VkIndexType	indexType;

	IndexedParamsBase (const vk::VkIndexType indexT)
		: indexType	(indexT)
	{}
};

// Structs to store draw parameters
struct DrawParams : DrawParamsBase
{
	// vkCmdDraw parameters is like a single VkDrawIndirectCommand
	vk::VkDrawIndirectCommand	params;

	DrawParams (const vk::VkPrimitiveTopology top, const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
		: DrawParamsBase	(top)
	{
		params.vertexCount		= vertexC;
		params.instanceCount	= instanceC;
		params.firstVertex		= firstV;
		params.firstInstance	= firstI;
	}
};

struct DrawIndexedParams : DrawParamsBase, IndexedParamsBase
{
	// vkCmdDrawIndexed parameters is like a single VkDrawIndexedIndirectCommand
	vk::VkDrawIndexedIndirectCommand	params;

	DrawIndexedParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT, const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
		: DrawParamsBase	(top)
		, IndexedParamsBase	(indexT)
	{
		params.indexCount		= indexC;
		params.instanceCount	= instanceC;
		params.firstIndex		= firstIdx;
		params.vertexOffset		= vertexO;
		params.firstInstance	= firstIns;
	}
};

struct DrawIndirectParams : DrawParamsBase
{
	std::vector<vk::VkDrawIndirectCommand>	commands;

	DrawIndirectParams (const vk::VkPrimitiveTopology top)
		: DrawParamsBase	(top)
	{}

	void addCommand (const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
	{
		vk::VkDrawIndirectCommand	cmd;
		cmd.vertexCount				= vertexC;
		cmd.instanceCount			= instanceC;
		cmd.firstVertex				= firstV;
		cmd.firstInstance			= firstI;

		commands.push_back(cmd);
	}
};

struct DrawIndexedIndirectParams : DrawParamsBase, IndexedParamsBase
{
	std::vector<vk::VkDrawIndexedIndirectCommand>	commands;

	DrawIndexedIndirectParams (const vk::VkPrimitiveTopology top, const vk::VkIndexType indexT)
		: DrawParamsBase	(top)
		, IndexedParamsBase	(indexT)
	{}

	void addCommand (const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
	{
		vk::VkDrawIndexedIndirectCommand	cmd;
		cmd.indexCount						= indexC;
		cmd.instanceCount					= instanceC;
		cmd.firstIndex						= firstIdx;
		cmd.vertexOffset					= vertexO;
		cmd.firstInstance					= firstIns;

		commands.push_back(cmd);
	}
};

// Reference renderer shaders
class PassthruVertShader : public rr::VertexShader
{
public:
	PassthruVertShader (void)
	: rr::VertexShader (2, 1)
	{
		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
		m_inputs[1].type	= rr::GENERICVECTYPE_FLOAT;
		m_outputs[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);

			tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1],
														packets[packetNdx]->instanceNdx,
														packets[packetNdx]->vertexNdx);

			packets[packetNdx]->outputs[0] = color;
		}
	}
};

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

	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
	{
		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
		{
			rr::FragmentPacket& packet = packets[packetNdx];
			for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
			{
				tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
			}
		}
	}
};

inline bool imageCompare (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const vk::VkPrimitiveTopology topology)
{
	if (topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
	{
		return tcu::intThresholdPositionDeviationCompare(
			log, "Result", "Image comparison result", reference, result,
			tcu::UVec4(4u),					// color threshold
			tcu::IVec3(1, 1, 0),			// position deviation tolerance
			true,							// don't check the pixels at the boundary
			tcu::COMPARE_LOG_RESULT);
	}
	else
		return tcu::fuzzyCompare(log, "Result", "Image comparison result", reference, result, 0.053f, tcu::COMPARE_LOG_RESULT);
}

class DrawTestInstanceBase : public TestInstance
{
public:
									DrawTestInstanceBase	(Context& context);
	virtual							~DrawTestInstanceBase	(void) = 0;
	void							initialize				(const DrawParamsBase& data);
	void							initPipeline			(const vk::VkDevice device);
	void							beginRenderPass			(void);

	// Specialize this function for each type
	virtual tcu::TestStatus			iterate					(void) = 0;
protected:
	// Specialize this function for each type
	virtual void					generateDrawData		(void) = 0;
	void							generateRefImage		(const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;

	DrawParamsBase											m_data;
	const vk::DeviceInterface&								m_vk;
	vk::Move<vk::VkPipeline>								m_pipeline;
	vk::Move<vk::VkPipelineLayout>							m_pipelineLayout;
	vk::VkFormat											m_colorAttachmentFormat;
	de::SharedPtr<Image>									m_colorTargetImage;
	vk::Move<vk::VkImageView>								m_colorTargetView;
	vk::Move<vk::VkRenderPass>								m_renderPass;
	vk::Move<vk::VkFramebuffer>								m_framebuffer;
	PipelineCreateInfo::VertexInputState					m_vertexInputState;
	de::SharedPtr<Buffer>									m_vertexBuffer;
	vk::Move<vk::VkCommandPool>								m_cmdPool;
	vk::Move<vk::VkCommandBuffer>							m_cmdBuffer;

	enum
	{
		WIDTH = 256,
		HEIGHT = 256
	};
};

DrawTestInstanceBase::DrawTestInstanceBase (Context& context)
	: vkt::TestInstance			(context)
	, m_vk						(context.getDeviceInterface())
	, m_colorAttachmentFormat	(vk::VK_FORMAT_R8G8B8A8_UNORM)
{
}

DrawTestInstanceBase::~DrawTestInstanceBase (void)
{
}

void DrawTestInstanceBase::initialize (const DrawParamsBase& data)
{
	m_data	= data;

	const vk::VkDevice	device				= m_context.getDevice();
	const deUint32		queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();

	const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();

	if (features.geometryShader == VK_FALSE &&
		(m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
		 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ||
		 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY ||
		 m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
		)
	{
		TCU_THROW(NotSupportedError, "Geometry Not Supported");
	}

	const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
	m_pipelineLayout						= vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);

	const vk::VkExtent3D targetImageExtent	= { WIDTH, HEIGHT, 1 };
	const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
		vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);

	m_colorTargetImage						= Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());

	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
	m_colorTargetView						= vk::createImageView(m_vk, device, &colorTargetViewInfo);

	RenderPassCreateInfo renderPassCreateInfo;
	renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
															 vk::VK_SAMPLE_COUNT_1_BIT,
															 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
															 vk::VK_ATTACHMENT_STORE_OP_STORE,
															 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
															 vk::VK_ATTACHMENT_STORE_OP_STORE,
															 vk::VK_IMAGE_LAYOUT_GENERAL,
															 vk::VK_IMAGE_LAYOUT_GENERAL));

	const vk::VkAttachmentReference colorAttachmentReference =
	{
		0,
		vk::VK_IMAGE_LAYOUT_GENERAL
	};

	renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
													   0,
													   0,
													   DE_NULL,
													   1,
													   &colorAttachmentReference,
													   DE_NULL,
													   AttachmentReference(),
													   0,
													   DE_NULL));

	m_renderPass		= vk::createRenderPass(m_vk, device, &renderPassCreateInfo);

	std::vector<vk::VkImageView> colorAttachments(1);
	colorAttachments[0] = *m_colorTargetView;

	const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);

	m_framebuffer		= vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);

	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
	{
		0,
		(deUint32)sizeof(tcu::Vec4) * 2,
		vk::VK_VERTEX_INPUT_RATE_VERTEX,
	};

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

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

	const vk::VkDeviceSize dataSize = m_data.vertices.size() * sizeof(PositionColorVertex);
	m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize,
		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);

	deUint8* ptr = reinterpret_cast<deUint8*>(m_vertexBuffer->getBoundMemory().getHostPtr());
	deMemcpy(ptr, &(m_data.vertices[0]), static_cast<size_t>(dataSize));

	vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());

	const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
	m_cmdPool	= vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
	m_cmdBuffer	= vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);

	initPipeline(device);
}

void DrawTestInstanceBase::initPipeline (const vk::VkDevice device)
{
	const vk::Unique<vk::VkShaderModule>	vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0));
	const vk::Unique<vk::VkShaderModule>	fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0));

	const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;

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

	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
	pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
	pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_data.topology));
	pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
	pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
	pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
	pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
	pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());

	m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
}

void DrawTestInstanceBase::beginRenderPass (void)
{
	const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };

	beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);

	initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
								  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);

	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
		vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);

	const vk::VkMemoryBarrier memBarrier =
	{
		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
		DE_NULL,
		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
	};

	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
		vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);

	const vk::VkRect2D renderArea = vk::makeRect2D(WIDTH, HEIGHT);

	vk::beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
}

void DrawTestInstanceBase::generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
{
	const PassthruVertShader				vertShader;
	const PassthruFragShader				fragShader;
	const rr::Program						program			(&vertShader, &fragShader);
	const rr::MultisamplePixelBufferAccess	colorBuffer		= rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
	const rr::RenderTarget					renderTarget	(colorBuffer);
	const rr::RenderState					renderState		((rr::ViewportState(colorBuffer)));
	const rr::Renderer						renderer;

	const rr::VertexAttrib	vertexAttribs[] =
	{
		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])
	};

	renderer.draw(rr::DrawCommand(renderState,
								  renderTarget,
								  program,
								  DE_LENGTH_OF_ARRAY(vertexAttribs),
								  &vertexAttribs[0],
								  rr::PrimitiveList(mapVkPrimitiveTopology(m_data.topology), (deUint32)vertices.size(), 0)));
}

template<typename T>
class DrawTestInstance : public DrawTestInstanceBase
{
public:
							DrawTestInstance		(Context& context, const T& data);
	virtual					~DrawTestInstance		(void);
	virtual void			generateDrawData		(void);
	virtual tcu::TestStatus	iterate					(void);
private:
	T						m_data;
};

template<typename T>
DrawTestInstance<T>::DrawTestInstance (Context& context, const T& data)
	: DrawTestInstanceBase	(context)
	, m_data				(data)
{
	generateDrawData();
	initialize(m_data);
}

template<typename T>
DrawTestInstance<T>::~DrawTestInstance (void)
{
}

template<typename T>
void DrawTestInstance<T>::generateDrawData (void)
{
	DE_FATAL("Using the general case of this function is forbidden!");
}

template<typename T>
tcu::TestStatus DrawTestInstance<T>::iterate (void)
{
	DE_FATAL("Using the general case of this function is forbidden!");
	return tcu::TestStatus::fail("");
}

template<typename T>
class DrawTestCase : public TestCase
{
	public:
									DrawTestCase		(tcu::TestContext& context, const char* name, const char* desc, const T data);
									~DrawTestCase		(void);
	virtual	void					initPrograms		(vk::SourceCollections& programCollection) const;
	virtual void					initShaderSources	(void);
	virtual TestInstance*			createInstance		(Context& context) const;

private:
	T													m_data;
	std::string											m_vertShaderSource;
	std::string											m_fragShaderSource;
};

template<typename T>
DrawTestCase<T>::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data)
	: vkt::TestCase	(context, name, desc)
	, m_data		(data)
{
	initShaderSources();
}

template<typename T>
DrawTestCase<T>::~DrawTestCase	(void)
{
}

template<typename T>
void DrawTestCase<T>::initPrograms (vk::SourceCollections& programCollection) const
{
	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
}

template<typename T>
void DrawTestCase<T>::initShaderSources (void)
{
	std::stringstream vertShader;
	vertShader	<< "#version 430\n"
				<< "layout(location = 0) in vec4 in_position;\n"
				<< "layout(location = 1) in vec4 in_color;\n"
				<< "layout(location = 0) out vec4 out_color;\n"

				<< "out gl_PerVertex {\n"
				<< "    vec4  gl_Position;\n"
				<< "    float gl_PointSize;\n"
				<< "};\n"
				<< "void main() {\n"
				<< "    gl_PointSize = 1.0;\n"
				<< "    gl_Position  = in_position;\n"
				<< "    out_color    = in_color;\n"
				<< "}\n";

	m_vertShaderSource = vertShader.str();

	std::stringstream fragShader;
	fragShader	<< "#version 430\n"
				<< "layout(location = 0) in vec4 in_color;\n"
				<< "layout(location = 0) out vec4 out_color;\n"
				<< "void main()\n"
				<< "{\n"
				<< "    out_color = in_color;\n"
				<< "}\n";

	m_fragShaderSource = fragShader.str();
}

template<typename T>
TestInstance* DrawTestCase<T>::createInstance (Context& context) const
{
	return new DrawTestInstance<T>(context, m_data);
}

// Specialized cases
template<>
void DrawTestInstance<DrawParams>::generateDrawData (void)
{
	de::Random		rnd			(SEED ^ m_data.params.firstVertex ^ m_data.params.vertexCount);

	const deUint32	vectorSize	= m_data.params.firstVertex + m_data.params.vertexCount;

	// Initialize the vector
	m_data.vertices = std::vector<PositionColorVertex>(vectorSize, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));

	// Fill only the used indexes
	for (deUint32 vertexIdx = m_data.params.firstVertex; vertexIdx < vectorSize; ++vertexIdx)
	{
		m_data.vertices[vertexIdx] = PositionColorVertex(
			tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0),										// Coord
			tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0)));	// Color
	}
}

template<>
tcu::TestStatus DrawTestInstance<DrawParams>::iterate (void)
{
	tcu::TestLog			&log				= m_context.getTestContext().getLog();
	const vk::VkQueue		queue				= m_context.getUniversalQueue();
	const vk::VkDevice		device				= m_context.getDevice();

	beginRenderPass();

	const vk::VkDeviceSize	vertexBufferOffset	= 0;
	const vk::VkBuffer		vertexBuffer		= m_vertexBuffer->object();

	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
	m_vk.cmdDraw(*m_cmdBuffer, m_data.params.vertexCount, m_data.params.instanceCount, m_data.params.firstVertex, m_data.params.firstInstance);
	endRenderPass(m_vk, *m_cmdBuffer);
	endCommandBuffer(m_vk, *m_cmdBuffer);

	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());

	// Validation
	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));

	std::vector<tcu::Vec4>	vertices;
	std::vector<tcu::Vec4>	colors;

	for (std::vector<PositionColorVertex>::const_iterator vertex = m_data.vertices.begin() + m_data.params.firstVertex; vertex != m_data.vertices.end(); ++vertex)
	{
		vertices.push_back(vertex->position);
		colors.push_back(vertex->color);
	}
	generateRefImage(refImage.getAccess(), vertices, colors);

	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);

	qpTestResult res = QP_TEST_RESULT_PASS;

	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
		res = QP_TEST_RESULT_FAIL;

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

template<>
void DrawTestInstance<DrawIndexedParams>::generateDrawData (void)
{
	de::Random		rnd			(SEED ^ m_data.params.firstIndex ^ m_data.params.indexCount);
	const deUint32	indexSize	= m_data.params.firstIndex + m_data.params.indexCount;

	// Initialize the vector with zeros
	m_data.indexes = std::vector<deUint32>(indexSize, 0);

	deUint32		highestIndex	= 0;	// Store to highest index to calculate the vertices size
	// Fill the indexes from firstIndex
	for (deUint32 idx = 0; idx < m_data.params.indexCount; ++idx)
	{
		deUint32	vertexIdx	= rnd.getInt(m_data.params.vertexOffset, INDEX_LIMIT);
		highestIndex = (vertexIdx > highestIndex) ? vertexIdx : highestIndex;

		m_data.indexes[m_data.params.firstIndex + idx]	= vertexIdx;
	}

	// Fill up the vertex coordinates with zeros until the highestIndex including the vertexOffset
	m_data.vertices = std::vector<PositionColorVertex>(m_data.params.vertexOffset + highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));

	// Generate random vertex only where you have index pointing at
	for (std::vector<deUint32>::const_iterator indexIt = m_data.indexes.begin() + m_data.params.firstIndex; indexIt != m_data.indexes.end(); ++indexIt)
	{
		// Get iterator to the vertex position  with the vertexOffset
		std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + m_data.params.vertexOffset + *indexIt;

		tcu::VecAccess<float, 4, 4>	positionAccess = vertexIt->position.xyzw();
		positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);

		tcu::VecAccess<float, 4, 4>	colorAccess = vertexIt->color.xyzw();
		colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
	}
}

template<>
tcu::TestStatus DrawTestInstance<DrawIndexedParams>::iterate (void)
{
	tcu::TestLog				&log				= m_context.getTestContext().getLog();
	const vk::DeviceInterface&	vk					= m_context.getDeviceInterface();
	const vk::VkDevice			vkDevice			= m_context.getDevice();
	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	const vk::VkQueue			queue				= m_context.getUniversalQueue();
	vk::Allocator&				allocator			= m_context.getDefaultAllocator();

	beginRenderPass();

	const vk::VkDeviceSize	vertexBufferOffset = 0;
	const vk::VkBuffer	vertexBuffer = m_vertexBuffer->object();

	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);

	const deUint32	bufferSize	= (deUint32)(m_data.indexes.size() * sizeof(deUint32));

	vk::Move<vk::VkBuffer>	indexBuffer;

	const vk::VkBufferCreateInfo	bufferCreateInfo =
	{
		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
		DE_NULL,									// const void*			pNext;
		0u,											// VkBufferCreateFlags	flags;
		bufferSize,									// VkDeviceSize			size;
		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
		1u,											// deUint32				queueFamilyIndexCount;
		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
	};

	indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);

	de::MovePtr<vk::Allocation>	indexAlloc;

	indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));

	deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);

	vk::flushAlloc(m_vk, vkDevice, *indexAlloc);

	m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
	m_vk.cmdDrawIndexed(*m_cmdBuffer, m_data.params.indexCount, m_data.params.instanceCount, m_data.params.firstIndex, m_data.params.vertexOffset, m_data.params.firstInstance);
	endRenderPass(m_vk, *m_cmdBuffer);
	endCommandBuffer(m_vk, *m_cmdBuffer);

	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());

	// Validation
	tcu::TextureLevel	refImage	(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));

	std::vector<tcu::Vec4>	vertices;
	std::vector<tcu::Vec4>	colors;

	for (std::vector<deUint32>::const_iterator it = m_data.indexes.begin() + m_data.params.firstIndex; it != m_data.indexes.end(); ++it)
	{
		deUint32 idx = m_data.params.vertexOffset + *it;
		vertices.push_back(m_data.vertices[idx].position);
		colors.push_back(m_data.vertices[idx].color);
	}
	generateRefImage(refImage.getAccess(), vertices, colors);

	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);

	qpTestResult res = QP_TEST_RESULT_PASS;

	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
		res = QP_TEST_RESULT_FAIL;

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

template<>
void DrawTestInstance<DrawIndirectParams>::generateDrawData (void)
{
	de::Random	rnd(SEED ^ m_data.commands[0].vertexCount ^ m_data.commands[0].firstVertex);

	deUint32 lastIndex	= 0;

	// Find the interval which will be used
	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
	{
		const deUint32	index = it->firstVertex + it->vertexCount;
		lastIndex	= (index > lastIndex) ? index : lastIndex;
	}

	// Initialize with zeros
	m_data.vertices = std::vector<PositionColorVertex>(lastIndex, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));

	// Generate random vertices only where necessary
	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
	{
		std::vector<PositionColorVertex>::iterator vertexStart = m_data.vertices.begin() + it->firstVertex;

		for (deUint32 idx = 0; idx < it->vertexCount; ++idx)
		{
			std::vector<PositionColorVertex>::iterator vertexIt = vertexStart + idx;

			tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
			positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);

			tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
			colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
		}
	}
}

template<>
tcu::TestStatus DrawTestInstance<DrawIndirectParams>::iterate (void)
{
	tcu::TestLog						&log				= m_context.getTestContext().getLog();
	const vk::DeviceInterface&			vk					= m_context.getDeviceInterface();
	const vk::VkDevice					vkDevice			= m_context.getDevice();
	vk::Allocator&						allocator			= m_context.getDefaultAllocator();
	const vk::VkQueue					queue				= m_context.getUniversalQueue();
	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	const vk::VkPhysicalDeviceFeatures	features			= m_context.getDeviceFeatures();

	beginRenderPass();

	const vk::VkDeviceSize	vertexBufferOffset	= 0;
	const vk::VkBuffer		vertexBuffer		= m_vertexBuffer->object();

	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);

	vk::Move<vk::VkBuffer>		indirectBuffer;
	de::MovePtr<vk::Allocation>	indirectAlloc;

	{
		const vk::VkDeviceSize	indirectInfoSize	= m_data.commands.size() * sizeof(vk::VkDrawIndirectCommand);

		const vk::VkBufferCreateInfo	indirectCreateInfo =
		{
			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
			DE_NULL,									// const void*			pNext;
			0u,											// VkBufferCreateFlags	flags;
			indirectInfoSize,							// VkDeviceSize			size;
			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,	// VkBufferUsageFlags	usage;
			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
			1u,											// deUint32				queueFamilyIndexCount;
			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
		};

		indirectBuffer	= createBuffer(vk, vkDevice, &indirectCreateInfo);
		indirectAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
		VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));

		deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);

		vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
	}

	// If multiDrawIndirect not supported execute single calls
	if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
	{
		for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
		{
			const deUint32	offset	= (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndirectCommand));
			m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndirectCommand));
		}
	}
	else
	{
		m_vk.cmdDrawIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndirectCommand));
	}

	endRenderPass(m_vk, *m_cmdBuffer);
	endCommandBuffer(m_vk, *m_cmdBuffer);

	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());

	// Validation
	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));

	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
	{
		std::vector<tcu::Vec4>	vertices;
		std::vector<tcu::Vec4>	colors;

		std::vector<PositionColorVertex>::const_iterator	firstIt	= m_data.vertices.begin() + it->firstVertex;
		std::vector<PositionColorVertex>::const_iterator	lastIt	= firstIt + it->vertexCount;

		for (std::vector<PositionColorVertex>::const_iterator vertex = firstIt; vertex != lastIt; ++vertex)
		{
			vertices.push_back(vertex->position);
			colors.push_back(vertex->color);
		}
		generateRefImage(refImage.getAccess(), vertices, colors);
	}

	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);

	qpTestResult res = QP_TEST_RESULT_PASS;

	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
		res = QP_TEST_RESULT_FAIL;

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

template<>
void DrawTestInstance<DrawIndexedIndirectParams>::generateDrawData (void)
{
	de::Random		rnd			(SEED ^ m_data.commands[0].firstIndex ^ m_data.commands[0].indexCount);

	deUint32		lastIndex	= 0;

	// Get the maximum range of indexes
	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
	{
		const deUint32	index		= it->firstIndex + it->indexCount;
						lastIndex	= (index > lastIndex) ? index : lastIndex;
	}

	// Initialize the vector with zeros
	m_data.indexes = std::vector<deUint32>(lastIndex, 0);

	deUint32	highestIndex	= 0;

	// Generate random indexes for the ranges
	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
	{
		for (deUint32 idx = 0; idx < it->indexCount; ++idx)
		{
			const deUint32	vertexIdx	= rnd.getInt(it->vertexOffset, INDEX_LIMIT);
			const deUint32	maxIndex	= vertexIdx + it->vertexOffset;

			highestIndex = (maxIndex > highestIndex) ? maxIndex : highestIndex;
			m_data.indexes[it->firstIndex + idx] = vertexIdx;
		}
	}

	// Initialize the vertex vector
	m_data.vertices = std::vector<PositionColorVertex>(highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));

	// Generate random vertices in the used locations
	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmdIt = m_data.commands.begin(); cmdIt != m_data.commands.end(); ++cmdIt)
	{
		deUint32	firstIdx	= cmdIt->firstIndex;
		deUint32	lastIdx		= firstIdx + cmdIt->indexCount;

		for (deUint32 idx = firstIdx; idx < lastIdx; ++idx)
		{
			std::vector<PositionColorVertex>::iterator	vertexIt = m_data.vertices.begin() + cmdIt->vertexOffset + m_data.indexes[idx];

			tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
			positionAccess = tcu::Vec4(rnd.getFloat(-1.0, 1.0), rnd.getFloat(-1.0, 1.0), 1.0, 1.0);

			tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
			colorAccess = tcu::Vec4(rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0), rnd.getFloat(0.0, 1.0));
		}
	}
}

template<>
tcu::TestStatus DrawTestInstance<DrawIndexedIndirectParams>::iterate (void)
{
	tcu::TestLog						&log				= m_context.getTestContext().getLog();
	const vk::DeviceInterface&			vk					= m_context.getDeviceInterface();
	const vk::VkDevice					vkDevice			= m_context.getDevice();
	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	const vk::VkQueue					queue				= m_context.getUniversalQueue();
	vk::Allocator&						allocator			= m_context.getDefaultAllocator();
	const vk::VkPhysicalDeviceFeatures	features			= m_context.getDeviceFeatures();

	beginRenderPass();

	const vk::VkDeviceSize	vertexBufferOffset	= 0;
	const vk::VkBuffer		vertexBuffer		= m_vertexBuffer->object();

	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);

	vk::Move<vk::VkBuffer>		indirectBuffer;
	de::MovePtr<vk::Allocation>	indirectAlloc;

	{
		const vk::VkDeviceSize	indirectInfoSize	= m_data.commands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);

		const vk::VkBufferCreateInfo	indirectCreateInfo =
		{
			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
			DE_NULL,									// const void*			pNext;
			0u,											// VkBufferCreateFlags	flags;
			indirectInfoSize,							// VkDeviceSize			size;
			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,	// VkBufferUsageFlags	usage;
			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
			1u,											// deUint32				queueFamilyIndexCount;
			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
		};

		indirectBuffer	= createBuffer(vk, vkDevice, &indirectCreateInfo);
		indirectAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
		VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));

		deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);

		vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
	}

	const deUint32	bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));

	vk::Move<vk::VkBuffer>			indexBuffer;

	const vk::VkBufferCreateInfo	bufferCreateInfo =
	{
		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
		DE_NULL,									// const void*			pNext;
		0u,											// VkBufferCreateFlags	flags;
		bufferSize,									// VkDeviceSize			size;
		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
		1u,											// deUint32				queueFamilyIndexCount;
		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
	};

	indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);

	de::MovePtr<vk::Allocation>	indexAlloc;

	indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));

	deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);

	vk::flushAlloc(m_vk, vkDevice, *indexAlloc);

	m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);

	// If multiDrawIndirect not supported execute single calls
	if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
	{
		for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
		{
			const deUint32	offset	= (deUint32)(indirectAlloc->getOffset() + cmdIdx * sizeof(vk::VkDrawIndexedIndirectCommand));
			m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, offset, 1, sizeof(vk::VkDrawIndexedIndirectCommand));
		}
	}
	else
	{
		m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset(), (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndexedIndirectCommand));
	}

	endRenderPass(m_vk, *m_cmdBuffer);
	endCommandBuffer(m_vk, *m_cmdBuffer);

	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());

	// Validation
	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));

	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmd = m_data.commands.begin(); cmd != m_data.commands.end(); ++cmd)
	{
		std::vector<tcu::Vec4>	vertices;
		std::vector<tcu::Vec4>	colors;

		for (deUint32 idx = 0; idx < cmd->indexCount; ++idx)
		{
			const deUint32 vertexIndex = cmd->vertexOffset + m_data.indexes[cmd->firstIndex + idx];
			vertices.push_back(m_data.vertices[vertexIndex].position);
			colors.push_back(m_data.vertices[vertexIndex].color);
		}
		generateRefImage(refImage.getAccess(), vertices, colors);
	}

	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);

	qpTestResult res = QP_TEST_RESULT_PASS;

	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
		res = QP_TEST_RESULT_FAIL;

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

typedef DrawTestCase<DrawParams>				DrawCase;
typedef DrawTestCase<DrawIndexedParams>			IndexedCase;
typedef DrawTestCase<DrawIndirectParams>		IndirectCase;
typedef DrawTestCase<DrawIndexedIndirectParams>	IndexedIndirectCase;

struct TestCaseParams
{
	const DrawCommandType			command;
	const vk::VkPrimitiveTopology	topology;

	TestCaseParams (const DrawCommandType cmd, const vk::VkPrimitiveTopology top)
		: command	(cmd)
		, topology	(top)
	{}
};

}	// anonymous

void populateSubGroup (tcu::TestCaseGroup* testGroup, const TestCaseParams caseParams)
{
	de::Random						rnd			(SEED ^ deStringHash(testGroup->getName()));
	tcu::TestContext&				testCtx		= testGroup->getTestContext();
	const DrawCommandType			command		= caseParams.command;
	const vk::VkPrimitiveTopology	topology	= caseParams.topology;

	for (deUint32 primitiveCountIdx = 0; primitiveCountIdx < DE_LENGTH_OF_ARRAY(PRIMITIVE_COUNT); ++primitiveCountIdx)
	{
		const deUint32 primitives = PRIMITIVE_COUNT[primitiveCountIdx];

		deUint32	multiplier	= 1;
		deUint32	offset		= 0;
		// Calculated by Vulkan 23.1
		switch (topology)
		{
			case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:													break;
			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						multiplier = 2;				break;
			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:													break;
			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					multiplier = 3;				break;
			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:												break;
			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:									offset = 1;	break;
			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		multiplier = 4;	offset = 1;	break;
			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:						offset = 1;	break;
			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	multiplier = 6;				break;
			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	multiplier = 2;				break;
			default:														DE_FATAL("Unsupported topology.");
		}

		const deUint32	vertexCount		= multiplier * primitives + offset;
		std::string		name			= de::toString(primitives);

		switch (command)
		{
			case DRAW_COMMAND_TYPE_DRAW:
			{
				deUint32	firstPrimitive	= rnd.getInt(0, primitives);
				deUint32	firstVertex		= multiplier * firstPrimitive;
				testGroup->addChild(new DrawCase(testCtx, name.c_str(), "vkCmdDraw testcase.",
					DrawParams(topology, vertexCount, 1, firstVertex, 0))
				);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDEXED:
			{
				deUint32	firstIndex			= rnd.getInt(0, OFFSET_LIMIT);
				deUint32	vertexOffset		= rnd.getInt(0, OFFSET_LIMIT);
				testGroup->addChild(new IndexedCase(testCtx, name.c_str(), "vkCmdDrawIndexed testcase.",
					DrawIndexedParams(topology, vk::VK_INDEX_TYPE_UINT32, vertexCount, 1, firstIndex, vertexOffset, 0))
				);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
			{
				deUint32	firstVertex		= rnd.getInt(0, OFFSET_LIMIT);

				DrawIndirectParams	params	= DrawIndirectParams(topology);

				params.addCommand(vertexCount, 1, 0, 0);
				testGroup->addChild(new IndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndirect testcase.", params));

				params.addCommand(vertexCount, 1, firstVertex, 0);
				testGroup->addChild(new IndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndirect testcase.", params));
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
			{
				deUint32	firstIndex		= rnd.getInt(vertexCount, OFFSET_LIMIT);
				deUint32	vertexOffset	= rnd.getInt(vertexCount, OFFSET_LIMIT);

				DrawIndexedIndirectParams	params	= DrawIndexedIndirectParams(topology, vk::VK_INDEX_TYPE_UINT32);
				params.addCommand(vertexCount, 1, 0, 0, 0);
				testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));

				params.addCommand(vertexCount, 1, firstIndex, vertexOffset, 0);
				testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
				break;
			}
			default:
				DE_FATAL("Unsupported draw command.");
		}
	}
}

void createTopologyGroups (tcu::TestCaseGroup* testGroup, const DrawCommandType cmdType)
{
	for (deUint32 idx = 0; idx != vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; ++idx)
	{
		const vk::VkPrimitiveTopology	topology	= vk::VkPrimitiveTopology(idx);
		const std::string				groupName	= de::toLower(getPrimitiveTopologyName(topology)).substr(22);
		addTestGroup(testGroup, groupName, "Testcases with a specific topology.", populateSubGroup, TestCaseParams(cmdType, topology));
	}
}

void createDrawTests (tcu::TestCaseGroup* testGroup)
{
	for (deUint32 idx = 0; idx < DRAW_COMMAND_TYPE_DRAW_LAST; ++idx)
	{
		const DrawCommandType	command	= DrawCommandType(idx);
		addTestGroup(testGroup, getDrawCommandTypeName(command), "Group for testing a specific draw command.", createTopologyGroups, command);
	}
}

tcu::TestCaseGroup*	createBasicDrawTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "basic_draw", "Basic drawing tests", createDrawTests);
}

}	// DrawTests
}	// vkt
