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