/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Copyright (c) 2016 The Android Open Source Project
 *
 * 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 Random uniform block layout case.
 *//*--------------------------------------------------------------------*/

#include "vktRandomUniformBlockCase.hpp"
#include "deRandom.hpp"

namespace vkt
{
namespace ubo
{

namespace
{

static std::string genName (char first, char last, int ndx)
{
	std::string	str			= "";
	int			alphabetLen	= last - first + 1;

	while (ndx > alphabetLen)
	{
		str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
		ndx = (ndx - 1) / alphabetLen;
	}

	str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));

	return str;
}

} // anonymous

RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext&	testCtx,
												const std::string&	name,
												const std::string&	description,
												BufferMode			bufferMode,
												deUint32			features,
												deUint32			seed)
	: UniformBlockCase						(testCtx, name, description, bufferMode, LOAD_FULL_MATRIX, (features & FEATURE_OUT_OF_ORDER_OFFSETS) != 0u)
	, m_features							(features)
	, m_maxVertexBlocks						((features & FEATURE_VERTEX_BLOCKS)		? 4 : 0)
	, m_maxFragmentBlocks					((features & FEATURE_FRAGMENT_BLOCKS)	? 4 : 0)
	, m_maxSharedBlocks						((features & FEATURE_SHARED_BLOCKS)		? 4 : 0)
	, m_maxInstances						((features & FEATURE_INSTANCE_ARRAYS)	? 3 : 0)
	, m_maxArrayLength						((features & FEATURE_ARRAYS)			? 8 : 0)
	, m_maxStructDepth						((features & FEATURE_STRUCTS)			? 2 : 0)
	, m_maxBlockMembers						(5)
	, m_maxStructMembers					(4)
	, m_seed								(seed)
	, m_blockNdx							(1)
	, m_uniformNdx							(1)
	, m_structNdx							(1)
	, m_availableDescriptorUniformBuffers	(12)
{
	de::Random rnd(m_seed);

	int numShared		= m_maxSharedBlocks				> 0	? rnd.getInt(1, m_maxSharedBlocks)				: 0;
	int numVtxBlocks	= m_maxVertexBlocks-numShared	> 0	? rnd.getInt(1, m_maxVertexBlocks - numShared)	: 0;
	int	numFragBlocks	= m_maxFragmentBlocks-numShared	> 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared): 0;

	// calculate how many additional descriptors we can use for arrays
	// this is needed for descriptor_indexing testing as we need to take in to account
	// maxPerStageDescriptorUniformBuffers limit and we can't query it as we need to
	// generate shaders before Context is created; minimal value of this limit is 12
	m_availableDescriptorUniformBuffers -= numVtxBlocks + numFragBlocks;

	for (int ndx = 0; ndx < numShared; ndx++)
		generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);

	for (int ndx = 0; ndx < numVtxBlocks; ndx++)
		generateBlock(rnd, DECLARE_VERTEX);

	for (int ndx = 0; ndx < numFragBlocks; ndx++)
		generateBlock(rnd, DECLARE_FRAGMENT);

	init();
}

void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
{
	DE_ASSERT(m_blockNdx <= 'z' - 'a');

	const float		instanceArrayWeight	= 0.3f;
	UniformBlock&	block				= m_interface.allocBlock(std::string("Block") + (char)('A' + m_blockNdx));
	int				numInstances		= (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
	int				numUniforms			= rnd.getInt(1, m_maxBlockMembers);

	if (m_features & FEATURE_DESCRIPTOR_INDEXING)
	{
		// generate arrays only when we are within the limit
		if (m_availableDescriptorUniformBuffers > 3)
			numInstances = rnd.getInt(2, 4);
		else if (m_availableDescriptorUniformBuffers > 1)
			numInstances = m_availableDescriptorUniformBuffers;
		else
			numInstances = 0;
		m_availableDescriptorUniformBuffers -= numInstances;
	}

	if (numInstances > 0)
		block.setArraySize(numInstances);

	if (numInstances > 0 || rnd.getBool())
		block.setInstanceName(std::string("block") + (char)('A' + m_blockNdx));

	// Layout flag candidates.
	std::vector<deUint32> layoutFlagCandidates;
	layoutFlagCandidates.push_back(0);

	if (m_features & FEATURE_STD140_LAYOUT)
		layoutFlagCandidates.push_back(LAYOUT_STD140);

	if (m_features & FEATURE_STD430_LAYOUT)
		layoutFlagCandidates.push_back(LAYOUT_STD430);

	if (m_features & FEATURE_SCALAR_LAYOUT)
		layoutFlagCandidates.push_back(LAYOUT_SCALAR);

	if (m_features & FEATURE_16BIT_STORAGE)
		layoutFlags |= LAYOUT_16BIT_STORAGE;

	if (m_features & FEATURE_8BIT_STORAGE)
		layoutFlags |= LAYOUT_8BIT_STORAGE;

	if (m_features & FEATURE_DESCRIPTOR_INDEXING)
		layoutFlags |= LAYOUT_DESCRIPTOR_INDEXING;

	layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());

	if (m_features & FEATURE_MATRIX_LAYOUT)
	{
		static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
		layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
	}

	block.setFlags(layoutFlags);

	for (int ndx = 0; ndx < numUniforms; ndx++)
		generateUniform(rnd, block);

	m_blockNdx += 1;
}

void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
{
	const float		unusedVtxWeight		= 0.15f;
	const float		unusedFragWeight	= 0.15f;
	bool			unusedOk			= (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
	deUint32		flags				= 0;
	std::string		name				= genName('a', 'z', m_uniformNdx);
	VarType			type				= generateType(rnd, 0, true);

	flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
	flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;

	block.addUniform(Uniform(name, type, flags));

	m_uniformNdx += 1;
}

VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
{
	const float structWeight	= 0.1f;
	const float arrayWeight		= 0.1f;

	if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
	{
		const float				unusedVtxWeight		= 0.15f;
		const float				unusedFragWeight	= 0.15f;
		bool					unusedOk			= (m_features & FEATURE_UNUSED_MEMBERS) != 0;
		std::vector<VarType>	memberTypes;
		int						numMembers = rnd.getInt(1, m_maxStructMembers);

		// Generate members first so nested struct declarations are in correct order.
		for (int ndx = 0; ndx < numMembers; ndx++)
			memberTypes.push_back(generateType(rnd, typeDepth+1, true));

		StructType& structType = m_interface.allocStruct(std::string("s") + genName('A', 'Z', m_structNdx));
		m_structNdx += 1;

		DE_ASSERT(numMembers <= 'Z' - 'A');
		for (int ndx = 0; ndx < numMembers; ndx++)
		{
			deUint32 flags = 0;

			flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
			flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;

			structType.addMember(std::string("m") + (char)('A' + ndx), memberTypes[ndx], flags);
		}

		return VarType(&structType, m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);
	}
	else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
	{
		const bool	arraysOfArraysOk	= (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
		const int	arrayLength			= rnd.getInt(1, m_maxArrayLength);
		VarType		elementType			= generateType(rnd, typeDepth, arraysOfArraysOk);
		return VarType(elementType, arrayLength);
	}
	else
	{
		std::vector<glu::DataType> typeCandidates;

		typeCandidates.push_back(glu::TYPE_FLOAT);
		typeCandidates.push_back(glu::TYPE_INT);
		typeCandidates.push_back(glu::TYPE_UINT);
		typeCandidates.push_back(glu::TYPE_BOOL);

		if (m_features & FEATURE_16BIT_STORAGE) {
			typeCandidates.push_back(glu::TYPE_UINT16);
			typeCandidates.push_back(glu::TYPE_INT16);
			typeCandidates.push_back(glu::TYPE_FLOAT16);
		}

		if (m_features & FEATURE_8BIT_STORAGE) {
			typeCandidates.push_back(glu::TYPE_UINT8);
			typeCandidates.push_back(glu::TYPE_INT8);
		}

		if (m_features & FEATURE_VECTORS)
		{
			typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
			typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
			typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
			typeCandidates.push_back(glu::TYPE_INT_VEC2);
			typeCandidates.push_back(glu::TYPE_INT_VEC3);
			typeCandidates.push_back(glu::TYPE_INT_VEC4);
			typeCandidates.push_back(glu::TYPE_UINT_VEC2);
			typeCandidates.push_back(glu::TYPE_UINT_VEC3);
			typeCandidates.push_back(glu::TYPE_UINT_VEC4);
			typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
			typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
			typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
			if (m_features & FEATURE_16BIT_STORAGE)
			{
				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC2);
				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC3);
				typeCandidates.push_back(glu::TYPE_FLOAT16_VEC4);
				typeCandidates.push_back(glu::TYPE_INT16_VEC2);
				typeCandidates.push_back(glu::TYPE_INT16_VEC3);
				typeCandidates.push_back(glu::TYPE_INT16_VEC4);
				typeCandidates.push_back(glu::TYPE_UINT16_VEC2);
				typeCandidates.push_back(glu::TYPE_UINT16_VEC3);
				typeCandidates.push_back(glu::TYPE_UINT16_VEC4);
			}
			if (m_features & FEATURE_8BIT_STORAGE)
			{
				typeCandidates.push_back(glu::TYPE_INT8_VEC2);
				typeCandidates.push_back(glu::TYPE_INT8_VEC3);
				typeCandidates.push_back(glu::TYPE_INT8_VEC4);
				typeCandidates.push_back(glu::TYPE_UINT8_VEC2);
				typeCandidates.push_back(glu::TYPE_UINT8_VEC3);
				typeCandidates.push_back(glu::TYPE_UINT8_VEC4);
			}
		}

		if (m_features & FEATURE_MATRICES)
		{
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
		}

		glu::DataType	type	= rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
		deUint32		flags	= (m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);

		if (glu::dataTypeSupportsPrecisionModifier(type))
		{
			// Precision.
			static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
			flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
		}

		return VarType(type, flags);
	}
}

} // ubo
} // vkt
