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 Expressions. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "rsgExpression.hpp" 25 #include "rsgVariableManager.hpp" 26 #include "rsgBinaryOps.hpp" 27 #include "rsgBuiltinFunctions.hpp" 28 #include "rsgUtils.hpp" 29 #include "deMath.h" 30 31 using std::vector; 32 33 namespace rsg 34 { 35 36 namespace 37 { 38 39 class IsReadableEntry 40 { 41 public: 42 typedef ValueEntryIterator<IsReadableEntry> Iterator; 43 44 IsReadableEntry (deUint32 exprFlags) 45 : m_exprFlags(exprFlags) 46 { 47 } 48 49 bool operator() (const ValueEntry* entry) const 50 { 51 if ((m_exprFlags & CONST_EXPR) && (entry->getVariable()->getStorage() != Variable::STORAGE_CONST)) 52 return false; 53 54 return true; 55 } 56 57 private: 58 deUint32 m_exprFlags; 59 }; 60 61 class IsReadableIntersectingEntry : public IsReadableEntry 62 { 63 public: 64 typedef ValueEntryIterator<IsReadableIntersectingEntry> Iterator; 65 66 IsReadableIntersectingEntry (ConstValueRangeAccess valueRange, deUint32 exprFlags) 67 : IsReadableEntry (exprFlags) 68 , m_valueRange (valueRange) 69 { 70 } 71 72 bool operator() (const ValueEntry* entry) const 73 { 74 if (!IsReadableEntry::operator()(entry)) 75 return false; 76 77 if (entry->getValueRange().getType() != m_valueRange.getType()) 78 return false; 79 80 if (!entry->getValueRange().intersects(m_valueRange)) 81 return false; 82 83 return true; 84 } 85 86 private: 87 ConstValueRangeAccess m_valueRange; 88 }; 89 90 class IsWritableIntersectingEntry : public IsWritableEntry 91 { 92 public: 93 typedef ValueEntryIterator<IsWritableIntersectingEntry> Iterator; 94 95 IsWritableIntersectingEntry (ConstValueRangeAccess valueRange) 96 : m_valueRange(valueRange) 97 { 98 } 99 100 bool operator() (const ValueEntry* entry) const 101 { 102 return IsWritableEntry::operator()(entry) && 103 entry->getVariable()->getType() == m_valueRange.getType() && 104 entry->getValueRange().intersects(m_valueRange); 105 } 106 107 private: 108 ConstValueRangeAccess m_valueRange; 109 }; 110 111 class IsWritableSupersetEntry : public IsWritableEntry 112 { 113 public: 114 typedef ValueEntryIterator<IsWritableSupersetEntry> Iterator; 115 116 IsWritableSupersetEntry (ConstValueRangeAccess valueRange) 117 : m_valueRange(valueRange) 118 { 119 } 120 121 bool operator() (const ValueEntry* entry) const 122 { 123 return IsWritableEntry()(entry) && 124 entry->getVariable()->getType() == m_valueRange.getType() && 125 entry->getValueRange().isSupersetOf(m_valueRange); 126 } 127 128 private: 129 ConstValueRangeAccess m_valueRange; 130 }; 131 132 class IsSamplerEntry 133 { 134 public: 135 typedef ValueEntryIterator<IsSamplerEntry> Iterator; 136 137 IsSamplerEntry (VariableType::Type type) 138 : m_type(type) 139 { 140 DE_ASSERT(m_type == VariableType::TYPE_SAMPLER_2D || m_type == VariableType::TYPE_SAMPLER_CUBE); 141 } 142 143 bool operator() (const ValueEntry* entry) const 144 { 145 if (entry->getVariable()->getType() == VariableType(m_type, 1)) 146 { 147 DE_ASSERT(entry->getVariable()->getStorage() == Variable::STORAGE_UNIFORM); 148 return true; 149 } 150 else 151 return false; 152 } 153 154 private: 155 VariableType::Type m_type; 156 }; 157 158 inline bool getWeightedBool (de::Random& random, float trueWeight) 159 { 160 DE_ASSERT(de::inRange<float>(trueWeight, 0.0f, 1.0f)); 161 return (random.getFloat() < trueWeight); 162 } 163 164 void computeRandomValueRangeForInfElements (GeneratorState& state, ValueRangeAccess valueRange) 165 { 166 const VariableType& type = valueRange.getType(); 167 de::Random& rnd = state.getRandom(); 168 169 switch (type.getBaseType()) 170 { 171 case VariableType::TYPE_BOOL: 172 // No need to handle bool as it will be false, true 173 break; 174 175 case VariableType::TYPE_INT: 176 for (int ndx = 0; ndx < type.getNumElements(); ndx++) 177 { 178 if (valueRange.getMin().component(ndx).asScalar() != Scalar::min<int>() || 179 valueRange.getMax().component(ndx).asScalar() != Scalar::max<int>()) 180 continue; 181 182 const int minIntVal = -16; 183 const int maxIntVal = 16; 184 const int maxRangeLen = maxIntVal - minIntVal; 185 186 int rangeLen = rnd.getInt(0, maxRangeLen); 187 int minVal = minIntVal + rnd.getInt(0, maxRangeLen-rangeLen); 188 int maxVal = minVal + rangeLen; 189 190 valueRange.getMin().component(ndx).asInt() = minVal; 191 valueRange.getMax().component(ndx).asInt() = maxVal; 192 } 193 break; 194 195 case VariableType::TYPE_FLOAT: 196 for (int ndx = 0; ndx < type.getNumElements(); ndx++) 197 { 198 if (valueRange.getMin().component(ndx).asScalar() != Scalar::min<float>() || 199 valueRange.getMax().component(ndx).asScalar() != Scalar::max<float>()) 200 continue; 201 202 const float step = 0.1f; 203 const int maxSteps = 320; 204 const float minFloatVal = -16.0f; 205 206 int rangeLen = rnd.getInt(0, maxSteps); 207 int minStep = rnd.getInt(0, maxSteps-rangeLen); 208 209 float minVal = minFloatVal + step*minStep; 210 float maxVal = minVal + step*rangeLen; 211 212 valueRange.getMin().component(ndx).asFloat() = minVal; 213 valueRange.getMax().component(ndx).asFloat() = maxVal; 214 } 215 break; 216 217 default: 218 DE_ASSERT(DE_FALSE); 219 throw Exception("computeRandomValueRangeForInfElements(): unsupported type"); 220 } 221 } 222 223 void setInfiniteRange (ValueRangeAccess valueRange) 224 { 225 const VariableType& type = valueRange.getType(); 226 227 switch (type.getBaseType()) 228 { 229 case VariableType::TYPE_BOOL: 230 for (int ndx = 0; ndx < type.getNumElements(); ndx++) 231 { 232 valueRange.getMin().component(ndx) = Scalar::min<bool>(); 233 valueRange.getMax().component(ndx) = Scalar::max<bool>(); 234 } 235 break; 236 237 case VariableType::TYPE_INT: 238 for (int ndx = 0; ndx < type.getNumElements(); ndx++) 239 { 240 valueRange.getMin().component(ndx) = Scalar::min<int>(); 241 valueRange.getMax().component(ndx) = Scalar::max<int>(); 242 } 243 break; 244 245 case VariableType::TYPE_FLOAT: 246 for (int ndx = 0; ndx < type.getNumElements(); ndx++) 247 { 248 valueRange.getMin().component(ndx) = Scalar::min<float>(); 249 valueRange.getMax().component(ndx) = Scalar::max<float>(); 250 } 251 break; 252 253 default: 254 DE_ASSERT(DE_FALSE); 255 throw Exception("setInfiniteRange(): unsupported type"); 256 } 257 } 258 259 bool canAllocateVariable (const GeneratorState& state, const VariableType& type) 260 { 261 DE_ASSERT(!type.isVoid()); 262 263 if (state.getExpressionFlags() & NO_VAR_ALLOCATION) 264 return false; 265 266 if (state.getVariableManager().getNumAllocatedScalars() + type.getScalarSize() > state.getShaderParameters().maxCombinedVariableScalars) 267 return false; 268 269 return true; 270 } 271 272 template <class T> float getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) { return T::getWeight(state, valueRange); } 273 template <class T> Expression* create (GeneratorState& state, ConstValueRangeAccess valueRange) { return new T(state, valueRange); } 274 275 struct ExpressionSpec 276 { 277 float (*getWeight) (const GeneratorState& state, ConstValueRangeAccess valueRange); 278 Expression* (*create) (GeneratorState& state, ConstValueRangeAccess valueRange); 279 }; 280 281 static const ExpressionSpec s_expressionSpecs[] = 282 { 283 { getWeight<FloatLiteral>, create<FloatLiteral> }, 284 { getWeight<IntLiteral>, create<IntLiteral> }, 285 { getWeight<BoolLiteral>, create<BoolLiteral> }, 286 { getWeight<ConstructorOp>, create<ConstructorOp> }, 287 { getWeight<AssignOp>, create<AssignOp> }, 288 { getWeight<VariableRead>, create<VariableRead> }, 289 { getWeight<MulOp>, create<MulOp> }, 290 { getWeight<AddOp>, create<AddOp> }, 291 { getWeight<SubOp>, create<SubOp> }, 292 { getWeight<LessThanOp>, create<LessThanOp> }, 293 { getWeight<LessOrEqualOp>, create<LessOrEqualOp> }, 294 { getWeight<GreaterThanOp>, create<GreaterThanOp> }, 295 { getWeight<GreaterOrEqualOp>, create<GreaterOrEqualOp> }, 296 { getWeight<EqualOp>, create<EqualOp> }, 297 { getWeight<NotEqualOp>, create<NotEqualOp> }, 298 { getWeight<SwizzleOp>, create<SwizzleOp> }, 299 { getWeight<SinOp>, create<SinOp> }, 300 { getWeight<CosOp>, create<CosOp> }, 301 { getWeight<TanOp>, create<TanOp> }, 302 { getWeight<AsinOp>, create<AsinOp> }, 303 { getWeight<AcosOp>, create<AcosOp> }, 304 { getWeight<AtanOp>, create<AtanOp> }, 305 { getWeight<ExpOp>, create<ExpOp> }, 306 { getWeight<LogOp>, create<LogOp> }, 307 { getWeight<Exp2Op>, create<Exp2Op> }, 308 { getWeight<Log2Op>, create<Log2Op> }, 309 { getWeight<SqrtOp>, create<SqrtOp> }, 310 { getWeight<InvSqrtOp>, create<InvSqrtOp> }, 311 { getWeight<ParenOp>, create<ParenOp> }, 312 { getWeight<TexLookup>, create<TexLookup> } 313 }; 314 315 static const ExpressionSpec s_lvalueSpecs[] = 316 { 317 { getWeight<VariableWrite>, create<VariableWrite> } 318 }; 319 320 #if !defined(DE_MAX) 321 # define DE_MAX(a, b) ((b) > (a) ? (b) : (a)) 322 #endif 323 324 enum 325 { 326 MAX_EXPRESSION_SPECS = (int)DE_MAX(DE_LENGTH_OF_ARRAY(s_expressionSpecs), DE_LENGTH_OF_ARRAY(s_lvalueSpecs)) 327 }; 328 329 const ExpressionSpec* chooseExpression (GeneratorState& state, const ExpressionSpec* specs, int numSpecs, ConstValueRangeAccess valueRange) 330 { 331 float weights[MAX_EXPRESSION_SPECS]; 332 333 DE_ASSERT(numSpecs <= (int)DE_LENGTH_OF_ARRAY(weights)); 334 335 // Compute weights 336 for (int ndx = 0; ndx < numSpecs; ndx++) 337 weights[ndx] = specs[ndx].getWeight(state, valueRange); 338 339 // Choose 340 return &state.getRandom().chooseWeighted<const ExpressionSpec&>(specs, specs+numSpecs, weights); 341 } 342 343 } // anonymous 344 345 Expression::~Expression (void) 346 { 347 } 348 349 Expression* Expression::createRandom (GeneratorState& state, ConstValueRangeAccess valueRange) 350 { 351 return chooseExpression(state, s_expressionSpecs, (int)DE_LENGTH_OF_ARRAY(s_expressionSpecs), valueRange)->create(state, valueRange); 352 } 353 354 Expression* Expression::createRandomLValue (GeneratorState& state, ConstValueRangeAccess valueRange) 355 { 356 return chooseExpression(state, s_lvalueSpecs, (int)DE_LENGTH_OF_ARRAY(s_lvalueSpecs), valueRange)->create(state, valueRange); 357 } 358 359 FloatLiteral::FloatLiteral (GeneratorState& state, ConstValueRangeAccess valueRange) 360 : m_value(VariableType::getScalarType(VariableType::TYPE_FLOAT)) 361 { 362 float minVal = -10.0f; 363 float maxVal = +10.0f; 364 float step = 0.25f; 365 366 if (valueRange.getType() == VariableType(VariableType::TYPE_FLOAT, 1)) 367 { 368 minVal = valueRange.getMin().component(0).asFloat(); 369 maxVal = valueRange.getMax().component(0).asFloat(); 370 371 if (Scalar::min<float>() == minVal) 372 minVal = -10.0f; 373 374 if (Scalar::max<float>() == maxVal) 375 maxVal = +10.0f; 376 } 377 378 int numSteps = (int)((maxVal-minVal)/step) + 1; 379 380 float value = deFloatClamp(minVal + step*state.getRandom().getInt(0, numSteps), minVal, maxVal); 381 ExecValueAccess access = m_value.getValue(VariableType::getScalarType(VariableType::TYPE_FLOAT)); 382 383 for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++) 384 access.asFloat(ndx) = value; 385 } 386 387 float FloatLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 388 { 389 DE_UNREF(state); 390 const VariableType& type = valueRange.getType(); 391 if (type == VariableType(VariableType::TYPE_FLOAT, 1)) 392 { 393 float minVal = valueRange.getMin().asFloat(); 394 float maxVal = valueRange.getMax().asFloat(); 395 396 if (Scalar::min<float>() == minVal && Scalar::max<float>() == maxVal) 397 return 0.1f; 398 399 // Weight based on value range length 400 float rangeLength = maxVal - minVal; 401 402 DE_ASSERT(rangeLength >= 0.0f); 403 return deFloatMax(0.1f, 1.0f - rangeLength); 404 } 405 else if (type.isVoid()) 406 return unusedValueWeight; 407 else 408 return 0.0f; 409 } 410 411 void FloatLiteral::tokenize (GeneratorState& state, TokenStream& str) const 412 { 413 DE_UNREF(state); 414 str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_FLOAT)).asFloat(0)); 415 } 416 417 IntLiteral::IntLiteral (GeneratorState& state, ConstValueRangeAccess valueRange) 418 : m_value(VariableType::getScalarType(VariableType::TYPE_INT)) 419 { 420 int minVal = -16; 421 int maxVal = +16; 422 423 if (valueRange.getType() == VariableType(VariableType::TYPE_INT, 1)) 424 { 425 minVal = valueRange.getMin().component(0).asInt(); 426 maxVal = valueRange.getMax().component(0).asInt(); 427 428 if (Scalar::min<int>() == minVal) 429 minVal = -16; 430 431 if (Scalar::max<int>() == maxVal) 432 maxVal = 16; 433 } 434 435 int value = state.getRandom().getInt(minVal, maxVal); 436 ExecValueAccess access = m_value.getValue(VariableType::getScalarType(VariableType::TYPE_INT)); 437 438 for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++) 439 access.asInt(ndx) = value; 440 } 441 442 float IntLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 443 { 444 DE_UNREF(state); 445 const VariableType& type = valueRange.getType(); 446 if (type == VariableType(VariableType::TYPE_INT, 1)) 447 { 448 int minVal = valueRange.getMin().asInt(); 449 int maxVal = valueRange.getMax().asInt(); 450 451 if (Scalar::min<int>() == minVal && Scalar::max<int>() == maxVal) 452 return 0.1f; 453 454 int rangeLength = maxVal - minVal; 455 456 DE_ASSERT(rangeLength >= 0); 457 return deFloatMax(0.1f, 1.0f - rangeLength/4.0f); 458 } 459 else if (type.isVoid()) 460 return unusedValueWeight; 461 else 462 return 0.0f; 463 } 464 465 void IntLiteral::tokenize (GeneratorState& state, TokenStream& str) const 466 { 467 DE_UNREF(state); 468 str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_INT)).asInt(0)); 469 } 470 471 BoolLiteral::BoolLiteral (GeneratorState& state, ConstValueRangeAccess valueRange) 472 : m_value(VariableType::getScalarType(VariableType::TYPE_BOOL)) 473 { 474 int minVal = 0; 475 int maxVal = 1; 476 477 if (valueRange.getType() == VariableType(VariableType::TYPE_BOOL, 1)) 478 { 479 minVal = valueRange.getMin().component(0).asBool() ? 1 : 0; 480 maxVal = valueRange.getMax().component(0).asBool() ? 1 : 0; 481 } 482 483 bool value = state.getRandom().getInt(minVal, maxVal) == 1; 484 ExecValueAccess access = m_value.getValue(VariableType::getScalarType(VariableType::TYPE_BOOL)); 485 486 for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++) 487 access.asBool(ndx) = value; 488 } 489 490 float BoolLiteral::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 491 { 492 DE_UNREF(state); 493 const VariableType& type = valueRange.getType(); 494 if (type == VariableType(VariableType::TYPE_BOOL, 1)) 495 return 0.5f; 496 else if (type.isVoid()) 497 return unusedValueWeight; 498 else 499 return 0.0f; 500 } 501 502 void BoolLiteral::tokenize (GeneratorState& state, TokenStream& str) const 503 { 504 DE_UNREF(state); 505 str << Token(m_value.getValue(VariableType::getScalarType(VariableType::TYPE_BOOL)).asBool(0)); 506 } 507 508 namespace 509 { 510 511 // \note int-bool and float-bool conversions handled in a special way. 512 template <typename SrcType, typename DstType> 513 inline DstType convert (SrcType src) 514 { 515 if (Scalar::min<SrcType>() == src) 516 return Scalar::min<DstType>().template as<DstType>(); 517 else if (Scalar::max<SrcType>() == src) 518 return Scalar::max<DstType>().template as<DstType>(); 519 else 520 return DstType(src); 521 } 522 523 // According to GLSL ES spec. 524 template <> inline bool convert<float, bool> (float src) { return src != 0.0f; } 525 template <> inline bool convert<int, bool> (int src) { return src != 0; } 526 template <> inline float convert<bool, float> (bool src) { return src ? 1.0f : 0.0f; } 527 template <> inline int convert<bool, int> (bool src) { return src ? 1 : 0; } 528 529 template <> inline int convert<float, int> (float src) 530 { 531 if (Scalar::min<float>() == src) 532 return Scalar::min<int>().as<int>(); 533 else if (Scalar::max<float>() == src) 534 return Scalar::max<int>().as<int>(); 535 else if (src > 0.0f) 536 return (int)deFloatFloor(src); 537 else 538 return (int)deFloatCeil(src); 539 } 540 541 template <typename SrcType, typename DstType> 542 inline void convertValueRange (SrcType srcMin, SrcType srcMax, DstType& dstMin, DstType& dstMax) 543 { 544 dstMin = convert<SrcType, DstType>(srcMin); 545 dstMax = convert<SrcType, DstType>(srcMax); 546 } 547 548 template <> 549 inline void convertValueRange<float, int> (float srcMin, float srcMax, int& dstMin, int& dstMax) 550 { 551 if (Scalar::min<float>() == srcMin) 552 dstMin = Scalar::min<int>().as<int>(); 553 else 554 dstMin = (int)deFloatCeil(srcMin); 555 556 if (Scalar::max<float>() == srcMax) 557 dstMax = Scalar::max<int>().as<int>(); 558 else 559 dstMax = (int)deFloatFloor(srcMax); 560 } 561 562 template <> 563 inline void convertValueRange<float, bool> (float srcMin, float srcMax, bool& dstMin, bool& dstMax) 564 { 565 dstMin = srcMin > 0.0f; 566 dstMax = srcMax > 0.0f; 567 } 568 569 // \todo [pyry] More special cases? 570 571 // Returns whether it is possible to convert some SrcType value range to given DstType valueRange 572 template <typename SrcType, typename DstType> 573 bool isConversionOk (DstType min, DstType max) 574 { 575 SrcType sMin, sMax; 576 convertValueRange(min, max, sMin, sMax); 577 return sMin <= sMax && 578 de::inRange(convert<SrcType, DstType>(sMin), min, max) && 579 de::inRange(convert<SrcType, DstType>(sMax), min, max); 580 } 581 582 // Work-around for non-deterministic float behavior 583 template <> bool isConversionOk<float, float> (float, float) { return true; } 584 585 // \todo [2011-03-26 pyry] Provide this in ValueAccess? 586 template <typename T> T getValueAccessValue (ConstValueAccess access); 587 template<> inline float getValueAccessValue<float> (ConstValueAccess access) { return access.asFloat(); } 588 template<> inline int getValueAccessValue<int> (ConstValueAccess access) { return access.asInt(); } 589 template<> inline bool getValueAccessValue<bool> (ConstValueAccess access) { return access.asBool(); } 590 591 template <typename T> T& getValueAccessValue (ValueAccess access); 592 template<> inline float& getValueAccessValue<float> (ValueAccess access) { return access.asFloat(); } 593 template<> inline int& getValueAccessValue<int> (ValueAccess access) { return access.asInt(); } 594 template<> inline bool& getValueAccessValue<bool> (ValueAccess access) { return access.asBool(); } 595 596 template <typename SrcType, typename DstType> 597 bool isConversionOk (ConstValueRangeAccess valueRange) 598 { 599 return isConversionOk<SrcType>(getValueAccessValue<DstType>(valueRange.getMin()), getValueAccessValue<DstType>(valueRange.getMax())); 600 } 601 602 template <typename SrcType, typename DstType> 603 void convertValueRangeTempl (ConstValueRangeAccess src, ValueRangeAccess dst) 604 { 605 DstType dMin, dMax; 606 convertValueRange(getValueAccessValue<SrcType>(src.getMin()), getValueAccessValue<SrcType>(src.getMax()), dMin, dMax); 607 getValueAccessValue<DstType>(dst.getMin()) = dMin; 608 getValueAccessValue<DstType>(dst.getMax()) = dMax; 609 } 610 611 template <typename SrcType, typename DstType> 612 void convertExecValueTempl (ExecConstValueAccess src, ExecValueAccess dst) 613 { 614 for (int ndx = 0; ndx < EXEC_VEC_WIDTH; ndx++) 615 dst.as<DstType>(ndx) = convert<SrcType, DstType>(src.as<SrcType>(ndx)); 616 } 617 618 typedef bool (*IsConversionOkFunc) (ConstValueRangeAccess); 619 typedef void (*ConvertValueRangeFunc) (ConstValueRangeAccess, ValueRangeAccess); 620 typedef void (*ConvertExecValueFunc) (ExecConstValueAccess, ExecValueAccess); 621 622 inline int getBaseTypeConvNdx (VariableType::Type type) 623 { 624 switch (type) 625 { 626 case VariableType::TYPE_FLOAT: return 0; 627 case VariableType::TYPE_INT: return 1; 628 case VariableType::TYPE_BOOL: return 2; 629 default: return -1; 630 } 631 } 632 633 bool isConversionOk (VariableType::Type srcType, VariableType::Type dstType, ConstValueRangeAccess valueRange) 634 { 635 // [src][dst] 636 static const IsConversionOkFunc convTable[3][3] = 637 { 638 { isConversionOk<float, float>, isConversionOk<float, int>, isConversionOk<float, bool> }, 639 { isConversionOk<int, float>, isConversionOk<int, int>, isConversionOk<int, bool> }, 640 { isConversionOk<bool, float>, isConversionOk<bool, int>, isConversionOk<bool, bool> } 641 }; 642 return convTable[getBaseTypeConvNdx(srcType)][getBaseTypeConvNdx(dstType)](valueRange); 643 } 644 645 void convertValueRange (ConstValueRangeAccess src, ValueRangeAccess dst) 646 { 647 // [src][dst] 648 static const ConvertValueRangeFunc convTable[3][3] = 649 { 650 { convertValueRangeTempl<float, float>, convertValueRangeTempl<float, int>, convertValueRangeTempl<float, bool> }, 651 { convertValueRangeTempl<int, float>, convertValueRangeTempl<int, int>, convertValueRangeTempl<int, bool> }, 652 { convertValueRangeTempl<bool, float>, convertValueRangeTempl<bool, int>, convertValueRangeTempl<bool, bool> } 653 }; 654 655 convTable[getBaseTypeConvNdx(src.getType().getBaseType())][getBaseTypeConvNdx(dst.getType().getBaseType())](src, dst); 656 } 657 658 void convertExecValue (ExecConstValueAccess src, ExecValueAccess dst) 659 { 660 // [src][dst] 661 static const ConvertExecValueFunc convTable[3][3] = 662 { 663 { convertExecValueTempl<float, float>, convertExecValueTempl<float, int>, convertExecValueTempl<float, bool> }, 664 { convertExecValueTempl<int, float>, convertExecValueTempl<int, int>, convertExecValueTempl<int, bool> }, 665 { convertExecValueTempl<bool, float>, convertExecValueTempl<bool, int>, convertExecValueTempl<bool, bool> } 666 }; 667 668 convTable[getBaseTypeConvNdx(src.getType().getBaseType())][getBaseTypeConvNdx(dst.getType().getBaseType())](src, dst); 669 } 670 671 } // anonymous 672 673 ConstructorOp::ConstructorOp (GeneratorState& state, ConstValueRangeAccess valueRange) 674 : m_valueRange(valueRange) 675 { 676 if (valueRange.getType().isVoid()) 677 { 678 // Use random range 679 const int maxScalars = 4; // We don't have to be able to assign this value to anywhere 680 m_valueRange = ValueRange(computeRandomType(state, maxScalars)); 681 computeRandomValueRange(state, m_valueRange.asAccess()); 682 } 683 684 // \todo [2011-03-26 pyry] Vector conversions 685 // int remainingDepth = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 686 687 const VariableType& type = m_valueRange.getType(); 688 VariableType::Type baseType = type.getBaseType(); 689 int numScalars = type.getNumElements(); 690 int curScalarNdx = 0; 691 692 // \todo [2011-03-26 pyry] Separate op for struct constructors! 693 DE_ASSERT(type.isFloatOrVec() || type.isIntOrVec() || type.isBoolOrVec()); 694 695 bool scalarConversions = state.getProgramParameters().useScalarConversions; 696 697 while (curScalarNdx < numScalars) 698 { 699 ConstValueRangeAccess comp = m_valueRange.asAccess().component(curScalarNdx); 700 701 if (scalarConversions) 702 { 703 int numInTypes = 0; 704 VariableType::Type inTypes[3]; 705 706 if (isConversionOk(VariableType::TYPE_FLOAT, baseType, comp)) inTypes[numInTypes++] = VariableType::TYPE_FLOAT; 707 if (isConversionOk(VariableType::TYPE_INT, baseType, comp)) inTypes[numInTypes++] = VariableType::TYPE_INT; 708 if (isConversionOk(VariableType::TYPE_BOOL, baseType, comp)) inTypes[numInTypes++] = VariableType::TYPE_BOOL; 709 710 DE_ASSERT(numInTypes > 0); // At least nop conversion should be ok 711 712 // Choose random 713 VariableType::Type inType = state.getRandom().choose<VariableType::Type>(&inTypes[0], &inTypes[0] + numInTypes); 714 715 // Compute converted value range 716 ValueRange inValueRange(VariableType(inType, 1)); 717 convertValueRange(comp, inValueRange); 718 m_inputValueRanges.push_back(inValueRange); 719 720 curScalarNdx += 1; 721 } 722 else 723 { 724 m_inputValueRanges.push_back(ValueRange(comp)); 725 curScalarNdx += 1; 726 } 727 } 728 } 729 730 ConstructorOp::~ConstructorOp (void) 731 { 732 for (vector<Expression*>::iterator i = m_inputExpressions.begin(); i != m_inputExpressions.end(); i++) 733 delete *i; 734 } 735 736 Expression* ConstructorOp::createNextChild (GeneratorState& state) 737 { 738 int numChildren = (int)m_inputExpressions.size(); 739 Expression* child = DE_NULL; 740 741 // \note Created in reverse order! 742 if (numChildren < (int)m_inputValueRanges.size()) 743 { 744 const ValueRange& inValueRange = m_inputValueRanges[m_inputValueRanges.size()-1-numChildren]; 745 child = Expression::createRandom(state, inValueRange); 746 try 747 { 748 m_inputExpressions.push_back(child); 749 } 750 catch (const std::exception&) 751 { 752 delete child; 753 throw; 754 } 755 } 756 757 return child; 758 } 759 760 float ConstructorOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 761 { 762 if (valueRange.getType().isVoid()) 763 return unusedValueWeight; 764 765 if (!valueRange.getType().isFloatOrVec() && !valueRange.getType().isIntOrVec() && !valueRange.getType().isBoolOrVec()) 766 return 0.0f; 767 768 if (state.getExpressionDepth() + getTypeConstructorDepth(valueRange.getType()) > state.getShaderParameters().maxExpressionDepth) 769 return 0.0f; 770 771 return 1.0f; 772 } 773 774 void ConstructorOp::tokenize (GeneratorState& state, TokenStream& str) const 775 { 776 const VariableType& type = m_valueRange.getType(); 777 DE_ASSERT(type.getPrecision() == VariableType::PRECISION_NONE); 778 type.tokenizeShortType(str); 779 780 str << Token::LEFT_PAREN; 781 782 for (vector<Expression*>::const_reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++) 783 { 784 if (i != m_inputExpressions.rbegin()) 785 str << Token::COMMA; 786 (*i)->tokenize(state, str); 787 } 788 789 str << Token::RIGHT_PAREN; 790 } 791 792 void ConstructorOp::evaluate (ExecutionContext& evalCtx) 793 { 794 // Evaluate children 795 for (vector<Expression*>::reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++) 796 (*i)->evaluate(evalCtx); 797 798 // Compute value 799 const VariableType& type = m_valueRange.getType(); 800 m_value.setStorage(type); 801 802 ExecValueAccess dst = m_value.getValue(type); 803 int curScalarNdx = 0; 804 805 for (vector<Expression*>::reverse_iterator i = m_inputExpressions.rbegin(); i != m_inputExpressions.rend(); i++) 806 { 807 ExecConstValueAccess src = (*i)->getValue(); 808 809 for (int elemNdx = 0; elemNdx < src.getType().getNumElements(); elemNdx++) 810 convertExecValue(src.component(elemNdx), dst.component(curScalarNdx++)); 811 } 812 } 813 814 AssignOp::AssignOp (GeneratorState& state, ConstValueRangeAccess valueRange) 815 : m_valueRange (valueRange) 816 , m_lvalueExpr (DE_NULL) 817 , m_rvalueExpr (DE_NULL) 818 { 819 if (m_valueRange.getType().isVoid()) 820 { 821 // Compute random value range 822 int maxScalars = state.getShaderParameters().maxCombinedVariableScalars - state.getVariableManager().getNumAllocatedScalars(); 823 bool useRandomRange = !state.getVariableManager().hasEntry<IsWritableEntry>() || ((maxScalars > 0) && getWeightedBool(state.getRandom(), 0.1f)); 824 825 if (useRandomRange) 826 { 827 DE_ASSERT(maxScalars > 0); 828 m_valueRange = ValueRange(computeRandomType(state, maxScalars)); 829 computeRandomValueRange(state, m_valueRange.asAccess()); 830 } 831 else 832 { 833 // Use value range from random entry 834 // \todo [2011-02-28 pyry] Give lower weight to entries without range? Choose subtype range? 835 const ValueEntry* entry = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin<IsWritableEntry>(), state.getVariableManager().getEnd<IsWritableEntry>()); 836 m_valueRange = ValueRange(entry->getValueRange()); 837 838 computeRandomValueRangeForInfElements(state, m_valueRange.asAccess()); 839 840 DE_ASSERT(state.getVariableManager().hasEntry(IsWritableIntersectingEntry(m_valueRange))); 841 } 842 } 843 844 IsWritableIntersectingEntry::Iterator first = state.getVariableManager().getBegin(IsWritableIntersectingEntry(m_valueRange)); 845 IsWritableIntersectingEntry::Iterator end = state.getVariableManager().getEnd(IsWritableIntersectingEntry(m_valueRange)); 846 847 bool possiblyCreateVar = canAllocateVariable(state, m_valueRange.getType()) && 848 (first == end || getWeightedBool(state.getRandom(), 0.5f)); 849 850 if (!possiblyCreateVar) 851 { 852 // Find all possible valueranges matching given type and intersecting with valuerange 853 // \todo [pyry] Actually collect all ValueRanges, currently operates only on whole variables 854 DE_ASSERT(first != end); 855 856 // Try to select one closest to given range but bigger (eg. superset) 857 bool supersetExists = false; 858 for (IsWritableIntersectingEntry::Iterator i = first; i != end; i++) 859 { 860 if ((*i)->getValueRange().isSupersetOf(m_valueRange)) 861 { 862 supersetExists = true; 863 break; 864 } 865 } 866 867 if (!supersetExists) 868 { 869 // Select some other range and compute intersection 870 // \todo [2011-02-03 pyry] Use some heuristics to select the range? 871 ConstValueRangeAccess selectedRange = state.getRandom().choose<const ValueEntry*>(first, end)->getValueRange(); 872 873 ValueRange::computeIntersection(m_valueRange, m_valueRange, selectedRange); 874 } 875 } 876 } 877 878 AssignOp::~AssignOp (void) 879 { 880 delete m_lvalueExpr; 881 delete m_rvalueExpr; 882 } 883 884 float AssignOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 885 { 886 if (!valueRange.getType().isVoid() && 887 !canAllocateVariable(state, valueRange.getType()) && 888 !state.getVariableManager().hasEntry(IsWritableIntersectingEntry(valueRange))) 889 return 0.0f; // Would require creating a new variable 890 891 if (!valueRange.getType().isVoid() && state.getExpressionDepth() + getTypeConstructorDepth(valueRange.getType()) + 1 >= state.getShaderParameters().maxExpressionDepth) 892 return 0.0f; 893 894 if (valueRange.getType().isVoid() && 895 !state.getVariableManager().hasEntry<IsWritableEntry>() && 896 state.getVariableManager().getNumAllocatedScalars() >= state.getShaderParameters().maxCombinedVariableScalars) 897 return 0.0f; // Can not allocate a new entry 898 899 if (state.getExpressionDepth() == 0) 900 return 4.0f; 901 else 902 return 0.0f; // \todo [pyry] Fix assign ops 903 } 904 905 Expression* AssignOp::createNextChild (GeneratorState& state) 906 { 907 if (m_lvalueExpr == DE_NULL) 908 { 909 // Construct lvalue 910 // \todo [2011-03-14 pyry] Proper l-value generation: 911 // - pure L-value part is generated first 912 // - variable valuerange is made unbound 913 // - R-value is generated 914 // - R-values in L-value are generated 915 m_lvalueExpr = Expression::createRandomLValue(state, m_valueRange); 916 return m_lvalueExpr; 917 } 918 else if (m_rvalueExpr == DE_NULL) 919 { 920 // Construct value expr 921 m_rvalueExpr = Expression::createRandom(state, m_valueRange); 922 return m_rvalueExpr; 923 } 924 else 925 return DE_NULL; 926 } 927 928 void AssignOp::tokenize (GeneratorState& state, TokenStream& str) const 929 { 930 m_lvalueExpr->tokenize(state, str); 931 str << Token::EQUAL; 932 m_rvalueExpr->tokenize(state, str); 933 } 934 935 void AssignOp::evaluate (ExecutionContext& evalCtx) 936 { 937 // Evaluate l-value 938 m_lvalueExpr->evaluate(evalCtx); 939 940 // Evaluate value 941 m_rvalueExpr->evaluate(evalCtx); 942 m_value.setStorage(m_valueRange.getType()); 943 m_value.getValue(m_valueRange.getType()) = m_rvalueExpr->getValue().value(); 944 945 // Assign 946 assignMasked(m_lvalueExpr->getLValue(), m_value.getValue(m_valueRange.getType()), evalCtx.getExecutionMask()); 947 } 948 949 namespace 950 { 951 952 inline bool isShaderInOutSupportedType (const VariableType& type) 953 { 954 // \todo [2011-03-11 pyry] Float arrays, structs? 955 return type.getBaseType() == VariableType::TYPE_FLOAT; 956 } 957 958 Variable* allocateNewVariable (GeneratorState& state, ConstValueRangeAccess valueRange) 959 { 960 Variable* variable = state.getVariableManager().allocate(valueRange.getType()); 961 962 // Update value range 963 state.getVariableManager().setValue(variable, valueRange); 964 965 // Random storage \todo [pyry] Check that scalar count in uniform/input classes is not exceeded 966 static const Variable::Storage storages[] = 967 { 968 Variable::STORAGE_CONST, 969 Variable::STORAGE_UNIFORM, 970 Variable::STORAGE_LOCAL, 971 Variable::STORAGE_SHADER_IN 972 }; 973 float weights[DE_LENGTH_OF_ARRAY(storages)]; 974 975 // Dynamic vs. constant weight. 976 float dynWeight = computeDynamicRangeWeight(valueRange); 977 int numScalars = valueRange.getType().getScalarSize(); 978 bool uniformOk = state.getVariableManager().getNumAllocatedUniformScalars() + numScalars <= state.getShaderParameters().maxUniformScalars; 979 bool shaderInOk = isShaderInOutSupportedType(valueRange.getType()) && 980 (state.getVariableManager().getNumAllocatedShaderInVariables() + NUM_RESERVED_SHADER_INPUTS < state.getShaderParameters().maxInputVariables); 981 982 weights[0] = de::max(1.0f-dynWeight, 0.1f); 983 weights[1] = uniformOk ? dynWeight*0.5f : 0.0f; 984 weights[2] = dynWeight; 985 weights[3] = shaderInOk ? dynWeight*2.0f : 0.0f; 986 987 state.getVariableManager().setStorage(variable, state.getRandom().chooseWeighted<Variable::Storage>(&storages[0], &storages[DE_LENGTH_OF_ARRAY(storages)], &weights[0])); 988 989 return variable; 990 } 991 992 inline float combineWeight (float curCombinedWeight, float partialWeight) 993 { 994 return curCombinedWeight * partialWeight; 995 } 996 997 float computeEntryReadWeight (ConstValueRangeAccess entryValueRange, ConstValueRangeAccess readValueRange) 998 { 999 const VariableType& type = entryValueRange.getType(); 1000 DE_ASSERT(type == readValueRange.getType()); 1001 1002 float weight = 1.0f; 1003 1004 switch (type.getBaseType()) 1005 { 1006 case VariableType::TYPE_FLOAT: 1007 { 1008 for (int elemNdx = 0; elemNdx < type.getNumElements(); elemNdx++) 1009 { 1010 float entryMin = entryValueRange.component(elemNdx).getMin().asFloat(); 1011 float entryMax = entryValueRange.component(elemNdx).getMax().asFloat(); 1012 float readMin = readValueRange.component(elemNdx).getMin().asFloat(); 1013 float readMax = readValueRange.component(elemNdx).getMax().asFloat(); 1014 1015 // Check for -inf..inf ranges - they don't bring down the weight. 1016 if (Scalar::min<float>() == entryMin && Scalar::max<float>() == entryMax) 1017 continue; 1018 1019 // Intersection to entry value range length ratio. 1020 float intersectionMin = deFloatMax(entryMin, readMin); 1021 float intersectionMax = deFloatMin(entryMax, readMax); 1022 float entryRangeLen = entryMax - entryMin; 1023 float readRangeLen = readMax - readMin; 1024 float intersectionLen = intersectionMax - intersectionMin; 1025 float entryRatio = (entryRangeLen > 0.0f) ? (intersectionLen / entryRangeLen) : 1.0f; 1026 float readRatio = (readRangeLen > 0.0f) ? (intersectionLen / readRangeLen) : 1.0f; 1027 float elementWeight = 0.5f*readRatio + 0.5f*entryRatio; 1028 1029 weight = combineWeight(weight, elementWeight); 1030 } 1031 break; 1032 } 1033 1034 case VariableType::TYPE_INT: 1035 { 1036 for (int elemNdx = 0; elemNdx < type.getNumElements(); elemNdx++) 1037 { 1038 int entryMin = entryValueRange.component(elemNdx).getMin().asInt(); 1039 int entryMax = entryValueRange.component(elemNdx).getMax().asInt(); 1040 int readMin = readValueRange.component(elemNdx).getMin().asInt(); 1041 int readMax = readValueRange.component(elemNdx).getMax().asInt(); 1042 1043 // Check for -inf..inf ranges - they don't bring down the weight. 1044 if (Scalar::min<int>() == entryMin && Scalar::max<int>() == entryMax) 1045 continue; 1046 1047 // Intersection to entry value range length ratio. 1048 int intersectionMin = deMax32(entryMin, readMin); 1049 int intersectionMax = deMin32(entryMax, readMax); 1050 int entryRangeLen = entryMax - entryMin; 1051 int readRangeLen = readMax - readMin; 1052 int intersectionLen = intersectionMax - intersectionMin; 1053 float entryRatio = (entryRangeLen > 0) ? ((float)intersectionLen / (float)entryRangeLen) : 1.0f; 1054 float readRatio = (readRangeLen > 0) ? ((float)intersectionLen / (float)readRangeLen) : 1.0f; 1055 float elementWeight = 0.5f*readRatio + 0.5f*entryRatio; 1056 1057 weight = combineWeight(weight, elementWeight); 1058 } 1059 break; 1060 } 1061 1062 case VariableType::TYPE_BOOL: 1063 { 1064 // \todo 1065 break; 1066 } 1067 1068 1069 case VariableType::TYPE_ARRAY: 1070 case VariableType::TYPE_STRUCT: 1071 1072 default: 1073 TCU_FAIL("Unsupported type"); 1074 } 1075 1076 return deFloatMax(weight, 0.01f); 1077 } 1078 1079 } // anonymous 1080 1081 VariableRead::VariableRead (GeneratorState& state, ConstValueRangeAccess valueRange) 1082 { 1083 if (valueRange.getType().isVoid()) 1084 { 1085 IsReadableEntry filter = IsReadableEntry(state.getExpressionFlags()); 1086 int maxScalars = state.getShaderParameters().maxCombinedVariableScalars - state.getVariableManager().getNumAllocatedScalars(); 1087 bool useRandomRange = !state.getVariableManager().hasEntry(filter) || ((maxScalars > 0) && getWeightedBool(state.getRandom(), 0.5f)); 1088 1089 if (useRandomRange) 1090 { 1091 // Allocate a new variable 1092 DE_ASSERT(maxScalars > 0); 1093 ValueRange newVarRange(computeRandomType(state, maxScalars)); 1094 computeRandomValueRange(state, newVarRange.asAccess()); 1095 1096 m_variable = allocateNewVariable(state, newVarRange); 1097 } 1098 else 1099 { 1100 // Use random entry \todo [pyry] Handle -inf..inf ranges? 1101 m_variable = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin(filter), state.getVariableManager().getEnd(filter))->getVariable(); 1102 } 1103 } 1104 else 1105 { 1106 // Find variable that has value range that intersects with given range 1107 IsReadableIntersectingEntry::Iterator first = state.getVariableManager().getBegin(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags())); 1108 IsReadableIntersectingEntry::Iterator end = state.getVariableManager().getEnd(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags())); 1109 1110 const float createOnReadWeight = 0.5f; 1111 bool createVar = canAllocateVariable(state, valueRange.getType()) && (first == end || getWeightedBool(state.getRandom(), createOnReadWeight)); 1112 1113 if (createVar) 1114 { 1115 m_variable = allocateNewVariable(state, valueRange); 1116 } 1117 else 1118 { 1119 // Copy value entries for computing weights. 1120 std::vector<const ValueEntry*> availableVars; 1121 std::vector<float> weights; 1122 1123 std::copy(first, end, std::inserter(availableVars, availableVars.begin())); 1124 1125 // Compute weights. 1126 weights.resize(availableVars.size()); 1127 for (int ndx = 0; ndx < (int)availableVars.size(); ndx++) 1128 weights[ndx] = computeEntryReadWeight(availableVars[ndx]->getValueRange(), valueRange); 1129 1130 // Select. 1131 const ValueEntry* entry = state.getRandom().chooseWeighted<const ValueEntry*>(availableVars.begin(), availableVars.end(), weights.begin()); 1132 m_variable = entry->getVariable(); 1133 1134 // Compute intersection 1135 ValueRange intersection(m_variable->getType()); 1136 ValueRange::computeIntersection(intersection, entry->getValueRange(), valueRange); 1137 state.getVariableManager().setValue(m_variable, intersection); 1138 } 1139 } 1140 } 1141 1142 VariableRead::VariableRead (const Variable* variable) 1143 { 1144 m_variable = variable; 1145 } 1146 1147 float VariableRead::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 1148 { 1149 if (valueRange.getType().isVoid()) 1150 { 1151 if (state.getVariableManager().hasEntry(IsReadableEntry(state.getExpressionFlags())) || 1152 state.getVariableManager().getNumAllocatedScalars() < state.getShaderParameters().maxCombinedVariableScalars) 1153 return unusedValueWeight; 1154 else 1155 return 0.0f; 1156 } 1157 1158 if (!canAllocateVariable(state, valueRange.getType()) && 1159 !state.getVariableManager().hasEntry(IsReadableIntersectingEntry(valueRange, state.getExpressionFlags()))) 1160 return 0.0f; 1161 else 1162 return 1.0f; 1163 } 1164 1165 VariableWrite::VariableWrite (GeneratorState& state, ConstValueRangeAccess valueRange) 1166 { 1167 DE_ASSERT(!valueRange.getType().isVoid()); 1168 1169 // Find variable with range that is superset of given range 1170 IsWritableSupersetEntry::Iterator first = state.getVariableManager().getBegin(IsWritableSupersetEntry(valueRange)); 1171 IsWritableSupersetEntry::Iterator end = state.getVariableManager().getEnd(IsWritableSupersetEntry(valueRange)); 1172 1173 const float createOnAssignWeight = 0.1f; // Will essentially create an unused variable 1174 bool createVar = canAllocateVariable(state, valueRange.getType()) && (first == end || getWeightedBool(state.getRandom(), createOnAssignWeight)); 1175 1176 if (createVar) 1177 { 1178 m_variable = state.getVariableManager().allocate(valueRange.getType()); 1179 // \note Storage will be LOCAL 1180 } 1181 else 1182 { 1183 // Choose random 1184 DE_ASSERT(first != end); 1185 const ValueEntry* entry = state.getRandom().choose<const ValueEntry*>(first, end); 1186 m_variable = entry->getVariable(); 1187 } 1188 1189 DE_ASSERT(m_variable); 1190 1191 // Reset value range. 1192 const ValueEntry* parentEntry = state.getVariableManager().getParentValue(m_variable); 1193 if (parentEntry) 1194 { 1195 // Use parent value range. 1196 state.getVariableManager().setValue(m_variable, parentEntry->getValueRange()); 1197 } 1198 else 1199 { 1200 // Use infinite range. 1201 ValueRange infRange(m_variable->getType()); 1202 setInfiniteRange(infRange); 1203 1204 state.getVariableManager().setValue(m_variable, infRange); 1205 } 1206 } 1207 1208 float VariableWrite::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 1209 { 1210 if (!canAllocateVariable(state, valueRange.getType()) && 1211 !state.getVariableManager().hasEntry(IsWritableSupersetEntry(valueRange))) 1212 return 0.0f; 1213 else 1214 return 1.0f; 1215 } 1216 1217 void VariableAccess::evaluate (ExecutionContext& evalCtx) 1218 { 1219 m_valueAccess = evalCtx.getValue(m_variable); 1220 } 1221 1222 ParenOp::ParenOp (GeneratorState& state, ConstValueRangeAccess valueRange) 1223 : m_valueRange (valueRange) 1224 , m_child (DE_NULL) 1225 { 1226 DE_UNREF(state); 1227 } 1228 1229 ParenOp::~ParenOp (void) 1230 { 1231 delete m_child; 1232 } 1233 1234 Expression* ParenOp::createNextChild (GeneratorState& state) 1235 { 1236 if (m_child == DE_NULL) 1237 { 1238 m_child = Expression::createRandom(state, m_valueRange); 1239 return m_child; 1240 } 1241 else 1242 return DE_NULL; 1243 } 1244 1245 void ParenOp::tokenize (GeneratorState& state, TokenStream& str) const 1246 { 1247 str << Token::LEFT_PAREN; 1248 m_child->tokenize(state, str); 1249 str << Token::RIGHT_PAREN; 1250 } 1251 1252 float ParenOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 1253 { 1254 if (valueRange.getType().isVoid()) 1255 return state.getExpressionDepth() + 2 <= state.getShaderParameters().maxExpressionDepth ? unusedValueWeight : 0.0f; 1256 else 1257 { 1258 int requiredDepth = 1 + getConservativeValueExprDepth(state, valueRange); 1259 return state.getExpressionDepth() + requiredDepth <= state.getShaderParameters().maxExpressionDepth ? 1.0f : 0.0f; 1260 } 1261 } 1262 1263 const int swizzlePrecedence = 2; 1264 1265 SwizzleOp::SwizzleOp (GeneratorState& state, ConstValueRangeAccess valueRange) 1266 : m_outValueRange (valueRange) 1267 , m_numInputElements (0) 1268 , m_child (DE_NULL) 1269 { 1270 DE_ASSERT(!m_outValueRange.getType().isVoid()); // \todo [2011-06-13 pyry] Void support 1271 DE_ASSERT(m_outValueRange.getType().isFloatOrVec() || 1272 m_outValueRange.getType().isIntOrVec() || 1273 m_outValueRange.getType().isBoolOrVec()); 1274 1275 m_value.setStorage(m_outValueRange.getType()); 1276 1277 int numOutputElements = m_outValueRange.getType().getNumElements(); 1278 1279 // \note Swizzle works for vector types only. 1280 // \todo [2011-06-13 pyry] Use components multiple times. 1281 m_numInputElements = state.getRandom().getInt(deMax32(numOutputElements, 2), 4); 1282 1283 std::set<int> availableElements; 1284 for (int ndx = 0; ndx < m_numInputElements; ndx++) 1285 availableElements.insert(ndx); 1286 1287 // Randomize swizzle. 1288 for (int elemNdx = 0; elemNdx < (int)DE_LENGTH_OF_ARRAY(m_swizzle); elemNdx++) 1289 { 1290 if (elemNdx < numOutputElements) 1291 { 1292 int inElemNdx = state.getRandom().choose<int>(availableElements.begin(), availableElements.end()); 1293 availableElements.erase(inElemNdx); 1294 m_swizzle[elemNdx] = (deUint8)inElemNdx; 1295 } 1296 else 1297 m_swizzle[elemNdx] = 0; 1298 } 1299 } 1300 1301 SwizzleOp::~SwizzleOp (void) 1302 { 1303 delete m_child; 1304 } 1305 1306 Expression* SwizzleOp::createNextChild (GeneratorState& state) 1307 { 1308 if (m_child) 1309 return DE_NULL; 1310 1311 // Compute input value range. 1312 VariableType inVarType = VariableType(m_outValueRange.getType().getBaseType(), m_numInputElements); 1313 ValueRange inValueRange = ValueRange(inVarType); 1314 1315 // Initialize all inputs to -inf..inf 1316 setInfiniteRange(inValueRange); 1317 1318 // Compute intersections. 1319 int numOutputElements = m_outValueRange.getType().getNumElements(); 1320 for (int outElemNdx = 0; outElemNdx < numOutputElements; outElemNdx++) 1321 { 1322 int inElemNdx = m_swizzle[outElemNdx]; 1323 ValueRange::computeIntersection(inValueRange.asAccess().component(inElemNdx), inValueRange.asAccess().component(inElemNdx), m_outValueRange.asAccess().component(outElemNdx)); 1324 } 1325 1326 // Create child. 1327 state.pushPrecedence(swizzlePrecedence); 1328 m_child = Expression::createRandom(state, inValueRange); 1329 state.popPrecedence(); 1330 1331 return m_child; 1332 } 1333 1334 void SwizzleOp::tokenize (GeneratorState& state, TokenStream& str) const 1335 { 1336 const char* rgbaSet[] = { "r", "g", "b", "a" }; 1337 const char* xyzwSet[] = { "x", "y", "z", "w" }; 1338 const char* stpqSet[] = { "s", "t", "p", "q" }; 1339 const char** swizzleSet = DE_NULL; 1340 1341 switch (state.getRandom().getInt(0, 2)) 1342 { 1343 case 0: swizzleSet = rgbaSet; break; 1344 case 1: swizzleSet = xyzwSet; break; 1345 case 2: swizzleSet = stpqSet; break; 1346 default: DE_ASSERT(DE_FALSE); 1347 } 1348 1349 std::string swizzleStr; 1350 for (int elemNdx = 0; elemNdx < m_outValueRange.getType().getNumElements(); elemNdx++) 1351 swizzleStr += swizzleSet[m_swizzle[elemNdx]]; 1352 1353 m_child->tokenize(state, str); 1354 str << Token::DOT << Token(swizzleStr.c_str()); 1355 } 1356 1357 float SwizzleOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 1358 { 1359 if (!state.getProgramParameters().useSwizzle) 1360 return 0.0f; 1361 1362 if (state.getPrecedence() < swizzlePrecedence) 1363 return 0.0f; 1364 1365 if (!valueRange.getType().isFloatOrVec() && 1366 !valueRange.getType().isIntOrVec() && 1367 !valueRange.getType().isBoolOrVec()) 1368 return 0.0f; 1369 1370 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 1371 1372 // Swizzle + Constructor + Values 1373 if (availableLevels < 3) 1374 return 0.0f; 1375 1376 return 1.0f; 1377 } 1378 1379 void SwizzleOp::evaluate (ExecutionContext& execCtx) 1380 { 1381 m_child->evaluate(execCtx); 1382 1383 ExecConstValueAccess inValue = m_child->getValue(); 1384 ExecValueAccess outValue = m_value.getValue(m_outValueRange.getType()); 1385 1386 for (int outElemNdx = 0; outElemNdx < outValue.getType().getNumElements(); outElemNdx++) 1387 { 1388 int inElemNdx = m_swizzle[outElemNdx]; 1389 outValue.component(outElemNdx) = inValue.component(inElemNdx).value(); 1390 } 1391 } 1392 1393 static int countSamplers (const VariableManager& varManager, VariableType::Type samplerType) 1394 { 1395 int numSamplers = 0; 1396 1397 IsSamplerEntry::Iterator i = varManager.getBegin(IsSamplerEntry(samplerType)); 1398 IsSamplerEntry::Iterator end = varManager.getEnd(IsSamplerEntry(samplerType)); 1399 1400 for (; i != end; i++) 1401 numSamplers += 1; 1402 1403 return numSamplers; 1404 } 1405 1406 TexLookup::TexLookup (GeneratorState& state, ConstValueRangeAccess valueRange) 1407 : m_type (TYPE_LAST) 1408 , m_coordExpr (DE_NULL) 1409 , m_lodBiasExpr (DE_NULL) 1410 , m_valueType (VariableType::TYPE_FLOAT, 4) 1411 , m_value (m_valueType) 1412 { 1413 DE_ASSERT(valueRange.getType() == VariableType(VariableType::TYPE_FLOAT, 4)); 1414 DE_UNREF(valueRange); // Texture output value range is constant. 1415 1416 // Select type. 1417 vector<Type> typeCandidates; 1418 if (state.getShaderParameters().useTexture2D) 1419 { 1420 typeCandidates.push_back(TYPE_TEXTURE2D); 1421 typeCandidates.push_back(TYPE_TEXTURE2D_LOD); 1422 typeCandidates.push_back(TYPE_TEXTURE2D_PROJ); 1423 typeCandidates.push_back(TYPE_TEXTURE2D_PROJ_LOD); 1424 } 1425 1426 if (state.getShaderParameters().useTextureCube) 1427 { 1428 typeCandidates.push_back(TYPE_TEXTURECUBE); 1429 typeCandidates.push_back(TYPE_TEXTURECUBE_LOD); 1430 } 1431 1432 m_type = state.getRandom().choose<Type>(typeCandidates.begin(), typeCandidates.end()); 1433 1434 // Select or allocate sampler. 1435 VariableType::Type samplerType = VariableType::TYPE_LAST; 1436 switch (m_type) 1437 { 1438 case TYPE_TEXTURE2D: 1439 case TYPE_TEXTURE2D_LOD: 1440 case TYPE_TEXTURE2D_PROJ: 1441 case TYPE_TEXTURE2D_PROJ_LOD: 1442 samplerType = VariableType::TYPE_SAMPLER_2D; 1443 break; 1444 1445 case TYPE_TEXTURECUBE: 1446 case TYPE_TEXTURECUBE_LOD: 1447 samplerType = VariableType::TYPE_SAMPLER_CUBE; 1448 break; 1449 1450 default: 1451 DE_ASSERT(DE_FALSE); 1452 } 1453 1454 int sampler2DCount = countSamplers(state.getVariableManager(), VariableType::TYPE_SAMPLER_2D); 1455 int samplerCubeCount = countSamplers(state.getVariableManager(), VariableType::TYPE_SAMPLER_CUBE); 1456 bool canAllocSampler = sampler2DCount + samplerCubeCount < state.getShaderParameters().maxSamplers; 1457 bool hasSampler = samplerType == VariableType::TYPE_SAMPLER_2D ? (sampler2DCount > 0) : (samplerCubeCount > 0); 1458 bool allocSampler = !hasSampler || (canAllocSampler && state.getRandom().getBool()); 1459 1460 if (allocSampler) 1461 { 1462 Variable* sampler = state.getVariableManager().allocate(VariableType(samplerType, 1)); 1463 state.getVariableManager().setStorage(sampler, Variable::STORAGE_UNIFORM); // Samplers are always uniforms. 1464 m_sampler = sampler; 1465 } 1466 else 1467 m_sampler = state.getRandom().choose<const ValueEntry*>(state.getVariableManager().getBegin(IsSamplerEntry(samplerType)), 1468 state.getVariableManager().getEnd(IsSamplerEntry(samplerType)))->getVariable(); 1469 } 1470 1471 TexLookup::~TexLookup (void) 1472 { 1473 delete m_coordExpr; 1474 delete m_lodBiasExpr; 1475 } 1476 1477 Expression* TexLookup::createNextChild (GeneratorState& state) 1478 { 1479 bool hasLodBias = m_type == TYPE_TEXTURE2D_LOD || 1480 m_type == TYPE_TEXTURE2D_PROJ_LOD || 1481 m_type == TYPE_TEXTURECUBE_LOD; 1482 1483 if (hasLodBias && !m_lodBiasExpr) 1484 { 1485 ValueRange lodRange(VariableType(VariableType::TYPE_FLOAT, 1)); 1486 setInfiniteRange(lodRange); // Any value is valid. 1487 1488 m_lodBiasExpr = Expression::createRandom(state, lodRange); 1489 return m_lodBiasExpr; 1490 } 1491 1492 if (!m_coordExpr) 1493 { 1494 if (m_type == TYPE_TEXTURECUBE || m_type == TYPE_TEXTURECUBE_LOD) 1495 { 1496 // Make sure major axis selection can be done. 1497 int majorAxisNdx = state.getRandom().getInt(0, 2); 1498 1499 ValueRange coordRange(VariableType(VariableType::TYPE_FLOAT, 3)); 1500 1501 for (int ndx = 0; ndx < 3; ndx++) 1502 { 1503 if (ndx == majorAxisNdx) 1504 { 1505 bool neg = state.getRandom().getBool(); 1506 coordRange.getMin().component(ndx) = neg ? -4.0f : 2.25f; 1507 coordRange.getMax().component(ndx) = neg ? -2.25f : 4.0f; 1508 } 1509 else 1510 { 1511 coordRange.getMin().component(ndx) = -2.0f; 1512 coordRange.getMax().component(ndx) = 2.0f; 1513 } 1514 } 1515 1516 m_coordExpr = Expression::createRandom(state, coordRange); 1517 } 1518 else 1519 { 1520 bool isProj = m_type == TYPE_TEXTURE2D_PROJ || m_type == TYPE_TEXTURE2D_PROJ_LOD; 1521 int coordScalarSize = isProj ? 3 : 2; 1522 1523 ValueRange coordRange(VariableType(VariableType::TYPE_FLOAT, coordScalarSize)); 1524 setInfiniteRange(coordRange); // Initialize base range with -inf..inf 1525 1526 if (isProj) 1527 { 1528 // w coordinate must be something sane, and not 0. 1529 bool neg = state.getRandom().getBool(); 1530 coordRange.getMin().component(2) = neg ? -4.0f : 0.25f; 1531 coordRange.getMax().component(2) = neg ? -0.25f : 4.0f; 1532 } 1533 1534 m_coordExpr = Expression::createRandom(state, coordRange); 1535 } 1536 1537 DE_ASSERT(m_coordExpr); 1538 return m_coordExpr; 1539 } 1540 1541 return DE_NULL; // Done. 1542 } 1543 1544 void TexLookup::tokenize (GeneratorState& state, TokenStream& str) const 1545 { 1546 bool isVertex = state.getShader().getType() == Shader::TYPE_VERTEX; 1547 1548 if (state.getProgramParameters().version == VERSION_300) 1549 { 1550 switch (m_type) 1551 { 1552 case TYPE_TEXTURE2D: str << "texture"; break; 1553 case TYPE_TEXTURE2D_LOD: str << (isVertex ? "textureLod" : "texture"); break; 1554 case TYPE_TEXTURE2D_PROJ: str << "textureProj"; break; 1555 case TYPE_TEXTURE2D_PROJ_LOD: str << (isVertex ? "textureProjLod" : "textureProj"); break; 1556 case TYPE_TEXTURECUBE: str << "texture"; break; 1557 case TYPE_TEXTURECUBE_LOD: str << (isVertex ? "textureLod" : "texture"); break; 1558 default: 1559 DE_ASSERT(DE_FALSE); 1560 } 1561 } 1562 else 1563 { 1564 switch (m_type) 1565 { 1566 case TYPE_TEXTURE2D: str << "texture2D"; break; 1567 case TYPE_TEXTURE2D_LOD: str << (isVertex ? "texture2DLod" : "texture2D"); break; 1568 case TYPE_TEXTURE2D_PROJ: str << "texture2DProj"; break; 1569 case TYPE_TEXTURE2D_PROJ_LOD: str << (isVertex ? "texture2DProjLod" : "texture2DProj"); break; 1570 case TYPE_TEXTURECUBE: str << "textureCube"; break; 1571 case TYPE_TEXTURECUBE_LOD: str << (isVertex ? "textureCubeLod" : "textureCube"); break; 1572 default: 1573 DE_ASSERT(DE_FALSE); 1574 } 1575 } 1576 1577 str << Token::LEFT_PAREN; 1578 str << m_sampler->getName(); 1579 str << Token::COMMA; 1580 m_coordExpr->tokenize(state, str); 1581 1582 if (m_lodBiasExpr) 1583 { 1584 str << Token::COMMA; 1585 m_lodBiasExpr->tokenize(state, str); 1586 } 1587 1588 str << Token::RIGHT_PAREN; 1589 } 1590 1591 float TexLookup::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 1592 { 1593 if (state.getShaderParameters().texLookupBaseWeight <= 0.0f) 1594 return 0.0f; 1595 1596 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 1597 1598 // Lookup + Constructor + Values 1599 if (availableLevels < 3) 1600 return 0.0f; 1601 1602 if (state.getExpressionFlags() & (CONST_EXPR|NO_VAR_ALLOCATION)) 1603 return 0.0f; 1604 1605 if (valueRange.getType() != VariableType(VariableType::TYPE_FLOAT, 4)) 1606 return 0.0f; 1607 1608 ValueRange texOutputRange(VariableType(VariableType::TYPE_FLOAT, 4)); 1609 for (int ndx = 0; ndx < 4; ndx++) 1610 { 1611 texOutputRange.getMin().component(ndx) = 0.0f; 1612 texOutputRange.getMax().component(ndx) = 1.0f; 1613 } 1614 1615 if (!valueRange.isSupersetOf(texOutputRange)) 1616 return 0.0f; 1617 1618 return state.getShaderParameters().texLookupBaseWeight; 1619 } 1620 1621 void TexLookup::evaluate (ExecutionContext& execCtx) 1622 { 1623 // Evaluate coord and bias. 1624 m_coordExpr->evaluate(execCtx); 1625 if (m_lodBiasExpr) 1626 m_lodBiasExpr->evaluate(execCtx); 1627 1628 ExecConstValueAccess coords = m_coordExpr->getValue(); 1629 ExecValueAccess dst = m_value.getValue(m_valueType); 1630 1631 switch (m_type) 1632 { 1633 case TYPE_TEXTURE2D: 1634 { 1635 const Sampler2D& tex = execCtx.getSampler2D(m_sampler); 1636 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1637 { 1638 float s = coords.component(0).asFloat(i); 1639 float t = coords.component(1).asFloat(i); 1640 tcu::Vec4 p = tex.sample(s, t, 0.0f); 1641 1642 for (int comp = 0; comp < 4; comp++) 1643 dst.component(comp).asFloat(i) = p[comp]; 1644 } 1645 break; 1646 } 1647 1648 case TYPE_TEXTURE2D_LOD: 1649 { 1650 ExecConstValueAccess lod = m_lodBiasExpr->getValue(); 1651 const Sampler2D& tex = execCtx.getSampler2D(m_sampler); 1652 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1653 { 1654 float s = coords.component(0).asFloat(i); 1655 float t = coords.component(1).asFloat(i); 1656 float l = lod.component(0).asFloat(i); 1657 tcu::Vec4 p = tex.sample(s, t, l); 1658 1659 for (int comp = 0; comp < 4; comp++) 1660 dst.component(comp).asFloat(i) = p[comp]; 1661 } 1662 break; 1663 } 1664 1665 case TYPE_TEXTURE2D_PROJ: 1666 { 1667 const Sampler2D& tex = execCtx.getSampler2D(m_sampler); 1668 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1669 { 1670 float s = coords.component(0).asFloat(i); 1671 float t = coords.component(1).asFloat(i); 1672 float w = coords.component(2).asFloat(i); 1673 tcu::Vec4 p = tex.sample(s/w, t/w, 0.0f); 1674 1675 for (int comp = 0; comp < 4; comp++) 1676 dst.component(comp).asFloat(i) = p[comp]; 1677 } 1678 break; 1679 } 1680 1681 case TYPE_TEXTURE2D_PROJ_LOD: 1682 { 1683 ExecConstValueAccess lod = m_lodBiasExpr->getValue(); 1684 const Sampler2D& tex = execCtx.getSampler2D(m_sampler); 1685 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1686 { 1687 float s = coords.component(0).asFloat(i); 1688 float t = coords.component(1).asFloat(i); 1689 float w = coords.component(2).asFloat(i); 1690 float l = lod.component(0).asFloat(i); 1691 tcu::Vec4 p = tex.sample(s/w, t/w, l); 1692 1693 for (int comp = 0; comp < 4; comp++) 1694 dst.component(comp).asFloat(i) = p[comp]; 1695 } 1696 break; 1697 } 1698 1699 case TYPE_TEXTURECUBE: 1700 { 1701 const SamplerCube& tex = execCtx.getSamplerCube(m_sampler); 1702 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1703 { 1704 float s = coords.component(0).asFloat(i); 1705 float t = coords.component(1).asFloat(i); 1706 float r = coords.component(2).asFloat(i); 1707 tcu::Vec4 p = tex.sample(s, t, r, 0.0f); 1708 1709 for (int comp = 0; comp < 4; comp++) 1710 dst.component(comp).asFloat(i) = p[comp]; 1711 } 1712 break; 1713 } 1714 1715 case TYPE_TEXTURECUBE_LOD: 1716 { 1717 ExecConstValueAccess lod = m_lodBiasExpr->getValue(); 1718 const SamplerCube& tex = execCtx.getSamplerCube(m_sampler); 1719 for (int i = 0; i < EXEC_VEC_WIDTH; i++) 1720 { 1721 float s = coords.component(0).asFloat(i); 1722 float t = coords.component(1).asFloat(i); 1723 float r = coords.component(2).asFloat(i); 1724 float l = lod.component(0).asFloat(i); 1725 tcu::Vec4 p = tex.sample(s, t, r, l); 1726 1727 for (int comp = 0; comp < 4; comp++) 1728 dst.component(comp).asFloat(i) = p[comp]; 1729 } 1730 break; 1731 } 1732 1733 default: 1734 DE_ASSERT(DE_FALSE); 1735 } 1736 } 1737 1738 } // rsg 1739