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
29using std::set;
30using std::string;
31using std::vector;
32
33namespace rsg
34{
35
36void 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
50void 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
57void 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
114void 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
125bool 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
153VariableType 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
185void 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
242int 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
287int 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
294static 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
353float 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