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 
addNewUniforms(vector<const ShaderInput * > & uniforms,set<string> & addedUniforms,const Shader & shader)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 
computeUnifiedUniforms(const Shader & vertexShader,const Shader & fragmentShader,std::vector<const ShaderInput * > & uniforms)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 
computeRandomValue(de::Random & rnd,ValueAccess dst,ConstValueRangeAccess valueRange)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 
computeUniformValues(de::Random & rnd,std::vector<VariableValue> & values,const std::vector<const ShaderInput * > & uniforms)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 
isUndefinedValueRange(ConstValueRangeAccess valueRange)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 
computeRandomType(GeneratorState & state,int maxScalars)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 
computeRandomValueRange(GeneratorState & state,ValueRangeAccess valueRange)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*minStep;
229 				float maxVal	= minVal + step*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 
getTypeConstructorDepth(const VariableType & type)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 
getConservativeValueExprDepth(const GeneratorState & state,ConstValueRangeAccess valueRange)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 
computeRangeLengthSum(ConstValueRangeAccess valueRange)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 
computeDynamicRangeWeight(ConstValueRangeAccess valueRange)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