/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2017 The Khronos Group Inc.
 * Copyright (c) 2017 Google Inc.
 * Copyright (c) 2017 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 Differing iterpolation decorations tests
 *//*--------------------------------------------------------------------*/

#include "vktDrawDifferingInterpolationTests.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 "tcuStringTemplate.hpp"

#include "rrRenderer.hpp"

#include <string>
#include <sstream>

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

struct DrawParams
{
	string	vertShader;
	string	fragShader;
	string	refVertShader;
	string	refFragShader;
	bool	useDynamicRendering;
};

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

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

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 void				checkSupport		(Context& context) const;
	virtual TestInstance*		createInstance		(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::initPrograms (SourceCollections& programCollection) const
{
	const tcu::StringTemplate	vertShader	(string(
		"#version 430\n"
		"layout(location = 0) in vec4 in_position;\n"
		"layout(location = 1) in vec4 in_color;\n"
		"layout(location = 0) ${qualifier:opt} 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"));

	const tcu::StringTemplate	fragShader	(string(
		"#version 430\n"
		"layout(location = 0) ${qualifier:opt} in vec4 in_color;\n"
		"layout(location = 0) out vec4 out_color;\n"
		"void main()\n"
		"{\n"
		"    out_color = in_color;\n"
		"}\n"));

	map<string, string> empty;
	map<string, string> flat;
	flat["qualifier"] = "flat";
	map<string, string> noPerspective;
	noPerspective["qualifier"] = "noperspective";

	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(empty));
	programCollection.glslSources.add("vertFlatColor") << glu::VertexSource(vertShader.specialize(flat));
	programCollection.glslSources.add("vertNoPerspective") << glu::VertexSource(vertShader.specialize(noPerspective));
	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(empty));
	programCollection.glslSources.add("fragFlatColor") << glu::FragmentSource(fragShader.specialize(flat));
	programCollection.glslSources.add("fragNoPerspective") << glu::FragmentSource(fragShader.specialize(noPerspective));
}

void DrawTestCase::checkSupport(Context& context) const
{
	if (m_data.useDynamicRendering)
		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
}

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

tcu::TestStatus DrawTestInstance::iterate (void)
{
	tcu::ConstPixelBufferAccess	frames[2];
	de::SharedPtr<Image>		colorTargetImages[2];
	const string				vertShaderNames[2]	= { m_data.vertShader, m_data.refVertShader };
	const string				fragShaderNames[2]	= { m_data.fragShader, m_data.refFragShader };
	tcu::TestLog				&log				= m_context.getTestContext().getLog();

	// Run two iterations with shaders that have different interpolation decorations. Images should still match.
	for (deUint32 frameIdx = 0; frameIdx < DE_LENGTH_OF_ARRAY(frames); frameIdx++)
	{
		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(vertShaderNames[frameIdx].c_str()), 0));
		const Unique<VkShaderModule>	fs						(createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShaderNames[frameIdx].c_str()), 0));
		const VkFormat					targetImageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
		de::SharedPtr<Buffer>			vertexBuffer;
		Move<VkRenderPass>				renderPass;
		Move<VkImageView>				colorTargetView;
		Move<VkFramebuffer>				framebuffer;
		Move<VkPipeline>				pipeline;

		// Create color buffer image.
		{
			const VkExtent3D				targetImageExtent		= { WIDTH, HEIGHT, 1 };
			const ImageCreateInfo			targetImageCreateInfo	(VK_IMAGE_TYPE_2D, targetImageFormat, 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);
			colorTargetImages[frameIdx]								= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
		}

		const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[frameIdx]->object(), VK_IMAGE_VIEW_TYPE_2D, targetImageFormat);
		colorTargetView = createImageView(vk, device, &colorTargetViewInfo);

		// Create render pass and frame buffer.
		if (!m_data.useDynamicRendering)
		{
			RenderPassCreateInfo			renderPassCreateInfo;
			renderPassCreateInfo.addAttachment(AttachmentDescription(targetImageFormat,
																	 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_GENERAL,
																	 VK_IMAGE_LAYOUT_GENERAL));

			const VkAttachmentReference		colorAttachmentRef		= { 0, VK_IMAGE_LAYOUT_GENERAL };
			renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
															   0,
															   0,
															   DE_NULL,
															   1,
															   &colorAttachmentRef,
															   DE_NULL,
															   AttachmentReference(),
															   0,
															   DE_NULL));

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

			vector<VkImageView>				colorAttachments		{ *colorTargetView };
			const FramebufferCreateInfo		framebufferCreateInfo	(*renderPass, colorAttachments, WIDTH, HEIGHT, 1);
			framebuffer	= createFramebuffer(vk, device, &framebufferCreateInfo);
		}

		// Create vertex buffer.
		{
			const PositionColorVertex	vertices[]	=
			{
				PositionColorVertex(
					tcu::Vec4(-0.8f, -0.7f, 1.0f, 1.0f),	// Coord
					tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)),		// Color

				PositionColorVertex(
					tcu::Vec4(0.0f, 0.4f, 0.5f, 0.5f),		// Coord
					tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)),		// Color

				PositionColorVertex(
					tcu::Vec4(0.8f, -0.5f, 1.0f, 1.0f),		// Coord
					tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f))		// Color
			};

			const VkDeviceSize			dataSize	= DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionColorVertex);
			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);
		}

		const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo;
		Move<VkPipelineLayout>			pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);

		// 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) * 2, VK_VERTEX_INPUT_RATE_VERTEX };

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

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

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

			VkPipelineRenderingCreateInfoKHR renderingCreateInfo
			{
				VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
				DE_NULL,
				0u,
				1u,
				&targetImageFormat,
				VK_FORMAT_UNDEFINED,
				VK_FORMAT_UNDEFINED
			};

			if (m_data.useDynamicRendering)
				pipelineCreateInfo.pNext = &renderingCreateInfo;

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

		// Queue draw and read results.
		{
			const VkQueue				queue				= m_context.getUniversalQueue();
			const VkClearValue			clearColor			= { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
			const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
			const VkMemoryBarrier		memBarrier			=
			{
				VK_STRUCTURE_TYPE_MEMORY_BARRIER,
				DE_NULL,
				VK_ACCESS_TRANSFER_WRITE_BIT,
				VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
			};
			const VkRect2D				renderArea			= makeRect2D(WIDTH, HEIGHT);
			const VkDeviceSize			vertexBufferOffset	= 0;
			const VkBuffer				buffer				= vertexBuffer->object();
			const VkOffset3D			zeroOffset			= { 0, 0, 0 };

			beginCommandBuffer(vk, *cmdBuffer, 0u);

			initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[frameIdx]->object(), VK_IMAGE_LAYOUT_GENERAL,
										  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);

			vk.cmdClearColorImage(*cmdBuffer, colorTargetImages[frameIdx]->object(),
				VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);

			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
				VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
				0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);

			if (m_data.useDynamicRendering)
				beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearColor);
			else
				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea);

			vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
			vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);

			if (m_data.useDynamicRendering)
				endRendering(vk, *cmdBuffer);
			else
				endRenderPass(vk, *cmdBuffer);

			endCommandBuffer(vk, *cmdBuffer);

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

			frames[frameIdx] = colorTargetImages[frameIdx]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
		}
	}

	qpTestResult res = QP_TEST_RESULT_PASS;

	if (!tcu::intThresholdCompare(log, "Result", "Image comparison result", frames[0], frames[1], tcu::UVec4(0), tcu::COMPARE_LOG_RESULT))
		res = QP_TEST_RESULT_FAIL;

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

void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
{
	tcu::TestContext&	testCtx	= testGroup->getTestContext();
	const DrawParams	paramsFlat0	= { "vert", "fragFlatColor", "vertFlatColor", "fragFlatColor", useDynamicRendering };
	const DrawParams	paramsFlat1	= { "vertFlatColor", "frag", "vert", "frag", useDynamicRendering };

	const DrawParams	paramsNoPerspective0	= { "vert", "fragNoPerspective", "vertNoPerspective", "fragNoPerspective", useDynamicRendering };
	const DrawParams	paramsNoPerspective1	= { "vertNoPerspective", "frag", "vert", "frag", useDynamicRendering };

	testGroup->addChild(new DrawTestCase(testCtx, "flat_0", "Mismatching flat interpolation testcase 0.", paramsFlat0));
	testGroup->addChild(new DrawTestCase(testCtx, "flat_1", "Mismatching flat interpolation testcase 1.", paramsFlat1));

	testGroup->addChild(new DrawTestCase(testCtx, "noperspective_0", "Mismatching noperspective interpolation testcase 0.", paramsNoPerspective0));
	testGroup->addChild(new DrawTestCase(testCtx, "noperspective_1", "Mismatching noperspective interpolation testcase 1.", paramsNoPerspective1));
}

}	// anonymous

tcu::TestCaseGroup*	createDifferingInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
{
	return createTestGroup(testCtx, "differing_interpolation", "Tests for mismatched interpolation decorations.", createTests, useDynamicRendering);
}

}	// Draw
}	// vkt
