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*(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
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 deInt64 minVal = valueRange.component(ndx).getMin().asInt();
325 deInt64 maxVal = valueRange.component(ndx).getMax().asInt();
326 rangeLength += (float)((int)(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