/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2018 The Khronos Group Inc.
 * Copyright (c) 2018 Danylo Piliaiev <danylo.piliaiev@gmail.com>
 *
 * 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 Test for conditional rendering of vkCmdDraw* functions
 *//*--------------------------------------------------------------------*/

#include "vktConditionalDrawTests.hpp"
#include "vktConditionalRenderingTestUtil.hpp"

#include "vktTestCaseUtil.hpp"
#include "vktDrawTestCaseUtil.hpp"

#include "vktDrawBaseClass.hpp"

#include "tcuTestLog.hpp"
#include "tcuResource.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuRGBA.hpp"

#include "vkDefs.hpp"
#include "vkCmdUtil.hpp"

namespace vkt
{
namespace conditional
{
namespace
{

enum DrawCommandType
{
	DRAW_COMMAND_TYPE_DRAW = 0,
	DRAW_COMMAND_TYPE_DRAW_INDEXED,
	DRAW_COMMAND_TYPE_DRAW_INDIRECT,
	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
	DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT,
	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT,

	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";
		case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:			return "draw_indirect_count";
		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:	return "draw_indexed_indirect_count";
		default:					                        DE_ASSERT(false);
	}
	return "";
}

struct ConditionalTestSpec : public Draw::TestSpecBase
{
	DrawCommandType		command;
	deUint32			drawCalls;
	ConditionalData		conditionalData;
};

class ConditionalDraw : public Draw::DrawTestsBaseClass
{
public:
	typedef		ConditionalTestSpec	TestSpec;

								ConditionalDraw				(Context &context, ConditionalTestSpec testSpec);

	virtual		tcu::TestStatus iterate						(void);
				void			createAndBindIndexBuffer	(vk::VkCommandBuffer cmdBuffer);
				void			createIndirectBuffer		(void);
				void			createIndexedIndirectBuffer	(void);
				void			createIndirectCountBuffer	(void);
				void			recordDraw					(vk::VkCommandBuffer cmdBuffer);

protected:
	const DrawCommandType		    m_command;
	const deUint32					m_drawCalls;

	const ConditionalData			m_conditionalData;
	de::SharedPtr<Draw::Buffer>		m_conditionalBuffer;

	vk::Move<vk::VkCommandBuffer>	m_secondaryCmdBuffer;

	std::vector<deUint32>		    m_indexes;
	de::SharedPtr<Draw::Buffer>		m_indexBuffer;

	de::SharedPtr<Draw::Buffer>		m_indirectBuffer;
	de::SharedPtr<Draw::Buffer>		m_indirectCountBuffer;
};

ConditionalDraw::ConditionalDraw (Context &context, ConditionalTestSpec testSpec)
	: Draw::DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
	, m_command(testSpec.command)
	, m_drawCalls(testSpec.drawCalls)
	, m_conditionalData(testSpec.conditionalData)
{
	checkConditionalRenderingCapabilities(context, m_conditionalData);

	const float minX = -0.3f;
	const float maxX = 0.3f;
	const float drawStep = 0.6f / static_cast<float>(m_drawCalls);

	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
	{
		const float minY = minX + static_cast<float>(drawIdx) * drawStep;
		const float maxY = minY + drawStep;

		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));

		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
	}

	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));

	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));

	for (deUint32 index = 0; index < m_data.size(); index++)
	{
		m_indexes.push_back(index);
	}

	initialize();

	m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
}

void ConditionalDraw::createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer)
{
	const vk::VkDeviceSize indexDataSize = m_indexes.size() * sizeof(deUint32);
	m_indexBuffer = Draw::Buffer::createAndAlloc(m_vk, m_context.getDevice(),
											Draw::BufferCreateInfo(indexDataSize,
															vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
											m_context.getDefaultAllocator(),
											vk::MemoryRequirement::HostVisible);

	deUint8* indexBufferPtr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
	deMemcpy(indexBufferPtr, &m_indexes[0], static_cast<size_t>(indexDataSize));

	vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());

	const vk::VkBuffer indexBuffer = m_indexBuffer->object();
	m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
}

void ConditionalDraw::createIndirectBuffer (void)
{
	const vk::VkDrawIndirectCommand badDrawCommand =
	{
		6u,					// vertexCount
		1u,					// instanceCount
		m_drawCalls * 6u,	// firstVertex
		0u					// firstInstance
	};

	std::vector<vk::VkDrawIndirectCommand> drawCommands;
	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
	{
		const vk::VkDrawIndirectCommand goodDrawCommand =
		{
			6u,				// vertexCount
			1u,				// instanceCount
			6u * drawIdx,	// firstVertex
			0u				// firstInstance
		};

		drawCommands.push_back(goodDrawCommand);
		// *Bad* commands should not be rendered by vkCmdDrawIndirectCountKHR
		drawCommands.push_back(badDrawCommand);
		drawCommands.push_back(badDrawCommand);
	}

	const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndirectCommand);

	m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
													m_context.getDevice(),
													Draw::BufferCreateInfo(drawCommandsSize,
																	vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
													m_context.getDefaultAllocator(),
													vk::MemoryRequirement::HostVisible);

	deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
	deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));

	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
}

void ConditionalDraw::createIndexedIndirectBuffer (void)
{
	const vk::VkDrawIndexedIndirectCommand badDrawCommand =
	{
		6u,					// indexCount
		1u,					// instanceCount
		m_drawCalls * 6u,	// firstIndex
		0u,					// vertexOffset
		0u,					// firstInstance
	};

	std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
	{
		const vk::VkDrawIndexedIndirectCommand goodDrawCommand =
		{
			6u,				// indexCount
			1u,				// instanceCount
			6u * drawIdx,	// firstIndex
			0u,				// vertexOffset
			0u,				// firstInstance
		};

		drawCommands.push_back(goodDrawCommand);
		// *Bad* commands should not be rendered by vkCmdDrawIndexedIndirectCountKHR
		drawCommands.push_back(badDrawCommand);
		drawCommands.push_back(badDrawCommand);
	}

	const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);

	m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
													m_context.getDevice(),
													Draw::BufferCreateInfo(drawCommandsSize,
																	vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
													m_context.getDefaultAllocator(),
													vk::MemoryRequirement::HostVisible);

	deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
	deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));

	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
}

void ConditionalDraw::createIndirectCountBuffer (void)
{
	m_indirectCountBuffer = Draw::Buffer::createAndAlloc(m_vk,
														m_context.getDevice(),
														Draw::BufferCreateInfo(sizeof(deUint32),
																			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
														m_context.getDefaultAllocator(),
														vk::MemoryRequirement::HostVisible);

	deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
	*(deUint32*)(countBufferPtr) = 1;

	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
}

void ConditionalDraw::recordDraw(vk::VkCommandBuffer cmdBuffer)
{
	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
	{
		/* Indirect buffer has next layout:
		 * goodCommand badCommand badCommand goodCommand badCommand badCommand ...
		 */
		const vk::VkDeviceSize indirectOffset = sizeof(vk::VkDrawIndirectCommand) * drawIdx * 3;
		const vk::VkDeviceSize indexedIndirectOffset = sizeof(vk::VkDrawIndexedIndirectCommand) * drawIdx * 3;
		switch (m_command)
		{
			case DRAW_COMMAND_TYPE_DRAW:
			{
				m_vk.cmdDraw(cmdBuffer, 6, 1, 6 * drawIdx, 0);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDEXED:
			{
				m_vk.cmdDrawIndexed(cmdBuffer, 6, 1, 6 * drawIdx, 0, 0);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
			{
				m_vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer->object(), indirectOffset, 1, 0);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
			{
				m_vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer->object(), indexedIndirectOffset, 1, 0);
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
			{
				m_vk.cmdDrawIndirectCount(	cmdBuffer,
											m_indirectBuffer->object(), indirectOffset,
											m_indirectCountBuffer->object(), 0, 3,
											sizeof(vk::VkDrawIndirectCommand));
				break;
			}
			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
			{
				m_vk.cmdDrawIndexedIndirectCount(cmdBuffer,
												 m_indirectBuffer->object(), indexedIndirectOffset,
												 m_indirectCountBuffer->object(), 0, 3,
												 sizeof(vk::VkDrawIndexedIndirectCommand));
				break;
			}
			default: DE_ASSERT(false);
		}
	}
}

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

	const bool useSecondaryCmdBuffer = m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
	beginRenderPass(useSecondaryCmdBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);

	vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;

	if (useSecondaryCmdBuffer)
	{
		const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
		{
			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
			DE_NULL,
			m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE	// conditionalRenderingEnable
		};

		const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
		{
			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
			&conditionalRenderingInheritanceInfo,
			*m_renderPass,										        // renderPass
			0u,															// subpass
			*m_framebuffer,										        // framebuffer
			VK_FALSE,													// occlusionQueryEnable
			(vk::VkQueryControlFlags)0u,								// queryFlags
			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
		};

		const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
		{
			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
			DE_NULL,
			vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
			&inheritanceInfo
		};

		m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo);

		targetCmdBuffer = *m_secondaryCmdBuffer;
	}

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

	m_vk.cmdBindVertexBuffers(targetCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);

	switch(m_command)
	{
		case DRAW_COMMAND_TYPE_DRAW:
		{
			break;
		}
		case DRAW_COMMAND_TYPE_DRAW_INDEXED:
		{
			createAndBindIndexBuffer(targetCmdBuffer);
			break;
		}
		case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
		{
			createIndirectBuffer();
			break;
		}
		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
		{
			createAndBindIndexBuffer(targetCmdBuffer);
			createIndexedIndirectBuffer();
			break;
		}
		case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
		{
			createIndirectBuffer();
			createIndirectCountBuffer();
			break;
		}
		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
		{
			createAndBindIndexBuffer(targetCmdBuffer);
			createIndexedIndirectBuffer();
			createIndirectCountBuffer();
			break;
		}
		default: DE_ASSERT(false);
	}

	m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);

	m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);

	if (m_conditionalData.conditionInSecondaryCommandBuffer)
	{
		beginConditionalRendering(m_vk, *m_secondaryCmdBuffer, *m_conditionalBuffer, m_conditionalData);
		recordDraw(*m_secondaryCmdBuffer);
		m_vk.cmdEndConditionalRenderingEXT(*m_secondaryCmdBuffer);
		m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
	}
	else if (m_conditionalData.conditionInherited)
	{
		recordDraw(*m_secondaryCmdBuffer);
		m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
	}

	if (m_conditionalData.conditionInPrimaryCommandBuffer)
	{
		beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);

		if (m_conditionalData.conditionInherited)
		{
			m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
		}
		else
		{
			recordDraw(*m_cmdBuffer);
		}

		m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
	}
	else if (useSecondaryCmdBuffer)
	{
		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
	}

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

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

	// Validation
	tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
								  referenceFrame.allocLevel(0);

	const deInt32 frameWidth	= referenceFrame.getWidth();
	const deInt32 frameHeight	= referenceFrame.getHeight();

	const tcu::Vec4 clearColor = tcu::RGBA::black().toVec();
	const tcu::Vec4 drawColor  = tcu::RGBA::blue().toVec();

	tcu::clear(referenceFrame.getLevel(0), clearColor);

	const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ?
										drawColor : clearColor;

	Draw::ReferenceImageCoordinates refCoords;

	for (int y = 0; y < frameHeight; y++)
	{
		const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;

		for (int x = 0; x < frameWidth; x++)
		{
			const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;

			if ((yCoord >= refCoords.bottom &&
				 yCoord <= refCoords.top	&&
				 xCoord >= refCoords.left	&&
				 xCoord <= refCoords.right))
				referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
		}
	}

	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 (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
		referenceFrame.getLevel(0), renderedFrame, 0.05f,
		tcu::COMPARE_LOG_RESULT))
	{
		res = QP_TEST_RESULT_FAIL;
	}

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

}	// anonymous

ConditionalDrawTests::ConditionalDrawTests (tcu::TestContext &testCtx)
	: TestCaseGroup	(testCtx, "draw", "Conditional Rendering Of Draw Commands")
{
	/* Left blank on purpose */
}

ConditionalDrawTests::~ConditionalDrawTests (void) {}

void ConditionalDrawTests::init (void)
{
	for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
	{
		const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];

		tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "Conditionaly execute draw calls");

		for (deUint32 commandTypeIdx = 0; commandTypeIdx < DRAW_COMMAND_TYPE_DRAW_LAST; ++commandTypeIdx)
		{
			const DrawCommandType	command	= DrawCommandType(commandTypeIdx);

			ConditionalTestSpec testSpec;
			testSpec.command = command;
			testSpec.drawCalls = 4;
			testSpec.conditionalData = conditionData;
			testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
			testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";

			conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalDraw>(m_testCtx, getDrawCommandTypeName(command), "", testSpec));
		}

		addChild(conditionalDrawRootGroup);
	}
}

}	// conditional
}	// vkt
