/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2018 Advanced Micro Devices, Inc.
 *
 * 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 cases for VK_KHR_shader_clock. Ensure that values are
          being read from the OpReadClockKHR OpCode.
 *//*--------------------------------------------------------------------*/

#include "vktShaderClockTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktShaderExecutor.hpp"

#include "vkQueryUtil.hpp"

#include "tcuStringTemplate.hpp"

#include "vktAtomicOperationTests.hpp"
#include "vktShaderExecutor.hpp"

#include "vkRefUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vktTestGroupUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuResultCollector.hpp"

#include "deStringUtil.hpp"
#include "deSharedPtr.hpp"
#include "deRandom.hpp"
#include "deArrayUtil.hpp"

#include <cassert>
#include <string>

namespace vkt
{
namespace shaderexecutor
{

namespace
{

enum
{
	NUM_ELEMENTS = 32
};

enum clockType
{
	SUBGROUP = 0,
	DEVICE
};

enum bitType
{
	BIT_32 = 0,
	BIT_64
};

struct testType
{
	clockType   testClockType;
	bitType     testBitType;
	const char* testName;
};

static inline void* getPtrOfVar(deUint64& var)
{
	return &var;
}

using namespace vk;

class ShaderClockTestInstance : public TestInstance
{
public:
	ShaderClockTestInstance(Context& context, bool realtimeTest, const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
		: TestInstance(context)
		, m_realtime_test(realtimeTest)
		, m_executor(createExecutor(m_context, shaderType, shaderSpec))
	{
		checkSupported();
	}

	virtual tcu::TestStatus iterate(void)
	{
		const deUint64 initValue = 0xcdcdcdcd;

		std::vector<deUint64>	outputs		(NUM_ELEMENTS, initValue);
		std::vector<void*>		outputPtr	(NUM_ELEMENTS, nullptr);

		std::transform(std::begin(outputs), std::end(outputs), std::begin(outputPtr), getPtrOfVar);

		m_executor->execute(NUM_ELEMENTS, nullptr, outputPtr.data());

		if (validateOutput(outputs))
			return tcu::TestStatus::pass("Pass");
		else
			return tcu::TestStatus::fail("Result comparison failed");
	}

private:
	void checkSupported(void)
	{
		m_context.requireDeviceExtension("VK_KHR_shader_clock");

		VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeatures = {};
		shaderClockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR;
		shaderClockFeatures.pNext = DE_NULL;

		VkPhysicalDeviceFeatures2 features = {};
		features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
		features.pNext = &shaderClockFeatures;

		m_context.getInstanceInterface().getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &features);

		if (m_realtime_test && !shaderClockFeatures.shaderDeviceClock)
			TCU_THROW(NotSupportedError, "Shader device clock is not supported");

		if (!m_realtime_test && !shaderClockFeatures.shaderSubgroupClock)
			TCU_THROW(NotSupportedError, "Shader subgroup clock is not supported");
	}

	bool validateOutput(std::vector<deUint64>& outputs)
	{
		// The shader will write a 1 in the output if the clock did not increase
		return (outputs.size() == deUint64(std::count(std::begin(outputs), std::end(outputs), 0)));
	}

	const bool							m_realtime_test;
	de::UniquePtr<ShaderExecutor>		m_executor;
};

class ShaderClockCase : public TestCase
{
public:
	ShaderClockCase(tcu::TestContext& testCtx, testType operation, glu::ShaderType shaderType)
		: TestCase(testCtx, operation.testName, operation.testName)
		, m_operation(operation)
		, m_shaderSpec()
		, m_shaderType(shaderType)
	{
		initShaderSpec();
	}

	TestInstance* createInstance(Context& ctx) const
	{
		return new ShaderClockTestInstance(ctx, (m_operation.testClockType == DEVICE), m_shaderSpec, m_shaderType);
	}

	void initPrograms(vk::SourceCollections& programCollection) const
	{
		generateSources(m_shaderType, m_shaderSpec, programCollection);
	}

private:
	void initShaderSpec()
	{
		std::stringstream extensions;
		std::stringstream source;

		if (m_operation.testBitType == BIT_64)
		{
			extensions	<< "#extension GL_ARB_gpu_shader_int64 : require        \n";

			source << "uint64_t time1 = " << m_operation.testName << "();   \n";
			source << "uint64_t time2 = " << m_operation.testName << "();   \n";
			source << "out0  = uvec2(0, 0);                                 \n";
			source << "if (time1 > time2) {                                 \n";
			source << "    out0.x = 1;                                      \n";
			source << "}                                                    \n";
		}
		else
		{
			source << "uvec2 time1 = " << m_operation.testName << "();                      \n";
			source << "uvec2 time2 = " << m_operation.testName << "();                      \n";
			source << "out0  = uvec2(0, 0);                                                 \n";
			source << "if (time1.y > time2.y || (time1.y == time2.y && time1.x > time2.x)){ \n";
			source << "    out0.x = 1;                                                      \n";
			source << "}                                                                    \n";
		}

		if (m_operation.testClockType == DEVICE)
		{
			extensions << "#extension GL_EXT_shader_realtime_clock : require	\n";
		}
		else
		{
			extensions << "#extension GL_ARB_shader_clock : enable				\n";
		}

		std::map<std::string, std::string> specializations = {
			{	"EXTENSIONS",	extensions.str()    },
			{	"SOURCE",		source.str()        }
		};

		m_shaderSpec.globalDeclarations = tcu::StringTemplate("${EXTENSIONS}").specialize(specializations);
		m_shaderSpec.source             = tcu::StringTemplate("${SOURCE}	").specialize(specializations);

		m_shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(glu::TYPE_UINT_VEC2, glu::PRECISION_HIGHP)));
	}

private:
	ShaderClockCase				(const ShaderClockCase&);
	ShaderClockCase& operator=	(const ShaderClockCase&);

	testType							m_operation;
	ShaderSpec							m_shaderSpec;
	glu::ShaderType						m_shaderType;
};

void addShaderClockTests (tcu::TestCaseGroup* testGroup)
{
	static glu::ShaderType stages[] =
	{
		glu::SHADERTYPE_VERTEX,
		glu::SHADERTYPE_FRAGMENT,
		glu::SHADERTYPE_COMPUTE
	};

	static testType operations[] =
    {
		{SUBGROUP, BIT_64, "clockARB"},
		{SUBGROUP, BIT_32, "clock2x32ARB" },
		{DEVICE,   BIT_64, "clockRealtimeEXT"},
		{DEVICE,   BIT_32, "clockRealtime2x32EXT"}
	};

	tcu::TestContext& testCtx = testGroup->getTestContext();

	for (size_t i = 0; i != DE_LENGTH_OF_ARRAY(stages); ++i)
	{
		const char* stageName = (stages[i] == glu::SHADERTYPE_VERTEX) ? ("vertex")
								: (stages[i] == glu::SHADERTYPE_FRAGMENT) ? ("fragment")
								: (stages[i] == glu::SHADERTYPE_COMPUTE) ? ("compute")
								: (DE_NULL);

		const std::string setName = std::string() + stageName;
		de::MovePtr<tcu::TestCaseGroup> stageGroupTest(new tcu::TestCaseGroup(testCtx, setName.c_str(), "Shader Clock Tests"));

		for (size_t j = 0; j != DE_LENGTH_OF_ARRAY(operations); ++j)
		{
			stageGroupTest->addChild(new ShaderClockCase(testCtx, operations[j], stages[i]));
		}

		testGroup->addChild(stageGroupTest.release());
	}
}

} // anonymous

tcu::TestCaseGroup* createShaderClockTests(tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "shader_clock", "Shader Clock Tests", addShaderClockTests);
}

} // shaderexecutor
} // vkt
