/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2017-2019 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  glcSpirvUtils.cpp
 * \brief Utility functions for using Glslang and Spirv-tools to work with
 *  SPIR-V shaders.
 */ /*-------------------------------------------------------------------*/

#include "glcSpirvUtils.hpp"
#include "deArrayUtil.hpp"
#include "deSingleton.h"
#include "deStringUtil.hpp"
#include "gluContextInfo.hpp"
#include "tcuTestLog.hpp"

#include "SPIRV/GlslangToSpv.h"
#include "SPIRV/disassemble.h"
#include "SPIRV/doc.h"
#include "glslang/MachineIndependent/localintermediate.h"
#include "glslang/Public/ShaderLang.h"

#include "spirv-tools/libspirv.hpp"
#include "spirv-tools/optimizer.hpp"

using namespace glu;

namespace glc
{

namespace spirvUtils
{

void checkGlSpirvSupported(deqp::Context& m_context)
{
	bool is_at_least_gl_46 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 6)));
	bool is_arb_gl_spirv   = m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv");

	if ((!is_at_least_gl_46) && (!is_arb_gl_spirv))
		TCU_THROW(NotSupportedError, "GL 4.6 or GL_ARB_gl_spirv is not supported");
}

EShLanguage getGlslangStage(glu::ShaderType type)
{
	static const EShLanguage stageMap[] = {
		EShLangVertex, EShLangFragment, EShLangGeometry, EShLangTessControl, EShLangTessEvaluation, EShLangCompute,
		EShLangRayGen, EShLangAnyHit, EShLangClosestHit, EShLangMiss, EShLangIntersect, EShLangCallable
	};

	return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
}

static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;

void initGlslang(void*)
{
	// Main compiler
	glslang::InitializeProcess();

	// SPIR-V disassembly
	spv::Parameterize();
}

void prepareGlslang(void)
{
	deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
}

void getDefaultLimits(TLimits* limits)
{
	limits->nonInductiveForLoops				 = true;
	limits->whileLoops							 = true;
	limits->doWhileLoops						 = true;
	limits->generalUniformIndexing				 = true;
	limits->generalAttributeMatrixVectorIndexing = true;
	limits->generalVaryingIndexing				 = true;
	limits->generalSamplerIndexing				 = true;
	limits->generalVariableIndexing				 = true;
	limits->generalConstantMatrixVectorIndexing  = true;
}

void getDefaultBuiltInResources(TBuiltInResource* builtin)
{
	getDefaultLimits(&builtin->limits);

	builtin->maxLights								   = 32;
	builtin->maxClipPlanes							   = 6;
	builtin->maxTextureUnits						   = 32;
	builtin->maxTextureCoords						   = 32;
	builtin->maxVertexAttribs						   = 64;
	builtin->maxVertexUniformComponents				   = 4096;
	builtin->maxVaryingFloats						   = 64;
	builtin->maxVertexTextureImageUnits				   = 32;
	builtin->maxCombinedTextureImageUnits			   = 80;
	builtin->maxTextureImageUnits					   = 32;
	builtin->maxFragmentUniformComponents			   = 4096;
	builtin->maxDrawBuffers							   = 32;
	builtin->maxVertexUniformVectors				   = 128;
	builtin->maxVaryingVectors						   = 8;
	builtin->maxFragmentUniformVectors				   = 16;
	builtin->maxVertexOutputVectors					   = 16;
	builtin->maxFragmentInputVectors				   = 15;
	builtin->minProgramTexelOffset					   = -8;
	builtin->maxProgramTexelOffset					   = 7;
	builtin->maxClipDistances						   = 8;
	builtin->maxComputeWorkGroupCountX				   = 65535;
	builtin->maxComputeWorkGroupCountY				   = 65535;
	builtin->maxComputeWorkGroupCountZ				   = 65535;
	builtin->maxComputeWorkGroupSizeX				   = 1024;
	builtin->maxComputeWorkGroupSizeY				   = 1024;
	builtin->maxComputeWorkGroupSizeZ				   = 64;
	builtin->maxComputeUniformComponents			   = 1024;
	builtin->maxComputeTextureImageUnits			   = 16;
	builtin->maxComputeImageUniforms				   = 8;
	builtin->maxComputeAtomicCounters				   = 8;
	builtin->maxComputeAtomicCounterBuffers			   = 1;
	builtin->maxVaryingComponents					   = 60;
	builtin->maxVertexOutputComponents				   = 64;
	builtin->maxGeometryInputComponents				   = 64;
	builtin->maxGeometryOutputComponents			   = 128;
	builtin->maxFragmentInputComponents				   = 128;
	builtin->maxImageUnits							   = 8;
	builtin->maxCombinedImageUnitsAndFragmentOutputs   = 8;
	builtin->maxCombinedShaderOutputResources		   = 8;
	builtin->maxImageSamples						   = 0;
	builtin->maxVertexImageUniforms					   = 0;
	builtin->maxTessControlImageUniforms			   = 0;
	builtin->maxTessEvaluationImageUniforms			   = 0;
	builtin->maxGeometryImageUniforms				   = 0;
	builtin->maxFragmentImageUniforms				   = 8;
	builtin->maxCombinedImageUniforms				   = 8;
	builtin->maxGeometryTextureImageUnits			   = 16;
	builtin->maxGeometryOutputVertices				   = 256;
	builtin->maxGeometryTotalOutputComponents		   = 1024;
	builtin->maxGeometryUniformComponents			   = 1024;
	builtin->maxGeometryVaryingComponents			   = 64;
	builtin->maxTessControlInputComponents			   = 128;
	builtin->maxTessControlOutputComponents			   = 128;
	builtin->maxTessControlTextureImageUnits		   = 16;
	builtin->maxTessControlUniformComponents		   = 1024;
	builtin->maxTessControlTotalOutputComponents	   = 4096;
	builtin->maxTessEvaluationInputComponents		   = 128;
	builtin->maxTessEvaluationOutputComponents		   = 128;
	builtin->maxTessEvaluationTextureImageUnits		   = 16;
	builtin->maxTessEvaluationUniformComponents		   = 1024;
	builtin->maxTessPatchComponents					   = 120;
	builtin->maxPatchVertices						   = 32;
	builtin->maxTessGenLevel						   = 64;
	builtin->maxViewports							   = 16;
	builtin->maxVertexAtomicCounters				   = 0;
	builtin->maxTessControlAtomicCounters			   = 0;
	builtin->maxTessEvaluationAtomicCounters		   = 0;
	builtin->maxGeometryAtomicCounters				   = 0;
	builtin->maxFragmentAtomicCounters				   = 8;
	builtin->maxCombinedAtomicCounters				   = 8;
	builtin->maxAtomicCounterBindings				   = 1;
	builtin->maxVertexAtomicCounterBuffers			   = 0;
	builtin->maxTessControlAtomicCounterBuffers		   = 0;
	builtin->maxTessEvaluationAtomicCounterBuffers	 = 0;
	builtin->maxGeometryAtomicCounterBuffers		   = 0;
	builtin->maxFragmentAtomicCounterBuffers		   = 1;
	builtin->maxCombinedAtomicCounterBuffers		   = 1;
	builtin->maxAtomicCounterBufferSize				   = 16384;
	builtin->maxTransformFeedbackBuffers			   = 4;
	builtin->maxTransformFeedbackInterleavedComponents = 64;
	builtin->maxCullDistances						   = 8;
	builtin->maxCombinedClipAndCullDistances		   = 8;
	builtin->maxSamples								   = 4;
	builtin->maxMeshOutputVerticesNV				   = 256;
	builtin->maxMeshOutputPrimitivesNV				   = 256;
	builtin->maxMeshWorkGroupSizeX_NV				   = 32;
	builtin->maxMeshWorkGroupSizeY_NV				   = 1;
	builtin->maxMeshWorkGroupSizeZ_NV				   = 1;
	builtin->maxTaskWorkGroupSizeX_NV				   = 32;
	builtin->maxTaskWorkGroupSizeY_NV				   = 1;
	builtin->maxTaskWorkGroupSizeZ_NV				   = 1;
	builtin->maxMeshViewCountNV						   = 4;
	builtin->maxDualSourceDrawBuffersEXT			   = 1;
};

glslang::EShTargetLanguageVersion getSpirvTargetVersion(SpirvVersion version)
{
    switch(version)
    {
    default:
        DE_FATAL("unhandled SPIRV target version");
        // fall-through
    case SPIRV_VERSION_1_0:
        return glslang::EShTargetSpv_1_0;
    case SPIRV_VERSION_1_1:
        return glslang::EShTargetSpv_1_1;
    case SPIRV_VERSION_1_2:
        return glslang::EShTargetSpv_1_2;
    case SPIRV_VERSION_1_3:
        return glslang::EShTargetSpv_1_3;
    }
}

bool compileGlslToSpirV(tcu::TestLog& log, std::string source, glu::ShaderType type, ShaderBinaryDataType* dst, SpirvVersion version)
{
	TBuiltInResource builtinRes;

	prepareGlslang();
	getDefaultBuiltInResources(&builtinRes);

	const EShLanguage shaderStage = getGlslangStage(type);

	glslang::TShader  shader(shaderStage);
	glslang::TProgram program;

	const char* src[] = { source.c_str() };

	shader.setStrings(src, 1);
	shader.setEnvTarget(glslang::EshTargetSpv, getSpirvTargetVersion(version));
	program.addShader(&shader);

	const int compileRes = shader.parse(&builtinRes, 100, false, EShMsgSpvRules);
	if (compileRes != 0)
	{
		const int linkRes = program.link(EShMsgSpvRules);

		if (linkRes != 0)
		{
			const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
			glslang::GlslangToSpv(*intermediate, *dst);

			return true;
		}
		else
		{
			log << tcu::TestLog::Message << "Program linking error:\n"
				<< program.getInfoLog() << "\n"
				<< "Source:\n"
				<< source << "\n"
				<< tcu::TestLog::EndMessage;
		}
	}
	else
	{
		log << tcu::TestLog::Message << "Shader compilation error:\n"
			<< shader.getInfoLog() << "\n"
			<< "Source:\n"
			<< source << "\n"
			<< tcu::TestLog::EndMessage;
	}

	return false;
}

void consumer(spv_message_level_t, const char*, const spv_position_t&, const char* m)
{
	std::cerr << "error: " << m << std::endl;
}

void spirvAssemble(ShaderBinaryDataType& dst, const std::string& src)
{
	spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);

	core.SetMessageConsumer(consumer);

	if (!core.Assemble(src, &dst))
		TCU_THROW(InternalError, "Failed to assemble Spir-V source.");
}

void spirvDisassemble(std::string& dst, const ShaderBinaryDataType& src)
{
	spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);

	core.SetMessageConsumer(consumer);

	if (!core.Disassemble(src, &dst))
		TCU_THROW(InternalError, "Failed to disassemble Spir-V module.");
}

bool spirvValidate(ShaderBinaryDataType& dst, bool throwOnError)
{
	spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);

	if (throwOnError)
		core.SetMessageConsumer(consumer);

	if (!core.Validate(dst))
	{
		if (throwOnError)
			TCU_THROW(InternalError, "Failed to validate Spir-V module.");
		return false;
	}

	return true;
}

ShaderBinary makeSpirV(tcu::TestLog& log, ShaderSource source, SpirvVersion version)
{
	ShaderBinary binary;

	if (!spirvUtils::compileGlslToSpirV(log, source.source, source.shaderType, &binary.binary, version))
		TCU_THROW(InternalError, "Failed to convert GLSL to Spir-V");

	binary << source.shaderType << "main";

	return binary;
}

/** Verifying if GLSL to SpirV mapping was performed correctly
 *
 * @param glslSource       GLSL shader template
 * @param spirVSource      SpirV disassembled source
 * @param mappings         Glsl to SpirV mappings vector
 * @param anyOf            any occurence indicator
 *
 * @return true if GLSL code occurs as many times as all of SpirV code for each mapping if anyOf is false
 *         or true if SpirV code occurs at least once if GLSL code found, false otherwise.
 **/
bool verifyMappings(std::string glslSource, std::string spirVSource, SpirVMapping& mappings, bool anyOf)
{
	std::vector<std::string> spirVSourceLines = de::splitString(spirVSource, '\n');

	// Iterate through all glsl functions
	for (SpirVMapping::iterator it = mappings.begin(); it != mappings.end(); it++)
	{
		int glslCodeCount  = 0;
		int spirVCodeCount = 0;

		// To avoid finding functions with similar names (ie. "cos", "acos", "cosh")
		// add characteristic characters that delimits finding results
		std::string glslCode = it->first;

		// Count GLSL code occurrences in GLSL source
		size_t codePosition = glslSource.find(glslCode);
		while (codePosition != std::string::npos)
		{
			glslCodeCount++;
			codePosition = glslSource.find(glslCode, codePosition + 1);
		}

		if (glslCodeCount > 0)
		{
			// Count all SpirV code variants occurrences in SpirV source
			for (int s = 0; s < (signed)it->second.size(); ++s)
			{
				std::vector<std::string> spirVCodes = de::splitString(it->second[s], ' ');

				for (int v = 0; v < (signed)spirVSourceLines.size(); ++v)
				{
					std::vector<std::string> spirVLineCodes = de::splitString(spirVSourceLines[v], ' ');

					bool matchAll = true;
					for (int j = 0; j < (signed)spirVCodes.size(); ++j)
					{
						bool match = false;
						for (int i = 0; i < (signed)spirVLineCodes.size(); ++i)
						{
							if (spirVLineCodes[i] == spirVCodes[j])
								match = true;
						}

						matchAll = matchAll && match;
					}

					if (matchAll)
						spirVCodeCount++;
				}
			}

			// Check if both counts match
			if (anyOf && (glslCodeCount > 0 && spirVCodeCount == 0))
				return false;
			else if (!anyOf && glslCodeCount != spirVCodeCount)
				return false;
		}
	}

	return true;
}

} // namespace spirvUtils

} // namespace glc
