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