Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) Module
      3  * -----------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Random uniform block layout case.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsRandomUniformBlockCase.hpp"
     25 #include "tcuCommandLine.hpp"
     26 #include "deRandom.hpp"
     27 #include "deStringUtil.hpp"
     28 
     29 using std::string;
     30 using std::vector;
     31 
     32 namespace deqp
     33 {
     34 namespace gls
     35 {
     36 
     37 using namespace gls::ub;
     38 
     39 RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext&	testCtx,
     40 												glu::RenderContext&	renderCtx,
     41 												glu::GLSLVersion	glslVersion,
     42 												const char*			name,
     43 												const char*			description,
     44 												BufferMode			bufferMode,
     45 												deUint32			features,
     46 												deUint32			seed)
     47 	: UniformBlockCase		(testCtx, renderCtx, name, description, glslVersion, bufferMode)
     48 	, m_features			(features)
     49 	, m_maxVertexBlocks		((features & FEATURE_VERTEX_BLOCKS)		? 4 : 0)
     50 	, m_maxFragmentBlocks	((features & FEATURE_FRAGMENT_BLOCKS)	? 4 : 0)
     51 	, m_maxSharedBlocks		((features & FEATURE_SHARED_BLOCKS)		? 4 : 0)
     52 	, m_maxInstances		((features & FEATURE_INSTANCE_ARRAYS)	? 3 : 0)
     53 	, m_maxArrayLength		((features & FEATURE_ARRAYS)			? 8 : 0)
     54 	, m_maxStructDepth		((features & FEATURE_STRUCTS)			? 2 : 0)
     55 	, m_maxBlockMembers		(5)
     56 	, m_maxStructMembers	(4)
     57 	, m_seed				(seed)
     58 	, m_blockNdx			(1)
     59 	, m_uniformNdx			(1)
     60 	, m_structNdx			(1)
     61 {
     62 }
     63 
     64 void RandomUniformBlockCase::init (void)
     65 {
     66 	de::Random rnd(m_seed);
     67 
     68 	int numShared		= m_maxSharedBlocks				> 0	? rnd.getInt(1, m_maxSharedBlocks)				: 0;
     69 	int numVtxBlocks	= m_maxVertexBlocks-numShared	> 0	? rnd.getInt(1, m_maxVertexBlocks-numShared)	: 0;
     70 	int	numFragBlocks	= m_maxFragmentBlocks-numShared	> 0 ? rnd.getInt(1, m_maxFragmentBlocks-numShared)	: 0;
     71 
     72 	for (int ndx = 0; ndx < numShared; ndx++)
     73 		generateBlock(rnd, DECLARE_VERTEX|DECLARE_FRAGMENT);
     74 
     75 	for (int ndx = 0; ndx < numVtxBlocks; ndx++)
     76 		generateBlock(rnd, DECLARE_VERTEX);
     77 
     78 	for (int ndx = 0; ndx < numFragBlocks; ndx++)
     79 		generateBlock(rnd, DECLARE_FRAGMENT);
     80 }
     81 
     82 void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
     83 {
     84 	DE_ASSERT(m_blockNdx <= 'z' - 'a');
     85 
     86 	const float		instanceArrayWeight	= 0.3f;
     87 	UniformBlock&	block				= m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
     88 	int				numInstances		= (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
     89 	int				numUniforms			= rnd.getInt(1, m_maxBlockMembers);
     90 
     91 	if (numInstances > 0)
     92 		block.setArraySize(numInstances);
     93 
     94 	if (numInstances > 0 || rnd.getBool())
     95 		block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
     96 
     97 	// Layout flag candidates.
     98 	vector<deUint32> layoutFlagCandidates;
     99 	layoutFlagCandidates.push_back(0);
    100 	if (m_features & FEATURE_PACKED_LAYOUT)
    101 		layoutFlagCandidates.push_back(LAYOUT_SHARED);
    102 	if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
    103 		layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
    104 	if (m_features & FEATURE_STD140_LAYOUT)
    105 		layoutFlagCandidates.push_back(LAYOUT_STD140);
    106 
    107 	layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
    108 
    109 	if (m_features & FEATURE_MATRIX_LAYOUT)
    110 	{
    111 		static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
    112 		layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
    113 	}
    114 
    115 	block.setFlags(layoutFlags);
    116 
    117 	for (int ndx = 0; ndx < numUniforms; ndx++)
    118 		generateUniform(rnd, block);
    119 
    120 	m_blockNdx += 1;
    121 }
    122 
    123 static std::string genName (char first, char last, int ndx)
    124 {
    125 	std::string	str			= "";
    126 	int			alphabetLen	= last - first + 1;
    127 
    128 	while (ndx > alphabetLen)
    129 	{
    130 		str.insert(str.begin(), (char)(first + ((ndx-1)%alphabetLen)));
    131 		ndx = ((ndx-1) / alphabetLen);
    132 	}
    133 
    134 	str.insert(str.begin(), (char)(first + (ndx%(alphabetLen+1)) - 1));
    135 
    136 	return str;
    137 }
    138 
    139 void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
    140 {
    141 	const float		unusedVtxWeight		= 0.15f;
    142 	const float		unusedFragWeight	= 0.15f;
    143 	bool			unusedOk			= (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
    144 	deUint32		flags				= 0;
    145 	std::string		name				= genName('a', 'z', m_uniformNdx);
    146 	VarType			type				= generateType(rnd, 0, true);
    147 
    148 	flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
    149 	flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
    150 
    151 	block.addUniform(Uniform(name.c_str(), type, flags));
    152 
    153 	m_uniformNdx += 1;
    154 }
    155 
    156 VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
    157 {
    158 	const float structWeight	= 0.1f;
    159 	const float arrayWeight		= 0.1f;
    160 
    161 	if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
    162 	{
    163 		const float		unusedVtxWeight		= 0.15f;
    164 		const float		unusedFragWeight	= 0.15f;
    165 		bool			unusedOk			= (m_features & FEATURE_UNUSED_MEMBERS) != 0;
    166 		vector<VarType>	memberTypes;
    167 		int				numMembers = rnd.getInt(1, m_maxStructMembers);
    168 
    169 		// Generate members first so nested struct declarations are in correct order.
    170 		for (int ndx = 0; ndx < numMembers; ndx++)
    171 			memberTypes.push_back(generateType(rnd, typeDepth+1, true));
    172 
    173 		StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
    174 		m_structNdx += 1;
    175 
    176 		DE_ASSERT(numMembers <= 'Z' - 'A');
    177 		for (int ndx = 0; ndx < numMembers; ndx++)
    178 		{
    179 			deUint32 flags = 0;
    180 
    181 			flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)		? UNUSED_VERTEX		: 0;
    182 			flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)	? UNUSED_FRAGMENT	: 0;
    183 
    184 			structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
    185 		}
    186 
    187 		return VarType(&structType);
    188 	}
    189 	else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
    190 	{
    191 		const bool	arraysOfArraysOk	= (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
    192 		const int	arrayLength			= rnd.getInt(1, m_maxArrayLength);
    193 		VarType	elementType	= generateType(rnd, typeDepth, arraysOfArraysOk);
    194 		return VarType(elementType, arrayLength);
    195 	}
    196 	else
    197 	{
    198 		vector<glu::DataType> typeCandidates;
    199 
    200 		typeCandidates.push_back(glu::TYPE_FLOAT);
    201 		typeCandidates.push_back(glu::TYPE_INT);
    202 		typeCandidates.push_back(glu::TYPE_UINT);
    203 		typeCandidates.push_back(glu::TYPE_BOOL);
    204 
    205 		if (m_features & FEATURE_VECTORS)
    206 		{
    207 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
    208 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
    209 			typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
    210 			typeCandidates.push_back(glu::TYPE_INT_VEC2);
    211 			typeCandidates.push_back(glu::TYPE_INT_VEC3);
    212 			typeCandidates.push_back(glu::TYPE_INT_VEC4);
    213 			typeCandidates.push_back(glu::TYPE_UINT_VEC2);
    214 			typeCandidates.push_back(glu::TYPE_UINT_VEC3);
    215 			typeCandidates.push_back(glu::TYPE_UINT_VEC4);
    216 			typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
    217 			typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
    218 			typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
    219 		}
    220 
    221 		if (m_features & FEATURE_MATRICES)
    222 		{
    223 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
    224 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
    225 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
    226 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
    227 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
    228 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
    229 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
    230 			typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
    231 		}
    232 
    233 		glu::DataType	type	= rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
    234 		deUint32		flags	= 0;
    235 
    236 		if (!glu::isDataTypeBoolOrBVec(type))
    237 		{
    238 			// Precision.
    239 			static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
    240 			flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
    241 		}
    242 
    243 		return VarType(type, flags);
    244 	}
    245 }
    246 
    247 } // gls
    248 } // deqp
    249