/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 Google 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 Compute Shader Based Test Case Utility Structs/Functions
 *//*--------------------------------------------------------------------*/

#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "tcuStringTemplate.hpp"

namespace vkt
{
namespace SpirVAssembly
{
namespace
{
bool verifyOutputWithEpsilon (const std::vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, tcu::TestLog& log, const float epsilon)
{
	DE_ASSERT(outputAllocs.size() != 0);
	DE_ASSERT(outputAllocs.size() == expectedOutputs.size());

	for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
	{
		std::vector<deUint8>	expectedBytes;
		expectedOutputs[outputNdx].getBytes(expectedBytes);

		std::vector<float>	expectedFloats	(expectedBytes.size() / sizeof (float));
		std::vector<float>	actualFloats	(expectedBytes.size() / sizeof (float));

		memcpy(&expectedFloats[0], &expectedBytes.front(), expectedBytes.size());
		memcpy(&actualFloats[0], outputAllocs[outputNdx]->getHostPtr(), expectedBytes.size());
		for (size_t floatNdx = 0; floatNdx < actualFloats.size(); ++floatNdx)
		{
			// Use custom epsilon because of the float->string conversion
			if (fabs(expectedFloats[floatNdx] - actualFloats[floatNdx]) > epsilon)
			{
				log << tcu::TestLog::Message << "Error: The actual and expected values not matching."
					<< " Expected: " << expectedFloats[floatNdx] << " Actual: " << actualFloats[floatNdx] << " Epsilon: " << epsilon << tcu::TestLog::EndMessage;
				return false;
			}
		}
	}
	return true;
}
}

std::string getComputeAsmShaderPreamble (const std::string& capabilities, const std::string& extensions, const std::string& exeModes, const std::string& extraEntryPoints)
{
	return
		std::string("OpCapability Shader\n") +
		capabilities +
		extensions +
		"OpMemoryModel Logical GLSL450\n"
		"OpEntryPoint GLCompute %main \"main\" %id\n" +
		extraEntryPoints +
		"OpExecutionMode %main LocalSize 1 1 1\n" +
		exeModes;
}

const char* getComputeAsmShaderPreambleWithoutLocalSize (void)
{
	return
		"OpCapability Shader\n"
		"OpMemoryModel Logical GLSL450\n"
		"OpEntryPoint GLCompute %main \"main\" %id\n";
}

std::string getComputeAsmCommonTypes (std::string blockStorageClass)
{
	return std::string(
		"%bool      = OpTypeBool\n"
		"%void      = OpTypeVoid\n"
		"%voidf     = OpTypeFunction %void\n"
		"%u32       = OpTypeInt 32 0\n"
		"%i32       = OpTypeInt 32 1\n"
		"%f32       = OpTypeFloat 32\n"
		"%uvec3     = OpTypeVector %u32 3\n"
		"%fvec3     = OpTypeVector %f32 3\n"
		"%uvec3ptr  = OpTypePointer Input %uvec3\n") +
		"%i32ptr    = OpTypePointer " + blockStorageClass + " %i32\n"
		"%f32ptr    = OpTypePointer " + blockStorageClass + " %f32\n"
		"%i32arr    = OpTypeRuntimeArray %i32\n"
		"%f32arr    = OpTypeRuntimeArray %f32\n";
}

const char* getComputeAsmCommonInt64Types (void)
{
	return
		"%i64       = OpTypeInt 64 1\n"
		"%i64ptr    = OpTypePointer Uniform %i64\n"
		"%i64arr    = OpTypeRuntimeArray %i64\n";
}

const char* getComputeAsmInputOutputBuffer (void)
{
	return
		"%buf     = OpTypeStruct %f32arr\n"
		"%bufptr  = OpTypePointer Uniform %buf\n"
		"%indata    = OpVariable %bufptr Uniform\n"
		"%outdata   = OpVariable %bufptr Uniform\n";
}

const char* getComputeAsmInputOutputBufferTraits (void)
{
	return
		"OpDecorate %buf BufferBlock\n"
		"OpDecorate %indata DescriptorSet 0\n"
		"OpDecorate %indata Binding 0\n"
		"OpDecorate %outdata DescriptorSet 0\n"
		"OpDecorate %outdata Binding 1\n"
		"OpDecorate %f32arr ArrayStride 4\n"
		"OpMemberDecorate %buf 0 Offset 0\n";
}

bool verifyOutput (const std::vector<Resource>&, const std::vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, tcu::TestLog& log)
{
	const float	epsilon	= 0.001f;
	return verifyOutputWithEpsilon(outputAllocs, expectedOutputs, log, epsilon);
}

// Creates compute-shader assembly by specializing a boilerplate StringTemplate
// on fragments, which must (at least) map "testfun" to an OpFunction definition
// for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
// with "BP_" to avoid collisions with fragments.
//
// It corresponds roughly to this GLSL:
//;
// void main (void) { test_func(vec4(gl_GlobalInvocationID)); }
std::string makeComputeShaderAssembly(const std::map<std::string, std::string>& fragments)
{
	static const char computeShaderBoilerplate[] =
		"OpCapability Shader\n"

		"${capability:opt}\n"
		"${extension:opt}\n"

		"OpMemoryModel Logical GLSL450\n"
		"OpEntryPoint GLCompute %BP_main \"main\" %BP_id3u\n"
		"OpExecutionMode %BP_main LocalSize 1 1 1\n"
		"${execution_mode:opt}\n"
		"OpSource GLSL 430\n"
		"OpDecorate %BP_id3u BuiltIn GlobalInvocationId\n"

		"${decoration:opt}\n"

		SPIRV_ASSEMBLY_TYPES
		SPIRV_ASSEMBLY_CONSTANTS
		SPIRV_ASSEMBLY_ARRAYS

		"%ip_v3u32  = OpTypePointer Input %v3u32\n"
		"%BP_id3u   = OpVariable %ip_v3u32 Input\n"

		"${pre_main:opt}\n"

		"%BP_main   = OpFunction %void None %voidf\n"
		"%BP_label  = OpLabel\n"
		"%BP_id3ul  = OpLoad %v3u32 %BP_id3u\n"
		"%BP_id4u   = OpCompositeConstruct %v4u32 %BP_id3ul %c_u32_0\n"
		"%BP_id4f   = OpConvertUToF %v4f32 %BP_id4u\n"
		"%BP_result = OpFunctionCall %v4f32 %test_code %BP_id4f\n"
		"             OpReturn\n"
		"             OpFunctionEnd\n"
		"\n"
		"${testfun}\n"
		"\n"

		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
		"%BP_getId_label = OpLabel\n"
		"%BP_id_0_ptr = OpAccessChain %ip_u32 %BP_id3u %c_u32_0\n"
		"%BP_id_1_ptr = OpAccessChain %ip_u32 %BP_id3u %c_u32_1\n"
		"%BP_id_2_ptr = OpAccessChain %ip_u32 %BP_id3u %c_u32_2\n"
		"%BP_id_0_val = OpLoad %u32 %BP_id_0_ptr\n"
		"%BP_id_1_val = OpLoad %u32 %BP_id_1_ptr\n"
		"%BP_id_2_val = OpLoad %u32 %BP_id_2_ptr\n"
		"%BP_id_uni_0 = OpBitwiseOr %u32 %BP_id_0_val %BP_id_1_val\n"
		"  %BP_id_uni = OpBitwiseOr %u32 %BP_id_2_val %BP_id_uni_0\n"
		" %is_id_zero = OpIEqual %bool %BP_id_uni %c_u32_0\n"
		"               OpReturnValue %is_id_zero\n"
		"               OpFunctionEnd\n";

	return tcu::StringTemplate(computeShaderBoilerplate).specialize(fragments);
}

} // SpirVAssembly
} // vkt
