Home | History | Annotate | Download | only in randomshaders
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Random Shader Generator
      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 Utilities.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "rsgUtils.hpp"
     25 
     26 #include <set>
     27 #include <string>
     28 
     29 using std::set;
     30 using std::string;
     31 using std::vector;
     32 
     33 namespace rsg
     34 {
     35 
     36 void addNewUniforms (vector<const ShaderInput*>& uniforms, set<string>& addedUniforms, const Shader& shader)
     37 {
     38 	const vector<ShaderInput*>& shaderUniforms = shader.getUniforms();
     39 	for (vector<ShaderInput*>::const_iterator i = shaderUniforms.begin(); i != shaderUniforms.end(); i++)
     40 	{
     41 		const ShaderInput* uniform = *i;
     42 		if (addedUniforms.find(uniform->getVariable()->getName()) == addedUniforms.end())
     43 		{
     44 			addedUniforms.insert(uniform->getVariable()->getName());
     45 			uniforms.push_back(uniform);
     46 		}
     47 	}
     48 }
     49 
     50 void computeUnifiedUniforms (const Shader& vertexShader, const Shader& fragmentShader, std::vector<const ShaderInput*>& uniforms)
     51 {
     52 	set<string> addedUniforms;
     53 	addNewUniforms(uniforms, addedUniforms, vertexShader);
     54 	addNewUniforms(uniforms, addedUniforms, fragmentShader);
     55 }
     56 
     57 void computeRandomValue (de::Random& rnd, ValueAccess dst, ConstValueRangeAccess valueRange)
     58 {
     59 	const VariableType& type = dst.getType();
     60 
     61 	switch (type.getBaseType())
     62 	{
     63 		case VariableType::TYPE_FLOAT:
     64 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
     65 			{
     66 				const float quantizeStep = 1.0f/8.0f;
     67 				float minVal = valueRange.component(ndx).getMin().asFloat();
     68 				float maxVal = valueRange.component(ndx).getMax().asFloat();
     69 				dst.component(ndx).asFloat() = getQuantizedFloat(rnd, minVal, maxVal, quantizeStep);
     70 			}
     71 			break;
     72 
     73 		case VariableType::TYPE_BOOL:
     74 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
     75 			{
     76 				int minVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
     77 				int maxVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
     78 				dst.component(ndx).asBool() = rnd.getInt(minVal, maxVal) == 1;
     79 			}
     80 			break;
     81 
     82 		case VariableType::TYPE_INT:
     83 		case VariableType::TYPE_SAMPLER_2D:
     84 		case VariableType::TYPE_SAMPLER_CUBE:
     85 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
     86 			{
     87 				int	minVal = valueRange.component(ndx).getMin().asInt();
     88 				int maxVal = valueRange.component(ndx).getMax().asInt();
     89 				dst.component(ndx).asInt() = rnd.getInt(minVal, maxVal);
     90 			}
     91 			break;
     92 
     93 		case VariableType::TYPE_ARRAY:
     94 		{
     95 			int numElements = type.getNumElements();
     96 			for (int ndx = 0; ndx < numElements; ndx++)
     97 				computeRandomValue(rnd, dst.arrayElement(ndx), valueRange.arrayElement(ndx));
     98 			break;
     99 		}
    100 
    101 		case VariableType::TYPE_STRUCT:
    102 		{
    103 			int numMembers = (int)type.getMembers().size();
    104 			for (int ndx = 0; ndx < numMembers; ndx++)
    105 				computeRandomValue(rnd, dst.member(ndx), valueRange.member(ndx));
    106 			break;
    107 		}
    108 
    109 		default:
    110 			TCU_FAIL("Invalid type");
    111 	}
    112 }
    113 
    114 void computeUniformValues (de::Random& rnd, std::vector<VariableValue>& values, const std::vector<const ShaderInput*>& uniforms)
    115 {
    116 	DE_ASSERT(values.empty());
    117 	for (vector<const ShaderInput*>::const_iterator i = uniforms.begin(); i != uniforms.end(); i++)
    118 	{
    119 		const ShaderInput* uniform = *i;
    120 		values.push_back(VariableValue(uniform->getVariable()));
    121 		computeRandomValue(rnd, values[values.size()-1].getValue(), uniform->getValueRange());
    122 	}
    123 }
    124 
    125 bool isUndefinedValueRange (ConstValueRangeAccess valueRange)
    126 {
    127 	switch (valueRange.getType().getBaseType())
    128 	{
    129 		case VariableType::TYPE_FLOAT:
    130 		case VariableType::TYPE_INT:
    131 		{
    132 			bool	isFloat	= valueRange.getType().getBaseType() == VariableType::TYPE_FLOAT;
    133 			Scalar	infMin	= isFloat ? Scalar::min<float>() : Scalar::min<int>();
    134 			Scalar	infMax	= isFloat ? Scalar::max<float>() : Scalar::max<int>();
    135 
    136 			for (int ndx = 0; ndx < valueRange.getType().getNumElements(); ndx++)
    137 			{
    138 				if (valueRange.getMin().component(ndx).asScalar() != infMin ||
    139 					valueRange.getMax().component(ndx).asScalar() != infMax)
    140 					return false;
    141 			}
    142 			return true;
    143 		}
    144 
    145 		case VariableType::TYPE_BOOL:
    146 			return false;
    147 
    148 		default:
    149 			TCU_FAIL("Unsupported type");
    150 	}
    151 }
    152 
    153 VariableType computeRandomType (GeneratorState& state, int maxScalars)
    154 {
    155 	DE_ASSERT(maxScalars >= 1);
    156 
    157 	static const VariableType::Type baseTypes[] =
    158 	{
    159 		VariableType::TYPE_BOOL,
    160 		VariableType::TYPE_INT,
    161 		VariableType::TYPE_FLOAT
    162 		// \todo [pyry] Other types
    163 	};
    164 
    165 	VariableType::Type baseType = VariableType::TYPE_LAST;
    166 	state.getRandom().choose(baseTypes, baseTypes + DE_LENGTH_OF_ARRAY(baseTypes), &baseType, 1);
    167 
    168 	switch (baseType)
    169 	{
    170 		case VariableType::TYPE_BOOL:
    171 		case VariableType::TYPE_INT:
    172 		case VariableType::TYPE_FLOAT:
    173 		{
    174 			const int minVecLength = 1;
    175 			const int maxVecLength = 4;
    176 			return VariableType(baseType, state.getRandom().getInt(minVecLength, de::min(maxScalars, maxVecLength)));
    177 		}
    178 
    179 		default:
    180 			DE_ASSERT(DE_FALSE);
    181 			throw Exception("computeRandomType(): Unsupported type");
    182 	}
    183 }
    184 
    185 void computeRandomValueRange (GeneratorState& state, ValueRangeAccess valueRange)
    186 {
    187 	const VariableType&	type	= valueRange.getType();
    188 	de::Random&			rnd		= state.getRandom();
    189 
    190 	switch (type.getBaseType())
    191 	{
    192 		case VariableType::TYPE_BOOL:
    193 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    194 			{
    195 				bool minVal = rnd.getBool();
    196 				bool maxVal = minVal ? true : rnd.getBool();
    197 				valueRange.getMin().component(ndx).asBool() = minVal;
    198 				valueRange.getMax().component(ndx).asBool() = maxVal;
    199 			}
    200 			break;
    201 
    202 		case VariableType::TYPE_INT:
    203 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    204 			{
    205 				const int minIntVal		= -16;
    206 				const int maxIntVal		=  16;
    207 				const int maxRangeLen	= maxIntVal - minIntVal;
    208 
    209 				int rangeLen	= rnd.getInt(0, maxRangeLen);
    210 				int minVal		= minIntVal + rnd.getInt(0, maxRangeLen-rangeLen);
    211 				int maxVal		= minVal + rangeLen;
    212 
    213 				valueRange.getMin().component(ndx).asInt() = minVal;
    214 				valueRange.getMax().component(ndx).asInt() = maxVal;
    215 			}
    216 			break;
    217 
    218 		case VariableType::TYPE_FLOAT:
    219 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    220 			{
    221 				const float step			= 0.1f;
    222 				const int	maxSteps		= 320;
    223 				const float minFloatVal		= -16.0f;
    224 
    225 				int rangeLen	= rnd.getInt(0, maxSteps);
    226 				int minStep		= rnd.getInt(0, maxSteps-rangeLen);
    227 
    228 				float minVal	= minFloatVal + step*(float)minStep;
    229 				float maxVal	= minVal + step*(float)rangeLen;
    230 
    231 				valueRange.getMin().component(ndx).asFloat() = minVal;
    232 				valueRange.getMax().component(ndx).asFloat() = maxVal;
    233 			}
    234 			break;
    235 
    236 		default:
    237 			DE_ASSERT(DE_FALSE);
    238 			throw Exception("computeRandomValueRange(): Unsupported type");
    239 	}
    240 }
    241 
    242 int getTypeConstructorDepth (const VariableType& type)
    243 {
    244 	switch (type.getBaseType())
    245 	{
    246 		case VariableType::TYPE_STRUCT:
    247 		{
    248 			const vector<VariableType::Member>& members		= type.getMembers();
    249 			int									maxDepth	= 0;
    250 			for (vector<VariableType::Member>::const_iterator i = members.begin(); i != members.end(); i++)
    251 			{
    252 				const VariableType&	memberType	= i->getType();
    253 				int					depth		= 0;
    254 				switch (memberType.getBaseType())
    255 				{
    256 					case VariableType::TYPE_STRUCT:
    257 						depth = getTypeConstructorDepth(memberType);
    258 						break;
    259 
    260 					case VariableType::TYPE_BOOL:
    261 					case VariableType::TYPE_FLOAT:
    262 					case VariableType::TYPE_INT:
    263 						depth = memberType.getNumElements() == 1 ? 1 : 2;
    264 						break;
    265 
    266 					default:
    267 						DE_ASSERT(DE_FALSE);
    268 						break;
    269 				}
    270 
    271 				maxDepth = de::max(maxDepth, depth);
    272 			}
    273 			return maxDepth + 1;
    274 		}
    275 
    276 		case VariableType::TYPE_BOOL:
    277 		case VariableType::TYPE_FLOAT:
    278 		case VariableType::TYPE_INT:
    279 			return 2; // One node for ctor, another for value
    280 
    281 		default:
    282 			DE_ASSERT(DE_FALSE);
    283 			return 0;
    284 	}
    285 }
    286 
    287 int getConservativeValueExprDepth (const GeneratorState& state, ConstValueRangeAccess valueRange)
    288 {
    289 	// \todo [2011-03-22 pyry] Do a look-up into variable manager?
    290 	DE_UNREF(state);
    291 	return getTypeConstructorDepth(valueRange.getType());
    292 }
    293 
    294 static float computeRangeLengthSum (ConstValueRangeAccess valueRange)
    295 {
    296 	const VariableType&	type		= valueRange.getType();
    297 	float				rangeLength	= 0.0f;
    298 
    299 	switch (type.getBaseType())
    300 	{
    301 		case VariableType::TYPE_FLOAT:
    302 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    303 			{
    304 				float minVal = valueRange.component(ndx).getMin().asFloat();
    305 				float maxVal = valueRange.component(ndx).getMax().asFloat();
    306 				rangeLength += maxVal - minVal;
    307 			}
    308 			break;
    309 
    310 		case VariableType::TYPE_BOOL:
    311 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    312 			{
    313 				int minVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
    314 				int maxVal = valueRange.component(ndx).getMin().asBool() ? 1 : 0;
    315 				rangeLength += (float)(maxVal - minVal);
    316 			}
    317 			break;
    318 
    319 		case VariableType::TYPE_INT:
    320 		case VariableType::TYPE_SAMPLER_2D:
    321 		case VariableType::TYPE_SAMPLER_CUBE:
    322 			for (int ndx = 0; ndx < type.getNumElements(); ndx++)
    323 			{
    324 				int	minVal = valueRange.component(ndx).getMin().asInt();
    325 				int maxVal = valueRange.component(ndx).getMax().asInt();
    326 				rangeLength += (float)(maxVal - minVal);
    327 			}
    328 			break;
    329 
    330 		case VariableType::TYPE_ARRAY:
    331 		{
    332 			int numElements = type.getNumElements();
    333 			for (int ndx = 0; ndx < numElements; ndx++)
    334 				rangeLength += computeRangeLengthSum(valueRange.arrayElement(ndx));
    335 			break;
    336 		}
    337 
    338 		case VariableType::TYPE_STRUCT:
    339 		{
    340 			int numMembers = (int)type.getMembers().size();
    341 			for (int ndx = 0; ndx < numMembers; ndx++)
    342 				rangeLength += computeRangeLengthSum(valueRange.member(ndx));
    343 			break;
    344 		}
    345 
    346 		default:
    347 			TCU_FAIL("Invalid type");
    348 	}
    349 
    350 	return rangeLength;
    351 }
    352 
    353 float computeDynamicRangeWeight (ConstValueRangeAccess valueRange)
    354 {
    355 	const VariableType& type		= valueRange.getType();
    356 	float				rangeLenSum	= computeRangeLengthSum(valueRange);
    357 	int					numScalars	= type.getScalarSize();
    358 
    359 	return rangeLenSum / (float)numScalars;
    360 }
    361 
    362 } // rsg
    363