/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2020 Google LLC
 * Copyright (c) 2020 The Khronos Group 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 new features in VK_KHR_shader_terminate_invocation
 *//*--------------------------------------------------------------------*/

#include <string>
#include <vector>
#include <amber/amber.h>

#include "tcuDefs.hpp"

#include "vkDefs.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktAmberTestCase.hpp"
#include "vktSpvAsmTerminateInvocationTests.hpp"
#include "vktTestGroupUtil.hpp"

namespace vkt
{
namespace SpirVAssembly
{
namespace
{

struct Case
{
	Case(const char* b, const char* d, bool v) : basename(b), description(d), spv1p3(v), requirements() { }
	Case(const char* b, const char* d, bool v, const std::vector<std::string>& e) : basename(b), description(d), spv1p3(v), requirements(e) { }
	const char *basename;
	const char *description;
	bool spv1p3;
	// Additional Vulkan requirements, if any.
	std::vector<std::string> requirements;
};
struct CaseGroup
{
	CaseGroup(const char* the_data_dir) : data_dir(the_data_dir) { }
	void add(const char* basename, const char* description, bool spv1p3)
	{
		cases.push_back(Case(basename, description, spv1p3));
	}
	void add(const char* basename, const char* description, bool spv1p3, const std::vector<std::string>& requirements)
	{
		cases.push_back(Case(basename, description, spv1p3, requirements));
	}

	const char* data_dir;
	std::vector<Case> cases;
};


void addTestsForAmberFiles (tcu::TestCaseGroup* tests, CaseGroup group)
{
	tcu::TestContext& testCtx = tests->getTestContext();
	const std::string data_dir(group.data_dir);
	const std::string category = data_dir;
	std::vector<Case> cases(group.cases);

	for (unsigned i = 0; i < cases.size() ; ++i)
	{
		deUint32 vulkan_version = cases[i].spv1p3 ? VK_MAKE_VERSION(1, 1, 0) : VK_MAKE_VERSION(1, 0, 0);
		vk::SpirvVersion spirv_version = cases[i].spv1p3 ? vk::SPIRV_VERSION_1_3 : vk::SPIRV_VERSION_1_0;
		vk::SpirVAsmBuildOptions asm_options(vulkan_version, spirv_version);

		const std::string file = std::string(cases[i].basename) + ".amber";
		cts_amber::AmberTestCase *testCase = cts_amber::createAmberTestCase(testCtx,
																			cases[i].basename,
																			cases[i].description,
																			category.c_str(),
																			file);
		DE_ASSERT(testCase != DE_NULL);
		testCase->addRequirement("VK_KHR_shader_terminate_invocation");
		const std::vector<std::string>& reqmts = cases[i].requirements;
		for (size_t r = 0; r < reqmts.size() ; ++r)
		{
			testCase->addRequirement(reqmts[r]);
		}

		testCase->setSpirVAsmBuildOptions(asm_options);
		tests->addChild(testCase);
	}
}

} // anonymous

tcu::TestCaseGroup* createTerminateInvocationGroup(tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> terminateTests(new tcu::TestCaseGroup(testCtx, "terminate_invocation", "VK_KHR_shader_terminate_invocation tests"));

	const char* data_data = "spirv_assembly/instruction/terminate_invocation";

	std::vector<std::string> Stores;
	Stores.push_back("Features.fragmentStoresAndAtomics");

	std::vector<std::string> VarPtr;
	VarPtr.push_back("VariablePointerFeatures.variablePointersStorageBuffer");
	VarPtr.push_back("Features.fragmentStoresAndAtomics");

	std::vector<std::string> Vote;
	Vote.push_back("SubgroupProperties.supportedOperations.vote");
	Vote.push_back("SubgroupProperties.supportedStages.fragment");

	std::vector<std::string> Ballot;
	Ballot.push_back("SubgroupProperties.supportedOperations.ballot");
	Ballot.push_back("SubgroupProperties.supportedStages.fragment");

	CaseGroup group(data_data);
	group.add("no_output_write", "no write to after calling terminate invocation", false);
	group.add("no_output_write_before_terminate", "no write to output despite occurring before terminate invocation", false);
	group.add("no_ssbo_store", "no store to SSBO when it occurs after terminate invocation", false, Stores);
	group.add("no_ssbo_atomic", "no atomic update to SSBO when it occurs after terminate invocation", false, Stores);
	group.add("ssbo_store_before_terminate", "ssbo store commits when it occurs before terminate invocation", false, Stores);
	group.add("no_image_store", "no image write when it occurs after terminate invocation", false, Stores);
	group.add("no_image_atomic", "no image atomic updates when it occurs after terminate invocation", false, Stores);
	group.add("no_null_pointer_load", "null pointer should not be accessed by a load in a terminated invocation", false, VarPtr);
	group.add("no_null_pointer_store", "null pointer should not be accessed by a store in a terminated invocation", false, VarPtr);
	group.add("no_out_of_bounds_load", "out of bounds pointer should not be accessed by a load in a terminated invocation", false, VarPtr);
	group.add("no_out_of_bounds_store", "out of bounds pointer should not be accessed by a store in a terminated invocation", false, VarPtr);
	group.add("no_out_of_bounds_atomic", "out of bounds pointer should not be accessed by an atomic in a terminated invocation", false, VarPtr);
	group.add("terminate_loop", "\"inifinite\" loop that calls terminate invocation", false);
	group.add("subgroup_ballot", "checks that terminated invocations don't participate in the ballot", true, Ballot);
	group.add("subgroup_vote", "checks that a subgroup all does not include any terminated invocations", true, Vote);
	terminateTests->addChild(createTestGroup(testCtx, "terminate", "Terminate Invocation", addTestsForAmberFiles, group));

	return terminateTests.release();
}

} // SpirVAssembly
} // vkt
